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

72 lines
5.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Movement 制御フローツールと park シグナル
エンジン内部リファレンス。「ツールを呼ぶと movement が**待機/終了状態に遷移**するが、その遷移先は**ピース毎の `rules` に書かなくてよい**」という仕組みのまとめ。BrowseWeb のログイン待ち・RequestTool の承認待ち・提案中のWaitSubTask が同じ骨格を共有する。今後この型を流用する時の下敷き。
## 要点
movement の遷移には **2 系統**ある。
| 系統 | 遷移先の決まり方 | LLM への提示 | 例 |
|------|------------------|--------------|-----|
| **rules ベース** | ピースの `rules[].next``buildTransitionTool` が enum 化 | `transition` ツールの選択肢として提示 | 別 movement への中間遷移 |
| **sentinel `next`park/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` | — | — | 終了 |
| `ABORT``cancelled` 含む) | キャンセル経路 | `cancelled` | — | — | 終了 |
| `ABORT` | `complete`/各種ガード(`text_only_limit``max_iterations` 等) | `aborted` | — | — | 終了 |
| `ASK` | `complete({status:'needs_user_input'})` | `waiting_human`(上限超で `aborted` | 現在の movement | — | 待機 |
| `WAIT_SUBTASKS` | `transition`rules 経由)/**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`)を更新。
既存の待機 status`waiting_human` / `waiting_subtasks`に相乗りできるなら、3〜4 は分岐追加だけで済むことが多い。
## 鉄則・gotcha
- **ツール内で同期ブロックして待たない。** 待機は必ず「停車ワーカー解放」で表現する。in-tool で `await` し続けると親ワーカーを占有し、最悪ワーカー枯渇でデッドロックする(`WAIT_SUBTASKS` が遷移=停車である理由)。
- **resume 先を意識する。** `default_next``COMPLETE` のピース(単一 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.html`WaitSubTask ツール=この型の新規適用例)
- 実装: `src/engine/agent-loop.ts``finishMovement` / 制御フローツール識別)、`src/engine/piece-runner.ts``mapMovementResult`)、`src/worker.ts`(待機ジョブの停車・再開)