Corrected after a closer read of the current code — see the comment below.
The sprint board has a reader/writer split under worktree isolation:
engine.py:661 (_backlog_hint) and engine.py:725 (_pick_next) load it from
self.paths.sprint_status — the main repo.
engine.py:2116 (_post_dev_sync) advances it via self.workspace.paths.sprint_status — the
worktree.
For a tracked board this is merely surprising: the advance rides the story commit and reaches
main at merge, so scheduling sees a board that lags by one merge.
For a gitignored board it is silent loss — add -A skips the file and
worktree_remove(force) deletes it, so _post_dev_sync's advance never happens at all. Unlike
the deferred-work ledger, I can find no comment or changelog entry stating that the board's write
is meant to squash into the story commit, so I am not sure which behavior is intended here.
A second consequence, independent of gitignore: with max_parallel > 1, worktrees that do carry
a board turn shared orchestrator state into cross-worktree merge conflicts.
Expected
The board is read and written consistently — one location, whichever you consider canonical.
Actual
Read from the main repo, written to the worktree.
Question for maintainers
Is _post_dev_sync's worktree write deliberate (mirroring the ledger's squash-into-the-commit
design), or an oversight given the two reads use self.paths? I have a patch that routes the
write to the main repo and threads a board_path through the verify gate so the check reads the
same board, but I would rather match your intent than guess.
Environment
bmad-loop 0.9.0, claude adapter, Linux (WSL2), worktree isolation on.
Corrected after a closer read of the current code — see the comment below.
The sprint board has a reader/writer split under worktree isolation:
engine.py:661(_backlog_hint) andengine.py:725(_pick_next) load it fromself.paths.sprint_status— the main repo.engine.py:2116(_post_dev_sync) advances it viaself.workspace.paths.sprint_status— theworktree.
For a tracked board this is merely surprising: the advance rides the story commit and reaches
main at merge, so scheduling sees a board that lags by one merge.
For a gitignored board it is silent loss —
add -Askips the file andworktree_remove(force)deletes it, so_post_dev_sync's advance never happens at all. Unlikethe deferred-work ledger, I can find no comment or changelog entry stating that the board's write
is meant to squash into the story commit, so I am not sure which behavior is intended here.
A second consequence, independent of gitignore: with
max_parallel > 1, worktrees that do carrya board turn shared orchestrator state into cross-worktree merge conflicts.
Expected
The board is read and written consistently — one location, whichever you consider canonical.
Actual
Read from the main repo, written to the worktree.
Question for maintainers
Is
_post_dev_sync's worktree write deliberate (mirroring the ledger's squash-into-the-commitdesign), or an oversight given the two reads use
self.paths? I have a patch that routes thewrite to the main repo and threads a
board_paththrough the verify gate so the check reads thesame board, but I would rather match your intent than guess.
Environment
bmad-loop 0.9.0, claude adapter, Linux (WSL2), worktree isolation on.