Corrected after a closer read of the current code — the original text of this issue
misdescribed the problem. See the comment below.
Ledger edits are deliberately written inside the story's worktree so they squash into the story
commit — engine.py:1484-1485 and engine.py:1654-1657 both say so explicitly, and the #234
changelog entry confirms it ("an in-repo ledger carries it in the story's own commit, worktree
isolation included"). A ledger outside the repo is handled too, and journaled
(deferred-close-external-ledger).
That leaves a third configuration with no defined behavior: an in-repo but gitignored ledger.
- The write lands in the worktree copy.
finalize_commit's add -A skips it, because it is ignored.
worktree_remove(force) deletes it at teardown.
The entry is silently lost. Concretely: a review-budget-followup entry meant to survive to a
later sweep never reaches the sweep, and a bundle's mark_done marks are lost, so the next
sweep cycle re-reads the ids as open and rebuilds work that was already resolved.
Expected
Either the gitignored-ledger case is supported (writes route to the main repo, as the reads at
engine.py:661/:725 already do for the sprint board), or it is rejected at validate time.
Actual
Writes are silently discarded at teardown.
Question for maintainers
Is a gitignored ledger a supported configuration? It is what an operator gets by gitignoring
their bmad output wholesale, which is a natural thing to do. If it is supported, I have a patch
routing these writes to the main repo, but it needs to be conditional on the ledger being
ignored — an unconditional redirect would break the intended squash-into-the-story-commit
behavior for a tracked ledger. Happy to shape it whichever way you prefer.
Environment
bmad-loop 0.9.0, claude adapter, Linux (WSL2), worktree isolation on.
Corrected after a closer read of the current code — the original text of this issue
misdescribed the problem. See the comment below.
Ledger edits are deliberately written inside the story's worktree so they squash into the story
commit —
engine.py:1484-1485andengine.py:1654-1657both say so explicitly, and the #234changelog entry confirms it ("an in-repo ledger carries it in the story's own commit, worktree
isolation included"). A ledger outside the repo is handled too, and journaled
(
deferred-close-external-ledger).That leaves a third configuration with no defined behavior: an in-repo but gitignored ledger.
finalize_commit'sadd -Askips it, because it is ignored.worktree_remove(force)deletes it at teardown.The entry is silently lost. Concretely: a
review-budget-followupentry meant to survive to alater sweep never reaches the sweep, and a bundle's
mark_donemarks are lost, so the nextsweep cycle re-reads the ids as open and rebuilds work that was already resolved.
Expected
Either the gitignored-ledger case is supported (writes route to the main repo, as the reads at
engine.py:661/:725already do for the sprint board), or it is rejected at validate time.Actual
Writes are silently discarded at teardown.
Question for maintainers
Is a gitignored ledger a supported configuration? It is what an operator gets by gitignoring
their bmad output wholesale, which is a natural thing to do. If it is supported, I have a patch
routing these writes to the main repo, but it needs to be conditional on the ledger being
ignored — an unconditional redirect would break the intended squash-into-the-story-commit
behavior for a tracked ledger. Happy to shape it whichever way you prefer.
Environment
bmad-loop 0.9.0, claude adapter, Linux (WSL2), worktree isolation on.