maestro/docs/movement-control-flow-tools.md
oss-sync a6d1879d63
Some checks failed
CI / build-and-test (push) Has been cancelled
sync: update from private repo (c764df2f)
2026-06-29 01:32:25 +00:00

5.9 KiB
Raw Blame History

Movement 制御フローツールと park シグナル

エンジン内部リファレンス。「ツールを呼ぶと movement が待機/終了状態に遷移するが、その遷移先はピース毎の rules に書かなくてよい」という仕組みのまとめ。BrowseWeb のログイン待ち・RequestTool の承認待ち・提案中のWaitSubTask が同じ骨格を共有する。今後この型を流用する時の下敷き。

要点

movement の遷移には 2 系統ある。

系統 遷移先の決まり方 LLM への提示
rules ベース ピースの rules[].nextbuildTransitionTool が enum 化 transition ツールの選択肢として提示 別 movement への中間遷移
sentinel nextpark/terminal ツールまたは engine が MovementResult.next特別な値を直接セット 専用ツール(complete 等)として提示。rules 不要 終了・各種待機

後者が今回の主題。ツールが「作業をする」のではなく「movement を畳む制御シグナルを出す」complete がまさにこれで、BrowseWeb(ログイン待ち)・RequestTool(承認待ち)も同じ。rules に依存しないので、rules: [] の単一 movement ピース(chat 等)でも一律に効く。

仕組みの流れ

agent-loop.ts
  LLM が制御フローツールを呼ぶ
    └─ finishMovement({ next: '<SENTINEL>', resumeMovement?, waitReason? }) を返す
        │  MovementResult.next に sentinel を載せる
        ▼
piece-runner.ts  mapMovementResult(result, ...)
    └─ next の値で分岐し PieceRunResult を返す
        ├─ 終了系 → kind:'done' / status: completed|aborted|cancelled
        └─ 待機系 → kind:'done' / status: waiting_* + resumeMovement(+waitReason)
        ▼
worker.ts
    └─ waiting_* のジョブを停車。条件成立で resumeMovement から再開
       waiting_subtasks=子全完了 / waiting_human=ユーザー回答・ログイン・承認)

ポイントは、待機系も「ジョブを停車してワーカーを解放」すること。ツール内で同期ブロックして待つのではない(後述の鉄則)。

sentinel カタログ(mapMovementResult の分岐・origin/main 時点)

next 生成元 結果 status resumeMovement waitReason 種別
COMPLETE complete ツール completed 終了
ABORTcancelled 含む) キャンセル経路 cancelled 終了
ABORT complete/各種ガード(text_only_limitmax_iterations 等) aborted 終了
ASK complete({status:'needs_user_input'}) waiting_human(上限超で aborted 現在の movement 待機
WAIT_SUBTASKS transitionrules 経由)/WaitSubTask ツール(提案) waiting_subtasks default_next(ツール版は現在の movement に変更予定) 待機
WAITING_HUMAN_BROWSER BrowseWeb(ログイン要求時) waiting_human 現在の movement browser_login 待機
WAITING_HUMAN_TOOL_REQUEST RequestTool waiting_human 現在の movement tool_request 待機
null 異常(ツール未決着) error 異常

WAIT_SUBTASKS だけは現状 rules[].next にも書けるrules ベース経由。ツール版WaitSubTaskを足すと、**同じ sentinel に「ルール不要の入口」**が増える。下流の mapMovementResult 分岐は共有。

新しい park ツールを足すレシピ

  1. ツール定義を該当モジュール(例 orchestration.ts)の TOOL_DEFS に追加。
  2. agent-loop で制御フローツールとして識別し、finishMovement({ next: '<新SENTINEL>', resumeMovement, waitReason }) を返す(WAITING_HUMAN_BROWSER の実装が雛形)。
  3. mapMovementResult に分岐を追加piece-runner.ts。終了なら status: 'aborted'|'completed'、待機なら status: 'waiting_*' + resumeMovement(+waitReason)。
  4. worker の再開条件を実装/再利用。既存の waiting_human / waiting_subtasks のどちらかに寄せられるなら新 status は不要。
  5. MovementResult.next のユニオン、waitReason)を更新。

既存の待機 statuswaiting_human / waiting_subtasksに相乗りできるなら、3〜4 は分岐追加だけで済むことが多い。

鉄則・gotcha

  • ツール内で同期ブロックして待たない。 待機は必ず「停車ワーカー解放」で表現する。in-tool で await し続けると親ワーカーを占有し、最悪ワーカー枯渇でデッドロックする(WAIT_SUBTASKS が遷移=停車である理由)。
  • resume 先を意識する。 default_nextCOMPLETE のピース(単一 movementで再開させると終了に飛ぶ。多くの待機ツールは現在の movement に再入させて、再開後に結果を読んで complete させる。
  • terminal と park を混同しない。 COMPLETE/ABORT はジョブを終わらせる(再開なし)。WAITING_*/WAIT_SUBTASKS は停車→再開。resumeMovement の有無が分かれ目。
  • sentinel は rules の enum に出さない。 これらは engine-internal。rules[].next に書けるのは別 movement 名と WAIT_SUBTASKS のみ(loadPiece/lint が COMPLETE/ABORT/ASK を reject する)。

関連

  • 設計: docs/design/2026-06-26-subtask-wait-and-safety.htmlWaitSubTask ツール=この型の新規適用例)
  • 実装: src/engine/agent-loop.tsfinishMovement / 制御フローツール識別)、src/engine/piece-runner.tsmapMovementResult)、src/worker.ts(待機ジョブの停車・再開)