Skip to content

docs(skills): objectstack-upgrade names os migrate meta --write beside the default run - #22122

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-22120-upgrade-skill-migrate-meta-write
Oct 8, 2026
Merged

os-zhuang merged 1 commit into
mainfrom
claude/issue-22120-upgrade-skill-migrate-meta-write

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #22120

Clause-②: no

The published upgrade skill said that os migrate meta "writes nothing but --out" (Quickstart comment, failure-mode row) and that it "does not rewrite your source files" (§1). Since os migrate meta --write landed (a959493cdf), that is true only of the default run. This PR makes every sentence in skills/objectstack-upgrade/SKILL.md that states what the command writes true of both routes, within the skill's token ceiling.

What changed (one file: skills/objectstack-upgrade/SKILL.md)

  • Quickstart step 1 comment: "(writes only --out; --write also rewrites the sites it can prove)".
  • Flag table in §1: one new example line, os migrate meta --from 16 --write # rewrite the proven sites in place.
  • §1 "The one fact that surprises every operator": now opens "By default os migrate meta rewrites no source file. It lists the mechanical edits and writes only the --out JSON snapshot." followed by one sentence for --write: it rewrites in place each edit it can trace to one literal in one project file, lists every other with the reason it was not written, never writes a semantic change, and if re-running the chain over the written files disagrees, restores every file and exits 1. The porting sentence now reads "Porting the edits left unwritten is yours" — true on both routes.
  • Failure-mode row "migrate meta reports changes, but the files are unchanged": cause "Working as designed — the default run only lists."; fix "Pass --write, or port the printed edits by hand; then replay from the target major to confirm 0 changes."
  • Failure-mode row "--apply refused / stored-only flag rejected": the tail "the authored-source chain has nothing to write to" (false under --write) now mirrors the CLI's own refusal text: "writes only --out and, with --write, the sources".

