Skip to content

Commit bd6337b

Browse files
committed
docs(governed): restate the projections, the registry and their laps as main builds them
ADR-0087's D4 progress note records #22483 (PR #22556) and #22485 (PR #22638) as landed and its other not-yet-landed sentences move to the past tense; the ruling quotation is untouched. AGENTS.md re-counts the checked-in generated artifacts (six) and the ADR-0087 row of the regenerate table says there is nothing to commit. The retirement playbook sends step edits to registry.ts.template and drops the gen:spec-changes / gen:upgrade-guide laps. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011u73oxZ5X95qrARPTeoU6v
1 parent a2e94c2 commit bd6337b

3 files changed

Lines changed: 37 additions & 31 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: 2 additions & 2 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

‎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)