Skip to content

fix(spec): retirement prescriptions state what os migrate meta actually does - #9732

Merged
os-elon merged 1 commit into
mainfrom
claude/issue-9529-retirement-sentence-reword
Aug 18, 2026
Merged

fix(spec): retirement prescriptions state what os migrate meta actually does#9732
os-elon merged 1 commit into
mainfrom
claude/issue-9529-retirement-sentence-reword

Conversation

@os-elon

@os-elon os-elon commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

Fixes #9529

Implements the maintainer's Option-2 ruling of 2026-08-18 (comment 5328152596, verbatim: 「其他接受你的建议」). Option 1 — the in-place AST codemod — is commissioned separately as #9591 for v18 and is not addressed here; nothing in this PR touches that card's scope or packages/cli.

The claim that was withdrawn

Every retiredKey() prescription whose surface an ADR-0087 conversion covers closed with a maintainer-ruled sentence (2026-08-09, #6856):

Run `os migrate meta --from N` to rewrite existing sources automatically.

os migrate meta has never written an authored source file. It replays the conversion chain over the loaded stack in memory, prints the attributed mechanical change list (Applied N mechanical change(s), one line per site as path: from → to (conversionId)), and writes exactly one file — the --out JSON snapshot, when you ask for it. Both write sites in packages/cli/src/commands/migrate/meta.ts are that snapshot, and there is no --write / --fix / in-place flag. So an author who followed the prescription got a replay, a printed diff and optionally a JSON document in a shape their per-artifact .ts modules are not written in — then still hand-edited every file, with nothing in the message saying so.

The new sentence

Run `os migrate meta --from N` to list the mechanical edits for existing sources; apply them by hand.

Partial-value conversions keep their two-clause MIXED shape, reworded the same way — e.g. ui/dashboard.zod.ts: "… to list the mechanical edits for the 1y case; the other durations are reported for you to re-state."

The wording keeps everything #6856 ruled and adds what #9529 ruled:

  • One antecedent. "existing sources" names one thing; the retired "rewrite it" spelling named either the key or your sources.
  • A property of the TOOL, never the fate of the key — the key's fate stays in the body prose ("Delete the key…", "Rename the key to…"), which every prescription already carries.
  • True of the tool. "list … edits" is what running it gets you; "apply them by hand" is the half the old sentence denied. This mirrors the fact skills/objectstack-upgrade/SKILL.md already told operators under "The one fact that surprises every operator" — the messages now agree with the skill instead of contradicting it.

What moved

  • The sentence sourcepackages/spec/src/shared/retired-key.ts: the house-sentence rule in the module docblock, with both rulings recorded and a pointer to feat(cli): os migrate meta --write — the AST codemod that rewrites authored sources for the mechanical applied set (v18) #9591's restoration path.
  • The class-wide pinpackages/spec/src/shared/retired-key-migrate-sentence.test.ts, in lockstep, and strengthened in both directions. The shape check now requires the new sentence; a new findWithdrawnClaims() scan makes the withdrawn claim a hard failure wherever it appears in prescription text — including in a prescription that spells the bare command with no --from N (three enum-value prescriptions in ui/component.zod.ts do), which the marker-anchored shape check alone would never have judged. Both directions have anti-vacuity fixtures.
  • Every shipped site, not only the canonical sentence: the MIXED two-clause sites, and the variant phrasings the domain:cli seat's measurement warned would otherwise be left standing ("rewrites author sources", "rewrites authored sources", "rewrites it for you", "only os migrate meta rewrites sources", "rewrites the consumer's source") in tombstone docblocks, the conversion registry and the migration ledger.
  • The hand-written upgrade docscontent/docs/upgrading.mdx (which claimed "it rewrites your source" in four places, and now carries the same "does not rewrite your source files" callout as the skill), plus content/docs/ui/apps.mdx, content/docs/data-modeling/fields.mdx, content/docs/automation/flows.mdx, content/docs/protocol/objectui/actions.mdx.
  • Generated artifacts regenerated, never hand-edited: content/docs/references/** and docs/protocol-upgrade-guide.md, via check:generated --fix (which proved exactly those two stale).

Behaviour is unchanged in both packages — message text only, no accept/reject verdict moves, packages/cli untouched.

Measured, on this branch's head 6e8b529

population (shipped, non-test .ts in packages/spec/src + packages/lint/src) before (2b292ce) after
canonical sentence, seam-aware (split literals counted) 95 occ / 27 files 0
new house sentence 0 95 occ / 27 files
MIXED two-clause, withdrawn spelling 3 0

Across all shipped surfaces (every tracked file except CHANGELOG.md, .changeset/, docs/adr/, docs/qa/), occurrences of the withdrawn claim in any phrasing: 215 in 61 files → 15 in 5 files, and each of the 15 survivors is deliberate — 11 are the pin's own RED fixtures, and the rest are the negation of the claim (content/docs/upgrading.mdx, skills/objectstack-upgrade/SKILL.md), a not.toMatch guard in packages/lint/src/validate-expressions.test.ts, and the docblock in retired-key.ts quoting the withdrawn wording as history.

Verification

  • Reverse verification, from the committed state: planted the withdrawn sentence back into one real site (packages/spec/src/data/field.zod.ts:1216) → the pin went RED on 3 of 9 tests, naming spec:data/field.zod.ts:1216; restored with git checkout HEAD -- and back to 9/9 green. No rebuild was involved or needed — the pin is a source scan that reads the files from disk and imports nothing from dist/.
  • pnpm --filter @objectstack/spec test413 files / 10974 tests passed; pnpm --filter @objectstack/lint test74 files / 2088 tests passed.
  • pnpm --filter @objectstack/spec check:generated — all 13 generated artifacts up to date; typecheck green for both packages.
  • The gate set re-derived from the real diff with node scripts/pm/dispatch-gates.mjs (30 gates, wider than the dispatch list) — all green, including check:type-check-debt --re-measure, check:engine-double-contract, check:where-matcher, check:query-options-erasure, check:cross-package-test-inputs, check:merge-driver, check:docs-audit-scope and node scripts/check-nul-bytes.mjs.

Deliberately not edited

.changeset/migrate-meta-reads-retired-key-sources.md (#9418's pending release note) quotes the withdrawn sentence, and its count, as the state that motivated that change. It is another card's release prose describing a past state, so it is left alone and filed as a finding instead.


Generated by Claude Code

…ally does (#9529)

The house sentence promised "rewrite existing sources automatically". The
command has never written an authored source file: it replays the conversion
chain in memory, prints the attributed mechanical change list, and writes only
the `--out` JSON snapshot. Withdraw the claim class-wide, per the maintainer
ruling of 2026-08-18, in favour of:

    Run `os migrate meta --from N` to list the mechanical edits for existing
    sources; apply them by hand.

Swept across every shipped site — the canonical sentence, the MIXED two-clause
shape for partial-value conversions, the variant phrasings in tombstone and
conversion-registry prose, and the hand-written upgrade docs. The class-wide pin
moves in lockstep and now holds both directions: the new sentence required, the
withdrawn claim red wherever it reappears.

Behaviour unchanged; `packages/cli` untouched. The in-place codemod that would
make the original claim true is #9591 (v18).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016D9wdJR14KKCxz1WgdAzcw
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/lint, @objectstack/spec, touching 52 documentable anchor(s).

29 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: node scripts/docs-audit/affected-docs.mjs --json e196c6a9baa8684c14e5e72545c8009f98a9ed14.

6 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails.

What this run could not see
  • 2 changed file(s) yielded no anchor (packages/spec/src/conversions/registry.ts, packages/spec/src/shared/retired-key.ts) — pages documenting those are invisible to this run
  • 9 name(s) were too generic to anchor anything (single lowercase words)

Coarse fallback — 115 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json e196c6a9baa8684c14e5e72545c8009f98a9ed14packageMentionDocs.

Which tree this was computed on

This run read content/docs from dbb89f5a30a082a9bd9b4a36e05f7afcbb1c2b56 — the merge of head 6e8b5299879c056a866dc9ef7746693d05789f7c into base e196c6a9baa8684c14e5e72545c8009f98a9ed14, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin dbb89f5a30a082a9bd9b4a36e05f7afcbb1c2b56 && git checkout dbb89f5a30a082a9bd9b4a36e05f7afcbb1c2b56
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin e196c6a9baa8684c14e5e72545c8009f98a9ed14 6e8b5299879c056a866dc9ef7746693d05789f7c && git checkout -B drift-repro e196c6a9baa8684c14e5e72545c8009f98a9ed14 && git merge --no-ff 6e8b5299879c056a866dc9ef7746693d05789f7c

node scripts/docs-audit/affected-docs.mjs --json e196c6a9baa8684c14e5e72545c8009f98a9ed14

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs e196c6a9baa8684c14e5e72545c8009f98a9ed14 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

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/l tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

os migrate meta never rewrites the authored sources that 144 shipped retirement messages promise it will

2 participants