Skip to content

cli: every documented os auth / os studio invocation now names a command that resolves - #11314

Merged
os-zhuang merged 3 commits into
mainfrom
claude/issue-11221-cli-documented-commands-resolve
Aug 23, 2026
Merged

cli: every documented os auth / os studio invocation now names a command that resolves#11314
os-zhuang merged 3 commits into
mainfrom
claude/issue-11221-cli-documented-commands-resolve

Conversation

@os-zhuang

@os-zhuangos-zhuang commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Fixes#11221
Fixes#11180

A family fold: two cards, one defect form — a documented CLI invocation that does not resolve — corrected to the real spelling, or removed. One commit per card, plus a third for the pin retirement the first commit fires. Verified against the built CLI, not by reading source.

A note on spelling in this body. The defect is about an os auth … prefix, where stands for register / whoami / logout. GitHub's body sanitizer strips short angle-bracket fragments — including inside code fences — so the angle-bracket placeholders that appear in the real source and in real CLI output are spelled without brackets here. The first version of this body lost them silently; this is the repair, not the original wording.

The two cards

#11221register / whoami / logout examples said os auth …

These three live at the root of packages/cli/src/commands/, so oclif's pattern-strategy loader registers them as register / whoami / logout. Their static override examples — which oclif prints verbatim in --help — spelled an os auth … shape that has never resolved.

Pre-fix, against packages/cli/bin/run.js:

$ node packages/cli/bin/run.js auth whoami --help
› Error: Command auth:whoami not found. (exit 2)
$ node packages/cli/bin/run.js auth register --help
› Error: Command auth:register not found. (exit 2)
$ node packages/cli/bin/run.js auth logout --help
› Error: Command auth:logout not found. (exit 2)

…while the bare os whoami / os register / os logout each exited 0 and printed help. The examples named the one spelling that could not work.

All seven examples entries now use the bare, registered spelling. The check that closes this card extracts the example lines from the rebuilt binary's own --help output and resolves each against the rebuilt binary's own registry:

RESOLVES os register
RESOLVES os register --email user@example.com --name "Jane Doe" --password mypassword
RESOLVES os register --url https://api.example.com
RESOLVES os whoami
RESOLVES os whoami --format json
RESOLVES os whoami --url https://api.example.com --token TOKEN
RESOLVES os logout
---
example lines checked: 7, unresolved: 0
anti-vacuity, the PRE-FIX spellings through this same check:
DEAD (expected) os auth register
DEAD (expected) os auth whoami
DEAD (expected) os auth logout
DEAD (expected) os studio

(TOKEN on the sixth line is an angle-bracket token placeholder in the real example string and in the real output — respelled here per the note above.)

The anti-vacuity block is the part that makes the seven RESOLVES mean something: the same predicate still rejects the spellings this PR removed.

Class renames.AuthRegisterRegister, AuthWhoamiWhoami, AuthLogoutLogout. oclif derives a command's id purely from its file path, never from the class name, so this changes no runtime resolution — re-verified by rebuilding and re-running --help on all three. It also brings them onto this package's measured convention: surveying every root-level command source, each class is exactly the PascalCase of its filename, with the Auth* quartet the sole exception.

login.ts keeps AuthLogin. Its examples were already correct ($ os login), which puts it outside this card's file surface; that lone remaining holdout is reported, not swept.

#11180 — the README listed os studio, a command the CLI does not ship

packages/cli/README.md's Development table carried a row reading os studio [config] — "Launch Studio UI with development server". Two independent readings, because "confirmed absent from the command registry" deserves better than a grep:

  1. From inside — loading the built CLI's own oclif Config enumerates 60 registered ids, of which zero match studio (and zero match auth, and there is no auth topic). Control, same enumeration: dev, serve, login, logout, register, whoami all present. The control is what makes the zero evidence rather than a broken probe.
  2. From outsideos studio --help exits 2 with Error: Command studio not found.

The row is deleted rather than rewritten. Studio is not reached by a CLI command at all — the console serves it at /_console/studio after os dev or os serve, both of which this same table already lists. A replacement row would reintroduce the category error that made this one wrong: a Commands table lists commands, and a browser route is not one.

The third commit: a pin that retired itself, exactly as designed

