Repository navigation
fix(cli): a program option is read only before the command, so a value that begins with -v is never the version - #981
Merged
Conversation
…e that begins with -v is never the version
Merged
kid7st
added a commit
that referenced
this pull request
Nov 8, 2026
## Release v0.30.1 Bump `@fastagent-sh/fastagent` from 0.30.0 to 0.30.1. Two fixes to 0.30.0; nothing else. ## Fixed - **An argument after the command that begins with `-v` printed the version and did nothing** (#981). commander read the program's `-v, --version` anywhere in the arguments by default, so `fastagent invoke "-very urgent: …"`, `--name -vendor` and `invoke --session <id>` with an id beginning with `-v` (1 storage in 4096) printed `0.30.0` and exited 0 having done nothing. The program's options are now read only before the command, as `docs/cli.md` says; an operand that begins with `-` after the command is refused as an unknown option (exit 2). - **A stopped or replaced step could report the wrong end** (#980). Stopping a ticket's step (`--check <ticket> --stop`), replacing it with a newer attempt, or giving up on its start signalled the step and wrote the reason after; a step that heard the consequences first (its host CLI killed by the same signal, as `signal-exit` lets it on Linux) recorded its own failure, and that one stayed. A ticket's end is now written once, before what it decides is done, and nothing the step writes after reopens it. ## Verification - `npm run lint`, `npm run typecheck`, `npm test` (195 files, 2382 passed, 2 skipped), `npm pack --dry-run --json`. - The ticket and CLI tests also passed three times under load in a Linux container (Node 26.13.0), where the step-ordering failure was measured. ## After merge Create and publish the GitHub Release `v0.30.1` from the merged commit, with the sections above as its notes. The protected publish workflow verifies and publishes the package to npm via Trusted Publishing. This PR itself does not tag or publish.
25 of 31 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Root cause of
cli-invoke.test.ts's intermittent failure ("continues a served session with the model this run names", once on Node 26), and the fix.Root cause
commander reads a program option anywhere in the arguments by default, a subcommand's option values and operands included (its documented default;
enablePositionalOptions()turns it off). The program's only option is-v, --version. So any argument after the command that begins with-vprinted the version and exited 0, doing nothing:fastagent invoke --session -vQ2jhwjklm.3 hi0.30.0, exit 0, nothing sentfastagent invoke "-very urgent: summarize"0.30.0, exit 0fastagent content add --name -vendor ./x0.30.0, exit 0fastagent invoke --model -v hi0.30.0, exit 0A session id is the storage's incarnation (
randomBytes(8).toString("base64url")) and pi-durable's id, so every session of one storage begins with the same characters, and 1 storage in 4096 begins with-v. Then everyinvoke --session <id>against it printed the version: what the test saw as a second run with an empty stderr. Of the 64 base64url characters after a-, onlyvdoes this.The fix
program.enablePositionalOptions()in the kernel: a program option is read before the command and nowhere else, which is whatdocs/cli.mdalready says ("-v/--versioncomes before any command"). Nowinvoke --session -v…and--model -vgive the command their values, and an operand that begins with-after the command is refused as an unknown option (exit 2, with the message), not answered with the version.fastagent -v,--versionand each command's--helpare unchanged.Tests
cli-kernel.test.ts, throughbuildProgram: a value after the command that begins with-vreaches the command; an operand that does is refused as an unknown option, without the version;-vbefore the command is still the version. The first two failed before the fix (the version was printed, exit 0). Mutation: withoutenablePositionalOptions()both fail.Not reproduced by running the original test: it needs one storage in 4096, and 150 targeted runs and 10 shard runs in a Linux container (Node 26.13.0) did not draw one. The mechanism was found by trying the arguments it passes.