エージェント・ハーネス設計 v4 — 実装を OpenCode(Muse Spark)へ¶
2026-09-04 ユーザー指示。v3(2026-08-14-agent-harness-design-v3.md・oh-my-beads 統合)の役割分担を、
実装担当だけ OpenCode(Muse Spark 1.3 Contributor・reasoning xhigh)へ差し替える。計画・設計・検証ゲート・
リリースは Claude Fable 5.1(コーディネーター)、敵対レビューは codex gpt-5.6-sol(reasoning max)のまま。
Beads(bd)でタスク状況を全エージェントに連携し、Fable がオーケストレーターとして全体を管理する。
役割¶
| 役割 | エージェント | 実行場所 | 起動 |
|---|---|---|---|
| 計画・設計・検証ゲート・リリース・bd 管理 | Claude Fable 5.1 | wastelink-coordinator worktree |
対話セッション |
| 実装 | OpenCode Muse Spark 1.3 Contributor(xhigh) | 実装用 worktree(exec-muse) |
nohup opencode run --agent implementer "<指示書パス>" > log 2>&1 & + PID 監視 |
| 敵対レビュー | codex gpt-5.6-sol(max) | review-sol worktree |
nohup codex exec --model gpt-5.6-sol -c model_reasoning_effort="max" --sandbox danger-full-access -C <wt> "<指示書パス参照>" + PID 監視 |
受け渡しは v3 と同じ: コーディネーターが bd 起票 → .worker-specs/*.md に指示書 → ワーカー起動 → 完了は
プロセス exit を主信号に検知 → 報告書 .worker-specs/*-report.md を検分 → PR → sol → APPROVE + CI 全 pass で
マージ → bd close。
ハーネスの組み込み(実測 2026-09-04)¶
| 要素 | Claude | Codex(sol) | OpenCode(Muse) |
|---|---|---|---|
| AGENTS.md(正典) | CLAUDE.md が @AGENTS.md |
ネイティブ読込(verdict で不変条件を参照した実績) | .opencode/opencode.json の instructions で明示(実測: Routing 節を正しく回答) |
.beads/PRIME.md(bd 運用) |
SessionStart hook で注入 | 未注入(レビュー専任・bd 不使用) | instructions で明示 |
| bd の破壊コマンド抑止 | oh-my-beads PreToolUse hook | 無し(不使用) | permission.bash で bd close* 等を deny(実測: deny 動作) |
| superpowers skills | plugin | plugin(openai-curated) | グローバル skills.paths(実測: TDD / verification を認識) |
| impeccable / DESIGN.md | ~/.claude/skills |
不要 | ~/.claude/skills を自動ロード |
| verify / docker proof / scenario | bash | bash(実績) | bash(build 系 agent は allow) |
.worker-specs 受け渡し |
ファイル | ファイル(実績) | ファイル |
| 長期メモリ | ~/.claude/projects/.../memory |
無し(指示書で補完) | 無し(指示書で補完) |
| orca 連携 | hooks | 常駐 TUI | orca の OpenCode plugin(status) |
OpenCode 側の設定¶
- グローバル
~/.config/opencode/opencode.json: providermeta(https://api.meta.ai/v1)・muse-spark-1.3-contributor(reasoningEffortxhigh・context 1,048,576 / output 131,072)を既定モデル・skills.pathsに superpowers。 認証はopencode auth(auth.json)が優先される(Meta のインストールスクリプトが書くmeta-api-keyファイル参照より前)。 - リポジトリ
.opencode/opencode.json:instructions: ["AGENTS.md", ".beads/PRIME.md"]・permission.bashの deny (bd close|delete|dolt push|dolt reset|edit・git push --force|-f・git reset --hard・git stash pop・main への checkout/switch)・question: deny(headless で止まらない)・doom_loop: allow。 - リポジトリ
.opencode/agent/implementer.md: 実装ワーカー agent(model・permission・共通規律 = 指示書を最初に読む・TDD・ verification-before-completion・カタログ最新写経・proof の歯・秘密不コミット・bd は note のみ・PR を作らない・報告書)。 - 投入プロンプトは指示書パスを参照する短い英文にする(長い日本語プロンプトは同梱 codex 0.146 で
input[0] invalid_requestを起こした実績があり、OpenCode でも同じ形を採る)。
移行の手順¶
- S2 R2(codex luna・実行中)は完走させ、S3 から OpenCode で投入する。
- 小タスクで OpenCode → sol の一巡を試し、品質・ゲート遵守・xhigh の応答時間を確認する。
- 実装用 worktree
exec-museを orca で新設し、codex 用exec-lunaは縮退(同一 worktree で 2 エージェントを混ぜない)。 - AGENTS.md Routing 節・
.beads/PRIME.md「ワーカー別の bd 規約」・長期メモリ(役割固定・投入手順)を更新済み(本 PR)。
判断の記録¶
- hook を持たないワーカー(OpenCode / Codex)では、bd の規約を permission の deny で「守らせる」のではなく、 指示書と PRIME.md で「伝える」。deny は最後の防衛線。
- OpenCode の認証は auth.json 優先。
meta-api-keyファイルは Meta スクリプトの互換のために残すが、実際の認証には使われない。 - 実装 = Claude 代替は、ワーカーが障害で使えないときの例外に限り、その場合も sol の事後レビューを省かない(S1 R2 の実例)。
初回運用で見つかった罠と是正(2026-09-04・S3 wl-luvw)¶
- 事象: OpenCode implementer が S3 の scenario 全緑・tsc 緑の直後、mutation 手順の
cp … /tmp/…でexternal_directory (/tmp/*)権限を求め、非対話opencode runが自動拒否 → モデルが「ユーザーが拒否した」と解釈して turn を終了(プロセス exit)。verify・commit・報告書が未了のまま止まった。 - 是正:
.opencode/opencode.jsonのpermission.external_directoryに/tmp/*/private/tmp/*を allow。 implementer agent に「permission エラーで止まらない」「一時ファイルは.worker-specs/tmp/」を追加。 再開はopencode run --agent implementer --session <ses_id> "<続きの指示>"(opencode session listで ID)。 - 教訓: 非対話ワーカーの「ask」は全部「deny」と同じ。許可したい操作は設定で allow に落とし、指示書で代替経路を明示する。
- 2 回目(同日・S3 R2): 兄弟ワークツリー
review-sol/.worker-specs/の verdict を読もうとしてexternal_directoryが自動拒否。external_directoryはプロジェクトルート外の全パスに当たる(兄弟 worktree も含む)。是正: 他 worktree の成果物は投入前に コーディネーターが.worker-specs/へコピーし、指示書はワークツリー内の相対パスで参照する。グローバル設定にワークスペース配下の allow も追加。
可視化の形 C(2026-09-04・ユーザー要望「各ワークツリーのセッションに渡す仕組みじゃダメなのか」への裁定)¶
ワークツリーは wastelink-coordinator(Claude)/ exec-muse(OpenCode)/ review-sol(codex sol)の 3 本に整理した(古い 13 本は削除・
すべて PR MERGED・dirty 0 を実測してから)。作業の見え方について 3 案を比較し、C を採用した。
| 形 | 見え方 | 完了検知 | 課題 |
|---|---|---|---|
A. 常駐 TUI に orca terminal send で渡す(v3 で試行) |
Orca でそのまま見える | tui-idle の推定のみ |
長いツール実行中を idle と誤判定した偽陽性。1 セッションにタスクが積み上がり前タスクの文脈が混入(無関係セッション接続でリリース済 migration を再編集した事故)。対話の承認プロンプトで止まる |
B. nohup で headless 起動(v4 初期) |
見えない | プロセス exit + 報告書(決定的) | 可視性がない |
| C. 各ワークツリーの Orca ターミナルで headless 実行 | ターミナルに進行が流れる | B と同じ | 実装コスト小 |
- OpenCode(exec-muse): Orca ターミナル
opencode-serveにopencode serve --port 4141 --hostname 127.0.0.1、opencode-viewにopencode attach http://127.0.0.1:4141。投入はopencode run --attach http://127.0.0.1:4141 --dir <exec-muse> --agent implementer "..."(nohup・ログはファイル)。実行ごとに新セッションが作られ attach 先の TUI にライブ表示される。curl http://127.0.0.1:4141/sessionで一覧が取れる。 S4 R2〜R3 で実測(起動〜完了・権限拒否 0)。 - codex(review-sol): Orca ターミナル
sol-exec(素のシェル)にorca terminal sendでcodex exec ... | tee <log>; echo DONEを投入。 完了は verdict ファイル + マーカー。S4 R2〜R3 で実測。 - 変わらないもの: タスクの中身は指示書ファイル、状態は beads、完了は報告書・verdict、
bd claim/closeはコーディネーターのみ、permission deny。 - Orca 上で状態が分かるよう、各ワークツリーにコメント(担当・直近の結果)を付ける。マージ前の作業ブランチは exec-muse に残す(差分が見える)。
D2: C の配達 + Orca orchestration の台帳と worker_done(2026-09-04・ユーザー指示「D2 を着手」)¶
C の弱点は完了検知が「プロセス exit + ログ末尾の推定」で、Orca 上にタスクの来歴が残らないこと。Orca orchestration は
Run(名前空間・受信箱)/ Task(作業)/ Dispatch(ターミナルへの割当) の台帳と、ワーカーが送る worker_done / escalation / question
の受信(check --wait)を提供する。配達方法は選べる(--inject で TUI に注入 = A 案の経路 / bare shell に dispatch だけして prompt は自分で送る)。
D2 は後者で、配達は C のまま、台帳と完了だけを Orca に担わせる。v3 で orchestration を諦めた実害(tui-idle 偽陽性・grace-poll・文脈混入・承認プロンプト)は
すべて --inject の配達経路に由来するので、D2 では再発しない。
- 前提:
orcaCLI は送信元ターミナルを env(ORCA_TERMINAL_HANDLE等)で識別し、ワーカーは Run/ID を自己申告できない。 したがってワーカーの起動は そのワークツリーの Orca ターミナル内で行う(exec-muse はmuse-exec、review-sol はsol-exec。いずれも素のシェル)。 コーディネーターの nohup 起動だとworker_doneがコーディネーターのターミナルから出たことになり成立しない。 - identity の罠(2026-09-04 実測・QA-2 で却下を経験):
opencode run --attachでは bash ツールがopencode serveのプロセスで実行されるため、 ワーカーのorca orchestration sendはopencode-serveペインの identity で送られる。dispatch 先をmuse-execにすると 「Dispatch … process incarnation is no longer current for its pane」で却下され、台帳は手動task-update --status completedで閉じることになった。 是正: OpenCode タスクの dispatch 先はopencode-serveターミナル(dry-run 2 で受理・completedを実測)。起動コマンドはmuse-execに送って 見せるままでよい(dispatch 先と起動場所は別)。codex はsol-exec内でcodex execが動くので dispatch 先 = 起動場所 =sol-exec。 一般則: dispatch 先は「実際にsendを実行するプロセスのペイン」。 - コーディネーターの手順:
run-create --objectiveで Run を bind(1 回)→ スライスごとにtask-create --spec "<指示書パス + 要約>"→dispatch --task <task_id> --to <worker terminal handle>(--inject無し)→ 指示書末尾にORCA_TASK_ID/ORCA_DISPATCH_IDを追記 →orca terminal send --terminal <handle> --text "<opencode run --attach … | codex exec …>" --enter→check --wait --types worker_done,escalation,question --timeout-ms 900000 --jsonを rolling で待つ → 受信した Delivery を--ack→worker-release --dispatch <id>(同じワーカーへ即続けるなら release せず次の dispatch)。 - ワーカーの手順: 報告書を書いた後に 1 回だけ
orca orchestration send --type worker_done … --task-id … --dispatch-id … --outcome succeeded|failed --files-modified …(implementer agent と sol 起動プロンプトに明記)。判断待ちはask。ID が無い投入では何も送らない(C にそのまま後退できる)。 - 注意: 同一タスクで dispatch が 3 回連続失敗するとサーキットブレークで failed になる(R2/R3 は新しい task か
--retry-of)。 ガイドにレガシー互換・adoption・takeover の注記が多く API は動いているので、台帳層への依存は薄く保つ(bd と報告書が正典のまま)。 - E との関係: D2 は permission 自動拒否による停止を解かない。E(OpenCode HTTP API 駆動・wl-lvpi)は D2 と併存できる。