Repository navigation
[finding][devx] cli.doctor-deprecation-scan calls os migrate meta "the codemod that actually exists" — it is a chain replayer that prints edits and writes no source #10418
Copy link
Copy link
Labels
Description
Activity
First-touch grading (triage seat): promoted to
pm:queue, Task, disposition A — reword the two descriptors to whatos migrate metais (lists mechanical edits, writes no source), bumpcli.doctor-deprecation-scanto revision 2 with a history entry. B (leave a contradiction inside one file the runner reads) fails the anti-confusion purpose the checklist exists for, at the cost of a two-line edit. Premise gate: land after PR #10412 so the wording aligns with the sibling item's final text. Co-location note: #10416 edits the same checklist area — fold or serialize at dispatch. Size/model suggestion: S, sonnet.
Generated by Claude Code
{ "issue": 10418, "status": "done", "branch": "claude/issue-10418-migrate-meta-not-a-codemod", "pr": "https://github.com/objectstack-ai/objectstack/pull/10829", "premise_still_valid": true, "summary": "Corrected the two descriptors in docs/qa/platform-checklist/areas/cli.json item cli.doctor-deprecation-scan that called `os migrate meta` a codemod, taking triage's disposition A. The acceptance clause now reads \"The remediation path that DOES exist is `os migrate meta` ... but it is not a codemod: it replays the migration chain and PRINTS the mechanical edits for the author to apply by hand\", citing the flag surface, the two if (flags.out)-guarded writes and the 'unsafe and lossy' header, and naming #9591 (v18, pm:on-hold) as the commissioned-but-unbuilt in-place codemod; the source descriptor now reads \"cli.migrate-meta-codemod (`os migrate meta` -- the remediation path that does exist; its revision 3 asserts the command LISTS mechanical edits and rewrites no source file. The id keeps its `-codemod` spelling only because ids are immutable ... it reads as a forward reference to #9591)\", and #9591 was added to `source` so that reference resolves. revision 1 -> 2 with a history entry per the directory README's change lifecycle. The item's load-bearing assertion is untouched and still an expected-fail (doctor.ts:2149 prescribes `objectstack codemod v2-to-v3`, registered nowhere); the clause additionally now warns that a fix which merely repoints the hint at `os migrate meta` must promise a LIST, not an auto-fix. All four premise facts re-derived at base f4e5d916d6 and all four HELD -- nothing had moved. cli.migrate-meta-codemod was read and left alone (its revision-3 text is already correct); meta.ts untouched. The claim has NOT spread under the word 'codemod' -- but the idea has, into four docs-site pages, filed as #10831.", "tests": "All at final commit 862b32b7b8 (git rev-parse --short HEAD), every exit code captured BEFORE any pipe (cmd > file 2>&1; ec=$?), and each verdict quoted from the gate's own output line, never from $?.\n\n`pnpm check:platform-checklist` is TWO halves and was run as two separate commands, before AND after the edit:\n BEFORE: node scripts/checklist-select.mjs --self-test = 0 | node scripts/check-platform-checklist.mjs = 0\n AFTER : node scripts/checklist-select.mjs --self-test = 0 -> '\\u2713 checklist-select self-test: 17 cases pass.'\n node scripts/check-platform-checklist.mjs = 0 -> 'check-platform-checklist: OK -- 15 areas, 205 items (205 active); coverage: 30 kinds mapped, 0 waived; traps: 19 documented, 19 in use (extractor control: 22 assertions).'\n The before-run matters: it proves the revision/history check was green on both sides, so the AFTER green is about my edit rather than a pre-existing red I happened to leave alone.\n\n\\u26a0\\ufe0f This gate is NOT wired into CI, by maintainer decision recorded at .github/workflows/lint.yml:954-960 and restated in docs/qa/platform-checklist/README.md ('Operating cadence -- when to run this (it is NOT in CI)'). The local green above is the ONLY signal this change will ever get. No CI job re-runs it on PR #10829, so a green Lint & Repo Gates on that PR says nothing whatsoever about the checklist.\n\nnode scripts/pm/dispatch-gates.mjs (no paths passed -- it derived the change set itself: '1 path(s) vs merge base f4e5d916d of origin/main and HEAD; committed 1, working tree 0, untracked 0'), exit 0, named exactly two families:\n pnpm check:doc-authoring = 0 -> '\\u2713 doc authoring guard: 389 files clean -- no bare metadata literals.'\n pnpm --filter @objectstack/lint run check:doc-formula-expressions = 0 -> '\\u2713 check:doc-formula-expressions: 22 record-scoped formula example(s) across 416 files / 1443 TS blocks judged clean by @objectstack/formula.' + '\\u2713 self-test: 30 cases passed'\n plus pnpm check:nul-bytes (standing, any edit) = 0 -> 'check-nul-bytes: OK (scanned 6252 text file(s) -- 6252 tracked, 0 untracked-not-ignored; skipped 5 binary; no raw ASCII control bytes).'\n and a targeted self-scan of the edited file: grep -naP '[\\\\x00-\\\\x08\\\\x0b\\\\x0c\\\\x0e-\\\\x1f\\\\x7f]' exit 1 (no match).\n The script echoed the script name in every run, so no zero-match silent green.\n\n\\u26a0\\ufe0f check:doc-formula-expressions FAILED twice first, and both failures were environmental, not mine: ERR_MODULE_NOT_FOUND 'typescript' (no pnpm install in the fresh worktree), then ERR_MODULE_NOT_FOUND @objectstack/formula/dist/index.mjs (dependency closure not built). Fixed by pnpm install then pnpm --workspace-concurrency=2 --filter '@objectstack/lint^...' build, both through scripts/pm/os-verify-lock.sh -c (VERDICT command-exit 0, held 7s / 143s, waited 0s / 143s). Recording it because an unbuilt closure reads exactly like a real red.\n\nEdit landed on disk, verified by anchored counts rather than by the editor's exit code: the two removed strings now occur exactly once each and BOTH occurrences are inside the new revision-2 history entry (proved by loading the JSON and testing each field -- 'FOUND in field: history' for both, and in no other field); the four injected anchors each occur exactly once; git diff --stat = 1 file changed, 6 insertions(+), 4 deletions(-); the file re-parses as JSON with revision 2, history revisions [1, 2], 6 source entries.\n\nNO ABLATION APPLIES. This is a prose correction inside a JSON ledger -- there is no guard under test whose deletion would flip a check red, so there is nothing to mutate and nothing to rebuild. Stating that rather than filling the slot with a ceremonial run.", "open_questions": [], "out_of_scope_findings": [ "filed as #10831 (domain:devx, unassigned, no pm:queue): four docs-site pages attribute an in-place source rewrite to `os migrate meta --from` -- flows.mdx:245 and widget-contract.mdx:316 (which also name the mutually-exclusive --from/--stored pair, meta.ts:195-198 `exclusive: ['stored']`, and say 'automatically'), query-syntax.mdx:860 and queries.mdx:388 -- while upgrading.mdx:145 states the opposite in bold and every generated reference table already carries #9529's corrected sentence. Includes meta.ts:81's own docblock ('this command rewrites an author's source') contradicting its header 74 lines below, and a scope warning that v17.mdx:2475 ('--stored rewrites sys_metadata rows in place') is CORRECT and must survive any search-and-replace." ] }
Generated by Claude Code
Found while rewriting the sibling item
cli.migrate-meta-codemodfor #9733 (PR #10412). Filed unassigned; deliberately not fixed in that PR — see the scope note below.The finding
docs/qa/platform-checklist/areas/cli.json, itemcli.doctor-deprecation-scan(added 2026-08-20, revision 1, P2), describesos migrate metatwice as a codemod:os migrate meta(cli.migrate-meta-codemod)"source: "sibling items … and cli.migrate-meta-codemod (the codemod that actually exists)"os migrate metais not a codemod. It declares exactlyfrom · to · step · out · stored · database-url · apply · yes · force · type · json— no--write/--fix/in-place flag — and on the authored-source arm its only file write is the--outJSON snapshot (bothwriteFileSynccalls areif (flags.out)-guarded).packages/cli/src/commands/migrate/meta.tsstates it in its own header:The in-place AST codemod is commissioned as #9591 for v18 and has not been built.
Why this is worth a card rather than a typo fix
The load-bearing assertion of that item is unaffected and correct:
os doctor's remediation hint prescribesobjectstack codemod v2-to-v3, which is registered nowhere, and the item records that as an expected-fail. The contrast it draws — unlike that command,os migrate metais real — is also true. Only the word "codemod" is wrong.It matters because PR #10412 rewrites the sibling item's title to say
os migrate meta"rewrites no source file". Once that lands, the same file asserts both things, and a reader hitting thecli.doctor-deprecation-scanclause first gets the same wrong idea the #9733 card exists to remove — that there is a working metadata codemod to be pointed at.Why #10412 did not fix it in passing
It fails the bounded in-place exemption on two of the four conditions:
cli.migrate-meta-codemodis active P1 for a capability that does not exist — it assertsos migrate metarewrites authored sources #9733 residue is anactiveP1 whose title and acceptance clauses assert a capability that does not exist. This is a loose descriptor in another item's parenthetical, where the surrounding assertion is true.os migrate meta— a framing call belonging to that item's author, not a substitution fixed by evidence.It also needs its own
revisionbump andhistoryentry (README lifecycle), in an item one day old.Suggested dispositions (triage's call)
os migrate meta— which lists mechanical edits rather than applying them"), bumpcli.doctor-deprecation-scanto revision 2 with a history entry. Keeps the contrast the clause is drawing while dropping the false noun.Refs:
docs/qa/platform-checklist/areas/cli.json(cli.doctor-deprecation-scan) ·packages/cli/src/commands/migrate/meta.ts· #9591 (the v18 codemod,pm:on-hold) · #9733 / #10412 (where this surfaced).Generated by Claude Code