Skip to content

refactor(envvars): centralize BMAD_LOOP_* env reads into a registry (#246)#269

Merged
pbean merged 1 commit into
mainfrom
feat/envvars-registry-246
Jul 23, 2026
Merged

refactor(envvars): centralize BMAD_LOOP_* env reads into a registry (#246)#269
pbean merged 1 commit into
mainfrom
feat/envvars-registry-246

Conversation

@pbean

@pbean pbean commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator

Summary

The env-var registry PR from #246 (folded item F-9b). The three BMAD_LOOP_* runtime override knobs were read inline via os.environ.get(...) at five scattered call sites, which left them undiscoverable and undocumented. This gives them one home and one operator-facing table. No behavior changes.

What changed

  • New src/bmad_loop/envvars.py — named constants + typed readers:
    • session_timeout_s() -> float | None — absorbs the parse + validation (unparseable / non-positive → None, so a fat-fingered value can't silently shorten a run).
    • mux_backend() -> str | None and process_host() -> str | None — return the value verbatim (callers test truthiness and resolve the name), so forced-selection semantics stay byte-identical.
    • Pure stdlib (imports only os), so any module can depend on it without a cycle.
  • Read sites routed through it: engine._session_timeout_s, adapters.multiplexer.{backend_forced, _select}, cli._mux_set, process_host.get_process_host. Dropped the now-unused import os from engine.py and multiplexer.py.
  • Docs: README gains an "Environment variables" reference table (the three vars, their values, and effects); the wider BMAD_LOOP_UNITY_* / BMAD_LOOP_ENGINE_* plugin set is pointed at the game-engine guide. Terse CHANGELOG line under Unreleased → Added.

Verification

  • Semantics are identical, so no test needed changing — the env-var tests (test_backend_registry, test_process_host, test_external_backends, test_stories_e2e's BMAD_LOOP_SESSION_TIMEOUT_S seam) pass untouched.
  • trunk check clean; uvx pyright@1.1.411 (basic gate now covers envvars.py) → 0 errors.
  • Full suite: 2766 passed, 1 skipped. The 2 test_module_skills_sync failures are the pre-existing local-only drift (gitignored .agents/.claude install copies at module_version 0.8.1 vs canonical 0.9.0), unrelated to this PR and absent on a fresh CI checkout.

Completes the F-9b half of #246 (the lint-alignment half shipped in #267); closes #246.

…246)

F-9b of #246: the three runtime override vars were read inline via
`os.environ.get(...)` at five scattered call sites, leaving them
undiscoverable and undocumented.

- New `bmad_loop.envvars`: named constants + typed readers for
  `BMAD_LOOP_SESSION_TIMEOUT_S` (-> float | None), `BMAD_LOOP_MUX_BACKEND`
  and `BMAD_LOOP_PROCESS_HOST` (-> str | None). Pure stdlib (imports only
  `os`), so any module can depend on it without a cycle.
- Route engine._session_timeout_s, adapters.multiplexer.{backend_forced,
  _select}, cli._mux_set, and process_host.get_process_host through the
  readers. `session_timeout_s()` absorbs the parse+validate (unparseable /
  non-positive -> None -> caller's default); the two string readers return
  the value verbatim so truthiness/name-resolution semantics are
  byte-identical. Dropped the now-unused `import os` from engine and
  multiplexer.
- README gains an "Environment variables" reference table; CHANGELOG note.

Semantics unchanged — the env-var tests (backend registry, process host,
stories-e2e timeout seam) pass untouched.
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@pbean, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 52 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3c9248eb-711f-44c4-8185-61163d86a720

📥 Commits

Reviewing files that changed from the base of the PR and between cd12526 and 548e0d2.

📒 Files selected for processing (7)
  • CHANGELOG.md
  • README.md
  • src/bmad_loop/adapters/multiplexer.py
  • src/bmad_loop/cli.py
  • src/bmad_loop/engine.py
  • src/bmad_loop/envvars.py
  • src/bmad_loop/process_host.py
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/envvars-registry-246

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 merged commit c1ff7a6 into main Jul 23, 2026
10 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.

Align local ruff lint.select with trunk + stale-noqa audit

1 participant