PlanGate

サブエージェント成果物契約(OUTCOME Contract)

Status: Specification(v1) 親: #710 サブエージェント委譲プロトコルをPlanGate運用に組み込む 対応子 Issue: #712 サブエージェント成果物契約を定義する 位置付け: README.md §2.5 の「委譲の契約・規範層」のうち 報告契約を担当。派遣プロンプト側の必須要素は dispatch-template.md を参照。

0. 目的

PlanGate で派遣するサブエージェントの最終報告形式を標準化し、オーケストレータ と実行ログ側が安定して判定できるようにする。表記ゆれ・偽 fail 判定・要判断事項の 見落としを構造的に防ぐ。

本契約は承認境界(C-3 / C-4 / 親子 PBI Gate)を変更しない。あくまで「サブエージェ ントがどう報告するか」「オーケストレータが受領時に何を確認するか」を定める。

1. OUTCOME(最終行契約)

サブエージェントは最終報告の最終行に、必ず以下のいずれか 1 つだけを出力する。

OUTCOME: success
OUTCOME: partial
OUTCOME: failure

1.1 定義

意味
OUTCOME: success 依頼されたタスクを完遂し、要判断事項(P0)が残っていない
OUTCOME: partial タスクの一部のみ完遂(未完了部分が残る)。または P0 の要判断事項が残り success を名乗れない。判別軸は完遂/一部完遂であり、P1/P2 は success と併存可(P0 のみが success を阻む。§2 / §7.4 と一致)
OUTCOME: failure タスクを完遂できなかった、または致命的な問題で継続不能になった

1.2 表記ルール(表記ゆれ防止)

判定用の正規表現例:

^OUTCOME: (success|partial|failure)$

この正規表現に一致しない最終行は契約違反として扱い、オーケストレータは サブエージェントへ SendMessage で是正を要求する(§6 受け入れ確認チェックリスト 参照)。

1.3 review=true タスクでの OUTCOME の扱い

レビュー・監査タスクで重大な問題を発見した場合でも、依頼されたレビュー作業自体 が完了していれば OUTCOME: success とする(何を発見したかと、依頼作業が完了 したかは別軸)。判定基準は「タスクの遂行状況」であり「対象コードの健全性」では ない。詳細は §4 を参照。

2. 要判断事項(P0 / P1 / P2)

ユーザーまたはオーケストレータの判断が必要な事項には、以下の優先度を付ける。

優先度 定義 扱い
P0 ブロッカー。即判断が必要 オーケストレータはユーザーへ即座にエスカレーションする。後続作業を進めない
P1 次工程に進む前に判断したい 次フェーズ(レビュー確定・実装着手・マージ等)に進む前にユーザー確認を挟む
P2 後続改善・補足判断でよい 記録に残すが、即時のブロッカーにはしない(handoff / known-issues 等に転記可)

2.1 記法

報告本文中に箇条書きで明示する。

## 要判断事項

- [P0] 既存 API のレスポンス形式を変更する必要がある。後方互換性が壊れる
- [P1] テストを追加したが、CI のタイムアウト設定が現行の 2 倍必要になる可能性がある
- [P2] 命名を `fooBar` から `foo_bar` に統一する余地がある(今回は既存命名踏襲)

3. 検証状態

各主張・成果物には、検証状態を以下 4 区分で明示する。

検証状態 意味 記載必須事項
実行済み 検証コマンド・テストを実際に実行し、出力を確認した 実行したコマンド・結果概要
未実行 実行する予定だったが、時間・権限・環境制約等で実行しなかった 未実行の理由
失敗 実行したが結果が NG だった エラー内容・失敗した箇所
未検証 検証手段自体が未定義、または着手していない(レビュー系タスクで結論の裏付けがまだない場合など) なぜ未検証か(検証手段がない/対象外/今回のスコープ外 等)

3.1 「未実行」と「未検証」の違い

この区別により、「本来やるべきだったが省略した」(未実行)と「今回のタスクの 性質上、検証という概念がまだ適用できない」(未検証)を混同しない。

3.2 記法例

## 検証結果

- ユニットテスト `npm test`: 実行済み(32 件 PASS / 0 件 FAIL)
- E2E テスト: 未実行(本タスクのスコープ外・ステージング環境が未提供のため)
- 型チェック `tsc --noEmit`: 失敗(`src/foo.ts:12` で型エラー 1 件)
- パフォーマンス影響: 未検証(負荷試験環境が存在しないため計測不能)

4. review=true

4.1 定義

レビュー・批評・監査・リスク列挙・真因調査タスクでは、失敗モードの列挙自体が 正しい成果物になる(例: 「脆弱性を 3 件発見した」は健全なレビュー成果物であり、 タスクの失敗ではない)。

このようなタスクを派遣する際は、Agent の description(または派遣プロンプトの タスク種別フィールド)に review=true を含める。

description: "セキュリティレビュー review=true — 認証まわりの脆弱性を洗い出す"

4.2 利用条件(対象タスク種別)

以下のタスク種別で review=true を付ける。

実装・修正・生成タスク(Implementer 系)には付けない。

4.3 何を変え、何を変えないか

言い換えると、review=true は「本文中に失敗語が出現しても、それだけで OUTCOMEfailure と誤判定してはならない」という解釈規則のフラグであり、 タスク遂行自体が失敗した場合(例: レビュー対象にアクセスできず何も評価できな かった)はやはり OUTCOME: failure を書く。

4.4 禁止用途

5. 最終報告フォーマット(まとめ)

サブエージェントの最終報告は以下の構造要件を満たす。

  1. 最初の一文で結論を書く(結論先行。詳細説明を先に書かない)
  2. 成果物の場所を書く(ファイルパス・PR URL・コミット SHA 等)
  3. 要判断事項は P0 / P1 / P2 で分類する(§2)
  4. 各主張・成果物の検証状態を明示する(§3)
  5. テスト失敗は出力ごと報告する(要約だけでなく実際のエラー出力を含める)
  6. 最終行に OUTCOME: {success|partial|failure} を書く(§1)

6. オーケストレータ受け入れ確認チェックリスト

サブエージェントの報告を受け取ったオーケストレータは、ユーザーへ結果を返す前に 以下を確認する(README.md §3 と同一チェックリストをここで 判定基準込みで定義する)。

# 確認項目 PASS 例 FAIL 例(是正要求)
1 要求された成果物があるか ファイルパス・PR URL 等が明記されている 「実装しました」とだけ書かれ、パスや diff が示されない
2 制約違反がないか 指定 scope(read-only / 対象 worktree 等)内に収まっている 禁止された操作(例: git push --force、対象外ディレクトリの編集)が行われている
3 OUTCOME が最終行にあるか ^OUTCOME: (success\|partial\|failure)$ に一致する行が最終行 OUTCOME 行がない、途中にある、表記ゆれがある(§1.2)
4 要判断事項が P0/P1/P2 で分類されているか 全ての要判断事項に [P0]/[P1]/[P2] が付いている 優先度なしの箇条書きだけ、または「要検討」とだけ書かれている
5 テスト・検証結果が明示されているか §3 の 4 区分(実行済み/未実行/失敗/未検証)で記載されている 「テストは問題ありません」とだけ書かれ、実行有無が不明

いずれか 1 項目でも FAIL の場合、オーケストレータはユーザーへ結果を返す前に 同一サブエージェントへ SendMessage で是正を要求する(別セッションへの 再委譲ではなく、同一コンテキストでの追指示を優先する)。P0 の要判断事項が 含まれる場合は、是正要求と並行してユーザーへ即座にエスカレーションする (§2 の P0 定義に従う)。

7. サンプル出力

7.1 OUTCOME: success の例

TASK-0142 のバリデーション追加を完了した。

成果物: src/validators/email.ts(新規) / src/validators/email.test.ts(新規)
PR: なし(同一ブランチ内コミット、コミット SHA: 3f2a9c1)

## 要判断事項
なし

## 検証結果
- ユニットテスト `npm test -- email.test.ts`: 実行済み(8 件 PASS / 0 件 FAIL)
- lint `npm run lint`: 実行済み(エラーなし)

OUTCOME: success

7.2 OUTCOME: partial の例

TASK-0143 の API 修正のうち、実装は完了したがマイグレーション方針の判断待ち。

成果物: src/api/orders.ts(更新)
未完了: DB スキーマ変更が必要だが、破壊的変更のため未実施

## 要判断事項
- [P0] `orders` テーブルの `status` 列を enum 化する必要がある。既存データの
  移行方針(デフォルト値 or 手動マッピング)をユーザーに判断してもらいたい
- [P2] `orders.ts` 内の重複ロジックを共通関数に切り出す余地がある(今回は
  スコープ外として着手せず)

## 検証結果
- ユニットテスト `npm test -- orders.test.ts`: 実行済み(5 件 PASS / 2 件 FAIL、
  DB スキーマ未変更のため失敗)
- マイグレーション: 未実行(P0 の判断待ちのため意図的に保留)

OUTCOME: partial

7.3 OUTCOME: failure の例

TASK-0144 の外部 API 連携実装は、認証情報が提供されておらず着手できなかった。

成果物: なし
着手できなかった理由: `.env.example` に記載の `EXTERNAL_API_KEY` が未設定で、
サンドボックス環境からも取得手段がない

## 要判断事項
- [P0] `EXTERNAL_API_KEY` の払い出し方法をユーザーに確認する必要がある

## 検証結果
- 実装: 未実行(認証情報欠如により着手不能)
- 疎通確認: 失敗(401 Unauthorized)

OUTCOME: failure

7.4 review=true タスクでの OUTCOME: success の例(レビュー結果に重大指摘あり)

description: "認証まわりのセキュリティレビュー review=true"

認証フローのセキュリティレビューを完了し、重大な脆弱性を 2 件発見した。

成果物: レビュー結果(本報告に記載)

## 発見事項(レビュー成果物)
- [重大] セッショントークンが localStorage に平文保存されており XSS で窃取可能
- [中] パスワードリセットトークンの有効期限が 24 時間と長すぎる

## 要判断事項
- [P0] セッショントークンの保存方式を httpOnly Cookie に変更するかの方針決定
- [P1] パスワードリセットトークンの有効期限短縮(推奨: 1 時間)の採否

## 検証結果
- 認証フロー全体のコードレビュー: 実行済み(対象ファイル 12 件を精読)
- 実際の攻撃再現: 未実施(レビュータスクのスコープ外)

OUTCOME: success

注: このタスクは「脆弱性を発見して報告する」ことが依頼内容であり、それを 完遂できたため OUTCOME: success。発見された脆弱性の深刻さは P0/P1 の 要判断事項として分離して報告する(§4.3 参照)。

8. 関連ファイル