amanuensis

Subsystem · B-04

Diff-aware materializer

Scope, structure, boundaries, defects, and the survey record for Diff-aware materializer.

Branch  main Checked  ec5824bceb9c As of  2026-10-07 22:54:09 Stale: 0 with a survey obligation, 65 exempt, of 655 scoped files Survey depth  Adversarial

Status: Adversarial Layer: Projection

§Scope

No purpose statement is recorded for this subsystem; the scope below states what it covers.

materializer/** and the promoted docs/ it renders

§Start here

amanuensis_materializer/core.py; renderers.py; readback.py

§Structure

What the survey recorded as claims about this subsystem, grouped by what each one states. Every claim is bound to the revision it was asserted at and to the evidence attached to it; a superseded claim is not shown here.

§Other claims

structure
ClaimSubjectStatementEpistemic kindAsserted at
B-04/projection/a-refusal-leaves-the-previous-output-untouchedB-04Every way this renderer can fail leaves the published projection as it was. A missing required view refuses before the plan is built; an unknown nav group refuses before a byte is written; a renderer exception records the traceback and clears ok; a read-back mismatch clears ok; and clean publication renders into a staging directory, promotes only on a green summary, and removes the stage otherwise. The one destructive step — replacing the output directory — is additionally refused while the output holds a file no prior manifest claims.Observationc0734040022f

§Vocabulary

  • page plan — The list of pages the current store requires, computed once per render and used four times over: to decide what to write, what to link, what to navigate, and what the read-back must find.

§Known defects here

2 defects here are open or awaiting verification. Each one's full record, with its evidence, is on Open findings.

  • The projection read-back's per-row stale-marker expectation set is empty for every real conspectus, so a projection that drops every stale marker still passes that part of the state axis; and the index page's stale reading is drawn from the same dead source. — B04-R1 · Medium · Open
  • A clean publish can go red on the read-back's coverage axis with dangling anchors whose only distinguishing property is the length of the record prose beside them: shortening five long rationales returned all seven missing anchors and the next publish was green on all three axes. — B04-R2 · Medium · Open

§Standing

Adversarial — Candidate conclusions are being challenged; treat them as provisional. It cannot justify that the challenge pass has finished.

Files read
24 of 94 ledger rows
Files in scope, not yet read
0 of 94
Files excluded from the survey obligation
70 of 94
Ledger rows the repository has changed under
64 of 94
Active concerns with a disposition recorded here
12 of 12 — 1 confirmed-bug, 8 confirmed-acceptable, 1 ruled-out, 2 out-of-scope
Findings by resolution state
2 open
Seams assessable from both sides
no seam names this subsystem

§Survey record

§File ledger

survey record
PathClassificationWhy in scopeExamined at
materializer/.gitignoreexaminedLocal build state kept out of the tree.c0734040
materializer/README.mdexaminedThe contract the renderer states for itself: what it produces, the three source kinds, and the self-contained HTML requirement.c0734040
materializer/amanuensis_materializer/__init__.pyexaminedThe package surface: one exported class.c0734040
materializer/amanuensis_materializer/core.pyexaminedThe orchestrator: the page plan, the diff-aware render decision, the global xref pass, the HTML projection, the retirement of orphaned pages, and the post-xref read-back.c0734040
materializer/amanuensis_materializer/db.pyexaminedThe read-only open and the REQUIRED_VIEWS probe with the one fix it names — the reason an older store is refused rather than rendered short.c0734040
materializer/amanuensis_materializer/diagrams.pyexaminedThe topology surfaces, and the atlas-not-graph rule: with no recorded edges the page says so and renders a subsystem atlas rather than asserting a dependency graph.c0734040
materializer/amanuensis_materializer/html_projection.pyexaminedThe diff-aware materializer: the Python projection of the store.410d769b
materializer/amanuensis_materializer/lint.pyexaminedThe orientation-prose lints: survey-status assertions shaped as assertions rather than matched as bare words, and the composite-index rule.c0734040
materializer/amanuensis_materializer/manifest.pyexaminedThe per-page source-hash record, the version bump that invalidates everything, and prune_retired.c0734040
materializer/amanuensis_materializer/readback.pyexaminedThe diff-aware materializer: the Python projection of the store.ec5824bc
materializer/amanuensis_materializer/renderers.pyexaminedThe diff-aware materializer: page renderers, read-back axes, and the HTML projection.a521e28
materializer/amanuensis_materializer/slugs.pyexaminedThe deterministic routing every page and every xref target is derived from.c0734040
materializer/amanuensis_materializer/vocabulary.pyexaminedThe diff-aware materializer: the Python projection of the store.410d769b
materializer/amanuensis_materializer/xref.pyexaminedThe global cross-reference pass: code fences and existing links stashed, self-references rendered bold rather than linked, and every candidate path verified inside the output root.c0734040
materializer/materialize.pyexaminedThe CLI: the three modes, the unmanaged-file refusal that protects a human's files from clean publication, and the stage/backup/promote sequence that leaves the prior output untouched on a red run.ec5824bc
materializer/pyproject.tomlexaminedThe ruff configuration the regression list runs.c0734040
materializer/test-history-and-disagreements.pyexaminedThe diff-aware materializer: the Python projection of the store.410d769b
materializer/test-ledger-freshness.pyexaminedThe diff-aware materializer: the Python projection of the store.410d769b
materializer/test-lens-pages.pyexaminedThe diff-aware materializer: the Python projection of the store.410d769b
materializer/test-materializer.pyexaminedThe diff-aware materializer: the Python projection of the store.ec5824bc
materializer/test-overview-truthfulness.pyexaminedThe diff-aware materializer: the Python projection of the store.410d769b
materializer/test-readback.pyexaminedThe diff-aware materializer: the Python projection of the store.410d769b
materializer/test-search-index.pyexaminedThe diff-aware materializer: the Python projection of the store.410d769b
materializer/test-unmeasured-coverage.pyexaminedThe diff-aware materializer: the Python projection of the store.a521e28
docs/.manifest.jsongenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/.projection-contract.jsongenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/architecture.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/architecture.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/concern-checklist.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/concern-checklist.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/concerns.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/concerns.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/contradictions.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/contradictions.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/diagnosticity.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/diagnosticity.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/disagreements.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/disagreements.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/entry-point.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/entry-point.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/field-notes.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/field-notes.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/files.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/files.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/findings.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/findings.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/hot-spots.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/hot-spots.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/how-to-read.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/how-to-read.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/index.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/index.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/master-plan.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/master-plan.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/not-yet-surveyed.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/not-yet-surveyed.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/onboarding-report.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/onboarding-report.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/open-questions.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/open-questions.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/resolution-history.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/resolution-history.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/resolved-findings.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/resolved-findings.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/resolved-leads.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/resolved-leads.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/seams.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/seams.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/search-index.jsgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/sessions.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/sessions.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/stale.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/stale.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/subsystems/b01-survey-methodology-and-agent-contracts.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/subsystems/b01-survey-methodology-and-agent-contracts.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/subsystems/b02-mcp-core-persistence-and-lifecycle.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.50abc288
docs/subsystems/b02-mcp-core-persistence-and-lifecycle.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.50abc288
docs/subsystems/b03-knowledge-tools-and-workflow-api.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/subsystems/b03-knowledge-tools-and-workflow-api.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/subsystems/b04-diff-aware-materializer.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.50abc288
docs/subsystems/b04-diff-aware-materializer.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.50abc288
docs/subsystems/b05-packaging-installer-validation-and-product-docs.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.50abc288
docs/subsystems/b05-packaging-installer-validation-and-product-docs.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.50abc288
docs/subsystems/b06-report-interface-design-and-validation-studies.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.50abc288
docs/subsystems/b06-report-interface-design-and-validation-studies.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.50abc288
docs/subsystems/b07-embedded-research-surveys-and-platform-trials.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.50abc288
docs/subsystems/b07-embedded-research-surveys-and-platform-trials.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.50abc288
docs/subsystems/b08-activation-evidence-and-release-readiness.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.50abc288
docs/subsystems/b08-activation-evidence-and-release-readiness.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.50abc288
docs/subsystems/b09-conspectus-design-lanes-their-drivers-and-receipts.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.50abc288
docs/subsystems/b09-conspectus-design-lanes-their-drivers-and-receipts.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.50abc288
docs/vocabulary.htmlgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
docs/vocabulary.mdgenerated-ignorematerialize_docs renders these pages and dev/promote-docs.mjs checks them in; they are the projection's output, not its source.a7f9384d
materializer/uv.lockgenerated-ignoreuv writes this lockfile; it is resolver output.a7f9384d

§Concern review

AT-1

Verdict
Accepted behavior
Evidence
Code verified
Linchpin dependency
🔗

Rationale

Clean publication is the atomic unit and it is a directory rename, which is atomic on one filesystem: the stage is fully rendered and verified before the old output is moved aside and the stage takes its place. The ordinary non-clean render is deliberately not atomic — it writes pages one at a time into the live directory — and the manifest is saved after them, so an interrupted render leaves a partly rewritten projection with a manifest describing the previous one. That is recoverable by the next render and is why publication uses the clean path.

AT-2

Verdict
Out of scope
Evidence
Code verified

Rationale

This process opens the store read-only and writes no database rows, so it cannot leave a WAL frame uncommitted. Checkpoint atomicity belongs to B-02, which owns the writer.

CC-1

Verdict
Confirmed defect
Evidence
Code verified

Rationale

The derived-state coherence question this subsystem is most exposed to is whether a projection can disagree with the rows behind it, and the read-back answers it on three axes over both formats — except at one point. Two readers still draw from entries, a table no code path writes: readback.py:687's per-row stale-marker expectation set and renderers.py:696's index reading. The freshness strip beside them was migrated onto the ledger (B04-2's repair), so the page now shows a live count while the axis that is supposed to verify its markers computes an empty expectation set. Filed as B04-R1.

CR-1

Verdict
Accepted behavior
Evidence
Code verified
Linchpin dependency
🔗

Rationale

The read side is safe by construction: mode=ro over WAL, so a concurrent agent write never blocks the render and never sees a partial page. The write side is a single process over one output directory with no lock of its own, so two concurrent renders into the same docs/ would interleave; clean publication narrows the window to a rename but does not close it. Not reachable as the product is driven — materialize_docs is a synchronous tool call on a single-threaded server — so acceptable rather than a defect, and recorded as a property of the configuration.

EP-1

Verdict
Accepted behavior
Evidence
Code verified

Rationale

The exceptional paths preserve the invariant the nominal path establishes: the previous projection survives every failure. A renderer exception is caught per page, recorded with its traceback, and clears summary.ok so the process exit code carries it; clean publication removes the stage on a red summary and restores the backup if promotion itself throws; the connection is closed in a finally. The deliberate asymmetry is that one failed page does not abort the run — batch behaviour retained on purpose, with the failure propagated rather than swallowed.

IF-1

Verdict
Accepted behavior
Evidence
Code verified
Linchpin dependency
🔗

Rationale

This is the subsystem the concern is really about, and the divergence it guards against is closed in three places rather than one: the cross-reference resolver re-runs over every alive page on every render, not only the rewritten ones, precisely because another page changing can change which ids resolve; the HTML navigation is rebuilt from the whole page plan; and orphaned pages are retired rather than left behind. Acceptable rather than ruled out because the equality is asserted by construction and not compared: nothing in the product renders both ways from one state and diffs them. test-materializer.py's five-step sequence is that comparison, and it is a test fixture rather than a gate on a real store.

RL-1

Verdict
Accepted behavior
Evidence
Code verified
Linchpin dependency
🔗

Rationale

The two resources are the SQLite connection and the staging directory. The connection is closed in a finally on both the render and the verify paths. The stage is removed on a red summary and on an exception, and the backup is restored if promotion throws before the output exists. Acceptable rather than ruled out for one residual the code itself notes: if the backup cannot be removed after a successful promotion the path is retained and reported as a warning, so a repeated failure accumulates backup directories beside the output.

SC-1

Verdict
Accepted behavior
Evidence
Code verified
Linchpin dependency
🔗

Rationale

The schema seam is held by a probe with a named cause and one fix, and the vocabulary seam by generation: OBLIGATION_BEARING_SQL and the evidence-quality ladder come from the generated module rather than from a hand-kept copy, which is what B04-4's repair was. Acceptable rather than ruled out for the seam nothing holds: reporting-style.md specifies the typed projections this file implements, and no check relates the two. B04-4's history is exactly that failure — a hand-maintained sixth copy of the evidence ladder in a static page that only humans read.

SI-1

Verdict
Out of scope
Evidence
Code verified

Rationale

The renderer is handed a storage directory and an output directory by its caller and derives no project identity of its own. Containment of the output is B-03's resolveStorageOutputPath before the spawn, plus the unmanaged-file refusal here. Out-of-scope so the identity concern stays where the derivation is.

SI-2

Verdict
Accepted behavior
Evidence
Code verified
Linchpin dependency
🔗

Rationale

Every revision the projection prints comes from a row that was resolved at write time by the server, so the renderer reproduces rather than re-derives them, and it stamps each page with the store's own checked revision rather than the working tree's. Acceptable rather than ruled out because the renderer performs no ancestry check of its own: a row whose ref_sha the workspace can no longer reach is printed exactly as a reachable one is, and only the gates outside this subsystem — the depth gate, the carry receipt, receipt-provenance — distinguish them.

TB-1

Verdict
Accepted behavior
Evidence
Code verified

Rationale

The one exogenous call this subsystem makes — git remote get-url origin, to decide whether file identities can open at a github.com revision — carries timeout=3 and check=False and returns None on any OSError or SubprocessError, so an unresponsive git costs the link affordance and nothing else. This is the bound B02-R1 finds missing on the server side, applied here.

TR-1

Verdict
Ruled out
Evidence
Code verified

Rationale

Every value this renderer writes comes from a store it opened read-only, and every path it writes is verified inside the output root: resolve_all resolves each candidate and skips anything that escapes, materialize.py refuses a clean replacement over a directory holding a file no manifest claims, and the MCP side resolves the output through resolveStorageOutputPath before the process is spawned. The projection never writes back to the store, so a corrupt derived artifact cannot become durable truth — ADR-0005 names that direction explicitly and the code follows it.

§Survey artifact

§B-04 — Diff-aware materializer

Structural account, read at c073404. Scope: materializer/** — the only Python in the product and the only reader-facing surface. docs/ is its output and is generated-ignore.

§Observed

One plan, four consumers. core.py:_plan computes the page list from the store; rendering, the HTML shell's navigation, the reader's-guide route table and the read-back's expected-path set all read it. A page cannot exist in one and not the others.

Diff-aware by source hash. .manifest.json records per page the identifiers it was rendered from (db:, prose:, synthetic:) and their hashes; a page is rewritten when a source hash changes, when its own content hash changes, when the file is missing, or when MATERIALIZER_VERSION moves. Pages whose generator disappeared are retired — file and manifest entry both.

Two formats, one source, read back independently. HTML is derived from the finished post-xref Markdown, and ProjectionVerifier checks state, coverage and content on each format separately, so a healthy Markdown cannot mask damaged HTML.

Refusal preserves the prior output. Absent required view, unknown nav group, renderer exception, red read-back, unmanaged file in the output directory — each leaves docs/ as it was. Clean publication stages, verifies, then promotes.

Derived predicates are generated, not restated. OBLIGATION_BEARING_SQL and the evidence-quality ladder come from the generated vocabulary module, so the renderer, the server and the lint cannot disagree about what carries an obligation or which rung is strongest.

§State containers

None held across calls. Manifest and Summary are per-run dataclasses; the SQLite connection is opened mode=ro and closed in a finally. Claimed as an explicit negative.

§Seam contracts from this side
  • memory.db — read mode=ro, never written. This side depends on the two views REQUIRED_VIEWS names and refuses by name when they are absent.
  • <storage>/docs/ — written here, promoted by dev/promote-docs.mjs (B-09) to the repository's checked-in docs/.
  • reporting-style.md (B-01) — specifies the typed projections this implements; nothing compares the two.
§Open

readback.py:687 and renderers.py:696 still read entries, a table no code path writes. Recorded as B04-R1.