Every claim is read from packages/cli/src/commands/migrate/meta.ts at db4c45b8c3 (flag description and exclusive: ['stored']; WriteOutcome.status = written | restored | unwritten; printWriteOutcome lists each unwritten site as "not written [kind]: reason"; this.exit(1) whenever write.status !== 'written') and from the packages/cli/src/utils/authored-source-codemod.ts module docblock (one object or array literal in one project file, statically matching the loaded value, no second reference to any binding the walk crossed; semantic TODOs never read). The default run and --write are both described; the text does not say what --out does on a run with nothing to migrate and does not describe the semantic-notice list (both are in flight on meta.ts in #22121 and #22115).

Token ratchet — paid in content, not wrapping

node scripts/check-skills-token-ratchet.mjs (tokens = ceil(utf8 bytes / 4); ceiling for this file 6193):

reading lines bytes tokens headroom
before (db4c45b8c3) 488 24772 6193 0
after (9bb10014) 484 24748 6187 6

Diff: +13 / −17 lines. Gate line at 9bb10014: ✓ check-skills-token-ratchet: skills/objectstack-upgrade/SKILL.md is 6187 tokens (ceiling 6193; headroom 6).

The growth (+179 bytes gross) was paid by deleting three pieces of duplicated content, no rule, failure-mode row or needed command among them:

  1. the --out recheck code block in §1 — its first line was byte-identical to Quickstart step 1 (os migrate meta --from 16 --out .upgrade/migrated.stack.json), and the "replay from the target major, 0 changes" recheck is already carried by Quickstart step 3, the §3.3 callout and the failure-mode row;
  2. the clause "It rewrites the loaded stack in memory and reports the diff" — the mechanism paragraph three lines above already states load → normalize without the load-time pass → replay per hop → parse;
  3. the sentence "The authored-source flags and the stored-only flags are mutually exclusive, and mixing them is refused rather than ignored" in the --stored subsection — the failure-mode row "--apply refused / stored-only flag rejected" carries the same fact with its fix, and the preceding "--stored takes no --from" keeps the other direction.

Scope held

Gates

Derived with node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack from the changeset at 9bb10014 (24 families; identical to the path-derived list). All 24 run, exit codes recorded beside the printed command and reconciled with --ran (see the report comment on #22120 for the table). check:doc-formula-expressions first exited 3 (prerequisite: @objectstack/lint not built) and was re-run after the prescribed build.

Acceptance notes

  • Out of scope, reported for a card: SKILL.md:103 says "os migrate meta --from 10 replays every step in order", but MIGRATION_SUPPORT_FLOOR = 16 (packages/spec/src/migrations/registry.ts:79), so that command refuses with MigrationFloorError / unsupported_from_major — the skill's own failure-mode row says so. Not fixed here: the sentence's point ("several majors late is the designed-for case") cannot be re-exampled truthfully on a 16 → 17 chain, so the fix is a rewording, not a mechanical edit.
  • Observation, not changed: evals/protocol-major-upgrade.json eval 1 expected_output says "the command rewrites nothing on disk" — true of the default route it describes; a --write-aware eval is a product decision, not a drift fix.

维护者速读(草稿)

改了什么:只改一份对外发布的技能文件 skills/objectstack-upgrade/SKILL.md。原文在三处断言 os migrate meta "只写 --out、不改源文件";自 --write 落地后这只对默认运行成立。现在每一句关于"命令写什么"的话都同时对默认运行和 --write 成立:默认只列出机械修改、只写 --out 快照;--write 只就地改写它能证明来源的站点(一个项目文件里的一个字面量),其余逐条列出未写原因,语义修改永不写,复跑不一致时恢复全部文件并以 1 退出。

为什么改:客户项目的 AI agent 整包加载这份技能;它读到"命令只写 --out"就永远不会发现 --write,而读到无条件的"自动改写"又会被误导。文字必须与 CLI 源码一致(meta.ts 的 flag 描述、written | restored | unwritten 三态、exit 1),并与 spec 侧退休句的措辞("列出机械修改")保持一致。

风险与代价(含回滚):纯文本改动,无代码、无 changeset、无生成物。token 棘轮:6193 → 6187(上限 6193),净减 24 字节,靠删除三处重复内容支付,未删任何规则、故障行或命令。回滚即 revert 本 PR 的一个提交。注意 #22121(--out 在无变更运行时的行为)与 #22115(语义通知列表)在 meta.ts 上并行,本文未对那两点做任何断言。

席位意见:(留空,席位定稿)

你要做的:skills/** 为 Tier H 受管面:请以授权账号 APPROVE 一次,或亲手合入;本 PR 保持 draft,不由 agent 翻 ready。


Generated by Claude Code

…ide the default run

The published upgrade skill said the command "writes nothing but --out" at
the Quickstart comment and the failure-mode row, and that it "does not
rewrite your source files". Since `--write` landed, that is true only of
the default run. Every sentence stating what the command writes now holds
for both routes: the default run lists the mechanical edits and writes only
the `--out` snapshot; `--write` rewrites in place each edit it can trace to
one literal in one project file, lists every other with the reason it was
not written, never writes a semantic change, and on a disagreeing re-run
restores every file and exits 1.

Token ratchet paid in content, not wrapping: the duplicated `--out` recheck
block (its first line was byte-identical to Quickstart step 1), the
"in memory" clause the mechanism paragraph already states, and the
stored/authored exclusivity sentence the stored-only-flag row already
carries. 24772 -> 24748 bytes, 6193 -> 6187 tokens, 488 -> 484 lines.

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

Copy link
Copy Markdown
Contributor Author

Contract review

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

Inputs: card #22120 (body and thread), the diff of 9bb10014 against its merge-base db4c45b8c3 (one file, skills/objectstack-upgrade/SKILL.md, +13/−17), the PR body, and the head's check-runs read through the API. Nothing built, run or re-run locally; the token figure below is arithmetic on the blob (24,748 bytes ⇒ ceil(/4) = 6187, ceiling 6193). Reviewed adversarially: every sentence the diff adds about what os migrate meta writes was traced to packages/cli/src/commands/migrate/meta.ts and packages/cli/src/utils/authored-source-codemod.ts on db4c45b8c3, and every deletion was checked for a surviving home in the same file.

① Derived judgments

  • Accept set and public surface: unchanged. No package source, schema or export moves; the diff is published teaching text. Clause-②: no is correct for the reason the claim gives (a documentation card).
  • Governed-text face, claim by claim:
    1. "By default os migrate meta rewrites no source file. It lists the mechanical edits and writes only the --out JSON snapshot." — true: write defaults to false (meta.ts :657-664); the authored-source mode writes the --out snapshot only. The sentence makes no claim about a run with nothing to migrate, so the in-flight fix(cli): os migrate meta --out writes its snapshot on a run with nothing to migrate #22121 cannot falsify it. PASS.
    2. "--write rewrites in place each edit it can trace to one literal in one project file" — true: the flag description and the codemod docblock's proof rule (one object or array literal in one project file, statically matching the loaded value, no second reference to any binding the walk crossed). PASS.
    3. "lists every other with the reason it was not written" — true: printWriteOutcome prints not written [kind]: reason per refused site over a closed CodemodRefusalKind set. PASS.
    4. "never writes a semantic change" — true: the flag description ("Never writes the manual (semantic) changes."); the planner is not handed todos. PASS.
    5. "if re-running the chain over the written files disagrees, restores every file and exits 1" — true: outcome status restored puts every file back and this.exit(1) fires whenever write.status !== 'written' (meta.ts :828, :859). The unwritten exit (a file changed on disk between read and write; nothing written, exit 1) is not described — an omission, not a false claim. PASS.
    6. The Quickstart comment "(writes only --out; --write also rewrites the sites it can prove)", the table line --write # rewrite the proven sites in place, the failure-mode row ("the default run only lists" / "Pass --write, or port the printed edits by hand; then replay from the target major to confirm 0 changes") and the stored-only row tail ("writes only --out and, with --write, the sources") — true of both routes; the replay-to-confirm instruction survives in the row. PASS.
  • Deletions and their homes: (a) the --out recheck code block — the recheck is carried by Quickstart step 3 (applied must be []), the §3.3 callout and the failure-mode row "Replay from the target major still applies changes"; its --out command line is Quickstart step 1 byte for byte. Survives. (b) "It rewrites the loaded stack in memory and reports the diff" — the mechanism paragraph above it (load, normalise without the load-time conversion pass, replay each major as a chain hop, parse) and the "Applied N mechanical change(s) … This is the diff, already attributed" bullet carry the fact; the words "in memory" are gone. Survives. (c) "The authored-source flags and the stored-only flags are mutually exclusive, and mixing them is refused rather than ignored" — the stored-only-flag direction is carried by the failure-mode row; the authored-flag-with---stored direction now survives only for --from ("--stored takes no --from"). The CLI refuses that mix loudly (oclif exclusive, exit 2), so the reader is not misled by silence; judged acceptable at a 6-token headroom and recorded here as the one deletion with a partial home — not a rule lost, not a reason to withhold.
  • Ratchet: 6193 → 6187 tokens (24,772 → 24,748 bytes), paid by the three deletions, no re-wrap counted; the gate's own line is quoted in the PR body and the arithmetic on the blob agrees.
  • Vocabulary against the spec sentence (feat(cli): os migrate meta --write — the AST codemod that rewrites authored sources for the mechanical applied set (v18) #9591 remainder 1): "lists the mechanical edits" matches "to list the mechanical edits for existing sources"; no unqualified "automatically". PASS.
  • Siblings: references/examples-upgrade.md:57 and evals/protocol-major-upgrade.json untouched; every must_contain anchor (os migrate meta --from 16, --out, tsc --noEmit, REPORT.md, applied) is present in the new blob (11 / 7 / 2 / 2 / 3 hits). Frontmatter unchanged, so no generated listing moves.

② Semver level

No package touched; skills/** ships by npx skills add / npm create objectstack, not through any package files[]. No changeset is the correct declaration; skip-changeset is on the PR and Check Changeset concluded success on this head. Consistent.

③ Boundary flags

Implemented-by: claude/issue-22120-upgrade-skill-migrate-meta-write
Reviewed-by: session_0181E4ZeZmWyknawnauxD2CE

VERDICT: PASS

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

维护者速读(终稿)

改了什么:只改一份对外发布的技能 skills/objectstack-upgrade/SKILL.md(+13/−17,30 行)。原文三处断言 os migrate meta「只写 --out、不改源文件」;自 --write(PR #22108)落地后这只对默认运行成立。现在每一句「命令写什么」都同时对默认运行与 --write 成立:默认只列出机械修改、只写 --out 快照;--write 只就地改写能证明来源的站点(一个项目文件里的一个字面量),其余逐条列出未写原因,语义修改永不写,复跑不一致则恢复全部文件并以 1 退出。

为什么改:客户项目的 agent 整包加载这份技能;读到「只写 --out」就永远不会用 --write,读到无条件的「自动改写」又会被误导。措辞与 CLI 源码(meta.ts 的 flag 描述、written | restored | unwritten 三态、exit 1)一致,也与 spec 侧退休句的「列出机械修改」一致;#9591 的 spec 半边独立落地,互不等待。

风险与代价(含回滚):纯文本,无代码、无 changeset、无生成物(frontmatter 未动,check:skill-docs 绿)。token 棘轮 6193 → 6187(上限 6193),靠删三处重复内容支付,未删规则、故障行或命令;其中「authored 与 stored 两组 flag 互斥、混用即拒」一句删后只剩单向表述,CLI 本身会响亮拒绝(exit 2),席位判可接受并记入契约复核。#22121(--out 空跑行为)与 #22115(语义通知列表)在 meta.ts 上并行,本文未对这两点做断言。回滚 = revert 一个提交。

席位意见:ACCEPT;席内契约复核 PASS(记录 6046687007,head 9bb10014)。建议批准:它把一份出货中的技能从「说错」改回「说对」,净减 24 字节。同文件的下一张卡 #22123(--from 10 低于支持底线 16 的过时示例)排在本 PR 之后。

你要做的(一个动作):以授权账号 APPROVE 本 PR(或亲手合入)。PR 保持 draft;获批后本席翻 ready、挂 auto-merge 入队并跟到 MERGED。

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/s skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

skills(objectstack-upgrade): the upgrade skill says os migrate meta "writes nothing but --out", which --write (PR #22108) now makes incomplete

3 participants