# v1.12 アップデート: セッションチェックポイント永続化 & レガシーツール削除
Release Date: 2026-01-31
---
## 背景
AVITO プロジェクトで `/code` セッションが READY フェーズ (Step 13) 中にコンテキスト枯渇。
CLI 終了 → MCP サーバープロセス終了 → `SessionState` 消滅。
継続セッションで発生した問題:
1. **検証スキップ**: POST_IMPL_VERIFY が実質的な作業なしで `passed: true` を送信(LLM がプロジェクト文脈を喪失)
2. **旧ツール呼び出し**: LLM が v1.11 フローに存在しない `record_outcome` を呼び出し(削除されるべきツールが残存)
### 根本原因
```
LLM 会話 ← コンパクト対象
↕ MCP プロトコル
MCP サーバー ← インメモリ保持(プロセス終了で消滅)
```
v1.11 の「コンパクト耐性」は **同一 CLI セッション内** でのみ有効。
CLI 終了 → 新規 CLI 起動では MCP サーバーも再起動され、`SessionState` は消滅する。
| シナリオ | MCP プロセス | SessionState | v1.11 耐性 |
|----------|-------------|-------------|-----------|
| 自動コンパクト(同一セッション) | 生存 | 保持 | **有効** |
| `/clear`(同一 CLI) | 生存 | 保持 | **有効** |
| CLI 終了 → `--continue` | 再起動 | **消滅** | 無効 |
| コンテキスト枯渇 → 新規会話 | 再起動 | **消滅** | 無効 |
---
## 設計原則
1. **チェックポイント永続化**: `submit_phase` ごとにセッション状態をディスクに保存。CLI 再起動後も `get_session_status` で復帰可能。
2. **ツールコンテキスト削減**: 未使用の旧ツール 18 個を削除。LLM のツール一覧を 39 → 21 に圧縮。
3. **後方互換性**: `SessionState` のメソッド(`submit_exploration()` 等)は内部利用のため維持。MCP ツール登録のみ削除。
4. **明示的再開**: `/code --resume` でチェックポイント復元を起動。code.md + CLAUDE.md コンテキストとサーバー状態の両方を確保。
5. **レスポンス防御**: 全ツールレスポンスに 256KB 上限。1 ターンでのコンテキスト即死を防止。
---
## Feature ①: セッションチェックポイント永続化
### 概要
```
submit_phase 成功
→ SessionState.to_dict() でシリアライズ
→ .code-intel/sessions/{session_id}.json に保存
CLI 再起動 → get_session_status
→ チェックポイントファイルを検出
→ SessionState.from_dict() で復元
→ LLM に現在フェーズ + instruction + expected_payload を返却
```
### 保存先
```
.code-intel/sessions/{session_id}.json
```
`.gitignore` に追加。MERGE(SESSION_COMPLETE)成功時に自動削除。
### 制約事項
チェックポイント永続化は **サーバー側の状態**(フェーズ、タスク進捗、探索結果等)を復元する。
ただし、LLM 側に必要な **プロジェクト固有の作業手順**(ビルド方法、検証方法等)は `/code` スキルと CLAUDE.md から提供される。
v1.12 では `/code --resume` で両方を同時に確保する:
```
新セッション → /code --resume
→ code.md 読み込み(LLM 側コンテキスト確保)
→ get_session_status → チェックポイント復元(サーバー側状態確保)
→ instruction + expected_payload に従い作業再開
```
> **注意**: `/code --resume` なしで直接 `get_session_status` を呼んだ場合、サーバー状態は復元されるが、LLM は検証手順等のプロジェクト文脈を持たないため、AVITO と同様の「検証スキップ」が再発する可能性がある。
### SessionState.to_dict() 完全化
現行の `to_dict()` に不足しているフィールドを追加:
| カテゴリ | 追加フィールド |
|----------|---------------|
| Identity | `repo_path` |
| Phase state | `ready_substep`, `gate_level` |
| v1.11 Tasks | `tasks` (TaskModel リスト) |
| v1.11 Flags | `no_verify`, `no_quality`, `fast_mode`, `quick_mode`, `no_doc`, `no_intervention`, `only_explore`, `only_verify` |
| v1.10 | `phase_assessments` |
| Semantic | `map_results`, `forest_results`, `map_hit` |
| v1.5 Quality | `quality_revert_count`, `quality_review_enabled`, `quality_review_max_revert`, `quality_review_completed` |
| v1.8 Commit | `commit_prepared`, `prepared_commit_message`, `prepared_kept_files`, `prepared_discarded_files` |
| v1.8 | `skip_implementation` |
| v1.7 Cache | `definitions_cache`(タプルキー → JSON 配列に変換) |
| Metadata | `checkpoint_version`, `checkpoint_at` |
### SessionState.from_dict() 新規追加
チェックポイントからの復元。ネストされたデータクラスごとにヘルパー関数を用意:
| ヘルパー関数 | 復元対象 |
|-------------|---------|
| `_restore_query_frame(data)` | QueryFrame + MappedSymbol + SlotSource + SlotEvidence |
| `_restore_exploration(data)` | ExplorationResult |
| `_restore_semantic(data)` | SemanticResult + Hypothesis |
| `_restore_verification(data)` | VerificationResult + VerifiedHypothesis + VerificationEvidence |
| `_restore_impact_analysis(data)` | ImpactAnalysisResult + VerifiedFile |
| `_restore_pre_commit_review(data)` | PreCommitReviewResult + ReviewedFile |
欠損フィールドはデフォルト値で補完(部分チェックポイント対応)。
### SessionManager チェックポイント操作
```python
class SessionManager:
def save_checkpoint(self, session_id: str, base_path: str) -> bool:
"""セッション状態を .code-intel/sessions/ に保存(アトミック書き込み)"""
def load_checkpoint(self, session_id: str, base_path: str) -> SessionState | None:
"""チェックポイントからセッション状態を復元"""
def list_checkpoints(self, base_path: str) -> list[dict]:
"""利用可能なチェックポイント一覧"""
@staticmethod
def delete_checkpoints(base_path: str) -> int:
"""全チェックポイント削除(--clean 用)"""
```
### サーバー統合 (code_intel_server.py)
| タイミング | 動作 |
|-----------|------|
| `submit_phase` 成功後 | `save_checkpoint()` |
| `start_session` 完了後 | `save_checkpoint()` + 既存チェックポイントがあれば `recovery_available` を返す |
| `get_session_status`(アクティブセッションなし) | チェックポイントを探して自動復元、`recovered_from_checkpoint: true` |
| MERGE(SESSION_COMPLETE) | チェックポイントファイル削除 |
| `cleanup_stale_branches` | `delete_checkpoints()` も実行 |
### definitions_cache のシリアライズ
タプルキー `(str, str, str | None, bool)` は JSON 非対応。JSON 配列に変換:
```python
# シリアライズ
def _serialize_cache_key(key: tuple) -> str:
return json.dumps([key[0], key[1], key[2], key[3]])
# デシリアライズ
def _deserialize_cache_key(key_str: str) -> tuple | None:
parts = json.loads(key_str)
return (parts[0], parts[1], parts[2], parts[3])
```
---
## Feature ②: レガシーツール削除
### 概要
v1.11 で `submit_phase` に統一されたが、旧ツールが MCP サーバーに残存。
LLM が ToolSearch で発見し、v1.11 フローにないツールを呼んでしまう問題が発生。
### 削除対象 (18 ツール)
**v1.11_ja.md 廃止 API に該当する MCP ツール登録 (14):**
| # | ツール名 | 代替 |
|---|----------|------|
| 1 | `check_phase_necessity` | submit_phase (Q1/Q2/Q3) |
| 2 | `set_query_frame` | submit_phase (QUERY_FRAME) |
| 3 | `begin_phase_gate` | submit_phase (BRANCH_INTERVENTION) |
| 4 | `submit_for_review` | submit_phase (READY 完了) |
| 5 | `submit_exploration` | submit_phase (EXPLORATION) |
| 6 | `submit_semantic` | submit_phase (SEMANTIC) |
| 7 | `submit_verification` | submit_phase (VERIFICATION) |
| 8 | `submit_impact_analysis` | submit_phase (IMPACT_ANALYSIS) |
| 9 | `submit_quality_review` | submit_phase (QUALITY_REVIEW) |
| 10 | `finalize_changes` | submit_phase (PRE_COMMIT) |
| 11 | `merge_to_base` | submit_phase (MERGE) |
| 12 | `record_verification_failure` | submit_phase (POST_IMPL_VERIFY: passed=false) |
| 13 | `record_intervention_used` | submit_phase (VERIFY_INTERVENTION) |
| 14 | `get_intervention_status` | サーバー内部管理 |
注: v1.11_ja.md 廃止リストの `complete_task` は MCP ツールとして登録されていない(`SessionState` のメソッドのみ)。削除不要。
**v1.11 Tool Overview に不在 (4):**
| # | ツール名 | 理由 |
|---|----------|------|
| 15 | `record_outcome` | ワークフロー外。AVITO で LLM が誤呼出 |
| 16 | `get_outcome_stats` | record_outcome の付随ツール |
| 17 | `validate_symbol_relevance` | v1.11 フローに不在 |
| 18 | `confirm_symbol_relevance` | v1.11 フローに不在 |
### 保持するツール (21)
| # | ツール名 | 用途 |
|---|----------|------|
| 1 | `start_session` | セッション開始 |
| 2 | `submit_phase` | 全フェーズの統一出口 |
| 3 | `get_session_status` | 状態復帰(+ v1.12 チェックポイント復元) |
| 4 | `search_text` | テキスト検索 |
| 5 | `search_files` | ファイル検索 |
| 6 | `find_definitions` | シンボル定義 |
| 7 | `find_references` | シンボル参照 |
| 8 | `analyze_structure` | コード構造分析 |
| 9 | `get_symbols` | シンボル一覧 |
| 10 | `get_function_at_line` | 行指定の関数取得 |
| 11 | `query` | インテリジェント検索 |
| 12 | `fetch_chunk_detail` | ChromaDB チャンク取得 |
| 13 | `semantic_search` | ベクトル検索 |
| 14 | `check_write_target` | 書き込み先検証 |
| 15 | `add_explored_files` | 探索済みファイル追加 |
| 16 | `revert_to_exploration` | 探索フェーズへ差戻し |
| 17 | `review_changes` | 変更レビュー |
| 18 | `analyze_impact` | 影響分析 |
| 19 | `cleanup_stale_branches` | ブランチ + セッション削除(v1.12 拡張) |
| 20 | `sync_index` | ChromaDB 同期 |
| 21 | `update_context` | コンテキスト更新 |
### 削除手順
1. `list_tools()` から 18 個の `Tool(name=...)` エントリを削除
2. `call_tool()` から対応する `elif name == "..."` ハンドラブロックを削除
3. `SessionState` のメソッド(`submit_exploration()` 等)は **削除しない**(v1.11 の `_submit_*` ハンドラが内部的に使用)
4. 不要になった import を整理
---
## Feature ③: `/code --resume` オプション
### 概要
チェックポイントからセッションを明示的に再開するためのフラグ。
`/code --resume` で code.md + CLAUDE.md のコンテキスト読み込みとサーバー状態の復元を同時に行う。
### フラグ定義
| Flag | Short | Effect |
|------|-------|--------|
| `--resume` | `-r` | チェックポイントからセッション再開(Step 1-2 スキップ) |
> **短縮オプションの再割り当て**: `-r` は v1.11 で `--rebuild` に割り当て。v1.12 で `--resume` に再割り当て。`--rebuild` の短縮オプションは廃止。
### 動作フロー
```
/code --resume
→ Step -1: Flag Check — --resume 検出
→ Step 1 (Intent Classification) — スキップ
→ Step 2: start_session を呼ばず get_session_status を直接呼ぶ
→ サーバー: チェックポイント検出 → 復元 → recovered_from_checkpoint: true
→ LLM: instruction + expected_payload に従い作業再開
```
チェックポイントが存在しない場合:
```
get_session_status → "no active session, no checkpoint found"
→ LLM がユーザーに通知: "復元可能なセッションがありません"
→ 処理終了
```
### フラグ併用制約
`--resume` は他のフラグと併用不可。チェックポイントに保存済みのフラグ(`no_verify`, `fast_mode` 等)が復元される。
```
/code --resume ← OK
/code --resume --no-verify ← エラー: --resume は単独使用
```
### 通常実行時のチェックポイント検出
`/code`(`--resume` なし)で旧チェックポイントが存在する場合、ユーザーに選択を提示:
```
/code fix the bug
→ start_session → recovery_available: true(旧チェックポイント検出)
→ LLM: AskUserQuestion でユーザーに選択を提示
"前回のセッションが見つかりました (READY Step 13: 'CSS修正タスク')"
→ [復元する] → get_session_status → チェックポイント復元 → 中断地点から再開
→ [破棄して新規] → 通常フロー続行。旧チェックポイントは次回 save_checkpoint 時に自動削除
```
`start_session` レスポンスに含まれるチェックポイント情報:
```json
{
"recovery_available": true,
"checkpoint_info": {
"session_id": "...",
"phase": "READY",
"step": 13,
"query": "CSS修正タスク",
"checkpoint_at": "2026-01-31T12:34:56"
}
}
```
### code.md 変更内容
**Flag Check テーブル更新**:
| 変更 | 内容 |
|------|------|
| 追加 | `--resume` / `-r` / チェックポイントから再開(Step 1-2 スキップ) |
| 変更 | `--rebuild` の短縮 `-r` を削除 → `--rebuild` / — / Force re-index and exit |
**CRITICAL RULES 追加**:
```
10. **--resume は単独使用**: --resume は他のフラグと併用不可。チェックポイントに保存済みのフラグが復元される。
```
**recovery_available ハンドリング追加**:
`start_session` が `recovery_available: true` を返した場合、AskUserQuestion でユーザーに「復元する / 破棄して新規」を選択させる。復元選択時は `get_session_status` で復帰。
**Compaction Recovery セクション更新**:
- 同一セッション内のコンパクト回復: 既存の `get_session_status` フロー(変更なし)
- CLI 再起動後のクロスセッション回復: `/code --resume` で起動
---
## Feature ④: ツールレスポンスサイズ制限
### 背景
AVITO プロジェクトで `search_text` が部分一致パターン `["<nav", "aria-label", "breadcrumb", "dashboard-menu"]` により 7,644 件マッチ + サブマッチ位置情報を生成。レスポンスサイズ **120.8MB** が 1 ターンでコンテキストを即死させた。
コンパクトは前ターンまでしか処理できないため、現在のターンのツール応答がコンテキストを超えると防御不能。
### 設計
全ツールレスポンスに **256KB** (262,144 bytes) のハード上限を設定。
| 設定 | 値 |
|------|-----|
| 上限 | 256KB (262,144 bytes) |
| ≈ tokens | ~64K |
| コンテキスト比 | ~32% |
### 超過時の動作
```
レスポンスサイズ > 256KB の場合:
→ 結果を 256KB で切り詰め
→ 末尾に警告を付与:
"truncated": true,
"total_matches": 7644,
"returned_matches": 342,
"message": "レスポンスが 256KB を超えたため切り詰めました。パターンを絞り込んでください。"
```
### 実装箇所
`code_intel_server.py` の `call_tool()` で、各ハンドラの戻り値をシリアライズした後にサイズチェック。共通のトランケーションロジックを 1 箇所に集約:
```python
MAX_RESPONSE_BYTES = 262_144 # 256KB
def _truncate_response(content: str, max_bytes: int = MAX_RESPONSE_BYTES) -> tuple[str, bool]:
"""レスポンスが上限を超えた場合に切り詰め + 警告を付与"""
```
全ツールに一律適用(search 系だけでなく全ツール)。個別ツールの修正は不要。
---
## 変更対象ファイル
| ファイル | 変更内容 | 影響度 |
|----------|----------|--------|
| `tools/session.py` | `to_dict()` 完全化、`from_dict()` 追加、復元ヘルパー、`SessionManager` チェックポイント操作 | 高 |
| `code_intel_server.py` | チェックポイント保存/復元ワイヤリング、18 ツール削除、レスポンスサイズ制限 | 高 |
| `.claude/commands/code.md` | `--resume` フラグ追加、`--rebuild` 短縮廃止、CRITICAL RULES 追加 | 中 |
| `.gitignore` | `.code-intel/sessions/` 追加 | 低 |
---
## 実装順序
1. `tools/session.py` — `to_dict()` 完全化 + `from_dict()` + 復元ヘルパー + チェックポイント操作
2. `code_intel_server.py` — チェックポイント保存/復元のワイヤリング
3. `code_intel_server.py` — 18 ツール登録 + ハンドラ削除
4. `cleanup_stale_branches` 拡張 + `.gitignore` 更新
5. `code_intel_server.py` — `_truncate_response()` + `call_tool()` にサイズチェック追加
6. `.claude/commands/code.md` — `--resume` フラグ追加 + `--rebuild` 短縮廃止
7. `tests/test_v1_12_features.py` — テスト作成
8. この文書の最終化
---
## テスト計画
```python
class TestCheckpointSerialization:
"""to_dict/from_dict ラウンドトリップテスト"""
def test_round_trip_all_fields(self):
"""全フィールドが保持されるか"""
def test_definitions_cache_tuple_keys(self):
"""タプルキー → JSON → タプルキー"""
def test_phase_enum_round_trip(self):
"""全 Phase で往復"""
def test_partial_checkpoint_defaults(self):
"""欠損フィールドがデフォルト値で補完"""
def test_nested_dataclass_restore(self):
"""QueryFrame, ExplorationResult 等の復元"""
def test_task_model_round_trip(self):
"""TaskModel のシリアライズ/デシリアライズ"""
class TestCheckpointIO:
"""ファイル I/O テスト"""
def test_save_and_load(self):
"""save → load → 内容一致"""
def test_atomic_write(self):
"""アトミック書き込み(tmp → rename)"""
def test_list_checkpoints(self):
"""チェックポイント一覧"""
def test_delete_checkpoints(self):
"""全削除"""
def test_merge_deletes_checkpoint(self):
"""MERGE 成功時にチェックポイント削除"""
class TestCheckpointRecovery:
"""復元フローテスト"""
def test_get_session_status_recovers_from_checkpoint(self):
"""_sessions クリア → get_session_status → 自動復元"""
def test_start_session_shows_recovery_available(self):
"""既存チェックポイントがあれば recovery_available + checkpoint_info を返す"""
def test_recovered_session_has_correct_phase(self):
"""復元後のセッションが正しいフェーズにいる"""
class TestLegacyToolRemoval:
"""旧ツール削除テスト"""
def test_tool_count(self):
"""list_tools() が 21 ツールを返す"""
def test_removed_tools_return_error(self):
"""削除された 18 ツールが Unknown tool エラー"""
def test_submit_phase_still_works(self):
"""統一ツール submit_phase が正常動作"""
class TestCleanupExtension:
"""--clean 拡張テスト"""
def test_clean_deletes_session_files(self):
"""cleanup_stale_branches がセッションファイルも削除"""
class TestResumeFlag:
"""--resume フラグテスト"""
def test_resume_skips_start_session(self):
"""--resume 時に start_session を呼ばず get_session_status で復元"""
def test_resume_no_checkpoint_returns_error(self):
"""チェックポイントがない場合にエラーメッセージ"""
def test_resume_rejects_other_flags(self):
"""--resume と他フラグの併用がエラー"""
def test_resume_restores_saved_flags(self):
"""復元セッションが保存済みフラグを持つ"""
class TestRecoveryPrompt:
"""通常実行時のチェックポイント検出テスト"""
def test_start_session_returns_checkpoint_info(self):
"""旧チェックポイント存在時に recovery_available + checkpoint_info を返す"""
def test_discard_deletes_old_checkpoint(self):
"""新規選択後の save_checkpoint で旧チェックポイントが削除される"""
class TestResponseTruncation:
"""レスポンスサイズ制限テスト"""
def test_small_response_unchanged(self):
"""256KB 未満のレスポンスはそのまま返る"""
def test_large_response_truncated(self):
"""256KB 超のレスポンスが切り詰められる"""
def test_truncation_includes_warning(self):
"""切り詰め時に truncated + total_matches + message が付与される"""
def test_truncation_applies_to_all_tools(self):
"""search_text 以外のツールにも制限が適用される"""
```
---
## リスク
| リスク | 対策 |
|--------|------|
| チェックポイント書き込み中のクラッシュ | アトミック書き込み(tmp → rename) |
| 旧スキルファイルが削除ツールを参照 | 実装前に全 `.claude/commands/*.md` を grep |
| QueryFrame 等の復元が複雑 | 専用ヘルパー関数 + ラウンドトリップテスト |
| チェックポイントファイルの蓄積 | MERGE 成功時に自動削除 + `--clean` で全削除 |
| definitions_cache のタプルキー | JSON 配列に変換(パイプ区切りより堅牢) |
| `-r` 短縮の再割り当て | `--rebuild -r` → `--rebuild`(短縮廃止)。低頻度コマンドのため影響軽微 |
| 256KB 制限で正当な大規模結果が切れる | 切り詰め時に警告 + 総マッチ数を返し、LLM にパターン絞り込みを促す |
---
## 実装ステータス
全 8 ステップ完了。テスト 28 件全パス。
| ステップ | 内容 | ステータス |
|----------|------|-----------|
| 1 | `tools/session.py` — `to_dict()` 完全化 + `from_dict()` + 復元ヘルパー + チェックポイント操作 | ✅ |
| 2 | `code_intel_server.py` — チェックポイント保存/復元ワイヤリング | ✅ |
| 3 | `code_intel_server.py` — 18 ツール削除(39 → 21 ツール) | ✅ |
| 4 | `cleanup_stale_branches` 拡張 + `.gitignore` 確認 | ✅ |
| 5 | `code_intel_server.py` — `_truncate_response()` 256KB 制限 | ✅ |
| 6 | `.claude/commands/code.md` — `--resume` フラグ + `--rebuild` 短縮廃止 | ✅ |
| 7 | `tests/test_v1_12_features.py` — 8 クラス 28 テスト | ✅ |
| 8 | ドキュメント最終化 | ✅ |