Skip to content

Commit 7873a05

Browse files
docs(governed): ADR-0087, AGENTS.md and the retirement playbook describe the D4 projections and the migration registry as main builds them (#22796)
Fixes #22667 Clause-②: no Three governed texts still described `packages/spec/spec-changes.json`, the protocol upgrade guide and `packages/spec/src/migrations/registry.ts` as committed files with a regeneration lap. On `main` none of the three is committed. This PR restates 12 sites as `main` now builds them (11 at the first head, site 12 in patch round 1 below). No code, gate, script or published file changes. Dispatched by `/pm-dispatch skills` seat 2 (PM session `session_011u73oxZ5X95qrARPTeoU6v`, claim `6106319581`), executed in the same session. Tree read: `origin/main` `a2e94c2a05`. The diff is measured from that base, and every gate below ran on head `bd6337b8b`. ## What `main` does (measured before editing) | Fact | Evidence on `a2e94c2a05` | |---|---| | Neither projection is committed | `git ls-files packages/spec/spec-changes.json packages/spec/protocol-upgrade-guide.md content/docs/protocol-upgrade` prints nothing. `.gitignore` lists all three paths. | | Neither projection has a `merge=os-regen` route | `grep -n os-regen .gitattributes` shows 16 routed paths, and neither projection is one of them. | | The guide's copy and route went at #22483 | `514bf3c101` (PR #22556) deletes `docs/protocol-upgrade-guide.md merge=os-regen` and reduces that file to a pointer stub. | | `spec-changes.json`'s copy and route went at #22485 | `46064dfa03` (PR #22638) deletes the file and `packages/spec/spec-changes.json merge=os-regen`. | | `registry.ts` is generated and not committed | `.gitignore` lists it. `registry.ts.template` is tracked (`ed1de8c2db`, PR #22706) and holds `STEP18_RATIONALE`, `const step18` and the earlier steps' `conversionIds` / `rationale`. | | `gen:migration-registry` exists; `check:migration-registry` does not | `packages/spec/package.json` scripts. `check-generated.ts` files `gen:migration-registry` under `UNGATED_GENERATORS`, and its gate was retired with the committed copy. | | The two projection checks still exist and never report stale | `check:spec-changes` / `check:upgrade-guide` run `--check`: they generate in memory, read nothing on disk, and exit 1 only when generation fails (`lib/projection-cli.ts`). | All five commits named above pass `git merge-base --is-ancestor` against HEAD with exit 0. A positive answer needs no control leg. ## The 11 sites (location, then before and after) | # | Location (base line) | Before | After | |---|---|---|---| | 1 | ADR-0087 `:3` Status | "which says what has landed and which cards carry the rest" | "which says what is generated where and where each part landed" | | 2 | ADR-0087 `:207`-`:208` (2026-08-06 note) | "`spec-changes.json` is deliberately unsharded" | "was left deliberately unsharded … That call was about merging its committed copy, which #22485 deleted (PR #22638)" | | 3 | ADR-0087 `:258`-`:273` (D4 note) | "The ruled end state, and the cards that still carry it … #22485, which lands last … Until #22485 lands the committed copies stay in the tree" | "The ruled end state, landed": #22483 as `514bf3c101` (PR #22556), #22485 as `46064dfa03` (PR #22638). No committed copy remains, and a registry entry's PR regenerates neither projection. | | 4 | ADR-0087 `:283`-`:284` | "which #22485 removes" | "which #22485 removed" | | 5 | ADR-0087 `:431`-`:432` (P2 bullet) | "is ruled to become a pointer stub … which #22483 carries" | "became a pointer stub … the docs site's per-major pages (#22483, PR #22556)" | | 6 | ADR-0087 `:438`-`:442` (P2 amendment) | "Those copies stay in the tree until #22485 deletes them … what #22483 and #22485 still carry" | "Those copies are gone … generate in memory and compare nothing … where each part landed" | | 7 | AGENTS.md `:706` | "**eight** checked-in generated artifacts" | "**six**" | | 8 | AGENTS.md `:717` (regenerate table) | ADR-0087 row: regenerate with `gen:spec-changes`, `gen:upgrade-guide` | Gates: the same two, in memory, red only when the registries do not project. Regenerate: nothing to commit; `gen:migration-registry` (install, build and test run it too) writes the gitignored `registry.ts`. | | 9 | playbook `:213`-`:216` (D3 step) | "在 `packages/spec/src/migrations/registry.ts`" | "在 `packages/spec/src/migrations/registry.ts.template`(`registry.ts` 由 `gen:migration-registry` 从它与 `entries/` 整文件生成并被 git 忽略,在 `registry.ts` 里手改不会进提交)", which is the wording proposed in `6100582202` | | 10 | playbook `:260` | "`gen:spec-changes`、`gen:upgrade-guide`、`gen:api-surface`、`gen:docs`。" | "`gen:api-surface`、`gen:docs`;新条目跑 `gen:migration-registry`;D4 投影不提交,本地不重生成。" | | 11 | playbook `:335`-`:337` | "只改 conversion 的 `summary` 也会过期 … 所以纯散文改动也要 `gen:spec-changes` + `gen:upgrade-guide`" | "只改 conversion 的 `summary` 不欠重生成。它逐字进两条 D4 投影,都不提交;PR 渲染其 diff。" | The card lists sites 2, 3, 4 and 6 to 11, with site 9 coming from `6100582202`. The dispatch's same-class sweep of ADR-0087 found sites 1 and 5, which describe unlanded work in the same way. The verbatim ruling quotation at ADR-0087 `:219`-`:220` is unchanged, and so is ADR-0120 `:459`-`:460`, which triage ruled to be history. The PR contains nothing beyond these 11 sites: `git diff --stat a2e94c2 HEAD` shows 3 files, +37 / -31. How site 7's count was measured: the table's "Gate that fails" column names eight gates, and six of them still guard tracked artifacts. - `check:docs`: `content/docs/references/` (225 tracked files) - `check:api-surface`: `packages/spec/api-surface/` (19) - `check:authorable-surface`: `packages/spec/authorable-surface/` (14), plus `json-schema.manifest/` (14) - `check:skill-docs`: `skills/README.md`, `content/docs/ai/skills-reference.mdx` - `check:skill-refs`: `skills/*/references/_index.md` (9) - `check:react-blocks`: `skills/objectstack-ui/references/react-blocks.md` `check:spec-changes` and `check:upgrade-guide` are the other two, and their projections have 0 tracked files. Site 8 differs from the card. The card proposed `check:migration-registry`, but PR #22706 (`ed1de8c2db`) removed that gate after the card was filed. The row therefore names the two gates that do exist and states that there is nothing to commit. Site 11 differs from the card too. No committed artifact carries a conversion's `summary` any more. It is read only by the two in-memory projections (`spec-changes.ts` `to`, `build-upgrade-guide.ts` table rows) and by their rendered PR diff. A summary-only edit therefore owes no regeneration. ## Line budget - `AGENTS.md`: 1108 lines before and 1108 after, with net 0 on the two edited lines. Ratchet line: `✓ check-skill-line-ratchet: AGENTS.md is 1108 lines (ceiling 1116; headroom 8).` The widest table row is 768 bytes (pin 768). - `.claude/skills/spec-property-retirement/SKILL.md`: 337 lines before and 337 after. Ratchet line: `✓ check-skill-line-ratchet: .claude/skills/spec-property-retirement/SKILL.md is 337 lines (ceiling 337; headroom 0).` Site 9 adds +2 lines for its new parenthetical. Site 11 pays for them with -2 lines by deleting the false regenerate instruction. That is a content deletion, not a re-wrap. Site 10 swaps one line for one line. Every new line is at most 120 bytes (largest 119). Breaks fall only where the ratchet's own `breakLegal` allows one. - ADR-0087 carries no ceiling (+27 / -21). ## Gates The gate list came from `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` with no paths: 31 commands derived from the merge base `a2e94c2a0`. All 31 exited 0 on head `bd6337b8b`. `dispatch-gates --ran` reports: `✓ dispatch-gates --ran: 31 derived famil(ies) accounted for — 31 run, 0 NOT-MEASURED (a DERIVED zero — all 31 recorded an exit code and none of them is 3).` The first run of `pnpm --filter @objectstack/lint run check:doc-formula-expressions` refused with exit 3 (PREREQUISITE NOT MET: `@objectstack/formula` and `@objectstack/lint` were unbuilt). I built both under the verify lock (`VERDICT command-exit 0`) and re-ran it: exit 0. Gates the dispatch named, with their verdict lines: - `check-adr-0087-registration --base origin/main`: "this PR adds no declared-breaking changeset". Its `--self-test` passes 463 assertions. - `check:adr-anchors`: OK (64 anchored files, 43489 citations resolve). - `check-adr-links`: 725 relative link destinations resolve. - `check-adr-symbol-anchors`: 2309 anchors across 142 records resolve. - `check:pm-governed-prose`: 2 surfaces name all 6 governed surfaces. - `check:pm-governed-merges`: passes. - `check:pm-skill-ratchet`: the two lines above. - `check:skill-frame-sync`: coherent. - `check:pm-prior-rulings`: 155 cases pass. - `check:future-spec-major`: passes. - `check:docs-audit-scope`: in sync. - `check:doc-authoring`: clean. - `check:pm-skill-id-lint`: 34 files clean. - `check:nul-bytes`: OK (10817 files, no raw control bytes). - `check-ci-filter-parity`: OK. The diff touches no package, so no package build or test is owed. CI runs the rest. Changeset: none. The diff touches only `docs/adr/**`, `.claude/**` and the private root's `AGENTS.md`, and no package's `files[]` ships any of them. The PR therefore takes `skip-changeset`. ## Acceptance notes - AGENTS.md section "Touched `packages/spec`?" still says "Two generators have **no** gate at all — `gen:openapi` and `gen:sbom`". `check:generated --reconcile-only` on this tree prints "3 ungated generators", because `gen:migration-registry` joined the list at PR #22706. It is the same family as this card, but it lies outside the AGENTS.md lines this claim declared, so it is not edited here and goes back to the seat. - The same section's "All of them live in one job — `TypeScript Type Check` … runs its gates **sequentially**" predates this card. Five of the six gates run in `Type Check · source gates`, and `check:api-surface` runs in `Type Check · consumer gates`. Both lanes sit behind the required `TypeScript Type Check` aggregate. Noted only. - ADR-0120 `:459`-`:460` and `:560` record what that PR ran, and stay untouched as history. ## Patch round 1 (written by the PM seat from the diff on `origin` and the dev's report; head `6cb0d8ecd`) - **Site 12 — AGENTS.md base `:761`–`:762`, the same "Touched `packages/spec`?" section.** Before: "Two generators have **no** gate at all — `gen:openapi` and `gen:sbom`. Nothing verifies their output is current; the wrapper reports that each run rather than staying silent." After: "Three generators have **no** gate at all. Nothing verifies `gen:openapi` and `gen:sbom` are current, and `gen:migration-registry` writes gitignored output that install, build and test regenerate; the wrapper reports all three each run rather than staying silent." Evidence: `packages/spec/scripts/check-generated.ts` lists `gen:migration-registry` under `UNGATED_GENERATORS` since PR #22706 (`ed1de8c2db`), and `pnpm --filter @objectstack/spec check:generated --reconcile-only` prints "3 ungated generators". The claim's AGENTS.md surface was widened to the whole section on the card (comment 6106593221) before the edit. - Incremental diff `bd6337b8b..6cb0d8e`: `AGENTS.md` +3/−2, nothing else. Whole PR against base `a2e94c2a05`: 3 files, +40/−33. - Line budget after the patch: `AGENTS.md` 1109 lines (ceiling 1116; headroom 7), +1 for the sentence's third line; the playbook and ADR-0087 are unchanged from the first head. - The first Acceptance note below is resolved by this round; the other two stand. ## 维护者速读(草稿) **改了什么**:三份给 agent 读的受管文本是 ADR-0087 的 D4 进度注、AGENTS.md「改了 `packages/spec` 要重生成什么」一节和属性退役 playbook。里面还有句子把 `spec-changes.json`、升级指南和迁移注册表 `registry.ts` 当作提交在仓里的文件来写。本 PR 把这 12 处改成 main 现在的样子:两条投影只在发布或文档构建时生成,PR 上只在内存里生成并展示 diff;`registry.ts` 在安装和构建时由模板加条目文件生成,不提交。改动只有文字,不碰代码、门禁和发布内容。 **为什么改**:旧句子会让下一个改 spec 迁移的 agent 去跑一圈已经不存在的重生成。本周已有三个 dev 重生成后又回退。旧句子还会让人把 step-18 的说明手改进一个不会被提交的生成文件,改动在下一次构建时静默丢失。 **风险与代价(含回滚)**:不发布任何包,不改任何门禁或脚本。ADR-0087 里维护者裁决的逐字引文没有动。回滚就是 revert 这一个 PR。代价是 playbook 删掉了一条已失效的陷阱说明(3 行压成 1 行),用来抵付新增的模板说明,行数棘轮不变。 **席位意见**: **你要做的**:看一遍上面的 11 项清单和补丁轮 1 的第 12 项。同意就给一个 APPROVED review,落地由席位来做。 --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 322ff1e commit 7873a05

3 files changed

Lines changed: 40 additions & 33 deletions

File tree

‎.claude/skills/spec-property-retirement/SKILL.md‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -210,10 +210,12 @@ conversion 是消费者跟的;D3 条目是升级方的 agent 读的。三个都
210210
「没有 alias 窗口,故意的」;对**默认值翻转**,只有确知输入早于翻转的 seam 才可重
211211
放,其余按 id 退订 `excludeConversionIds` —— `app-hidden-to-unpublished` 在 artifact
212212
门即如此。
213-
- [ ] **一步 D3 链**,在 `packages/spec/src/migrations/registry.ts`;`conversion.toMajor` **必须等于**该步的
214-
major。**18 步**:conversion 只进 `conversions/registry.ts` 的 `MAJOR_18_CONVERSIONS`,照其头注按
215-
标识符排序插入,本步 `conversionIds` 由它派生;`rationale` 只加一个 `STEP18_RATIONALE` 片段,
216-
按其头注插在你 D3 semantic id 的排序位;尾部追加被两处头注点名的 merge 测试拒收。
213+
- [ ] **一步 D3 链**,在 `packages/spec/src/migrations/registry.ts.template`(`registry.ts` 由
214+
`gen:migration-registry` 从它与 `entries/` 整文件生成并被 git 忽略,在 `registry.ts` 里手改不会
215+
进提交);`conversion.toMajor` **必须等于**该步的 major。**18 步**:conversion 只进
216+
`conversions/registry.ts` 的 `MAJOR_18_CONVERSIONS`,照其头注按标识符排序插入,本步 `conversionIds`
217+
由它派生;`rationale` 只加一个 `STEP18_RATIONALE` 片段,按其头注插在你 D3 semantic id 的排序
218+
位;尾部追加被两处头注点名的 merge 测试拒收。
217219
**更早的步**:id 加进 `MIGRATIONS_BY_MAJOR[N].conversionIds`,扩写该步 `rationale`。⚠ 没有东西
218220
直接断言「每个 conversion 都接进了某一步」,拼错的 id 在 replay 时被**静默跳过**;
219221
chain-replay 测试抓得到它,只因为没接线的 fixture 永远到不了自己的 `after`。
@@ -257,7 +259,7 @@ conversion 是消费者跟的;D3 条目是升级方的 agent 读的。三个都
257259
无墓碑删键 → 该行**消失**,这是门 (a) 的绊线,所以同一个 PR 里有意删掉它)与
258260
`json-schema.manifest/<category>.json`。#5837 起两者都按 category 分片 —— 门
259261
禁把整个目录读成一个集合,退役流程不变;变的只是那一行住在哪个文件。然后
260-
`gen:spec-changes`、`gen:upgrade-guide`、`gen:api-surface`、`gen:docs`。
262+
`gen:api-surface`、`gen:docs`;新条目跑 `gen:migration-registry`;D4 投影不提交,本地不重生成。
261263
「改了 X → 重新生成 Y」的表见 AGENTS.md。
262264
- [ ] **Forms** —— 从 `packages/spec/src/**/*.form.ts` 剪掉 `{ field: '<key>' }` 输
263265
入。未强制能力的表单输入是假合规的 UI 半边。原位留一行注释。
@@ -332,6 +334,4 @@ pnpm check:i18n && pnpm --filter @objectstack/spec test
332334
- **截断的 grep 漏掉编写者。** `| head -8` 藏掉了 `SKILL.md` 的 `defineSkill` 示
333335
例;`examples/` 有三处 `template: true`,不是一处。先按上下文找文件,再进文件里
334336
grep 键 —— 且把 `tsc` 和门禁当权威清扫器。
335-
- **只改 conversion 的 `summary` 也会过期。** 那个字符串被逐字抄进
336-
`spec-changes.json` 的 `to` 字段与 upgrade guide 的表行,所以纯散文改动也要
337-
`gen:spec-changes` + `gen:upgrade-guide`,和任何别的改动一样。
337+
- **只改 conversion 的 `summary` 不欠重生成。** 它逐字进两条 D4 投影,都不提交;PR 渲染其 diff。

