Skip to content

feat(cli): python -m bmad_loop + entry-point/exit-code smoke tests (#240)#249

Merged
pbean merged 1 commit into
mainfrom
feat/python-m-entry
Jul 22, 2026
Merged

feat(cli): python -m bmad_loop + entry-point/exit-code smoke tests (#240)#249
pbean merged 1 commit into
mainfrom
feat/python-m-entry

Conversation

@pbean

@pbean pbean commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator

Closes #240 (findings F-7/F-8 of the brownfield CLI/TUI refactor assessment). Session 2 of the refactor program — the first code PR; the exit-code characterization tests here are the guard rail everything later leans on.

What

  1. src/bmad_loop/__main__.py — a thin module entry delegating to cli.main(), mirroring the cli.py __main__ guard. python -m bmad_loop … now works alongside the installed bmad-loop console script (pyproject.toml [project.scripts]). Both share one dispatch path.

  2. Subprocess smoke tests (tests/test_entry_point.py::test_module_*) — every existing CLI test calls cli.main() in-process, so startup import cycles and broken script wiring are invisible to the suite. These three spawn a real interpreter via sys.executable -m bmad_loop:

    • --versionbmad-loop <version> on stdout, rc 0
    • --help → usage on stdout, rc 0
    • validate --json in an empty project → rc 1 (bmad-config gate fails) but stdout is still a whole parseable document

    They are the deliberate exception to the in-process pattern (per the issue's trap note), and are xdist-safe: sys.executable + a per-test temp cwd/--project, no shared writable state.

  3. Exit-code characterization tests (test_exit_*) pinning today's rc semantics at the cli.py dispatch tail:

    • typed errors (BmadConfigError / SprintStatusError / PolicyError / GitError) → 1
    • broad except Exception backstop → 1
    • argparse usage error (unknown subcommand) → 2 (via SystemExit, raised before the dispatch try)

No behavior changes

__main__.py is additive; the tests pin current semantics as the guard rail for the exit-code-taxonomy work (#241) and the cli.py composition extraction (#243). Nothing existing changes behavior.

Verification

  • uv run pytest -q -n auto — green except one pre-existing failure on clean origin/main (test_tui_app.py::test_validate_findings_multiline_message_keeps_column_alignment), a TUI column-alignment test unrelated to this diff (this branch changes only CHANGELOG.md + the two new files).
  • Full trunk check --no-fix — no issues on the modified files.
  • CHANGELOG: terse ## [Unreleased] line for python -m support.

Summary by CodeRabbit

  • New Features

    • Added support for running the package with python -m bmad_loop.
    • Module execution now provides the same command-line behavior as the installed bmad-loop command.
  • Bug Fixes

    • Standardized command-line exit codes for validation errors, unexpected errors, and invalid usage.
  • Tests

    • Added coverage for module version, help, validation, error handling, and argument parsing behavior.
  • Documentation

    • Documented the new module-based invocation in the unreleased changelog.

…semantics (#240)

Add src/bmad_loop/__main__.py delegating to cli.main(), mirroring the
cli.py __main__ guard, so the package runs as a module alongside the
installed `bmad-loop` console script.

Add tests/test_entry_point.py:
- subprocess smoke tests (`python -m bmad_loop --version`/`--help` and one
  `validate --json`) that spawn a real interpreter via sys.executable — the
  deliberate exception to the in-process cli.main() tests, so packaging
  regressions (startup import cycles, broken script wiring) become visible.
- characterization tests pinning today's CLI exit codes: typed errors
  (BmadConfigError/SprintStatusError/PolicyError/GitError) and the broad
  backstop -> 1, argparse usage error -> 2.

No behavior changes — the tests pin current semantics as the guard rail for
the exit-code-taxonomy work (#241) and the cli.py composition extraction (#243).
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b3015650-aeb9-4906-b4c1-32ac5e310bb3

📥 Commits

Reviewing files that changed from the base of the PR and between f071a0d and 18ac56f.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • src/bmad_loop/__main__.py
  • tests/test_entry_point.py

Walkthrough

Adds python -m bmad_loop support by delegating to the existing CLI entry point. New subprocess tests cover version, help, validation JSON output, and current exit-code behavior for typed errors, broad exceptions, and argparse usage errors.

Changes

Module Entry Point

Layer / File(s) Summary
Module entry-point wiring
src/bmad_loop/__main__.py, CHANGELOG.md
Adds the guarded python -m bmad_loop entry point and documents the command and unreleased comparison link.
Subprocess smoke and exit-code characterization
tests/test_entry_point.py
Runs the module in isolated subprocesses and verifies startup output, validation JSON, typed and untyped error code 1, and argparse error code 2.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant PythonInterpreter
  participant bmad_loop.__main__
  participant bmad_loop.cli.main
  PythonInterpreter->>bmad_loop.__main__: execute python -m bmad_loop
  bmad_loop.__main__->>bmad_loop.cli.main: invoke main()
  bmad_loop.cli.main-->>bmad_loop.__main__: return exit code
  bmad_loop.__main__-->>PythonInterpreter: sys.exit(exit code)
Loading

Poem

A rabbit hops through Python’s door,
The CLI runs as code before.
Smoke tests check each exit sign,
Errors, help, and JSON align.
“The module path is clear!” 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the module entry point and smoke-test additions described in the PR.
Linked Issues check ✅ Passed The changes implement main.py, subprocess smoke tests, exit-code pinning, and changelog notes required by #240.
Out of Scope Changes check ✅ Passed The diff stays within the issue scope and only adds the module entry point, tests, and changelog entry.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/python-m-entry

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@pbean
pbean marked this pull request as ready for review July 22, 2026 01:09
@pbean
pbean merged commit 9f8adc2 into main Jul 22, 2026
9 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.

python -m bmad_loop + installed-entry-point smoke tests

1 participant