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
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ story <id>`, the same annotation a sweep bundle writes. Both sprint and stories
upstream skill emits it yet (BMAD-METHOD#2619 proposes it at breakdown), and re-deriving
`stories.yaml` drops it unless the intent is logged in `.memlog.md`.

- **Readable run logs for `opencode-http` (#306).** Contributed by
[@jackmcintyre](https://github.com/jackmcintyre). The HTTP adapter has no tmux pane to replay,
so a finished opencode run left `logs/<task-id>.log` holding nothing but the server's own INFO
stdout. Per-session logs now split three ways, rendered off the SSE stream the adapter already
reads for completion:
- `<task-id>.log` — curated transcript: role-prefixed agent/user prose plus `[bmad]` marker
lines for tool calls, slash commands, file edits, permission asks/replies and session errors.
- `<task-id>.server.out` — the server's own stdout, no longer mixed into the transcript.
- `<task-id>.sse.jsonl` — structured trace of the raw SSE frames for post-hoc debugging.

- **`review.on_timeout` policy knob (#271).** A timeout-like review verdict (`timeout` /
`stalled` / `over_budget`) previously always burned a review cycle (RETRY) until
`max_review_cycles`, then deferred — even when the dev product was already finalized and
Expand Down
2 changes: 1 addition & 1 deletion docs/FEATURES.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ See [README.md](../README.md) for the narrative overview and [setup-guide.md](se
- Generic adapter drives any CLI fitting the injection + hook-signal transport; CLI specifics live in declarative TOML profiles. Two independent axes: the **CLI** (`CodingCLIAdapter` + profile) and the **terminal transport** (`TerminalMultiplexer`) — tmux ships bundled (with an experimental native-Windows `psmux` backend alongside it), and external backends (e.g. the [herdr adapter](https://github.com/pbean/bmad-loop-adapter-herdr)) co-install as packages that self-register ([how](multiplexer-backends.md)), behind a pluggable seam that lets a new backend slot in without touching the engine (see the [adapter authoring guide](adapter-authoring-guide.md#two-axes-cli-vs-transport)).
- The OS is abstracted by a **registry of seams**, each selecting an implementation by platform (with a test-override env var) and extended by a single registration line: the terminal multiplexer (`register_multiplexer`, with availability-aware selection: env var → persisted `[mux] backend` via `bmad-loop mux set` → platform default → first available platform match), the process-lifecycle `ProcessHost` (`register_process_host` — `terminate`/`force_kill`/`is_alive`/`identity`), and the hook interpreter (`ProcessHost.hook_interpreter()`); `bmad-loop validate` runs a platform preflight over them. Porting to a new OS is new files + registrations, no core edits — see [Porting bmad-loop to a new OS](porting-to-a-new-os.md).
- Supported, E2E-verified: `claude` (reference), `codex` (≥ 0.139), `gemini` (≥ 0.46), `copilot` (GitHub Copilot CLI ≥ 2026-02 — the `copilot` binary, not the VS Code extension; `agentStop` turn-end, `-i` interactive launch, `--allow-all-tools`; pin a capable model — the free GPT-5 mini default is unreliable for multi-step skills).
- Supported, E2E-verified over HTTP/SSE (no tmux window): `opencode` (OpenCode ≥ 1.18, profile `opencode-http`, alias `opencode`) — one headless `opencode serve` per session, SSE `session.idle` completion with an HTTP poll fallback, per-session server password, token usage read back over the API. Hookless (`[hooks] dialect = "none"`, no hook registration). Install the extra (`pip install 'bmad-loop[opencode]'`), auth once globally (`opencode auth login`), and set `model` as `provider/model`; the Unity plugin's window guards don't apply (there is no window).
- Supported, E2E-verified over HTTP/SSE (no tmux window): `opencode` (OpenCode ≥ 1.18, profile `opencode-http`, alias `opencode`) — one headless `opencode serve` per session, SSE `session.idle` completion with an HTTP poll fallback, per-session server password, token usage read back over the API. Hookless (`[hooks] dialect = "none"`, no hook registration). With no pane to replay, the run logs split three ways: a curated readable transcript in `logs/<task-id>.log` (agent/user prose, tool calls, slash commands, file edits, permission asks/replies, errors), the server's own stdout in `<task-id>.server.out`, and a structured SSE trace in `<task-id>.sse.jsonl`. Install the extra (`pip install 'bmad-loop[opencode]'`), auth once globally (`opencode auth login`), and set `model` as `provider/model`; the Unity plugin's window guards don't apply (there is no window).
- Experimental, `isolation = "none"` only: `antigravity` (Google's `agy` ≥ 1.1.3) — `-i` interactive launch, `Stop` turn-end hook (flat handler in `.agents/hooks.json`, no SessionStart/SessionEnd), `--dangerously-skip-permissions` for unattended runs; `usage_parser = "none"` permanently — agy's transcript exposes no usage data (tokens live only in an internal SQLite/protobuf store). `agy` gates each workspace on an exact-path `trustedWorkspaces` entry and blocks on an interactive trust dialog, which `--dangerously-skip-permissions` does not bypass — so worktree isolation hangs ([#169](https://github.com/bmad-code-org/bmad-loop/issues/169)). Verify against your `agy` build with `probe-adapter antigravity`.
- Per-stage CLI/model overrides: run dev on one CLI/model, review on another (`[adapter.dev]`, `[adapter.review]`, `[adapter.triage]`).
- Add a CLI without touching Python: drop a TOML profile in `.bmad-loop/profiles/<name>.toml` (binary, prompt template, bypass flags, hook dialect, native→canonical event map).
Expand Down
14 changes: 14 additions & 0 deletions docs/adapter-authoring-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,20 @@ decisions worth stealing:
loss. Completion evidence is gated by a forward-advancing floor so an idle
event without proof of new work never completes a session — the same
artifact-distrust invariant the tmux adapters enforce.
- **A transport with no pane still owes the operator a transcript.** The tmux
adapters get `logs/<task-id>.log` for free by replaying the pane; over HTTP that
file would hold nothing but `opencode serve`'s own INFO stdout, leaving finished
runs unreadable. So the transcript is _curated_ off the SSE stream the adapter
already consumes for control — a second consumer on the same
`sessionID`-filtered dispatch, costing one `write()` per interesting frame.
Three sinks, one per audience: `<task-id>.log` is the readable transcript
(role-prefixed prose plus `[bmad]`-marked `tool:` / `cmd:` / `file:` /
`perm ask:` / `perm reply:` / `error:` lines), `<task-id>.server.out` takes the
server's own stdout so it cannot drown that transcript, and
`<task-id>.sse.jsonl` keeps the raw frames for post-hoc debugging (behind the
`sse_trace` module knob, per-token deltas excluded). The catch of curating:
what you render is only as good as the event names you pinned — check every
branch against the running binary, not against the names that read plausibly.
- **Hookless profile.** The profile sets `[hooks] dialect = "none"`: no hook
registration, no hook-config merge into worktrees; `init`, `validate` and
worktree provisioning all understand `profile.hookless`. Skills still install
Expand Down
5 changes: 4 additions & 1 deletion docs/setup-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,10 @@ them to whoever owns the machine:
workspace-trust dialog to answer). Requires OpenCode ≥ 1.18. Set the model as
`provider/model` (e.g. `[adapter] model = "anthropic/claude-haiku-4-5"`). No hooks are
registered — the adapter drives a headless `opencode serve` over HTTP/SSE, so there is no
tmux window to attach to; watch a session via its `logs/<task-id>.log` or the TUI Log tab.
tmux window to attach to; watch a session via its `logs/<task-id>.log` — a curated
transcript of the agent's prose, tool calls, file edits and permission decisions — or the
TUI Log tab. The server's own stdout lands beside it in `<task-id>.server.out`, and a
structured trace of the raw SSE frames in `<task-id>.sse.jsonl`.

### Skill location

Expand Down
Loading