Describe the bug
hyperframes check documents --frame-check as usable bare ("Bare --frame-check uses defaults…") or with a spec value. But the flag is declared as type: "string" in citty, and citty 0.2.2 consumes the next argv token as the value even when that token is another flag. So a bare --frame-check followed by any --prefixed flag swallows that flag:
--frame-check --caption-zone "x0=…" → frame-check becomes the string "--caption-zone" and the caption zone is silently dropped
--snapshots --samples 15 --frame-check --json → frame-check becomes "--json" and JSON output is silently disabled
The command then fails before the pipeline runs — and with a misleading error: parseFrameCheckFields reuses parseCaptionField, which throws captionZoneError() when the swallowed token has no =. The user sees Invalid --caption-zone; use "x0=0;y0=.82…" when the caption zone they wrote is perfectly valid (or when they never passed one at all).
Only orderings where bare --frame-check is the last token, or the --frame-check= / --frame-check <spec> forms, work. Existing tests only exercise those safe orderings, so this was never caught (packages/cli/src/commands/check.test.ts puts --frame-check last in its argv-level test).
Introduced in 659cb6a (feat(cli): --frame-check accepts a severity/seek/tol spec), which changed the flag from boolean to string. Previously reported in #2312 (closed unmerged in a backlog sweep with "Reopen only if a current reproducible case makes it a priority again" — we now have integrators hitting this when assembling argv arrays grouped by logical concern).
Link to reproduction
Reproduces in any project — no composition changes needed. npx hyperframes init repro --non-interactive --example blank is sufficient; the failure happens at argv parsing, before the pipeline touches the composition.
Steps to reproduce
npx hyperframes init repro --non-interactive --example blank && cd repro
npx hyperframes check --frame-check --caption-zone "x0=0;y0=.82;x1=1;y1=1"
- See
✗ Check failed: Invalid --caption-zone; use "x0=0;y0=.82;x1=1;y1=1[;severity=warning|error][;seek=.5,1]" with fractions from 0 to 1.
- Also:
npx hyperframes check --snapshots --samples 15 --frame-check --json → same class of failure, blamed on --caption-zone even though no caption zone was passed.
Expected behavior
Bare --frame-check enables frame checking with defaults regardless of where it appears in the argument list, as the help text promises. Any parse error in the --frame-check value is attributed to --frame-check, not --caption-zone.
Actual behavior
Bare --frame-check swallows the next flag: that flag's semantics are silently lost, and the run aborts with Invalid --caption-zone pointing at the wrong option.
Environment
Reproduced on current main (3cf268e) with the repo's installed citty 0.2.2, verified directly against citty's runCommand:
["--caption-zone","x0=…","--frame-check"] => fc="", OK (safe order)
["--frame-check","--caption-zone","x0=…"] => fc="--caption-zone" FAIL (zone dropped)
["--snapshots","--samples","15","--frame-check","--json"] => fc="--json" FAIL (json stays false)
["--frame-check=","--json"] => fc="", json=true OK
["--frame-check","severity=error","--caption-zone","x0=…"] => both correct OK
Additional context
Proposed fix (PR to follow): normalize rawArgs at the check command boundary — rewrite bare --frame-check followed by a --prefixed token (or at end) to --frame-check= — plus correct error attribution so frame-check spec errors throw Invalid --frame-check, and argv-order regression tests. --caption-zone and --layout are not affected in their documented usage (neither supports a bare form), but they get the same "value looks like a flag" guard for a clearer error when a value is accidentally omitted.
Describe the bug
hyperframes checkdocuments--frame-checkas usable bare ("Bare --frame-check uses defaults…") or with a spec value. But the flag is declared astype: "string"in citty, and citty 0.2.2 consumes the next argv token as the value even when that token is another flag. So a bare--frame-checkfollowed by any--prefixed flag swallows that flag:--frame-check --caption-zone "x0=…"→frame-checkbecomes the string"--caption-zone"and the caption zone is silently dropped--snapshots --samples 15 --frame-check --json→frame-checkbecomes"--json"and JSON output is silently disabledThe command then fails before the pipeline runs — and with a misleading error:
parseFrameCheckFieldsreusesparseCaptionField, which throwscaptionZoneError()when the swallowed token has no=. The user seesInvalid --caption-zone; use "x0=0;y0=.82…"when the caption zone they wrote is perfectly valid (or when they never passed one at all).Only orderings where bare
--frame-checkis the last token, or the--frame-check=/--frame-check <spec>forms, work. Existing tests only exercise those safe orderings, so this was never caught (packages/cli/src/commands/check.test.tsputs--frame-checklast in its argv-level test).Introduced in 659cb6a (
feat(cli): --frame-check accepts a severity/seek/tol spec), which changed the flag from boolean to string. Previously reported in #2312 (closed unmerged in a backlog sweep with "Reopen only if a current reproducible case makes it a priority again" — we now have integrators hitting this when assembling argv arrays grouped by logical concern).Link to reproduction
Reproduces in any project — no composition changes needed.
npx hyperframes init repro --non-interactive --example blankis sufficient; the failure happens at argv parsing, before the pipeline touches the composition.Steps to reproduce
npx hyperframes init repro --non-interactive --example blank && cd repronpx hyperframes check --frame-check --caption-zone "x0=0;y0=.82;x1=1;y1=1"✗ Check failed: Invalid --caption-zone; use "x0=0;y0=.82;x1=1;y1=1[;severity=warning|error][;seek=.5,1]" with fractions from 0 to 1.npx hyperframes check --snapshots --samples 15 --frame-check --json→ same class of failure, blamed on--caption-zoneeven though no caption zone was passed.Expected behavior
Bare
--frame-checkenables frame checking with defaults regardless of where it appears in the argument list, as the help text promises. Any parse error in the--frame-checkvalue is attributed to--frame-check, not--caption-zone.Actual behavior
Bare
--frame-checkswallows the next flag: that flag's semantics are silently lost, and the run aborts withInvalid --caption-zonepointing at the wrong option.Environment
Reproduced on current
main(3cf268e) with the repo's installed citty 0.2.2, verified directly against citty'srunCommand:Additional context
Proposed fix (PR to follow): normalize
rawArgsat thecheckcommand boundary — rewrite bare--frame-checkfollowed by a--prefixed token (or at end) to--frame-check=— plus correct error attribution so frame-check spec errors throwInvalid --frame-check, and argv-order regression tests.--caption-zoneand--layoutare not affected in their documented usage (neither supports a bare form), but they get the same "value looks like a flag" guard for a clearer error when a value is accidentally omitted.