diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json
index 73cbbea..ce0d8e2 100644
--- a/.claude-plugin/marketplace.json
+++ b/.claude-plugin/marketplace.json
@@ -12,7 +12,7 @@
"name": "bmad-loop",
"source": "./src/bmad_loop/data/skills",
"description": "Automation-mode skills driven by the bmad-loop orchestrator: interactive escalation resolution (bmad-loop-resolve) and deferred-work sweep triage (bmad-loop-sweep) — the inner dev primitive (which self-reviews and commits) is the upstream bmad-dev-auto skill",
- "version": "0.8.0",
+ "version": "0.8.1",
"author": {
"name": "pinkyd"
},
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e3f91e4..2ff2b2c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,50 @@ All notable changes to `bmad-loop` are documented here. The format is based on
[Semantic Versioning](https://semver.org/spec/v2.0.0.html). While the project is pre-1.0,
breaking changes may land in a minor release.
+## [0.8.1] — 2026-07-05
+
+### Fixed
+
+- **A session that finished its work but crashed before the run recorded it no longer loses that work
+ to a restart-and-rollback.** The engine now records a completed dev/review session behind a
+ durability barrier _before_ running post-session hooks (usage is folded in afterward as best-effort
+ metadata); on resume it consumes that durably-recorded result straight into verify/decide instead of
+ restarting the attempt from baseline. A raw `KeyboardInterrupt` now records a controlled stop, and
+ replay preserves the attempt/cycle/baseline. (#62, closes #57)
+- **Several narrower resume-replay edges opened by that durability work are closed.** A host death in
+ the post-session window of the _last_ allowed review cycle no longer drops a recorded clean review to
+ a defer; a reconcile early-return no longer persists a pre-reconcile dict that could silently skip a
+ recommended follow-up review; and triage/sweep and labeled plugin-workflow sessions no longer persist
+ large, never-consumed result payloads into `state.json`. (#63)
+- **A dev session is now completed only on a real Stop or window death, never on a terminal artifact
+ glimpsed while the agent window is still alive.** The idle-tick and grace-expiry shortcuts could
+ return "completed" mid-turn and let the run's cleanup kill a working agent, handing the engine
+ half-written state. Both shortcuts are removed, liveness is re-probed immediately before the
+ grace-expiry stall verdict, and a re-driven spec has its stale `## Auto Run Result` section stripped
+ on both re-arm paths so a resolved re-drive can't be misread as its own terminal result. Result scans
+ are now fence-aware, so an `## Auto Run Result` heading quoted inside a fenced code block is never
+ mistaken for a real section (nor destructively stripped). (#53, closes #48 #52)
+- **Long journal fields in the TUI now wrap with a hanging indent instead of spilling back under the
+ timestamp and kind columns.** Each row renders as a fixed-width grid whose fields cell folds within
+ its own column.
+
+### Added
+
+- **Attempt-preserve recovery refs are now bounded.** With `scm.rollback_on_failure` on, auto-rollback
+ parks a failed attempt's committed work under `attempt-preserve/*` and its dirty worktree snapshot
+ under `attempt-preserve-dirty/*`; nothing pruned them, so they grew unbounded. Run start now keeps
+ only the newest `scm.preserve_keep` (default 20, `0` = never prune) per family by committer date and
+ best-effort-deletes the tail — a stuck ref never wedges the ones behind it, and prune failures are
+ journaled but never block the run. (#50 #54, closes #32 #49)
+
+### Changed
+
+- **The adapter shell-dialect seam is now an explicit, documented contract.** `new_window` /
+ `new_parked_window` factor their shell-dialect fragments into overridable hooks (POSIX output stays
+ byte-identical), and the `command` parameter's semantics are pinned in the ABC docstring
+ (shlex-joined argv; operator handling is backend-defined). Relevant only to authors porting the
+ adapter to a non-POSIX backend. (#47 #60)
+
## [0.8.0] — 2026-07-03
### Changed
@@ -945,6 +989,7 @@ enforced in CI.
implementation phase, driven by a Python control loop with hook-based session transport and
resumable on-disk run state.
+[0.8.1]: https://github.com/bmad-code-org/bmad-loop/releases/tag/v0.8.1
[0.8.0]: https://github.com/bmad-code-org/bmad-loop/releases/tag/v0.8.0
[0.7.12]: https://github.com/bmad-code-org/bmad-auto/releases/tag/v0.7.12
[0.7.11]: https://github.com/bmad-code-org/bmad-auto/releases/tag/v0.7.11
diff --git a/docs/images/dashboard.png b/docs/images/dashboard.png
index 3fea92d..001d629 100644
Binary files a/docs/images/dashboard.png and b/docs/images/dashboard.png differ
diff --git a/docs/images/dashboard.svg b/docs/images/dashboard.svg
index 0a13265..822ef21 100644
--- a/docs/images/dashboard.svg
+++ b/docs/images/dashboard.svg
@@ -19,228 +19,228 @@
font-weight: 700;
}
- .terminal-2618510671-matrix {
+ .terminal-1304272949-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
- .terminal-2618510671-title {
+ .terminal-1304272949-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
- .terminal-2618510671-r1 { fill: #c5c8c6 }
-.terminal-2618510671-r2 { fill: #e0e0e0 }
-.terminal-2618510671-r3 { fill: #a0a3a6 }
-.terminal-2618510671-r4 { fill: #0053aa }
-.terminal-2618510671-r5 { fill: #e2e2e2;font-weight: bold }
-.terminal-2618510671-r6 { fill: #e0e0e0;font-weight: bold }
-.terminal-2618510671-r7 { fill: #98e024 }
-.terminal-2618510671-r8 { fill: #9d9d9d }
-.terminal-2618510671-r9 { fill: #fd971f }
-.terminal-2618510671-r10 { fill: #a1a1a1 }
-.terminal-2618510671-r11 { fill: #ddedf9;font-weight: bold }
-.terminal-2618510671-r12 { fill: #1e1e1e }
-.terminal-2618510671-r13 { fill: #003054 }
-.terminal-2618510671-r14 { fill: #797979 }
-.terminal-2618510671-r15 { fill: #e1e1e1;font-weight: bold }
-.terminal-2618510671-r16 { fill: #262626 }
-.terminal-2618510671-r17 { fill: #0178d4 }
-.terminal-2618510671-r18 { fill: #121212 }
-.terminal-2618510671-r19 { fill: #191919 }
-.terminal-2618510671-r20 { fill: #3e3e3e }
-.terminal-2618510671-r21 { fill: #9e9e9e }
-.terminal-2618510671-r22 { fill: #58d1eb }
-.terminal-2618510671-r23 { fill: #f4005f }
-.terminal-2618510671-r24 { fill: #f4005f;font-weight: bold }
-.terminal-2618510671-r25 { fill: #ffa62b;font-weight: bold }
-.terminal-2618510671-r26 { fill: #495259 }
+ .terminal-1304272949-r1 { fill: #c5c8c6 }
+.terminal-1304272949-r2 { fill: #e0e0e0 }
+.terminal-1304272949-r3 { fill: #a0a3a6 }
+.terminal-1304272949-r4 { fill: #0053aa }
+.terminal-1304272949-r5 { fill: #e2e2e2;font-weight: bold }
+.terminal-1304272949-r6 { fill: #e0e0e0;font-weight: bold }
+.terminal-1304272949-r7 { fill: #98e024 }
+.terminal-1304272949-r8 { fill: #9d9d9d }
+.terminal-1304272949-r9 { fill: #fd971f }
+.terminal-1304272949-r10 { fill: #a1a1a1 }
+.terminal-1304272949-r11 { fill: #ddedf9;font-weight: bold }
+.terminal-1304272949-r12 { fill: #1e1e1e }
+.terminal-1304272949-r13 { fill: #003054 }
+.terminal-1304272949-r14 { fill: #797979 }
+.terminal-1304272949-r15 { fill: #e1e1e1;font-weight: bold }
+.terminal-1304272949-r16 { fill: #262626 }
+.terminal-1304272949-r17 { fill: #0178d4 }
+.terminal-1304272949-r18 { fill: #121212 }
+.terminal-1304272949-r19 { fill: #191919 }
+.terminal-1304272949-r20 { fill: #3e3e3e }
+.terminal-1304272949-r21 { fill: #9e9e9e }
+.terminal-1304272949-r22 { fill: #58d1eb }
+.terminal-1304272949-r23 { fill: #f4005f }
+.terminal-1304272949-r24 { fill: #f4005f;font-weight: bold }
+.terminal-1304272949-r25 { fill: #ffa62b;font-weight: bold }
+.terminal-1304272949-r26 { fill: #495259 }
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
- bmad-loop
+ bmad-loop
-
-
-
- ⭘bmad-loop — ~/code/acme-search
-─Runs────────────────────────────│20260612-141000-e5f6▶ running started 2026-06-12T14:10:00 epic 2
- st run type │tasks 5 done 2 deferred 1 escalated 0 1,059,100 tokens (2,473,900 raw)
-✔ 20260610-090000-a1b2 story │────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
-▶ 20260611-101500-c3d4 sweep │ story phase dev review tokens info r
- ▶ 20260612-141000-e5f6 story │ 2-1-search-index done ×1 ×1 338,400 a1b2c3d4e5f6 8
-│ 2-2-typeahead done ×1 ×2 283,200 b2c3d4e5f607 6
-│ 2-3-search-ranking review-running ×1 ×1 224,300 5
-│ 2-4-saved-searches dev-running ×1 ×0 81,900 1
-│ 2-5-search-analytics deferred ×2 ×1 131,300 dev budget exhausted (2 attempts) 2
-│▍
-│JournalLogAttention
-─Sprint──────────────────────────│╸━━━━━━━╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-▼ Epic 1 · 3/3 ✓│▊▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▎
-├ ✓ 1-auth│▊11:32:21 session-start task_id=2-1-search-index role=dev story_key=2-1-search-index▎
-├ ✓ 2-session-tokens│▊11:32:21 story-done story_key=2-1-search-index commit=a1b2c3d4e5f6▎
-├ ✓ 3-password-reset│▊11:32:21 session-start task_id=2-2-typeahead role=dev story_key=2-2-typeahead▎
-└ ✓ retrospective│▊11:32:21 review-cycle story_key=2-2-typeahead cycle=2 findings=3▎
-▼ Epic 2 · 2/5│▊11:32:21 story-done story_key=2-2-typeahead commit=b2c3d4e5f607▎
-├ ✓ 1-search-index│▊11:32:21 story-start story_key=2-3-search-ranking epic=2▎
-├ ✓ 2-typeahead│▊11:32:21 spec-approved story_key=2-3-search-ranking tokens=1834▎
-├ ▶ 3-search-ranking│▊11:32:21 dev-done story_key=2-3-search-ranking tasks_done=3 tasks_total=3▎
-├ ◆ 4-saved-searches│▊11:32:21 verify-ok story_key=2-3-search-ranking commands=pytest -q, ruff check .▎
-└ ○ 5-search-analytics│▊11:32:21 review-start story_key=2-3-search-ranking role=review▎
-▼ Epic 3 · 0/2│▊11:32:21 escalation-preference story_key=2-3-search-ranking detail=reviewer used codex for the scoring math▎
-├ · 1-billing-portal│▊11:32:21 story-deferred story_key=2-5-search-analytics reason=dev budget exhausted▎
-└ · 2-invoices│▊▎
-│▊▎
-│▊▎
-─Deferred Work — 2 to answer (d)─│▊▎
-DW-1 Harden the OAuth token refr…│▊▎
-DW-2 Add pagination to the searc…│▊▎
-DW-3 Replace the ad-hoc ranking …│▊▎
-DW-4 Flaky retry in the indexer …│▊▎
-DW-5 ✓ Polish the empty-state co…│▊▎
-│▊▎
-│▊▎
-│▊▎
-│▊▎
-│▊▎
-│▊▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▎
- y copy q quit r run s sweep e resume R resolve d decisions a attach x stop D delete A archive c cleanup v validate g setting▏^p palette
+
+
+
+ ⭘bmad-loop — ~/code/acme-search
+─Runs────────────────────────────│20260612-141000-e5f6▶ running started 2026-06-12T14:10:00 epic 2
+ st run type │tasks 5 done 2 deferred 1 escalated 0 1,059,100 tokens (2,473,900 raw)
+✔ 20260610-090000-a1b2 story │────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
+▶ 20260611-101500-c3d4 sweep │ story phase dev review tokens info r
+ ▶ 20260612-141000-e5f6 story │ 2-1-search-index done ×1 ×1 338,400 a1b2c3d4e5f6 8
+│ 2-2-typeahead done ×1 ×2 283,200 b2c3d4e5f607 6
+│ 2-3-search-ranking review-running ×1 ×1 224,300 5
+│ 2-4-saved-searches dev-running ×1 ×0 81,900 1
+│ 2-5-search-analytics deferred ×2 ×1 131,300 dev budget exhausted (2 attempts) 2
+│▍
+│JournalLogAttention
+─Sprint──────────────────────────│╸━━━━━━━╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+▼ Epic 1 · 3/3 ✓│▊▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▎
+├ ✓ 1-auth│▊22:45:10session-start task_id=2-1-search-index role=dev story_key=2-1-search-index▎
+├ ✓ 2-session-tokens│▊22:45:10story-done story_key=2-1-search-index commit=a1b2c3d4e5f6▎
+├ ✓ 3-password-reset│▊22:45:10session-start task_id=2-2-typeahead role=dev story_key=2-2-typeahead▎
+└ ✓ retrospective│▊22:45:10review-cycle story_key=2-2-typeahead cycle=2 findings=3▎
+▼ Epic 2 · 2/5│▊22:45:10story-done story_key=2-2-typeahead commit=b2c3d4e5f607▎
+├ ✓ 1-search-index│▊22:45:10story-start story_key=2-3-search-ranking epic=2▎
+├ ✓ 2-typeahead│▊22:45:10spec-approved story_key=2-3-search-ranking tokens=1834▎
+├ ▶ 3-search-ranking│▊22:45:10dev-done story_key=2-3-search-ranking tasks_done=3 tasks_total=3▎
+├ ◆ 4-saved-searches│▊22:45:10verify-ok story_key=2-3-search-ranking commands=pytest -q, ruff check .▎
+└ ○ 5-search-analytics│▊22:45:10review-start story_key=2-3-search-ranking role=review▎
+▼ Epic 3 · 0/2│▊22:45:10escalation-preference story_key=2-3-search-ranking detail=reviewer used codex for the scoring math▎
+├ · 1-billing-portal│▊22:45:10story-deferred story_key=2-5-search-analytics reason=dev budget exhausted▎
+└ · 2-invoices│▊▎
+│▊▎
+│▊▎
+─Deferred Work — 2 to answer (d)─│▊▎
+DW-1 Harden the OAuth token refr…│▊▎
+DW-2 Add pagination to the searc…│▊▎
+DW-3 Replace the ad-hoc ranking …│▊▎
+DW-4 Flaky retry in the indexer …│▊▎
+DW-5 ✓ Polish the empty-state co…│▊▎
+│▊▎
+│▊▎
+│▊▎
+│▊▎
+│▊▎
+│▊▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▎
+ y copy q quit r run s sweep e resume R resolve d decisions a attach x stop D delete A archive c cleanup v validate g setting▏^p palette
diff --git a/docs/images/decision-answer.png b/docs/images/decision-answer.png
index de374cf..0af3282 100644
Binary files a/docs/images/decision-answer.png and b/docs/images/decision-answer.png differ
diff --git a/docs/images/decision-answer.svg b/docs/images/decision-answer.svg
index fb5cc61..3ce83c9 100644
--- a/docs/images/decision-answer.svg
+++ b/docs/images/decision-answer.svg
@@ -19,234 +19,234 @@
font-weight: 700;
}
- .terminal-3169928090-matrix {
+ .terminal-3357278493-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
- .terminal-3169928090-title {
+ .terminal-3357278493-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
- .terminal-3169928090-r1 { fill: #e0e0e0 }
-.terminal-3169928090-r2 { fill: #646464 }
-.terminal-3169928090-r3 { fill: #4a4c4d }
-.terminal-3169928090-r4 { fill: #c5c8c6 }
-.terminal-3169928090-r5 { fill: #0a2c4e }
-.terminal-3169928090-r6 { fill: #646464;font-weight: bold }
-.terminal-3169928090-r7 { fill: #476419 }
-.terminal-3169928090-r8 { fill: #494949 }
-.terminal-3169928090-r9 { fill: #704717 }
-.terminal-3169928090-r10 { fill: #4a4a4a }
-.terminal-3169928090-r11 { fill: #704717;font-weight: bold }
-.terminal-3169928090-r12 { fill: #0053aa }
-.terminal-3169928090-r13 { fill: #e0e0e0;font-weight: bold }
-.terminal-3169928090-r14 { fill: #161616 }
-.terminal-3169928090-r15 { fill: #0a1e2c }
-.terminal-3169928090-r16 { fill: #9e9e9e }
-.terminal-3169928090-r17 { fill: #1a1a1a }
-.terminal-3169928090-r18 { fill: #141414 }
-.terminal-3169928090-r19 { fill: #58d1eb }
-.terminal-3169928090-r20 { fill: #98e024 }
-.terminal-3169928090-r21 { fill: #232323 }
-.terminal-3169928090-r22 { fill: #2d2d2d }
-.terminal-3169928090-r23 { fill: #0d0d0d }
-.terminal-3169928090-r24 { fill: #2e5e68 }
-.terminal-3169928090-r25 { fill: #6c0a30 }
-.terminal-3169928090-r26 { fill: #656565;font-weight: bold }
-.terminal-3169928090-r27 { fill: #455969;font-weight: bold }
-.terminal-3169928090-r28 { fill: #6c0a30;font-weight: bold }
-.terminal-3169928090-r29 { fill: #4b4b4b }
-.terminal-3169928090-r30 { fill: #121212 }
-.terminal-3169928090-r31 { fill: #704d1c;font-weight: bold }
-.terminal-3169928090-r32 { fill: #282b2e }
+ .terminal-3357278493-r1 { fill: #e0e0e0 }
+.terminal-3357278493-r2 { fill: #646464 }
+.terminal-3357278493-r3 { fill: #4a4c4d }
+.terminal-3357278493-r4 { fill: #c5c8c6 }
+.terminal-3357278493-r5 { fill: #0a2c4e }
+.terminal-3357278493-r6 { fill: #646464;font-weight: bold }
+.terminal-3357278493-r7 { fill: #476419 }
+.terminal-3357278493-r8 { fill: #494949 }
+.terminal-3357278493-r9 { fill: #704717 }
+.terminal-3357278493-r10 { fill: #4a4a4a }
+.terminal-3357278493-r11 { fill: #704717;font-weight: bold }
+.terminal-3357278493-r12 { fill: #0053aa }
+.terminal-3357278493-r13 { fill: #e0e0e0;font-weight: bold }
+.terminal-3357278493-r14 { fill: #161616 }
+.terminal-3357278493-r15 { fill: #0a1e2c }
+.terminal-3357278493-r16 { fill: #9e9e9e }
+.terminal-3357278493-r17 { fill: #1a1a1a }
+.terminal-3357278493-r18 { fill: #141414 }
+.terminal-3357278493-r19 { fill: #58d1eb }
+.terminal-3357278493-r20 { fill: #98e024 }
+.terminal-3357278493-r21 { fill: #232323 }
+.terminal-3357278493-r22 { fill: #2d2d2d }
+.terminal-3357278493-r23 { fill: #0d0d0d }
+.terminal-3357278493-r24 { fill: #2e5e68 }
+.terminal-3357278493-r25 { fill: #6c0a30 }
+.terminal-3357278493-r26 { fill: #656565;font-weight: bold }
+.terminal-3357278493-r27 { fill: #455969;font-weight: bold }
+.terminal-3357278493-r28 { fill: #6c0a30;font-weight: bold }
+.terminal-3357278493-r29 { fill: #4b4b4b }
+.terminal-3357278493-r30 { fill: #121212 }
+.terminal-3357278493-r31 { fill: #704d1c;font-weight: bold }
+.terminal-3357278493-r32 { fill: #282b2e }
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
- bmad-loop
+ bmad-loop
-
-
-
- ⭘bmad-loop — ~/code/acme-search
-─Runs────────────────────────────│20260611-101500-c3d4 [sweep] ▶ running started 2026-06-11T10:15:00 epic 2
- st run type │tasks 1 done 1 deferred 0 escalated 0 153,300 tokens (369,300 raw)
-✔ 20260610-090000-a1b2 story │⚑ decision needed: DW-1 — Reopen the OAuth refresh race now, or hold it for the auth hardening epic?
- ▶ 20260611-101500-c3d4 sweep │ press a to attach and answer
-▶ 20260612-141000-e5f6 story█▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀█────────────────────────────────
-██ r
-█DW-1 — answer this decision█0a91c440 3
-██▍
-█Harden the OAuth refresh race now, or hold it for the auth-hardening epic?█
-█Two concurrent requests can both refresh the token. A single-flight lock fixes█━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-█it now, but the upcoming auth-hardening epic reworks this module anyway.█▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▎
-─Sprint─────────────────────────██▎
-▼ Epic 1 · 3/3 ✓█[1] Add a single-flight lock now · build (recommended)█▎
-├ ✓ 1-auth█ Guard the refresh path with a single-flight lock so only one refresh runs.█▎
-├ ✓ 2-session-tokens██ce now, or hold it for the▎
-├ ✓ 3-password-reset█▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔█▎
-└ ✓ retrospective█ choose 1 █▎
-▼ Epic 2 · 2/5█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█▎
-├ ✓ 1-search-index██▎
-├ ✓ 2-typeahead█[2] Hold for the auth-hardening epic · keep-open█▎
-├ ▶ 3-search-ranking█▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔█▎
-├ ◆ 4-saved-searches█ choose 2 █▎
-└ ○ 5-search-analytics█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█▎
-▼ Epic 3 · 0/2██▎
-├ · 1-billing-portal█[3] Won't fix — refresh is idempotent · close█▎
-└ · 2-invoices█ A double refresh is harmless; the second result is discarded.█▎
-██▎
-█▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔█▎
-─Deferred Work — 2 to answer (d)█ choose 3 █▎
-DW-1 Harden the OAuth token refr█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█▎
-DW-2 Add pagination to the searc██▎
-DW-3 Replace the ad-hoc ranking █▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔█▎
-DW-4 Flaky retry in the indexer █ skip █▎
-DW-5 ✓ Polish the empty-state co█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█▎
-██▎
-█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█▎
-│▊▎
-│▊▎
-│▊▎
-│▊▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▎
- y copy q quit r run s sweep e resume R resolve d decisions a attach x stop D delete A archive c cleanup v validate g setting▏^p palette
+
+
+
+ ⭘bmad-loop — ~/code/acme-search
+─Runs────────────────────────────│20260611-101500-c3d4 [sweep] ▶ running started 2026-06-11T10:15:00 epic 2
+ st run type │tasks 1 done 1 deferred 0 escalated 0 153,300 tokens (369,300 raw)
+✔ 20260610-090000-a1b2 story │⚑ decision needed: DW-1 — Reopen the OAuth refresh race now, or hold it for the auth hardening epic?
+ ▶ 20260611-101500-c3d4 sweep │ press a to attach and answer
+▶ 20260612-141000-e5f6 story█▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀█────────────────────────────────
+██ r
+█DW-1 — answer this decision█0a91c440 3
+██▍
+█Harden the OAuth refresh race now, or hold it for the auth-hardening epic?█
+█Two concurrent requests can both refresh the token. A single-flight lock fixes█━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+█it now, but the upcoming auth-hardening epic reworks this module anyway.█▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▎
+─Sprint─────────────────────────██▎
+▼ Epic 1 · 3/3 ✓█[1] Add a single-flight lock now · build (recommended)█▎
+├ ✓ 1-auth█ Guard the refresh path with a single-flight lock so only one refresh runs.█▎
+├ ✓ 2-session-tokens██ce now, or hold it for the ▎
+├ ✓ 3-password-reset█▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔█▎
+└ ✓ retrospective█ choose 1 █▎
+▼ Epic 2 · 2/5█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█▎
+├ ✓ 1-search-index██▎
+├ ✓ 2-typeahead█[2] Hold for the auth-hardening epic · keep-open█▎
+├ ▶ 3-search-ranking█▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔█▎
+├ ◆ 4-saved-searches█ choose 2 █▎
+└ ○ 5-search-analytics█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█▎
+▼ Epic 3 · 0/2██▎
+├ · 1-billing-portal█[3] Won't fix — refresh is idempotent · close█▎
+└ · 2-invoices█ A double refresh is harmless; the second result is discarded.█▎
+██▎
+█▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔█▎
+─Deferred Work — 2 to answer (d)█ choose 3 █▎
+DW-1 Harden the OAuth token refr█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█▎
+DW-2 Add pagination to the searc██▎
+DW-3 Replace the ad-hoc ranking █▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔█▎
+DW-4 Flaky retry in the indexer █ skip █▎
+DW-5 ✓ Polish the empty-state co█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█▎
+██▎
+█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█▎
+│▊▎
+│▊▎
+│▊▎
+│▊▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▎
+ y copy q quit r run s sweep e resume R resolve d decisions a attach x stop D delete A archive c cleanup v validate g setting▏^p palette
diff --git a/docs/images/deferred-modal.png b/docs/images/deferred-modal.png
index 58a1121..953ccd0 100644
Binary files a/docs/images/deferred-modal.png and b/docs/images/deferred-modal.png differ
diff --git a/docs/images/deferred-modal.svg b/docs/images/deferred-modal.svg
index 0303e87..11e94b7 100644
--- a/docs/images/deferred-modal.svg
+++ b/docs/images/deferred-modal.svg
@@ -19,232 +19,232 @@
font-weight: 700;
}
- .terminal-2838225026-matrix {
+ .terminal-1045143045-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
- .terminal-2838225026-title {
+ .terminal-1045143045-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
- .terminal-2838225026-r1 { fill: #e0e0e0 }
-.terminal-2838225026-r2 { fill: #646464 }
-.terminal-2838225026-r3 { fill: #4a4c4d }
-.terminal-2838225026-r4 { fill: #c5c8c6 }
-.terminal-2838225026-r5 { fill: #0a2c4e }
-.terminal-2838225026-r6 { fill: #646464;font-weight: bold }
-.terminal-2838225026-r7 { fill: #476419 }
-.terminal-2838225026-r8 { fill: #494949 }
-.terminal-2838225026-r9 { fill: #704717 }
-.terminal-2838225026-r10 { fill: #4a4a4a }
-.terminal-2838225026-r11 { fill: #704717;font-weight: bold }
-.terminal-2838225026-r12 { fill: #0053aa }
-.terminal-2838225026-r13 { fill: #e0e0e0;font-weight: bold }
-.terminal-2838225026-r14 { fill: #161616 }
-.terminal-2838225026-r15 { fill: #0a1e2c }
-.terminal-2838225026-r16 { fill: #1a1a1a }
-.terminal-2838225026-r17 { fill: #141414 }
-.terminal-2838225026-r18 { fill: #232323 }
-.terminal-2838225026-r19 { fill: #2e5e68 }
-.terminal-2838225026-r20 { fill: #6c0a30 }
-.terminal-2838225026-r21 { fill: #656565;font-weight: bold }
-.terminal-2838225026-r22 { fill: #455969;font-weight: bold }
-.terminal-2838225026-r23 { fill: #6c0a30;font-weight: bold }
-.terminal-2838225026-r24 { fill: #4b4b4b }
-.terminal-2838225026-r25 { fill: #6db2ff }
-.terminal-2838225026-r26 { fill: #ddedf9;font-weight: bold }
-.terminal-2838225026-r27 { fill: #004295 }
-.terminal-2838225026-r28 { fill: #121212 }
-.terminal-2838225026-r29 { fill: #704d1c;font-weight: bold }
-.terminal-2838225026-r30 { fill: #282b2e }
+ .terminal-1045143045-r1 { fill: #e0e0e0 }
+.terminal-1045143045-r2 { fill: #646464 }
+.terminal-1045143045-r3 { fill: #4a4c4d }
+.terminal-1045143045-r4 { fill: #c5c8c6 }
+.terminal-1045143045-r5 { fill: #0a2c4e }
+.terminal-1045143045-r6 { fill: #646464;font-weight: bold }
+.terminal-1045143045-r7 { fill: #476419 }
+.terminal-1045143045-r8 { fill: #494949 }
+.terminal-1045143045-r9 { fill: #704717 }
+.terminal-1045143045-r10 { fill: #4a4a4a }
+.terminal-1045143045-r11 { fill: #704717;font-weight: bold }
+.terminal-1045143045-r12 { fill: #0053aa }
+.terminal-1045143045-r13 { fill: #e0e0e0;font-weight: bold }
+.terminal-1045143045-r14 { fill: #161616 }
+.terminal-1045143045-r15 { fill: #0a1e2c }
+.terminal-1045143045-r16 { fill: #1a1a1a }
+.terminal-1045143045-r17 { fill: #141414 }
+.terminal-1045143045-r18 { fill: #232323 }
+.terminal-1045143045-r19 { fill: #2e5e68 }
+.terminal-1045143045-r20 { fill: #6c0a30 }
+.terminal-1045143045-r21 { fill: #656565;font-weight: bold }
+.terminal-1045143045-r22 { fill: #455969;font-weight: bold }
+.terminal-1045143045-r23 { fill: #6c0a30;font-weight: bold }
+.terminal-1045143045-r24 { fill: #4b4b4b }
+.terminal-1045143045-r25 { fill: #6db2ff }
+.terminal-1045143045-r26 { fill: #ddedf9;font-weight: bold }
+.terminal-1045143045-r27 { fill: #004295 }
+.terminal-1045143045-r28 { fill: #121212 }
+.terminal-1045143045-r29 { fill: #704d1c;font-weight: bold }
+.terminal-1045143045-r30 { fill: #282b2e }
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
- bmad-loop
+ bmad-loop
-
-
-
- ⭘bmad-loop — ~/code/acme-search
-─Runs────────────────────────────│20260611-101500-c3d4 [sweep] ▶ running started 2026-06-11T10:15:00 epic 2
- st run type │tasks 1 done 1 deferred 0 escalated 0 153,300 tokens (369,300 raw)
-✔ 20260610-090000-a1b2 story │⚑ decision needed: DW-1 — Reopen the OAuth refresh race now, or hold it for the auth hardening epic?
- ▶ 20260611-101500-c3d4 █▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀█
-▶ 20260612-141000-e5f6 ██───────────────────────────
-█DW-1 — Harden the OAuth token refresh race█ r
-██440 3
-█### DW-1: Harden the OAuth token refresh race█▍
-██
-█origin: epic 1 review, 2026-06-02█━━━━━━━━━━━━━━━━━━━━━━━━━━━
-█location: src/auth/tokens.py:184█▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▎
-─Sprint────────────────────█severity: high█▎
-▼ Epic 1 · 3/3 ✓█reason: Two concurrent requests can both refresh; needs a single-flight lock.█▎
-├ ✓ 1-auth█status: open█▎
-├ ✓ 2-session-tokens██w, or hold it for the▎
-├ ✓ 3-password-reset██▎
-└ ✓ retrospective██▎
-▼ Epic 2 · 2/5██▎
-├ ✓ 1-search-index██▎
-├ ✓ 2-typeahead██▎
-├ ▶ 3-search-ranking██▎
-├ ◆ 4-saved-searches██▎
-└ ○ 5-search-analytics██▎
-▼ Epic 3 · 0/2██▎
-├ · 1-billing-portal██▎
-└ · 2-invoices██▎
-██▎
-██▎
-─Deferred Work — 2 to answe██▎
-DW-1 Harden the OAuth token██▎
-DW-2 Add pagination to the ██▎
-DW-3 Replace the ad-hoc ran█▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔█▎
-DW-4 Flaky retry in the ind█ close █▎
-DW-5 ✓ Polish the empty-sta█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█▎
-██▎
-█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█▎
-│▊▎
-│▊▎
-│▊▎
-│▊▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▎
- y copy q quit r run s sweep e resume R resolve d decisions a attach x stop D delete A archive c cleanup v validate g setting▏^p palette
+
+
+
+ ⭘bmad-loop — ~/code/acme-search
+─Runs────────────────────────────│20260611-101500-c3d4 [sweep] ▶ running started 2026-06-11T10:15:00 epic 2
+ st run type │tasks 1 done 1 deferred 0 escalated 0 153,300 tokens (369,300 raw)
+✔ 20260610-090000-a1b2 story │⚑ decision needed: DW-1 — Reopen the OAuth refresh race now, or hold it for the auth hardening epic?
+ ▶ 20260611-101500-c3d4 █▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀█
+▶ 20260612-141000-e5f6 ██───────────────────────────
+█DW-1 — Harden the OAuth token refresh race█ r
+██440 3
+█### DW-1: Harden the OAuth token refresh race█▍
+██
+█origin: epic 1 review, 2026-06-02█━━━━━━━━━━━━━━━━━━━━━━━━━━━
+█location: src/auth/tokens.py:184█▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▎
+─Sprint────────────────────█severity: high█▎
+▼ Epic 1 · 3/3 ✓█reason: Two concurrent requests can both refresh; needs a single-flight lock.█▎
+├ ✓ 1-auth█status: open█▎
+├ ✓ 2-session-tokens██w, or hold it for the ▎
+├ ✓ 3-password-reset██▎
+└ ✓ retrospective██▎
+▼ Epic 2 · 2/5██▎
+├ ✓ 1-search-index██▎
+├ ✓ 2-typeahead██▎
+├ ▶ 3-search-ranking██▎
+├ ◆ 4-saved-searches██▎
+└ ○ 5-search-analytics██▎
+▼ Epic 3 · 0/2██▎
+├ · 1-billing-portal██▎
+└ · 2-invoices██▎
+██▎
+██▎
+─Deferred Work — 2 to answe██▎
+DW-1 Harden the OAuth token██▎
+DW-2 Add pagination to the ██▎
+DW-3 Replace the ad-hoc ran█▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔█▎
+DW-4 Flaky retry in the ind█ close █▎
+DW-5 ✓ Polish the empty-sta█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█▎
+██▎
+█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█▎
+│▊▎
+│▊▎
+│▊▎
+│▊▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▎
+ y copy q quit r run s sweep e resume R resolve d decisions a attach x stop D delete A archive c cleanup v validate g setting▏^p palette
diff --git a/docs/images/demo.gif b/docs/images/demo.gif
index 6918567..8a4d4a3 100644
Binary files a/docs/images/demo.gif and b/docs/images/demo.gif differ
diff --git a/docs/images/settings-scm.png b/docs/images/settings-scm.png
index 76b2baa..6fd4b31 100644
Binary files a/docs/images/settings-scm.png and b/docs/images/settings-scm.png differ
diff --git a/docs/images/settings-scm.svg b/docs/images/settings-scm.svg
index 156f49b..3b0194f 100644
--- a/docs/images/settings-scm.svg
+++ b/docs/images/settings-scm.svg
@@ -19,216 +19,216 @@
font-weight: 700;
}
- .terminal-639115204-matrix {
+ .terminal-2298416402-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
- .terminal-639115204-title {
+ .terminal-2298416402-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
- .terminal-639115204-r1 { fill: #c5c8c6 }
-.terminal-639115204-r2 { fill: #e0e0e0 }
-.terminal-639115204-r3 { fill: #a0a3a6 }
-.terminal-639115204-r4 { fill: #1e1e1e }
-.terminal-639115204-r5 { fill: #191919 }
-.terminal-639115204-r6 { fill: #a5a5a5 }
-.terminal-639115204-r7 { fill: #737373 }
-.terminal-639115204-r8 { fill: #a5a5a5;font-style: italic; }
-.terminal-639115204-r9 { fill: #7f7f7f }
-.terminal-639115204-r10 { fill: #003054 }
-.terminal-639115204-r11 { fill: #121212 }
-.terminal-639115204-r12 { fill: #000000 }
-.terminal-639115204-r13 { fill: #ffa62b;font-weight: bold }
-.terminal-639115204-r14 { fill: #495259 }
+ .terminal-2298416402-r1 { fill: #c5c8c6 }
+.terminal-2298416402-r2 { fill: #e0e0e0 }
+.terminal-2298416402-r3 { fill: #a0a3a6 }
+.terminal-2298416402-r4 { fill: #a5a5a5 }
+.terminal-2298416402-r5 { fill: #1e1e1e }
+.terminal-2298416402-r6 { fill: #7f7f7f }
+.terminal-2298416402-r7 { fill: #191919 }
+.terminal-2298416402-r8 { fill: #a5a5a5;font-style: italic; }
+.terminal-2298416402-r9 { fill: #003054 }
+.terminal-2298416402-r10 { fill: #121212 }
+.terminal-2298416402-r11 { fill: #737373 }
+.terminal-2298416402-r12 { fill: #000000 }
+.terminal-2298416402-r13 { fill: #ffa62b;font-weight: bold }
+.terminal-2298416402-r14 { fill: #495259 }
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
- bmad-loop
+ bmad-loop
-
-
-
- ⭘bmad-loop — ~/code/acme-search
-▊▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▎
-target_branch▊default: the branch checked out at run start▎
-▊▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▎
-worktree mode: branch all units merge back into (created if missing)
-
-▊▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▎
-merge_strategy▊default: merge▼▎
-▊▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▎
-worktree mode: how a unit branch lands on the target — ff, merge, or squash
-
-▊▔▔▔▔▔▔▔▔▎
-delete_branch▊▎
-▊▁▁▁▁▁▁▁▁▎
-worktree mode: delete the unit branch after a successful merge
-
-▊▔▔▔▔▔▔▔▔▎▅▅
-keep_failed▊▎
-▊▁▁▁▁▁▁▁▁▎
-worktree mode: keep a failed unit's worktree + branch mounted for inspection
-
-▊▔▔▔▔▔▔▔▔▎
-auto-rollback failed▊▎
-attempts▊▁▁▁▁▁▁▁▁▎
-
-⚠ in-place mode (isolation=none): when ON, a failed attempt's tracked changes are auto-reverted and the
-untracked files this run created are deleted (its uncommitted work is lost). When OFF (default), the
-orchestrator never touches your tree — it pauses with manual recovery steps. Governs unattended/stopped
-attempts only: a resolved escalation's re-drive always auto-recovers regardless (reverts the failed source,
-keeps the corrected spec). Prefer isolation=worktree to keep failures off your main checkout.▅▅
-
-▊▔▔▔▔▔▔▔▔▎
-seed adapter configs▊▎
-▊▁▁▁▁▁▁▁▁▎
-worktree mode: copy each loaded adapter's gitignored MCP/CLI configs (.mcp.json, .claude/settings.json,
-.codex/config.toml …) into the worktree so isolated sessions can reach their MCP server
-
-▊▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▎
-extra worktree seed files▊▎
-▊▎
-▊▎
- esc back ^s save ^e expand/collapse all q quit r run s sweep e resume R resolve d decisions a attach x stop D delete A archiv▏^p palette
+
+
+
+ ⭘bmad-loop — ~/code/acme-search
+merge_strategy▊default: merge▼▎
+▊▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▎
+worktree mode: how a unit branch lands on the target — ff, merge, or squash
+
+▊▔▔▔▔▔▔▔▔▎
+delete_branch▊▎
+▊▁▁▁▁▁▁▁▁▎
+worktree mode: delete the unit branch after a successful merge
+
+▊▔▔▔▔▔▔▔▔▎
+keep_failed▊▎
+▊▁▁▁▁▁▁▁▁▎
+worktree mode: keep a failed unit's worktree + branch mounted for inspection
+
+▊▔▔▔▔▔▔▔▔▎
+auto-rollback failed▊▎
+attempts▊▁▁▁▁▁▁▁▁▎▄▄
+
+⚠ in-place mode (isolation=none): when ON, a failed attempt's tracked changes are auto-reverted and the
+untracked files this run created are deleted (its uncommitted work is lost). When OFF (default), the
+orchestrator never touches your tree — it pauses with manual recovery steps. Governs unattended/stopped
+attempts only: a resolved escalation's re-drive always auto-recovers regardless (reverts the failed source,
+keeps the corrected spec). Prefer isolation=worktree to keep failures off your main checkout.
+
+▊▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▎
+preserve-ref retention▊default: 20▎
+▊▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▎
+attempt-preserve/* recovery branches and attempt-preserve-dirty/* worktree snapshots kept at each run start
+(per family) · the newest by committer date survive and the tail is deleted (0 = never prune)▁▁
+
+▊▔▔▔▔▔▔▔▔▎
+seed adapter configs▊▎
+▊▁▁▁▁▁▁▁▁▎
+worktree mode: copy each loaded adapter's gitignored MCP/CLI configs (.mcp.json, .claude/settings.json,
+.codex/config.toml …) into the worktree so isolated sessions can reach their MCP server
+
+▊▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▎
+extra worktree seed files▊▎
+▊▎
+▊▎
+ esc back ^s save ^e expand/collapse all q quit r run s sweep e resume R resolve d decisions a attach x stop D delete A archiv▏^p palette
diff --git a/docs/images/settings.svg b/docs/images/settings.svg
index 6f721a6..7d2025d 100644
--- a/docs/images/settings.svg
+++ b/docs/images/settings.svg
@@ -19,209 +19,209 @@
font-weight: 700;
}
- .terminal-3457620312-matrix {
+ .terminal-3186694558-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
- .terminal-3457620312-title {
+ .terminal-3186694558-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
- .terminal-3457620312-r1 { fill: #c5c8c6 }
-.terminal-3457620312-r2 { fill: #e0e0e0 }
-.terminal-3457620312-r3 { fill: #a0a3a6 }
-.terminal-3457620312-r4 { fill: #121212 }
-.terminal-3457620312-r5 { fill: #6f6f6f }
-.terminal-3457620312-r6 { fill: #ffa62b;font-weight: bold }
-.terminal-3457620312-r7 { fill: #495259 }
+ .terminal-3186694558-r1 { fill: #c5c8c6 }
+.terminal-3186694558-r2 { fill: #e0e0e0 }
+.terminal-3186694558-r3 { fill: #a0a3a6 }
+.terminal-3186694558-r4 { fill: #121212 }
+.terminal-3186694558-r5 { fill: #6f6f6f }
+.terminal-3186694558-r6 { fill: #ffa62b;font-weight: bold }
+.terminal-3186694558-r7 { fill: #495259 }
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
- bmad-loop
+ bmad-loop
-
+
-
- ⭘bmad-loop — ~/code/acme-search
-
-~/code/acme-search/.bmad-loop/policy.toml
-running engines snapshot policy at start — changes apply to new runs and resumes
-▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
-▶ gates — approval gates, escalation & retrospective behavior
-
-▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
-▶ review — separate adversarial review session toggle
-
-▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
-▶ limits — cycle/attempt caps, timeout & token budget
-
-▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
-▶ verify — post-implementation verification commands
-
-▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
-▶ notify — desktop & file notifications
-
-▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
-▶ adapter — CLI client, model & bypass flags (base for all stages)
-
-▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
-▶ adapter.dev — dev-stage adapter overrides
-
-▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
-▶ adapter.review — review-stage adapter overrides
-
-▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
-▶ adapter.triage — triage-stage adapter overrides
-
-▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
-▶ sweep — deferred-work sweep automation
-
-▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
-▶ scm — git isolation, branching & merge-back
-
-▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
-▶ cleanup — disk reclamation for .bmad-loop/runs (terminal runs only)
-
-▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
- esc back ^s save ^e expand/collapse all q quit r run s sweep e resume R resolve d decisions a attach x stop D delete A archiv▏^p palette
+
+ ⭘bmad-loop — ~/code/acme-search
+
+~/code/acme-search/.bmad-loop/policy.toml
+running engines snapshot policy at start — changes apply to new runs and resumes
+▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
+▶ gates — approval gates, escalation & retrospective behavior
+
+▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
+▶ review — separate adversarial review session toggle
+
+▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
+▶ limits — cycle/attempt caps, timeout & token budget
+
+▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
+▶ verify — post-implementation verification commands
+
+▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
+▶ notify — desktop & file notifications
+
+▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
+▶ adapter — CLI client, model & bypass flags (base for all stages)
+
+▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
+▶ adapter.dev — dev-stage adapter overrides
+
+▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
+▶ adapter.review — review-stage adapter overrides
+
+▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
+▶ adapter.triage — triage-stage adapter overrides
+
+▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
+▶ sweep — deferred-work sweep automation
+
+▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
+▶ scm — git isolation, branching & merge-back
+
+▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
+▶ cleanup — disk reclamation for .bmad-loop/runs (terminal runs only)
+
+▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
+ esc back ^s save ^e expand/collapse all q quit r run s sweep e resume R resolve d decisions a attach x stop D delete A archiv▏^p palette
diff --git a/docs/images/start-run-modal.png b/docs/images/start-run-modal.png
index efe87a1..d846434 100644
Binary files a/docs/images/start-run-modal.png and b/docs/images/start-run-modal.png differ
diff --git a/docs/images/start-run-modal.svg b/docs/images/start-run-modal.svg
index 3bf2706..dec641c 100644
--- a/docs/images/start-run-modal.svg
+++ b/docs/images/start-run-modal.svg
@@ -19,243 +19,243 @@
font-weight: 700;
}
- .terminal-1593462663-matrix {
+ .terminal-3417491320-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
- .terminal-1593462663-title {
+ .terminal-3417491320-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
- .terminal-1593462663-r1 { fill: #e0e0e0 }
-.terminal-1593462663-r2 { fill: #646464 }
-.terminal-1593462663-r3 { fill: #4a4c4d }
-.terminal-1593462663-r4 { fill: #c5c8c6 }
-.terminal-1593462663-r5 { fill: #0a2c4e }
-.terminal-1593462663-r6 { fill: #646464;font-weight: bold }
-.terminal-1593462663-r7 { fill: #476419 }
-.terminal-1593462663-r8 { fill: #494949 }
-.terminal-1593462663-r9 { fill: #704717 }
-.terminal-1593462663-r10 { fill: #4a4a4a }
-.terminal-1593462663-r11 { fill: #704717;font-weight: bold }
-.terminal-1593462663-r12 { fill: #161616 }
-.terminal-1593462663-r13 { fill: #0a1e2c }
-.terminal-1593462663-r14 { fill: #3b3b3b }
-.terminal-1593462663-r15 { fill: #1a1a1a }
-.terminal-1593462663-r16 { fill: #0b3a5f }
-.terminal-1593462663-r17 { fill: #0053aa }
-.terminal-1593462663-r18 { fill: #121212 }
-.terminal-1593462663-r19 { fill: #141414 }
-.terminal-1593462663-r20 { fill: #e0e0e0;font-weight: bold }
-.terminal-1593462663-r21 { fill: #232323 }
-.terminal-1593462663-r22 { fill: #1e1e1e }
-.terminal-1593462663-r23 { fill: #0178d4 }
-.terminal-1593462663-r24 { fill: #797979 }
-.terminal-1593462663-r25 { fill: #191919 }
-.terminal-1593462663-r26 { fill: #737373 }
-.terminal-1593462663-r27 { fill: #2e5e68 }
-.terminal-1593462663-r28 { fill: #6c0a30 }
-.terminal-1593462663-r29 { fill: #242f38 }
-.terminal-1593462663-r30 { fill: #000f18 }
-.terminal-1593462663-r31 { fill: #6db2ff }
-.terminal-1593462663-r32 { fill: #2d2d2d }
-.terminal-1593462663-r33 { fill: #ddedf9;font-weight: bold }
-.terminal-1593462663-r34 { fill: #656565;font-weight: bold }
-.terminal-1593462663-r35 { fill: #004295 }
-.terminal-1593462663-r36 { fill: #0d0d0d }
-.terminal-1593462663-r37 { fill: #455969;font-weight: bold }
-.terminal-1593462663-r38 { fill: #6c0a30;font-weight: bold }
-.terminal-1593462663-r39 { fill: #4b4b4b }
-.terminal-1593462663-r40 { fill: #704d1c;font-weight: bold }
-.terminal-1593462663-r41 { fill: #282b2e }
+ .terminal-3417491320-r1 { fill: #e0e0e0 }
+.terminal-3417491320-r2 { fill: #646464 }
+.terminal-3417491320-r3 { fill: #4a4c4d }
+.terminal-3417491320-r4 { fill: #c5c8c6 }
+.terminal-3417491320-r5 { fill: #0a2c4e }
+.terminal-3417491320-r6 { fill: #646464;font-weight: bold }
+.terminal-3417491320-r7 { fill: #476419 }
+.terminal-3417491320-r8 { fill: #494949 }
+.terminal-3417491320-r9 { fill: #704717 }
+.terminal-3417491320-r10 { fill: #4a4a4a }
+.terminal-3417491320-r11 { fill: #704717;font-weight: bold }
+.terminal-3417491320-r12 { fill: #161616 }
+.terminal-3417491320-r13 { fill: #0a1e2c }
+.terminal-3417491320-r14 { fill: #3b3b3b }
+.terminal-3417491320-r15 { fill: #1a1a1a }
+.terminal-3417491320-r16 { fill: #0b3a5f }
+.terminal-3417491320-r17 { fill: #0053aa }
+.terminal-3417491320-r18 { fill: #121212 }
+.terminal-3417491320-r19 { fill: #141414 }
+.terminal-3417491320-r20 { fill: #e0e0e0;font-weight: bold }
+.terminal-3417491320-r21 { fill: #232323 }
+.terminal-3417491320-r22 { fill: #1e1e1e }
+.terminal-3417491320-r23 { fill: #0178d4 }
+.terminal-3417491320-r24 { fill: #797979 }
+.terminal-3417491320-r25 { fill: #191919 }
+.terminal-3417491320-r26 { fill: #737373 }
+.terminal-3417491320-r27 { fill: #2e5e68 }
+.terminal-3417491320-r28 { fill: #6c0a30 }
+.terminal-3417491320-r29 { fill: #242f38 }
+.terminal-3417491320-r30 { fill: #000f18 }
+.terminal-3417491320-r31 { fill: #6db2ff }
+.terminal-3417491320-r32 { fill: #2d2d2d }
+.terminal-3417491320-r33 { fill: #ddedf9;font-weight: bold }
+.terminal-3417491320-r34 { fill: #656565;font-weight: bold }
+.terminal-3417491320-r35 { fill: #004295 }
+.terminal-3417491320-r36 { fill: #0d0d0d }
+.terminal-3417491320-r37 { fill: #455969;font-weight: bold }
+.terminal-3417491320-r38 { fill: #6c0a30;font-weight: bold }
+.terminal-3417491320-r39 { fill: #4b4b4b }
+.terminal-3417491320-r40 { fill: #704d1c;font-weight: bold }
+.terminal-3417491320-r41 { fill: #282b2e }
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
- bmad-loop
+ bmad-loop
-
-
-
- ⭘bmad-loop — ~/code/acme-search
-─Runs────────────────────────────│20260611-101500-c3d4 [sweep] ▶ running started 2026-06-11T10:15:00 epic 2
- st run type │tasks 1 done 1 deferred 0 escalated 0 153,300 tokens (369,300 raw)
-✔ 20260610-090000-a1b2 story │⚑ decision needed: DW-1 — Reopen the OAuth refresh race now, or hold it for the auth hardening epic?
- ▶ 20260611-101500-c3d4 sweep │ press a to attach and answer
-▶ 20260612-141000-e5f6 story │────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
-│ story phase dev review tokens info r
-│ dw-search-pagination done ×1 ×1 153,300 2b7f0a91c440 3
-│▍
-│JournalLogAttention
-│╸━━━━━━━╺█▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀█━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-│▊▔▔▔▔▔▔▔▔██▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▎
-─Sprint──────────────────────────│▊11:32:2█start run█▎
-▼ Epic 1 · 3/3 ✓│▊11:32:2██ons=2▎
-├ ✓ 1-auth│▊11:32:2█▊▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▎█▎
-├ ✓ 2-session-tokens│▊11:32:2█▊epic — blank for all▎█ refresh race now, or hold it for the▎
-├ ✓ 3-password-reset│▊auth …█▊▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▎█▎
-└ ✓ retrospective│▊█▊▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▎█▎
-▼ Epic 2 · 2/5│▊█▊story — 3-1, 3.1, slug, or full key (blank for all)▎█▎
-├ ✓ 1-search-index│▊█▊▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▎█▎
-├ ✓ 2-typeahead│▊█▊▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▎█▎
-├ ▶ 3-search-ranking│▊█▊max stories — blank for no limit▎█▎
-├ ◆ 4-saved-searches│▊█▊▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▎█▎
-└ ○ 5-search-analytics│▊█▊▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▎█▎
-▼ Epic 3 · 0/2│▊█▊▐X▌ dry run (print the plan, spawn nothing) ▎█▎
-├ · 1-billing-portal│▊█▊▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▎█▎
-└ · 2-invoices│▊██▎
-│▊█▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔█▎
-│▊█ start cancel █▎
-─Deferred Work — 2 to answer (d)─│▊█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█▎
-DW-1 Harden the OAuth token refr…│▊██▎
-DW-2 Add pagination to the searc…│▊█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█▎
-DW-3 Replace the ad-hoc ranking …│▊▎
-DW-4 Flaky retry in the indexer …│▊▎
-DW-5 ✓ Polish the empty-state co…│▊▎
-│▊▎
-│▊▎
-│▊▎
-│▊▎
-│▊▎
-│▊▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▎
- y copy q quit r run s sweep e resume R resolve d decisions a attach x stop D delete A archive c cleanup v validate g setting▏^p palette
+
+
+
+ ⭘bmad-loop — ~/code/acme-search
+─Runs────────────────────────────│20260611-101500-c3d4 [sweep] ▶ running started 2026-06-11T10:15:00 epic 2
+ st run type │tasks 1 done 1 deferred 0 escalated 0 153,300 tokens (369,300 raw)
+✔ 20260610-090000-a1b2 story │⚑ decision needed: DW-1 — Reopen the OAuth refresh race now, or hold it for the auth hardening epic?
+ ▶ 20260611-101500-c3d4 sweep │ press a to attach and answer
+▶ 20260612-141000-e5f6 story │────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
+│ story phase dev review tokens info r
+│ dw-search-pagination done ×1 ×1 153,300 2b7f0a91c440 3
+│▍
+│JournalLogAttention
+│╸━━━━━━━╺█▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀█━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+│▊▔▔▔▔▔▔▔▔██▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▎
+─Sprint──────────────────────────│▊22:45:1█start run█▎
+▼ Epic 1 · 3/3 ✓│▊22:45:1██ons=2▎
+├ ✓ 1-auth│▊22:45:1█▊▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▎█▎
+├ ✓ 2-session-tokens│▊22:45:1█▊epic — blank for all▎█ refresh race now, or hold it for the ▎
+├ ✓ 3-password-reset│▊█▊▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▎█▎
+└ ✓ retrospective│▊█▊▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▎█▎
+▼ Epic 2 · 2/5│▊█▊story — 3-1, 3.1, slug, or full key (blank for all)▎█▎
+├ ✓ 1-search-index│▊█▊▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▎█▎
+├ ✓ 2-typeahead│▊█▊▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▎█▎
+├ ▶ 3-search-ranking│▊█▊max stories — blank for no limit▎█▎
+├ ◆ 4-saved-searches│▊█▊▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▎█▎
+└ ○ 5-search-analytics│▊█▊▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▎█▎
+▼ Epic 3 · 0/2│▊█▊▐X▌ dry run (print the plan, spawn nothing) ▎█▎
+├ · 1-billing-portal│▊█▊▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▎█▎
+└ · 2-invoices│▊██▎
+│▊█▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔█▎
+│▊█ start cancel █▎
+─Deferred Work — 2 to answer (d)─│▊█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█▎
+DW-1 Harden the OAuth token refr…│▊██▎
+DW-2 Add pagination to the searc…│▊█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█▎
+DW-3 Replace the ad-hoc ranking …│▊▎
+DW-4 Flaky retry in the indexer …│▊▎
+DW-5 ✓ Polish the empty-state co…│▊▎
+│▊▎
+│▊▎
+│▊▎
+│▊▎
+│▊▎
+│▊▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▎
+ y copy q quit r run s sweep e resume R resolve d decisions a attach x stop D delete A archive c cleanup v validate g setting▏^p palette
diff --git a/docs/images/sweep-decision.png b/docs/images/sweep-decision.png
index 417946e..8f491b2 100644
Binary files a/docs/images/sweep-decision.png and b/docs/images/sweep-decision.png differ
diff --git a/docs/images/sweep-decision.svg b/docs/images/sweep-decision.svg
index be13a6b..68af14e 100644
--- a/docs/images/sweep-decision.svg
+++ b/docs/images/sweep-decision.svg
@@ -19,229 +19,229 @@
font-weight: 700;
}
- .terminal-2638274601-matrix {
+ .terminal-2260530837-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
- .terminal-2638274601-title {
+ .terminal-2260530837-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
- .terminal-2638274601-r1 { fill: #c5c8c6 }
-.terminal-2638274601-r2 { fill: #e0e0e0 }
-.terminal-2638274601-r3 { fill: #a0a3a6 }
-.terminal-2638274601-r4 { fill: #0053aa }
-.terminal-2638274601-r5 { fill: #e2e2e2;font-weight: bold }
-.terminal-2638274601-r6 { fill: #e0e0e0;font-weight: bold }
-.terminal-2638274601-r7 { fill: #98e024 }
-.terminal-2638274601-r8 { fill: #9d9d9d }
-.terminal-2638274601-r9 { fill: #fd971f }
-.terminal-2638274601-r10 { fill: #a1a1a1 }
-.terminal-2638274601-r11 { fill: #fd971f;font-weight: bold }
-.terminal-2638274601-r12 { fill: #ddedf9;font-weight: bold }
-.terminal-2638274601-r13 { fill: #1e1e1e }
-.terminal-2638274601-r14 { fill: #003054 }
-.terminal-2638274601-r15 { fill: #797979 }
-.terminal-2638274601-r16 { fill: #262626 }
-.terminal-2638274601-r17 { fill: #0178d4 }
-.terminal-2638274601-r18 { fill: #121212 }
-.terminal-2638274601-r19 { fill: #191919 }
-.terminal-2638274601-r20 { fill: #e1e1e1;font-weight: bold }
-.terminal-2638274601-r21 { fill: #9e9e9e }
-.terminal-2638274601-r22 { fill: #58d1eb }
-.terminal-2638274601-r23 { fill: #3e3e3e }
-.terminal-2638274601-r24 { fill: #f4005f }
-.terminal-2638274601-r25 { fill: #f4005f;font-weight: bold }
-.terminal-2638274601-r26 { fill: #ffa62b;font-weight: bold }
-.terminal-2638274601-r27 { fill: #495259 }
+ .terminal-2260530837-r1 { fill: #c5c8c6 }
+.terminal-2260530837-r2 { fill: #e0e0e0 }
+.terminal-2260530837-r3 { fill: #a0a3a6 }
+.terminal-2260530837-r4 { fill: #0053aa }
+.terminal-2260530837-r5 { fill: #e2e2e2;font-weight: bold }
+.terminal-2260530837-r6 { fill: #e0e0e0;font-weight: bold }
+.terminal-2260530837-r7 { fill: #98e024 }
+.terminal-2260530837-r8 { fill: #9d9d9d }
+.terminal-2260530837-r9 { fill: #fd971f }
+.terminal-2260530837-r10 { fill: #a1a1a1 }
+.terminal-2260530837-r11 { fill: #fd971f;font-weight: bold }
+.terminal-2260530837-r12 { fill: #ddedf9;font-weight: bold }
+.terminal-2260530837-r13 { fill: #1e1e1e }
+.terminal-2260530837-r14 { fill: #003054 }
+.terminal-2260530837-r15 { fill: #797979 }
+.terminal-2260530837-r16 { fill: #262626 }
+.terminal-2260530837-r17 { fill: #0178d4 }
+.terminal-2260530837-r18 { fill: #121212 }
+.terminal-2260530837-r19 { fill: #191919 }
+.terminal-2260530837-r20 { fill: #e1e1e1;font-weight: bold }
+.terminal-2260530837-r21 { fill: #9e9e9e }
+.terminal-2260530837-r22 { fill: #58d1eb }
+.terminal-2260530837-r23 { fill: #3e3e3e }
+.terminal-2260530837-r24 { fill: #f4005f }
+.terminal-2260530837-r25 { fill: #f4005f;font-weight: bold }
+.terminal-2260530837-r26 { fill: #ffa62b;font-weight: bold }
+.terminal-2260530837-r27 { fill: #495259 }
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
- bmad-loop
+ bmad-loop
-
-
-
- ⭘bmad-loop — ~/code/acme-search
-─Runs────────────────────────────│20260611-101500-c3d4 [sweep] ▶ running started 2026-06-11T10:15:00 epic 2
- st run type │tasks 1 done 1 deferred 0 escalated 0 153,300 tokens (369,300 raw)
-✔ 20260610-090000-a1b2 story │⚑ decision needed: DW-1 — Reopen the OAuth refresh race now, or hold it for the auth hardening epic?
- ▶ 20260611-101500-c3d4 sweep │ press a to attach and answer
-▶ 20260612-141000-e5f6 story │────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
-│ story phase dev review tokens info r
-│ dw-search-pagination done ×1 ×1 153,300 2b7f0a91c440 3
-│▍
-│JournalLogAttention
-│╸━━━━━━━╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-│▊▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▎
-─Sprint──────────────────────────│▊11:32:21 sweep-start cycle=1▎
-▼ Epic 1 · 3/3 ✓│▊11:32:21 triage-done bundles=1 already_resolved=1 decisions=2▎
-├ ✓ 1-auth│▊11:32:21 bundle-done bundle=search-pagination dw_ids=DW-2▎
-├ ✓ 2-session-tokens│▊11:32:21 decision-pending dw_id=DW-1 question=Reopen the OAuth refresh race now, or hold it for the▎
-├ ✓ 3-password-reset│▊auth …▎
-└ ✓ retrospective│▊▎
-▼ Epic 2 · 2/5│▊▎
-├ ✓ 1-search-index│▊▎
-├ ✓ 2-typeahead│▊▎
-├ ▶ 3-search-ranking│▊▎
-├ ◆ 4-saved-searches│▊▎
-└ ○ 5-search-analytics│▊▎
-▼ Epic 3 · 0/2│▊▎
-├ · 1-billing-portal│▊▎
-└ · 2-invoices│▊▎
-│▊▎
-│▊▎
-─Deferred Work — 2 to answer (d)─│▊▎
-DW-1 Harden the OAuth token refr…│▊▎
-DW-2 Add pagination to the searc…│▊▎
-DW-3 Replace the ad-hoc ranking …│▊▎
-DW-4 Flaky retry in the indexer …│▊▎
-DW-5 ✓ Polish the empty-state co…│▊▎
-│▊▎
-│▊▎
-│▊▎
-│▊▎
-│▊▎
-│▊▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▎
- y copy q quit r run s sweep e resume R resolve d decisions a attach x stop D delete A archive c cleanup v validate g setting▏^p palette
+
+
+
+ ⭘bmad-loop — ~/code/acme-search
+─Runs────────────────────────────│20260611-101500-c3d4 [sweep] ▶ running started 2026-06-11T10:15:00 epic 2
+ st run type │tasks 1 done 1 deferred 0 escalated 0 153,300 tokens (369,300 raw)
+✔ 20260610-090000-a1b2 story │⚑ decision needed: DW-1 — Reopen the OAuth refresh race now, or hold it for the auth hardening epic?
+ ▶ 20260611-101500-c3d4 sweep │ press a to attach and answer
+▶ 20260612-141000-e5f6 story │────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
+│ story phase dev review tokens info r
+│ dw-search-pagination done ×1 ×1 153,300 2b7f0a91c440 3
+│▍
+│JournalLogAttention
+│╸━━━━━━━╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+│▊▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▎
+─Sprint──────────────────────────│▊22:45:10sweep-start cycle=1▎
+▼ Epic 1 · 3/3 ✓│▊22:45:10triage-done bundles=1 already_resolved=1 decisions=2▎
+├ ✓ 1-auth│▊22:45:10bundle-done bundle=search-pagination dw_ids=DW-2▎
+├ ✓ 2-session-tokens│▊22:45:10decision-pending dw_id=DW-1 question=Reopen the OAuth refresh race now, or hold it for the ▎
+├ ✓ 3-password-reset│▊auth … ▎
+└ ✓ retrospective│▊▎
+▼ Epic 2 · 2/5│▊▎
+├ ✓ 1-search-index│▊▎
+├ ✓ 2-typeahead│▊▎
+├ ▶ 3-search-ranking│▊▎
+├ ◆ 4-saved-searches│▊▎
+└ ○ 5-search-analytics│▊▎
+▼ Epic 3 · 0/2│▊▎
+├ · 1-billing-portal│▊▎
+└ · 2-invoices│▊▎
+│▊▎
+│▊▎
+─Deferred Work — 2 to answer (d)─│▊▎
+DW-1 Harden the OAuth token refr…│▊▎
+DW-2 Add pagination to the searc…│▊▎
+DW-3 Replace the ad-hoc ranking …│▊▎
+DW-4 Flaky retry in the indexer …│▊▎
+DW-5 ✓ Polish the empty-state co…│▊▎
+│▊▎
+│▊▎
+│▊▎
+│▊▎
+│▊▎
+│▊▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▎
+ y copy q quit r run s sweep e resume R resolve d decisions a attach x stop D delete A archive c cleanup v validate g setting▏^p palette
diff --git a/module.yaml b/module.yaml
index c91c12f..684c354 100644
--- a/module.yaml
+++ b/module.yaml
@@ -1,7 +1,7 @@
code: bmad-loop
name: BMAD Loop Skills
description: "Automation-mode skills driven by the bmad-loop orchestrator: interactive escalation resolution (bmad-loop-resolve) and deferred-work sweep triage (bmad-loop-sweep) — the inner dev primitive (which self-reviews and commits) is the upstream bmad-dev-auto skill"
-module_version: 0.8.0
+module_version: 0.8.1
default_selected: false
module_greeting: >
BMAD Loop installed — both the automation skills and the
diff --git a/pyproject.toml b/pyproject.toml
index 18a9553..2302cdc 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project]
name = "bmad-loop"
-version = "0.8.0"
+version = "0.8.1"
description = "Deterministic ralph-loop orchestrator for the BMAD implementation phase"
readme = "README.md"
license = "MIT"
diff --git a/src/bmad_loop/__init__.py b/src/bmad_loop/__init__.py
index 77218c8..f9f12a2 100644
--- a/src/bmad_loop/__init__.py
+++ b/src/bmad_loop/__init__.py
@@ -6,4 +6,4 @@
spec files, and the per-run directory under .bmad-loop/runs/.
"""
-__version__ = "0.8.0"
+__version__ = "0.8.1"
diff --git a/src/bmad_loop/data/skills/bmad-loop-setup/assets/module.yaml b/src/bmad_loop/data/skills/bmad-loop-setup/assets/module.yaml
index c91c12f..684c354 100644
--- a/src/bmad_loop/data/skills/bmad-loop-setup/assets/module.yaml
+++ b/src/bmad_loop/data/skills/bmad-loop-setup/assets/module.yaml
@@ -1,7 +1,7 @@
code: bmad-loop
name: BMAD Loop Skills
description: "Automation-mode skills driven by the bmad-loop orchestrator: interactive escalation resolution (bmad-loop-resolve) and deferred-work sweep triage (bmad-loop-sweep) — the inner dev primitive (which self-reviews and commits) is the upstream bmad-dev-auto skill"
-module_version: 0.8.0
+module_version: 0.8.1
default_selected: false
module_greeting: >
BMAD Loop installed — both the automation skills and the
diff --git a/src/bmad_loop/tui/widgets.py b/src/bmad_loop/tui/widgets.py
index 4fa72fe..6c4df70 100644
--- a/src/bmad_loop/tui/widgets.py
+++ b/src/bmad_loop/tui/widgets.py
@@ -11,6 +11,7 @@
from pathlib import Path
from typing import Any
+from rich.table import Table
from rich.text import Text
from textual.selection import Selection
from textual.widgets import RichLog, Static, Tree
@@ -166,23 +167,34 @@ def show_run(
# the journal -> log jump, not the human
_JOURNAL_HIDDEN_FIELDS = ("ts", "kind", "log_task", "log_pos")
+# Row-grid geometry. The fields column's left edge sits at
+# _JOURNAL_CLOCK_WIDTH + _JOURNAL_COL_PAD + _JOURNAL_KIND_WIDTH + _JOURNAL_COL_PAD;
+# the hanging-indent test derives its indent from the same constants so the two
+# can't silently drift apart.
+_JOURNAL_CLOCK_WIDTH = 8
+_JOURNAL_KIND_WIDTH = 24
+_JOURNAL_COL_PAD = 1 # per-column right pad in the row grid
-def journal_line(entry: dict[str, Any]) -> Text:
+
+def journal_line(entry: dict[str, Any]) -> Table:
kind = str(entry.get("kind", "?"))
style = next((s for sub, s in _JOURNAL_STYLES if sub in kind), "dim")
ts = entry.get("ts")
clock = ""
if isinstance(ts, (int, float)):
clock = time.strftime("%H:%M:%S", time.localtime(ts))
- text = Text()
- text.append(f"{clock:8s} ", style="dim")
- text.append(f"{kind:24s}", style=style)
fields = " ".join(
f"{k}={_short(v)}" for k, v in entry.items() if k not in _JOURNAL_HIDDEN_FIELDS
)
- if fields:
- text.append(" " + fields)
- return text
+ # A grid per row so the fields cell folds within its own column (hanging
+ # indent) instead of wrapping back under the clock/kind columns. A long kind
+ # likewise folds within its own column rather than spilling into the fields.
+ grid = Table.grid(padding=(0, _JOURNAL_COL_PAD, 0, 0))
+ grid.add_column(width=_JOURNAL_CLOCK_WIDTH)
+ grid.add_column(width=_JOURNAL_KIND_WIDTH, overflow="fold")
+ grid.add_column(overflow="fold")
+ grid.add_row(Text(clock, style="dim"), Text(kind, style=style), Text(fields))
+ return grid
class JournalEntryOption(Option):
diff --git a/tests/test_tui_app.py b/tests/test_tui_app.py
index 5fe7c63..c515a64 100644
--- a/tests/test_tui_app.py
+++ b/tests/test_tui_app.py
@@ -12,6 +12,7 @@
import pytest
from conftest import install_bmad_config, write_sprint
+from rich.console import Console
from rich.text import Text
from textual.geometry import Offset
from textual.selection import Selection
@@ -39,7 +40,15 @@
StartSweepModal,
TextOutputModal,
)
-from bmad_loop.tui.widgets import RunHeader, SelectableRichLog, SprintTree
+from bmad_loop.tui.widgets import (
+ _JOURNAL_CLOCK_WIDTH,
+ _JOURNAL_COL_PAD,
+ _JOURNAL_KIND_WIDTH,
+ RunHeader,
+ SelectableRichLog,
+ SprintTree,
+ journal_line,
+)
def make_run(
@@ -270,7 +279,14 @@ async def test_token_weight_falls_back_to_default(project):
def journal_rows(journal: OptionList) -> list[str]:
- return [str(journal.get_option_at_index(i).prompt) for i in range(journal.option_count)]
+ # Journal prompts are Rich Table grids, so render them to plain text.
+ console = Console(width=400)
+ rows = []
+ for i in range(journal.option_count):
+ with console.capture() as capture:
+ console.print(journal.get_option_at_index(i).prompt)
+ rows.append(capture.get())
+ return rows
def log_text(screen: DashboardScreen) -> str:
@@ -296,6 +312,30 @@ def has_entry() -> bool:
assert any("1-2-search" in row for row in journal_rows(journal))
+def test_journal_line_wraps_fields_with_hanging_indent():
+ entry = {
+ "ts": 1_750_000_000,
+ "kind": "session-start",
+ "task_id": "6-1-sound-as-information-audio-layer-dev-1",
+ "role": "dev",
+ "prompt": "/bmad-dev-auto 6-1-sound-as-information-audio-layer",
+ }
+ console = Console(width=60)
+ with console.capture() as capture:
+ console.print(journal_line(entry))
+ lines = capture.get().splitlines()
+ assert len(lines) > 1 # fields are long enough to wrap at width 60
+ assert "session-start" in lines[0]
+ # continuation lines stay in the fields column, never spilling back under
+ # the clock/kind columns. The fields column's left edge is derived from the
+ # same width constants journal_line lays the grid out with.
+ indent = _JOURNAL_CLOCK_WIDTH + _JOURNAL_COL_PAD + _JOURNAL_KIND_WIDTH + _JOURNAL_COL_PAD
+ for line in lines[1:]:
+ assert line[:indent] == " " * indent
+ # and the wrapped fields carry real content past the indent
+ assert any(line[indent:].strip() for line in lines[1:])
+
+
async def test_log_pane_shows_emulated_content(project):
from test_tui_data import ink_stream
diff --git a/uv.lock b/uv.lock
index bc0ecb1..908e843 100644
--- a/uv.lock
+++ b/uv.lock
@@ -4,7 +4,7 @@ requires-python = ">=3.11"
[[package]]
name = "bmad-loop"
-version = "0.8.0"
+version = "0.8.1"
source = { editable = "." }
dependencies = [
{ name = "pyyaml" },