Uh oh!
There was an error while loading. Please reload this page.
docs(adr): ADR-0129 records the enforced object-naming contract; decision letters for the letter-cited ADRs - #13067
Conversation
📓 Docs Drift CheckThis PR changes 4 package(s): 3 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
What this run could not see
Coarse fallback — 130 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 57301f0d7786c12ad09a37386831412f8d88f996 && git checkout 57301f0d7786c12ad09a37386831412f8d88f996
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 6c6157af05b25b28be0b3a7e92ce03ef85a98653 9a7a7ec79366f6f0b61b09f010ac8bae27c8bd0b && git checkout -B drift-repro 6c6157af05b25b28be0b3a7e92ce03ef85a98653 && git merge --no-ff 9a7a7ec79366f6f0b61b09f010ac8bae27c8bd0b
node scripts/docs-audit/affected-docs.mjs --json 6c6157af05b25b28be0b3a7e92ce03ef85a98653
|
Uh oh!
There was an error while loading. Please reload this page.
Fixes#12786
Fixes#12918
Ruled two-card convoy (2026-08-29, maintainer, live director session batch #1 — verbatim ruling on both cards: 「执行,批 #1 其他卡同意」).
Ruling on #12786 (option 1, scoped): "give decision-letter indices to the ADRs that live code cites by letter today — ADR-0014 (D2), ADR-0024 (D4, D5.2), ADR-0067 (D2 — its own amendment already names 'the D2 join'), ADR-0081 (D1). Not all 67: only cited records get letters. … Letters are recognition, never invention: each letter heading must name a decision the record already states. Where a clean mapping would distort a record's structure, that ADR takes the ruled fallback (option 2: respell those code citations to what the record does say) instead — decided per-record in the PR, with reasoning shown."
Ruling on #12918 (option 甲, new ADR): "one page recording the enforced current-state naming contract — the object name IS the canonical id everywhere, the module prefix is embedded literally in the name, there is no separate namespace field … written with decision letters so citations verify. The same page reconciles ADR-0028: 0028's D1–D6 are a Deferred target model pointing the other way; until its recorded re-open trigger fires, the new ADR is the governing record."
Governed surface (docs/adr/**): this PR stays draft for the maintainer's pinned approval and hand merge. Clause-②: no — no schema shape moves; the diff is ADR pages, code comments, two rejection-message strings, and one test title.
Part A — ADR-0129 (new, next free number; tree max was 0128 and no open PR adds one)
docs/adr/0129-object-name-is-the-canonical-id.mdrecords the enforced current-state object-naming contract, with letters:ADR-0028 reconciliation line: 0028's Supersedes-line note previously read "there is no standalone ADR for that rule today" — this PR gives it the one-line factual correction the new record makes true (it now points at ADR-0129 and its governing-until-re-open rule). Nothing else in 0028 moves; its Deferred status and re-open trigger stand as written.
Part B — per-record letter dispositions
ADR-0067 — letters attached (clean recognition). The record numbers its decisions ordinally (headings "1."–"6.") and its own status line and 2026-08-06 Amendment already call Decision-2 "D2" ("the D2 join"). The six Decision headings are relabeled to D1–D6 at the same positions, same order, same titles:
ADR-0014 — ruled fallback (respell). The record is the
recordform-field type; the two engine.ts citations claimed a service-principal audit-attribution decision the record nowhere states — a phantom number (no repo ADR letters that decision). Attaching a D2 would make the citation resolve while still pointing at an unrelated decision — the exact "swap the phantom for a lie" guardrail from #12913. Respelled both sites to the real contract: ExecutionContext.actor in @objectstack/spec kernel/execution-context.zod.ts.ADR-0024 — ruled fallback (respell with the cloud qualifier). The record here is MCP connectors; the cited D4 (identity provenance) and D5.2 (break-glass last-admin invariant) are the cloud repo's enterprise-identity ADR-0024. Evidence already landed in this repo: the guard implementation itself (last-admin-guard.ts line 4), plugin index.ts, and both guard test headers spell it "cloud ADR-0024 D5.2", as do plugin-auth CHANGELOG entries. The four anchored-surface citations gain the same qualifier (the anchors gate's structural cross-repo escape, kept honest for readers); the adjacent bare ADR-0071 on the same edited auth-plugin line — also a cloud record (SCIM verification), unrelated to this repo's 0071 — is qualified in the same stroke. This session could not read the cloud repo (no access), so the D4 qualifier extends the identification the D5.2 spellings already established rather than a fresh verification — recorded on #9072, the standing card for the cloud-side check.
ADR-0081 — ruled fallback (respell). The record is the trusted React page tier; ADR-0105's citation note records that its "Decision section is numbered 1–4 and has no D-numbered decisions at all", and both ADR-0093 (D9 citation note) and ADR-0105 document that the "ADR-0081 D1/D2" labels come from a pre-repo decision record whose number collides with this repo's series. Minting a D1 in the React-page record would be pure invention. Respelled: the sys-member action-gate sites now cite ADR-0093 D9 (the repo record that restates exactly the leaned-on invariant — single-org sessions carry an active org); the auth-plugin bootstrap docblocks describe the pre-repo decision and point at ADR-0093 D9's citation note. Whether the pre-repo record is cloud ADR-0081 stays an open question owned by #9072 — this PR deliberately does not assert it.
Part C — surviving phantom spellings re-pointed to ADR-0129 D3
Changeset: one patch changeset for @objectstack/spec (published rejection-message strings changed; not breaking, no ADR-0087 disposition required — check:adr-0087-registration green).
Gate counts — the closure proof (all at head 9a7a7ec)
check:adr-anchors cannot-verify note, before (base e4902d2) vs after:
Verdict lines at 9a7a7ec: "check-adr-anchors --self-test: 106 assertions" (exit 0) and "check-adr-anchors: OK (52 anchored file(s) … 917 decision-letter citation(s) on the anchored surface name a decision the record makes)" (exit 0) — the target ("empty on the letter-cited surface") is met exactly.
Other gates run locally at 9a7a7ec (exit codes captured before any pipe): check:adr-links (575 link destinations resolve) · check:nul-bytes · spec check:generated ("All 14 generated artifacts are up to date" — includes check:docs, check:authorable-surface, check:api-surface, check:skill-refs, check:strictness-ledger, check:liveness, check:test-typecheck) · check:empty-state · check:variant-docs · check:i18n · check:i18n-stale-fill · check:type-check-coverage · check:type-check-debt --re-measure ("none above its recorded number") · check:engine-double-contract · check:where-matcher · check:query-options-erasure · check:dispatcher-error-vocabulary · check:cross-package-test-inputs · check:durability-log-level · check:merge-driver · check:doc-authoring · check:engine-split-ratio (after deepening the shallow clone as the gate prescribes) · plus the remaining dispatch-gates union — all exit 0. Not measurable in this container: scripts/pm/check-half-states.mjs (no GitHub credential — exit 3 "no reading", per its own text; CI runs it with credentials).
Tests at 9a7a7ec: spec object.test.ts — 185 passed; the renamed title runs and passes when selected by name ("1 passed | 184 skipped"); translation.test.ts — 118 passed.
Out of scope, recorded
The phantom-label families extend beyond the anchored surface (about 18 more live ADR-0014-D2 sites, about 26 more ADR-0024 letter sites including runtime error strings pinned by tests, about 15 more ADR-0081-D1 sites). They are outside the gate's population today, but any of those files gaining an anchor JSON re-arms the tripwire. Census recorded as a comment on #9072 (the standing pre-repo-label card) rather than a new issue — dedup search hit it directly.
Generated by Claude Code
Generated by Claude Code