Spec multi-arg audit: git and the editor diff options - #342
Conversation
Audit of options declaring two or more args, for the git and editor-diff
group. Each verdict was checked against the tool's own ground truth.
Operands written into the option (option is a boolean flag; the extra
args duplicate the command's positionals):
git branch -m/--move, -M, --no-track (git branch -h; git-branch(1)
synopsis 'git branch (-m|-M) [<old-branch>] <new-branch>')
git switch -c/--create, -C/--force-create
('-c, --[no-]create <branch>' takes exactly one value; the
start-point is an operand of switch)
git switch --no-track
code -d/--diff, code-insiders -d/--diff
(microsoft/vscode argv.ts: "diff" is type:'boolean'; its 'args'
field is only read by formatUsage for help rendering, and the two
paths are collected into argv._)
A value set enumerated as args:
git branch -t/--track, git switch -t/--track
('-t, --[no-]track[=(direct|inherit)]') collapse to one optional
argument carrying direct/inherit as suggestions, matching the
sibling --color[=<when>] shape already used in this spec.
git branch had no top-level args of its own, so simply removing the
option args would have dropped branch-name completion entirely. Added
the documented operand as a variadic positional so it still resolves.
git config --get-urlmatch and --get-color are genuinely two-valued
('get value specific for the URL: section[.var] URL' and 'find the
color configured: slot [default]') and are left untouched.
hub.json is a stale Fig-derived copy of the git spec that ships for the
hub command, so it carries the same defects and gets the same fixes.
Its arg generators are inline Fig JavaScript, which Warp does not
deserialize, so no generatorName was introduced there.
|
This PR was generated with Warp. Comment |
Review finding on the revision: --track's direct|inherit value is legal only when attached. Verified both forms -- git branch --track=direct attached start succeeds git branch --track direct spaced start prints usage git's parse-options marks the option OPTION_OPTARG. A plain optional argument models the space-separated form, so carrying direct/inherit as suggestions would complete a command git rejects. The schema cannot express attached-only today: CommandOption.requires_equals is deserialized in fig_types.rs but dropped by From<CommandOption> for Opt, and Opt has no such field, so the flag never reaches the completer. Leave the option boolean in all four places (git branch and git switch, in both git.json and hub.json). Suggesting nothing beats suggesting an invalid command. Recorded in the PR body as unmodellable rather than merely omitted, so it does not get 'fixed' back.
|
I'm starting a first review of this pull request. You can view the conversation on Warp. I completed the review and no human review was requested for this pull request. Comment Powered by Oz |
There was a problem hiding this comment.
Per-hunk reasoning, inline below, so the evidence sits next to the change instead of only in the description.
Ground truth was git 2.43.0's own -h output, run in this environment — no git man pages were installed, so the synopses were cross-checked against git-scm.com. For VS Code, code could not be installed here, so the authority is the option table in src/vs/platform/environment/node/argv.ts in microsoft/vscode.
Two options in scope are deliberately absent from the diff. Both were checked and are genuinely two-valued, per git config -h:
--get-urlmatch [name, url]—--[no-]get-urlmatch get value specific for the URL: section[.var] URL--get-color [name, default]—--[no-]get-color find the color configured: slot [default], the second value optional, matching the spec'sisOptionalexactly.
They sit roughly 6,000 lines from the nearest hunk in git.json, and GitHub only accepts inline comments on lines inside the diff, so that note is here rather than anchored.
Responding as wilson: Open session · View in factory
| "template": "filepaths" | ||
| } | ||
| ] | ||
| "description": "Compare two files with each other" |
There was a problem hiding this comment.
VS Code's parser treats --diff as a mode flag, so the two paths are never consumed by the option. argv.ts:104: 'diff': { type: 'boolean', cat: 'o', alias: 'd', args: ['file', 'file'], … } — type: 'boolean' puts diff into booleanOptions, which is handed to minimist(args, { boolean: booleanOptions, … }) at argv.ts:328, so both paths land in argv._.
The args field is read only by formatUsage (argv.ts:400-408) to render the help line; --merge on the next line is also type: 'boolean' with four "args", which settles that it is help metadata rather than option values. code's top-level variadic filepaths+folders positional already serves the operands, so nothing is lost.
| "template": "filepaths" | ||
| } | ||
| ] | ||
| "description": "Compare two files with each other" |
There was a problem hiding this comment.
Same option, same source: code-insiders is the Insiders build of the same CLI and shares argv.ts. Reasoning is on the code.json hunk.
| "generatorName": "local_branches" | ||
| } | ||
| ] | ||
| "description": "Move/rename a branch and its reflog" |
There was a problem hiding this comment.
Both are listed by git branch -h with no value placeholder — -m, --[no-]move move/rename a branch and its reflog and -M move/rename a branch, even if target exists — so neither consumes a value. The two branch names are operands of the command, per the usage line git branch [<options>] (-m | -M) [<old-branch>] <new-branch>; they keep their local_branches completions through the subcommand positional added further down this file.
| "generatorName": "commits" | ||
| } | ||
| ] | ||
| "description": "When creating a new branch, set up 'upstream' configuration" |
There was a problem hiding this comment.
git branch -h: -t, --[no-]track[=(direct|inherit)]. The value set is direct|inherit — never a branch and a start point, which is what the removed args claimed.
It stays a bare flag rather than becoming a one-value option because git accepts the value only when attached: git branch --track=direct attached start succeeds, git branch --track direct spaced start prints usage (parse-options marks it OPTION_OPTARG). We cannot express attachment today — requires_equals is dropped by From<CommandOption> for Opt (fig_types.rs:485-499) and Opt (signature.rs:169-176) has no such field — so offering direct/inherit at a space-separated position would confidently complete a command git rejects.
| "generatorName": "local_branches" | ||
| } | ||
| ] | ||
| "description": "Do not set up 'upstream' configuration, even if the branch.autoSetupMerge configuration variable is true" |
There was a problem hiding this comment.
The negated half of -t, --[no-]track[=(direct|inherit)] takes no value at all. The two local_branches args it carried were the command's own operands, from git branch [--track[=(direct|inherit)] | --no-track] [-f] [--recurse-submodules] <branch-name> [<start-point>].
| ] | ||
| } | ||
| ] | ||
| ], |
There was a problem hiding this comment.
Mirrors the git branch positional added in git.json, with one deliberate difference: no generatorName. hub has no registered generator set in generators/mod.rs, so a name here would satisfy all_referenced_generators_exist — that test pools generator names across all commands — while resolving to nothing at runtime.
| } | ||
| } | ||
| ] | ||
| "args": { |
There was a problem hiding this comment.
Mirrors git switch -c in git.json.
| } | ||
| } | ||
| ] | ||
| "args": { |
There was a problem hiding this comment.
Mirrors git switch -C in git.json.
| } | ||
| } | ||
| ] | ||
| "description": "When creating a new branch, set up 'upstream' configuration" |
There was a problem hiding this comment.
Mirrors git switch --track in git.json.
| } | ||
| } | ||
| ] | ||
| "description": "Do not set up 'upstream' configuration, even if the branch.autoSetupMerge configuration variable is true" |
There was a problem hiding this comment.
Mirrors git switch --no-track in git.json.
There was a problem hiding this comment.
Overview
This PR updates static command signature metadata for VS Code diff flags and git branch/switch options by removing option-level args that represent command operands or help-only metadata, and by adding a branch positional operand so branch-name completion is not dropped.
Concerns
- No blocking correctness concerns found in the annotated diff.
- Security pass found no issues: the changes are static JSON metadata only, with no new executable code, dependencies, auth paths, input handling, or secrets.
- Spec alignment was not applicable because
spec_context.mdcontains no approved or repository spec context. - Comment/test audit: no code comments or tests were added or changed in the diff.
Verdict
Found: 0 critical, 0 important, 0 suggestions
Approve
Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).
Powered by Oz
<!-- warp:pr-description-artifacts start --> <!-- warp:pr-description-artifacts end --> ## Description Bumps the `warp-command-signatures` git dependency from `564724f` to `d3725aa`, bringing the four merged spec-audit PRs into the app on top of the already-merged `ln` fix (#341, which landed via #15480). **What moved:** `Cargo.toml` rev `564724f` → `d3725aa`, plus the two matching `Cargo.lock` entries (`warp-command-signatures`, `warp-completion-metadata`). No other lockfile entries change. **Commits in range (`564724f..d3725aa`):** exactly four — - Spec multi-arg audit: git and the editor diff options (warpdotdev/command-signatures#342) - Fix mis-modelled multi-arg options: text, data and file utility specs (#343) - Fix multi-arg option modelling: build systems and language tooling (#344) - Fix mis-modelled multi-arg options: ecosystem CLIs and macOS tools (#345) (The full `ac69f9b..d3725aa` range is the five-PR audit; #341 is already in the app via #15480, so this bump carries the remaining four.) ### What changes for users - `date -f`, `hugo new -k`, and the `git branch` / `git switch` options stop carrying the command's own operands as their arguments (the same modelling error the `ln` fix corrected, now fixed across these too). - `rsync --info` and `--debug` collapse to a single comma-separated argument, and `--debug` gains the 27 flags it never had. - `rustc -L` now inserts `dependency=` instead of a bare, invalid `dependency`. - `dart format`'s `--show` and `--summary` are modelled as real options again. - `lpass`'s boolean options offer `true` and `false`. - `unzip -0` and `rustc --l` disappear — they are flags that don't actually exist. - **Deliberate loss:** `pmset`'s setting/value pair is no longer modelled. This is the one visible regression in the batch and is intentional — the previous modelling was wrong, and no correct arity was available to replace it. All four audit PRs were validated in the real GUI before merge. The `make` variadic fix (`make.json`) came out of that validation, which is why a `make` change rides along in a batch that is otherwise about option arity. ## Linked Issue - [x] The linked issue is labeled `ready-to-spec` or `ready-to-implement`. - [x] Where appropriate, screenshots or a short video of the implementation are included below (especially for user-visible or UI changes). ## Testing - `cargo metadata --locked` passes — the minimal lockfile (only the two command-signatures entries bumped) is in sync with the new rev. - `cargo nextest run -p warp_completer --locked` corpus-backed tests pass against the new specs, including `test_all_known_signature_names_are_within_the_length_cap` (iterates the whole embedded corpus) and the `bundle`/`kubectl`/`sudo` registry tests. No corpus-backed test shifts. - [x] I have manually tested my changes locally with `./script/run` ## Agent Mode - [x] Warp Agent Mode - This PR was created via Warp's AI Agent Mode CHANGELOG-BUG-FIX: Fixed completions for many commands' multi-argument options that were mis-modelled (e.g. `git branch`/`git switch`, `rsync --info`/`--debug`, `rustc -L`, `dart format`, `hugo new`, `date`), so they no longer offer the wrong arguments. Co-authored-by: warp-agent-staging[bot] <240773466+warp-agent-staging[bot]@users.noreply.github.com>
<!-- warp:pr-description-artifacts start --> <!-- warp:pr-description-artifacts end --> ## Description Bumps the `warp-command-signatures` git dependency from `564724f` to `d3725aa`, bringing the four merged spec-audit PRs into the app on top of the already-merged `ln` fix (warpdotdev#341, which landed via warpdotdev#15480). **What moved:** `Cargo.toml` rev `564724f` → `d3725aa`, plus the two matching `Cargo.lock` entries (`warp-command-signatures`, `warp-completion-metadata`). No other lockfile entries change. **Commits in range (`564724f..d3725aa`):** exactly four — - Spec multi-arg audit: git and the editor diff options (warpdotdev/command-signatures#342) - Fix mis-modelled multi-arg options: text, data and file utility specs (warpdotdev#343) - Fix multi-arg option modelling: build systems and language tooling (warpdotdev#344) - Fix mis-modelled multi-arg options: ecosystem CLIs and macOS tools (warpdotdev#345) (The full `ac69f9b..d3725aa` range is the five-PR audit; warpdotdev#341 is already in the app via warpdotdev#15480, so this bump carries the remaining four.) ### What changes for users - `date -f`, `hugo new -k`, and the `git branch` / `git switch` options stop carrying the command's own operands as their arguments (the same modelling error the `ln` fix corrected, now fixed across these too). - `rsync --info` and `--debug` collapse to a single comma-separated argument, and `--debug` gains the 27 flags it never had. - `rustc -L` now inserts `dependency=` instead of a bare, invalid `dependency`. - `dart format`'s `--show` and `--summary` are modelled as real options again. - `lpass`'s boolean options offer `true` and `false`. - `unzip -0` and `rustc --l` disappear — they are flags that don't actually exist. - **Deliberate loss:** `pmset`'s setting/value pair is no longer modelled. This is the one visible regression in the batch and is intentional — the previous modelling was wrong, and no correct arity was available to replace it. All four audit PRs were validated in the real GUI before merge. The `make` variadic fix (`make.json`) came out of that validation, which is why a `make` change rides along in a batch that is otherwise about option arity. ## Linked Issue - [x] The linked issue is labeled `ready-to-spec` or `ready-to-implement`. - [x] Where appropriate, screenshots or a short video of the implementation are included below (especially for user-visible or UI changes). ## Testing - `cargo metadata --locked` passes — the minimal lockfile (only the two command-signatures entries bumped) is in sync with the new rev. - `cargo nextest run -p warp_completer --locked` corpus-backed tests pass against the new specs, including `test_all_known_signature_names_are_within_the_length_cap` (iterates the whole embedded corpus) and the `bundle`/`kubectl`/`sudo` registry tests. No corpus-backed test shifts. - [x] I have manually tested my changes locally with `./script/run` ## Agent Mode - [x] Warp Agent Mode - This PR was created via Warp's AI Agent Mode CHANGELOG-BUG-FIX: Fixed completions for many commands' multi-argument options that were mis-modelled (e.g. `git branch`/`git switch`, `rsync --info`/`--debug`, `rustc -L`, `dart format`, `hugo new`, `date`), so they no longer offer the wrong arguments. Co-authored-by: warp-agent-staging[bot] <240773466+warp-agent-staging[bot]@users.noreply.github.com>



