diff --git a/canon/architecture/adr-012-projection-source-and-preliminary-overlay.md b/canon/architecture/adr-012-projection-source-and-preliminary-overlay.md index 00170a7..8e77224 100644 --- a/canon/architecture/adr-012-projection-source-and-preliminary-overlay.md +++ b/canon/architecture/adr-012-projection-source-and-preliminary-overlay.md @@ -128,8 +128,37 @@ Three properties make it real rather than ceremonial: - **Routine, not emergency.** It should be run deliberately and often enough that it is known to work, not discovered under pressure. A reset that has never been performed is indistinguishable from one that does not work. -- **Scoped.** Per repository as well as fleet-wide. Rebuilding one repository's - records must not require discarding everything, or it will never be used. +- **Per repository is the unit.** Not a convenience over a fleet-wide operation — + the repository *is* the unit of reconstruction, and the fleet-wide form is + defined as iteration over it. + + This follows from the source. Each repository is a separate forge repository + with its own history and its own head commit, so its projection is derivable in + isolation and provable in isolation: fetch that repository, rebuild its + records, compare against that repository's head. Nothing about that requires + knowing the state of any other repository, and a design that made it require so + would be inventing a dependency the source does not have. + + It also bounds the blast radius, which is what makes decision 7's "routine" + achievable. A rebuild that can only run fleet-wide is an operation nobody runs + casually, and therefore an operation nobody runs — which is precisely how + `ADR-010`'s never-executed reconstruction claim came to be believed. Scoped to + one repository, a rebuild is small enough to be ordinary, and ordinary is the + only state in which it stays known-working. + + It is also the only form that composes with the refusals below. A repository + holding projection-only records can be held back and dispositioned while every + healthy repository around it is rebuilt; an all-or-nothing reset is blocked + entirely by a single bad repository, which in practice means it is blocked + permanently. + + With contributors, per-repository scope is what keeps one person's rebuild from + touching another person's records. + + The fleet-wide form must therefore be a loop over the per-repository form, + sharing one implementation. The rarely-used dangerous path and the frequently + used safe path must be the same code, so the rare one is exercised by the + common one rather than trusted on the strength of never having been run. - **Idempotent and verifiable.** A reset followed by a reset produces the same projection, and the result can be compared against the forge to show it matches. Derived identifiers (`ADR-007`) are what make this possible: the same commit @@ -147,6 +176,13 @@ local database, and a rebuild at that moment would have erased them. The reset path must detect that condition and stop, naming what would be lost, rather than proceed and report success. +The refusal is evaluated per repository, in keeping with the scope above. A +repository whose records all exist in the forge is rebuildable regardless of what +any other repository holds, and a fleet-wide run must skip and report the +repositories it refuses rather than abort the whole pass. Otherwise one +unresolved repository blocks reconstruction everywhere, and the capability decays +back into the untested assumption this decision exists to prevent. + **8. Formal git review stays optional.** Deriving from the default branch gives a shared baseline without requiring pull requests. Review can be adopted per repository where it earns its keep; this ADR neither mandates nor forbids it.