## 概要
`resources/` ディレクトリを `builtins/` にリネームし、用途を明確化。同時に export-cc コマンドを拡張して全リソースをコピーするように修正する。
---
## タスク一覧
### 1. ディレクトリリネーム(優先度: 高)
| 変更前 | 変更後 |
|--------|--------|
| `resources/` | `builtins/` |
| `resources/global/{lang}/` | `builtins/{lang}/`(global/ 階層を除去) |
| `resources/project/` | `builtins/project/` |
| `resources/skill/` | `builtins/skill/` |
### 2. 不要ファイル削除(優先度: 高)
- `builtins/{lang}/prompts/` を削除
- 対象: `interactive-system.md`, `interactive-summary.md`
- 理由: コードから未参照、実体は `src/shared/prompts/`
### 3. コード修正 — パス参照(優先度: 高)
`resources` → `builtins`、`global/{lang}` → `{lang}` に更新:
| ファイル | 修正内容 |
|----------|----------|
| `src/infra/resources/index.ts` | `getResourcesDir()`, `getGlobalResourcesDir()`, `getLanguageResourcesDir()` 等のパス |
| `src/infra/config/paths.ts` | `getBuiltinPiecesDir()`, `getBuiltinPersonasDir()` |
| `src/infra/config/global/initialization.ts` | `copyLanguageConfigYaml()` |
| `src/infra/config/loaders/pieceCategories.ts` | `getLanguageResourcesDir()` 参照 |
| `src/features/config/ejectBuiltin.ts` | `getLanguageResourcesDir()` 参照 |
| `src/features/config/deploySkill.ts` | `getResourcesDir()` 参照 |
### 4. export-cc 修正(優先度: 高)
ファイル: `src/features/config/deploySkill.ts`
**現状**: pieces/ と personas/ のみコピー
**修正後**:
- `builtins/{lang}/` 全体を `~/.claude/skills/takt/` にコピー
- `skill/` のファイル(SKILL.md, references/, takt-command.md)は従来通り
- サマリー表示を新リソースタイプ(stances, instructions, knowledge 等)に対応
- confirm メッセージ修正:
- 現状: `'上書きしますか?'`
- 修正後: `'既存のスキルファイルをすべて削除し、最新版に置き換えます。続行しますか?'`
### 5. テスト修正(優先度: 中)
| ファイル | 修正内容 |
|----------|----------|
| `src/__tests__/initialization.test.ts` | `getLanguageResourcesDir` のパス期待値 |
| `src/__tests__/piece-category-config.test.ts` | mock パス |
| その他 `resources` パスを参照しているテスト | パス更新 |
### 6. ビルド・パッケージ設定(優先度: 中)
| ファイル | 修正内容 |
|----------|----------|
| `package.json` | `files` フィールドで `resources/` → `builtins/` |
| `tsconfig.json` | `resources/` への参照があれば更新 |
| `.gitignore` | 必要に応じて更新 |
### 7. ドキュメント(優先度: 低)
- `CLAUDE.md` の Directory Structure セクションを更新
- JSDoc コメントから `prompts/` 記述を削除
---
## 制約
- `builtins/{lang}/` のフラット構造は変更不可(ピースYAML内の相対パス依存)
- eject のセーフティ(skip-if-exists)は変更不要
- export-cc のセーフティ(SKILL.md 存在チェック + confirm)は維持
---
## 確認方法
- `npm run build` が成功すること
- `npm test` が全てパスすること
- `takt init` / `takt eject` / `takt export-cc` が正常動作すること
375 lines
14 KiB
Markdown
375 lines
14 KiB
Markdown
# TAKT 実行エンジン詳細
|
||
|
||
## チームメイトの起動方法
|
||
|
||
全ての movement は Task tool でチームメイトを起動して実行する。
|
||
**あなた(Team Lead)が直接作業することは禁止。**
|
||
|
||
### Task tool の呼び出し
|
||
|
||
```
|
||
Task tool:
|
||
subagent_type: "general-purpose"
|
||
team_name: "takt"
|
||
name: "{movement_name}"
|
||
description: "{movement_name} - {piece_name}"
|
||
prompt: <プロンプト構築で組み立てた内容>
|
||
mode: permission_mode
|
||
```
|
||
|
||
### permission_mode
|
||
|
||
コマンド引数で解析された `permission_mode` をそのまま Task tool の `mode` に渡す。
|
||
- `/takt coding yolo タスク` → `permission_mode = "bypassPermissions"`(確認なし)
|
||
- `/takt coding タスク` → `permission_mode = "default"`(権限確認あり)
|
||
|
||
## 通常 Movement の実行
|
||
|
||
通常の movement(`parallel` フィールドを持たない)は、Task tool で1つのチームメイトを起動する。
|
||
|
||
1. プロンプトを構築する(後述の「プロンプト構築」参照)
|
||
2. Task tool でチームメイトを起動する
|
||
3. チームメイトの出力を受け取る
|
||
4. Rule 評価で次の movement を決定する
|
||
|
||
## Parallel Movement の実行
|
||
|
||
`parallel` フィールドを持つ movement は、複数のチームメイトを並列起動する。
|
||
|
||
### 実行手順
|
||
|
||
1. parallel 配列の各サブステップに対して Task tool を準備する
|
||
2. **全ての Task tool を1つのメッセージで並列に呼び出す**(依存関係がないため)
|
||
3. 全チームメイトの完了を待つ
|
||
4. 各サブステップの出力を収集する
|
||
5. 各サブステップの出力に対して、そのサブステップの `rules` で条件マッチを判定する
|
||
6. 親 movement の `rules` で aggregate 評価(all()/any())を行う
|
||
|
||
### サブステップの条件マッチ判定
|
||
|
||
各サブステップの出力テキストに対して、そのサブステップの `rules` の中からマッチする condition を特定する。
|
||
|
||
判定方法(通常 movement の Rule 評価と同じ優先順位):
|
||
1. `[STEP:N]` タグがあればインデックスで照合(最後のタグを採用)
|
||
2. タグがなければ、出力全体を読んでどの condition に最も近いかを判断する
|
||
|
||
マッチした condition 文字列を記録する(次の aggregate 評価で使う)。
|
||
|
||
## プロンプト構築
|
||
|
||
各チームメイト起動時、以下を結合してプロンプトを組み立てる。
|
||
|
||
### 構成要素(上から順に結合)
|
||
|
||
```
|
||
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}` のような記法がある場合:
|
||
1. レポートディレクトリ内に対応するレポートファイルがあれば Read で読む
|
||
2. 読み込んだ内容をプレースホルダーに展開する
|
||
3. ファイルが存在しない場合は「(レポート未作成)」に置換する
|
||
|
||
### agent フィールドがない場合
|
||
|
||
`agent:` が指定されていない movement の場合、エージェントプロンプト部分を省略し、`instruction_template` の内容のみでプロンプトを構成する。
|
||
|
||
## レポート出力指示の自動注入
|
||
|
||
movement に `report` フィールドがある場合、プロンプト末尾にレポート出力指示を自動追加する。
|
||
|
||
### 形式1: name + format
|
||
|
||
```yaml
|
||
report:
|
||
name: 01-plan.md
|
||
format: |
|
||
# タスク計画
|
||
## 元の要求
|
||
...
|
||
```
|
||
|
||
→ プロンプトに追加する指示:
|
||
|
||
```
|
||
---
|
||
## レポート出力(必須)
|
||
作業完了後、以下のフォーマットに従ってレポートを出力してください。
|
||
レポートは ```markdown ブロックで囲んで出力してください。
|
||
|
||
ファイル名: 01-plan.md
|
||
フォーマット:
|
||
# タスク計画
|
||
## 元の要求
|
||
...
|
||
```
|
||
|
||
### 形式2: 配列(複数レポート)
|
||
|
||
```yaml
|
||
report:
|
||
- Summary: summary.md
|
||
- Scope: 01-scope.md
|
||
```
|
||
|
||
→ プロンプトに追加する指示:
|
||
|
||
```
|
||
---
|
||
## レポート出力(必須)
|
||
作業完了後、以下の各レポートを出力してください。
|
||
各レポートは見出し付きの ```markdown ブロックで囲んで出力してください。
|
||
|
||
1. Summary → ファイル名: summary.md
|
||
2. Scope → ファイル名: 01-scope.md
|
||
```
|
||
|
||
### レポートの抽出と保存
|
||
|
||
チームメイトの出力からレポート内容を抽出し、Write tool でレポートディレクトリに保存する。
|
||
**この作業は Team Lead(あなた)が行う。** チームメイトの出力を受け取った後に実施する。
|
||
|
||
**レポートディレクトリ**: `.takt/reports/{timestamp}-{slug}/` に作成する。
|
||
- `{timestamp}`: `YYYYMMDD-HHmmss` 形式
|
||
- `{slug}`: タスク内容の先頭30文字をスラグ化
|
||
|
||
抽出方法:
|
||
- 出力内の ```markdown ブロックからレポート内容を取得する
|
||
- ファイル名の手がかり(見出しやコメント)から対応するレポートを特定する
|
||
- 特定できない場合は出力全体をレポートとして保存する
|
||
|
||
## ステータスタグ出力指示の自動注入
|
||
|
||
movement に `rules` がある場合、プロンプト末尾にステータスタグ出力指示を自動追加する。
|
||
|
||
### 注入する指示
|
||
|
||
```
|
||
---
|
||
## ステータス出力(必須)
|
||
全ての作業とレポート出力が完了した後、最後に以下のいずれかのタグを出力してください。
|
||
あなたの作業結果に最も合致するものを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 評価
|
||
|
||
チームメイトの出力からどの rule にマッチするかを判定する。
|
||
|
||
### 通常 Movement の Rule 評価
|
||
|
||
判定優先順位(最初にマッチしたものを採用):
|
||
|
||
#### 1. タグベース検出(優先)
|
||
|
||
チームメイト出力に `[STEP:N]` タグ(N は 0始まりのインデックス)が含まれる場合、そのインデックスに対応する rule を選択する。複数のタグがある場合は **最後のタグ** を採用する。
|
||
|
||
例: rules が `["タスク完了", "進行できない"]` で出力に `[STEP:0]` → "タスク完了" を選択
|
||
|
||
#### 2. フォールバック(AI 判定)
|
||
|
||
タグが出力に含まれない場合、出力テキスト全体を読み、全ての condition と比較して最もマッチするものを選択する。
|
||
|
||
### Parallel Movement の Rule 評価(Aggregate)
|
||
|
||
親 movement の rules に `all()` / `any()` の aggregate 条件を使用する。
|
||
|
||
#### all() の評価
|
||
|
||
```yaml
|
||
- condition: all("approved")
|
||
next: COMPLETE
|
||
```
|
||
|
||
**引数が1つ**: 全サブステップのマッチ条件が "approved" であれば true。
|
||
|
||
```yaml
|
||
- condition: all("AI特有の問題なし", "すべて問題なし")
|
||
next: COMPLETE
|
||
```
|
||
|
||
**引数が複数(位置対応)**: サブステップ1が "AI特有の問題なし" にマッチ AND サブステップ2が "すべて問題なし" にマッチ であれば true。
|
||
|
||
#### any() の評価
|
||
|
||
```yaml
|
||
- condition: any("needs_fix")
|
||
next: fix
|
||
```
|
||
|
||
いずれかのサブステップのマッチ条件が "needs_fix" であれば 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 サイクルを監視する。
|
||
|
||
### 動作
|
||
|
||
```yaml
|
||
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
|
||
```
|
||
|
||
### 検出ロジック
|
||
|
||
1. movement 遷移履歴を記録する(例: `[plan, implement, ai_review, ai_fix, ai_review, ai_fix, ...]`)
|
||
2. 各 loop_monitor の `cycle` パターンが履歴の末尾に `threshold` 回以上連続で出現するかチェックする
|
||
3. 閾値に達した場合:
|
||
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 でレポートディレクトリに保存する。
|
||
|
||
抽出手順:
|
||
1. 出力内の ```markdown ブロックを検索する
|
||
2. レポートのファイル名やセクション見出しから対応するレポートを特定する
|
||
3. Write tool で `{report_dir}/{ファイル名}` に保存する
|
||
|
||
### レポートの参照
|
||
|
||
後続の movement の `instruction_template` 内で `{report:ファイル名}` として参照すると、そのレポートファイルを Read して内容をプレースホルダーに展開する。
|
||
|
||
## 状態遷移の全体像
|
||
|
||
```
|
||
[開始]
|
||
↓
|
||
ピースYAML読み込み + エージェント .md 読み込み
|
||
↓
|
||
Teammate(spawnTeam) でチーム作成
|
||
↓
|
||
レポートディレクトリ作成
|
||
↓
|
||
initial_movement を取得
|
||
↓
|
||
┌─→ Task tool でチームメイト起動
|
||
│ ├── 通常: 1つの Task tool 呼び出し
|
||
│ │ prompt = agent.md + context + instruction + task
|
||
│ │ + previous_response + レポート指示 + タグ指示
|
||
│ └── parallel: 複数の Task tool を1メッセージで並列呼び出し
|
||
│ 各サブステップを別々のチームメイトとして起動
|
||
│ ↓
|
||
│ チームメイトの出力を受け取る
|
||
│ ↓
|
||
│ 出力からレポート抽出 → Write で保存(Team Lead が実施)
|
||
│ ↓
|
||
│ Loop Monitor チェック(該当サイクルがあれば judge チームメイト介入)
|
||
│ ↓
|
||
│ Rule 評価(Team Lead が実施)
|
||
│ ├── タグ検出 [STEP:N] → rule 選択
|
||
│ └── タグなし → AI フォールバック判定
|
||
│ ├── parallel: サブステップ条件 → aggregate(all/any)
|
||
│ ↓
|
||
│ next を決定
|
||
│ ├── COMPLETE → Teammate(cleanup) → ユーザーに結果報告
|
||
│ ├── ABORT → Teammate(cleanup) → ユーザーにエラー報告
|
||
│ └── movement名 → ループ検出チェック → 次の movement
|
||
│ ↓
|
||
└──────────────────────────────────────────────┘
|
||
```
|