コンテンツにスキップ

エージェント・ハーネス設計 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.jsoninstructions で明示(実測: Routing 節を正しく回答)
.beads/PRIME.md(bd 運用) SessionStart hook で注入 未注入(レビュー専任・bd 不使用) instructions で明示
bd の破壊コマンド抑止 oh-my-beads PreToolUse hook 無し(不使用) permission.bashbd 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: provider metahttps://api.meta.ai/v1)・muse-spark-1.3-contributor (reasoningEffort xhigh・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|editgit push --force|-fgit reset --hardgit 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 でも同じ形を採る)。

移行の手順

  1. S2 R2(codex luna・実行中)は完走させ、S3 から OpenCode で投入する。
  2. 小タスクで OpenCode → sol の一巡を試し、品質・ゲート遵守・xhigh の応答時間を確認する。
  3. 実装用 worktree exec-muse を orca で新設し、codex 用 exec-luna は縮退(同一 worktree で 2 エージェントを混ぜない)。
  4. 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.jsonpermission.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-serveopencode serve --port 4141 --hostname 127.0.0.1opencode-viewopencode 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 sendcodex 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 では再発しない。

  • 前提: orca CLI は送信元ターミナルを 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 sendopencode-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 …>" --entercheck --wait --types worker_done,escalation,question --timeout-ms 900000 --json を rolling で待つ → 受信した Delivery を --ackworker-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 と併存できる。