From ad457175dbe4c1035a27976ba85403b366a8f534 Mon Sep 17 00:00:00 2001 From: Guillermo Montero Date: Wed, 23 Sep 2026 11:57:47 +0200 Subject: [PATCH 1/2] fix(policy): warn when scm.max_parallel is silently clamped to 1 --- CHANGELOG.md | 3 +++ src/bmad_loop/policy.py | 8 ++++++++ tests/test_policy.py | 18 ++++++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a55a12d0d..60c4322e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -394,6 +394,9 @@ breaking changes may land in a minor release. cannot be read at a graceful stop journals `sweep-remaining-estimate-unreadable` next to the `run-stop` row, so a withheld estimate says why it was withheld. +- bmad-loop now warns when scm.max_parallel > 1 is configured, since parallel fan-out + is not yet built and the value is clamped to 1. + - **`bmad-loop diagnose --json` reports `schema_version: 4`.** Journal `path` values become `path_present`; stale-restore and merge filename lists become counts. diff --git a/src/bmad_loop/policy.py b/src/bmad_loop/policy.py index 319af2467..e38d982ac 100644 --- a/src/bmad_loop/policy.py +++ b/src/bmad_loop/policy.py @@ -1125,6 +1125,14 @@ def loads(text: str, plugin_schemas: dict[str, Any] | None = None) -> Policy: requested_parallel = _typed_int(scm_d, "scm", "max_parallel", ScmPolicy.max_parallel) if requested_parallel < 1: raise PolicyError(f"scm.max_parallel must be >= 1: got {requested_parallel}") + if requested_parallel > 1: + warnings.warn( + f"scm.max_parallel = {requested_parallel} is configured, but parallel " + "fan-out (Phase 5) is not built yet: the value is clamped to 1 and has " + "no effect (see #229).", + UserWarning, + stacklevel=3, + ) # This one was strict before its sibling int knobs were (a TOML `true`, with # int(True) == 1, or a `1.9` coercing through int() would silently shrink a # safety-net budget); `_typed_int` is that same guard, message included. diff --git a/tests/test_policy.py b/tests/test_policy.py index 1cadd597c..342e87ef0 100644 --- a/tests/test_policy.py +++ b/tests/test_policy.py @@ -1277,6 +1277,24 @@ def test_scm_max_parallel_clamped_to_one(tmp_path): policy.load(p) +def test_scm_max_parallel_above_one_warns(): + """Phase 5 parallel fan-out (#229) is unbuilt, so a configured value > 1 is + still silently inert without this warning -- an operator setting + ``max_parallel = 4`` would otherwise get no signal that it has no effect. + + Ablation: delete the ``requested_parallel > 1`` warning block in ``loads()``; + this test fails because no warning fires while the clamp still applies.""" + with pytest.warns(UserWarning, match=r"scm\.max_parallel"): + loaded = policy.loads("[scm]\nmax_parallel = 4\n") + assert loaded.scm.max_parallel == 1 + + +def test_scm_max_parallel_equal_to_one_does_not_warn(recwarn): + loaded = policy.loads("[scm]\nmax_parallel = 1\n") + assert loaded.scm.max_parallel == 1 + assert len(recwarn) == 0 + + def test_scm_preserve_keep_settings(tmp_path): p = tmp_path / "policy.toml" p.write_text("[scm]\npreserve_keep = 5\n") From e54d183021b20cac789d158df7856f17a19840ab Mon Sep 17 00:00:00 2001 From: Guillermo Montero Date: Wed, 23 Sep 2026 14:55:01 +0200 Subject: [PATCH 2/2] docs(policy): move max_parallel warning entry to Unreleased, imperative MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CodeRabbit: same misplacement as #810/#811 — the entry landed inside the already-published ## [0.12.0] section instead of ## [Unreleased], and used narrative wording instead of this repo's imperative CHANGELOG convention. Moved and reworded; left src/bmad_loop/policy.py's stacklevel=3 as-is (not a clear bug: loads() is called both directly and via load(), which adds a frame — CodeRabbit's stacklevel=2 suggestion would be correct for the direct-call path but wrong for the load()-via-loads() path that tui/app.py actually uses in production, and stacklevel=3 matches the existing precedent at _fold_deprecated_engine in the same file). --- CHANGELOG.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60c4322e2..b3cc494a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,8 @@ breaking changes may land in a minor release. ### Changed +- Warn when `scm.max_parallel > 1` is configured; keep the value clamped to 1 + until parallel fan-out is built (#229). - Register hooks through the installed `bmad-loop relay ` command. Upgrading invalidates Codex hook trust: Codex re-prompts at the next launch, and hooks silently do not fire until the new commands are accepted. Re-run `bmad-loop init` to migrate @@ -394,9 +396,6 @@ breaking changes may land in a minor release. cannot be read at a graceful stop journals `sweep-remaining-estimate-unreadable` next to the `run-stop` row, so a withheld estimate says why it was withheld. -- bmad-loop now warns when scm.max_parallel > 1 is configured, since parallel fan-out - is not yet built and the value is clamped to 1. - - **`bmad-loop diagnose --json` reports `schema_version: 4`.** Journal `path` values become `path_present`; stale-restore and merge filename lists become counts.