feat(cli): ExitCode enum + exit-code docs (#241, PR 1 of 2)#255
Conversation
Add ExitCode(IntEnum) — OK=0, FAILURE=1, USAGE=2 — in cli.py and use it in main()'s two dispatch-tail return paths as named constants. Purely a naming + documentation change: the values are the existing released rc numbers, so behavior is unchanged (ExitCode.FAILURE == 1). - USAGE=2 names argparse's own SystemExit(2); it is documented, not rerouted. - Codes 3+ and INTERRUPTED (Ctrl+C -> 130) are deferred to the follow-up PR; the KeyboardInterrupt path is untouched here. - README gains an 'Exit codes' section under the scripting docs. - Tests assert the enum values, that no codes 3+ crept in, and that members return as ints; the existing rc characterization tests stay green. This is PR 1 of #241 (enum + docs, no behavior change).
|
Warning Review limit reached
Next review available in: 39 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. WalkthroughThe CLI now defines named exit codes for success, failure, and usage errors. Exception backstops return the named failure code, README documents the contract and JSON verdict behavior, and tests verify enum values and integer compatibility. ChangesCLI exit-code contract
Estimated code review effort: 1 (Trivial) | ~5 minutes Possibly related issues
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@README.md`:
- Around line 522-534: Update the “Exit codes” section around the `ExitCode`
enum and normal command-dispatch contract to clarify that the three documented
codes apply only to those paths. Add a concise exception stating that Ctrl+C
remains an exit status of 130 until the planned follow-up change, and adjust the
“every command” wording so it does not incorrectly include interruptions.
In `@src/bmad_loop/cli.py`:
- Around line 2603-2609: Resolve Ruff BLE001 in the CLI boundary backstop around
the outer exception handler: either narrow the caught exception if the
surrounding flow permits, or add a targeted Ruff suppression for this
intentional catch. Preserve the existing stderr error message and
ExitCode.FAILURE behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 18a8ad4f-95e2-485a-a80f-7ef1ab3d6c54
📒 Files selected for processing (3)
README.mdsrc/bmad_loop/cli.pytests/test_entry_point.py
CodeRabbit (Major): the 'every command exits with one of three codes' claim
was wrong — an uncaught KeyboardInterrupt dies by SIGINT and exits 130, which
is not in {0,1,2}. Narrow the contract to normal dispatch + argparse usage
errors and document interruption as the one exception (130, a bare traceback
today; #241 PR 2 makes it a clean message but keeps the code).
130 stays prose-only, not an ExitCode member: PR 1 must not add codes >=3 and
INTERRUPTED is deferred to PR 2.
PR 1 of the two-PR exit-code taxonomy (#241) — the enum + documentation half. No behavior change.
What
ExitCode(IntEnum)tocli.py—OK=0,FAILURE=1,USAGE=2— and use it inmain()'s two dispatch-tail return paths as named constants. BecauseExitCode.FAILURE == 1, the returned codes are byte-identical to before.USAGE=2names argparse's ownSystemExit(2); it's documented, not rerouted throughmain().--jsonverdict-vs-error caveat (validate --jsonexits 1 to carry a verdict, not because it broke).Scope guardrails (per the issue)
≥3added — deferred until a consumer asks.INTERRUPTED(Ctrl+C → 130) is the follow-up PR (released-contract change, ships alone). Theengine.run()clean-stop path is not in this diff.python -m bmad_loop+ entry-point/exit-code smoke tests (#240) #249), already merged tomain; this branches offmain.Tests
≥3sneaking in, and confirm members return asint(somain() -> int/sys.exitconsume them transparently).test_exit_*intest_entry_point.py) stay green — they pin the raw rc numbers this enum now names.module.yamlat0.8.1vs canonical0.9.0— gitignored installed copies, not in this diff).Closes part of #241 (the issue stays open for PR 2).
Summary by CodeRabbit
Documentation
1while providing a complete response, so scripts should use the JSON verdict field.Bug Fixes