Skip to content

feat(adapters): opencode dev/review synthesis parity (Phase 4)#166

Merged
pbean merged 1 commit into
mainfrom
feat/opencode-dev-synthesis
Jul 16, 2026
Merged

feat(adapters): opencode dev/review synthesis parity (Phase 4)#166
pbean merged 1 commit into
mainfrom
feat/opencode-dev-synthesis

Conversation

@pbean

@pbean pbean commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

Phase 4 of the opencode-http adapter plan (#163#164#165 → this): hookless dev/review roles now run the real bmad-dev-auto loop over HTTP/SSE.

What

  • OpencodeDevAdapter(_DevSynthesisMixin, OpencodeHttpAdapter) — the Phase 2 synthesis mixin composed over the Phase 3 transport, paths= kwarg + _configure_dev_knobs(), mirroring GenericDevAdapter. Terminal-spec synthesis, stories mode, DW bundles, plan-halt, and the Hardening: reconcile seam is unreachable for stalled sessions — a finished-but-lost-Stop session cannot be recovered as completed #61 post-kill rescue all arrive via the mixin unchanged (no fork of the synthesis logic; devcontract.py and generic.py untouched).
  • _probe_alive (the one seam the host must implement) = poll() on a per-task Popen stash populated in start_session and kept past kill() — the kill pops the _ServerSession registry before _post_kill_reconcile runs, and the retained handle answers liveness truthfully: never None (no probe that can hang), True when a force-kill-surviving process means the live-server invariant still applies.
  • MRO note: the mixin's _result_json (spec synthesis) deliberately shadows the core adapter's result.json read-back — the dev skill writes no result.json, and a unit test pins that.
  • _make_adapters: synthesizing hookless roles construct OpencodeDevAdapter (shared per (cfg, synthesizes) key); the temporary Phase 3 SystemExit guard is deleted, and cmd_validate's mirroring FAIL (added in feat(adapters): core opencode-http adapter over HTTP/SSE (Phase 3) #165's review round to match the guard) is removed with it.

Tests

FakeOpencode gains a spec-write mechanic (FAKE_OPENCODE_SPEC_PATH/_SPEC_TEXT, no-op when unset — existing scenarios byte-compatible). New coverage:

  • E2E terminal-spec synthesis: scripted turn writes a status: done + ## Auto Run Result spec → synthesized dict matches devcontract (auto-dev, baseline_commit, story_key), usage captured, template-rendered prompt, clean teardown, and no FAKE_OPENCODE_RESULT_PATH set — proving dev never leans on result.json.
  • E2E stories mode: BMAD_LOOP_SPEC_FOLDER id-keyed resolve with the mtime scan monkeypatched to raise.
  • E2E post-kill rescue: spec written, idle never delivered (fake stays busy) → timeout under a live server → run()'s kill settles liveness → rescued completed with post_kill_reconciled: true.
  • Units: dev knobs from policy, never-None probe tri-state, result.json-shadowing MRO pin.
  • test_cli.py: guard tests flipped to their post-Phase-4 counterparts (dispatch + validate-passes).

All tests bind 127.0.0.1 and reuse the Phase 3 Windows-safe harness mechanics. CHANGELOG deferred to Phase 5 by plan design.

Verification

  • Full suite: 2314 passed, 1 skipped
  • trunk fmt (black) + full trunk check (no filter): clean

OpencodeDevAdapter composes _DevSynthesisMixin over OpencodeHttpAdapter,
so hookless dev/review sessions run the real bmad-dev-auto loop: terminal-
spec synthesis via devcontract, stories-mode id-keyed resolve, DW bundles,
plan-halt, and the #61 post-kill rescue — all mixin-shared with
GenericDevAdapter, never duplicated.

- _probe_alive = poll() on a per-task Popen stash kept past kill(): the
  kill pops the _ServerSession registry before _post_kill_reconcile runs,
  and the retained handle answers liveness truthfully (never unknown).
- _make_adapters: synthesizing hookless roles dispatch OpencodeDevAdapter
  (paths= wired); the temporary Phase 3 SystemExit guard is gone, and
  cmd_validate's mirroring FAIL goes with it.
- FakeOpencode grows a spec-write mechanic (FAKE_OPENCODE_SPEC_PATH/_TEXT,
  no-op when unset); dev E2E covers terminal-spec synthesis, stories mode,
  and the timeout->rescue path, plus unit pins for the dev knobs, the
  never-None probe, and the result.json-shadowing MRO.
@pbean

pbean commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator Author

@CodeRabbit review

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Action performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@pbean
pbean merged commit d3beea8 into main Jul 16, 2026
9 checks passed
@pbean
pbean deleted the feat/opencode-dev-synthesis branch July 17, 2026 14:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant