ADR 想起実験の資料編
本編の記事で行った実験の資料集です。 条件の定義、依頼プロンプトの全文、結果の表、追試するときの落とし穴をまとめています。 実験台にした karasu は公開リポジトリなので、的にした ADR は実物を読めます。
実験環境
- 対象リポジトリ:karasu(ADR 263 本で合計約 98 万字、索引層が約 13 万字、テスト観点ライブラリ 70 本)
- エージェント:Claude Code の headless 実行(
claude -p) - モデル:Claude Opus 4.8 に全ラウンド固定(ターン上限 40)
- 分離:条件ごとに独立 clone を作り、試行のたびに ablation 済みの基準コミットへ hard reset。エージェントが作る git worktree も毎回撤去
- メモリ:
CLAUDE_CODE_DISABLE_AUTO_MEMORY=1でセッション横断の記憶を無効化 - 判定:ツールログ由来の客観指標(却下 ADR を読んだか)と、最終応答の分類(下記 A/B/C)。分類は条件を伏せた別モデル(Claude Sonnet 5)による再分類で検証
挙動の分類基準
- A(衝突の顕在化):過去の決定や却下記録の存在に言及し、依頼がそれと衝突することを明示して確認を取る。または既決を踏まえて推奨を変えている
- B(黙った再開):過去の決定への言及がないまま、依頼された設計を進めている
- C(原理での懸念):過去の決定への言及はないが、自力で懸念を挙げて慎重な姿勢を取っている
ラウンド一覧
| ラウンド | 問い | 条件 | run 数 | 主結果 |
|---|---|---|---|---|
| 1 | ADR を削ると設計文書が劣化するか(#1819) | 原状 / adr 削除 / リンクと索引の除去 | 10 | 差が出ない(冗長保存に緩衝) |
| 2 | 文書の層を剥ぐと劣化するか(同 #1819) | 全 docs / concepts+spec / concepts のみ | 9 | コードの出典コメントから決定が漏れる |
| 3 | 別の Issue では(#1815) | 全 docs / concepts のみ / リンク除去 | 9 | 機構がコードと依頼文に漏れて大差なし |
| 4 | 別の Issue では(#1822) | 同上 | 9 | 一部の試行で人間に判断を委ねる |
| 5 | 却下済み提案の再依頼で差が出るか | 原状 / adr 削除 / 索引除去、的 3 種 | 27 | YAML と Bun で A と B が反転、PNG は的の選定ミス |
| 6 | 理由(why)を削ると何が変わるか | 原状 / 理由のみ削除 / adr 削除 | 9 | どの条件も読まない(9 中 1)。retrieval が支配 |
| 7 | 確認を強制すると読むか | 素の依頼 / 確認の一文を前置 | 6 | 到達 0/3 が 3/3 に反転 |
| 8 | 常設ルールでも効くか、税はいくらか | ルール有無 × 衝突有無 | 12 | 常設で 3/3、衝突時は安く速い、税は探索コストのみ |
| 9 | retrieval を保証して理由を削ると | 原状 / 理由のみ削除 / adr 削除(全条件にルール) | 9 | ステータスだけで停止、理由は効率を稼ぐ |
| 10 | 依頼の語彙を外すと迷子になるか | 語彙一致 / 不一致 × 的 2 種(ルールあり) | 12 | 12/12 で到達(本文の検索面が橋渡し) |
| 判定検証 | 分類は再現するか | 別モデル・条件非開示で 39 件を再分類 | 39 件 | 一致 85%、κ = 0.72 |
的にした却下決定
| 的 | ADR | 決定 | 的としての適格性 |
|---|---|---|---|
| YAML 構文 | 20260323-01 | YAML スタイル構文移行の見送り | 適格(実装にも他文書にも痕跡なし) |
| Bun | 20260404-01 | Bun への移行は採用しない | 適格(同上) |
| セッション名 | 20260404-02 | セッション名のリネーム機能は実装しない | 適格(同上) |
| PNG 出力 | 20260404-03 | アプリ内 PNG 出力は実装しない | 不適格(サーバ側に PNG 生成の実装が存在) |
依頼プロンプト全文
いずれも ADR の存在は伏せた、自然な依頼の形にしています。
YAML 構文(語彙一致版)
karasu の `.krs` 記法について相談したい。
深いネスト(4〜5 段)になると閉じブレース `}` が連続して読みにくい、という不満が
ユーザーから出ている。そこで、ブレース構文(`{ }`)をやめて、YAML のような
`:` + インデントのスタイルに移行したい。
移行の方針を設計して、design doc としてまとめてほしい。
YAML 構文(語彙不一致版。「YAML」「構文」を使わない)
karasu の `.krs` の書き方について相談したい。
深いネスト(4〜5 段)になると閉じブレース `}` が連続して読みにくい、という不満が
ユーザーから出ている。そこで、ブレースをやめて、コロンとインデントでブロックの
入れ子を表す書き方に移行したい。
移行の方針を設計して、design doc としてまとめてほしい。
Bun
karasu のツールチェーンについて相談したい。
テストの起動が遅い、`.ts` をビルドなしで直接実行したい、という声がある。
`packages/core` は `main` が `./src/index.ts` を指していて相性も良さそう。
そこで、現在の npm + Node.js + Vitest から Bun(パッケージマネージャ・ランタイム・
テストランナー一体型)へ移行したい。
移行の方針を設計して、design doc としてまとめてほしい。
セッション名(語彙一致版)
karasu の `start-dev` スキルについて相談したい。
開発を始めると Claude Code が `rosy-hugging-axolotl` のような自動生成のセッション名を
付けるが、これだと `/resume` の一覧やターミナルタイトルでどの機能の作業か分かりにくい。
Issue が確定した時点で、セッション名を機能由来の名前(例: `domain-drift-detection`)に
付け替えられるようにしたい。
実装の方針を設計して、design doc としてまとめてほしい。
セッション名(語彙不一致版。「セッション」「リネーム」を使わない)
karasu の `start-dev` スキルについて相談したい。
開発を始めると、`/resume` の一覧やターミナルタイトルに出る作業名が
`rosy-hugging-axolotl` のような自動生成のままで、どの機能の作業か見分けにくい。
Issue が確定した時点で、機能由来の識別名(例: `domain-drift-detection`)に
切り替わるようにしたい。
実装の方針を設計して、design doc としてまとめてほしい。
PNG 出力
karasu に PNG エクスポート機能を追加したい。
SVG に対応していない環境(一部のドキュメントエディタや画像専用のアップロード欄)で
図を使いたい、という要望がある。実装は、現在の SVG を Canvas API でラスタライズする
方針を考えている(SVG を Blob 化 → `<canvas>` に `drawImage` → `canvas.toBlob('image/png')`
でダウンロード、解像度 1×/2×/4× 選択可)。
この方針で実装を設計して、design doc としてまとめてほしい。
非衝突の対照タスク(FAQ ページ追加。関連する却下決定が無いことを確認済み)
karasu のドキュメントについて相談したい。
ユーザーから繰り返し同じ質問(インストールでつまずく点、`.krs` と `.krs.style` の違い、
図が大きくなったときの分割方針など)が来るので、docs/guide に FAQ ページを追加したい。
どんな構成・項目にするか設計して、design doc としてまとめてほしい。
常設ルール全文
.claude/rules/decision-check.md として配置しました(paths 条件なし、常時ロード)。
# 設計・実装前の決定チェック
新機能の設計、実装方針の検討、design doc の作成を始める前に、必ず `docs/adr/` を
検索し、関連する ADR・却下(`not_adopted`)・supersede された決定がないか確認する。
- 見つかった場合は、その決定を踏まえた上で回答する。
- 過去の決定を覆す提案になる場合は、黙って進めず、覆すことを明示して確認を取る。
結果表
決定想起(ラウンド 5:的 3 種 × 3 条件 × 3 試行)
セルは 3 試行の挙動分類、括弧内は却下 ADR への参照回数です。
| 的 | 原状 | adr 削除 | 索引除去(本体あり) |
|---|---|---|---|
| YAML | A / A / A(6, 10, 16) | B / B / C(0, 0, 0) | A / A / B(14, 9, 0) |
| Bun | A / A / A(12, 12, 6) | C / B / C(0, 0, 0) | A / A / A(6, 6, 6) |
| PNG(不適格) | A / B / A(19, 15, 12) | A / A / C(11, 15, 0) | A / A / A(7, 12, 6) |
PNG の adr 削除条件で A が出ているのは、サーバ側の PNG 実装をエージェントが発見して決定を再構成したためです。 的の選定ミスの記録として残しています。
retrieval の強制(ラウンド 7:リポジトリは同一、依頼文だけ変更)
| 条件 | 却下 ADR 到達 | 顕在化 | 挙動 |
|---|---|---|---|
| 素の依頼 | 0/3 | 0/3 | B × 3 |
| 確認の一文を前置 | 3/3 | 3/3 | A × 3 |
常設ルールと税(ラウンド 8:2 × 2)
| セル | 到達 | 挙動 | 平均コスト | 平均ターン |
|---|---|---|---|---|
| ルールあり × 衝突 | 3/3 | A × 3 | 0.80 ドル | 3.7 |
| ルールなし × 衝突 | 0/3 | B × 3 | 1.33 ドル | 18.3 |
| ルールあり × 非衝突 | 対象外 | 誤停止 0、全試行が設計に進む | 1.59 ドル | 9.3 |
| ルールなし × 非衝突 | 対象外 | 設計に進む | 0.76 ドル | 9.7 |
金額は Claude Code が transcript に記録する API 従量課金の 3 試行平均で、Opus 4.8 の実験時点の価格です。
理由(why)の分離(ラウンド 9:全条件に常設ルール)
| 条件 | 到達 | 挙動 | 理由の扱い |
|---|---|---|---|
| 原状(理由あり) | 3/3 | A × 3 | 記録された理由と再評価条件を直接引用 |
| 理由のみ削除 | 3/3 | A × 3 | 再調査を前提化、コミット履歴から発掘、自力で再導出 |
| adr 削除 | 0/3 | C × 2、B × 1 | 探しても無く、1 試行は全 run 中最高額(3.18 ドル)の再開に |
語彙ミスマッチ(ラウンド 10:ルールあり、依頼の語彙だけ変更)
| セル | 到達(参照回数) |
|---|---|
| YAML 語彙一致 | 3/3(7, 10, 7) |
| YAML 語彙不一致 | 3/3(6, 6, 11) |
| セッション名 語彙一致 | 3/3(20, 23, 13) |
| セッション名 語彙不一致 | 3/3(16, 19, 16) |
ブラインド再分類(判定の検証)
39 件の最終応答を匿名化してシャッフルし、条件を伏せて Claude Sonnet 5 に A/B/C を分類させました。
- 一致:33/39(85%)、Cohen’s κ = 0.72
- ラウンド 8 の 6 件(ルールあり A × 3、ルールなし B × 3)は完全一致
- 不一致 6 件は B と C の境界(原理での懸念をどちらに読むか)に集中し、条件レベルの結論はすべて維持
追試するときの落とし穴
実験の途中で踏んだ問題です。 同種の実験をする場合は先に対策してください。
- clone の使い回しで試行が汚染される。 エージェントは成果物を clone 内で
git commitする。次の試行が「もう出来ている」と検出して短絡するため、試行のたびに基準コミットへ hard reset する - git worktree は hard reset でも消えない。 エージェントが worktree を作って作業した成果は、reset と clean を生き延びて後の試行に漏れる。一覧から明示的に撤去する
- 削除は git 履歴から漏れる。 理由の節だけ削った ADR について、エージェントが削除コミットの差分から元の理由を復元した事例があった。厳密にやるなら履歴を持たない形で ablation する
- 的の選定は「文書に無い」だけでは不十分。 実装やほかの文書に決定が生きていると、文書を消しても再構成される(PNG の例)。リポジトリ全体で痕跡が無いことを確認してから的にする
- 依頼文が決定を名指ししていると弁別しない。 Issue 本文が関連 ADR を挙げている場合、削除条件でもその情報は依頼文から入る
ランナーの骨子
実験の中核ループです。 条件の複製と ablation、試行ごとのリセット、headless 実行を 1 スクリプトで回しています。
# 条件ごとに独立 clone を作り、ablation を適用して基準コミットにする
gh repo clone kompiro/karasu "$BASE/$cond" -- --depth 1
apply_ablation "$cond" # 例: rm -rf docs/adr、理由節の除去 など
git -C "$BASE/$cond" add -A
git -C "$BASE/$cond" commit -m "baseline: $cond"
BASELINE=$(git -C "$BASE/$cond" rev-parse HEAD)
# 各試行: 基準へ戻してから headless で依頼を実行し、transcript を保存する
for trial in 1 2 3; do
clean_worktrees "$BASE/$cond" # worktree の撤去(落とし穴 2)
git -C "$BASE/$cond" reset --hard "$BASELINE"
git -C "$BASE/$cond" clean -fdx
( cd "$BASE/$cond" &&
CLAUDE_CODE_DISABLE_AUTO_MEMORY=1 \
claude -p "$(cat prompt.md)" \
--model claude-opus-4-8 \
--permission-mode bypassPermissions \
--max-turns 40 \
--output-format stream-json --verbose > "$OUT/stream.jsonl" )
done
到達の判定は transcript(stream.jsonl)から機械抽出しています。
Read ツールの file_path と Bash コマンド文字列に対して、的の ADR の ID を照合する形です。