Repository navigation
Commit 745ac30
docs(skills): retirement kit routes a RETIRED_KEYS_BY_MAJOR entry through entries/retired-keys/ and gen:migration-registry, and an enum-value narrowing through enumWithRetiredValues() (#20828)
Fixes #20803
Clause-②: no
Dispatched by the `domain:skills` seat 1 (seat post #7623) under the PM
claim 5907960440, session `session_01KTZmMfzVzjNvyaLyQ8mHvg`, branch
`claude/issue-20803-retirement-kit-registry-entries`. This is a draft.
The file is on a governed surface (`.claude/**`, Tier S in the
`GOVERNED_SURFACES` register), so the seat lands it after an at-tier
contract review.
## 维护者速读(草稿)
- **改了什么**:退役技能包 `.claude/skills/spec-property-retirement/SKILL.md`
的两段文字。§3 把「退役键登记」改成在 `entries/retired-keys/` 加一个文件、再跑
`gen:migration-registry`;§2 的枚举值退役改指现成的 `enumWithRetiredValues()`,不再教手写
`error` map。文件行数不变(337/337)。
- **为什么改**:登记表 `registry.ts` 早已改为由 `entries/` 逐文件生成,旧文字却让照做的 agent
往生成区手打,`check:migration-registry` 必红、白费一轮;枚举值退役已有通用 helper,旧文字仍在教旧的手写形状。
- **风险与代价(含回滚)**:纯文字改动,零运行时影响,不发布任何包。回滚即 revert 本 PR。它与 #20809(门 (b)
打印的补救文案)须说同一条路线:本 PR 先落,#20809 引用本文。
- **席位意见**:
- **你要做的**:无。本 PR 属 Tier S,由席位达档复核 PASS 后入队落地。
## What changed
One file, `.claude/skills/spec-property-retirement/SKILL.md`, two texts,
net 0 lines (337 before and after; ceiling 337). The landing site is the
one the claim named. The measurement found no other producer of the
wrong text inside `.claude/**`.
**Text 1: §3, the `RETIRED_KEYS_BY_MAJOR` checklist item.** It sent the
entry to be typed into `packages/spec/src/migrations/registry.ts`, and
it said the gate's failure output prints "the line to paste". That table
is now generated: it is concatenated from one file per entry, and the
generator reverts a hand edit between the markers, which
`check:migration-registry` reports first. The item now says what an
author actually does:
- add one file under
`packages/spec/src/migrations/entries/retired-keys/`, named as
`entries/README.md` says. The kit does not restate the naming
convention.
- run `pnpm --filter @objectstack/spec gen:migration-registry`, which
generates the entry into `registry.ts`. Never type the entry there.
Kept unchanged:
- the literal `'DEFKEY:NAME'` value, spelled as
`authorable-surface/CATEGORY.json` spells it (minus `[RETIRED]`), filed
under the current major;
- gate (b) reads it by exact set membership, with no inference;
- the (b2) warning: do not add the entry before the tombstone lands;
- the "why a second table" note and the aging-clock note.
Two lines of the old item are byte-identical in the new one: the
`authorable-surface/…` line and the (b2) tail line.
Deleted: "the gate's failure output prints the line to paste". That
sentence named the paste route this card retires, and what gate (b)
prints is #20809's to change. The new text is true both before and after
#20809 lands, because it names the file route and never quotes the
gate's current wording as the thing to follow.
**Text 3: §2, the enum-value paragraph.** It prescribed a hand-rolled
enum `error` map dispatched on `issue.input`, citing
`HookBodyCapability` (`data/hook-body.zod.ts`) and the
`object.managedBy: 'system'` precedent. It now points at
`enumWithRetiredValues()` in `shared/retired-key.ts`: declare the
retired members and their prescriptions there, with no hand-written
`error` map.
Kept: an enum-value narrowing is invisible to the four ratchets, and
none of the three key routes applies to it.
Deleted: the two hand-rolled citations. Offered as the shape to copy,
they now point at the wrong route. They also have another home: the
helper's own docblock (`retired-key.ts`, "The gap this closes") names
both as the hand-rolled precursors of the helper.
## Measured before writing (`origin/main` at `79114850`)
- **The registry is generated.**
`packages/spec/src/migrations/registry.ts:19-26` says the three tables
are GENERATED from `./entries/`, one file per entry, "never by typing
between the markers. See `./entries/README.md`." There are 237 files
under `entries/retired-keys/`.
- **The README owns the route.** `entries/README.md` "Adding an entry"
gives the file-name rule and the `gen:migration-registry` command. Its
"Four rules" say that the next `gen:` run reverts a hand edit inside the
markers, and that `check:migration-registry` (`tsx
scripts/build-migration-registry.ts --self-test --check`) reports it
before that.
- **The helper has no production caller.** `HookBodyCapability`
(`data/hook-body.zod.ts:48-60`) and `object.managedBy`
(`data/object.zod.ts:1705-1710`) are still hand-rolled `z.enum(values, {
error })` maps. `enumWithRetiredValues()` has 0 non-test call sites.
`git grep` outside `*.test.ts` finds only its definition and docblock in
`retired-key.ts`, and one test file uses it
(`shared/retired-key.test.ts`).
- **The helper covers every retirement the hand-rolled map covers.**
Both hand-rolled sites answer one exact retired string with a
prescription and leave every other value to zod, which is exactly the
helper's `retired` map. The helper's docblock names one case it does not
cover: a retired member that WAS the default. A hand-rolled map cannot
cover that case either, because the default must be a live member. The
docblock routes that case to `acceptRetiredDefaultResidue`. So the kit
says "don't hand-roll" with no exception, and stays true.
- **No other sentence sends an entry into `registry.ts`.** The census
covered `.claude/**`, `AGENTS.md` and `CLAUDE.md`, grepping for
`migrations/registry`, `registry.ts`, `RETIRED_KEYS_BY_MAJOR`,
`RETIRED_DEFS_BY_MAJOR`, `copy these lines` and `粘贴`, plus paste/append
near registry. It found two `registry.ts` hits, both in the kit:
- the text-1 line, fixed here;
- the step-18 D3-chain item. That item is true and stays untouched: a
`MIGRATIONS_BY_MAJOR` step's `rationale` and `conversionIds` are
hand-written outside the generated markers (`registry.ts:37-42`;
`STEP18_RATIONALE` at `:5024`).
The kit's D3 `semantic` item already routes through `entries/`, and
nothing outside the kit matched.
## One route, said once in each place (with #20809)
At this head, #20809 has no branch or PR, so this lands first. Under the
triage split the second to land quotes the first, so gate (b)'s printed
remedy should name the same directory and command:
- directory: `packages/spec/src/migrations/entries/retired-keys/`, with
the file name per `entries/README.md`;
- command: `pnpm --filter @objectstack/spec gen:migration-registry`.
#20809 remains open. This PR touches nothing under `packages/spec/**`.
## Line budget
- **Lines:** 337 / 337 (ceiling 337, headroom 0). Text 1 went from 6
lines to 7, and text 3 from 4 lines to 3.
- **Line width:** the widest new line is 116 bytes, and every new
non-table line is 120 bytes or less.
- **Table rows:** none touched. The widest is 324 bytes against the 326
pin.
- **No re-wrap of untouched lines.** Every deleted clause is false or
has another home (see above).
## Changeset
None: the diff publishes nothing. `.claude/**` ships in no package's
`files[]`:
- 69 non-private `package.json` manifests, 0 of whose `files[]` names
`.claude`;
- the root package is `private`;
- no `.claude/` directory sits inside any package directory (`git
ls-files` shows 50 tracked files under the root `.claude/` only);
- positive control: `@objectstack/spec`'s `files[]` reads `dist`,
`json-schema`, `liveness`, `prompts`, `llms.txt`, `README.md`,
`src/**/*.zod.ts`, `CHANGELOG.md`, `api-surface`, `spec-changes.json`.
The seat applies `skip-changeset`; this PR writes no label.
## Gates (at head `21db5689`)
`node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` (no paths) derived 18 commands, the same set
as the dispatch. I ran all 18 plus three extras,
`check:pm-settings-deny-roster`, `check:pm-skill-id-lint` and
`check:pm-governed-prose`. Every one exited 0. `dispatch-gates --ran`
with the recorded exit codes reported "18 derived famil(ies) accounted
for — 18 run, 0 NOT-MEASURED (a DERIVED zero)".
- `check:pm-skill-ratchet` exit 0: "spec-property-retirement/SKILL.md is
337 lines (ceiling 337; headroom 0)"; "widest table row is 324 bytes
(pin 326; headroom 2)".
- `check:skill-frame-sync` exit 0; `check:doc-authoring` exit 0;
`check:nul-bytes` exit 0 ("no raw ASCII control bytes");
`check:pm-skill-id-lint` exit 0 ("34 file(s) clean").
- `check:pm-governed-merges` exit 0 · `check:pm-governed-prose` exit 0 ·
`check:pm-settings-deny-roster` exit 0.
- `pnpm --filter @objectstack/lint run check:doc-formula-expressions`
exit 0, after a `turbo run build --filter='@objectstack/lint...'` (4
tasks, exit 0) under `os-verify-lock.sh`.
- `check-ci-filter-parity` · `check-closing-keyword-parity` (+
`--self-test`) · `check-comment-mask-corpus` · `check-harness-current
--self-test` · `check:agent-test-spelling` ·
`check:cross-package-test-inputs` · `check:driver-memory-census` ·
`check:gitlink-declared` · `check:refd-timer-probe` ·
`check:required-contexts` · `check:watch-hint-literal`: each exit 0.
## Acceptance notes
- **A sibling of gate (b), same family as #20809.**
`packages/spec/scripts/build-schemas.ts:2636-2640` is the def-removal
gate. It prints the same "copy these lines in … under `18: [ … ]`"
remedy for `RETIRED_DEFS_BY_MAJOR`, whose table is generated from
`entries/retired-defs/`. #20809 lists only gate (b) (`:1127-1128`), so
its author may want to take this sibling in the same edit. Not filed
separately.
- **Zero production callers for the helper.** `enumWithRetiredValues()`
still has no production call site, and its docblock `@example` shows
`HookBodyCapability` built with it, which `main` does not do. Both
hand-rolled precursors work as they are; this is an observation, not a
defect. Carrier: none.
- **Table-row pin headroom.** The kit's table-row pin has headroom 2
(widest 324 against pin 326), and the ratchet prints a hint to lower it.
That headroom predates this PR, and this PR touches no table row, so the
pin is left as it is. Carrier: none.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01KTZmMfzVzjNvyaLyQ8mHvg)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent addbbf0 commit 745ac30
1 file changed
Lines changed: 8 additions & 8 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
138 | 138 | | |
139 | 139 | | |
140 | 140 | | |
141 | | - | |
142 | | - | |
143 | | - | |
144 | | - | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
145 | 144 | | |
146 | 145 | | |
147 | 146 | | |
| |||
180 | 179 | | |
181 | 180 | | |
182 | 181 | | |
183 | | - | |
184 | | - | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
185 | 185 | | |
186 | | - | |
187 | | - | |
| 186 | + | |
| 187 | + | |
188 | 188 | | |
189 | 189 | | |
190 | 190 | | |
| |||
0 commit comments