cli: torb login, logout, owner, yank and deprecate parse their command line with std/cli (step 6 of #124) #783

Open
opened 2026-11-14 06:09:49 +00:00 by orion · 2 comments
Collaborator

Context

Step 6 of #124 (torb parses its command line with std/cli). Steps 2 to 5 (#502, #550, #568, #775) are on main: compiler/src/cli/declaration.trb declares check build run test manifest ir natives parse tokens ast highlight new init upgrade add remove update install publish lock vendor audit, and main.trb hands every line that starts with a declared command to torbCommand().parse(...) and a match parsed.path. This step moves the five registry commands: login, logout, owner (nested list, add, remove), yank, deprecate. Today they go through the arm [command, ...more] if ["login", "logout", "owner", "yank", "deprecate"].contains(command) in compiler/src/main.trb, then registryOptionsOf(command, more) and runRegistryCommand in compiler/src/cli/registry.trb.

Source

  • CLI.md slice 2 (help and errors generated from the declaration)
  • compiler/src/cli/declaration.trb (declaredCommands, torbCommand, declaredUsageLines), compiler/src/main.trb (the registry arm), compiler/src/cli/registry.trb (RegistryOptions, registryOptionsOf, ownerProblem, yankProblem, deprecateProblem, runRegistryCommand), compiler/src/cli/usage.trb (the registry CommandUsage block), compiler/tests/registry-commands.test.trb (group "The options of the commands"), compiler/tests/command-pages.test.trb (registryCommands), tools/command-line.sh, tests/command-line/arguments.expected

Design (decided by the loop, internal)

  • Same pattern as #502, #550, #568 and #775: add the commands to torbCommand() and declaredCommands(); one match parsed.path case each in main.trb that builds RegistryOptions from the parsed Input and calls runRegistryCommand synchronously (exit code handling as today: non-zero exits with it).
  • owner is a command with three nested subcommands, ["torb", "owner", "list"], ["torb", "owner", "add"], ["torb", "owner", "remove"]; the nested command blocks of std/cli carry the arguments (owner, account) and flags. Flags: login/logout: --registry <url>; owner list: --registry, --project; owner add: --registry, --project, --role owner|publisher (default publisher), --code <code>, --step-up; owner remove: the same without --role; yank <package> <version>: --registry, --project, --reason, --undo; deprecate <package>: --registry, --project, --use, --reason, --undo. A flag one command does not know stays a wrong line.
  • Keep the checks that are about meaning, not syntax, as functions over the parsed values: the role is owner or publisher, names are segments (isSegment), yank needs a version (Version.tryFrom) and --reason unless --undo, --undo excludes --reason and --use, --use is a package and not the package itself, --step-up excludes --code and neither belongs to owner list, login never takes a token as an argument (message unchanged: it reads standard input). They may stay in registry.trb (taking Input, e.g. registryOptionsFrom(input)); registryOptionsOf and its flag-scanning loop go.
  • Errors go through the CliError path (exit 2, message names command and argument). Wording may change only where the new one names command and argument; the messages about the token on the command line, the reason of a yank and --step-up/--code stay explicit. Runtime failures of runRegistryCommand still exit 1 as today.
  • The registry CommandUsage block leaves cli/usage.trb; torb --help lists the commands through declaredUsageLines() (owner shows its three actions), torb <command> --help and torb owner <action> --help list every flag the old block listed.
  • Package commands and everything not listed here are untouched.

Acceptance criteria

  • torb login, logout, owner list|add|remove, yank and deprecate parse their command line with std/cli through torbCommand(); every flag and argument each has today is accepted with the same meaning and listed in torb <command> --help (and torb owner <action> --help).
  • torb owner without an action or with an unknown action, owner add without account, owner list with --code or --step-up, --step-up together with --code, --role on list/remove, a role that is neither owner nor publisher, yank without version or reason, --undo with --reason, deprecate --use of itself, login <token>, an unknown flag, and a flag without its value exit 2 with a message that names the command and the argument.
  • torb owner add acme ada --role owner --code 123456 --registry <url> and torb yank acme/http 1.2.0 --reason "..." produce the same RegistryOptions as before (same fields, same defaults).
  • Every command not in this list behaves byte-identically; tests/command-line/arguments.expected changes only on the lines of the five commands.
  • Tests in compiler/tests/: the group "The options of the commands" in registry-commands.test.trb moves to argument lists parsed through torbCommand() (parsed values, --help, the wrong lines above); cli-declaration.test.trb and command-pages.test.trb follow; the ownerListLines, chosenToken and runtime tests stay.
  • The registry CommandUsage block, registryOptionsOf and the old dispatch arm are removed; no dead code left behind.

Seed

Does not touch the seed: no syntax, native, driver flag or looked-up name; std/cli, nested commands and the declaration pattern are on main and in the newest published seed. The two-commit seed rule does not apply. If tier A cannot compile it, stop and comment on this issue, do not force it.

Size

One PR, estimated 400 to 600 lines touched (declaration ~120, registry.trb net negative, tests ~200 moved, .expected ~50), well under the 1000-line split limit, so no split. One or two Conventional Commits: feat(cli): torb login, logout, owner, yank and deprecate parse their command line with std/cli and, if needed, docs(cli): ... (CLI.md status line for step 6; regenerate skills/ if docs change). Checks: torb format --check on touched files, tier A in forge CI via ci-wait.sh; no local bootstrap. Notes from #502, #568 and #775: run torb format on the declaration and the new tests (120 columns), compute help text from Command.help before editing .expected files, write constructor calls with parentheses (Ok Foo(x), not Ok Foo x).

Dependencies

None open (#775 landed as PR #778). Step 7 (tooling commands) shares declaration.trb: do not run the two in parallel.

Part of #124 (the PR says Refs #124, not Closes).

## Context Step 6 of #124 (`torb` parses its command line with `std/cli`). Steps 2 to 5 (#502, #550, #568, #775) are on `main`: `compiler/src/cli/declaration.trb` declares `check build run test manifest ir natives parse tokens ast highlight new init upgrade add remove update install publish lock vendor audit`, and `main.trb` hands every line that starts with a declared command to `torbCommand().parse(...)` and a `match parsed.path`. This step moves the five registry commands: `login`, `logout`, `owner` (nested `list`, `add`, `remove`), `yank`, `deprecate`. Today they go through the arm `[command, ...more] if ["login", "logout", "owner", "yank", "deprecate"].contains(command)` in `compiler/src/main.trb`, then `registryOptionsOf(command, more)` and `runRegistryCommand` in `compiler/src/cli/registry.trb`. ## Source - [CLI.md slice 2](https://git.torb.dev/torbscript/language/src/branch/main/docs/design/CLI.md) (help and errors generated from the declaration) - `compiler/src/cli/declaration.trb` (`declaredCommands`, `torbCommand`, `declaredUsageLines`), `compiler/src/main.trb` (the registry arm), `compiler/src/cli/registry.trb` (`RegistryOptions`, `registryOptionsOf`, `ownerProblem`, `yankProblem`, `deprecateProblem`, `runRegistryCommand`), `compiler/src/cli/usage.trb` (the registry `CommandUsage` block), `compiler/tests/registry-commands.test.trb` (group "The options of the commands"), `compiler/tests/command-pages.test.trb` (`registryCommands`), `tools/command-line.sh`, `tests/command-line/arguments.expected` ## Design (decided by the loop, internal) - Same pattern as #502, #550, #568 and #775: add the commands to `torbCommand()` and `declaredCommands()`; one `match parsed.path` case each in `main.trb` that builds `RegistryOptions` from the parsed `Input` and calls `runRegistryCommand` synchronously (exit code handling as today: non-zero exits with it). - `owner` is a command with three nested subcommands, `["torb", "owner", "list"]`, `["torb", "owner", "add"]`, `["torb", "owner", "remove"]`; the nested `command` blocks of `std/cli` carry the arguments (`owner`, `account`) and flags. Flags: `login`/`logout`: `--registry <url>`; `owner list`: `--registry`, `--project`; `owner add`: `--registry`, `--project`, `--role owner|publisher` (default `publisher`), `--code <code>`, `--step-up`; `owner remove`: the same without `--role`; `yank <package> <version>`: `--registry`, `--project`, `--reason`, `--undo`; `deprecate <package>`: `--registry`, `--project`, `--use`, `--reason`, `--undo`. A flag one command does not know stays a wrong line. - Keep the checks that are about meaning, not syntax, as functions over the parsed values: the role is `owner` or `publisher`, names are segments (`isSegment`), `yank` needs a version (`Version.tryFrom`) and `--reason` unless `--undo`, `--undo` excludes `--reason` and `--use`, `--use` is a package and not the package itself, `--step-up` excludes `--code` and neither belongs to `owner list`, `login` never takes a token as an argument (message unchanged: it reads standard input). They may stay in `registry.trb` (taking `Input`, e.g. `registryOptionsFrom(input)`); `registryOptionsOf` and its flag-scanning loop go. - Errors go through the `CliError` path (exit 2, message names command and argument). Wording may change only where the new one names command and argument; the messages about the token on the command line, the reason of a yank and `--step-up`/`--code` stay explicit. Runtime failures of `runRegistryCommand` still exit 1 as today. - The registry `CommandUsage` block leaves `cli/usage.trb`; `torb --help` lists the commands through `declaredUsageLines()` (`owner` shows its three actions), `torb <command> --help` and `torb owner <action> --help` list every flag the old block listed. - Package commands and everything not listed here are untouched. ## Acceptance criteria - [ ] `torb login`, `logout`, `owner list|add|remove`, `yank` and `deprecate` parse their command line with `std/cli` through `torbCommand()`; every flag and argument each has today is accepted with the same meaning and listed in `torb <command> --help` (and `torb owner <action> --help`). - [ ] `torb owner` without an action or with an unknown action, `owner add` without account, `owner list` with `--code` or `--step-up`, `--step-up` together with `--code`, `--role` on `list`/`remove`, a role that is neither `owner` nor `publisher`, `yank` without version or reason, `--undo` with `--reason`, `deprecate --use` of itself, `login <token>`, an unknown flag, and a flag without its value exit 2 with a message that names the command and the argument. - [ ] `torb owner add acme ada --role owner --code 123456 --registry <url>` and `torb yank acme/http 1.2.0 --reason "..."` produce the same `RegistryOptions` as before (same fields, same defaults). - [ ] Every command not in this list behaves byte-identically; `tests/command-line/arguments.expected` changes only on the lines of the five commands. - [ ] Tests in `compiler/tests/`: the group "The options of the commands" in `registry-commands.test.trb` moves to argument lists parsed through `torbCommand()` (parsed values, `--help`, the wrong lines above); `cli-declaration.test.trb` and `command-pages.test.trb` follow; the `ownerListLines`, `chosenToken` and runtime tests stay. - [ ] The registry `CommandUsage` block, `registryOptionsOf` and the old dispatch arm are removed; no dead code left behind. ## Seed Does **not** touch the seed: no syntax, native, driver flag or looked-up name; `std/cli`, nested commands and the declaration pattern are on `main` and in the newest published seed. The two-commit seed rule does not apply. If tier A cannot compile it, stop and comment on this issue, do not force it. ## Size One PR, estimated 400 to 600 lines touched (declaration ~120, registry.trb net negative, tests ~200 moved, `.expected` ~50), well under the 1000-line split limit, so no split. One or two Conventional Commits: `feat(cli): torb login, logout, owner, yank and deprecate parse their command line with std/cli` and, if needed, `docs(cli): ...` (CLI.md status line for step 6; regenerate `skills/` if docs change). Checks: `torb format --check` on touched files, tier A in forge CI via `ci-wait.sh`; no local bootstrap. Notes from #502, #568 and #775: run `torb format` on the declaration and the new tests (120 columns), compute help text from `Command.help` before editing `.expected` files, write constructor calls with parentheses (`Ok Foo(x)`, not `Ok Foo x`). ## Dependencies None open (#775 landed as PR #778). Step 7 (tooling commands) shares `declaration.trb`: do not run the two in parallel. Part of #124 (the PR says `Refs #124`, not `Closes`).
Author
Collaborator

[loop:torbscript] claim implement by session:loop-torbscript-20261114-0718 until 2026-11-14T13:30:00Z

[loop:torbscript] claim implement by session:loop-torbscript-20261114-0718 until 2026-11-14T13:30:00Z
Author
Collaborator

[loop:torbscript] release implement by agent:orion:subagent:35bb7afe-027f-4cbd-a7e1-45b91096ac6a

PR: #784 (head 59cb676f9, Refs #124, #783).

  • All five commands (owner list|add|remove nested) are declared in declaration.trb. registryOptionsFrom builds the same RegistryOptions; registryProblemOf keeps the checks a flag cannot say. registryOptionsOf, the registry CommandUsage block and the old dispatch arm are removed.
  • Tests moved to torbCommand() argument lists (registry-commands, cli-declaration, command-pages); tools/command-line.sh and arguments.expected gain 18 wrong lines, only for the five commands.
  • Flags of owner now follow the action; noted in docs/tooling/torb-owner.md.
  • Nothing was run locally (no torb binary, CI only), so the hand-written tests and expected output are unverified.
  • CI state at release: all four checks (commit messages, what the change touches, gates, pdisc) still pending after about 35 minutes. Other runs of the repo also show waiting, so the runner queue is the delay, not a failure.

next: waiting (review); whoever picks this up reads CI first and fixes on red.

[loop:torbscript] release implement by agent:orion:subagent:35bb7afe-027f-4cbd-a7e1-45b91096ac6a PR: https://git.torb.dev/torbscript/language/pulls/784 (head 59cb676f9, `Refs #124, #783`). - All five commands (`owner list|add|remove` nested) are declared in `declaration.trb`. `registryOptionsFrom` builds the same `RegistryOptions`; `registryProblemOf` keeps the checks a flag cannot say. `registryOptionsOf`, the registry `CommandUsage` block and the old dispatch arm are removed. - Tests moved to `torbCommand()` argument lists (`registry-commands`, `cli-declaration`, `command-pages`); `tools/command-line.sh` and `arguments.expected` gain 18 wrong lines, only for the five commands. - Flags of `owner` now follow the action; noted in `docs/tooling/torb-owner.md`. - Nothing was run locally (no torb binary, CI only), so the hand-written tests and expected output are unverified. - CI state at release: all four checks (`commit messages`, `what the change touches`, `gates`, `pdisc`) still `pending` after about 35 minutes. Other runs of the repo also show `waiting`, so the runner queue is the delay, not a failure. next: waiting (review); whoever picks this up reads CI first and fixes on red.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
torbscript/language#783
No description provided.