fix(parse): stop losing a flag that is missing its value - #807
Conversation
Three of the divergences the conformance corpus recorded, all of them the parser quietly discarding something. `ex --jobs` parsed successfully with nothing bound, so a forgotten value looked like a working command — and `ex --jobs --force` bound `force` while dropping `jobs` without a word. A full parse now reports it. `parse_partial` deliberately does not: a half-typed `--jobs ` is exactly what a completion is asked about, which is why the pending flag is left in the output rather than raised there. `-j=8` bound `=8`, because the value was taken as everything after the letter. One `=` between the letter and the value is a separator, matching the long form; `-j==8` still means `=8`. `--jobs=` bound nothing at all, collapsing "given empty" into "not given" — the two were told apart by whether an `=` was written, rather than by whether anything followed it. The corpus is how each of these was verified: fixing them made it report five labels as stale, and deleting those labels is the whole workflow. Eleven divergences remain, two of which need a decision rather than a patch and are marked as such in PLAN.md. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Warning Review limit reached
Next review available in: 24 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Central YAML (base), Organization UI (inherited) Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (6)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 550c2b9. Configure here.
Greptile SummaryThe PR corrects three argv parsing divergences while preserving partial-parse behavior for completions.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains; the previously reported empty-suffix positional leak is prevented by the new argument-aware queue condition and covered by a focused corpus vector. Important Files Changed
Reviews (2): Last reviewed commit: "fix(parse): do not queue an empty value ..." | Re-trigger Greptile |
Telling `--jobs=` apart from `--jobs` by whether an `=` was written also started queueing the empty text after `--force=`, where the flag holds no value and has nothing to do with it — leaving a stray empty word to be read as a positional. An empty value now reaches only a flag that takes one. A non-empty value on a flag that takes none is left as it was, which is a separate question the corpus does not answer yet. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Fixed. Telling An empty value now reaches only a flag that takes one, with a corpus vector pinning AI-assisted — Tool: Claude Code; model: anthropic/claude-fable-5; version: unavailable. |
Instruction countsNothing was compared, and so nothing was gated. No series appears on both sides: either the base has no measurements recorded, or the two were measured on different runner classes, which are deliberately not comparable — counts shift between machine types by more than a real regression does. New, nothing to compare against: Only instruction counts gate. Wall clock is shown for context — on identical hardware it moves 4-20% run to run. Measured by tak — instruction-counted CLI benchmarks, stored in this repository's git notes.
|
|
Both remaining threads here are re-posts of the empty-suffix finding, which is fixed in Green and ready. AI-assisted — Tool: Claude Code; model: anthropic/claude-fable-5; version: unavailable. |

First of the parser fixes, taking you at your word that these are bugs that went unnoticed because the parser is mostly used for completions.
Three divergences the corpus recorded, all of them the parser quietly discarding something:
ex --jobsparsed fine and bound nothing. A forgotten value looked like a working command, andex --jobs --forceboundforcewhile droppingjobssilently. Now an error.Worth noting where the check went:
parse, notparse_partial. A half-typed--jobsis exactly what a completion is asked about, so the pending flag stays in the partial output and only a full parse — which has nothing left to wait for — treats it as a failure. That distinction is whyParseOutput::flag_awaiting_valueexists, so the fix is two lines and a comment rather than a new code path.-j=8bound=8. The value was taken as everything after the letter. One=between letter and value is a separator, matching the long form;-j==8still means=8.--jobs=bound nothing, collapsing "given empty" into "not given". The two are now told apart by whether an=was written rather than by whether anything followed it.The corpus did its job
Fixing these made the suite report five labels as stale — "you claimed usage-lib diverges here, it now agrees, delete the label" — which is the workflow the corpus was built for. Deleting them takes the recorded divergences from 16 to 11.
One test needed rethinking rather than updating: it asserted usage-argv resolves "at least a dozen" divergences, which was a floor that shrinks every time usage-lib gets fixed. An empty set would mean the reference caught up entirely, which is the goal, so the floor is gone and the per-vector assertion carries the weight.
Two I did not touch, because they need your call
Unrecognized flags fall through to positionals (
ex --watbinds--watto an argument). This is the root of most remaining divergences, but mise parses task arguments with this parser at run time —usage::Parser::new(&spec).parse(&args)insrc/task/mod.rs— so rejecting an undeclared flag changes what a task accepts, not just what a completion offers. That could break tasks that pass arbitrary flags through today.A repeated
--is eaten. The grammar says only the first is a separator. Buttest_double_dashes_without_preserveasserts the current behavior explicitly, anddouble_dash="preserve"exists precisely to keep separators — which makes "the default consumes them all" look like a deliberate design rather than an oversight. I reverted my fix for this one when that test failed. If your reading is that the spec's design wins, the corpus vector changes instead of the parser.Both are marked Needs a decision in
PLAN.md.AI-assisted — Tool: Claude Code; model: anthropic/claude-fable-5; version: unavailable.
Note
Medium Risk
Changes real argv binding and errors for full parses (including mise task argument parsing), though completions stay on parse_partial; behavior is intentional and corpus-backed.
Overview
Aligns usage-lib parsing with the argv grammar on three flag-binding bugs that previously showed up only in the conformance corpus.
Missing flag values now fail in full
parsewhen a value-taking flag ends without a value (e.g.ex --jobs,ex --jobs --force), usingflag_awaiting_valueafter partial parsing.parse_partialis unchanged so half-typed flags still work for completions.Attached
=semantics are fixed: long--jobs=binds an empty string (distinct from omitting the flag); boolean--force=no longer leaves a stray empty positional; short-j=8binds8by treating a single leading=as a separator (long-form parity).The corpus drops stale usage-lib divergence labels on the affected vectors, adds coverage for
--force=, bumps in-scope vector count, and relaxes the conformance test that required resolving “at least a dozen” divergences. PLAN.md and docs/spec/argv.md record remaining open decisions (unknown flags → positionals, repeated--).Reviewed by Cursor Bugbot for commit 22703a2. Bugbot is set up for automated code reviews on this repo. Configure here.