From c0cead216940708db48ff8ffd8c619811e6d5153 Mon Sep 17 00:00:00 2001 From: codex Date: Tue, 25 Aug 2026 21:44:14 +0200 Subject: [PATCH] docs(canon): accept ADR-012 and retract the parts it supersedes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ADR-012 accepted 2026-08-25. ADR-010 — partially superseded, notes added inline: decision 1: "a reading of the repositories" never said which copy, and the answer was neither the forge nor a working copy but whichever checkout last synced. The hub holds no repository files and never reads one. decision 5: "central derives, does not accept pushes" was policy while the workstation pushed everything. decision 6: "preliminary" was named but never built. ADR-003 — partially superseded: decision 2: fingerprints composed from filesystem mtime are invalidated in part. mtime is a property of one workstation, differs across clones, and says nothing about content. Evidence: git_fingerprint for the-custodian held the initial commit while last_state_synced_at was minutes old. decision 5: the rebuild principle was correct but never exercised, and its "without data loss" claim holds only while nothing exists solely in the hub — which was false for 111 records on 2026-08-25. ADR-001, ADR-005, ADR-007 and ADR-011 reviewed and unaffected; ADR-007 is reinforced, since derived identifiers let an overlay and a forge-derived projection compute the same identity. Co-Authored-By: Claude Opus 5 --- .../adr-003-materialized-derived-state.md | 31 ++++++++++++++++++- ...010-hub-authority-and-local-cache-model.md | 22 ++++++++++++- ...ojection-source-and-preliminary-overlay.md | 11 +++++-- 3 files changed, 59 insertions(+), 5 deletions(-) diff --git a/canon/architecture/adr-003-materialized-derived-state.md b/canon/architecture/adr-003-materialized-derived-state.md index 7657a0d..cdd15f4 100644 --- a/canon/architecture/adr-003-materialized-derived-state.md +++ b/canon/architecture/adr-003-materialized-derived-state.md @@ -16,7 +16,10 @@ tags: ["architecture", "state-hub", "caching", "read-model", "materialized-view" ## Status -Accepted. +Accepted, and **partially superseded by `ADR-012`** (accepted 2026-08-25). +Decision 2's fingerprint composition is invalidated in part; decision 5's rebuild +principle is given a concrete source and a required operation. See the notes on +each. ## Context @@ -84,6 +87,19 @@ the stored value is updated. computation (repo record, related domain, goals, snapshots). - Include the `mtime` (filesystem modification time) of every file that feeds the computation (`SCOPE.md`, `CLAUDE.md`, lockfiles, `tpsc.yaml`, etc.). + +> **Invalidated in part 2026-08-25 by `ADR-012` decisions 1 and 2.** Filesystem +> `mtime` is not a property of the source. It differs between machines, changes +> on a fresh clone, and says nothing about content — so a fingerprint built from +> it describes one workstation's filesystem rather than the repository. Under +> `ADR-012` the projection derives from the forge, and the commit that produced +> a record is both the correct input and the auditable one. +> +> This was not merely theoretical drift. `git_fingerprint` for `the-custodian` +> held the repository's *initial* commit while `last_state_synced_at` was minutes +> old: the field meant to identify what a projection reflects was wrong by the +> entire history of the repository, and nothing noticed. Replace `mtime` inputs +> with the source commit. - Join all components with `|` as a pipe-separated string — no hashing needed since the string is compared by equality, not transmitted to clients. - If a file is absent, encode `filename:absent` rather than omitting it, so @@ -110,6 +126,19 @@ table's `max(snapshot_at)` directly rather than relying on the repo record. Per ADR-001, the state-hub must be rebuildable from scratch by re-ingesting all canonical sources. Materialised tables are **caches**, not records of authority. They may be wiped and repopulated at any time without data loss. + +> **Given concrete form 2026-08-25 by `ADR-012` decision 7.** This principle was +> correct and, until now, never exercised — an untested rebuild path is an +> assumption rather than a capability, and this one was believed for long enough +> that a divergence survived seven weeks behind it. `ADR-012` requires the +> reconstruction to exist as a routine operation, scoped per repository, sourced +> from the forge, and verifiable against it. +> +> The claim "without data loss" also needs its precondition stated: it holds only +> while the rule immediately below does. On 2026-08-25, 111 work records existed +> only in the hub, so a rebuild at that moment would have destroyed them. +> `ADR-012` therefore requires reset to refuse, per repository, when records have +> no counterpart in the forge. This means: - No materialised table may be the only copy of any information. - Schema migrations that wipe a materialised table are safe and expected. diff --git a/canon/architecture/adr-010-hub-authority-and-local-cache-model.md b/canon/architecture/adr-010-hub-authority-and-local-cache-model.md index 7fdac66..62edf03 100644 --- a/canon/architecture/adr-010-hub-authority-and-local-cache-model.md +++ b/canon/architecture/adr-010-hub-authority-and-local-cache-model.md @@ -16,7 +16,9 @@ tags: ["architecture", "state-hub", "repo-manager", "hub-core", "authority", "ca ## Status -Proposed. +Proposed, and **partially superseded by `ADR-012`** (accepted 2026-08-25). +Decisions 1, 5 and 6 are sharpened or given a mechanism there; see the notes on +each below. Everything else in this ADR remains in force. ## Context @@ -69,6 +71,12 @@ Hub — running on railiance — is authoritative. It is authoritative *as a rea of the repositories*, not as a second place data lives. Repository files remain the source of truth (`ADR-001`). +> **Sharpened 2026-08-25 by `ADR-012` decision 1.** "A reading of the +> repositories" never said *which* copy of them, and the honest answer was +> neither the forge nor any particular working copy: the projection derived from +> whichever checkout last ran the sync. The hub holds no repository files at all +> and never reads one. `ADR-012` names the forge as the projection source. + **2. A local hub is a cache, never a database.** Local instances hold a rebuildable projection. A cache may be discarded and reconstructed from the repositories at any time, and losing it must never lose work. @@ -118,11 +126,23 @@ conflict and belongs to git. "Authoritative" means authoritative *reading*, so nothing may inject derived state directly. Hub-native records are the exception and keep a real write path. +> **Sharpened 2026-08-25 by `ADR-012` decision 6.** This was policy, not +> practice: nothing derived, and the workstation pushed everything. `ADR-012` +> retires push-based sync as the primary path so that "central derives" becomes +> true rather than aspirational. + **6. Preliminary until confirmed.** Locally registered data and uncommitted repository state are preliminary until the central service has seen them. Mitigation is by changing the repository files and the local cache — never by editing central to match a local view. +> **Given a mechanism 2026-08-25 by `ADR-012` decisions 3 and 4.** "Preliminary" +> was named here but never built, so in practice locally registered data was +> indistinguishable from derived state once it arrived. It is now a labelled +> overlay within the same projection — explicitly not a second store — and it +> retires when the commit carrying it reaches the forge. The prohibition on +> editing central to match a local view is unchanged. + Combined with `ADR-007` decision 2 (identifiers derived from `PREFIX-WP-NNNN`), "preliminary" largely stops mattering: a cache computes the same identifier central will, so offline-registered data is already correct on arrival and needs 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 8e77224..45b4f8c 100644 --- a/canon/architecture/adr-012-projection-source-and-preliminary-overlay.md +++ b/canon/architecture/adr-012-projection-source-and-preliminary-overlay.md @@ -2,9 +2,9 @@ id: CUST-ADR-012 type: architecture-decision-record title: "What the Hub Projects: Forge as Projection Source, Working Copies as Preliminary Overlay" -status: proposed +status: accepted owner: the-custodian -revision: "draft-1" +revision: "1.0" last_reviewed: "2026-08-25" review_interval: 6m decided_by: Bernd Worsch @@ -16,7 +16,7 @@ tags: ["architecture", "state-hub", "forgejo", "projection", "provenance", "auth ## Status -Proposed. Supersedes `ADR-010` decision 1's phrase "authoritative as a reading of +**Accepted 2026-08-25** by Bernd Worsch. Supersedes `ADR-010` decision 1's phrase "authoritative as a reading of the repositories" by making the reading concrete, and implements decision 6's unbuilt notion of "preliminary". @@ -227,6 +227,11 @@ built. Those belong to implementation. - **`ADR-010`** — decisions 1 and 5 are sharpened, not reversed: central still derives and still does not accept pushes of derived state. Decision 6's "preliminary" gains a mechanism. The local-cache-versus-database framing stands. +- **`ADR-003`** — partially superseded. Decision 2 composes fingerprints from + filesystem `mtime`, which is a property of one workstation rather than of the + source; under decision 1 here the input is the commit. Decision 5 already + stated the rebuild principle correctly but had never been exercised; decision 7 + here makes it an operation with a source, a scope and a verification. - **`ADR-007`** — derived identifiers become more valuable here: a forge-derived projection and a preliminary overlay compute the same identifier for the same record, so absorbing an overlay entry needs no reconciliation.