You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Found while implementing #11313, whose own "worth checking in the same pass" paragraph asked for this sweep and whose dispatch fenced the result to a finding rather than edits. Recording the measurement so the gate question can be decided on numbers instead of on the impression that this class is everywhere. No assignee.
What was measured
Every `os …` span (backticked, plus single/double-quoted spans starting os or $ os ) in the 107 non-test TypeScript sources under packages/cli/src/**, checked against the ids the built CLI actually registers. The id set is not transcribed: it is read from the built oclif Config (packages/cli/bin/run.js's package, after building the package and its dependency closure), whose canonical ids use : and are converted to the user-typed form with oclif.topicSeparator.
Two of the six were in #11313's own declared file surface and are fixed by its PR (utils/auth-config.ts:36 and :60). The other four are listed below, and they do not all want the same treatment — which is the useful part of this finding.
The four remaining, triaged
Genuinely stale — a real, mechanical spelling defect:
src/utils/api-client.ts:20 — `~/.objectstack/credentials.json` (written by `os projects switch`) . projects became environments in v5.0 with no aliases (ADR-0006); the registered id is environments switch, and the enumeration shows no projects topic and no id containing project. This is the exact twin of the line fixed in auth-config.ts under packages/cli: auth-config.ts tells a stuck user to run os auth login — that command does not resolve #11313 — same defect, one file over, left alone only because it is outside that card's surface.
src/commands/environments/create.ts:39 — "Starter content is installed from the App Marketplace instead (os packages install, …)". Registered ids under that topic are package install and package publish, singular. A plural typo, never a rename.
True negatives for a naive gate — the reason this is not just "N spelling swaps":
src/commands/package/publish.ts:16 — "(The legacy direct-to-environment os publish / os rollback commands, which wrote sys_environment_revision, have been removed.)" The sentence is about commands that no longer exist. A gate that flags it is asking an author to delete accurate history.
src/utils/response-envelope.ts:14 — "The three os datasource subcommands each carried their own transcription of …". datasource is a real topic (datasource introspect / list-tables / validate), just not a runnable id on its own. The prose names the topic, correctly.
The gate question
There is no gate over this class today.#11221's pin (src/commands/environments/environments.test.ts, #10967 pin: examples resolve to a real command id) reads static override examples via the TypeScript AST — it structurally cannot see a thrown-error string or a doc comment, and it only walks src/commands/**, so src/utils/** is outside its population entirely. #11313's new pin (src/utils/auth-config.test.ts) scans one file. Between them, four of the six findings above sit in no pin's population.
What the numbers argue, though, is that the error-path guidance class — the one #11313 was graded on, where a user is already stuck and the recovery instruction also fails — has exactly one instance repo-wide, and it is fixed. Everything else the sweep found is a doc comment: an IDE-hover and code-reading concern, not a "the tool is broken" concern. So the honest options are not "gate or N swaps":
A. Fix items 1 and 2 as a small card, no gate. Cheapest; leaves the class ungated, so it returns.
B. Fix 1 and 2, and widen the existing #10967 pin's population from examples arrays to all backticked invocations across packages/cli/src/**, with the self-retiring EXCLUDED map it already implements carrying items 3 and 4. That map is already built for exactly this — an exemption that asserts its own cause still holds — so the two true negatives would be declared rather than silently skipped, and an author who later deletes the legacy sentence is told to drop the exclusion.
C. As B, but teach the predicate to accept a bare topic name (item 4) and to recognise a prose-about-a-retired-command shape (item 3). Item 4 is mechanical (the topic list is right there in the Config); item 3 is not — "have been removed" is not a machine-readable marker, and inventing one is worse than an exclusion entry.
Recommendation: B. It reuses a mechanism this package already has, already documents, and has already retired once, and it declares the two true negatives instead of narrowing the population until they disappear.
Reproducing
The sweep is ~40 lines: load Config from packages/cli, walk src/** skipping *.test.ts variants, regex `(?:\\?\$ )?(os [^`\n]*)` plus the quoted forms, drop a trailing backslash (an escaped closing backtick inside a template literal), and accept an invocation when the remainder equals a registered id or starts with one plus a space. Requires the CLI and its dependency closure built, since oclif's pattern strategy scans dist/commands.
Found while implementing #11313, whose own "worth checking in the same pass" paragraph asked for this sweep and whose dispatch fenced the result to a finding rather than edits. Recording the measurement so the gate question can be decided on numbers instead of on the impression that this class is everywhere. No assignee.
What was measured
Every
`os …`span (backticked, plus single/double-quoted spans startingosor$ os) in the 107 non-test TypeScript sources underpackages/cli/src/**, checked against the ids the built CLI actually registers. The id set is not transcribed: it is read from the built oclifConfig(packages/cli/bin/run.js's package, after building the package and its dependency closure), whose canonical ids use:and are converted to the user-typed form withoclif.topicSeparator.Two of the six were in #11313's own declared file surface and are fixed by its PR (
utils/auth-config.ts:36and:60). The other four are listed below, and they do not all want the same treatment — which is the useful part of this finding.The four remaining, triaged
Genuinely stale — a real, mechanical spelling defect:
src/utils/api-client.ts:20—`~/.objectstack/credentials.json` (written by `os projects switch`).projectsbecameenvironmentsin v5.0 with no aliases (ADR-0006); the registered id isenvironments switch, and the enumeration shows noprojectstopic and no id containingproject. This is the exact twin of the line fixed inauth-config.tsunder packages/cli: auth-config.ts tells a stuck user to runos auth login— that command does not resolve #11313 — same defect, one file over, left alone only because it is outside that card's surface.src/commands/environments/create.ts:39— "Starter content is installed from the App Marketplace instead (os packages install, …)". Registered ids under that topic arepackage installandpackage publish, singular. A plural typo, never a rename.True negatives for a naive gate — the reason this is not just "N spelling swaps":
src/commands/package/publish.ts:16— "(The legacy direct-to-environmentos publish/os rollbackcommands, which wrotesys_environment_revision, have been removed.)" The sentence is about commands that no longer exist. A gate that flags it is asking an author to delete accurate history.src/utils/response-envelope.ts:14— "The threeos datasourcesubcommands each carried their own transcription of …".datasourceis a real topic (datasource introspect/list-tables/validate), just not a runnable id on its own. The prose names the topic, correctly.The gate question
There is no gate over this class today.#11221's pin (
src/commands/environments/environments.test.ts,#10967 pin: examples resolve to a real command id) readsstatic override examplesvia the TypeScript AST — it structurally cannot see a thrown-error string or a doc comment, and it only walkssrc/commands/**, sosrc/utils/**is outside its population entirely. #11313's new pin (src/utils/auth-config.test.ts) scans one file. Between them, four of the six findings above sit in no pin's population.What the numbers argue, though, is that the error-path guidance class — the one #11313 was graded on, where a user is already stuck and the recovery instruction also fails — has exactly one instance repo-wide, and it is fixed. Everything else the sweep found is a doc comment: an IDE-hover and code-reading concern, not a "the tool is broken" concern. So the honest options are not "gate or N swaps":
#10967pin's population fromexamplesarrays to all backticked invocations acrosspackages/cli/src/**, with the self-retiringEXCLUDEDmap it already implements carrying items 3 and 4. That map is already built for exactly this — an exemption that asserts its own cause still holds — so the two true negatives would be declared rather than silently skipped, and an author who later deletes the legacy sentence is told to drop the exclusion.Config); item 3 is not — "have been removed" is not a machine-readable marker, and inventing one is worse than an exclusion entry.Recommendation: B. It reuses a mechanism this package already has, already documents, and has already retired once, and it declares the two true negatives instead of narrowing the population until they disappear.
Reproducing
The sweep is ~40 lines: load
Configfrompackages/cli, walksrc/**skipping*.test.tsvariants, regex`(?:\\?\$ )?(os [^`\n]*)`plus the quoted forms, drop a trailing backslash (an escaped closing backtick inside a template literal), and accept an invocation when the remainder equals a registered id or starts with one plus a space. Requires the CLI and its dependency closure built, since oclif's pattern strategy scansdist/commands.Generated by Claude Code