‎AGENTS.md‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -703,7 +703,7 @@ Root also exports: `defineStack`, `composeStacks`, `defineView`, `defineApp`, `d
703703

704704
### Touched `packages/spec`? Regenerate its artifacts BEFORE pushing
705705

706-
`packages/spec` has **eight** checked-in generated artifacts, each with its own CI
706+
`packages/spec` has **six** checked-in generated artifacts, each with its own CI
707707
gate. All of them live in one job — `TypeScript Type Check` in `lint.yml`, which is
708708
required and has no paths filter, so no gate can go dormant on the PR that breaks it.
709709
That job runs its gates **sequentially**, so the first stale artifact masks every one
@@ -714,7 +714,7 @@ behind it. Match the change to the gate and regenerate up front:
714714
| A `.describe()` / TSDoc on any schema | `check:docs` | `gen:schema && gen:docs` |
715715
| A public export (added / removed / renamed) | `check:api-surface` | `gen:api-surface` |
716716
| An authorable key on a metadata schema | `check:authorable-surface` | `gen:schema` |
717-
| An ADR-0087 conversion / migration registry | `check:spec-changes`, `check:upgrade-guide` | `gen:spec-changes`, `gen:upgrade-guide` |
717+
| An ADR-0087 conversion / migration registry entry | `check:spec-changes`, `check:upgrade-guide` — in memory, red only when the registries do not project | nothing to commit — `gen:migration-registry` (install, build and test run it too) writes the gitignored `registry.ts` |
718718
| A `SKILL.md` (frontmatter or body) | `check:skill-docs`, `check:skill-refs` | `gen:skill-docs`, `gen:skill-refs` |
719719
| The react-blocks contract | `check:react-blocks` | `gen:react-blocks` |
720720

@@ -758,8 +758,9 @@ Principles the wrapper encodes (its own output is the authority on detail):
758758
a name, with accepted cases in the shrink-only, hand-edited
759759
`dual-source-exports.baseline.json`.
760760

761-
Two generators have **no** gate at all — `gen:openapi` and `gen:sbom`. Nothing verifies
762-
their output is current; the wrapper reports that each run rather than staying silent.
761+
Three generators have **no** gate at all. Nothing verifies `gen:openapi` and `gen:sbom`
762+
are current, and `gen:migration-registry` writes gitignored output that install, build and
763+
test regenerate; the wrapper reports all three each run rather than staying silent.
763764

764765
---
765766
## Context Routing — apply the right role per path

‎docs/adr/0087-metadata-protocol-upgrade-contract.md‎

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# ADR-0087: Metadata protocol upgrades for AI consumers — conversion over notification, executable migrations, machine-verifiable upgrades
22

3-
**Status**: Accepted (2026-07-04, #2582) · trued up to as-built 2026-07-15 (see Addendum) · **Amended** (2026-09-30, #20390 ruling A — the artifact-ingestion window decides per entry by each retired conversion's `retiredAfter`; see the amendment note under the 2026-09-13 addendum's window bullet) · **Amended** (2026-10-09, #22449 ruling B′ — the two D4 projections, the per-major section of `spec-changes.json` and the protocol upgrade guide, are generated at publish rather than committed; see the amendment note under D4, which says what has landed and which cards carry the rest, and the struck clauses in the P2 phase-status bullet)
3+
**Status**: Accepted (2026-07-04, #2582) · trued up to as-built 2026-07-15 (see Addendum) · **Amended** (2026-09-30, #20390 ruling A — the artifact-ingestion window decides per entry by each retired conversion's `retiredAfter`; see the amendment note under the 2026-09-13 addendum's window bullet) · **Amended** (2026-10-09, #22449 ruling B′ — the two D4 projections, the per-major section of `spec-changes.json` and the protocol upgrade guide, are generated at publish rather than committed; see the amendment note under D4, which says what is generated where and where each part landed, and the struck clauses in the P2 phase-status bullet)
44
**Deciders**: ObjectStack Protocol Architects
55
**Builds on**: [ADR-0059](./0059-third-party-backward-compatibility-gates.md) (layered backward-compat gates — this ADR is its consumer-facing sequel), [ADR-0078](./0078-no-silently-inert-metadata.md) (no declarable-but-unenforced metadata — the un-checked `engines.protocol` is exactly this class), [ADR-0025](./0025-plugin-package-distribution.md) (§3.2 `engines.protocol` / `engines.platform` compatibility ranges, §3.10 #3 protocol-first check order), [ADR-0033](./0033-ai-assisted-metadata-authoring.md) (the authoring population this ADR designs for), [ADR-0049](./0049-no-unenforced-security-properties.md) (enforce-or-remove), [ADR-0054](./0054-runtime-proof-for-authorable-surface.md) (prove-it-runs), AGENTS.md Prime Directive #12 (contract-first, no consumer-side dialect fallbacks — §"Why the conversion layer does not violate PD #12" draws the line)
66
**Consumers**: `@objectstack/spec` (protocol version constant, conversion layer, deprecation/change registries), `@objectstack/cli` (`validate`, `doctor`, `migrate meta`), the runtime metadata loader (handshake + conversion), `@objectstack/mcp` (the AI-native change/migration surface), `@objectstack/create-objectstack`, the Release workflow, and every third-party consumer — whose maintainer is assumed to be an **AI agent**
@@ -205,7 +205,9 @@ chain** — the database-migration model applied to metadata source files.
205205
> **Amended 2026-08-06 (#5837), paths only.** `api-surface.json` became the directory
206206
> `api-surface/` (one shard per entry point) and ships in the npm artifact as such; the
207207
> release diff reads whichever layout the previously published tarball carried. `spec-changes.json`
208-
> is deliberately unsharded — it is keyed by version, which has never been a conflict surface.
208+
> was left deliberately unsharded — it is keyed by version, which was never a conflict surface.
209+
> That call was about merging its committed copy, which #22485 deleted (PR #22638): nothing
210+
> merges it any more.
209211
210212
> **Amended 2026-10-09 (#22449, ruling B′) — where the two projections live.** Ruling
211213
> `6078203801` on #22449, letter B′, which the maintainer answered 「同意」 at
@@ -255,20 +257,23 @@ chain** — the database-migration model applied to metadata source files.
255257
> artifact when it is non-empty. That step is red only when a side cannot be
256258
> generated, never because of the size of a diff.
257259
>
258-
> **The ruled end state, and the cards that still carry it.** Not landed when this
259-
> note was written, and stated here as ruled rather than as done:
260+
> **The ruled end state, landed** (trued up 2026-10-11). Not landed when this note was
261+
> first written; both remaining cards have landed since, each deleting one committed copy
262+
> and its `merge=os-regen` route in `.gitattributes`:
260263
>
261-
> - condition (2), the guide's public address and the pointer stub at
262-
> `docs/protocol-upgrade-guide.md` — #22483;
263-
> - the deletion of the committed copies (the per-major projection in
264-
> `packages/spec/spec-changes.json`, the guide body at
265-
> `docs/protocol-upgrade-guide.md`) and of their two `merge=os-regen` routes in
266-
> `.gitattributes` — #22485, which lands last.
264+
> - condition (2) — #22483, landed as `514bf3c101` (PR #22556). The guide's public
265+
> address is the docs site, one page per protocol major, generated at docs build into
266+
> the gitignored `content/docs/protocol-upgrade/`. `docs/protocol-upgrade-guide.md`
267+
> stays at its path as a hand-written pointer stub naming that address; the guide body
268+
> it used to hold left git with its route;
269+
> - the committed `packages/spec/spec-changes.json` and its route — #22485, landed last
270+
> as `46064dfa03` (PR #22638).
267271
>
268-
> Until #22485 lands the committed copies stay in the tree, and the generators'
269-
> no-flag mode (`gen:spec-changes`, `gen:upgrade-guide`) still writes them, but
270-
> `check:spec-changes` and `check:upgrade-guide` no longer compare them: they can go
271-
> stale, and the copies that ship are the record. Condition (3) is cloud's half and
272+
> No committed copy of either projection remains. `packages/spec/spec-changes.json` and
273+
> `packages/spec/protocol-upgrade-guide.md` are gitignored paths the publish lane writes
274+
> for `files[]` to ship, and the generators' no-flag mode writes only untracked output
275+
> (`gen:spec-changes` that `spec-changes.json`, `gen:upgrade-guide` the docs pages), so a
276+
> registry entry's pull request regenerates neither. Condition (3) is cloud's half and
272277
> lives in that repository (objectstack-ai/cloud#2750); this record governs the
273278
> framework half.
274279
>
@@ -281,7 +286,7 @@ chain** — the database-migration model applied to metadata source files.
281286
> generators the publish lane runs, and the registry entries those projections are
282287
> computed from stay committed, reviewable source. What leaves git is the committed
283288
> aggregate and the re-sync laps it cost. The 2026-08-06 note above ("deliberately
284-
> unsharded") is about that committed copy, which #22485 removes.
289+
> unsharded") is about that committed copy, which #22485 removed.
285290
286291
- The Release workflow diffs the current `api-surface.json` against the previously
287292
published one (reusing the ADR-0059 §3 gate artifact instead of discarding it),
@@ -428,18 +433,19 @@ scaling framework-side execution when the consumers can execute themselves.
428433
**amended 2026-10-09** — it is generated from the registries at publish, as
429434
`protocol-upgrade-guide.md` inside the npm artifact and on the GitHub Release,
430435
and in memory, with its diff rendered, at pull request;
431-
`docs/protocol-upgrade-guide.md` is ruled to become a pointer stub naming the
432-
guide's public address, which #22483 carries.
436+
`docs/protocol-upgrade-guide.md` became a pointer stub naming the guide's
437+
public address, the docs site's per-major pages (#22483, PR #22556).
433438

434439
> **Amended (2026-10-09) — the projections are generated at publish, not
435440
> committed.** Provenance: ruling `6078203801` on #22449 (letter B′; maintainer
436441
> 「同意」), which supersedes the 2026-08-10 #6957 ruling's rejection of option B
437442
> and keeps its reason, the review diff, as its condition (1); the generation
438443
> half landed as `5b12503c31` (PR #22533, card #22482). The struck clauses
439-
> describe committed copies drift-checked in CI. Those copies stay in the tree
440-
> until #22485 deletes them, and `check:spec-changes` / `check:upgrade-guide`
441-
> no longer compare them. The amendment note under D4 is the full record:
442-
> what is generated where, and what #22483 and #22485 still carry.
444+
> describe committed copies drift-checked in CI. Those copies are gone — the
445+
> guide's at #22483 (PR #22556), `spec-changes.json`'s at #22485 (PR #22638) —
446+
> and `check:spec-changes` / `check:upgrade-guide` generate in memory and
447+
> compare nothing. The amendment note under D4 is the full record: what is
448+
> generated where, and where each part landed.
443449
- **P3 — MCP tools + RC discipline (D6): deferred, evidence-gated** (as the ADR
444450
Boundaries intended): built when external-consumer demand justifies the
445451
operational surface. Nothing else in this ADR depends on it.

0 commit comments

Comments
 (0)