ADR-012 decision 7 requires the fleet form to share the per-repository
implementation: the rarely-run wide operation must be the frequently-run narrow
one, or the wide one is trusted on the strength of never having been exercised.
Failure behaviour is the substance. A refusal does not stop the pass — aborting
on the first refusal means one unresolved repository blocks reconstruction
everywhere, which in practice means permanently. An error does not stop it
either. Each repository gets its own session so one failure cannot roll back
another's work, and only repositories that applied are committed.
Refs STATE-WP-0083-T04
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 2583210@bnt-lap001
Assistant-Session: f2bff2d5-e9b2-4338-92ca-10282a927006
The reset raised IntegrityError on net-kingdom: its ADHOC-2026-08-23 derives to
an identifier another repository already holds — the collision CUST-WP-0066
documents, where two repositories created the same daily identifier on the same
day. Derivation is deterministic, so the clash is real rather than incidental.
It now checks, before creating anything, whether a derived identifier belongs to
another repository, and refuses naming both the record and the holder. A refusal
is something the caller can rule on; a constraint violation is a stack trace.
Acknowledging retirements deliberately does not authorise a collision. Those are
different decisions — one says the work is gone, the other says take an
identifier another repository owns — and conflating them would let a routine
acknowledgement smuggle an identity change through.
Refs STATE-WP-0083-T03
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 2583210@bnt-lap001
Assistant-Session: f2bff2d5-e9b2-4338-92ca-10282a927006
Every work-record type carried a stable identifier except tasks, whose rows held
only id, workplan_id, title, status and priority — nothing connecting a row to
CUST-WP-0067-T01 in the file it came from. Matching was therefore by title, so a
renamed heading looked like one task vanishing and another appearing, and the
forge-derived reset had to refuse to touch tasks at all.
Adds tasks.record_id (nullable: no migration can invent an identity for an
existing row) and a backfill that reads the pairing from the repository files,
where a task declares both its canonical id and its projection UUID. 5516 pairs
across 121 repositories with zero conflicts; 4456 of 6073 cache task rows
identified.
Diff and reset now key on record_id where present, falling back to a
title-prefixed key so an unidentified row stays visibly unidentified.
Unknown stays unknown: a row the files do not claim keeps no identity and the
reset keeps refusing to act on it, and an existing identity is never
overwritten — a mismatch is recorded as a conflict rather than resolved.
Refs STATE-WP-0083-T06
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 2583210@bnt-lap001
Assistant-Session: f2bff2d5-e9b2-4338-92ca-10282a927006
Implements ADR-012 decision 7 as amended (STATE-WP-0083-T03). Creates what the
forge has and the hub lacks, updates what differs, retires what no longer
derives. It never deletes: hub-native records reference workplans with ON DELETE
RESTRICT, and destroying a progress event to tidy a derived projection would
lose hub-native truth to fix a derived-state problem.
Retirement is refused by default. A record that stops deriving may mean a
deliberately deleted file or a caller pointed at the wrong branch; only the
caller can say which.
Verified against live data and rolled back: whitehat-security applied 5 updates
with no retirements; the-custodian refused, naming the four hub-first records
confirmed by hand to have no backing file.
Tasks of existing workplans are deliberately untouched — hub tasks carry no
canonical identifier, so matching is by title and a renamed heading would
destroy and recreate a record. Tasks are created only alongside a new workplan,
where nothing exists to mis-match. Tracked as T06.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 2583210@bnt-lap001
Assistant-Session: f2bff2d5-e9b2-4338-92ca-10282a927006
Implements ADR-012 decisions 1 and 2 (STATE-WP-0083 T01, T02 partial). Central
clones the default branch from Forgejo and derives its own projection: 69
workplans and 459 tasks from the-custodian at d5013ae, identical across runs,
with the commit recorded as provenance.
Identifiers are derived in the ADR-007 namespace and verified against live
records, so a forge-derived projection and a preliminary overlay agree on
identity without reconciliation.
The diff first matched hub records by UUID and was badly wrong: most hub records
carry pre-ADR-007 random identifiers, so nearly everything appeared
simultaneously missing and stale, and a reset built on it would have destroyed
and recreated the entire projection. It now matches canonical record id, falling
back to the backing file. whitehat-security — bootstrapped straight from files —
now reports clean, which is the control.
Task-level comparison is deliberately not trusted: hub tasks carry no canonical
record id, only a title, so matching is by title. Recorded as T06; T03 is
limited to workplans until it lands.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 2583210@bnt-lap001
Assistant-Session: f2bff2d5-e9b2-4338-92ca-10282a927006