Skip to content

Commit 033e5c5

Browse files
docs(skills): objectstack-upgrade names os migrate meta --write beside the default run (#22122)
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 - No `packages/spec/**` (the retirement sentence in `retired-key.ts` is #9591's spec-lane remainder; this text uses its vocabulary — "lists the mechanical edits" — so the two read consistently once that lands). No `content/docs/**` (devx lane under #22108). No generated listing: frontmatter unchanged, `check:skill-docs` green ("Skill docs in sync"). - Siblings untouched and still true of the by-hand route: `references/examples-upgrade.md:57` ("Ported into sources from `os migrate meta --out`") and `evals/protocol-major-upgrade.json` (`must_contain` includes `--out`; the eval's expected answer describes the default route, which still rewrites no source). ## 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](https://claude.ai/code/session_0181E4ZeZmWyknawnauxD2CE)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 8fc50b7 commit 033e5c5

1 file changed

Lines changed: 13 additions & 17 deletions

File tree

‎skills/objectstack-upgrade/SKILL.md‎

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ The id is the commit's subject line and its justification.
5959
grep -rn "protocol" objectstack.config.ts package.json | head
6060
node -p "require('@objectstack/spec/package.json').version"
6161

62-
# 1 · mechanical — replay the chain (reads the config, writes nothing but --out)
62+
# 1 · mechanical — replay the chain (writes only --out; --write also rewrites the sites it can prove)
6363
os validate > .upgrade/validate-before.txt 2>&1 || true # the control, kept
6464
os migrate meta --from 16 --step
6565
os migrate meta --from 16 --json > .upgrade/migrate.json
@@ -128,6 +128,7 @@ os migrate meta --from 16 --step # per-hop checkpoint (bisect a f
128128
os migrate meta --from 16 --to 17 # stop at a specific major
129129
os migrate meta --from 16 --json # machine-readable result
130130
os migrate meta --from 16 --out migrated.json # write the canonicalized stack
131+
os migrate meta --from 16 --write # rewrite the proven sites in place
131132
os migrate meta --from 16 apps/crm/objectstack.config.ts # pick the stack explicitly
132133
```
133134

@@ -148,19 +149,15 @@ it prints:
148149

149150
### ⚠ The one fact that surprises every operator
150151

151-
**`os migrate meta` does not rewrite your source files.** It rewrites the
152-
loaded stack *in memory* and reports the diff. The only file it writes is
153-
`--out`, a JSON snapshot.
152+
**By default `os migrate meta` rewrites no source file.** It lists the
153+
mechanical edits and writes only the `--out` JSON snapshot. `--write` rewrites
154+
in place each edit it can trace to one literal in one project file, lists every
155+
other with the reason it was not written, never writes a semantic change, and
156+
if re-running the chain over the written files disagrees, restores every file
157+
and exits 1.
154158

155-
Porting the printed edits into the project's own sources is yours. Work from
156-
that list, one `conversionId` at a time; use `--out` as the oracle you diff
157-
against, never as the file you ship.
158-
159-
```bash
160-
os migrate meta --from 16 --out .upgrade/migrated.stack.json
161-
# then, after porting the edits into the real sources:
162-
os migrate meta --from 17 --out .upgrade/recheck.json # should apply 0 changes
163-
```
159+
Porting the edits left unwritten is yours, one `conversionId` at a time; use
160+
`--out` as the oracle you diff against, never as the file you ship.
164161

165162
### Stored rows: rehydration replays the same conversions
166163

@@ -186,8 +183,7 @@ and you never hand-edit `sys_metadata`. To make it durable, run the stored pass
186183
exiting 1 with `confirmation_required`.
187184

188185
`--stored` takes no `--from`: a stored row carries its own history, so the
189-
pass replays the whole chain. The authored-source flags and the stored-only
190-
flags are mutually exclusive, and mixing them is refused rather than ignored.
186+
pass replays the whole chain.
191187

192188
### Data migrations are not metadata migrations
193189

@@ -466,13 +462,13 @@ guarantee.
466462

467463
| Symptom | What it actually is | Fix |
468464
|:--|:--|:--|
469-
| `migrate meta` reports changes, but the files are unchanged | Working as designed — the command writes nothing but `--out`. | Port the printed edits into the sources, then replay from the target major to confirm 0 changes. |
465+
| `migrate meta` reports changes, but the files are unchanged | Working as designed — the default run only lists. | Pass `--write`, or port the printed edits by hand; then replay from the target major to confirm 0 changes. |
470466
| Replay from the target major still applies changes | The port is incomplete, or a source builds metadata at runtime from a shape the chain never saw. | Diff against `--out`; grep for the `conversionId`'s surface in code that constructs metadata dynamically. |
471467
| `validate` green, but a feature silently stopped working | An R2 residue item: code reading a renamed key now reads `undefined`. | Exercise the path for real. A green parse says nothing about a `??` chain in the project's own code. |
472468
| `validate` green from the start, so "there was nothing to upgrade" | A migration-chain-only conversion — no tombstone rejects it, so nothing complains. | Replay the chain anyway. `validate` green is necessary, not sufficient; see [3.3](#33-validate). |
473469
| `validate` reports findings that have nothing to do with retired keys | The author-time rule pass, not the schema pass. | Diff against the pre-upgrade `validate` control. Pre-existing findings are not this upgrade's scope. |
474470
| A retired key round-trips without error | The schema carrying it is not strict and the key is being stripped, or the key still has a live load-path window. | Determine which — the two need different acceptance evidence. See [the reverse check](#reverse-check). |
475-
| `--apply` refused / stored-only flag rejected | `--apply`, `--yes`, `--force`, `--type`, `--database-url` mean something only with `--stored`. | Add `--stored`, or drop the flag; the authored-source chain has nothing to write to. |
471+
| `--apply` refused / stored-only flag rejected | `--apply`, `--yes`, `--force`, `--type`, `--database-url` mean something only with `--stored`. | Add `--stored`, or drop the flag; the authored-source chain writes only `--out` and, with `--write`, the sources. |
476472
| `MigrationFloorError` | `--from` is older than the chain's support floor. | Upgrade to the floor by an older route first; the floor is a release-policy boundary, not an oversight. |
477473

478474
Scripting the run instead of reading it? Every `--json` failure above carries a

0 commit comments

Comments
 (0)