# **B-04** — Diff-aware materializer

**Status**: 🟢 mapped  
**Layer**: projection

## Scope

materializer/**; read-only DB access, page planning and rendering, the typed HTML projection and its independent read-back, manifest dependency hashes, xref resolution, and clean documentation output.

## Start here

materializer/amanuensis_materializer/core.py; materializer/amanuensis_materializer/html_projection.py; materializer/amanuensis_materializer/diagrams.py

## Notes

Derived-artifact correctness boundary and the primary human reading surface. Gained html_projection.py and readback.py since onboarding, and diagrams.py replaced the runtime-boundary placeholder with extraction from registered prose. Finding [B04-1](../findings.md#b04-1) recorded in the 2026-08-27 refresh: staleness_map renders an empty result as an affirmative freshness claim, so the published HTML asserts the conspectus is fresh regardless of drift.

## File ledger

| Path | Classification | Why in scope | Ref SHA |
|---|---|---|---|
| `materializer/amanuensis_materializer/html_projection.py` | candidate | HTML projection renderer; the primary human reading surface per the reporting contract. | `5694080` |
| `materializer/amanuensis_materializer/readback.py` | candidate | Independent read-back verification of published HTML and Markdown views. | `5694080` |
| `materializer/test-readback.py` | candidate | Test covering independent HTML and Markdown read-back verification. | `5694080` |
| `materializer/uv.lock` | candidate | Pinned Python dependency set for the materializer. | `5694080` |
| `materializer/.gitignore` | examined | Pinned A0 inventory assigns this file to **B-04**. | `b8b566f` |
| `materializer/README.md` | examined | Pinned A0 inventory assigns this file to **B-04**. | `b8b566f` |
| `materializer/amanuensis_materializer/__init__.py` | examined | Pinned A0 inventory assigns this file to **B-04**. | `b8b566f` |
| `materializer/amanuensis_materializer/core.py` | examined | Pinned A0 inventory assigns this file to **B-04**. | `b8b566f` |
| `materializer/amanuensis_materializer/db.py` | examined | Pinned A0 inventory assigns this file to **B-04**. | `b8b566f` |
| `materializer/amanuensis_materializer/diagrams.py` | examined | Pinned A0 inventory assigns this file to **B-04**. | `b8b566f` |
| `materializer/amanuensis_materializer/manifest.py` | examined | Pinned A0 inventory assigns this file to **B-04**. | `b8b566f` |
| `materializer/amanuensis_materializer/renderers.py` | examined | Pinned A0 inventory assigns this file to **B-04**. | `b8b566f` |
| `materializer/amanuensis_materializer/slugs.py` | examined | Pinned A0 inventory assigns this file to **B-04**. | `b8b566f` |
| `materializer/amanuensis_materializer/xref.py` | examined | Pinned A0 inventory assigns this file to **B-04**. | `b8b566f` |
| `materializer/materialize.py` | examined | Pinned A0 inventory assigns this file to **B-04**. | `b8b566f` |
| `materializer/pyproject.toml` | examined | Pinned A0 inventory assigns this file to **B-04**. | `b8b566f` |
| `materializer/test-materializer.py` | examined | Pinned A0 inventory assigns this file to **B-04**. | `b8b566f` |
| `docs/.manifest.json` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/.projection-contract.json` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/architecture.html` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/architecture.md` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/concern-checklist.html` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/concern-checklist.md` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/concerns.html` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/concerns.md` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/contradictions.html` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/contradictions.md` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/diagnosticity.html` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/diagnosticity.md` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/entry-point.html` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/entry-point.md` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/field-notes.html` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/field-notes.md` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/findings.html` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/findings.md` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/how-to-read.html` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/how-to-read.md` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/index.html` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/index.md` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/master-plan.html` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/master-plan.md` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/onboarding-report.html` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/onboarding-report.md` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/open-questions.html` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/open-questions.md` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/seams.html` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/seams.md` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/subsystems/b01-survey-methodology-and-agent-contracts.html` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/subsystems/b01-survey-methodology-and-agent-contracts.md` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/subsystems/b02-mcp-core-persistence-and-lifecycle.html` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/subsystems/b02-mcp-core-persistence-and-lifecycle.md` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/subsystems/b03-knowledge-tools-and-workflow-api.html` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/subsystems/b03-knowledge-tools-and-workflow-api.md` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/subsystems/b04-diff-aware-materializer.html` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/subsystems/b04-diff-aware-materializer.md` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/subsystems/b05-packaging-installer-validation-and-product-docs.html` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/subsystems/b05-packaging-installer-validation-and-product-docs.md` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/subsystems/b06-report-interface-design-and-validation-studies.html` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/subsystems/b06-report-interface-design-and-validation-studies.md` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/subsystems/b07-embedded-research-surveys-and-platform-trials.html` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/subsystems/b07-embedded-research-surveys-and-platform-trials.md` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/subsystems/b08-activation-evidence-and-release-readiness-harness.html` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/subsystems/b08-activation-evidence-and-release-readiness-harness.md` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/vocabulary.html` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |
| `docs/vocabulary.md` | generated-ignore | Published conspectus projection regenerated by the materializer; derived output, not authored source. | `aba6d04` |

## Concern review

| Concern | Classification | Evidence quality | Linchpin? | Rationale |
|---|---|---|---|---|
| **[AT-1](../concerns.md#at-1)** | unresolved-competition | code-verified | 🔗 | Code shape makes [AT-1](../concerns.md#at-1) plausible in **B-04**, but runtime or domain evidence is required before confirmation. |
| **[AT-2](../concerns.md#at-2)** | out-of-scope | code-verified |  | The structural and behavioral read supports out-of-scope for [AT-2](../concerns.md#at-2) in **B-04**. |
| **[CC-1](../concerns.md#cc-1)** | confirmed-acceptable | code-verified |  | The structural and behavioral read supports confirmed-acceptable for [CC-1](../concerns.md#cc-1) in **B-04**. |
| **[CR-1](../concerns.md#cr-1)** | confirmed-acceptable | code-verified |  | The structural and behavioral read supports confirmed-acceptable for [CR-1](../concerns.md#cr-1) in **B-04**. |
| **[EP-1](../concerns.md#ep-1)** | confirmed-acceptable | code-verified |  | The structural and behavioral read supports confirmed-acceptable for [EP-1](../concerns.md#ep-1) in **B-04**. |
| **[EP-2](../concerns.md#ep-2)** | out-of-scope | code-verified |  | The structural and behavioral read supports out-of-scope for [EP-2](../concerns.md#ep-2) in **B-04**. |
| **[IF-1](../concerns.md#if-1)** | confirmed-acceptable | code-verified |  | The structural and behavioral read supports confirmed-acceptable for [IF-1](../concerns.md#if-1) in **B-04**. |
| **[RL-1](../concerns.md#rl-1)** | confirmed-acceptable | code-verified |  | The structural and behavioral read supports confirmed-acceptable for [RL-1](../concerns.md#rl-1) in **B-04**. |
| **[RL-2](../concerns.md#rl-2)** | confirmed-acceptable | code-verified |  | The structural and behavioral read supports confirmed-acceptable for [RL-2](../concerns.md#rl-2) in **B-04**. |
| **[SC-1](../concerns.md#sc-1)** | confirmed-acceptable | code-verified |  | [SM-03](../seams.md#sm-03) integral contract was read from both mapped endpoints and passed at the pinned revision; residuals remain separately visible. |
| **[SC-2](../concerns.md#sc-2)** | confirmed-acceptable | code-verified |  | [SM-05](../seams.md#sm-05) integral contract was read from both mapped endpoints and passed at the pinned revision; residuals remain separately visible. |
| **[SC-3](../concerns.md#sc-3)** | confirmed-acceptable | code-verified |  | **B-04** implements the refined [B-06](b06-report-interface-design-and-validation-studies.md) coverage index with retained semantic matrix, contextual identifier definitions, and prose-flow thresholds; integration and failure/read-back gates pass. |
| **[SI-1](../concerns.md#si-1)** | confirmed-acceptable | code-verified |  | The structural and behavioral read supports confirmed-acceptable for [SI-1](../concerns.md#si-1) in **B-04**. |
| **[SI-2](../concerns.md#si-2)** | confirmed-acceptable | code-verified |  | The structural and behavioral read supports confirmed-acceptable for [SI-2](../concerns.md#si-2) in **B-04**. |
| **[TB-1](../concerns.md#tb-1)** | out-of-scope | code-verified |  | The structural and behavioral read supports out-of-scope for [TB-1](../concerns.md#tb-1) in **B-04**. |
| **[TR-1](../concerns.md#tr-1)** | confirmed-acceptable | code-verified |  | The structural and behavioral read supports confirmed-acceptable for [TR-1](../concerns.md#tr-1) in **B-04**. |
| **[TR-2](../concerns.md#tr-2)** | out-of-scope | code-verified |  | The structural and behavioral read supports out-of-scope for [TR-2](../concerns.md#tr-2) in **B-04**. |
| **[VG-1](../concerns.md#vg-1)** | confirmed-bug | code-verified |  | The materializer converts an empty query result into an affirmative claim. staleness_map reads the entries table, which no server code path populates, and its empty branch emits 'No stale entries — the conspectus is fresh.' rather than reporting that no staleness data exists. The published HTML and Markdown at this SHA both carry that sentence while the conspectus was 23 commits behind HEAD. This is a projection-layer defect independent of [B03-2](../findings.md#b03-2)'s root cause: even once staleness is wired to a populated source, rendering absence-of-data as positive health is unsound. |

## Findings

### [B04-1](../findings.md#b04-1) · 🟡 MEDIUM · fixed

**Symptom**: The published conspectus states 'No stale entries — the conspectus is fresh.' in both the HTML reading surface and its Markdown companion, regardless of how far behind HEAD the survey actually is.  
**Root cause**: diagrams.py:staleness_map renders an empty query result as an affirmative freshness claim. Its source, the entries table, is never populated by the server (see [B03-2](../findings.md#b03-2)), so the empty branch is the only branch that ever executes — but the deeper defect is that the empty case is reported as positive health rather than as absent data.

_Business context_: The HTML projection is the primary human reading surface and the product's main deliverable. A reader opening it to judge whether the conspectus can be trusted is told, in the document's own voice, that it is fresh. At 5694080 that sentence was published while the survey sat 23 commits behind HEAD with 47% of tracked files unclassified. Because the claim is generated rather than authored, it carries the authority of the derived-artifact pipeline while resting on no measurement at all. This is the reader-facing endpoint of [B03-2](../findings.md#b03-2) and the reason that defect matters beyond an internal metric.

**Primary files**:
- `materializer/amanuensis_materializer/diagrams.py:staleness_map@5694080`

## Related subsystems

| From | → | To | Relationship | Strength | Context |
|---|---|---|---|---|---|
| **[B-03](b03-knowledge-tools-and-workflow-api.md)** | → | **B-04** | data-flow | confirmed | Staleness flows from [B-03](b03-knowledge-tools-and-workflow-api.md)'s detect_changes into **B-04**'s staleness_map projection via the entries table (seam [SM-09](../seams.md#sm-09)). Because no writer inserts rows, the defect propagates from an inert internal metric ([B03-2](../findings.md#b03-2)) into a published freshness claim in the primary reading surface ([B04-1](../findings.md#b04-1)). |

## Seams

| Seam | Shared object | Other party |
|---|---|---|
| **[SM-03](../seams.md#sm-03)** | materialize_docs subprocess and storage/docs projection | **[B-03](b03-knowledge-tools-and-workflow-api.md)** |
| **[SM-05](../seams.md#sm-05)** | packaged Python materializer mirror | **[B-05](b05-packaging-installer-validation-and-product-docs.md)** |
| **[SM-06](../seams.md#sm-06)** | report projection design/component contract | **[B-06](b06-report-interface-design-and-validation-studies.md)** |
| **[SM-09](../seams.md#sm-09)** | entries table (staleness columns: stale, stale_since, stale_reason) | **[B-03](b03-knowledge-tools-and-workflow-api.md)** |

## Survey notes

# **B-04** · Diff-aware materializer

- Survey revision: `b8b566f`
- Status: adversarial pass complete; packaging pending

## Key types

`Materializer` plans and renders the documentation site, `PagePlan` binds a page to its sources/renderer, `Summary` reports the run, and `Manifest`/`PageManifest` retain source and content hashes (`materializer/amanuensis_materializer/core.py:Materializer@b8b566f`; `materializer/amanuensis_materializer/manifest.py:Manifest@b8b566f`). `XrefIndex` resolves IDs into relative links after rendering (`materializer/amanuensis_materializer/xref.py:XrefIndex@b8b566f`).

## State containers

- Read-only SQLite connection: durable survey source, one materialization run (`materializer/amanuensis_materializer/db.py:open_ro@b8b566f`).
- `.manifest.json`: per-page source hashes, output hash, and render timestamp; persistent projection metadata (`materializer/amanuensis_materializer/manifest.py:Manifest.save@b8b566f`).
- `.materializer-lock`: excludes concurrent writers for the output directory (`materializer/amanuensis_materializer/core.py:Materializer@b8b566f`).
- `docs/`: derived Markdown projection; never the durable survey authority.

## Data flow

The CLI resolves storage/output, opens the database read-only, builds page plans from aggregate and subsystem renderers, compares stable source hashes to the previous manifest, renders affected pages, resolves cross-references, prunes retired pages, saves the new manifest, and prints a JSON summary (`materializer/materialize.py:main@b8b566f`; `materializer/amanuensis_materializer/core.py:Materializer.run@b8b566f`).

## Concurrency model

One process owns an output-directory lock. Database access is read-only. File updates and final manifest persistence are sequential; the manifest warns and rebuilds on corrupt JSON (`materializer/amanuensis_materializer/manifest.py:Manifest.load@b8b566f`).

## Seam contracts

- **[SM-03](../seams.md#sm-03) · [B-03](b03-knowledge-tools-and-workflow-api.md) ↔ **B-04**:** [B-03](b03-knowledge-tools-and-workflow-api.md) supplies storage/output and treats process exit as the operation result; **B-04** reads `memory.db` plus registered prose and writes only the derived output tree.
- **[SM-05](../seams.md#sm-05) · **B-04** ↔ [B-05](b05-packaging-installer-validation-and-product-docs.md):** packaging copies the root materializer as the published mirror.

## Concern dispositions

All active concerns are covered. Incremental/full parity is exercised by repeated and forced renders. Corrupt-manifest recovery is visible via warnings. Multi-file projection atomicity remains an unresolved competition: the lock prevents concurrent writers, but a killed process may leave some page files updated before the manifest is saved. It is not promoted to a confirmed defect without a kill-point control.

## Adversarial review

The pass tried to disprove diff-awareness by finding a change source absent from page plans. Tests cover unchanged runs, prose changes, disposition changes, retired pages, and forced full output (`materializer/test-materializer.py:main@b8b566f`). The baseline A0 clean-export checker adds independent state, coverage, and content read-back. Verdict: incremental contract upheld for the observed source classes; generator correctness still needs independent accept-corpus evidence.
