You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
After a story reaches story-done + unit-merged, bmad-loop only merges locally into target_branch (engine._merge_local → journal unit-merged). There is no first-class path that:
pushes the unit branch (or the merge result) to a remote,
opens / updates a GitHub PR,
waits for merge to the remote default branch, and
treats remote containment as part of the story Done gate.
Today “done” means: local commit + local merge + sprint-status advanced. For any project whose real gate is code on origin/main (or equivalent remote), that semantic gap forces an external salvage layer.
Why is this needed?
Field use (bmad-loop 0.8.1, scm.isolation = "worktree", multi-story epics, unattended overnight + daytime salvage):
Journal / board / auto-dev specs can all say done while origin never saw the product code.
Continuity gates and human/AI supervisors then redispatch work that already exists only in a local merge or a kept worktree — or, worse, mark progress complete when the shared trunk is empty.
This is not “put an LLM in the control loop.” It is deterministic SCM after the creative sessions finish — same philosophy as local merge-back, one hop further for remote-first teams.
How should it work? (proposal, not a PR)
Keep local merge as default (no behavior change for current users). Add an opt-in SCM policy, for example:
[scm]
# existing: isolation, merge_strategy, delete_branch, ...# new (sketch):closeout = "local"# default — today's behavior# closeout = "remote" # require remote integration before story Done# remote_mode = "push-pr" # push unit branch + open PR (gh)# remote_mode = "push-merge" # push merge commit / ff to tracking branch (advanced)# remote_target = "" # empty = origin/<default># require_remote_sha = true # journal unit-remote-merged only when origin contains sha
Suggested contract
Event
Meaning
unit-merged
local merge into run target (unchanged)
unit-remote-pending
branch/PR opened, waiting
unit-remote-merged
remote default contains the story commit (or PR merged)
story-done when closeout=remote
only after unit-remote-merged (or explicit policy skip)
Journal should record merge_scope: local|remote so supervisors do not misread local merge as ship.
Out of scope for v1 (fine to refuse): multi-remote, protected-branch policy negotiation, admin-bypass CI — those stay project hooks. v1 can be: push + gh pr create + poll mergeability + fail-closed escalate with kept branch (same spirit as local merge conflict escalate).
Acceptance ideas
Default closeout=local: byte-identical to 0.8.1 for existing suites.
With closeout=remote + mock/gh fixture: story does not journal terminal Done until remote SHA observed; failure escalates with branch kept (keep_failed).
Docs: one paragraph in unattended / SCM policy: “local unit-merged ≠ origin.”
PR
Willing to implement after maintainer design nod (per CONTRIBUTING: feature/large change → Discord first). Prefer design agreement on policy keys + journal events before any code PR. Ideal PR size: 200–400 LOC for policy + journal + one adapter seam; no bulk refactor.
External salvage we run today: stop thrash → product-only paths → Issue+PR+admin squash → board cite → never redispatch false greens. That is the human-amplification layer Field report: a week of unattended overnight runs — what held, and three gaps #232 describes; putting a narrow remote closeout in-engine would shrink that layer without moving judgment into an LLM.
Describe your idea
After a story reaches
story-done+unit-merged, bmad-loop only merges locally intotarget_branch(engine._merge_local→ journalunit-merged). There is no first-class path that:Today “done” means: local commit + local merge + sprint-status advanced. For any project whose real gate is code on
origin/main(or equivalent remote), that semantic gap forces an external salvage layer.Why is this needed?
Field use (bmad-loop 0.8.1,
scm.isolation = "worktree", multi-story epics, unattended overnight + daytime salvage):This is not “put an LLM in the control loop.” It is deterministic SCM after the creative sessions finish — same philosophy as local merge-back, one hop further for remote-first teams.
How should it work? (proposal, not a PR)
Keep local merge as default (no behavior change for current users). Add an opt-in SCM policy, for example:
Suggested contract
unit-mergedunit-remote-pendingunit-remote-mergedstory-donewhencloseout=remoteunit-remote-merged(or explicit policy skip)Journal should record
merge_scope: local|remoteso supervisors do not misread local merge as ship.Out of scope for v1 (fine to refuse): multi-remote, protected-branch policy negotiation, admin-bypass CI — those stay project hooks. v1 can be: push +
gh pr create+ poll mergeability + fail-closed escalate with kept branch (same spirit as local merge conflict escalate).Acceptance ideas
closeout=local: byte-identical to 0.8.1 for existing suites.closeout=remote+ mock/ghfixture: story does not journal terminal Done until remote SHA observed; failure escalates with branch kept (keep_failed).PR
Willing to implement after maintainer design nod (per CONTRIBUTING: feature/large change → Discord first). Prefer design agreement on policy keys + journal events before any code PR. Ideal PR size: 200–400 LOC for policy + journal + one adapter seam; no bulk refactor.
Additional context