# v1.13 仕様設計メモ(実装完了)
Release Date: 2026-02-01
## 位置づけ
- 本ドキュメントは **仕様設計フェーズ** の整理資料。
- `templates/code-intel/phase_contract.yml` と対になる「設計上の意図・方針」を記述する。
- **実装は完了**(v1.13 仕様は反映済み)。
## 目的
- オーケストレーター→LLM の指示をブラックボックス化させない
- フェーズごとの「指示の内容」「参照すべき付帯リソース」「期待する返却構造」を明確化
- DOCUMENT_RESEARCH を中心に **コンテキスト圧縮** を設計上保証する
## 共通設計方針(v1.13)
1) 指示の明文化
- 各フェーズで「何をやるか」を具体化し、曖昧指示を排除する
2) 付帯リソースの提示
- 各フェーズで参照すべき `.code-intel/*` を **必ず提示**する
3) ツール使用の強制(監査ログ化は不要)
- 必須ツールを指示文に明記
- `expected_payload` に `tools_used` を追加し、**使用証跡を提出**させる
- サーバー側で **ツール使用の有無を検証**(未使用なら弾く)
- ただし **summary のみ返すフェーズ**(READY 完了 / MERGE)は `tools_used` を要求しない
4) 返却の最小化 + 永続化
- `expected_payload` は **最小限**(フェーズ完了の合図 + 必須項目 + summary)
- 詳細情報は **summary に圧縮**し、**summary フィールドだけ**永続化する
- **永続化対象は summary(+オーケストレーター状態)のみ**とし、他のフィールドは保存しない
5) コンテキスト圧縮
- DOCUMENT_RESEARCH で抽出 → メインが必要箇所だけ読む → 要約/要点を永続化
6) フェーズ指示の外だし(phase_contract.yml)
- `.code-intel/phase_contract.yml` にフェーズ指示(instruction/expected_payload/tools 等)を集約
- 基本的にユーザーが変更する想定はなく、**変更がある場合は instruction の文言調整のみ**を想定
- 実装は「ファイル優先 → 未定義はデフォルトにフォールバック」の方針
---
## フェーズ別 仕様設計(反映済みの指示案)
### Step 2: BRANCH_INTERVENTION
- 目的: stale ブランチ対応のユーザー選択
- 指示方針: 3択を **意味付きで説明**して選択させる
- 指示フォーマット案(見直し後):
```json
{
"phase": "BRANCH_INTERVENTION",
"step": 2,
"instruction": "llm_task_* ブランチが検出されました。以下の選択肢をユーザーに提示し、選択結果を submit_phase で送信してください。1) delete: すべての llm_task_* ブランチを破棄(複数ブランチ完全破棄) 2) merge: 現在ブランチのみ base にマージし、その他は破棄 3) continue: 現在ブランチに留まり、READY で新規タスクブランチを作成しない。選択肢の意味を説明した上で選ばせてください。",
"expected_payload": {
"choice": "str: 'delete' | 'merge' | 'continue'",
"tools_used": "list[str]",
"summary": "str (再開時に必要な要点)"
},
"call": "submit_phase"
}
```
- 実装差分(反映済み):
- merge は「現在の llm_task_* ブランチのみマージ→削除」。他は削除
- continue は「現在ブランチ固定」のまま READY に進む
- 必須/推奨ツール:
- 必須: `submit_phase`
### Step 3: DOCUMENT_RESEARCH
- 目的: 必要箇所だけを抽出し **コンテキスト圧縮**
- 付帯リソース:
- `.code-intel/context.yml`(project_rules / doc_research / document_search)
- `.code-intel/doc_research/*.md`
- 指示方針:
- サブエージェントが **rule_refs / must_read** を抽出
- メインが **must_read を必ず読む** → 要約を永続化
- payload は最小化(documents_reviewed + summary + tools_used)
- 指示フォーマット案(見直し後):
```json
{
"phase": "DOCUMENT_RESEARCH",
"step": 3,
"instruction": "context.yml の project_rules を前提に、doc_research と document_search に従って設計文書を調査してください。サブエージェントに調査を依頼し、rule_refs / must_read を中心に返却してください。返却された must_read はメインエージェントが必ず読んで要約し、必要なルール/制約を理解したうえで submit_phase で送信してください。",
"expected_payload": {
"documents_reviewed": "list[str]",
"tools_used": "list[str]",
"summary": "str (再開時に必要な要点)"
},
"call": "submit_phase"
}
```
- 永続化(例):
- `rule_refs` / `must_read` / `dependencies` / `warnings` は **summary に要点として含めて**保存
- 必須/推奨ツール:
- 必須: `submit_phase`
- 推奨: `search_files` / `search_text`
### Step 4: QUERY_FRAME
- 目的: 指示の構造化(引用検証で幻覚防止)
- 指示方針: スロット定義 + quote 必須
- 指示フォーマット案(見直し後):
```json
{
"phase": "QUERY_FRAME",
"step": 4,
"instruction": "ユーザー指示を以下のスロットに分解し、各スロットは原文の引用(quote)付きで検証してください。target_feature(何を対象にするか)、trigger_condition(発生条件)、observed_issue(現状の問題)、desired_action(望む対応)。不明なスロットは空にし、推測はしないでください。完了後 submit_phase で送信してください。",
"expected_payload": {
"action_type": "str",
"target_symbols": "list[str]",
"scope": "str",
"constraints": "str",
"tools_used": "list[str]",
"summary": "str (再開時に必要な要点)"
},
"call": "submit_phase"
}
```
- 必須/推奨ツール:
- 必須: `submit_phase`
### Step 5: EXPLORATION
- 目的: 根拠ある探索
- 必須ツール: `search_text` など **2種類以上**
- 指示フォーマット案(見直し後):
```json
{
"phase": "EXPLORATION",
"step": 5,
"instruction": "code-intel ツールを最低2種類使って探索し、探索根拠を findings にまとめて submit_phase で送信してください。使用したツール名は tools_used に列挙してください。",
"expected_payload": {
"explored_files": "list[str]",
"findings": "list[str]",
"tools_used": "list[str] (at least 2 types)",
"summary": "str (再開時に必要な要点)"
},
"call": "submit_phase"
}
```
- 必須/推奨ツール:
- 必須: `search_text` など2種類以上 / `submit_phase`
- 推奨: `search_files` / `find_definitions` / `get_symbols` / `analyze_structure` / `get_function_at_line` / `find_references`
### Step 6: Q1
- 目的: SEMANTIC 必要性評価
- 指示フォーマット案(見直し後):
```json
{
"phase": "Q1",
"step": 6,
"instruction": "SEMANTIC フェーズ(ChromaDB の意味検索: semantic_search)を実施する必要があるか評価し、理由を添えて submit_phase で送信してください。必要な場合は「何を意味検索で確認したいか」も短く記してください。",
"expected_payload": {
"needs_more_information": "bool",
"reason": "str",
"tools_used": "list[str] (empty allowed)",
"summary": "str (再開時に必要な要点)"
},
"call": "submit_phase"
}
```
- 必須/推奨ツール:
- 必須: `submit_phase`
### Step 7: SEMANTIC
- 必須ツール: `semantic_search`
- 指示フォーマット案(見直し後):
```json
{
"phase": "SEMANTIC",
"step": 7,
"instruction": "QueryFrame/EXPLORATION の内容から検索クエリを作成し、semantic_search で追加情報を収集してください。map/forest を意識し、map で十分な確度が得られた場合は forest 探索を最小化してください。必要に応じて fetch_chunk_detail を使い、結果を submit_phase で送信してください。",
"expected_payload": {
"search_query": "str",
"search_results": "list[str]",
"tools_used": "list[str] (must include semantic_search)",
"summary": "str (再開時に必要な要点)"
},
"call": "submit_phase"
}
```
- 必須/推奨ツール:
- 必須: `semantic_search` / `submit_phase`
- 推奨: `fetch_chunk_detail`
### Step 8: Q2
- 目的: VERIFICATION 必要性評価
- 指示フォーマット案(見直し後):
```json
{
"phase": "Q2",
"step": 8,
"instruction": "VERIFICATION は仮説や探索結果の裏取り(根拠確認・矛盾解消)を指します。未検証の仮説がある/根拠が弱い/相反する結果がある場合は必要と判断し、理由を添えて submit_phase で送信してください。",
"expected_payload": {
"has_unverified_hypotheses": "bool",
"reason": "str",
"tools_used": "list[str] (empty allowed)",
"summary": "str (再開時に必要な要点)"
},
"call": "submit_phase"
}
```
- 必須/推奨ツール:
- 必須: `submit_phase`
### Step 9: VERIFICATION
- 目的: 仮説検証(根拠必須)
- 指示フォーマット案(見直し後):
```json
{
"phase": "VERIFICATION",
"step": 9,
"instruction": "仮説を1件ずつ検証し、証拠は file:line もしくはツール出力で示してください。推測は不可。根拠が無い場合は result=false とし、理由を記載してください。コードに関する仮説は必ず code-intel ツールを使い、tools_used に記載してください。",
"expected_payload": {
"hypotheses_verified": "list[{hypothesis, result, evidence}]",
"tools_used": "list[str]",
"summary": "str (再開時に必要な要点)"
},
"call": "submit_phase"
}
```
- 必須/推奨ツール:
- 必須: `submit_phase`
- 推奨: `search_text` / `find_definitions` / `find_references`
### Step 10: Q3
- 目的: IMPACT_ANALYSIS 必要性評価
- 指示フォーマット案(見直し後):
```json
{
"phase": "Q3",
"step": 10,
"instruction": "修正箇所の参照先や依存先への影響について十分な調査ができているか評価し、理由を添えて submit_phase で送信してください。",
"expected_payload": {
"needs_impact_analysis": "bool",
"reason": "str",
"tools_used": "list[str] (empty allowed)",
"summary": "str (再開時に必要な要点)"
},
"call": "submit_phase"
}
```
- 必須/推奨ツール:
- 必須: `submit_phase`
### Step 11: IMPACT_ANALYSIS
- 必須ツール: `analyze_impact`
- 指示フォーマット案(見直し後):
```json
{
"phase": "IMPACT_ANALYSIS",
"step": 11,
"instruction": "analyze_impact を実行し、修正箇所の参照先/依存先への影響、関連ファイル・テスト・設定への波及を短くまとめて submit_phase で送信してください。",
"expected_payload": {
"impact_summary": "dict",
"tools_used": "list[str] (must include analyze_impact)",
"summary": "str (再開時に必要な要点)"
},
"call": "submit_phase"
}
```
- 必須/推奨ツール:
- 必須: `analyze_impact` / `submit_phase`
### Step 12: READY (Planning)
- 指示方針:
- タスク分割前に `.code-intel/task_planning.md` を読む
- 指針に従ってタスクリスト作成
- 指示フォーマット案(見直し後):
```json
{
"phase": "READY",
"step": 12,
"instruction": ".code-intel/task_planning.md があれば必ず読み、指針に従ってタスクリストを作成し submit_phase で送信してください。",
"expected_payload": {
"tasks": "list[{id, description, status, failure_count?, revert_reason?}]",
"tools_used": "list[str]",
"summary": "str (再開時に必要な要点)"
},
"call": "submit_phase"
}
```
- 補足:
- `status` は初期値として **"pending"** を入れる
- `failure_count` / `revert_reason` はこの時点では **省略**(サーバーが付与)
- 付帯リソース(本来の設計):
- `.code-intel/task_planning.md`(タスク分割の指針)
- 必須/推奨ツール:
- 必須: `submit_phase`
### Step 13: READY (Implementation)
- 指示方針:
- 変更対象ファイルは **事前に `check_write_target`**
- 実装後に `submit_phase`
- 指示フォーマット案(見直し後):
```json
{
"phase": "READY",
"step": 13,
"instruction": "変更対象ファイルは事前に check_write_target を実行し、実装後に submit_phase で報告してください。",
"expected_payload": {
"task_id": "str",
"summary": "str (再開時に必要な要点)",
"tools_used": "list[str]"
},
"call": "submit_phase"
}
```
- 必須/推奨ツール:
- 必須: `check_write_target` / `submit_phase`
### Step 14: READY (Completion)
- 指示方針: 全タスク完了を通知
- 指示フォーマット案(見直し後):
```json
{
"phase": "READY",
"step": 14,
"instruction": "全タスクが完了しました。summary を添えて submit_phase で送信してください。",
"expected_payload": {
"summary": "str (再開時に必要な要点)"
},
"call": "submit_phase"
}
```
- 補足:
- Step 14 は「全タスク完了の**確定ポイント**」として、未完タスクの再チェックと分岐条件(no-verify/quick など)を集約する
- 実装中にタスクが追加/見直しされた場合でも、最終的な整合をここで確認する
- 必須/推奨ツール:
- 必須: `submit_phase`
### Step 15: POST_IMPL_VERIFY
- 指示方針:
- 変更内容に応じて verifier を選定
- `.code-intel/verifiers/*.md` を読み、検証を実行
- 指示フォーマット案(見直し後):
```json
{
"phase": "POST_IMPL_VERIFY",
"step": 15,
"instruction": "利用者が追加した verifier を含む .code-intel/verifiers/*.md から適切なものを選び、手順に従って検証を実行してください。使用した手順書(verifier)の名前/パスを明記し、失敗時は具体的な失敗内容を記載して submit_phase で送信してください。",
"expected_payload": {
"verifier_used": "str (name or path)",
"passed": "bool",
"failed_tasks": "list[str] (if passed=false)",
"details": "str",
"tools_used": "list[str]",
"summary": "str (再開時に必要な要点)"
},
"call": "submit_phase"
}
```
- 補足:
- 失敗が **3回** 続いた場合は Step 16: VERIFY_INTERVENTION に遷移する
- 付帯リソース(本来の設計):
- `.code-intel/verifiers/*.md`(検証手順の提示)
- 旧フローの Step 8.5 に対応
- 必須/推奨ツール:
- 必須: `submit_phase`
### Step 16: VERIFY_INTERVENTION
- 位置づけ:
- Step 15 の失敗が **3回** 続いた場合に発火する介入フェーズ
- 指示方針:
- `.code-intel/interventions/*.md` を参照し、適切な介入プロンプトを選定して実行
- 通常は `.code-intel/interventions/*.md` から適切なプロンプトを選んで実行する
- **オーケストレーターの指示時のみ** `.code-intel/user_escalation.md` に従う(LLMの自己判断でエスカレーションしない)
- タイミング補足:
- 介入が **2回** 行われた時点で、**オーケストレーターが user_escalation 分岐を出す**
- 指示パターン(2種類):
- 通常介入(オーケストレーターが user_escalation を指示していない場合)
- user_escalation 指示時(オーケストレーターが user_escalation を指示した場合)
- 指示フォーマット案(見直し後):
```json
{
"phase": "VERIFY_INTERVENTION",
"step": 16,
"instruction": "Step 15 の検証失敗が3回続いたので介入を実施します。.code-intel/interventions/*.md から適切な介入プロンプトを選定・実行し、使用したプロンプトの名前/パスを明記して submit_phase で送信してください。",
"expected_payload": {
"prompt_used": "str (name or path)",
"action_taken": "str",
"tools_used": "list[str]",
"summary": "str (再開時に必要な要点)"
},
"call": "submit_phase"
}
```
- 指示フォーマット案(user_escalation 指示時):
```json
{
"phase": "VERIFY_INTERVENTION",
"step": 16,
"instruction": ".code-intel/user_escalation.md の手順に従いユーザーへヘルプ要請を行ってください。使用した手順書の名前/パスを明記して submit_phase で送信してください。",
"expected_payload": {
"prompt_used": "str (name or path, should be .code-intel/user_escalation.md)",
"action_taken": "str",
"tools_used": "list[str]",
"summary": "str (再開時に必要な要点)"
},
"call": "submit_phase"
}
```
- 付帯リソース(本来の設計):
- `.code-intel/interventions/*.md`(検証ループ打開の介入)
- `.code-intel/user_escalation.md`(最終手段: **オーケストレーター指示時のみ**ユーザーへヘルプ要請)
- 必須/推奨ツール:
- 必須: `submit_phase`
### Step 17: PRE_COMMIT
- 指示方針:
- `review_changes` を実行
- `garbage_detection.md` に従って **不要物(ゴミ)の判定** を行う
- 指示フォーマット案(見直し後):
```json
{
"phase": "PRE_COMMIT",
"step": 17,
"instruction": "review_changes で差分一覧を取得し、.code-intel/review_prompts/garbage_detection.md に従って不要物(ゴミ)かどうか判断してください。使用した手順書の名前/パスを明記し、結果を submit_phase で送信してください。",
"expected_payload": {
"review_prompt_used": "str (name or path)",
"reviewed_files": "list[str]",
"commit_message": "str",
"tools_used": "list[str] (must include review_changes)",
"summary": "str (再開時に必要な要点)"
},
"call": "submit_phase"
}
```
- 付帯リソース(本来の設計):
- `.code-intel/review_prompts/garbage_detection.md`(ゴミ検出)
- 必須/推奨ツール:
- 必須: `review_changes` / `submit_phase`
### Step 18: QUALITY_REVIEW
- 指示方針:
- `quality_review.md` のチェックリストに従い **差分の品質** を評価する
- 指示フォーマット案(見直し後):
```json
{
"phase": "QUALITY_REVIEW",
"step": 18,
"instruction": ".code-intel/review_prompts/quality_review.md のチェックリストに従って品質レビューを実施してください。使用した手順書の名前/パスを明記し、結果を submit_phase で送信してください。",
"expected_payload": {
"quality_prompt_used": "str (name or path)",
"quality_score": "str",
"issues": "list[str]",
"tools_used": "list[str]",
"summary": "str (再開時に必要な要点)"
},
"call": "submit_phase"
}
```
- 遷移補足:
- 失敗(issues あり)の場合は READY (Planning) に差し戻し
- 失敗回数が上限に達した場合は **強制完了** として MERGE へ進む
- 付帯リソース(本来の設計):
- `.code-intel/review_prompts/quality_review.md`(最終品質チェック)
- 旧フローの Step 9.5 に対応
- 必須/推奨ツール:
- 必須: `submit_phase`
### Step 19: MERGE
- 指示方針: summary を添えて submit_phase を呼ぶ
- 指示フォーマット案(見直し後):
```json
{
"phase": "MERGE",
"step": 19,
"instruction": "summary を添えて submit_phase で送信し、マージを実行してください。",
"expected_payload": {
"summary": "str (再開時に必要な要点)"
},
"call": "submit_phase"
}
```
- 必須/推奨ツール:
- 必須: `submit_phase`
---
## チェックポイント復元のための永続化(フェーズ別)
v1.12 のチェックポイント復元を実効化するため、**オーケストレーターが保持すべき状態**と **LLM が再開時に読み直す文脈**を分離して永続化する。
(保存先例: `.code-intel/sessions/{session_id}.json` / サマリは context.yml 連携も可)
### A) オーケストレーターが保持すべき状態(LLM は基本読まない)
- **共通(全フェーズ)**
- session_id / flags / phase_state
- counters(verification_failure_count / quality_revert_count / intervention_count)
- **compaction_count**(コンパクト検知カウンタ。LLM とのずれでサマリー返却を制御)
- **Step 2: BRANCH_INTERVENTION**
- branch_policy(通常は null。continue 選択時のみ「現在ブランチ固定」の意図として保持)
- **Step 12: READY (Planning)**
- tasks(id/description/status/failure_count/revert_reason)
- ※Step12 の tasks は **submit payload から取り出して保存**(重複生成しない)
- **それ以外**
- 追加保存不要(summary のみ phase_payloads に保存すれば復元できる)
### B) LLM が再開時に読み返す文脈(LLM 向けサマリ)
- **方針**: 初回の生文脈は保持しない。再開時は**要約に落ちることを許容**し、意思決定の要点・制約・未解決点だけを残す。
- **目安**: 重要な要点だけに絞る。箇条書きなら **5項目以内**、文章なら **200〜400文字程度**を上限とし、超える場合は再圧縮する。
- **扱い**: 具体項目の一覧化は行わず、**各フェーズの submit payload に summary を含め、永続化は summary のみ**とする。
- **補足**: summary の長さは **目安** であり、サーバー側で厳格に弾かない。
---
## 永続化の粒度と保存先の具体構造
### 1) 粒度(原則)
- **最小・再開に必要な情報のみ**を保存(冗長な全文は避ける)
- **再現性のための参照**は `path:line` を優先
- **重い内容(長文/巨大 diff/全文ログ)は保存しない**
- 必要なら「要約」+「参照先」だけを持つ
### 2) 保存先(案)
- **セッション状態**: `.code-intel/sessions/{session_id}.json`
- 再開に必要な状態・最小要約
- **サマリ補助**(任意): `.code-intel/context.yml`
- project_rules / doc_research の更新サマリ
### 3) ファイル構造(案)
- **注記**: ここに示す `phase_payloads` は **抜粋例** であり、実際は summary を返した全フェーズ分が入る。
- **注記**: `phase_payloads` のキー命名は固定しない(`step_XX_*` は例)。
```json
{
"orchestrator_state": {
"session_id": "20260201_123456",
"flags": {
"no_verify": false,
"no_quality": false,
"fast": false,
"quick": false,
"no_doc": false,
"no_intervention": false
},
"phase_state": {
"current_phase": "EXPLORATION",
"step": 5,
"ready_substep": null
},
"branch_policy": "continue",
"counters": {
"verification_failure_count": 0,
"quality_revert_count": 0,
"intervention_count": 0
},
"compaction_count": 0,
"tasks": [
{ "id": "T1", "description": "Fix login", "status": "pending", "failure_count": 0 }
]
},
"phase_payloads": {
"step_02_BRANCH_INTERVENTION": {
"summary": "現在ブランチのみマージを選択"
},
"step_03_DOCUMENT_RESEARCH": {
"summary": "要点の短い要約"
},
"step_12_READY_PLANNING": {
"summary": "計画の要点"
},
"step_14_READY_COMPLETION": {
"summary": "全タスク完了を確認"
},
"step_19_MERGE": {
"summary": "マージ実行"
}
}
}
```
### 4) 実運用ルール(案)
- **phase_state は必須**
- **制御に使う値は orchestrator_state を正とする**(phase_payloads の summary は要約・補助)
- **artifacts は空でも可**(未実施フェーズは欠落可)
- **phase_payloads には summary のみ保存**(他フィールドは破棄)
- **カウンタはセッション再開時にリセットしない**(永続化された値を引き継ぎ、リセットは既存実装のタイミングに従う)
- JSON の**サイズ上限**を設ける(例: 256KB)
- 超過する場合は **summary を再圧縮**し、必要なら `path:line` の参照だけ残す
## コンパクト耐性: compaction_count 方式
### 課題
v1.13 で submit payload の `summary` を `phase_payloads` に永続化する仕組みを実装したが、**永続化されたサマリーを LLM に返す経路が未定義**だった。
- `get_session_status` は `phase_payloads` を返さない
- コンパクト発生後、LLM が `get_session_status` を呼ぶ保証がない
- boolean の `recovered` フラグでは **2度目以降のコンパクトを検知できない**
### 設計: compaction_count カウンタ方式
**原理**: サーバーとLLMが `compaction_count`(整数)を共有し、**値のずれ**でコンパクト発生を検知する。
#### フロー
1. セッション開始時: サーバー側 `compaction_count = 0`
2. 通常の submit: LLM は `compaction_count: 0` を送る → サーバー `0` と一致 → 通常応答
3. **1度目のコンパクト発生**: LLM は "continued from previous conversation" ヘッダを検知 → `compaction_count: 1` で submit
4. サーバー: 保持値 `0` ≠ 受信値 `1` → **ずれ検知** → サマリーをレスポンスに付与 + 保持値を `1` に更新
5. 通常の submit: LLM は `compaction_count: 1` → サーバー `1` と一致 → 通常応答
6. **2度目のコンパクト発生**: LLM は continuation header を再検知 → 直前レスポンスの `compaction_count: 1` を元に `+1` → `compaction_count: 2` で submit
7. サーバー: 保持値 `1` ≠ 受信値 `2` → **ずれ検知** → サマリーをレスポンスに付与 + 保持値を `2` に更新
#### サーバー側の実装要件
1. **SessionState に `compaction_count: int = 0` を追加**
- `to_dict()` / `to_compact_dict()` / `from_dict()` で永続化・復元
2. **submit_phase レスポンスに `compaction_count` を常に含める**
- LLM がコンパクト後にこの値を参照して `+1` できるように
3. **submit_phase で `compaction_count` のずれを検知**
- `data.get("compaction_count")` が `session.compaction_count` と異なる場合:
- `phase_payloads` の全サマリーをレスポンスに `phase_summaries` として付与
- `session.compaction_count` を受信値に更新
4. **get_session_status にも `compaction_count` を含める**
- `-r` スキルでの復帰時にも参照可能にするため
#### LLM 側のプロトコル(get_phase_response で全 instruction に自動付与)
1. **毎回の submit_phase で `compaction_count` を data に含める**
- **通常時**: 直前の submit_phase レスポンスに含まれる `compaction_count` をそのままエコーバック
- **コンパクト直後**: 直前の submit_phase レスポンスがコンテキスト内に存在しない場合、最後に確認した `compaction_count + 1` を送る(不明なら `1`)
- **復帰2ターン目以降**: 直前レスポンスが参照可能 → エコーバック(+1 しない)
- **注意**: トリガーは "continued from previous conversation" ヘッダの有無ではなく、**直前レスポンスの参照可否**。ヘッダはコンパクト後の全ターンで残るため、ヘッダ判定だと毎回 +1 してしまう。
2. **レスポンスに `phase_summaries` が含まれていたら読む**
- 前フェーズまでの文脈を復元するためにサマリーを参照
- 次回以降は通常の submit に戻る(サマリーは1回だけ返される)
#### `-r` スキルでの復帰
- `-r` でセッション復帰した場合、LLM は `compaction_count: 0` から始める
- サーバー側に保持されていた `compaction_count` と必ずずれる → サマリーが返される
- 結果: 新規コンパクトと同じ経路でサマリー復元が行われる
#### phase_summaries のレスポンス形式
```json
{
"success": true,
"phase": "Q1",
"step": 6,
"instruction": "...",
"expected_payload": { ... },
"compaction_count": 1,
"phase_summaries": {
"step_02_BRANCH_INTERVENTION": "現在ブランチのみマージを選択",
"step_03_DOCUMENT_RESEARCH": "要点の短い要約",
"step_05_EXPLORATION": "探索結果の要約"
}
}
```
- `phase_summaries` は `phase_payloads` から `summary` 値だけをフラット化した dict
- 通常時(ずれなし)は `phase_summaries` キー自体がレスポンスに含まれない
---
## 実装反映済み(v1.13)
- `expected_payload` への `tools_used` / `summary` 追加(READY 完了 / MERGE は summary のみ)
- サーバー側で **必須ツールの使用確認**(未使用なら payload_mismatch)
- サーバー側で **summary の有無を検証**(READY 完了 / MERGE も summary 必須)
- BRANCH_INTERVENTION の merge/continue 挙動修正
- submit payload から **summary のみ**を `phase_payloads` に永続化
- phase_contract.yml の読み込み対応(instruction/expected_payload 上書き可)
- `.code-intel/phase_contract.yml` の実ファイル生成
- **compaction_count 方式によるコンパクト耐性**(サマリーの LLM 返却経路)