Uh oh!
There was an error while loading. Please reload this page.
fix(cli): doctor prescribes no codemod command that does not exist - #10882
Conversation
…10680) After `--scan-deprecations` reported its hits, `os doctor` printed ``Run `objectstack codemod v2-to-v3` to auto-fix``. No `codemod` command is registered: oclif resolves this CLI by globbing `dist/commands/**`, nothing under `src/commands/` compiles to `codemod`, and neither bundled plugin supplies one — the prescription exits 2, `command codemod:v2-to-v3 not found`, only after the operator has spent time on it. The docs already recorded the automated codemod as "not yet available"; the tool was the last place still claiming otherwise. The hint is deliberately NOT repointed at `os migrate meta`. That command's subject is an authored stack config replayed across protocol majors, and its own header declines the rewrite this hint promised — "does not silently rewrite TS config source (that AST rewrite is unsafe and lossy)" — with both writes guarded behind `--out` JSON snapshots. It cannot touch the `src/**` TypeScript these patterns are found in, and three of the eight DEPRECATED_PATTERNS are not metadata at all. `os lint --fix` is print-only by declaration. Nothing registered does the job, so the line says so and points at the per-finding replacement it already computes, printed under `--verbose`. The new pin closes the class rather than the instance: every `os …` / `objectstack …` hint in `doctor.ts` must resolve to a command file under `src/commands/`, and the whole rendered report is held to the same rule. The scanner is untouched — file:line attribution, `→ replacement` detail and the advisory exit 0 are pinned here so this edit cannot regress them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019bmVFqoQPq63zhKrxdYG1r
The class-closing sweep read the raw file, so the print site's own comment — which quotes the dead prescription verbatim, on purpose, as the record of why the line reads as it does — tripped it. The rule is about the report an operator sees, so the sweep now reads printable source: whole comment lines dropped, never a trailing `//`, because `http://localhost:3000` lives inside these strings and a greedier strip would delete real hints and leave the sweep passing over less than it claims. The haystack size is asserted for the same reason. The ban is on the prescription, not the word: the corrected line has to be able to say there is no codemod. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019bmVFqoQPq63zhKrxdYG1r
📓 Docs Drift CheckThis PR changes 1 package(s): 5 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 1 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 23 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 00a7ffc53fe4e56da8f00abe1ab6a9e811d3a20e && git checkout 00a7ffc53fe4e56da8f00abe1ab6a9e811d3a20e
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 0b4e2b73560589562ab39c80f9d578dfb770f38a af5c56435295b8ce9141ef0f6b281a81fe7bbf12 && git checkout -B drift-repro 0b4e2b73560589562ab39c80f9d578dfb770f38a && git merge --no-ff af5c56435295b8ce9141ef0f6b281a81fe7bbf12
node scripts/docs-audit/affected-docs.mjs --json 0b4e2b73560589562ab39c80f9d578dfb770f38a
|
Uh oh!
There was an error while loading. Please reload this page.
⛔ merge queue 构建失败 — 先分诊,再决定要不要重排队列构建 32500260335 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集), 失败的 job(日志抽取,best effort):
跨 PR 相同签名(24h,按失败测试文件聚合):
历史信号:
分诊清单:
Generated by Claude Code · merge-queue-triage workflow (#4859) |
Fixes#10680
The defect
After listing its hits,
os doctor --scan-deprecationsprinted:No
codemodcommand has ever been registered. oclif resolves this CLI by globbingdist/commands/**/*.js(package.json→oclif.commands, pattern strategy); nothing undersrc/commands/compiles tocodemod, and neither bundled plugin (@oclif/plugin-help,@oclif/plugin-plugins) supplies one. Probed against the built binary on this branch:content/docs/protocol/backward-compatibility.mdx:134already recorded the automated codemod as "not yet available". The tool was the last place still claiming otherwise — and a wrong prescription costs the operator their time before they can find out, which is the same false-confidence class as the two defects this lane landed today (os datasource validatepassing over drift it never read;os doctorprinting✓over a tree it never walked, #10679).Why the hint was removed, not repointed
The obvious repair — point it at
os migrate meta— is deliberately not what landed. That would be the same defect respelled:os codemod v2-to-v3os migrate metamigrate/meta.ts,--helpexit 0)--outJSON snapshots (:347,:394), and--fromis required, so a bare invocation fails tooos lint --fixnode scripts/codemod/*.mjsoscommandapimethods-legacy-to-primitivesandview-to-viewitem, neither covering these patternsos migrate metaalso cannot reach the subject: the scan reports onsrc/**TypeScript, and three of the eightDEPRECATED_PATTERNS(EnhancedObjectKerneland the two deep-import paths) are not metadata at all. The in-place AST codemod is commissioned as #9591 (v18,pm:on-hold) and unbuilt.Nothing registered does the job, so the line says so and points at the remedy that really exists — the replacement already computed for each finding, printed under
--verbose:The pin closes the class, not the instance
doctor-deprecation-hint-commands.test.tsasserts that everyos …/objectstack …hint doctor can print resolves to a command file undersrc/commands/— applied both to the file's printable source and to the whole rendered report. That hint was the only unresolvable one of the six distinct hints in this 2,290-line file; a future phantom prescription fails here rather than shipping.The sweep reads printable source: whole comment lines are dropped (the print site documents the dead prescription verbatim, on purpose), never a trailing
//—http://localhost:3000lives inside these strings and a greedier strip would silently delete real hints and leave the sweep passing over less than it claims. The haystack size is asserted for that reason.The scanner itself is untouched, and its passing clauses are now pinned here so this edit cannot be what regresses them: file:line attribution, the
→ replacementdetail under--verbose, and warns-not-gates measured as a delta against a cleansrc/in the same cwd.⛔ Nothing in #10679's landed work is touched —
MonorepoTreeScan, the✓scoping, and theNot builtgate are all as they were, and its test file is re-run green alongside this one.Verification, at
af5c564352Ablation (subject resolves from source: the test imports
./doctor.jsrelative within the same package, so vitest readsdoctor.ts— nodistrebuild is involved, which the red leg proves rather than assumes):Test Files 2 passed (2)·Tests 26 passed (26)(with #10679's file)Tests 5 failed | 7 passed (12)— incl. 3 end-to-end casesTests 12 passed (12)The 7 that stayed green in leg 2 are the probe self-tests and the passing-clause pins — correct: the defect did not touch them.
Package:
pnpm --filter @objectstack/cli typecheck→TYPECHECK_EXIT=0; the full@objectstack/clisuite →Test Files 143 passed,Tests 1596 passed(the 2 failures in that run were an over-broad assertion in the new file, fixed inaf5c564352).Gate union, re-derived from the real changeset with
node scripts/pm/dispatch-gates.mjs(no paths) at this head — 13 path-matched + 5 convention-triggered (new test file) +check:nul-bytes, all green:Their own verdict lines, not a bare exit code:
Out of scope, filed
#10881 —
packages/cli/README.md:119still documentsos codemod v2-to-v3in a### Code Transformstable, and:306shows acodemod/v2-to-v3.tsnode in its source-tree listing. Same claim, one surface over; filed unassigned rather than folded in, per this card's docs fence.#10881 is not addressed here.Generated by Claude Code