Audit of the options in this group that declare two or more
args, part of the corpus-wide pass following thelnfix in #341. Group: git and the editor diff options.The completer resolves the last declared arg of a multi-arg option regardless of which value is being typed, so a mis-modelled option actively breaks completion. Every verdict below was checked against the tool's own ground truth before anything was edited.
Ground truth used
git branch -h,git switch -h,git config -h. No git man pages were installed, so the synopses were cross-checked against https://git-scm.com/docs/git-branch and https://git-scm.com/docs/git-switch.codeis not installable here, so the official parser definition was used —src/vs/platform/environment/node/argv.tsinmicrosoft/vscode.Why git appears twice
The scan found the git options in two files because two specs describe git:
command-signatures/json/git.json— the maintained spec, using RustgeneratorNamereferences.command-signatures/json/hub.json— a stale Fig-derived copy of the same spec (its internal"name"is literally"git", and it carries no hub-specific subcommands). Lookup inassets.rsis by filename, so this file is what ships for thehubcommand, which proxies git. Both are real and both are fixed here.One difference matters: every arg in
hub.jsoncarries inline Fig JavaScriptgenerators, a field the RustArgstruct incompletion-metadata/src/fig_types.rsdoes not deserialize. Those args therefore produce no suggestions at all today. NogeneratorNamewas introduced inhub.json, becausehubhas no registered generator set ingenerators/mod.rs— a name there would passall_referenced_generators_exist(which pools names across all commands) but resolve to nothing at runtime.Options changed
git branch -m/--movegit.json,hub.jsongit branch -h:-m, --[no-]move move/rename a branch and its reflog, listed under "Specific git-branch actions" with no value placeholder. Usage line:git branch [<options>] (-m | -M) [<old-branch>] <new-branch>— the two names are operands ofgit branch.git branch -Mgit.json,hub.jsongit branch -h:-M move/rename a branch, even if target exists— no value placeholder; same usage line.git branch --no-trackgit.json,hub.jsongit branch -h:-t, --[no-]track[=(direct|inherit)]— the negated form takes no value. Its twolocal_branchesargs were the<branch-name> [<start-point>]operands fromgit branch [--track[=(direct|inherit)] | --no-track] [-f] [--recurse-submodules] <branch-name> [<start-point>].git branch -t/--trackgit.json,hub.jsongit branch -h:-t, --[no-]track[=(direct|inherit)]. The declared[branch, start point]was wrong on both counts: the value set isdirect|inherit, and those two names are the command's operands. The args are removed and the option left boolean — see "The--trackvalue is unmodellable today" below for why it does not become a one-argument option.git switch -c/--creategit.json,hub.jsongit switch -h:-c, --[no-]create <branch>— exactly one value. Synopsis:git switch [<options>] (-c|-C) <new-branch> [<start-point>]— the start-point is an operand ofswitch.git switch -C/--force-creategit.json,hub.jsongit switch -h:-C, --[no-]force-create <branch>— exactly one value; same synopsis line.git switch -t/--trackgit.json,hub.jsongit switch -h:-t, --[no-]track[=(direct|inherit)]. Same treatment as thegit branchcopy: args removed, option left boolean.git switch --no-trackgit.json,hub.json--no-trackwith no value: "Do not set up 'upstream' configuration…". Its args were duplicates of switch's own positionals.code -d/--diffcode.jsonmicrosoft/vscode,src/vs/platform/environment/node/argv.ts:104:'diff': { type: 'boolean', cat: 'o', alias: 'd', args: ['file', 'file'], … }.typeis'boolean', sodiffgoes intobooleanOptionsand is passed tominimist(args, { boolean: booleanOptions, … })(argv.ts:328); the two paths land inargv._. Theargsfield is read only byformatUsage(argv.ts:400-408) to render the help line.--mergein the same table is alsotype: 'boolean'with four "args", which confirms the field is help-text metadata rather than option values.code-insiders -d/--diffcode-insiders.jsoncode-insidersis the Insiders build of the same CLI.One structural addition
git branchhad no top-levelargsin either spec, so removing the option args alone would have dropped branch-name completion outright —git branch -m ⇥would have offered nothing. The documented operand was therefore added to thebranchsubcommand as an optional variadicbranch-name, per the synopsis forms in git-branch(1). Ingit.jsonit carriesgeneratorName: local_branches(the same generator the removed option args used, so today's suggestions are preserved); inhub.jsonit carries no generator, for the reason above.The
--trackvalue is unmodellable today — please do not "fix" this back--trackdoes acceptdirectorinherit, so it is tempting to model it as a single optional argument carrying those two suggestions. That would be wrong, and the omission here is deliberate.git's
parse-optionsmarks--trackasOPTION_OPTARG, so the value is legal only when attached. Both forms were run to confirm:git branch --track=direct attached start— succeeds.git branch --track direct spaced start— prints usage and fails.A normal optional argument in this schema models the space-separated form, so suggesting
direct/inheritthere would confidently complete a command git rejects. The schema cannot express the attached-only form either:CommandOption.requires_equalsexists incompletion-metadata/src/fig_types.rs(deserialized fromrequiresEquals), butFrom<CommandOption> for Opt(fig_types.rs:485-499) copies onlyname,description,args,is_requiredandpriority—requires_equalsis silently dropped.Optitself (completion-metadata/src/signature.rs:169-176) has no such field, so the information cannot reach the completer at all.Until
requiresEqualsis plumbed through toOpt, suggesting nothing beats suggesting an invalid command.--tracktherefore stays boolean in all four places.Options verified as correct and left alone
git config --get-urlmatch [name, url]git config -h:--[no-]get-urlmatch get value specific for the URL: section[.var] URL— two values.git config --get-color [name, default]git config -h:--[no-]get-color find the color configured: slot [default]— two values, the second optional. Matches the spec's[name, default (isOptional)]exactly.Other residuals
Nothing in this group was left unresolved for lack of ground truth. Two further things a reviewer should know:
git switch -c <name> ⇥loses thecommitsgenerator. Before the fix, the second declared arg (start point,generatorName: commits) was what the completer resolved — meaning you gotgit log --onelinehashes while typing the new branch name, which is the bug. After the fix, the start-point operand falls through toswitch's own first positional, which offerslocal_branches+refs_remote_branchesrather than commits. Branches are valid start points, so this is a narrower suggestion set at that position, not a broken one. Wideningswitch's first positional to include commits would pollute plaingit switch <branch>, where a bare commit is not accepted, so it was left alone.git branch -mwas not user-visibly broken before, because both of its declared args were the identicallocal_branchesgenerator, so the last-arg bug produced the right answer by coincidence. The modelling was still wrong, and the fix keeps the same suggestions via the new top-level positional.Noticed outside this group, not touched
code/code-insiders-a/--addand-g/--gotoare the same class of error but declare a single arg, so they fell below the scan's two-or-more threshold.argv.ts:106,108declares bothtype: 'boolean'with help-onlyargs; their operands belong to the command, which already has a variadicfilepaths+folderspositional.git.jsonsets"requiresSeparator": trueongit log --diff-filter, butrequiresSeparatoris not a field onCommandOptionincompletion-metadata/src/fig_types.rs, so it is silently dropped at deserialization. Renaming it torequiresEqualswould not help, for the reason given above.Validation
cargo test -p warp-command-signatures— 176 passed, 0 failed. This coversall_command_specs_succeed_deserializationandall_referenced_generators_exist.npx prettier --checkon all four edited files — clean.Computer-use video recordings (1)
View video recording - GUI validation of this PR: typing
git branch,git branch -m,git branch -m feaandgit branch --track, showing branch names offered from the newly added positional in every form, with no duplicated pair.