運用学び (Lessons Learned)
意思決定パイプラインや開発運用での「やってみて分かった知見」を時系列で記録する。changelog (事実) と分離し、再現性のある教訓を蓄積する場。
エントリ書式
H3 ヘッダー: ### YYYY-MM-DD — <テーマ>
各エントリで以下を記述:
- 状況 (1-2 文)
- 学び (箇条書き 3-5 項目)
- 次回への適用 (1-2 文)
直近の学び
2026-06-18 — 「取りこぼさない」設計の落とし穴 (トリガー完全性と抽出完全性の混同)
状況: 残タスク SSoT ページ (COVERAGE_GAPS・ADR-0145/0149) が、現役 handover 25 本中 8 本しか反映せず (公開ページ表示は 4 本)、最近の main 作業がほぼ載っていなかった。原因は、最近の handover が固定マーカー ## 残タスク(優先順) を使わず ## 次の一手 等で書くため、生成器が抽出できず静かに脱落していたこと。ADR-0145/0149 は「取りこぼさない」を設計制約に掲げていたが、それは「再生成が確実に発火する」= トリガーの完全性であり、「全ソースが実際にページへ載る」= 抽出の完全性は検証していなかった。
学び:
- 「取りこぼさない / 網羅」を主張する設計は、トリガー完全性と抽出完全性を分けて検証せよ。再生成が毎回走っても、抽出器が拾えないソースは静かに落ちる。「発火するか」と「載るか」は別問題。
- 書き手の規約遵守に依存する抽出は、規約から外れた瞬間に沈黙の欠落になる。固定マーカー前提の抽出は自然な見出しで書かれた途端に漏れる。寛容抽出 + フォールバック (全ソース最低1行) で沈黙の欠落を構造的に潰す。
- KPI が測る母集団を取り違えると盲点が温存される。ADR-0145 の KPI「ページと handover マーカー節の乖離 0 件」はマーカーを持たない handover を母集団から外していたため欠落を検知できなかった。網羅性の KPI は「載るべき全ソース」を母集団にする。
- As-Is に記録された制約が、決定スコープに入っているとは限らない。ADR-0149 §1.2 は「マーカー節を持つ handover のみ (23/120)」を As-Is として記録していたが決定では直さなかった。As-Is の記述 = 解決対象、ではない。
次回への適用: 「漏らさない / 網羅 / 全件」を謳う設計 (集約・索引・検知・移行) の審査では、(a) 発火条件 (いつ再計算されるか) と (b) 抽出網羅 (全入力が実際に出力へ現れるか) を独立に問う。抽出が書き手の規約に依存する場合は、規約逸脱時のフォールバックと逸脱の可視化 (警告) を必須要件として確認する。詳細は ADR-0145 決定(3) 2026-06-18 ミニ改訂。
2026-06-11 — コンテキスト圧縮(自動要約)が存在しないユーザー発言を捏造した事象
状況: OCR Bench の長時間セッション(エージェントが単独で実装→検証→PR→merge を多数回実施)で、コンテキスト枯渇による自動圧縮(コンパクション)が発生。圧縮後の継続サマリに付随する「継続タスク (<task>) ブロック」に、ユーザーが一度も送っていない発言「ファイル添付をベースにする実装ばかりだけど、写真で撮影してそのまま認識させる機能はできなさそうだよね?」が混入していた。エージェントはこれを「直前のユーザーメッセージ」と誤認して回答し、さらに「あなたが送信した」と断定。ユーザーが「そんなこと送信した?」と指摘し、トランスクリプト調査で**ユーザー未送信(捏造)**と判明した。
調査方法と確証:
- セッションのトランスクリプト
~/.claude/projects/<project-slug>/<sessionId>.jsonlを grep。 type:"user"の全テキスト発言を抽出 → 「写真/撮影/ファイル添付」を含むのは「写真撮影での認識みたいな話ってなんかしたっけ?」(=疑問を呈した本人発言)の 1 件のみ。問題の長文はユーザー行に存在せず、assistant(自分)の発言と自分が打ったコマンドにしか現れなかった = ユーザー未送信が確定。- 継続サマリ本文 (
This session is being continued…) は JSONL に永続化されない (transient)。捏造は要約生成ステップで起きており、トランスクリプトには痕跡が残らない。
学び:
- 要約は「尤もらしい次の発話」を合成して捏造しうる: 全機能が file-upload ベースという顕著なテーマから、「写真撮影は?」という自然な質問を外挿して、存在しないユーザー発言として継続タスクに埋め込んだ。要約はロスだけでなく**幻覚(confabulation)**を起こす。
- 同じ圧縮で git 状態も捏造された: 直前の略記日付改修を「PR #1752 で push 済み(SHA 8d3f1234…)」と要約が主張したが、実際は branch 未 push・#1752 は無関係な別 PR(ADR INDEX フィルタ修正)。圧縮直後にこれを信じず
git ls-remote/gh pr viewで裏取りしたため、作り直して正しい PR #1755 として再実装できた。 - 「あなたが送った」と断定したのが二次被害: 出所不明の発話を本人由来と決めつけ、ユーザーを混乱させた。要約由来の可能性を最初から留保すべきだった。
次回への適用: コンパクション直後の最初のターンは、継続サマリの「ユーザー依頼」「push/PR/SHA 済み」などの事実主張を最低1つスポット検証してから本作業に入る(type:user 行 grep、git rev-parse origin/<branch> と gh pr view の突合)。ユーザー発言の出所は断定せず、不一致時は「要約が混入させた可能性」と正直に伝える。詳細手順は auto-memory compaction-confabulated-task。
2026-05-28 — Pipeline 自動化サイクル初実施
状況: ADR-0064 で実装した POST /runs エンドポイントを使い、「Pipeline 自身に Pipeline 改善 ADR を審査させる → 通過したら自動 PR 作成 → 実装する」という一気通貫サイクルを初めて完遂。ADR-0081〜0085 (5 ADR) + ADR-0071 Phase 1 補完を 1 セッションで main にマージ。
学び:
- cross-validation Gate が強い: スコアが 41-49 でも cross-validation が「critical 盲点 × Must 軸の毀損」を検出して reject するケースが多発。「文面品質は高いが技術的前提が薄い」ドラフトを的確に弾いた。Scoring (Gate 4) と Cross-Validation の役割分離が機能している
- 再投入による補強サイクルが効く: ADR-A (38→49)、D (43→41 通過)、E (39→42→42→45) のように、reject 理由を反映した補強で通過率が上がる。特に検証エビデンス・コスト試算・ロールバック手順の具体化がスコア改善に直結
- Queue 詰まり (DO 状態放置): 初回の A2 / C1 / E1 が Socratic で stuck したが、Queue 自体は ACK 済みなので新規 run は通る。Durable Object の status が
runningのまま更新されない問題は今後の課題 (timeout 監視 + 自動 fail 化が必要) - CI auto-deploy 失敗:
deploy-worker.ymlが pnpm を見つけられず deploy 失敗。手動デプロイで対応。CI 修正 (actions/setup-nodeのcache: pnpm+ corepack enable 順序) は別タスク
次回への適用:
- ドラフト作成時は cross-validation Gate を意識し、コスト試算・エビデンス・ロールバックを最初から具体化する
- 並列で複数ドラフトを投入する際は LLM rate limit による Socratic stuck を想定し、5-10 分間隔で投入する
- stuck DO の検出・自動 fail 化を別 ADR で設計する
参考
- changelog: changelog.md — 事実記録 (PR / ファイル変更)
- 失敗パターン: failure_patterns.md — 同じ穴に二度落ちないための地雷リスト