nrslib 4e9c02091a feat: add takt-default pieces and TAKT knowledge facet for self-development
- Add takt-default piece (5-parallel review, takt knowledge)
- Add takt-default-team-leader piece (team_leader implement variant)
- Add takt.md knowledge facet (EN/JA) covering TAKT architecture
- Add team-leader-implement instruction facet (EN/JA)
- Add TAKT Development category to piece-categories
2026-02-28 12:04:22 +09:00

152 lines
5.7 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.

# TAKT アーキテクチャ知識
## コア構造
PieceEngine は状態機械。movement 間の遷移を EventEmitter ベースで管理する。
```
CLI → PieceEngine → Runner4種 → RuleEvaluator → 次の movement
```
| Runner | 用途 | 使い分け |
|--------|------|---------|
| MovementExecutor | 通常の3フェーズ実行 | デフォルト |
| ParallelRunner | 並列サブムーブメント | parallel ブロック |
| ArpeggioRunner | データ駆動バッチ処理 | arpeggio ブロック |
| TeamLeaderRunner | タスク分解 → サブエージェント並列 | team_leader ブロック |
各 Runner は排他。1つの movement に複数の Runner タイプを指定しない。
### 3フェーズ実行モデル
通常 movement は最大3フェーズで実行される。セッションはフェーズ間で維持される。
| フェーズ | 目的 | ツール | 条件 |
|---------|------|--------|------|
| Phase 1 | メイン作業 | movement の allowed_tools | 常に |
| Phase 2 | レポート出力 | Write のみ | output_contracts 定義時 |
| Phase 3 | ステータス判定 | なし(判定のみ) | タグベースルール時 |
## ルール評価
RuleEvaluator は5段階フォールバックで遷移先を決定する。先にマッチした方法が優先される。
| 優先度 | 方法 | 対象 |
|--------|------|------|
| 1 | aggregate | parallel 親all/any |
| 2 | Phase 3 タグ | `[STEP:N]` 出力 |
| 3 | Phase 1 タグ | `[STEP:N]` 出力(フォールバック) |
| 4 | ai() judge | ai("条件") ルール |
| 5 | AI fallback | 全条件を AI が判定 |
タグが複数出現した場合は**最後のマッチ**が採用される。
### Condition の記法
| 記法 | パース | 正規表現 |
|------|--------|---------|
| `ai("...")` | AI 条件評価 | `AI_CONDITION_REGEX` |
| `all("...")` / `any("...")` | 集約条件 | `AGGREGATE_CONDITION_REGEX` |
| 文字列 | タグまたは AI フォールバック | — |
新しい特殊構文を追加する場合は pieceParser.ts の正規表現と RuleEvaluator の両方を更新する。
## プロバイダー統合
Provider インターフェースで抽象化。具体的な SDK の差異は各プロバイダー内に閉じ込める。
```
Provider.setup(AgentSetup) → ProviderAgent
ProviderAgent.call(prompt, options) → AgentResponse
```
| 基準 | 判定 |
|------|------|
| SDK 固有のエラーハンドリングが Provider 外に漏れている | REJECT |
| AgentResponse.error にエラーを伝播していない | REJECT |
| プロバイダー間でセッションキーが衝突する | REJECT |
| セッションキー形式 `{persona}:{provider}` | OK |
### モデル解決
5段階の優先順位でモデルを解決する。上位が優先。
1. persona_providers のモデル指定
2. movement の model フィールド
3. CLI `--model` オーバーライド
4. config.yamlプロバイダー一致時
5. プロバイダーデフォルト
## ファセット組み立て
faceted-prompting モジュールは TAKT 本体に依存しない独立モジュール。
```
compose(facets, options) → ComposedPrompt { systemPrompt, userMessage }
```
| 基準 | 判定 |
|------|------|
| faceted-prompting から TAKT コアへの import | REJECT |
| TAKT コアから faceted-prompting への依存 | OK |
| ファセットパス解決のロジックが faceted-prompting 外にある | 警告 |
### ファセット解決の3層優先順位
プロジェクト `.takt/` → ユーザー `~/.takt/` → ビルトイン `builtins/{lang}/`
同名ファセットは上位が優先。ビルトインのカスタマイズは上位層でオーバーライドする。
## テストパターン
vitest を使用。テストファイルの命名規約で種別を区別する。
| プレフィックス | 種別 | 内容 |
|--------------|------|------|
| なし | ユニットテスト | 個別関数・クラスの検証 |
| `it-` | 統合テスト | ピース実行のシミュレーション |
| `engine-` | エンジンテスト | PieceEngine シナリオ検証 |
### Mock プロバイダー
`--provider mock` でテスト用の決定論的レスポンスを返す。シナリオキューで複数ターンのテストを構成する。
```typescript
// NG - テストでリアル API を呼ぶ
const response = await callClaude(prompt)
// OK - Mock プロバイダーでシナリオを設定
setMockScenario([
{ persona: 'coder', status: 'done', content: '[STEP:1]\nDone.' },
{ persona: 'reviewer', status: 'done', content: '[STEP:1]\napproved' },
])
```
### テストの分離
| 基準 | 判定 |
|------|------|
| テスト間でグローバル状態を共有 | REJECT |
| 環境変数をテストセットアップでクリアしていない | 警告 |
| E2E テストで実 API を前提としている | `provider` 指定の config で分離 |
## エラー伝播
プロバイダーエラーは `AgentResponse.error` → セッションログ → コンソール出力の経路で伝播する。
| 基準 | 判定 |
|------|------|
| SDK エラーが空の `blocked` ステータスになる | REJECT |
| エラー詳細がセッションログに記録されない | REJECT |
| エラー時に ABORT 遷移が定義されていない | 警告 |
## セッション管理
エージェントセッションは cwd ごとに保存される。worktree/clone 実行時はセッション再開をスキップする。
| 基準 | 判定 |
|------|------|
| `cwd !== projectCwd` でセッション再開している | REJECT |
| セッションキーにプロバイダーが含まれない | REJECTクロスプロバイダー汚染 |
| Phase 間でセッションが切れている | REJECTコンテキスト喪失 |