Skip to content

Preserve dashed-literal contract while fail-closing on recognized-option-as-value (#184) - #455

Merged
Widthdom merged 3 commits into
mainfrom
fix/issue-184-cli-arg-validation
Apr 19, 2026
Merged

Preserve dashed-literal contract while fail-closing on recognized-option-as-value (#184)#455
Widthdom merged 3 commits into
mainfrom
fix/issue-184-cli-arg-validation

Conversation

@Widthdom

Copy link
Copy Markdown
Owner

Summary

  • Fail-close when a value-taking option is followed by another recognized CLI option instead of silently swallowing it (e.g. cdidx search hello --limit --lang rust now reports "--limit requires a value" cleanly instead of consuming --lang as the --limit value and failing numeric validation with a confusing "got '--lang'" message). The new IsRecognizedOptionToken guard fires in TryReadRawOptionValue unconditionally, and in TryReadStringOptionValue only when the option does NOT accept separated dash-prefixed literal values.
  • Preserve the pre-existing dashed-literal contract for --db, --path, --exclude-path, and --query: --db --json / --path --json / --exclude-path --json still fail closed with the inline-form hint (pass it as \--db=`), and --query --jsonstill accepts--jsonas literal query text. Use--query=` to disambiguate if a flag name collides with a literal query.
  • Emit Warning: <option> specified more than once; using the last value '<v>'. on every repeat of a non-repeatable value-taking option so scripted or copy-pasted duplicates are visible instead of silent take-last. --top is canonicalized to --limit, so --limit 5 --top 10 also warns. Repeatable options (--path, --exclude-path, --name) are deliberately excluded.
  • Regression locks: recognized-option-as-value short-circuit for every value-taking entrypoint (search, symbols, impact, …), duplicate-warning behavior for non-repeatable and repeatable options, dashed-literal hint preservation for --db / --path / --exclude-path, --query dashed-literal acceptance, and positive-integer validation for --focus-column / --max-line-width (zero and non-numeric fail closed). Updated bilingual CHANGELOG entries.

Closes #184.

Test plan

  • dotnet build (main project + tests project both clean)
  • dotnet test tests/CodeIndex.Tests/CodeIndex.Tests.csproj — 2150 passed, 2 skipped (long-running perf tests), 0 failed
  • Manual: cdidx search hello --limit --lang rust--limit requires a value
  • Manual: cdidx search foo --db --json--db requires a value. Hint: if the literal value starts with --, pass it as --db=<value>
  • Manual: cdidx find --query --json --path src/** --db <path> --json → parses --json as literal query text (no "requires a value" error)
  • Manual: cdidx search foo --limit 5 --limit 10Warning: --limit specified more than once; using the last value '10'.
  • Codex independent code review iteration 3: 言伝: 全件 accept

Widthdom and others added 3 commits April 19, 2026 06:13
QueryCommandRunner.ParseArgs previously let a value-taking option consume
the next recognized CLI flag (e.g. --json, --lang) as its value, silently
dropping the swallowed flag and surfacing a confusing numeric-parse error.
Add an IsRecognizedOptionToken guard in TryReadRawOptionValue and
TryReadStringOptionValue so the missing value is reported cleanly with
"<option> requires a value.". --query is exempted because its design
intentionally accepts dashed literals (use --query=<value> to disambiguate
if needed).

Also warn on repeat occurrences of non-repeatable value-taking options
(--db, --limit/--top, --lang, --query, --kind, --since, --start, --end,
--before, --after, --focus-line, --focus-column, --focus-length,
--snippet-lines, --max-line-width, --depth) so silent take-last overrides
become visible. Repeatable --path/--exclude-path/--name are unchanged.

Add regression locks for both the missing-value guard and duplicate
warnings, and update the three pre-existing missing-value tests whose
error message shifted from the downstream "requires a positive integer"
to the earlier "requires a value" short-circuit.

Closes #184

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…184)

Codex iteration 2 flagged that the new IsRecognizedOptionToken guard in
TryReadStringOptionValue short-circuited every option before the existing
IsRejectedSeparatedStringValue step, which silently broke the pre-existing
contract for options that legitimately accept separated dash-prefixed
literal values. `cdidx search foo --db --json` used to return
"--db requires a value. Hint: if the literal value starts with `--`,
pass it as `--db=<value>`." Now it must continue to return that hinted
error rather than the plain "requires a value" short-circuit.

Change TryReadStringOptionValue to apply the recognized-option guard only
when the option does NOT accept separated dash-prefixed literals. For
flags with allowSeparatedDashPrefixedLiteralValue=true (`--db`, `--path`,
`--exclude-path`, `--query`), the guard is skipped and the downstream
IsRejectedSeparatedStringValue flow still emits the inline-form hint for
double-dash values. The numeric TryReadRawOptionValue guard is unchanged
because numeric options never accept dashed literals.

Add regression tests:
- --db / --path / --exclude-path followed by --json must fail closed with
  the inline-form hint.
- --query followed by --json must accept --json as literal query text.
- --focus-column and --max-line-width must reject zero and non-numeric
  values with "requires a positive integer" (covers the positive-integer
  contract that the existing missing-value tests no longer prove after
  the short-circuit change).

Update the English and Japanese CHANGELOG entries to describe the new
contract: the guard is unconditional in TryReadRawOptionValue, but in
TryReadStringOptionValue it is gated on allowSeparatedDashPrefixedLiteralValue
so `--db --json` / `--path --json` / `--exclude-path --json` continue to
fail closed with the inline-form hint, and `--query --json` continues to
accept `--json` as literal query text.

All 2150 tests pass (2 skipped: long-running performance tests).
@Widthdom
Widthdom merged commit 8c3889f into main Apr 19, 2026
6 checks passed
@Widthdom
Widthdom deleted the fix/issue-184-cli-arg-validation branch April 24, 2026 13:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant