DAG Engineering
大きなソフトウェアエンジニアリングタスクを、依存関係を持つサブタスク(ノード)に分割します。各ノードはサブエージェントが自身のワークツリーとブランチで実装し、メインエージェントが統合ワークツリーで一つずつマージして検証します。修正もこの分離に従い、サブエージェントは統合ワークツリーで変更やコミットを行いません。メインエージェントは調査、計画、ディスパッチ、統合、修正手配、最終検証を担当します。調査サブエージェントは特定の質問に対して読み取り専用で回答します。ノードサブエージェントはまずrefineで詳細化し、その後実装とコミットを行います。レビューサブエージェントは読み取り専用でレビューします。
調査の深さ、サブエージェントの数、検証範囲はタスクの実際の複雑さに応じて決定します。独立した作業がない場合、サブエージェントを使用するために無理に分割しません。
Codexでサブエージェントをディスパッチする際は、明示的に fork_turns="none" を設定します。
0. 既存の計画を続行する
開始前にメインワークスペースの .dag/ を確認します。「計画ステータス:進行中」の計画が存在する場合、それを読み、Gitの実際の状態と照合して現在の進捗から継続し、再分割は行いません。計画とGitの状態に不一致がある場合は、確認後のコード状態で計画を修正します。
- 統合ワークツリーに
MERGE_HEADが存在する場合(git -C <統合wt> rev-parse -q --verify MERGE_HEAD):統合が中断されており、検証結果が不明です。git merge --abortを実行後、そのノードをsubmittedとして再び統合します。 - 各ノードを一つずつ確認します:
done:ノードのコミットが統合ブランチにマージされていることを確認します(git -C <統合wt> merge-base --is-ancestor <コミット> HEAD)。確認できれば再実行しません。submitted:ノードのコミットが統合ブランチにマージされている場合、直接doneにします(マージコミットは検証通過後にのみ生成されます)。そうでなければ手順6に従って統合します。running:現在のセッションでエージェントがまだ実行中であれば待機します。エージェントが既に存在しない場合は、ノードのワークツリーのコミットと未コミットの変更を確認し、新しいエージェントを同じワークツリーで既存の成果から続行させ、新しいワークツリーは作成しません。blocked:理由を読み、条件が既に解除されているか判断します。pending:手順5に従ってスケジュールします。ノードが古い書き方(目標、範囲、手順、検収、検証)の場合、ディスパッチ前に手順4のテンプレートに書き換えます。
- すべてのノードが
doneの場合:手順7に進みます。
状態が不明な場合、ワークツリー、ブランチ、未コミットの変更は削除しません。
1. 統合ワークツリーを作成する
各DAGに対して1つの統合ワークツリーとブランチを作成し、メインエージェントのみが書き込みます。メインワークスペースは変更しません。
git worktree add "../<repo>-<plan-id>" -b "dag/<plan-id>"
<plan-id>は作業を簡潔に説明するkebab-caseを使用します。ブランチまたはディレクトリが既に存在する場合は別の名前にします。- メインワークスペースに未コミットの変更がある場合、これらの変更はワークツリーに反映されないことをユーザーに伝え、ユーザーが先にコミットするか続行するかを決定できるようにします。
- 検証コマンドがインストール手順(
node_modules、仮想環境など)に依存する場合、統合ワークツリーで先にインストールを完了します。 - 起点コミット(
git rev-parse HEAD)を記録し、全体レビューの基準とします。
2. 調査と重要な設計
順序:要件分析 → 対象を絞ったコード調査 → 統一された重要な設計。
メインエージェントはまず要件に基づいて既存の実装、関連モジュール、呼び出し関係、テストを特定し、計画に影響を与える未知の問題をリストアップします。曖昧さが目標、範囲、または検収基準を変更する場合は、まずユーザーに質問します。その他の不確定事項は計画の「仮定」に書き込みます。
複数の独立した調査質問がある場合、同じメッセージ内で読み取り専用の調査サブエージェントを並行してディスパッチします。質問が少ないか相互に依存している場合は、メインエージェント自身が調査します。調査は具体的な質問ごとに分割します(既存の実装と再利用、重要なインターフェースと呼び出しチェーン、共有状態と外部リソース、テストとエンジニアリング制約など)。ディレクトリごとに機械的に分割しません。調査サブエージェントは統合ワークツリーを直接読み取るため、自身のワークツリーは必要ありません。指示には以下を明記します:
読み取り専用で
<統合wt>を調査し、ファイルを変更せず、他のエージェントをディスパッチしません。目標:<…>。範囲:<…>。回答が必要な質問:<質問リスト>。質問への回答が完了したら停止し、範囲外の探索は行いません。以下のみを報告します:重要な事実とその位置(ファイル:シンボル)、再利用可能な既存の実装、エンジニアリング制約、確認できなかった事項。確認された事実と推測を区別します。
メインエージェントは結果を統合し、矛盾する結論を処理し、計画に影響を与えるギャップのみを追加調査します。ノードの goal、scope、verify、stop を記述するのに十分な事実が揃った時点で調査を停止します。steps の詳細はノードサブエージェントが着手時に詳細化するために残します(手順5)。計画時の調査はノードの境界を決定できる深さにとどめます:構造的なクエリ(ファイルと行数、呼び出し関係、依存関係エッジ、マニフェストエントリ)を使用して回答し、関数の実装は読みません。実装の理解はノードサブエージェントの役割です。
モジュール間の事実(特定のシンボルが誰によって呼び出されているか、特定のモジュールが何に依存しているか、ファイルセットとその依存関係のサイズなど)は、言語サーバー、ast-grep、または検索を使用して必要に応じて調査し、ソースコード全体を読んで導き出すことはしません。一度調査した結果は記録して再利用します:メインエージェントまたは調査サブエージェントが調査したものは、関連ノードの refine 結果または note に書き込みます。ノードサブエージェントは報告で新たに発見したモジュール間の事実をリストアップし、メインエージェントはそれを使用する下流ノードの refine に記録します。下流ノードが着手する際はまずこれらの記録を確認し、記録が不十分であるか、関連コードが後続のノードによって変更されて古くなっている可能性がある場合にのみ再調査します。
次に、計画の「重要な設計」を決定し、書き込みます:
- 目標の動作と非目標
- 直接再利用する既存の実装、依存関係、またはプラットフォーム機能
- 機能とコードの帰属
- ノード間で一貫性を保つ必要があるインターフェース、データ構造、アーキテクチャ制約
- 共有リソースと統合条件
ノード間の協調に必要な設計のみを固定し、ノード内部の実装はノードサブエージェントに委ねます。将来の要件のために抽象化を追加したり、既存の機能を再実装したりしません。
3. DAGを分割する
- ノードの粒度:独立して検収可能な振る舞いを単位とし、それを実行可能かつ検証可能にするために必要な接続を含みます。設定、スキャフォールディング、ドキュメントが1つのノードでのみ使用される場合はそのノードに含め、複数のノードで使用される場合は上流ノードとして分離します。結合度が高く、分割すると検証不可能な中間状態が生じたり、大量の重複修正が必要になる作業は1つのノードにまとめます。結合度が低い作業は並行実行できるように分割します。並行性を高めるためだけに無理に分割しません。
- 項目ごとの確認:ノードが多数のファイルやエントリをカバーする場合、まず確認項目と項目ごとの検収基準を明確にします。独立して確認できる範囲は読み取り専用のサブエージェントに並行処理させ、ギャップをまとめた後に実装します。既存の確認結論がまだ有効な場合はそれを再利用し、再スキャンしません。
- 依存関係:下流が本当に上流のコード、決定、または検証済みの動作を必要とする場合、または上流の失敗によって下流が無効になる場合にのみ依存関係を記述します。共有インターフェースが重要な設計ですでに決定されており、双方がそれぞれ実装とテストを行える場合は依存関係を記述せず、並行実行を許可し、統合検証で実際の連携を確認します。順序を制御するために依存関係を偽造しません。
- 競合:依存関係はないが安全に同時実行できないノードにのみ競合をマークします:論理的に相互に影響を与える変更、データベースやポートなどの共有実行リソース、マイグレーションのシーケンス番号など直列に割り当てる必要があるリソース。同一ファイルの通常の変更の重複は競合とは見なさず、並行実行を許可し、Gitマージで処理します。重複が集中しており、マージのコストが直列実行よりも明らかに高い場合にのみ競合をマークします。
- 実験が必要な決定:結論を導き出すための調査ノードを作成し、下流はそれに依存します。
各ノードは手順4のテンプレートに従って記述します。計画時には goal、scope、verify、stop、refine を記述します。steps はノードサブエージェントが着手時に refine に従って詳細化します(手順5)。計画時にすでに確定できる手順は先に記述しても構いません。
- goal:1~2文で、完了後にどのような動作が成立するか。
- scope:変更を許可するファイルまたはディレクトリ、変更してはならない部分、および遵守すべき重要な設計とビジネス制約。
- verify:観察可能な検収結果、および直接実行可能な実際のコマンド。このノードの変更によって影響を受ける既存のガード(ドキュメントのボリューム、コードの複雑さ、レイヤリング、契約チェックなど)を含みます。狭いエントリポイントを優先します。狭いエントリポイントがない場合のみ完全なチェックを実行し、完全なチェックは他の検証と並行して実行しません。
- stop:このノードに固有の停止・報告条件。例:「帰属がルールで判断できない」「特定のインターフェースが存在しない」。一般的な条件はディスパッチ指示に含まれるため、ここでは繰り返しません。
- refine:steps を決定するために調査が必要な事項を、実行可能なクエリとして記述します。例:「Xプレフィックス以下の全エントリとその依存する未処理モジュールをリストアップ」「Yの全呼び出し元をリストアップ」。ノードサブエージェントが着手時に最初の段落で完了します。計画または調査ですでに調査済みの結論は refine に直接記述し、調査済みであることを明記します。サブエージェントはそれを直接使用し、再調査しません。refine は未回答の項目のみをクエリとして残します。調査事項がない場合は「なし」と記述します。
- steps:順序付けられた手順。各手順は1つの確認可能なことのみを行い、モジュール、コマンド、インターフェースのレベルで記述します:何をするか、どこにあるか、外部の振る舞い。関数レベルでは境界部分のみ記述します:同一ファイルを異なるノードに分割する必要がある場合、または特定の関数の帰属に争いがある場合、境界の両側にある関数をリストアップします。
ソース資料と重要な設計ですでに決定された値、条件、境界は、関連ノードに直接記述し、サブエージェントに導出させません。ファイル、シンボル、コマンドは実際のコードに基づいている必要があり、捏造してはいけません。以下のような書き方は修正します:
- 「適宜実装」「境界ケースを処理」などの実行不可能な記述
- 検収基準が実装動作を言い換えただけのもの(例:「Xを実装した」)
- 振る舞いの検収がファイルの存在、インポート可能性、キーワード検索のみに依存しているもの
- 分類や選択がルール名やドキュメントのセクション番号のみを参照し(例:「D7に従う」)、デフォルトの動作と例外条件を記述していないもの
ディスパッチ前に計画を確認し、2つの質問セットに回答します。
**計画がすべて完了した後、グローバル検収基準が必然的に達成されるか。**以下の各項目でギャップを探します:
- 範囲は実際のソースから列挙し、要件からのみ推測しません:関連するコード、設定、バージョン管理外のファイルとローカルマシンの状態、インストールとデプロイ方法、その他の実行プラットフォーム、外部の呼び出し元。各項目は正確に1つのノードに属するか、非目標に記載します。
- 各検証が成立すること:ターゲット環境で実行可能であること。実行時に本番データや外部システムに書き込まないこと。どうしても書き込む必要があるノードは分離方法を明記すること。検証に合格することで対応する検収結論が導き出せること。検証に使用されるツール自体が検証済みであること。
- 計画で導入された一時的な免除、互換レイヤー、一時データ、ツールには、それらを削除または正式化するノードが存在すること。
- 外部システムの書き込み、本番環境の切り替え、他のプラットフォームでのみ実行されるパスは、納品前に少なくとも1つのノードが実際の環境で1回実行されること。
- ノード間のインターフェースとアーキテクチャが一貫していること。依存関係と競合に誤りや欠落がないこと。ノード間の統合を担当するノードが存在すること。各ノードの refine が steps を導き出せ、verify がすべて実行可能であること。
ギャップはノードとして補います。補えない場合、または補うためのコストにユーザーの判断が必要な場合は、計画の「完成度ギャップ」に書き込み、ユーザーに決定を委ねます。
設計が時間の無駄になっていないか。
- 各ノードの成果物には下流の利用者がいること。検証も利用者と見なします。利用者のないノードは削除します。
- ユーザーの決定や立ち会いが必要なノード、既存の動作を変更するノードは、他のノードを待たせないこと。下流がそれを待つ必要がある場合、動作を変更しない部分(先に実施)と変更する部分(後で実施)に分割します。
- 2つ以上のノードが使用する同じ機能やツールは、上流ノードとして分離し、各ノードが個別に実装しないようにします。各ノードの verify が何によって証明されるかを一つずつ確認します:2つ以上のノードが同じ検証手段(新旧比較、リプレイ、成果物比較など)を使用する場合、それも上流ツールノードとして分離します。そのノードの verify には、既知の差異があるサンプルを使用してツールが差異を報告できることを証明するテストを含めます。2つ以上のノードが同じ大規模な資料(マニフェスト、マッピングテーブル、決定ドキュメント)を繰り返し参照する必要があり、プロジェクトに必要に応じてクエリするエントリポイントがない場合、上流ノードとしてクエリエントリポイントを追加します。
- 各ノードが読み取りと変更に必要とする量を推定します(scope内のファイルに、そのノードが依存する未処理のコードを加えたもの)。量が多くてサブエージェントが確実に完了するのが難しい場合、または互いに関連のない独立して検収可能なモジュールにまたがる場合は分割します。結合度が高く、分割すると検証不可能な中間状態が生じる場合は、量が多くても分割しません。行数は判断の目安であり、固定のしきい値は設定しません。推定できない場合は、計算する内容を refine に書き込み、ノードサブエージェントが着手時に最初の段落で推定します。分割方法はワークツリー作成前に決定する必要がある場合、手順5に従って最初に調査サブエージェントをディスパッチして推定します。
- 既存の機能が重複実装されていないこと。不必要な分割や過剰設計がないこと。安全に並行実行できるノードが直列化されていないこと。
ノードが5つ以下の場合はメインエージェントがチェックします。5つを超える場合は、まずドラフトを手順4に従って .dag/<plan-id>.md に書き込み、その後読み取り専用のサブエージェントをディスパッチしてレビューします。サブエージェントには計画、要件、コードの場所のみを渡し、メインエージェントの推論プロセスは渡しません:
読み取り専用で
<計画パス>をレビューし、ファイルを変更せず、他のエージェントをディスパッチしません。要件:<元の要件またはその位置>。コード:<統合wt>。以下の各項目を一つずつチェックします:<上記1~10の原文>。以下のみを報告します:目標達成のギャップ、時間の無駄な設計、ユーザーの決定が必要な事項。各項目に位置、証拠(ファイル:シンボル、コマンド出力、または計画の原文)、および最小限の修正提案を記述し、確定した問題と推測を区別します。
メインエージェントは具体的な証拠がある問題のみを修正します。
4. 計画を保存する
メインワークスペースの .dag/<plan-id>.md に書き込みます。どのワークツリーにも入れず、コミットされるのを防ぎます。.dag/ がGitで無視されていない場合、.git/info/exclude に追加します。
# <plan-id>
- 目標:
- グローバル検収基準:
- 非目標:
- 仮定:
- 完成度ギャップ:<計画完了後も保証できない部分、およびユーザーの決定。なければ「なし」>
- 重要な設計:
- plan ステータス:進行中
- 統合ワークツリー:<パス> ブランチ:dag/<plan-id> 起点:<sha>
- インターフェース記録:`.dag/<plan-id>-interfaces.md`
## ノード
### N1 <タイトル>
#### goal
#### scope
#### steps
<ノードサブエージェント着手時に詳細化>
#### verify
#### stop
#### refine
#### state
- 依存:なし
- 競合:なし
- ステータス:pending
- worktree: ブランチ: コミット:
## 実行記録
- N1:<マージコミットsha> <一言結果>。<修正、異常、または残課題。なければ記述しない>
インターフェース記録ファイルは計画と同じ場所に配置し、各ノードがマージされるたびにセクションを追加します。ノードサブエージェントは読み取り専用で参照できます:
## N1(<マージコミットsha>)
- <インターフェース、名前、位置>:<形状と使用法>
実行記録には結果と残課題のみを記述します。外部インターフェースはインターフェース記録ファイルに、モジュール間の事実はそれを使用する下流ノードの refine に記述します。比較の差異などの詳細はノードのコミットメッセージと報告ファイルに残します。
goal から refine まではノードサブエージェントに渡します。state はメインエージェントのみが使用します。
ステータスの値:
pending:未ディスパッチrunning:サブエージェントが実装または修正中submitted:サブエージェントがコミット済み、統合待ちdone:統合ブランチにマージされ、メインエージェントの検収を通過blocked:続行不可。理由を実行記録に記述
計画はメインエージェントのみが変更します。ステータスが変更されるたびに即座に更新します。これはセッションをまたいで作業を継続するための基盤です。
保存後、ユーザーにノード、依存関係、並行実行可能なノード、完成度ギャップ、およびユーザーの決定が必要なすべての事項(1回で全て列挙し、複数回に分けて質問しない)を簡潔に表示します。ユーザーが計画の出力のみを要求している場合はここで停止します。そうでなければ実行を続行します。
5. 動的ディスパッチ
依存関係がすべて done であり、running/submitted ノードと競合しない pending ノードが準備完了ノードです。すべての準備完了ノードを特定し、同じメッセージ内で並行してディスパッチします。固定の並行実行上限は設定せず、実際の並行性はエージェントツールと環境が許す範囲に依存します。その後、ノードが done になるたびに、すぐに新しい準備完了ノードを探してディスパッチし、他の独立したノードの終了を待ちません。
各ノードをディスパッチする前に、メインエージェントは事前確認のみを行います:このノードが使用する上流の決定、インターフェース、名前、ルールをリストアップし、それらがすべて統合ブランチのHEADにマージされていることを確認します。これらのいずれかが running または pending のノードによって変更される可能性がある場合、このノードに依存関係を追加し、ディスパッチを延期します。
refine 内のクエリはノードサブエージェントが着手時に最初の段落で完了します。メインエージェントは実行しません。以下の2つの例外があり、その場合は手順2に従って読み取り専用の調査サブエージェントをディスパッチし、結論のみを受け取ります:
- ノードを並行実行可能な複数のノードに分割する必要がある可能性があり、分割方法をワークツリー作成前に決定する必要がある場合:調査サブエージェントが refine に従ってボリュームと結合度を推定し、メインエージェントは手順3の項目9に従って分割後、それぞれディスパッチします。
- 複数の準備完了ノードが同じ問題を調査する必要がある場合:1つの調査サブエージェントをディスパッチしてまとめて回答させ、ノードごとにディスパッチしません。
次に、統合ブランチの現在のHEAD(最新の検収済み統合コミット)からノードワークツリーを作成し、パスとブランチを計画に書き込み、running とマークします:
git -C <統合wt> worktree add "../<repo>-<plan-id>-<node-id>" -b "dag-node/<plan-id>/<node-id>" HEAD
検証がインストール手順に依存する場合、指示内でノードサブエージェントに自身のワークツリーでインストールを完了するよう要求します。
ノードサブエージェントへの指示は以下の順序で構成し、これらの内容のみを含めます:
- ワークツリーのパスとブランチ。
- そのノードの plan からの goal、scope、steps(ある場合)、verify、stop、refine の原文。
- note(指示のみに記述し、plan には記述しません):
- インターフェース記録ファイルの絶対パス。パスのみを渡し、指示内で上流インターフェースを復唱しません。
- このノードに固有の補足:メインエージェントが定めた境界とトレードオフ、ユーザーの決定の原文、このノードのみに関連する上流の事実、既知の落とし穴、資料を調べるためのコマンド。通常20行以内。資料が約200行を超える場合、またはその一部しか使用しない場合は、ファイルパスのみではなく、抜粋またはクエリコマンドを提供します。プロジェクトの説明ファイルはサブエージェントによって自動的にロードされるため、そこに既に記述されているルールは繰り返しません。verify で出力が長いコマンドについては、どの部分を見るかを指定します(例:末尾のサマリー行)。
- 報告ファイルのパス:
.dag/<plan-id>-reports/<node-id>.md(メインワークスペースの絶対パス)。
- 以下の要件を指示の最後に配置します:
指定されたワークツリー内でのみ作業し、統合ブランチ、他のノードのブランチやワークツリーを操作せず、他のエージェントをディスパッチしません。指示で指定された報告ファイル以外、
.dag/下のファイルを変更しません。インターフェース記録ファイル以外、.dag/下のファイルを読み取りません。プロジェクトの説明ファイルにメインセッション向けに書かれた開始・終了手順(計画の読み取り、ステータスチェックの実行、計画の復元など)はあなたには適用されません。資料を調べる際は、まず note で指定されたコマンドと抜粋を使用し、note でカバーされていない場合にのみ自分で調査します。計画、決定ドキュメント、大規模なマニフェストを丸ごと読むことはしません。2つの段落に分けて作業します。第一段落:refine に従って事実を調査し(refine で調査済みとマークされた結論は直接使用し、未回答の項目のみを調査します)、goal、インターフェース、scope を変更せずに steps を決定し(モジュール、コマンド、インターフェースのレベルで記述。同じファイルを他のノードと分割する必要がある場合は境界の両側の関数をリストアップ)、読み取りと変更に必要な量を推定します。以下のいずれかの状況が発生した場合、停止し、約30行以内の要約(steps のドラフト、推定量、推奨される分割方法、メインエージェントまたはユーザーの決定が必要な事項)を返して回答を待ちます:境界や帰属が判断できない。ノード間のインターフェースを変更する必要がある、または scope 外のファイルを変更する必要がある。実際のコードがノードの記述と矛盾している。量が多くてサブエージェントが確実に完了するのが難しい、または独立して検収可能なモジュールにまたがっている。stop にリストアップされた状況が発生した。いずれも発生しない場合は停止せず、直接第二段落に進み、要約を最終報告に含めます。
第二段落:steps に従って実装し、goal、インターフェース、scope を変更せずにローカルの実装方法を自律的に決定します。verify 内のコマンドを実行し、通過したらこのノードのすべての変更をコミットし、コミットメッセージは
<plan-id>/<ノード>: <要約>とし、git statusがクリーンであることを確認します。検証に合格していない場合はコミットしません。第二段落で第一段落にリストアップされた停止条件が発生した場合、または実際の量が第一段落の推定の約2倍を超えた場合、停止して報告します。自分で範囲を拡大しないでください。完了した部分で verify の適用可能なコマンドに合格している場合は先にコミットし、合格していない場合はワークツリーに保持したまま、報告に完了済みの作業と残りの作業をリストアップします。終了または停止する際、完全な報告(変更の要約、検証コマンドと完全な結果、比較の差異、逸脱の説明)を報告ファイルに書き込み、メインエージェントには約40行以内で以下のみを返します:ステータス(DONE:完了し検証通過。DONE_WITH_CONCERNS:完了したが懸念あり。BLOCKED:完了不可または停止)、コミットsha、検証結果の1行、外部インターフェースの追加または変更、新たに発見されたモジュール間の事実(例:特定のシンボルが他にどのモジュールで使用されているか、特定のインターフェースの実際の形状)、懸念またはブロックの理由、決定が必要な事項。
サブエージェントが第一段落で停止して要約を返した場合、メインエージェントは境界と決定が必要な事項を確認し(ユーザーの決定が必要なものは先にユーザーに質問)、確定した steps を plan に書き戻し、エージェントツールの継続機能(Claude Code の SendMessage、Codex の同一エージェントへの後続入力)を使用して同じサブエージェントに第二段落を続行させます。新しいエージェントはディスパッチせず、すでに読んだコードの再読込を避けます。分割が推奨される場合、手順6の「計画自体に誤りがある」のルールに従って分割します:元のサブエージェントはその一部を続行し、残りの部分は新しいノードとして手順5からディスパッチします。元のエージェントが継続できない場合、新しいエージェントを同じワークツリーにディスパッチして続行し、要約を添付します。
サブエージェントがコミットを返した後、コミットshaを plan に書き込み、submitted とマークし、手順6に進みます。
待機ルール(調査・レビューサブエージェントにも同様に適用):
- サブエージェントの範囲と競合しない具体的で独立した作業(統合済みノードの統合など)がある場合、それを先に完了します。そうでなければネイティブ待機に入ります。
- Claude Code ではバックグラウンドエージェントの完了通知またはネイティブ待機を使用します。Codex では直接エージェントツールを呼び出し、
functions.execやfunctions.waitには入れません。wait_agentにはtimeout_ms=600000を設定します。ツールのパラメータがこの値をサポートしない場合、許可される最長の待機時間を使用します。ツールが結果をバッチでしか返せない場合は、その能力に応じて処理し、存在しない通知をシミュレートしません。 - ループで短い sleep、エージェントリストのクエリ、Git ステータスの繰り返し確認を待機の代わりに使用しません。また、進捗更新を送信するために待機時間を短縮しません。
- 結果またはユーザーメッセージを受け取ったらすぐに処理します。待機タイムアウトは失敗を意味しません。引き続き待機し、まだ実行中のノードを再ディスパッチしません。
6. ノードごとの統合検証
メインエージェントは統合ワークツリーで、一度に1つの submitted ノードを統合します。他のサブエージェントは作業を続行します。サブエージェントの報告を直接信用しません:
git -C <統合wt> diff --stat HEAD...<ノードブランチ>:変更されたファイルがすべてノードの scope 内にあることを確認します。ノードワークツリーのgit statusに残っている未コミットの変更がないことを確認します。次に、他のノードと共有するファイル(共通モジュール、設定、ガードのベースライン、マニフェスト、契約テスト)の完全な diff を確認し、goal と重要な設計に準拠していることを確認します。ノード独自の新しいコードは、手順3の検証と実際の動作で判断し、1行ずつ読むことはしません。詳細が必要な場合は、報告ファイルの該当する段落を読みます。- マージは行いますが、まだコミットしません:
git -C <統合wt> merge --no-ff --no-commit "dag-node/<plan-id>/<node-id>" - 統合ワークツリーで、そのノードの verify 内のコマンドと、マージの影響を受ける統合チェックを実行します。verify の検収結果と1つずつ照合し、少なくとも1つの動作を実際に検証します。影響を受けるガードの新たな失敗はこのノードで修正し、最終検証まで残しません。既存の失敗は個別に記録し、しきい値やベースラインは緩和しません。毎回完全なテストスイートを実行する必要はありません。
- すべて合格:
git -C <統合wt> commit --no-editを実行し、ノードをdoneとマークし、1行の実行記録を書き、外部インターフェースをインターフェース記録ファイルに追記し、モジュール間の事実をそれを使用する下流ノードの refine に書き込み、手順5に戻って新たに解放されたノードをディスパッチします。
マニフェストカバレッジタイプの検収は、確認済みの結論、未確認の項目、ギャップを項目ごとに記録する必要があります。宣言されたすべての範囲が確認され、検収基準を満たしている場合のみ done とマークできます。ファイルの存在、本文が空でないこと、またはサンプルチェックの合格は、項目ごとのカバレッジの代わりにはなりません。
マージ中に競合が発生した場合、双方の意図が明確な通常の重複はメインエージェントが直接解決し、その後手順3を実行します。
その他の競合、またはチェックに合格しなかった場合、未完了のマージを取り消し(git -C <統合wt> merge --abort)、統合ブランチは最後の検証済みコミットに維持し、ノードのコミットはノードブランチに残します。問題の帰属に従って処理します:
- ノードの実装の欠陥:ノードを
runningに戻し、具体的な問題を元のノードサブエージェントに元のワークツリーで修正後再コミットするよう依頼します。元のエージェントが継続できない場合、新しいエージェントを同じワークツリーにディスパッチして続行します。メインエージェントはデフォルトでノードの実装を自分で書き換えません。 - ノードが最新の統合成果を参照する必要がある競合:ノードサブエージェントに自身のワークツリーで
dag/<plan-id>をマージさせ、競合を解決し、再検証し、コミットさせます。 - ノード間のインターフェースまたはロジックの競合:メインエージェントが正しい設計を決定し、計画の重要な設計と関連ノードを更新し、関連するノードサブエージェントに調整を依頼します。
- 計画自体に誤りがある(scope、steps、依存関係、または verify が実際のコードと一致しない):新たに発見されたコードの事実に基づいて、影響を受けるノード、依存関係、検証のみを修正します。有効な完了成果は保持し、DAG全体を再設計しません。修正がグローバル検収基準または非目標に影響する場合、最初にユーザーに質問します。
- サブエージェントが
DONE_WITH_CONCERNSを報告:懸念が検収基準に影響する場合は不合格として扱います。そうでなければ通常通り統合し、懸念を実行記録に書き込みます。 - サブエージェントが実際の量が推定を超えたために停止:コミット済みの部分が独立して検収可能な場合、このノードの goal、scope、verify を完了済みの部分に変更し、この手順に従って統合します。残りの作業は「計画自体に誤りがある」に従って新しいノードに分割し、手順5からディスパッチします。コミット済みの部分が独立して検収できない場合、統合せず、ノードを
runningのままにし、残りの作業をそのノードの steps に書き込み、新しいエージェントを同じワークツリーにディスパッチして既存の成果から続行します。 - サブエージェントが
BLOCKEDを報告、またはノードが続行不可:blockedとマークし具体的な理由を記録します。それに依存するノードはディスパッチせず、他のノードは続行します。準備完了または実行中のノードがなく、blockedノードのみが残っている場合、停止してユーザーにブロック理由を報告し、ユーザーの決定を待ってから続行します。手順7には進みません。
ノードが done になった後、そのワークツリーとブランチをクリーンアップします。ワークツリーに未コミットの変更がある場合は停止して確認し、--force や -D は使用しません:
git -C <ノードwt> status --porcelain
git -C <統合wt> worktree remove "<ノードwt>"
git -C <統合wt> branch -d "dag-node/<plan-id>/<node-id>"
blocked、修正中、または状態が不明なノードのワークツリーとブランチは保持します。
7. 全体レビュー
すべてのノードが done になった後、読み取り専用のサブエージェントをディスパッチして統合ブランチの完全な変更をレビューします:
読み取り専用で
<統合wt>の<起点sha>..HEADのすべての変更をレビューし、ファイルを変更せず、他のエージェントをディスパッチしません。以下の目標、グローバル検収基準、非目標と照らしてチェックします:要件カバレッジ、ノード間のインターフェースと動作の一貫性、重複実装、重要な設計から逸脱したアーキテクチャ、正確性の欠陥、残存するデバッグ用または一時的なコード、重要なテストの欠落または主張する動作を実際にカバーしていないこと。各問題について位置、証拠、関連するノードを記述し、確定した問題と推測を区別します。別途、ユーザーの決定が必要な事項をリストアップします。
指示には plan の目標、グローバル検収基準、非目標、重要な設計を添付します。
メインエージェントは各問題を確認後、帰属に従って修正を手配します:実装が必要な問題は修正ノード(例:F1)として plan に書き込み、手順5~6に従ってディスパッチし統合します。局所的で明らかな小さな問題(残存するデバッグ文など)は、メインエージェントが直接統合ワークツリーで修正しコミットできます。ユーザーの決定が必要な事項は自分で決定せず、報告に書き込みます。
8. 最終検証と報告
メインエージェントは統合ワークツリーで以下のチェックを完了します:
<起点sha>..HEADの完全な diff を確認し、plan の目標を超える変更がないことを確認します。- すべてのノードの検証コマンドと、プロジェクト内の変更モジュールをカバーするテスト、ビルド、lint コマンドを実行します。
- グローバル検収基準を1つずつ照合します。
チェックに失敗した場合:問題が plan の目標内にある場合、手順7の帰属ルールに従って修正後、再チェックします。問題が plan の目標外にある場合(例:起点時点で既に失敗していたテスト)、修正せず、報告に書き込みます。すべて完了後、「plan ステータス」を「完了」に変更します。
最終報告には以下を含めます:完了したノードと対応するマージコミット、レビューの発見と処理、検証結果、未完了またはリスクのある事項、ユーザーの決定が必要な事項、統合ワークツリーのパスとブランチ、保持されているノードワークツリー。ターゲットブランチへのマージと統合ワークツリーの削除は、ユーザーが要求した場合のみ行います。