Summary
When _bmad/bmm/config.yaml sets repo_root to a different path than project (the documented split-repo setup — planning artifacts in one repo, code in another), [verify].commands runs in the wrong directory on the post-review gate, so verify fails on every story even though the same commands succeed if run manually in repo_root.
Root cause (verify.py, v0.9.0)
-
verify_dev's companion verify-commands call (engine.py:1741) uses self.workspace.root, which for isolation = "none" correctly resolves to repo_root.
-
But verify_review, verify_review_stories, and verify_review_bundle (verify.py:2096, 2128, 2168) all call:
return verify_commands_outcome(policy, paths.project)
using paths.project instead of paths.repo_root / workspace.root. This runs whether or not the standalone review session fires — it's the gate hit on virtually every story (including "review disabled" dev-only finalization).
Repro
_bmad/bmm/config.yaml:
planning_artifacts: "{project-root}"
implementation_artifacts: "{project-root}"
repo_root: "/abs/path/to/code-repo" # a different git repo than project-root
.bmad-loop/policy.toml:
[verify]
commands = ["npx nx affected -t lint test --base=HEAD~1"]
Result — every story's post-review verify gate fails:
NX Could not find Nx modules at "<ancestor of project, NOT repo_root>".
Have you run npm/yarn install?
even though cd repo_root && npx nx affected ... succeeds by hand.
Impact
With scm.rollback_on_failure = false (recommended for in-place isolation to avoid discarding committed work), a verify failure on a real commit pauses the run for manual recovery (ACTION REQUIRED / rescue-branch-then-reset instructions) instead of continuing. From the outside this looks like "the loop stops after every story instead of iterating" — it's not a review/commit bug, it's the verify gate running in the wrong repo every time.
Fix
verify_review / verify_review_stories / verify_review_bundle should pass paths.repo_root (or the equivalent workspace.root) to verify_commands_outcome, matching what the dev-side verify-commands call already does, so both gates run [verify].commands in the same directory.
Workaround
Hardcode the real repo into the command string itself (wins over whatever cwd is passed, since commands run with shell=True):
commands = ["cd /abs/path/to/code-repo && npx nx affected -t lint test --base=HEAD~1"]
Environment
bmad-loop version: 0.9.0
python: 3.11.15
os: Darwin 25.6.0
Summary
When
_bmad/bmm/config.yamlsetsrepo_rootto a different path thanproject(the documented split-repo setup — planning artifacts in one repo, code in another),[verify].commandsruns in the wrong directory on the post-review gate, so verify fails on every story even though the same commands succeed if run manually inrepo_root.Root cause (verify.py, v0.9.0)
verify_dev's companion verify-commands call (engine.py:1741) usesself.workspace.root, which forisolation = "none"correctly resolves torepo_root.But
verify_review,verify_review_stories, andverify_review_bundle(verify.py:2096,2128,2168) all call:using
paths.projectinstead ofpaths.repo_root/workspace.root. This runs whether or not the standalone review session fires — it's the gate hit on virtually every story (including "review disabled" dev-only finalization).Repro
_bmad/bmm/config.yaml:.bmad-loop/policy.toml:Result — every story's post-review verify gate fails:
even though
cd repo_root && npx nx affected ...succeeds by hand.Impact
With
scm.rollback_on_failure = false(recommended for in-place isolation to avoid discarding committed work), a verify failure on a real commit pauses the run for manual recovery (ACTION REQUIRED/ rescue-branch-then-reset instructions) instead of continuing. From the outside this looks like "the loop stops after every story instead of iterating" — it's not a review/commit bug, it's the verify gate running in the wrong repo every time.Fix
verify_review/verify_review_stories/verify_review_bundleshould passpaths.repo_root(or the equivalentworkspace.root) toverify_commands_outcome, matching what the dev-side verify-commands call already does, so both gates run[verify].commandsin the same directory.Workaround
Hardcode the real repo into the command string itself (wins over whatever cwd is passed, since commands run with
shell=True):Environment