Skip to content

Fail on unknown or malformed CLI options - #2

Merged
stromcom merged 1 commit into
masterfrom
fix/strict-cli-parsing
Aug 3, 2026
Merged

Fail on unknown or malformed CLI options#2
stromcom merged 1 commit into
masterfrom
fix/strict-cli-parsing

Conversation

@stromcom

@stromcom stromcom commented Aug 3, 2026

Copy link
Copy Markdown
Owner

InputParser silently ignored anything it did not recognise. Three consequences,
all of them "the report just isn't there and nothing tells you why":

input before now
--output-htlm=report.html (typo) flag dropped, exit 0, no report Error: Unknown option: --output-htlm — did you mean --output-html?, exit 3
--output-html report.html (space) path swallowed as the environment name works — value may be =-joined or the next argument
--output-html (no value) flag dropped, exit 0 Error: Option --output-html requires a value, exit 3
http-smoke dev report.html environment silently replaced Error: Unexpected argument "report.html" — environment is already set to "dev"
--concurrency=many parsed as 0 Error: Option --concurrency expects a whole number, got "many"
--var=TOKEN dropped Error: Option --var expects KEY=VALUE, got "TOKEN"

Options are now declared in FLAGS / VALUE_OPTIONS tables instead of a chain of
str_starts_with() calls with hand-counted substr() offsets. Problems are
collected in ParsedInput::$errors; RunCommand prints them with the help text
and returns ExitCode::UsageError (3), so CI fails loudly instead of quietly
producing no artefact.

No new dependency: symfony/console would give this for free, but the package
keeps psr/container as its only runtime dependency so it can drop into any
project as a --dev tool without console-framework version constraints. That
trade-off is now written down in docs/claude/conventions.md, together with the
rule that pays for it — the parser must never silently no-op.

Also documented in the README CLI reference (= vs space, hard-error behaviour).

Tests: tests/Unit/Console/InputParserTest.php (new, covers every option plus
each failure mode above). PHPStan max 0 errors, PHP-CS-Fixer clean, PHPUnit
117 tests / 342 assertions.

InputParser silently ignored anything it did not recognise, so a typo
(--output-htlm=report.html) or an option written with a space on an older
release skipped the report with exit code 0, and a value passed as the next
argument was swallowed as the environment name.

Options are now declared in FLAGS / VALUE_OPTIONS tables and both --opt=value
and --opt value are accepted. Unknown options (with a levenshtein "did you
mean" hint), missing or empty values, non-numeric numbers, malformed --var and
stray positional arguments are collected in ParsedInput::$errors; RunCommand
prints them with the help text and returns ExitCode::UsageError.
@stromcom
stromcom merged commit a3feed3 into master Aug 3, 2026
2 checks passed
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