packages/cli/src/commands/environments/environments.test.ts (landed by #11227 for #10967) carries a deliberately self-retiringEXCLUDED map. Its header states the contract:

when #11221's fix removes the last one, that assertion goes red on purpose, and the failure message says to delete the entry

That is measured here, not predicted. With only the first commit applied:

 × register.ts still needs its exclusion (owned by #11221)
× whoami.ts still needs its exclusion (owned by #11221)
× logout.ts still needs its exclusion (owned by #11221)
Tests 3 failed | 68 passed (71)
AssertionError: register.ts no longer has an unresolved examples entry --
remove it from EXCLUDED above so it is scanned like every other command source.

So #11221 could not land green without this edit, and the failing test names this card as the owner of the remedy. After retiring: 71 passed (71), with all three files now covered by the main assertion instead of exempted — the pin got stronger, not weaker.

Retirement shape follows the precedent the file names as its own (packages/create-objectstack/src/starter-comments-self-contained.test.ts, retired the same way in #11022): the map goes back to empty, the retiring assertion stays so the next entry added is held to the same self-retirement, and the header records that it fired.

On file ownership, since this path was on the dispatch's read-only list: that fence was attributed to #10967, which is closed (completed, 2026-08-23T05:11:28Z) with PR #11227merged at 04:58 — roughly 3.5h before dispatch. No open PR or branch touches the file. The one genuinely live hold, #11268, touches serve.ts, test/serve-node-env-production-default.e2e.test.ts, vitest.config.ts and its changeset — checked against its file list, zero overlap. Both genuinely-held surfaces (serve.ts, packages/cli/test/**) are untouched by this branch. Kept as its own commit so it can be dropped independently. Confirmed by the dispatching PM before this PR was opened.

Out of scope, filed not swept

  • packages/cli: auth-config.ts tells a stuck user to run os auth login — that command does not resolve #11313packages/cli/src/utils/auth-config.ts:60 throws "No stored credentials found. Please run os auth login first.", and os auth login is dead too (exit 2, measured). Deliberately not fixed here: it is a user-facing thrown error rather than an examples string, so it is a different surface and belongs to a graded card of its own rather than being slipped into this one. Worth noting the existing pin cannot see this class at all — it reads examples arrays via AST.

Verification

All at final head bc08f9bb, each verdict quoted from what the gate itself printed.

  • pnpm --filter @objectstack/cli testTest Files 160 passed (160) / Tests 1822 passed (1822), VERDICT command-exit 0. Includes remote-api-commands.test.ts, which default-imports two of the renamed classes (default imports are rename-proof, so that held file needed no edit and still passes) and environments.test.ts.
  • pnpm --filter @objectstack/cli typecheck (tsc --noEmit) — VERDICT command-exit 0.
  • pnpm lint (repo-wide eslint . --no-inline-config) — VERDICT command-exit 0 in 81s. Run in full; no narrowing taken.
  • Gate families re-derived at this head with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (change set read by the script itself, three-dot, 7 paths). All 14 path-matched families run and green: check:changeset-gate-self-tests, check:cross-package-test-inputs, check:objectui-changeset, check:published-files, check:slot-lookup, check:test-source-alias, check:type-source-resolution, check-adr-0087-registration, check-changeset-no-major, check-ci-filter-parity, check-cross-package-test-inputs, check-empty-changeset, check-plugin-teardown-shape, check-affected-docs.
  • Convention-triggered families (this edits a test file), all green: check:query-options-erasure, check:type-check-coverage, check:engine-double-contract, check:where-matcher, plus check:nul-bytes.
  • check:type-check-debt — first attempt refused (--re-measure cannot run: 1 workspace dependenc(ies) … have no built type entry point on disk -- @objectstack/service-knowledge), which means not measured, not passed. Built that closure and re-ran: OK — 33 ledger entr(ies) re-measured in 248.9s, 1897 raw tsc error(s) total, none above its recorded number. The --lower surplus it reports sits in plugin-approvals / runtime / plugin-auth / trigger-record-change — all pre-existing and untouched by this diff.

Two changesets, one per card, both patch on @objectstack/cli, matching the precedent of both sibling fixes (#11227 for the help-text class, #10968 for the README-prose class). No skip-changeset.

Generated by Claude Code

…md>` in --help
Fixes#11221
These three commands live at the root of packages/cli/src/commands/, so
oclif's pattern-strategy loader registers them as `register` / `whoami` /
`logout`. Their `static override examples` — printed verbatim by --help —
spelled an `os auth <cmd>` shape that has never resolved, so a user
copy-pasting out of --help hit `Error: Command auth:<cmd> not found.`
Measured against the built CLI (packages/cli/bin/run.js) before the fix:
`os auth whoami`, `os auth register`, `os auth logout` each exit 2 with
`Error: Command auth:<cmd> not found.`; the bare `os whoami` / `os register`
/ `os logout` each exit 0 and print help. All seven examples entries now use
the bare, registered spelling.
Exported default classes are renamed to match their file-path-derived command
id (AuthRegister -> Register, AuthWhoami -> Whoami, AuthLogout -> Logout).
oclif derives ids from file paths, never from class names, so this changes no
runtime resolution — re-verified against the rebuilt binary. It also brings
these onto the package's measured convention: every other root-level command
class is the PascalCase of its filename. packages/cli/test/remote-api-commands
.test.ts imports two of them, but as DEFAULT imports, so the local binding is
independent of the class name — that file is untouched and still passes.
login.ts keeps AuthLogin: its examples were already correct (`$ os login`),
putting it outside this card's file surface. The remaining holdout is
reported rather than swept.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019siH5jDmk5hrayvfyojUqR
Fixes#11180
packages/cli/README.md's Development command table listed
`| os studio [config] | Launch Studio UI with development server |`.
The CLI ships no `studio` command. The oclif command set is pattern-derived
from packages/cli/src/commands/**, and loading the built CLI's own Config
enumerates 60 registered ids with zero matching `studio` — control: dev,
serve, login, logout, register and whoami are all present in the same
enumeration, so the check is not vacuous. From the outside, `os studio
--help` exits 2 with `Error: Command studio not found.`
The row is deleted rather than rewritten. Studio is not reached by a CLI
command at all — the console serves it at /_console/studio after `os dev` or
`os serve`, both of which this same table already lists. A replacement row
would reintroduce the category error that made this one wrong: a Commands
table lists commands, and a browser route is not one.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019siH5jDmk5hrayvfyojUqR
… just fired
Part of #11221 — the second half of the commit before it.
environments.test.ts's #10967 pin carries a self-retiring EXCLUDED map. Its
header states the design: register.ts / whoami.ts / logout.ts are carved out
of the main assertion, and a second it.each re-runs the same predicate over
exactly those files asserting an unresolved entry is still there — "when
#11221's fix removes the last one, that assertion goes red on purpose, and
the failure message says to delete the entry."
Measured, with only the previous commit applied: 3 failed | 68 passed (71),
each failure reading "register.ts no longer has an unresolved examples entry
-- remove it from EXCLUDED above so it is scanned like every other command
source." After retiring: 71 passed (71), all three now covered by the main
assertion instead of exempted.
Retirement shape follows the precedent this file names as its own
(packages/create-objectstack/src/starter-comments-self-contained.test.ts,
#11022): the map goes back to empty, the retiring assertion stays so the next
entry is held to the same self-retirement, and the header records that it
fired.
See the PR body for the file-ownership check behind touching this file.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019siH5jDmk5hrayvfyojUqR
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/cli, touching 6 documentable anchor(s).

2 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/deployment/cli.mdx(via os logout (command), os register (command), os whoami (command))
  • content/docs/permissions/authentication.mdx(via os register (command))
What this run could not see
  • 1 changed file(s) yielded no anchor (packages/cli/README.md) — pages documenting those are invisible to this run
  • 4 name(s) were too generic to anchor anything (single lowercase words)

Coarse fallback — 23 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json ab23c67abc2c99db9b58e70d46c438cd2c47151cpackageMentionDocs.

Which tree this was computed on

This run read content/docs from d75d144077239f8f09118fdc77d89fd91b641c37 — the merge of head bc08f9bbc91579cf6379a04d90d9b6153d6bbfd1 into base ab23c67abc2c99db9b58e70d46c438cd2c47151c, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin d75d144077239f8f09118fdc77d89fd91b641c37 && git checkout d75d144077239f8f09118fdc77d89fd91b641c37
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin ab23c67abc2c99db9b58e70d46c438cd2c47151c bc08f9bbc91579cf6379a04d90d9b6153d6bbfd1 && git checkout -B drift-repro ab23c67abc2c99db9b58e70d46c438cd2c47151c && git merge --no-ff bc08f9bbc91579cf6379a04d90d9b6153d6bbfd1
node scripts/docs-audit/affected-docs.mjs --json ab23c67abc2c99db9b58e70d46c438cd2c47151c

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs ab23c67abc2c99db9b58e70d46c438cd2c47151c → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tests tooling labels Aug 23, 2026
@os-zhuangos-zhuang changed the title cli: every documented os auth <cmd> / os studio invocation now names a command that resolvescli: every documented os auth / os studio invocation now names a command that resolvesAug 23, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review August 23, 2026 10:14
@os-zhuang
os-zhuang added this pull request to the merge queueAug 23, 2026
Merged via the queue into main with commit e278a29Aug 23, 2026
38 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-11221-cli-documented-commands-resolve branch August 23, 2026 10:26
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/mteststooling

Projects

None yet

2 participants

@os-zhuang@claude