14 KiB
TAKT 実行エンジン詳細
通常 Movement の実行
通常の movement(parallel フィールドを持たない movement)は、Task tool で1つのエージェントを起動する。
Task tool の呼び出し
Task tool:
subagent_type: "general-purpose"
description: "{movement名} - {ピース名}" (3-5語)
prompt: <後述のプロンプト構築で組み立てた内容>
mode: <permission_mode から決定>
permission_mode の決定
movement の edit フィールドと permission_mode フィールドから決定する:
| edit | permission_mode | Task tool の mode |
|---|---|---|
| true | 未指定 | "bypassPermissions" |
| true | "edit" | "bypassPermissions" |
| true | "full" | "bypassPermissions" |
| false | 未指定 | "default" |
| false | "readonly" | "default" |
edit: false の movement は読み取り専用。edit: true の movement はファイル編集が可能。
Parallel Movement の実行
parallel フィールドを持つ movement は、複数のサブステップを並列実行する。
実行手順
- parallel 配列の各サブステップに対して Task tool を起動する
- 全ての Task tool を1つのメッセージで並列に呼び出す(依存関係がないため)
- 全エージェントの完了を待つ
- 各サブステップの出力を収集する
- 各サブステップの出力に対して、そのサブステップの
rulesで条件マッチを判定する - 親 movement の
rulesで aggregate 評価(all()/any())を行う
サブステップの条件マッチ判定
各サブステップの出力テキストに対して、そのサブステップの rules の中からマッチする condition を特定する。
判定方法(通常 movement の Rule 評価と同じ優先順位):
[STEP:N]タグがあればインデックスで照合(最後のタグを採用)- タグがなければ、出力全体を読んでどの condition に最も近いかを判断する
マッチした condition 文字列を記録する(次の aggregate 評価で使う)。
プロンプト構築
各 movement のエージェント起動時、以下を結合してプロンプトを組み立てる。
構成要素(上から順に結合)
1. エージェントプロンプト(agent: で参照される .md の全内容)
2. ---(区切り線)
3. 実行コンテキスト情報
4. instruction_template の内容(テンプレート変数を展開済み)
5. ユーザーのタスク({task} が template に含まれない場合、末尾に自動追加)
6. 前の movement の出力(pass_previous_response: true の場合、自動追加)
7. レポート出力指示(report フィールドがある場合、自動追加)
8. ステータスタグ出力指示(rules がある場合、自動追加)
実行コンテキスト情報
## 実行コンテキスト
- ワーキングディレクトリ: {cwd}
- ピース: {piece_name}
- Movement: {movement_name}
- イテレーション: {iteration} / {max_iterations}
- Movement イテレーション: {movement_iteration} 回目
テンプレート変数の展開
instruction_template 内の以下のプレースホルダーを置換する:
| 変数 | 値 |
|---|---|
{task} |
ユーザーが入力したタスク内容 |
{previous_response} |
前の movement のエージェント出力 |
{iteration} |
ピース全体のイテレーション数(1始まり) |
{max_iterations} |
ピースの max_iterations 値 |
{movement_iteration} |
この movement が実行された回数(1始まり) |
{report_dir} |
レポートディレクトリパス |
{report:ファイル名} |
指定レポートファイルの内容(Read で取得) |
{report:ファイル名} の処理
instruction_template 内に {report:04-ai-review.md} のような記法がある場合:
- レポートディレクトリ内に対応するレポートファイルがあれば Read で読む
- 読み込んだ内容をプレースホルダーに展開する
- ファイルが存在しない場合は「(レポート未作成)」に置換する
agent フィールドがない場合
agent: が指定されていない movement の場合、エージェントプロンプト部分を省略し、instruction_template の内容のみでプロンプトを構成する。
レポート出力指示の自動注入
movement に report フィールドがある場合、プロンプト末尾にレポート出力指示を自動追加する。これにより、takt 本体の Phase 2(レポート出力フェーズ)を1回の呼び出しに統合する。
形式1: name + format
report:
name: 01-plan.md
format: |
# タスク計画
## 元の要求
...
→ プロンプトに追加する指示:
---
## レポート出力(必須)
作業完了後、以下のフォーマットに従ってレポートを出力してください。
レポートは ```markdown ブロックで囲んで出力してください。
ファイル名: 01-plan.md
フォーマット:
# タスク計画
## 元の要求
...
形式2: 配列(複数レポート)
report:
- Summary: summary.md
- Scope: 01-scope.md
→ プロンプトに追加する指示:
---
## レポート出力(必須)
作業完了後、以下の各レポートを出力してください。
各レポートは見出し付きの ```markdown ブロックで囲んで出力してください。
1. Summary → ファイル名: summary.md
2. Scope → ファイル名: 01-scope.md
レポートの抽出と保存
エージェントの出力からレポート内容を抽出し、Write tool でレポートディレクトリに保存する。
レポートディレクトリ: .takt/reports/{timestamp}-{slug}/ に作成する(takt 本体と同じ構造)。
{timestamp}:YYYYMMDD-HHmmss形式{slug}: タスク内容の先頭30文字をスラグ化
抽出方法:
- 出力内の ```markdown ブロックからレポート内容を取得する
- ファイル名の手がかり(見出しやコメント)から対応するレポートを特定する
- 特定できない場合は出力全体をレポートとして保存する
ステータスタグ出力指示の自動注入
movement に rules がある場合、プロンプト末尾にステータスタグ出力指示を自動追加する。これにより、takt 本体の Phase 3(ステータス判定フェーズ)を1回の呼び出しに統合する。
注入する指示
---
## ステータス出力(必須)
全ての作業とレポート出力が完了した後、最後に以下のいずれかのタグを出力してください。
あなたの作業結果に最も合致するものを1つだけ選んでください。
[STEP:0] = {rules[0].condition}
[STEP:1] = {rules[1].condition}
[STEP:2] = {rules[2].condition}
...
ai() 条件の場合
condition が ai("条件テキスト") 形式の場合でも、同じくタグ出力指示に含める:
[STEP:0] = 条件テキスト
[STEP:1] = 別の条件テキスト
これにより、エージェントが自ら判断して適切なタグを出力する。ai() の括弧は除去して condition テキストのみを表示する。
サブステップの場合
parallel のサブステップにも同様にタグ出力指示を注入する。サブステップの rules からタグリストを生成する。
Rule 評価
movement 実行後、エージェントの出力テキストからどの rule にマッチするかを判定する。
通常 Movement の Rule 評価
判定優先順位(最初にマッチしたものを採用):
1. タグベース検出(優先)
エージェント出力に [STEP:N] タグ(N は 0始まりのインデックス)が含まれる場合、そのインデックスに対応する rule を選択する。複数のタグがある場合は 最後のタグ を採用する。
例: rules が ["タスク完了", "進行できない"] で出力に [STEP:0] → "タスク完了" を選択
2. フォールバック(AI 判定)
タグが出力に含まれない場合、出力テキスト全体を読み、全ての condition と比較して最もマッチするものを選択する。
出力テキストの判定例:
- rules:
["実装完了", "判断できない"] - 出力: 「全てのファイルを修正し、テストもパスしました。」
- → "実装完了" にマッチ
Parallel Movement の Rule 評価(Aggregate)
親 movement の rules に all() / any() の aggregate 条件を使用する。
all() の評価
- condition: all("approved")
next: COMPLETE
引数が1つ: 全サブステップのマッチ条件が "approved" であれば true。
- condition: all("AI特有の問題なし", "すべて問題なし")
next: COMPLETE
引数が複数(位置対応): サブステップ1が "AI特有の問題なし" にマッチ AND サブステップ2が "すべて問題なし" にマッチ であれば true。
any() の評価
- condition: any("needs_fix")
next: fix
いずれかのサブステップのマッチ条件が "needs_fix" であれば true。
- condition: any("AI特有の問題あり")
next: ai_fix
引数が1つ: いずれかのサブステップが "AI特有の問題あり" にマッチすれば true。
Aggregate 評価の順序
親 rules を上から順に評価し、最初にマッチした rule を採用する。
Rule にマッチしない場合
全ての rule を評価してもマッチしない場合は ABORT する。エラーメッセージとともに、マッチしなかった出力の要約をユーザーに報告する。
ループ検出
基本ルール
- 同じ movement が連続3回以上実行されたら警告を表示する
max_iterationsに到達したら強制終了(ABORT)する
カウンター管理
以下のカウンターを管理する:
| カウンター | 説明 | リセットタイミング |
|---|---|---|
iteration |
ピース全体の movement 実行回数 | リセットしない |
movement_iteration[name] |
各 movement の実行回数 | リセットしない |
consecutive_count[name] |
同じ movement の連続実行回数 | 別の movement に遷移したとき |
Loop Monitors
ピースに loop_monitors が定義されている場合、特定の movement サイクルを監視する。
動作
loop_monitors:
- cycle: [ai_review, ai_fix]
threshold: 3
judge:
agent: ../agents/default/supervisor.md
instruction_template: |
サイクルが {cycle_count} 回繰り返されました...
rules:
- condition: 健全
next: ai_review
- condition: 非生産的
next: reviewers
検出ロジック
- movement 遷移履歴を記録する(例:
[plan, implement, ai_review, ai_fix, ai_review, ai_fix, ...]) - 各 loop_monitor の
cycleパターン(例:[ai_review, ai_fix])が履歴の末尾にthreshold回以上連続で出現するかチェックする - 閾値に達した場合:
a. judge の
agentを Read で読み込む b.instruction_templateの{cycle_count}を実際のサイクル回数に置換する c. Task tool で judge エージェントを起動する d. judge の出力を judge のrulesで評価する e. マッチした rule のnextに遷移する(通常のルール評価をオーバーライドする)
レポート管理
レポートディレクトリの作成
ピース実行開始時にレポートディレクトリを作成する:
.takt/reports/{YYYYMMDD-HHmmss}-{slug}/
このパスを {report_dir} 変数として全 movement から参照可能にする。
レポートの保存
エージェント出力からレポート内容を抽出し、Write tool でレポートディレクトリに保存する。
抽出手順:
- 出力内の ```markdown ブロックを検索する
- レポートのファイル名やセクション見出しから対応するレポートを特定する
- Write tool で
{report_dir}/{ファイル名}に保存する
レポートの参照
後続の movement の instruction_template 内で {report:ファイル名} として参照すると、engine がそのレポートファイルを Read して内容をプレースホルダーに展開する。
状態遷移の全体像
[開始]
↓
レポートディレクトリ作成
↓
initial_movement を取得
↓
┌─→ movement を実行
│ ├── 通常: Task tool (1エージェント)
│ │ prompt = agent.md + context + instruction + task
│ │ + previous_response + レポート指示 + タグ指示
│ └── parallel: Task tool (複数エージェント並列)
│ 各サブステップも同様のプロンプト構築
│ ↓
│ 出力からレポート抽出 → Write で保存
│ ↓
│ Loop Monitor チェック(該当サイクルがあれば judge 介入)
│ ↓
│ Rule 評価
│ ├── タグ検出 [STEP:N] → rule 選択
│ └── タグなし → AI フォールバック判定
│ ├── parallel: サブステップ条件 → aggregate(all/any)
│ ↓
│ next を決定
│ ├── COMPLETE → [成功終了] ユーザーに結果報告
│ ├── ABORT → [失敗終了] ユーザーにエラー報告
│ └── movement名 → ループ検出チェック → 次の movement
│ ↓
└──────────────────────────────────────────────┘