Skip to content

fix: reject non-boolean --matches-stack values instead of eating a positional - #47

Open
alerizzo wants to merge 1 commit into
mainfrom
fix/matches-stack-strict-parsing
Open

fix: reject non-boolean --matches-stack values instead of eating a positional#47
alerizzo wants to merge 1 commit into
mainfrom
fix/matches-stack-strict-parsing

Conversation

@alerizzo

@alerizzo alerizzo commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator

Follow-up to #45, which merged before this fix existed. The bug is on main but has not been released — the patterns-matches-stack changeset is still pending — so no user has seen it.

The bug

Commander's optional-value syntax ([value]) greedily consumes the next token, including one meant as a positional. patterns takes toolName as its 4th positional, so:

$ codacy patterns gh my-org my-repo --matches-stack eslint
Error: Ambiguous arguments for 'patterns'. Expected 1 or 4 positional arguments, got 3.

eslint was silently swallowed as the flag's value (matchesStack=true), and the error never mentions --matches-stack — so a user who did supply a tool name is told their positional count is wrong.

--matches-stack is the command's first optional-value option; every other option on patterns is either a plain boolean (never consumes a token) or a required-value <value> option (consumption is the point). Every test and doc example in #45 placed the flag after the tool name, so the broken ordering was never exercised.

The fix

A new strictBooleanOption() in src/utils/options.ts accepts only true/false and otherwise errors immediately:

error: option '-k, --matches-stack [value]' argument 'eslint' is invalid.
expected "true" or "false". If "eslint" was meant as an argument, place it
before --matches-stack, or pass --matches-stack on its own to mean true.

The three specified behaviours are unchanged: bare flag → true, truetrue, falsefalse.

Also drops a redundant tri-state re-derivation in patterns.ts — Commander already yields exactly true | false | undefined, so the value is now passed through directly.

Deliberately not changed

issues --false-positives [value] uses the lax parseBooleanOption and has the same swallow hazard (issues --false-positives gh org repo would eat gh). Switching it would change existing, shipped behaviour — --false-positives banana currently means true — so it's left alone and flagged as a follow-up in SPECS/commands/tools-and-patterns.md. Happy to do it here if you'd rather.

Test plan

  • npm run check-types — clean
  • npm test — 630 passing (was 625; +5)
  • Regression test asserts the bad ordering now throws and never reaches the API
  • Manual:
    codacy patterns gh org repo --matches-stack eslint   # clear error, names the flag
    codacy patterns eslint9 --matches-stack              # true
    codacy patterns eslint9 --matches-stack false        # false

Verified against codacy/codacy-cloud-cli / eslint9: true and false still return disjoint sets (100 vs 21 under --categories Security).

🤖 Generated with Claude Code

…sitional

Code review caught a real bug in the new flag. Commander's optional-value
syntax (`[value]`) greedily consumes the next token, so

    codacy patterns gh my-org my-repo --matches-stack eslint

parsed as matchesStack=true with `eslint` silently swallowed, and then failed
with "Ambiguous arguments for 'patterns'. Expected 1 or 4 positional
arguments, got 3." — an error that never mentions the flag that ate the tool
name. Every test and doc example placed the flag after the tool name, so the
broken ordering was never exercised.

`--matches-stack` now uses a new `strictBooleanOption()` that accepts only
true/false and otherwise errors immediately, naming the flag and the offending
value and saying where to put the argument. The three specified behaviours
(bare flag, explicit true, explicit false) are unchanged.

Also drops the redundant tri-state re-derivation in patterns.ts: Commander
already yields exactly true | false | undefined, so the value is passed
through directly.

`issues --false-positives` keeps the lax parser and the same latent hazard —
left alone to keep this change in scope, and flagged as a follow-up in
SPECS/commands/tools-and-patterns.md.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@codacy-production

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 13 complexity · 0 duplication

Metric Results
Complexity 13
Duplication 0

View in Codacy

AI Reviewer: first review requested successfully. AI can make mistakes. Always validate suggestions.

Run reviewer

TIP This summary will be updated as you push new changes.

@codacy-production codacy-production Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

No merge-blocking issues were identified. Codacy reports the PR is up to standards. The only noted gap is missing coverage for forwarding --matches-stack values in bulk update mode while excluding the filter from the post-update overview request.

Test suggestions

  • Strict parser accepts true and false, case-insensitively.
  • Strict parser rejects non-boolean and empty values with a descriptive InvalidArgumentError.
  • Misordered positional argument after --matches-stack fails before calling the patterns API.
  • Bare, true, and false matches-stack values preserve tri-state behavior in patterns list mode.
  • Matches-stack values are forwarded correctly in bulk update mode and excluded from the overview request.
Prompt proposal for missing tests
Consider implementing these tests if applicable:
1. Matches-stack values are forwarded correctly in bulk update mode and excluded from the overview request.

TIP How was this review? Give us feedback

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant