---
title: Bengal 0.1.9
description: Architecture decomposition, Python 3.14 modernization, build performance, protocol migrations, and comprehensive docs audit
type: changelog
date: 2026-02-08
draft: false
lang: en
tags: [release, changelog, architecture, performance, protocols, modernization, thread-safety]
keywords: [release, 0.1.9, decomposition, PEP 695, protocols, fast mode, autodoc caching, EffectTracer, ConfigService, docs audit]
category: changelog
---

# Bengal 0.1.9

**Key additions:** Major architecture decomposition (mixins → free functions + composed services, 12 → 4 Site mixins), Python 3.14 modernization (PEP 695 type params, slots, exception chaining), build performance optimizations (~50-60% faster), protocol-based decoupling across 40+ files, thread safety hardening, incremental build improvements, structured error handling, and a comprehensive documentation staleness audit.

---

## Highlights

### Architecture Decomposition

The largest structural change in Bengal's history — systematic decomposition of monolithic mixins into free functions and composed services:

- **Protocol-based decoupling**: `PageLike` and `SiteLike` split into role-based protocols (`SiteConfig`, `SiteContent`, `Summarizable`), migrated across 40+ consumer files
- **Mixin elimination**: `Site` inheritance chain reduced from 12 to 4 mixins — `PageComputedMixin`, `PageBundleMixin`, `PageNavigationMixin`, `SitePropertiesMixin`, and `SiteVersioningMixin` all extracted to free functions or composed services
- **ConfigService**: New frozen dataclass composing all configuration access, wired into `Site` with bridge properties (31 tests)
- **EffectTracer**: Replaces `DependencyTracker` with persistence, file fingerprinting, and thread-safe operation
- **Module splits**: `snapshots/builder.py` (1,762 lines) split into 5 focused modules
- **Type cleanup**: 55 stale `type: ignore` comments removed, `Any` escape hatches replaced with correct types across rendering and Page files

### Python 3.14 Modernization

Codebase-wide adoption of modern Python syntax:

- **PEP 695 type parameters**: `class Foo[T]:` replaces `class Foo(Generic[T]):` throughout
- **`slots=True`** on all frozen dataclasses for memory efficiency
- **Exception chaining** in all raise-in-except blocks
- **`ClassVar` annotations** on mutable class defaults
- **Comprehension conversion** from manual list building (PERF401)
- **Narrowed exception handlers** across rendering modules

### Build Performance Optimizations

Three-phase performance RFC delivering cumulative ~50-60% speedup for large sites:

- **Fast mode** (`build.fast_mode=True`): Skip HTML pretty-printing/minification for ~10-15% speedup
- **Render-time asset tracking**: ContextVar-based AssetTracker eliminates post-render HTML parsing (~20-25% speedup)
- **Autodoc AST caching**: Cache parsed Python module data across builds (~30-40% speedup for autodoc-heavy sites)
- **Parser pooling**: Re-enabled with patitas 0.1.1's `_reinit()` support (~78% faster parser instantiation)
- **Snapshot pre-computation**: NavTrees and renderer caches pre-computed at snapshot time for lock-free lookups

### Incremental Build Observability

New CLI flags for understanding rebuild decisions:

```bash
# Explain why pages are being rebuilt
bengal build --explain

# Preview what would be rebuilt without doing it
bengal build --dry-run

# Machine-readable rebuild manifest
bengal build --explain-json > manifest.json
```

### Thread Safety Hardening

Comprehensive free-threading support for Python 3.14t:

- **ContextVar asset manifest**: Fixes TOCTOU race condition (~8M ops/sec, zero lock contention)
- **Lock ordering convention**: Documented lock hierarchy prevents deadlocks
- **Immutable snapshots**: Pre-computed at snapshot time for lock-free rendering
- **BuildCache/DependencyTracker separation**: Clean pipeline boundaries
- **Threading integration tests**: EffectTracer and BuildTaxonomyIndex verified under concurrent load

### Cache Coordination

Unified `CacheCoordinator` manages cache invalidation across all subsystems:

- **PathRegistry**: Centralized path-to-cache-key mapping
- **RebuildManifest**: Tracks what needs rebuilding and why
- **Content-hash embedding**: O(1) change detection via embedded hashes in output
- **Template change detection**: Cache now detects template file changes and triggers rebuilds
- **EffectTracer pipeline**: Wired into incremental builds with persistence and file fingerprinting

### Structured Error Handling

Five new exception classes with actionable suggestions:

| Exception | Use Case |
|-----------|----------|
| `BengalParsingError` | Markdown/frontmatter parsing failures |
| `BengalAutodocError` | Autodoc extraction issues |
| `BengalValidatorError` | Health check validation failures |
| `BengalBuildError` | Build pipeline errors |
| `BengalTemplateFunctionError` | Template filter/function errors |

All exceptions include error codes (O/V/B series) and contextual suggestions.

### Documentation Audit

Comprehensive staleness audit across all documentation sections:

- Fixed stale claims in about, building, content, extending, get-started, reference, and theming
- Aligned page URL properties to match codebase (`page.href`, `page._path`)
- Replaced Jinja2-style block endings with `{% end %}` in Kida examples
- Added external cross-links for Kida, Patitas, and Rosettes

---

## Additional Changes

### Developer Experience
- **`bengal upgrade`**: Self-update command with PyPI version checking and installer detection
- **Serve-first startup**: Dev server serves cached content immediately (~200ms first paint)
- **Dead link indicators**: Visual styling for broken internal links

### Theme Enhancements
- **Header customization**: `nav_position` (left/center), `sticky`, and `autohide` options via data attributes

### Changelog & Releases Filter
- Smart semver-aware version sorting
- Domain-aware filtering with simplified API

### CI & Packaging
- **Trusted publishing**: `python-publish.yml` GitHub Actions workflow for OIDC-based PyPI publishing
- **Pages fix**: `--clean-output` flag fixes 404s on `/api/` and `/cli/`

### Directives
- Patitas-native glossary directive

---

## Breaking Changes

None. This is a fully backward-compatible release.

---

## Bug Fixes

- **Duplicate tag pages**: Fixed incremental builds generating duplicate taxonomy pages
- **Anchor fragment preservation**: `.md` links now preserve `#section` anchors during normalization
- **Serve-first activation**: Fixed serve-first not triggering when `baseurl` is `/`
- **Python 3.14 import scoping**: Fixed cache loading issue with import scoping in 3.14
- **Undefined references**: Fixed undefined name references in site and sitemap modules
- **Incremental tag terms**: Fixed tag term page generation in incremental builds
- **CI test failures**: Fixed missing module, wrong kwarg, and unimplemented test gaps

---

## Dependency Updates

| Package | Version | Change |
|---------|---------|--------|
| `patitas` | ≥0.1.1 | Adds `_reinit()` for parser pooling |
| `kida-templates` | ≥0.1.2 | RenderContext, profiling support |

---

## Upgrading

```bash
uv pip install --upgrade bengal
# or
pip install --upgrade bengal
# or use the new self-update command
bengal upgrade
```
