Repository navigation
Description
fleet(dispatch): duplicate and contradictory flags are silently resolved — last value wins, --no-* always beats --*
Summary
fleet dispatch launch / fleet dispatch enqueue parse their flags with a hand-rolled parser (pkgs/fleet/crates/fleet-dispatch/src/lib.rs) that silently discards user input in three ways:
- Duplicate value flags overwrite silently.
parse_argsstores each--flag valuewithvalues.insert(...)(lib.rs:555), so--repo developing-today/code --repo dezren39/darwin-nixlaunches against the second repo with no error or warning — the first value is silently dropped. - Contradictory boolean pairs resolve by check order, not argument order.
verb_launchtestsno-issuebeforeissueandno-waitbeforewait(lib.rs:638-649), so--issue --no-issueand--no-issue --issueboth sendissue: false. One of the two flags the user typed is silently ignored, whichever order they wrote them in. --prompt+--prompt-filetogether silently drop the prompt.prompt_of(lib.rs:580-587) prefers--prompt-filewhenever it is present; an explicitly typed--prompt <text>is discarded without a word.
This is the fleet CLI family's established silent-discard class (see #5568, #5572, #5592, #5603, #5607, #5652 — trailing/extra arguments silently ignored, each fixed to a usage error naming the argument). Duplicate and contradictory flags are the same failure one step earlier in parsing, with sharper consequences: launch creates real sessions, tracking issues, and queue tasks, so a silently-wrong --repo, a silently-dropped tracking issue (--issue overridden by a stray --no-issue), or a silently-substituted prompt acts on the wrong work instead of merely misreporting success.
Evidence (main @ af0847d, read via gh api raw; laptop unavailable this run — broker tunnel down, #5708)
pkgs/fleet/crates/fleet-dispatch/src/lib.rs:527-570—parse_args: value flags go into aMapviavalues.insert(name, ...)at :555 with no duplicate check; bool flags viaflags.insert(...)at :544. Unknown flags and missing values are usage errors — duplicates are the one malformed shape that is not.pkgs/fleet/crates/fleet-dispatch/src/lib.rs:638-649—verb_launch:if parsed.flag("no-issue") { issue=false } else if parsed.flag("issue") { issue=true }, and the same shape forno-wait/wait. Both members of a pair can be present simultaneously; the negative always wins regardless of order.pkgs/fleet/crates/fleet-dispatch/src/lib.rs:580-587—prompt_of:if let Some(path) = args.get("prompt-file") { read it }else require--prompt. Both supplied → the--prompttext never reaches the request body.pkgs/fleet/crates/fleet-dispatch/src/lib.rs:660-735—verb_enqueueshares the same parser and the sameprompt_of, so duplicates of--repo/--title/--issue-number/--dedupe-keyoverwrite silently there too.- The fleet-queue client parser has the same overwrite shape (
pkgs/fleet/crates/fleet-queue/src/client.rs:471-504,opts.insertat :487/:490) — noted as the sibling surface; this issue's fix is scoped to fleet-dispatch, and the queue parser can be aligned in the same change if the worker judges it in-scope, or filed separately.
Why it matters
fleet dispatch launch is the fleet's own session launcher: it POSTs to pm-dispatch, which creates a tracking issue and a queue task and starts an OpenCode session on the laptop. Silent flag resolution means a mistyped or scripted command can launch work against the wrong repository, skip the tracking issue the operator asked for, wait (or not wait) contrary to the flag they wrote last, or run a prompt read from a file instead of the text they typed — with exit 0 and no indication anything was overridden. Every sibling surface in this CLI family now errors on silently-discarded input; dispatch's parser is the remaining one that resolves it quietly.
Acceptance criteria
parse_argsin fleet-dispatch rejects a repeated value flag (--repo a --repo b, including the--repo=ainline form) with a usage error naming the flag, before any network call.verb_launchrejects--issuetogether with--no-issue, and--waittogether with--no-wait, with a usage error naming the contradictory pair, before any network call. (Rejecting a repeated identical bool flag is optional; the contradictory pair must error.)- Supplying both
--promptand--prompt-fileto launch or enqueue is a usage error naming both, instead of silently preferring the file. - Single, non-contradictory invocations behave exactly as today (including
--helpin any position, per fleet dispatch status silently ignores all arguments — --help performs a live GET /health and typos are swallowed #5560's verb help handling). - New pinning tests in the fleet-dispatch test module cover: duplicate value flag rejected, both contradictory pairs rejected in both orders, prompt+prompt-file rejected, and the ordinary single-flag controls still parse.
cargo test -p fleet-dispatchpasses on the laptop / in CI.
Related: #5560 (dispatch status args, fixed), #5555 (dispatch status endpoint gap), #5413 (absorb dispatch into repo-queue — if that lands first, the same rule should hold in the absorbing parser).
Activity
dezren39 commentedon Nov 5, 2026
🤖 Agent note · filed
134 remaining items
dezren39 commentedon Nov 6, 2026
🤖 Agent note · handed off
dezren39 commentedon Nov 6, 2026
🤖 Agent note · handed off
dezren39 commentedon Nov 6, 2026
Agent note — task 9818 handed off (lane code-g)
small_fix, issue fleet(dispatch): duplicate and contradictory flags silently resolved — repeated values overwrite, --no-* always beats --* #5713)opencode— handing off to the opencode claimant per the worker runbook; this lane did not work the issue directly.