Skip to content

check: bare --frame-check swallows the next flag and misattributes the error to --caption-zone #2965

Description

@cauyxy

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 --jsonframe-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

  1. npx hyperframes init repro --non-interactive --example blank && cd repro
  2. npx hyperframes check --frame-check --caption-zone "x0=0;y0=.82;x1=1;y1=1"
  3. 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.
  4. 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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions