Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,19 @@ breaking changes may land in a minor release.
forced selection. A tmux-less POSIX host still selects `TmuxMultiplexer` and reports it
unavailable, exactly as before.

- **Herdr TUI-launch surface.** The herdr backend now covers everything `tui/launch.py` drives:
parked orchestrator windows (a typed `exec sh -c '<argv>; banner; read; trailer'` recipe,
tmux-identical from the operator's seat, with the return-to-origin target mirrored into a
per-window return file the trailer consumes), tmux-style `=session[:window]` target parsing
across select/kill/option/attach methods, `list_windows` tmux-field mapping
(`window_id`/`window_name`/`@option`), finalized `attach_target_argv` (blocking
`terminal attach` outside herdr, fire-and-forget `tab focus` inside), and `switch_client`
via `tab focus`. The TUI/CLI attach flows and `in_ctl_session` now ask the seam
(`current_pane_id()`/`current_session()`) instead of sniffing `TMUX`, so they work under any
backend; the tmux backend's `current_*` gained the TMUX guard that keeps "not inside" honest.
Remaining herdr degradations: `detach_client` stays a no-op (the post-exit detach return rides
pane-close ending `terminal attach`; only the mid-process hand-back degrades to staying
attached), and `switch_client` has no last-client fallback.
- **Herdr multiplexer backend (opt-in, non-tmux-family).** A new `herdr` transport implements
the `TerminalMultiplexer` seam _fresh_ (subclassing nothing) over
[herdr](https://herdr.dev)'s cross-platform workspace/tab/pane model — Unix socket on POSIX,
Expand All @@ -65,9 +78,8 @@ breaking changes may land in a minor release.
session/window options (herdr has none; writes lock-guarded via a new cross-platform
`platform_util.file_lock`), lazy server autostart, and a protocol-version guard
(fail-below / warn-above). Landed as one registration line plus one sanctioned `probe.py` gate
fix — zero portability-guard allowlist changes. The TUI-launch surface (parked windows,
attach/detach, full window options) is a follow-up PR; until then those degrade to raises / no-ops
(see the backend module docstring's degradation ledger).
fix — zero portability-guard allowlist changes. The TUI-launch surface landed as a second PR
(previous entry); the remaining degradations are in the backend module docstring's ledger.
- **Stories mode — a second planning pipeline that drives the loop off a typed `stories.yaml` (folder+id dispatch) instead of `sprint-status.yaml`.** Opt in with `[stories] source = "stories"` + `spec_folder`, or per run with `bmad-loop run --spec <folder>` (overrides policy); `--story` then filters by story id. Each entry dispatches by folder + id — the dev skill creates-or-resumes the story spec at `<folder>/stories/<id>-<slug>.md` and the orchestrator reads that id-keyed path back deterministically (no shared board to line-edit, no result-artifact mtime-scan). Strictly linear schedule (list order, no `depends_on`); `bmad-loop run --dry-run --spec <folder>` and `bmad-loop status` print the board (id · live disk state · checkpoint markers · title). Sprint mode is unchanged and remains the default. Requires a `bmad-dev-auto` new enough for folder+id dispatch — the run preflight checks and remediates.
- **Per-story human checkpoints (stories mode).** Independent `spec_checkpoint` (pause before code to review the plan — dev halts at `ready-for-dev`; approve to implement, or request a replan that resets the spec to `draft`) and `done_checkpoint` (pause after the story commits, skipped when it is the last story); both additive to `gates.mode`. A blocked story escalates + resolves as in sprint mode, with a pre-planning-halt sentinel auto-deleted (a copy preserved under the run dir) on re-arm.
- **TUI human-in-the-loop surface for stories mode.** The sprint tree is replaced by a stories board (id · live disk state · spec/done checkpoint markers · title) when a stories-mode run is selected; paused runs carry a per-run pause-kind badge and the run list shows a global _⚑ N need attention_ count; `p` opens the stage-appropriate viewer — plan-checkpoint spec review (Approve & resume / Request replan), story-checkpoint summary card (Continue / Stop), escalation with story context (Resolve / Re-arm & resume), and a gate spec viewer that the existing spec-approval/epic pauses reuse. The start-run modal gains a source select + spec-folder field with a live schedule preview. Every TUI action calls the same code paths as the CLI.
Expand Down
5 changes: 3 additions & 2 deletions docs/ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Status legend: **planned** (agreed, not started) · **exploring** (shape still o

## Native Windows multiplexer backend

**Status:** planned · **Foundation:** the full platform-seam series landed (multiplexer registry + `BaseTmuxBackend` + `ProcessHost` + hook interpreter + validate preflight, v0.7.6; availability-aware backend selection + `bmad-loop mux`, #87; original seam v0.7.0) · a first non-tmux-family, native-Windows-capable backend — **herdr** — now ships for the engine run path (TUI-launch surface follows in a second PR)
**Status:** planned · **Foundation:** the full platform-seam series landed (multiplexer registry + `BaseTmuxBackend` + `ProcessHost` + hook interpreter + validate preflight, v0.7.6; availability-aware backend selection + `bmad-loop mux`, #87; original seam v0.7.0) · a first non-tmux-family, native-Windows-capable backend — **herdr** — now ships end-to-end on POSIX (engine run path + TUI-launch surface; the win32 `agent.start` launch path is the remaining follow-up)
Comment thread
pbean marked this conversation as resolved.

The orchestrator no longer fuses tmux into the engine. All session/window/pane operations
go through a single `TerminalMultiplexer` ABC (`src/bmad_loop/adapters/multiplexer.py`),
Expand Down Expand Up @@ -43,7 +43,8 @@ availability-aware with discriminating `available()` probes (psmux →
`which("psmux") and which("tmux") and which("pwsh")`; tmux-windows →
`which("tmux") and not which("psmux")`) and an explicit `bmad-loop mux set <name>` tie-break.

The third — **herdr** — has **shipped** (for the engine run path) as a
The third — **herdr** — has **shipped** end-to-end on POSIX (engine run path +
TUI-launch surface) as a
different-binary-family backend: it implements `TerminalMultiplexer` fresh over herdr's
workspace/tab/pane model rather than subclassing `BaseTmuxBackend`, and probes
`which("herdr")`, so it is pairwise-discriminating against the tmux family by construction
Expand Down
9 changes: 5 additions & 4 deletions docs/porting-to-a-new-os.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,11 @@ version, and the current selection. (The result is cached — see
session is a herdr **workspace** (label == session name), a window is a **tab**
(its `root_pane.pane_id` is the native window id), and the launched command runs
via a typed `exec <argv>` so process-exit stays tmux-identical window death.
Where herdr has no analogue for a contract method — options, `pipe_pane`, parked
windows, detach — it degrades honestly (a JSON sidecar for options, a polling
tee for `pipe_pane`, a raise / no-op for the rest); that **degradation ledger**
is the module docstring, and it is the template for what "implement fresh" costs
Where herdr has no analogue for a contract method — options, `pipe_pane`,
the parked-window return hop, detach — it emulates or degrades honestly (a
JSON sidecar for options, a polling tee for `pipe_pane`, a per-window return
file for the parked trailer, a no-op detach); that **degradation ledger** is
the module docstring, and it is the template for what "implement fresh" costs
in practice.

`available()` gates whether the backend is usable on the current host (e.g. its
Expand Down
Loading
Loading