Repository navigation
Commit 4cc5bcd
docs(governed): the retirement route is retiredKey() on any shape, with the retiredAfter stamp and the step-18 registry shape (#20797)
Fixes #20465
Fixes #20575
Clause-②: no
Family PR, one commit per card. Tier H as a whole (`AGENTS.md`,
`docs/adr/**`), so it stays a draft for the maintainer's review. Nothing
here publishes: `skip-changeset`.
## What changed
**#20465, commit `249b7836`** (the route, the `retiredAfter` stamp, and
the ADR-0087 window sentence from the spec seat 4 fold `5873572274`):
- `.claude/skills/spec-property-retirement/SKILL.md` §2 route table. Row
1 is now "any shape, strict or not" → `retiredKey()` tombstone. On a
strict shape a bare deletion is loud, but it reports only an
unrecognized key and loses both the prescription and the `tsc` channel.
Row 2 keeps the guidance map only for a spelling the shape never
declared (a retired key's old alias, a wrong-layer pointer). Such a
spelling has no property for a tombstone to replace. The example is now
`data/mapping.zod.ts`. The same section's ledger table, and two lines in
§4, rename "strict 删除" to "无墓碑删键", because the route table no longer
names a strict deletion.
- The kit's `retiredFromLoadPath` checklist item now names the required
`retiredAfter: 'x.y.z'`. `tsc` refuses a retirement without it. A new
retirement carries the current `packages/spec/package.json` label, and
`retired-after.census.test.ts` pins each value. The artifact door opens
its window per entry from this stamp.
- `AGENTS.md` Post-Task Checklist step 3 says the same as the kit, in
one rule: `retiredKey()` whether or not the schema is `.strict()`, and a
`*_RETIRED_KEY_GUIDANCE` entry only for a spelling the shape never
declared. The closing clause now says what actually differs between the
routes: a tombstone keeps its liveness-ledger row, and a key deleted
without one loses it.
- `docs/adr/0087-metadata-protocol-upgrade-contract.md`, in the
2026-09-13 addendum's window bullet: the sentence "`floor >= runtime`
replays nothing" is struck through and amended in the dated style that
ADR-0005 and ADR-0053 used on 2026-09-30. The amendment note gives the
provenance (the #20390 ruling A, landed as `e956924e`), and the status
line gains an Amended entry.
**#20575, commit `2e3f8aa0`** (the step-18 D3-chain item, worded for the
shape on `main` after #20535 and #20574):
- For step 18, the conversion goes only into `MAJOR_18_CONVERSIONS` in
`conversions/registry.ts`. It is inserted at its identifier's sorted
position, as the list's header says. `CONVERSIONS_BY_MAJOR[18]` and the
step's `conversionIds` both derive from that list. The `rationale` gains
one `STEP18_RATIONALE` fragment at the sorted position of its D3
semantic id. The merge pin that each header names refuses an append at
the tail.
- Earlier steps keep the old wording, and the misspelled-id warning now
covers them only. Step 18 cannot hit it, because its ids are derived.
## Measured first (premise holds), at `7a09eee1`
- **The route.** The `retired-key.ts` header (`:22`–`:28`) gives the
reason tombstones stay on closed shapes. The `acceptsNothing` doc in
`strict-object.ts` calls a tombstone "strictly stronger than a
`guidance` entry". The precedents are real: `action.aria` (`dcd3bceaa`,
a `strictObject`, whose comment at `action.zod.ts:1678` says
"`retiredKey()` rather than a bare deletion although this is a
`strictObject`"), the list view's `tabs` (`6e3e5462c`, in the strict
`ListViewShapeSchema`), and the cube members' inner `name`
(`analytics.zod.ts:243`, `:298`).
- **Where the guidance map still carries weight.** `data/mapping.zod.ts`
lists the retired keys' old alias spellings (`query`, `onError`) in its
guidance map so that "an author who learned the alias should land on the
prescription". Those spellings were never declared keys, so a tombstone
has nothing to replace. `app.zod.ts` (`showall`, `location`) has the
same shape.
- **`retiredAfter`.** `conversions/types.ts` types it as REQUIRED on the
retired arm of the union. The census test pins an entry that no
published tarball carries retired to the package label (`17.5.0` on this
tree).
- **ADR-0087's sentence is false on `main`.** `idsTheFloorPostdates` in
`artifact-forward-conversion.ts` replays a retired entry when the floor
is at or below its `retiredAfter`, even when the floor is at or above
the runtime label (verdict `'converted-retired-after'`). On this tree
three entries carry `retiredAfter: '17.5.0'`, which equals the label
(`time-default-utc-suffix-dropped`, `cube-refresh-key-removed`,
`connector-triggers-removed`). An artifact whose floor is `17.5.0`
therefore replays three entries, where the ADR said it replays none.
`artifact-forward-conversion.test.ts:564` pins the same case one release
back.
- **Step 18.** `step18.conversionIds` is
`CONVERSIONS_BY_MAJOR[18]!.map((c) => c.id)`, and
`CONVERSIONS_BY_MAJOR[18]` is
`inApplicationOrder(MAJOR_18_CONVERSIONS)`. `rationale` is
`joinRationale(STEP18_RATIONALE)`. The pins are
`packages/spec/scripts/conversions-major18-merge.test.ts` and
`step18-rationale-merge.test.ts`. `step17` still carries a hand-kept
`conversionIds` list.
## For the reviewer: one point where the text departs from the triage
wording
The #20465 triage direction says to keep the guidance map "only for the
case that needs it: a shape where a tombstone cannot sit, such as a
`z.preprocess` stage ahead of the closed shape (`retired-key.ts:177`)".
The route follows that direction, but the example did not hold up when
measured:
- `retired-key.ts:177` describes `acceptRetiredDefaultResidue`. That
preprocess stage strips an emitted default ahead of a closed shape that
still declares the key as a `retiredKey()` tombstone. The tombstone sits
there.
- The list view's `tabs` tombstone (`6e3e5462c`) sits in a strict member
of `ViewMetadataSchema`, which is itself a `z.preprocess` ahead of its
union.
- The guidance map is consulted only on the `unrecognized_keys` path of
a `strictObject`, so a preprocess stage cannot carry one either.
So both texts name the case that was measured: a spelling the shape
never declared. If the maintainer means a different case, the Tier H
review is the place to say so, and the kit follows.
## Scope notes
- The claim's surface for the kit named `:86`–`:87`, `:207` and
`:215`–`:220`. Consequential edits in the same file: the §2 ledger table
row and the ORPHAN bullet (`:102`, `:107`), and §4 `:242` and `:257`
(the "strict 删除" term). The file is otherwise unchanged.
- The new lines were paid for by deleting narrative that is kept
elsewhere:
- the orphan leg's history (the "report `aria`/`performance`" story),
which `packages/spec/scripts/liveness/orphans.mts` carries verbatim in
its header;
- the "上一版样例栽在这" sentence in the `retiredFromLoadPath` item. The rule it
taught is the item's own preceding sentence and the
`conversions/types.ts` docblock.
## Line budget (`node scripts/pm/check-skill-line-ratchet.mjs`, exit 0)
| file | before | after |
|---|---|---|
| `.claude/skills/spec-property-retirement/SKILL.md` lines | 337 / 337 |
337 / 337 |
| same file, widest table row | 326 / 326 bytes | 324 / 326 bytes |
| `AGENTS.md` lines | 1106 / 1116 | 1107 / 1116 |
Every added line of the kit and of `AGENTS.md` is within 120 bytes,
except table rows, which are structurally exempt. After commit 1 the kit
read 335 / 337. The ratchet prints an informational hint to lower the
row pin to 324; the pin lives in
`scripts/pm/check-skill-line-ratchet.mjs`, which is outside this
surface, so it is left for the owning seat.
## Gates, at head `2e3f8aa0`
These were derived by `node scripts/pm/dispatch-gates.mjs --commands`
from this change set (31 families, the same set the dispatch named). All
exited 0. Reconciled with `--ran`: "31 derived, 31 run, 0 NOT-MEASURED,
0 UNRUN", a derived zero, with every exit code recorded.
- `check-adr-0087-registration` (and its self-test), `check-adr-links`
(and self-test; 691 links resolve), `check-adr-symbol-anchors` (and
self-test; 2157 anchors across 140 records resolve),
`check-ci-filter-parity`, `check-closing-keyword-parity` (and
self-test), `check-comment-mask-corpus`, `check-harness-current
--self-test`.
- `pnpm check:` adr-anchors, agent-test-spelling,
changeset-gate-self-tests, cross-package-test-inputs, doc-authoring,
docs-audit-scope, driver-memory-census, future-spec-major,
gitlink-declared, nul-bytes, pm-governed-merges, pm-governed-prose (2
instruction surfaces name all 6 governed surfaces), pm-prior-rulings,
pm-skill-id-lint (34 files clean), pm-skill-ratchet, refd-timer-probe,
required-contexts, skill-frame-sync, watch-hint-literal.
- `pnpm --filter @objectstack/lint run check:doc-formula-expressions`.
The first run exited 3 (PREREQUISITE NOT MET: `@objectstack/formula` and
`@objectstack/lint` were unbuilt in the fresh worktree), which measured
nothing. After `turbo run build` for those two packages under the verify
lock, the re-run exited 0.
- Beyond the derived set:
`packages/spec/src/shared/retired-key-migrate-sentence.test.ts` reads
this kit as part of its corpus. 1 file and 14 tests passed.
## Acceptance notes
- Also out of this PR's surface: kit §3's `RETIRED_KEYS_BY_MAJOR` item
still says to add the entry "in
`packages/spec/src/migrations/registry.ts`". Since #7297, an entry is
one file under `packages/spec/src/migrations/entries/retired-keys/`
followed by `gen:migration-registry`, and the region in `registry.ts` is
generated. The kit is echoing the `build-schemas.ts` gate (b) failure
text, which still says to paste the key into `registry.ts` under the
current major. That gate text is the producer, and it is outside this
surface. It is reported to the PM in the dev report, not filed.
## 维护者速读(草稿)
**改了什么**
- 退役手册 §2 与 AGENTS.md 第 3 步统一为一条路线:任何 schema(strict 与否)都用 `retiredKey()`
墓碑。guidance map 只留给 shape 从未声明过的拼写(如退役键的旧别名),那里没有属性可供墓碑替换。
- 手册的 `retiredFromLoadPath` 条目补上必填的 `retiredAfter` 版本戳。
- 第 18 步 D3 链条目改写为 main 上的排序键形状:conversion 只进
`MAJOR_18_CONVERSIONS`,rationale 只加一个排序片段。
- ADR-0087 中「floor ≥ runtime 不重放任何条目」一句已按落地的逐条窗口规则做了日期化修订。
**为什么改**
- 两份受管文本与代码头注、本周三次落地的先例相反,每次退役都要在报告和复核里重新争论路线。
- 第 18 步条目让作者去改一个已经由代码派生、不再手写的列表。
- ADR 那句话在 main 上已经为假:3 个 `retiredAfter` 等于当前版本标签的条目,在 floor 等于 runtime
时仍会被重放。
**风险与代价(含回滚)**
- 纯文档与 agent 规则,不发布任何包,也没有运行时影响。回滚方式是 revert 本 PR 的两个提交。
- 一处措辞偏离:分诊方向举的例子是「z.preprocess
阶段」,实测不成立(那里墓碑照样能放)。两份文本改为点名实测成立的情形,详见正文「For the reviewer」一节。
**席位意见**
**你要做的**
- 审阅 AGENTS.md 与 ADR-0087 两处改动(Tier H),同意则给 APPROVED review。
- 如果希望 strict shape 保留「删键 + guidance
map」路线,或坚持使用原示例的措辞,请在评审里写明,手册这一半会随之修改。
---
_Generated by [Claude
Code](https://claude.ai/code/session_01KTZmMfzVzjNvyaLyQ8mHvg)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent d2b188f commit 4cc5bcd
3 files changed
Lines changed: 44 additions & 26 deletions
File tree
- .claude/skills/spec-property-retirement
- docs/adr
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
83 | 83 | | |
84 | 84 | | |
85 | 85 | | |
86 | | - | |
87 | | - | |
| 86 | + | |
| 87 | + | |
88 | 88 | | |
89 | 89 | | |
90 | 90 | | |
| |||
99 | 99 | | |
100 | 100 | | |
101 | 101 | | |
102 | | - | |
| 102 | + | |
103 | 103 | | |
104 | 104 | | |
105 | 105 | | |
106 | 106 | | |
107 | | - | |
| 107 | + | |
108 | 108 | | |
109 | | - | |
110 | | - | |
111 | | - | |
112 | | - | |
113 | | - | |
| 109 | + | |
| 110 | + | |
114 | 111 | | |
115 | 112 | | |
116 | 113 | | |
| |||
204 | 201 | | |
205 | 202 | | |
206 | 203 | | |
207 | | - | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
208 | 207 | | |
209 | 208 | | |
210 | 209 | | |
211 | 210 | | |
212 | 211 | | |
213 | | - | |
214 | | - | |
215 | | - | |
216 | | - | |
217 | | - | |
218 | | - | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
219 | 219 | | |
220 | 220 | | |
221 | 221 | | |
| |||
239 | 239 | | |
240 | 240 | | |
241 | 241 | | |
242 | | - | |
| 242 | + | |
243 | 243 | | |
244 | 244 | | |
245 | 245 | | |
| |||
254 | 254 | | |
255 | 255 | | |
256 | 256 | | |
257 | | - | |
| 257 | + | |
258 | 258 | | |
259 | 259 | | |
260 | 260 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1077 | 1077 | | |
1078 | 1078 | | |
1079 | 1079 | | |
1080 | | - | |
1081 | | - | |
1082 | | - | |
1083 | | - | |
1084 | | - | |
| 1080 | + | |
| 1081 | + | |
| 1082 | + | |
| 1083 | + | |
| 1084 | + | |
| 1085 | + | |
1085 | 1086 | | |
1086 | 1087 | | |
1087 | 1088 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
| 3 | + | |
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| |||
903 | 903 | | |
904 | 904 | | |
905 | 905 | | |
906 | | - | |
| 906 | + | |
907 | 907 | | |
908 | | - | |
| 908 | + | |
| 909 | + | |
| 910 | + | |
| 911 | + | |
| 912 | + | |
909 | 913 | | |
910 | 914 | | |
911 | 915 | | |
912 | 916 | | |
913 | 917 | | |
| 918 | + | |
| 919 | + | |
| 920 | + | |
| 921 | + | |
| 922 | + | |
| 923 | + | |
| 924 | + | |
| 925 | + | |
| 926 | + | |
| 927 | + | |
| 928 | + | |
| 929 | + | |
| 930 | + | |
914 | 931 | | |
915 | 932 | | |
916 | 933 | | |
| |||
0 commit comments