Skip to content

docs(skills): spec-property-retirement's retiredAfter item names the stamp under a prerelease label — the newest published stable release (#23057) - #23162

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-23057-retired-after-prerelease-playbook
Oct 13, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-23057-retired-after-prerelease-playbook

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #23057
Clause-②: no

The spec-property-retirement playbook's retiredFromLoadPath / retiredAfter checklist item told the author of a new retirement to stamp "packages/spec/package.json 的当前版本标签" (the package's current version label). Under a Changesets prerelease label (18.0.0-next.N) that value fails tsc's ${number}.${number}.${number} template type and the census's triple(). This PR brings that one sentence into line with the rule the spec half already landed: the retiredAfter TSDoc in packages/spec/src/conversions/types.ts (719183f50, PR #23130). It adds no rule of its own and names that TSDoc as the authority.

Tier S (.claude/**): this PR stays draft. It lands only by the owning seat on a contract-tier review of record. The authoring seat does not flip it to ready, queue it, or arm auto-merge.

The change

One file, .claude/skills/spec-property-retirement/SKILL.md. Lines 205 and 206 are rewritten in place. Line 204 and lines 207 to 337 are byte-identical.

Before (base 02bec6ca8):

- [ ] **`retiredFromLoadPath: true` 与 `retiredAfter: 'x.y.z'`** —— 后者必填(缺则 `tsc` 拒),新退役填
      `packages/spec/package.json` 的当前版本标签(`retired-after.census.test.ts` 逐值钉;artifact 门据它
      逐条开窗)。前者退役恒真,但管辖权只有 authoring 漏斗

After (9b14911b4c):

- [ ] **`retiredFromLoadPath: true` 与 `retiredAfter: 'x.y.z'`** —— 后者必填(缺则 `tsc` 拒),新退役填
      落地时最新 stable 发布(标签为 `x.y.z-next.N` 时永不填它或 `x.y.z`;`retired-after.census.test.ts`
      逐值钉;artifact 门据它逐条开窗;TSDoc 为准)。前者退役恒真,但管辖权只有 authoring 漏斗

Acceptance notes

The landed TSDoc text and the new sentence, side by side. The TSDoc is quoted verbatim from packages/spec/src/conversions/types.ts at 02bec6ca8:

Landed retiredAfter TSDoc (719183f50) Playbook sentence after this PR
"It is a FACT when the entry is written, never a guess at the next release number: the newest stable release at the moment the retirement lands, read off the package's version label." 新退役填落地时最新 stable 发布 (a new retirement stamps the newest stable release at the moment it lands)
"Under a prerelease label (x.y.z-PRERELEASE, Changesets pre mode), it is the newest published stable release, which sits below x.y.z — never the label (not a stable x.y.z) and never x.y.z, the first stable release that carries the entry retired (17.7.0 under 18.0.0-next.N, say)." 标签为 x.y.z-next.N 时永不填它或 x.y.z (when the label is x.y.z-next.N, never that label and never x.y.z)
The whole TSDoc block TSDoc 为准 (the TSDoc is the authority)
  • What the sentence leaves to the TSDoc pointer, and why. The stable-label arm ("Under a stable label (x.y.z), it is the label itself") gets no clause of its own. Under a stable label, the newest stable release at landing is the label, so the general rule already gives that value. The TSDoc's paragraph on already-published entries (the census-refresh re-stamp) is not restated either. The item is about new retirements, and the old sentence never carried that paragraph. The TSDoc 为准 pointer covers both.
  • Line budget (check-skill-line-ratchet). 337 lines before and after (ceiling 337, headroom 0). The widest table row is 324 bytes before and after (pin 326). The rewritten lines are 118 and 117 bytes; before, they were 119 and 73. The new text fits on the sentence's own two lines, using the slack on line 206, which carried the tail of the same sentence's parenthetical. No line of other content was joined, moved or re-wrapped to make room. The pointer is the unqualified TSDoc 为准 rather than a longer form such as 以其 TSDoc 为准 because the longer form makes line 206 121 bytes.
  • Premise check on origin/main 02bec6ca8. packages/spec/package.json reads 17.7.0 (a stable label). .changeset/pre.json is mode: pre, tag: next, so the next Version Packages pass writes 18.0.0-next.N, and the old sentence would then hand an author a value that tsc and the census refuse. 719183f50 is an ancestor of origin/main (git merge-base --is-ancestor exit 0).
  • Observation, not filed, no carrier: the gate's info line says this file's max-table-row-bytes pin has 2 bytes of headroom (widest row 324, pin 326) and suggests lowering it. That is true on the base too and is unrelated to this diff. Lowering it means editing scripts/pm/check-skill-line-ratchet.mjs, which is outside this card's file surface.

Gates

The gate list comes from node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack with no paths (change set read from git against merge base 02bec6ca8). It names 18 commands, the same 18 as the dispatch. Each command ran alone in the foreground at HEAD 9b14911b4c, and its exit code was read before any pipe.

Command Exit Verdict line (abridged)
node scripts/check-ci-filter-parity.mjs 0 OK: all 9 console entr(ies) are literal paths …
node scripts/check-closing-keyword-parity.mjs 0 check-closing-keyword-parity: OK (3 parsers agree on all 9 keywords …)
node scripts/check-closing-keyword-parity.mjs --self-test 0 40 assertions, 5 mutations of the shipped parsers each driven to red
node scripts/check-comment-mask-corpus.mjs 0 8935 files, 0 disagree, 0 unparseable
node scripts/pm/check-harness-current.mjs --self-test 0 all 26 cases passed
pnpm --filter @objectstack/lint run check:doc-formula-expressions 0 9 @example(s) judged clean …; 15 predicate(s) … judged clean
pnpm check:agent-test-spelling 0 0 violations
pnpm check:cross-package-test-inputs 0 OK: 30 package(s) read outside themselves, all declared …
pnpm check:doc-authoring 0 18459 customer-facing string(s) … clean
pnpm check:driver-memory-census 0 OK — every declaration is ledgered …
pnpm check:gitlink-declared 0 OK (11183 index entries -- 0 gitlink(s) …)
pnpm check:nul-bytes 0 OK (scanned 11174 text file(s) …; no raw ASCII control bytes)
pnpm check:pm-governed-merges 0 --self-test: 500 assertions; live: the real generator … certified this tree
pnpm check:pm-skill-ratchet 0 spec-property-retirement/SKILL.md is 337 lines (ceiling 337; headroom 0); widest table row 324 bytes (pin 326)
pnpm check:refd-timer-probe 0 OK — 8929 source file(s) swept
pnpm check:required-contexts 0 5 required context name(s) pinned across 3 workflow(s)
pnpm check:skill-frame-sync 0 the one declared copy of the decision frame is internally coherent
pnpm check:watch-hint-literal 0 73 declaration(s) across 4 rostered name(s) …
  • The first run of check:doc-formula-expressions exited 3 (PREREQUISITE NOT MET: @objectstack/formula and @objectstack/lint not built), so nothing was measured. I built both under the shared verify lock (pnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lint --concurrency=2, VERDICT command-exit 0) and re-ran the gate: exit 0, the row above.
  • Reconciliation: node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran ran.list gives "18 derived famil(ies) accounted for — 18 run, 0 NOT-MEASURED".
  • The direct judge named in the dispatch, node scripts/pm/check-skill-line-ratchet.mjs, exits 0. Its 120-byte line rule prints only on failure, and nothing printed for this file.
  • No changeset: the diff touches only .claude/**, which publishes nothing. The PR carries skip-changeset.

维护者速读(草稿)

  • 改了什么: spec-property-retirement 技能里 retiredAfter 那一条清单项。原文让新退役填 packages/spec/package.json 的当前版本标签;现改为填「落地时最新的 stable 发布」,并写明预发布标签(x.y.z-next.N)下永不填标签本身或 x.y.z,以 retiredAfter 的 TSDoc 为准。只改两行,文件行数不变(337)。
  • 为什么改: 仓库已处于 Changesets 预发布模式(.changeset/pre.json,tag next),下一次 Version Packages 会把版本标签写成 18.0.0-next.N;照旧句填写,tsc 与 census 都会拒。规则本身已由 spec 侧(PR test(spec): under a prerelease package label the retired-after census refuses the release triple, and the retiredAfter TSDoc names the newest published stable release #23130)写进 TSDoc,本 PR 只让技能文本跟上,不另立规则。
  • 风险与代价(含回滚): 纯内部 agent 文档,不发布任何包,不触运行时。回滚即 revert 这一个 commit。
  • 席位意见:
  • 你要做的: 无。Tier S(.claude/**),由 domain:skills 席位凭达档复核记录落地;对措辞有异议请在本 PR 留言。

Generated by Claude Code

…newest stable release at landing, never a prerelease label

The checklist item told a new retirement to stamp packages/spec/package.json's
current version label. Under a prerelease label (x.y.z-next.N) that value fails
tsc's x.y.z template type and the census. The item now restates the landed
retiredAfter TSDoc in packages/spec/src/conversions/types.ts: the newest stable
release at the moment the retirement lands, never the prerelease label and
never its x.y.z, with that TSDoc named as the authority. Rewritten on the
item's own lines; line count unchanged (337).

Claude-Session: https://claude.ai/code/session_012dGTuJen61ECNHXYXKChoC
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 9b14911b4c0c2613b94934606b0d7ac59a2e2616
Local-runs: none

Inputs read: card #23057 (body; comments 6126795562 triage, 6138010848 unlock, 6138255257 claim, 6138492837 dev report), PR #23162 (body, file list, git diff origin/main...9b14911b4c after git fetch; merge base 02bec6ca8 is origin/main at this reading, so the three-dot diff and the net diff against main are the same hunk), the check-runs on the head, and — for the factual claims — packages/spec/src/conversions/types.ts, packages/spec/src/conversions/retired-after.census.test.ts, .changeset/pre.json, packages/spec/package.json and scripts/pm/check-skill-line-ratchet.mjs on origin/main. Nothing was built, run or re-run.

① Derived judgments

  • Diff shape — right. One file, .claude/skills/spec-property-retirement/SKILL.md, +2/−2: lines 205–206 of the retiredFromLoadPath / retiredAfter checklist item rewritten in place. With those two lines removed from both sides the base and head files are byte-identical, so nothing else in the file moved, joined or re-wrapped. No accept-set changes (no schema, no runtime, no generated baseline) and no public surface: the file is seat-read tooling that ships in no package.
  • The sentence against the landed retiredAfter TSDoc (719183f50, an ancestor of origin/main; read verbatim on origin/main) — right, no rule of its own.
    • General clause: TSDoc "the newest stable release at the moment the retirement lands, read off the package's version label" ↔ playbook "新退役填落地时最新 stable 发布". Same value, same moment.
    • Prerelease arm: TSDoc "never the label (not a stable x.y.z) and never x.y.z, the first stable release that carries the entry retired (17.7.0 under 18.0.0-next.N, say)" ↔ playbook "标签为 x.y.z-next.N 时永不填它或 x.y.z". The two forbidden values are the TSDoc's two; the value TO stamp (the newest published stable release) comes from the general clause, exactly as it does in the TSDoc's first paragraph.
    • Stable arm: TSDoc "it is the label itself" is not restated. Under a stable label the general clause already yields the label (main carries the last release's label until the next release is cut), and the census's unpublishedStampProblem takes exactly the label once that release is censused (between a bump and a census refresh it admits the closed range from the last censused release up to the label) — so the omission adds no rule and loses no value. The old sentence's "packages/spec/package.json 的当前版本标签" pointer is gone: that pointer is exactly the wrong instruction under a prerelease label, which is the defect this card exists for; TSDoc 为准 now names where the full text lives.
    • "TSDoc 为准" is a pointer to the authority, not a rule. Every other clause traces to a TSDoc sentence. The triage direction (restate the landed text, no new words) and the unlock direction (no restated rule of its own) hold.
    • One narrowing of spelling, judged acceptable and flagged under ③: the playbook writes the arm's trigger as x.y.z-next.N (the TSDoc's own example and the current .changeset/pre.json tag) where the TSDoc writes x.y.z-PRERELEASE.
  • An AI author following the playbook stamps a value tsc and the census accept — right. Today packages/spec/package.json reads 17.7.0 (stable) and .changeset/pre.json is mode: pre, tag: next. Once the Version Packages pass writes 18.0.0-next.N, the author reads "newest stable release at landing, never the label, never 18.0.0" and stamps 17.7.0 (or a later 17.x maintenance release if one is published first): it matches tsc's ${number}.${number}.${number} template, and the census's prerelease branch accepts any v in [last censused release, 18.0.0). Under the stable label as it stands today the author stamps 17.7.0, which equals the label, and the census's stable branch accepts exactly that. The old sentence would have handed the author 18.0.0-next.N, which both refuse.
  • The parenthetical still carries both pointers — right. "retired-after.census.test.ts 逐值钉" (the census pin) and "artifact 门据它逐条开窗" (the artifact-door pointer) are carried verbatim from the old sentence, in the same parenthetical.
  • Line ratchet — right. 337 lines before and after against the CEILINGS row ['.claude/skills/spec-property-retirement/SKILL.md', 337]. Rewritten lines measure 118 and 117 bytes (base 116 and 76 by my byte count; the PR body says 119 and 73 — same 192-byte total, immaterial), both within the 120-byte budget. Widest table row unchanged at 324 bytes (line 86; pin 326). Zero raw control bytes in the head file. CI's Lint · repo & tooling gates (the job that runs pnpm check:pm-skill-ratchet, lint.yml:1016) is green on this head.
  • Commit and PR body — right. The head commit carries the session-URL trailer and a model-free Co-authored-by trailer; its claim "line count unchanged (337)" is true. The PR body's two TSDoc quotations match the landed text word for word, its "Before" block matches the base lines, and Fixes #23057 plus Clause-②: no are present. The head repo is objectstack-ai/objectstack (not a fork).

② Semver level

  • skip-changeset — right. The diff publishes nothing: .claude/** is repo-root seat tooling, no packages/*/package.json references it, and the published skill catalog (skills/**) is untouched. Check Changeset is green with the label.
  • Clause-②: no — right. No ADR-0087 conversion entry, no authorable surface, no changeset body; no with no arm is the correct declaration and the PR body carries it.

③ Boundary flags

  • Dev deviations (4), each answered. (1) Two pushes, the empty-branch write probe then the commit: as os-dev rule 1 asks; fine. (2) check:doc-formula-expressions first exited 3 (prerequisite build missing) and was re-run after building @objectstack/formula and @objectstack/lint locally: a local-environment matter only; CI's own Lint · docs & code guards is the verdict of record here. (3) The pointer is the unqualified TSDoc 为准 because 以其 TSDoc 为准 overran 120 bytes: accepted — the bolded retiredAfter key at the head of the same item fixes the referent. (My count makes the longer form 124 bytes, not 121; either way over budget.) (4) Attribution trailers follow AGENTS.md's model-free form: fine.
  • open_questions: none. Nothing to answer or escalate.
  • out_of_scope_findings (1) — correctly out. The ratchet's info line reporting 2 bytes of max-table-row-bytes headroom (widest 324, pin 326) is a condition of the base 02bec6ca8, not of this diff; lowering the pin edits scripts/pm/check-skill-line-ratchet.mjs, outside this card's declared file surface; the ratchet is shrink-only and the line is advisory. Carried as 承接者:无 in the PR's Acceptance notes, which is the shape os-dev.md asks for when no carrier exists.
  • For the maintainer, no action owed before landing:
    • The prerelease arm is spelled x.y.z-next.N, narrower than the TSDoc's x.y.z-PRERELEASE. It is right for the current next tag and the stamped value is the same under any tag (the general clause gives it, and the census's releaseTriple drops any suffix), but should the pre tag ever change (this file itself cites 17.0.0-rc.0 at line 198) the explicit arm would not name that label — the general clause and the TSDoc pointer still would.
    • The PR body's 维护者速读(草稿) has an empty 席位意见: bullet; the owning seat fills or drops it when it lands the PR.
    • Check-runs on the head, read at 2026-10-13T05:00Z after the last in-progress run (Test Core (1/6)) completed: 43 runs, all completed — 32 success, 11 skipped (path-filtered battery: Build Core, Build Docs, Console Pin Gate, Dogfood matrix, Temporal Conformance, Dogfood Verify CLI, Packed-tarball smoke, and the second Check Changeset / Auto Label / Check PR Size instances), 0 failure, 0 in progress. Governed Surface Queue Guard, Check Changeset, Lint · repo & tooling gates, Lint · PM dispatch-gates, all six Test Core shards and every type-check job are green.

Implemented-by: claude/issue-23057-retired-after-prerelease-playbook
Reviewed-by: session_012dGTuJen61ECNHXYXKChoC

VERDICT: PASS


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/xs skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants