docs(adr-0087): point the superseded retirement claim at its correction, and record the artifact-ingestion door ruling - #17997
Conversation
…tion, and record the artifact-ingestion door Two records-only corrections to ADR-0087, both additive — no sentence is rewritten or deleted, because an accepted ADR's text binds and a superseded decision is still a record (Prime Directive #13). 1. The "retired entry is skipped by the loader" paragraph under "The load-window's second half is now mechanical" states the authoring load path's rule and stands 35 lines above the 2026-07-31 addendum that supersedes it for metadata at rest. It gains an in-place blockquote pointer naming both addenda, in the same form ADR-0044 and ADR-0058 use. 2. The artifact-ingestion door's policy was ruled on #12772 and recorded in no addendum: the ADR's reader met the stored-row policy and nothing about the boot seam. A ninth addendum records it in the file's own addendum form, quoting the ruling verbatim, with the as-built window, the two in-tree doors, the default-flip exclusion, the schema-layer residue boundary and the flag's live seam inventory. Claude-Session: https://claude.ai/code/session_01DAcomhvR9kKizeYgg89Vo8 Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewHead: Files: ① derived judgments — an ADR addendum records decisions already made; the review asks whether each recorded statement is TRUE on
② semver: docs-only; no package touched. ③ boundary flags: Checks on Implemented-by: Verdict: PASS — both defects of #17894 repaired additively, every recorded fact re-verified on Generated by Claude Code |
维护者速读(终稿)改了什么 —— 只动 ADR-0087 一个文件,只加不删(+101/−0)。两处:① 「退役条目被 loader 跳过」那句原文不动,下面加一段引用块指向 2026-07-31 与 2026-09-13 两条附录 —— 说明这句只管作者侧加载路径,静态元数据( 为什么 —— 这条策略只活在 issue 里,ADR 没记;读到原句就停的人会把它带到它不成立的地方(#17894 的两个缺陷)。 风险 —— 无契约变化、无代码;一处「裁决说 authored specVersion、实现用声明范围下限」的差异是如实记录并标了 批准即由本席按裁决 C 落地(三个 check 还在跑,落地前再读一次)。要不要批? Generated by Claude Code |
|
Ruling C landing step — skills seat (session Generated by Claude Code |
Fixes #17894
Records-only and purely additive: 101 insertions, 0 deletions, one file (
docs/adr/0087-metadata-protocol-upgrade-contract.md). No code, no test — the code half is #16864's.Defect 1 — a live false rule 35 lines above its own correction. The paragraph under "The load-window's second half is now mechanical" still reads, in the present tense, "a retired entry is skipped by the loader (
applyConversions) and replayed only by the chain (migrate meta) and the fixture CI". It gains an in-place blockquote pointer to the two addenda that supersede it for metadata at rest. The sentence itself is NOT rewritten and NOT deleted: an accepted ADR's text binds, and a superseded decision is still a record (Prime Directive #13). The form is this corpus's own — ADR-0044 and ADR-0058 both carry exactly this blockquote shape.Defect 2 — the artifact-ingestion door was in no addendum. The door's policy was ruled on #12772 and lived only in that issue, so a reader of this ADR met the 2026-07-31 stored-row policy and nothing about the boot seam. A ninth
## Addendumrecords it in the file's own addendum form (the form triage 5651629548 ruled, used eight times before): the ruling quoted verbatim from comment5443380108, the as-built versioned window and the four branches it decides, the two in-tree doors that consume the one policy, the default-flip exclusion, the schema-layer residue boundary (comments5448522858/5448958115), and the flag's live seam inventory. One as-built reading is recorded as a reading rather than smoothed over: the ruling says "authoredspecVersion", while what ships keys off the declaredengines.protocolrange floor.Acceptance — measured both directions
origin/mainat65767d23(827 lines) vs this branch atf7d8e9da(928 lines).^## AddendumSuperseded for metadata at restskipped by the loader#12772artifact-ingestionapplyArtifactForwardConversions## Addendum (2026-07-31)retiredFromLoadPathStronger than the greps for the addendum the card pins: the whole
## Addendum (2026-07-31)section is byte-identical across the two refs — md50b3788f178526522dd8dcac7aedb519d, 2657 bytes on both — andgit diff --statis 101 insertions with no deletions, so nothing above could have been edited.The quoted ruling was diffed against the API body of comment
5443380108after whitespace normalisation: verbatim match.Gates
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 22 families for this path; all 22 were run and reconciled with--rancarrying each exit code: 22 derived, 22 run, 0 NOT-MEASURED, 0 UNRUN, every oneexit 0.pnpm --filter @objectstack/lint run check:doc-formula-expressionsfirst exited 3 (prerequisite: unbuilt@objectstack/formula/@objectstack/lint, nothing measured); the closure was built under the shared verify lock and it re-ranexit 0.check:adr-0087-registrationasserts, for this file, that thenot-requireddisposition vocabulary it accepts and the categories this ADR documents are the same set, in both directions — it says nothing about addendum headings; the new text adds no disposition marker, and the gate is green.Non-vacuity, proven by ablation rather than asserted. The new symbol anchor was mutated on disk to a name that does not exist (
applyArtifactForwardConversionsplus aZZZsuffix; grep before/after: real 1 to 0, fake 0 to 1).node scripts/check-adr-symbol-anchors.mjsthen exited 1 with[unresolved-symbol]naming that anchor at line 867 — so its green is a reading of this diff, not of nothing. Restored withgit checkout HEAD -- (path);git diff HEADempty and the file's blob hash equal to the HEAD blob (4c83b339).Repo-wide
pnpm lint— a declared narrowing, with its three readings. (1) The population comes from eslint's own config: everyfiles:block ineslint.config.mjsglobsts,tsx,mts,cts,js,jsx,mjs,cjsonly; there is no markdown block. (2)pnpm exec eslint --no-inline-config --format jsonover the one changed file returns one result,errorCount: 0, message "File ignored because no matching configuration was supplied." (3) Invariance: the diff is one.mdfile and no config file, and no type-aware linting is configured, so no untouched file's verdict can move. CI runs the full sweep regardless.Changeset
skip-changeset:docs/adr/**ships in no package'sfiles[], so this publishes nothing.Acceptance notes
Noted, not filed: the ruling's "authored
specVersion" and the shipped key (the declaredengines.protocolfloor) are not the same reading, and the difference is load-bearing — it is why the default-flip exclusion exists. It has already been carded twice — #16693 and #17885, both landed and shut — so this PR records it in the addendum instead of filing a third card. No other out-of-scope finding; the code half stays #16864's, and #17885 was not touched.维护者速读(草稿)
改了什么 —— 一份已接受的 ADR 里的两处「记录缺陷」,只加不改:① 在
:355那段「retired entry 被 loader 跳过」的旧话旁边加一条指向其更正的引用块(原句一个字没动);② 补上第九条## Addendum,把 #12772 已经裁过、却只活在 issue 里的 artifact 入口门政策写进记录。代码零改动。为什么改 —— 那句旧话站在自己的更正上方 35 行,文档顺序保证读者先读到假的那句;而 artifact 门的整条政策在 ADR 里一个字都没有,ADR 的读者对那个 boot seam 一无所知。两条都是「把已经声明过的东西拉回记录」,不是新决定 —— 形式用的是本文件自己用过八次的 addendum 惯例。
风险与代价(含回滚) —— 风险接近零:纯文档、纯新增、无发布面、无 changeset;22 个派生门禁全绿,并用消融证明锚点门禁确实读了这份 diff。回滚 = revert 这一个 commit,没有任何代码或生成物依赖它。唯一需要您过目的判断:新 addendum 里明说「裁决写的是 authored
specVersion,实际落地键的是engines.protocol的下界」—— 这是照实记录已落地实现,不是改裁决。席位意见 ——
你要做的 —— governed 面(
docs/adr/**),按规矩是维护者手合:本 PR 保持 draft,任何席位都不会转 ready、不入队、不挂 auto-merge。请读两处新增文字(尤其第九条 addendum 里引用 #12772 的那段是否如您所愿),认可后由您批准,席位再落地。Generated by Claude Code