From 644cdcfc63adb22bda32835b5d708f63f2f3f293 Mon Sep 17 00:00:00 2001 From: "warp-agent-staging[bot]" <240773466+warp-agent-staging[bot]@users.noreply.github.com> Date: Sun, 23 Aug 2026 21:38:44 +0000 Subject: [PATCH 1/2] Fix multi-arg option modelling: git branch/switch, code --diff 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) [] ') git switch -c/--create, -C/--force-create ('-c, --[no-]create ' 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[=] 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. --- command-signatures/json/code-insiders.json | 12 +- command-signatures/json/code.json | 12 +- command-signatures/json/git.json | 129 ++++++---------- command-signatures/json/hub.json | 166 ++++++--------------- 4 files changed, 95 insertions(+), 224 deletions(-) diff --git a/command-signatures/json/code-insiders.json b/command-signatures/json/code-insiders.json index 24a53007..ef2ad8cf 100644 --- a/command-signatures/json/code-insiders.json +++ b/command-signatures/json/code-insiders.json @@ -14,17 +14,7 @@ "-d", "--diff" ], - "description": "Compare two files with each other", - "args": [ - { - "name": "file", - "template": "filepaths" - }, - { - "name": "file", - "template": "filepaths" - } - ] + "description": "Compare two files with each other" }, { "name": [ diff --git a/command-signatures/json/code.json b/command-signatures/json/code.json index 783fe5e0..587246ac 100644 --- a/command-signatures/json/code.json +++ b/command-signatures/json/code.json @@ -15,17 +15,7 @@ "-d", "--diff" ], - "description": "Compare two files with each other", - "args": [ - { - "name": "file", - "template": "filepaths" - }, - { - "name": "file", - "template": "filepaths" - } - ] + "description": "Compare two files with each other" }, { "name": [ diff --git a/command-signatures/json/git.json b/command-signatures/json/git.json index 991e6091..7f12b390 100644 --- a/command-signatures/json/git.json +++ b/command-signatures/json/git.json @@ -6788,27 +6788,11 @@ "-m", "--move" ], - "description": "Move/rename a branch and its reflog", - "args": [ - { - "generatorName": "local_branches" - }, - { - "generatorName": "local_branches" - } - ] + "description": "Move/rename a branch and its reflog" }, { "name": "-M", - "description": "Move/rename a branch, even if target exists", - "args": [ - { - "generatorName": "local_branches" - }, - { - "generatorName": "local_branches" - } - ] + "description": "Move/rename a branch, even if target exists" }, { "name": [ @@ -6958,17 +6942,21 @@ "--no-track" ], "description": "When creating a new branch, set up 'upstream' configuration", - "args": [ - { - "name": "branch", - "generatorName": "local_branches" - }, - { - "name": "start point", - "isOptional": true, - "generatorName": "commits" - } - ] + "args": { + "name": "mode", + "description": "Tracking mode (default: direct)", + "isOptional": true, + "suggestions": [ + { + "name": "direct", + "description": "Track the start-point branch itself" + }, + { + "name": "inherit", + "description": "Copy the upstream configuration of the start-point branch" + } + ] + } }, { "name": "--no-track", @@ -6976,16 +6964,7 @@ "--track", "-t" ], - "description": "Do not set up 'upstream' configuration, even if the branch.autoSetupMerge configuration variable is true", - "args": [ - { - "generatorName": "local_branches" - }, - { - "isOptional": true, - "generatorName": "local_branches" - } - ] + "description": "Do not set up 'upstream' configuration, even if the branch.autoSetupMerge configuration variable is true" }, { "name": [ @@ -7049,7 +7028,14 @@ "--color" ] } - ] + ], + "args": { + "name": "branch-name", + "description": "Branch operand(s): [] when creating, [] with -m/-M/-c/-C, ... with -d/-D, or [...] with --list", + "isOptional": true, + "isVariadic": true, + "generatorName": "local_branches" + } }, { "name": "checkout", @@ -8336,16 +8322,9 @@ "--create" ], "description": "Create a new branch named starting at before switching to the branch", - "args": [ - { - "name": "new branch" - }, - { - "name": "start point", - "isOptional": true, - "generatorName": "commits" - } - ] + "args": { + "name": "new branch" + } }, { "name": [ @@ -8353,16 +8332,9 @@ "--force-create" ], "description": "Similar to --create except that if already exists it will be reset to ", - "args": [ - { - "name": "new branch" - }, - { - "name": "start point", - "isOptional": true, - "generatorName": "commits" - } - ] + "args": { + "name": "new branch" + } }, { "name": [ @@ -8436,17 +8408,21 @@ "--no-track" ], "description": "When creating a new branch, set up 'upstream' configuration", - "args": [ - { - "name": "branch", - "generatorName": "local_branches" - }, - { - "name": "start point", - "isOptional": true, - "generatorName": "commits" - } - ] + "args": { + "name": "mode", + "description": "Tracking mode (default: direct)", + "isOptional": true, + "suggestions": [ + { + "name": "direct", + "description": "Track the start-point branch itself" + }, + { + "name": "inherit", + "description": "Copy the upstream configuration of the start-point branch" + } + ] + } }, { "name": "--no-track", @@ -8454,16 +8430,7 @@ "--track", "-t" ], - "description": "Do not set up 'upstream' configuration, even if the branch.autoSetupMerge configuration variable is true", - "args": [ - { - "generatorName": "local_branches" - }, - { - "isOptional": true, - "generatorName": "local_branches" - } - ] + "description": "Do not set up 'upstream' configuration, even if the branch.autoSetupMerge configuration variable is true" }, { "name": "--orphan", diff --git a/command-signatures/json/hub.json b/command-signatures/json/hub.json index 7c3edcd4..7df3d49d 100644 --- a/command-signatures/json/hub.json +++ b/command-signatures/json/hub.json @@ -6401,39 +6401,11 @@ "-m", "--move" ], - "description": "Move/rename a branch and its reflog", - "args": [ - { - "generators": { - "script": "git --no-optional-locks branch --no-color --sort=-committerdate", - "postProcess": "_NuFrRa_t=>{let{insertWithoutRemotes:i=!1}=o,r=l(t);return r.startsWith(\"fatal:\")?[]:r.split(`\n`).filter(a=>!a.trim().startsWith(\"HEAD\")).map(a=>{let s=a.trim(),n=a.match(/\\S+/g);if(n.length>1){if(n[0]===\"*\")return a.includes(\"HEAD detached\")?null:{name:a.replace(\"*\",\"\").trim(),description:\"Current branch\",priority:100,icon:\"\\u2B50\\uFE0F\"};n[0]===\"+\"&&(s=a.replace(\"+\",\"\").trim())}let c=\"Branch\";return i&&s.startsWith(\"remotes/\")&&(s=s.slice(s.indexOf(\"/\",8)+1),c=\"Remote branch\"),{name:s,description:c,icon:\"fig://icon?type=git\",priority:75}})}" - } - }, - { - "generators": { - "script": "git --no-optional-locks branch --no-color --sort=-committerdate", - "postProcess": "_NuFrRa_t=>{let{insertWithoutRemotes:i=!1}=o,r=l(t);return r.startsWith(\"fatal:\")?[]:r.split(`\n`).filter(a=>!a.trim().startsWith(\"HEAD\")).map(a=>{let s=a.trim(),n=a.match(/\\S+/g);if(n.length>1){if(n[0]===\"*\")return a.includes(\"HEAD detached\")?null:{name:a.replace(\"*\",\"\").trim(),description:\"Current branch\",priority:100,icon:\"\\u2B50\\uFE0F\"};n[0]===\"+\"&&(s=a.replace(\"+\",\"\").trim())}let c=\"Branch\";return i&&s.startsWith(\"remotes/\")&&(s=s.slice(s.indexOf(\"/\",8)+1),c=\"Remote branch\"),{name:s,description:c,icon:\"fig://icon?type=git\",priority:75}})}" - } - } - ] + "description": "Move/rename a branch and its reflog" }, { "name": "-M", - "description": "Move/rename a branch, even if target exists", - "args": [ - { - "generators": { - "script": "git --no-optional-locks branch --no-color --sort=-committerdate", - "postProcess": "_NuFrRa_t=>{let{insertWithoutRemotes:i=!1}=o,r=l(t);return r.startsWith(\"fatal:\")?[]:r.split(`\n`).filter(a=>!a.trim().startsWith(\"HEAD\")).map(a=>{let s=a.trim(),n=a.match(/\\S+/g);if(n.length>1){if(n[0]===\"*\")return a.includes(\"HEAD detached\")?null:{name:a.replace(\"*\",\"\").trim(),description:\"Current branch\",priority:100,icon:\"\\u2B50\\uFE0F\"};n[0]===\"+\"&&(s=a.replace(\"+\",\"\").trim())}let c=\"Branch\";return i&&s.startsWith(\"remotes/\")&&(s=s.slice(s.indexOf(\"/\",8)+1),c=\"Remote branch\"),{name:s,description:c,icon:\"fig://icon?type=git\",priority:75}})}" - } - }, - { - "generators": { - "script": "git --no-optional-locks branch --no-color --sort=-committerdate", - "postProcess": "_NuFrRa_t=>{let{insertWithoutRemotes:i=!1}=o,r=l(t);return r.startsWith(\"fatal:\")?[]:r.split(`\n`).filter(a=>!a.trim().startsWith(\"HEAD\")).map(a=>{let s=a.trim(),n=a.match(/\\S+/g);if(n.length>1){if(n[0]===\"*\")return a.includes(\"HEAD detached\")?null:{name:a.replace(\"*\",\"\").trim(),description:\"Current branch\",priority:100,icon:\"\\u2B50\\uFE0F\"};n[0]===\"+\"&&(s=a.replace(\"+\",\"\").trim())}let c=\"Branch\";return i&&s.startsWith(\"remotes/\")&&(s=s.slice(s.indexOf(\"/\",8)+1),c=\"Remote branch\"),{name:s,description:c,icon:\"fig://icon?type=git\",priority:75}})}" - } - } - ] + "description": "Move/rename a branch, even if target exists" }, { "name": [ @@ -6586,23 +6558,21 @@ "--no-track" ], "description": "When creating a new branch, set up 'upstream' configuration", - "args": [ - { - "name": "branch", - "generators": { - "script": "git --no-optional-locks branch --no-color --sort=-committerdate", - "postProcess": "_NuFrRa_t=>{let{insertWithoutRemotes:i=!1}=o,r=l(t);return r.startsWith(\"fatal:\")?[]:r.split(`\n`).filter(a=>!a.trim().startsWith(\"HEAD\")).map(a=>{let s=a.trim(),n=a.match(/\\S+/g);if(n.length>1){if(n[0]===\"*\")return a.includes(\"HEAD detached\")?null:{name:a.replace(\"*\",\"\").trim(),description:\"Current branch\",priority:100,icon:\"\\u2B50\\uFE0F\"};n[0]===\"+\"&&(s=a.replace(\"+\",\"\").trim())}let c=\"Branch\";return i&&s.startsWith(\"remotes/\")&&(s=s.slice(s.indexOf(\"/\",8)+1),c=\"Remote branch\"),{name:s,description:c,icon:\"fig://icon?type=git\",priority:75}})}" - } - }, - { - "name": "start point", - "isOptional": true, - "generators": { - "script": "git --no-optional-locks log --oneline", - "postProcess": "function(o){let t=l(o);return t.startsWith(\"fatal:\")?[]:t.split(`\n`).map(i=>({name:i.substring(0,7),icon:\"fig://icon?type=node\",description:i.substring(7)}))}" + "args": { + "name": "mode", + "description": "Tracking mode (default: direct)", + "isOptional": true, + "suggestions": [ + { + "name": "direct", + "description": "Track the start-point branch itself" + }, + { + "name": "inherit", + "description": "Copy the upstream configuration of the start-point branch" } - } - ] + ] + } }, { "name": "--no-track", @@ -6610,22 +6580,7 @@ "--track", "-t" ], - "description": "Do not set up 'upstream' configuration, even if the branch.autoSetupMerge configuration variable is true", - "args": [ - { - "generators": { - "script": "git --no-optional-locks branch --no-color --sort=-committerdate", - "postProcess": "_NuFrRa_t=>{let{insertWithoutRemotes:i=!1}=o,r=l(t);return r.startsWith(\"fatal:\")?[]:r.split(`\n`).filter(a=>!a.trim().startsWith(\"HEAD\")).map(a=>{let s=a.trim(),n=a.match(/\\S+/g);if(n.length>1){if(n[0]===\"*\")return a.includes(\"HEAD detached\")?null:{name:a.replace(\"*\",\"\").trim(),description:\"Current branch\",priority:100,icon:\"\\u2B50\\uFE0F\"};n[0]===\"+\"&&(s=a.replace(\"+\",\"\").trim())}let c=\"Branch\";return i&&s.startsWith(\"remotes/\")&&(s=s.slice(s.indexOf(\"/\",8)+1),c=\"Remote branch\"),{name:s,description:c,icon:\"fig://icon?type=git\",priority:75}})}" - } - }, - { - "isOptional": true, - "generators": { - "script": "git --no-optional-locks branch --no-color --sort=-committerdate", - "postProcess": "_NuFrRa_t=>{let{insertWithoutRemotes:i=!1}=o,r=l(t);return r.startsWith(\"fatal:\")?[]:r.split(`\n`).filter(a=>!a.trim().startsWith(\"HEAD\")).map(a=>{let s=a.trim(),n=a.match(/\\S+/g);if(n.length>1){if(n[0]===\"*\")return a.includes(\"HEAD detached\")?null:{name:a.replace(\"*\",\"\").trim(),description:\"Current branch\",priority:100,icon:\"\\u2B50\\uFE0F\"};n[0]===\"+\"&&(s=a.replace(\"+\",\"\").trim())}let c=\"Branch\";return i&&s.startsWith(\"remotes/\")&&(s=s.slice(s.indexOf(\"/\",8)+1),c=\"Remote branch\"),{name:s,description:c,icon:\"fig://icon?type=git\",priority:75}})}" - } - } - ] + "description": "Do not set up 'upstream' configuration, even if the branch.autoSetupMerge configuration variable is true" }, { "name": [ @@ -6701,7 +6656,13 @@ "--color" ] } - ] + ], + "args": { + "name": "branch-name", + "description": "Branch operand(s): [] when creating, [] with -m/-M/-c/-C, ... with -d/-D, or [...] with --list", + "isOptional": true, + "isVariadic": true + } }, { "name": "checkout", @@ -8007,19 +7968,9 @@ "--create" ], "description": "Create a new branch named starting at before switching to the branch", - "args": [ - { - "name": "new branch" - }, - { - "name": "start point", - "isOptional": true, - "generators": { - "script": "git --no-optional-locks log --oneline", - "postProcess": "function(o){let t=l(o);return t.startsWith(\"fatal:\")?[]:t.split(`\n`).map(i=>({name:i.substring(0,7),icon:\"fig://icon?type=node\",description:i.substring(7)}))}" - } - } - ] + "args": { + "name": "new branch" + } }, { "name": [ @@ -8027,19 +7978,9 @@ "--force-create" ], "description": "Similar to --create except that if already exists it will be reset to ", - "args": [ - { - "name": "new branch" - }, - { - "name": "start point", - "isOptional": true, - "generators": { - "script": "git --no-optional-locks log --oneline", - "postProcess": "function(o){let t=l(o);return t.startsWith(\"fatal:\")?[]:t.split(`\n`).map(i=>({name:i.substring(0,7),icon:\"fig://icon?type=node\",description:i.substring(7)}))}" - } - } - ] + "args": { + "name": "new branch" + } }, { "name": [ @@ -8112,23 +8053,21 @@ "--no-track" ], "description": "When creating a new branch, set up 'upstream' configuration", - "args": [ - { - "name": "branch", - "generators": { - "script": "git --no-optional-locks branch --no-color --sort=-committerdate", - "postProcess": "_NuFrRa_t=>{let{insertWithoutRemotes:i=!1}=o,r=l(t);return r.startsWith(\"fatal:\")?[]:r.split(`\n`).filter(a=>!a.trim().startsWith(\"HEAD\")).map(a=>{let s=a.trim(),n=a.match(/\\S+/g);if(n.length>1){if(n[0]===\"*\")return a.includes(\"HEAD detached\")?null:{name:a.replace(\"*\",\"\").trim(),description:\"Current branch\",priority:100,icon:\"\\u2B50\\uFE0F\"};n[0]===\"+\"&&(s=a.replace(\"+\",\"\").trim())}let c=\"Branch\";return i&&s.startsWith(\"remotes/\")&&(s=s.slice(s.indexOf(\"/\",8)+1),c=\"Remote branch\"),{name:s,description:c,icon:\"fig://icon?type=git\",priority:75}})}" - } - }, - { - "name": "start point", - "isOptional": true, - "generators": { - "script": "git --no-optional-locks log --oneline", - "postProcess": "function(o){let t=l(o);return t.startsWith(\"fatal:\")?[]:t.split(`\n`).map(i=>({name:i.substring(0,7),icon:\"fig://icon?type=node\",description:i.substring(7)}))}" + "args": { + "name": "mode", + "description": "Tracking mode (default: direct)", + "isOptional": true, + "suggestions": [ + { + "name": "direct", + "description": "Track the start-point branch itself" + }, + { + "name": "inherit", + "description": "Copy the upstream configuration of the start-point branch" } - } - ] + ] + } }, { "name": "--no-track", @@ -8136,22 +8075,7 @@ "--track", "-t" ], - "description": "Do not set up 'upstream' configuration, even if the branch.autoSetupMerge configuration variable is true", - "args": [ - { - "generators": { - "script": "git --no-optional-locks branch --no-color --sort=-committerdate", - "postProcess": "_NuFrRa_t=>{let{insertWithoutRemotes:i=!1}=o,r=l(t);return r.startsWith(\"fatal:\")?[]:r.split(`\n`).filter(a=>!a.trim().startsWith(\"HEAD\")).map(a=>{let s=a.trim(),n=a.match(/\\S+/g);if(n.length>1){if(n[0]===\"*\")return a.includes(\"HEAD detached\")?null:{name:a.replace(\"*\",\"\").trim(),description:\"Current branch\",priority:100,icon:\"\\u2B50\\uFE0F\"};n[0]===\"+\"&&(s=a.replace(\"+\",\"\").trim())}let c=\"Branch\";return i&&s.startsWith(\"remotes/\")&&(s=s.slice(s.indexOf(\"/\",8)+1),c=\"Remote branch\"),{name:s,description:c,icon:\"fig://icon?type=git\",priority:75}})}" - } - }, - { - "isOptional": true, - "generators": { - "script": "git --no-optional-locks branch --no-color --sort=-committerdate", - "postProcess": "_NuFrRa_t=>{let{insertWithoutRemotes:i=!1}=o,r=l(t);return r.startsWith(\"fatal:\")?[]:r.split(`\n`).filter(a=>!a.trim().startsWith(\"HEAD\")).map(a=>{let s=a.trim(),n=a.match(/\\S+/g);if(n.length>1){if(n[0]===\"*\")return a.includes(\"HEAD detached\")?null:{name:a.replace(\"*\",\"\").trim(),description:\"Current branch\",priority:100,icon:\"\\u2B50\\uFE0F\"};n[0]===\"+\"&&(s=a.replace(\"+\",\"\").trim())}let c=\"Branch\";return i&&s.startsWith(\"remotes/\")&&(s=s.slice(s.indexOf(\"/\",8)+1),c=\"Remote branch\"),{name:s,description:c,icon:\"fig://icon?type=git\",priority:75}})}" - } - } - ] + "description": "Do not set up 'upstream' configuration, even if the branch.autoSetupMerge configuration variable is true" }, { "name": "--orphan", From 93826919ef0b62f3c791e96c085ce448bf50835c Mon Sep 17 00:00:00 2001 From: "warp-agent-staging[bot]" <240773466+warp-agent-staging[bot]@users.noreply.github.com> Date: Sun, 23 Aug 2026 21:58:19 +0000 Subject: [PATCH 2/2] Revert --track to a boolean flag in git branch and git switch 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 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. --- command-signatures/json/git.json | 34 ++------------------------------ command-signatures/json/hub.json | 34 ++------------------------------ 2 files changed, 4 insertions(+), 64 deletions(-) diff --git a/command-signatures/json/git.json b/command-signatures/json/git.json index 7f12b390..9758411b 100644 --- a/command-signatures/json/git.json +++ b/command-signatures/json/git.json @@ -6941,22 +6941,7 @@ "exclusiveOn": [ "--no-track" ], - "description": "When creating a new branch, set up 'upstream' configuration", - "args": { - "name": "mode", - "description": "Tracking mode (default: direct)", - "isOptional": true, - "suggestions": [ - { - "name": "direct", - "description": "Track the start-point branch itself" - }, - { - "name": "inherit", - "description": "Copy the upstream configuration of the start-point branch" - } - ] - } + "description": "When creating a new branch, set up 'upstream' configuration" }, { "name": "--no-track", @@ -8407,22 +8392,7 @@ "exclusiveOn": [ "--no-track" ], - "description": "When creating a new branch, set up 'upstream' configuration", - "args": { - "name": "mode", - "description": "Tracking mode (default: direct)", - "isOptional": true, - "suggestions": [ - { - "name": "direct", - "description": "Track the start-point branch itself" - }, - { - "name": "inherit", - "description": "Copy the upstream configuration of the start-point branch" - } - ] - } + "description": "When creating a new branch, set up 'upstream' configuration" }, { "name": "--no-track", diff --git a/command-signatures/json/hub.json b/command-signatures/json/hub.json index 7df3d49d..bc4b1ce0 100644 --- a/command-signatures/json/hub.json +++ b/command-signatures/json/hub.json @@ -6557,22 +6557,7 @@ "exclusiveOn": [ "--no-track" ], - "description": "When creating a new branch, set up 'upstream' configuration", - "args": { - "name": "mode", - "description": "Tracking mode (default: direct)", - "isOptional": true, - "suggestions": [ - { - "name": "direct", - "description": "Track the start-point branch itself" - }, - { - "name": "inherit", - "description": "Copy the upstream configuration of the start-point branch" - } - ] - } + "description": "When creating a new branch, set up 'upstream' configuration" }, { "name": "--no-track", @@ -8052,22 +8037,7 @@ "exclusiveOn": [ "--no-track" ], - "description": "When creating a new branch, set up 'upstream' configuration", - "args": { - "name": "mode", - "description": "Tracking mode (default: direct)", - "isOptional": true, - "suggestions": [ - { - "name": "direct", - "description": "Track the start-point branch itself" - }, - { - "name": "inherit", - "description": "Copy the upstream configuration of the start-point branch" - } - ] - } + "description": "When creating a new branch, set up 'upstream' configuration" }, { "name": "--no-track",