[PR #3811] [MERGED] fix(cli): accept --flag=value for global output flags #5916

Closed
opened 2026-10-31 01:10:25 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/3811
Author: @kaoru0822-kitauji
Created: 10/15/2026
Status: ✅ Merged
Merged: 10/15/2026
Merged by: @kaoru0822-kitauji

Base: main ← Head: fix/cli-equals-output-flags


📝 Commits (2)

  • dda7245 fix(cli): accept --flag=value for global output flags
  • 6c2ac83 fix(cli): detect missing output values while parsing output flags

📊 Changes

5 files changed (+137 additions, -25 deletions)

View changed files

📝 docs/cli.md (+3 -1)
📝 scripts/rea.mjs (+6 -4)
📝 src/cliOutput.ts (+47 -7)
📝 tests/boundary/cli/cliOutput.test.ts (+80 -12)
📝 tests/boundary/cli/dispatcher.test.ts (+1 -1)

📄 Description

Summary

rea <command> --format=json failed with Unknown flag: --format, and so did --filter-output=..., --token-limit=... and --token-offset=.... Command options already accept --flag=value (--table=t works), and rea mcp doctor parses --format= itself. Agents write the equals form often, so each such call failed and had to be retried.

A valued output flag with no value (--format as the last argument, or --format=) also failed with Unknown flag: --format and code UNKNOWN, which points at the wrong problem.

Now the equals forms behave exactly like the spaced forms. A missing value fails before the command runs with MISSING_OUTPUT_VALUE: --format requires a value, as in --format <value> or --format=<value>.

Problem and expected behavior

Incur extracts its global flags with exact token matches (token === '--format' && argv[i + 1]). An equals form, or a flag without a value, therefore passes through to the command's option parser, which reports the global flag as unknown. rea's parseCliOutputArguments mirrored that behavior on purpose, so rea's output validation agreed with what Incur would apply. The equals form was consistently ignored rather than honored.

Change and scope

  • src/cliOutput.ts, which owns output-argument interpretation, gains normalizeCliOutputArguments. It splits --format=V, --filter-output=V, --token-limit=V and --token-offset=V into the spaced form. Everything else is unchanged, including boolean flags, --json, command options and values that merely contain =.
  • scripts/rea.mjs passes the normalized argv to validateCliOutputArguments, createCliResultOutput, Incur serve and the empty-filter fallback. All four therefore read the same effective values, preserving the invariant the existing tests protect.
  • validateCliOutputArguments reports MISSING_OUTPUT_VALUE for a valued output flag that is last or followed by an empty value. This check runs after the existing filter-slice and token-window checks, so their precedence is unchanged.
  • docs/cli.md documents both forms and the new error.
  • Not included: mcp doctor, which has its own parser that already accepts --format=; command-local options; MCP.

Contract and boundary impact

  • Semantic owner and earliest changed stage: CLI output-argument interpretation (src/cliOutput.ts), applied at the entry point before Incur.
  • Contribution scope fit and linked maintainer decision: CLI usability/correctness fix; not applicable.
  • CLI and MCP/tool-catalog contract: previously rejected equals forms now work. There is a new pre-execution error code MISSING_OUTPUT_VALUE. Schemas and MCP are unchanged.
  • Provider, bridge, target-format, or platform compatibility: all CLI commands, all platforms.
  • Evidence, artifact, provenance, or reconstruction contract: unchanged.
  • Target selection, authority, upstream behavior, and cleanup details: unchanged.
  • Generated metadata, package, or installation impact: none.

Expected effects:

  • Documentation or usability only; no target interaction.

Evidence and regression coverage

  • Tests updated in tests/boundary/cli/cliOutput.test.ts, all through the compiled CLI:
    • Equals forms are now asserted as honored: --format=json --filter-output=capabilities[0,1] returns the filtered JSON, and --json --token-limit=5 is rejected as a token window exactly like the spaced form. The previous assertion, that --token-limit=5 was not an active builtin, encoded the old behavior.
    • The structured-error case now uses --format=json --token-limit=5.
    • Missing values for --format, --filter-output, --token-limit and --token-offset=, and a trailing --format, assert MISSING_OUTPUT_VALUE naming the flag.
  • Base reproduction: against the unfixed src/cliOutput.ts and scripts/rea.mjs, both updated tests fail (Tests 2 failed | 16 passed).
  • User-visible output before:
    $ rea inspect-plist /Applications/Ghostty.app --format=json
    code: UNKNOWN
    message: "Unknown flag: --format"
    
    After:
    $ rea inspect-plist /Applications/Ghostty.app --format=json --filter-output=normalized_result.bundle.identifier
    {"normalized_result":{"bundle":{"identifier":"com.mitchellh.ghostty"}}}
    $ rea inspect-plist /Applications/Ghostty.app --format=
    {"ok":false,"error":{"code":"MISSING_OUTPUT_VALUE","message":"--format requires a value, as in --format <value> or --format=<value>."}}
    
  • Remaining proof gaps: none known.

Validation performed

  • npm run test:focused -- tests/boundary/cli/cliOutput.test.ts tests/boundary/cli/closedStdout.test.ts tests/boundary/cli/jsonOutput.test.ts tests/boundary/cli/cliOptionAliases.test.ts: 65 passed
  • npm run test:focused -- tests/boundary/cli/mcpDoctorHelpCli.test.ts tests/boundary/cli/javascriptIntegrityPolicyCli.test.ts tests/boundary/cli/nativeUiScenarioInputCli.test.ts: 15 passed. These cover command-local "Unknown flag" errors, which are unchanged.
  • npm run check:fast: passed; npm run docs:check: passed
  • Real app on macOS (Darwin 25.6, arm64), against /Applications/Ghostty.app:
    • --format=json, --format=json --filter-output=... and --token-limit=20 now match their spaced forms.
    • --format=, a trailing --format, and --filter-output "" --format yaml give MISSING_OUTPUT_VALUE in the selected structured format.
    • --format=xml still gives Incur's Invalid format message.
  • Cost: argv normalization is linear in the argument count. For agents, it removes a failed call and retry per equals-form invocation.

Compatibility, safety, and release

  • Breaking changes or migration steps: none for valid invocations; previously failing invocations now succeed. A missing value still exits 1, now with MISSING_OUTPUT_VALUE instead of UNKNOWN.
  • Real Hopper/Ghidra, browser, or OS coverage: not applicable.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: none.

Author readiness

Human owner:

  • I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work.
  • I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps.
  • I declare this PR ready for initial maintainer review.

Before merge

  • This PR addresses a concrete problem or an agreed enhancement.
  • Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff.
  • The PR has one focused outcome and the title follows type(scope): outcome.
  • Related issue is linked, or the reason for not linking one is stated above. (Found by exercising the real CLI; no existing issue.)
  • Tests cover changed observable behavior and meaningful failure paths.
  • Owning docs, contracts, and generated metadata are updated where needed.
  • User-visible CLI/MCP changes include representative output.
  • I checked the final diff for secrets, unrelated cleanup, and unsupported claims.

🤖 Generated with Claude Code


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/3811 **Author:** [@kaoru0822-kitauji](https://github.com/kaoru0822-kitauji) **Created:** 10/15/2026 **Status:** ✅ Merged **Merged:** 10/15/2026 **Merged by:** [@kaoru0822-kitauji](https://github.com/kaoru0822-kitauji) **Base:** `main` ← **Head:** `fix/cli-equals-output-flags` --- ### 📝 Commits (2) - [`dda7245`](https://github.com/morluto/rea/commit/dda7245153cab916f36c83826fd2b2afa24028f2) fix(cli): accept --flag=value for global output flags - [`6c2ac83`](https://github.com/morluto/rea/commit/6c2ac83de6a51ffde1ec299fad7b93cb3611bf05) fix(cli): detect missing output values while parsing output flags ### 📊 Changes **5 files changed** (+137 additions, -25 deletions) <details> <summary>View changed files</summary> 📝 `docs/cli.md` (+3 -1) 📝 `scripts/rea.mjs` (+6 -4) 📝 `src/cliOutput.ts` (+47 -7) 📝 `tests/boundary/cli/cliOutput.test.ts` (+80 -12) 📝 `tests/boundary/cli/dispatcher.test.ts` (+1 -1) </details> ### 📄 Description ## Summary `rea <command> --format=json` failed with `Unknown flag: --format`, and so did `--filter-output=...`, `--token-limit=...` and `--token-offset=...`. Command options already accept `--flag=value` (`--table=t` works), and `rea mcp doctor` parses `--format=` itself. Agents write the equals form often, so each such call failed and had to be retried. A valued output flag with no value (`--format` as the last argument, or `--format=`) also failed with `Unknown flag: --format` and code `UNKNOWN`, which points at the wrong problem. Now the equals forms behave exactly like the spaced forms. A missing value fails before the command runs with `MISSING_OUTPUT_VALUE: --format requires a value, as in --format <value> or --format=<value>.` ## Problem and expected behavior Incur extracts its global flags with exact token matches (`token === '--format' && argv[i + 1]`). An equals form, or a flag without a value, therefore passes through to the command's option parser, which reports the global flag as unknown. rea's `parseCliOutputArguments` mirrored that behavior on purpose, so rea's output validation agreed with what Incur would apply. The equals form was consistently ignored rather than honored. ## Change and scope - `src/cliOutput.ts`, which owns output-argument interpretation, gains `normalizeCliOutputArguments`. It splits `--format=V`, `--filter-output=V`, `--token-limit=V` and `--token-offset=V` into the spaced form. Everything else is unchanged, including boolean flags, `--json`, command options and values that merely contain `=`. - `scripts/rea.mjs` passes the normalized argv to `validateCliOutputArguments`, `createCliResultOutput`, Incur `serve` and the empty-filter fallback. All four therefore read the same effective values, preserving the invariant the existing tests protect. - `validateCliOutputArguments` reports `MISSING_OUTPUT_VALUE` for a valued output flag that is last or followed by an empty value. This check runs after the existing filter-slice and token-window checks, so their precedence is unchanged. - `docs/cli.md` documents both forms and the new error. - Not included: `mcp doctor`, which has its own parser that already accepts `--format=`; command-local options; MCP. ## Contract and boundary impact - Semantic owner and earliest changed stage: CLI output-argument interpretation (`src/cliOutput.ts`), applied at the entry point before Incur. - Contribution scope fit and linked maintainer decision: CLI usability/correctness fix; not applicable. - CLI and MCP/tool-catalog contract: previously rejected equals forms now work. There is a new pre-execution error code `MISSING_OUTPUT_VALUE`. Schemas and MCP are unchanged. - Provider, bridge, target-format, or platform compatibility: all CLI commands, all platforms. - Evidence, artifact, provenance, or reconstruction contract: unchanged. - Target selection, authority, upstream behavior, and cleanup details: unchanged. - Generated metadata, package, or installation impact: none. Expected effects: - [x] Documentation or usability only; no target interaction. ## Evidence and regression coverage - Tests updated in `tests/boundary/cli/cliOutput.test.ts`, all through the compiled CLI: - Equals forms are now asserted as honored: `--format=json --filter-output=capabilities[0,1]` returns the filtered JSON, and `--json --token-limit=5` is rejected as a token window exactly like the spaced form. The previous assertion, that `--token-limit=5` was not an active builtin, encoded the old behavior. - The structured-error case now uses `--format=json --token-limit=5`. - Missing values for `--format`, `--filter-output`, `--token-limit` and `--token-offset=`, and a trailing `--format`, assert `MISSING_OUTPUT_VALUE` naming the flag. - Base reproduction: against the unfixed `src/cliOutput.ts` and `scripts/rea.mjs`, both updated tests fail (`Tests 2 failed | 16 passed`). - User-visible output before: ``` $ rea inspect-plist /Applications/Ghostty.app --format=json code: UNKNOWN message: "Unknown flag: --format" ``` After: ``` $ rea inspect-plist /Applications/Ghostty.app --format=json --filter-output=normalized_result.bundle.identifier {"normalized_result":{"bundle":{"identifier":"com.mitchellh.ghostty"}}} $ rea inspect-plist /Applications/Ghostty.app --format= {"ok":false,"error":{"code":"MISSING_OUTPUT_VALUE","message":"--format requires a value, as in --format <value> or --format=<value>."}} ``` - Remaining proof gaps: none known. ## Validation performed - `npm run test:focused -- tests/boundary/cli/cliOutput.test.ts tests/boundary/cli/closedStdout.test.ts tests/boundary/cli/jsonOutput.test.ts tests/boundary/cli/cliOptionAliases.test.ts`: 65 passed - `npm run test:focused -- tests/boundary/cli/mcpDoctorHelpCli.test.ts tests/boundary/cli/javascriptIntegrityPolicyCli.test.ts tests/boundary/cli/nativeUiScenarioInputCli.test.ts`: 15 passed. These cover command-local "Unknown flag" errors, which are unchanged. - `npm run check:fast`: passed; `npm run docs:check`: passed - Real app on macOS (Darwin 25.6, arm64), against `/Applications/Ghostty.app`: - `--format=json`, `--format=json --filter-output=...` and `--token-limit=20` now match their spaced forms. - `--format=`, a trailing `--format`, and `--filter-output "" --format yaml` give `MISSING_OUTPUT_VALUE` in the selected structured format. - `--format=xml` still gives Incur's `Invalid format` message. - Cost: argv normalization is linear in the argument count. For agents, it removes a failed call and retry per equals-form invocation. ## Compatibility, safety, and release - Breaking changes or migration steps: none for valid invocations; previously failing invocations now succeed. A missing value still exits `1`, now with `MISSING_OUTPUT_VALUE` instead of `UNKNOWN`. - Real Hopper/Ghidra, browser, or OS coverage: not applicable. - Package or release metadata impact: none. - Security, privacy, process, or containment review: none. ## Author readiness Human owner: <!-- @GitHub-handle --> - [ ] I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work. - [ ] I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps. - [ ] I declare this PR ready for initial maintainer review. ## Before merge - [x] This PR addresses a concrete problem or an agreed enhancement. - [x] Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff. - [x] The PR has one focused outcome and the title follows `type(scope): outcome`. - [x] Related issue is linked, or the reason for not linking one is stated above. (Found by exercising the real CLI; no existing issue.) - [x] Tests cover changed observable behavior and meaningful failure paths. - [x] Owning docs, contracts, and generated metadata are updated where needed. - [x] User-visible CLI/MCP changes include representative output. - [x] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-31 01:10:25 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#5916
No description provided.