AI に同じ失敗を
二度させない
開発体制を「進化」させる仕組み
個人開発のリポジトリで回している「開発体制を進化させる仕組み」についてまとめる。
何を作っているか
- 進化型カード TRPG「カルタグラフ」
- 仕様書サイト(VitePress)+ Web アプリ(React)
- 書いているのは主に AI コーディングエージェント
- 人間は「決める」「確かめる」係
Note:
作っているのは「カルタグラフ」という、遊ぶほどルールが進化していくカード TRPG 。
仕様書サイトと Web アプリのモノレポで。コードはほとんど AI エージェントに移譲。
何を作るか決めることと、出来上がったものを確かめることが人間の仕事。
ルールに書いても反映されないことがある
CLAUDE.md に「heredoc でファイルを書くな」と書いた
↓
次の PR でまた heredoc で書いて壊す
ルールを読ませても、注意力はモデル次第・その日次第
Note:
注意書きは「読んで、覚えていて、守る」という AI の注意力に頼っているので、モデルやその日のコンテキストで簡単に崩れる。
発想:体制そのものを「進化」させる
候補 → 評価 → 採用 / 却下
(誰でも) (人間が裁定) (却下も理由付きで残す)
- 記録先は1ファイル:
docs/process/evolution.md - 採用した変更には きっかけ と 止め方 を必ず書く
Note:
「進化ループ」を開発体制にも入れた。
作業中に「ルールが足りない」「邪魔だった」と気づいたら、人間でも AI でも候補として進化ログに書く。
振り返りで人間が採用か却下を決める。却下したものも消さずに、理由と一緒に残す。
ポイントは、採用した変更には必ず「何がきっかけで」「どうやって止めるか」を書くこと。
1サイクルの流れ
1. プラン作成(AI が質問・人間が答える)
2. プランの AI レビュー
3. テスト網羅レビュー
4. 実装
5. テスト全通過(TDD)
6. 実装の AI レビュー(3観点を並列)
7. 人間レビュー
8. push・振り返り ──▶ 進化ログに候補を出す
振り返りで出た改善が、次のサイクルのルールになる
Note:
1機能をこの8ステップのサイクルで作成。
最後の「振り返り」で出た改善候補が、次のサイクルのルールや仕組みになる。
開発サイクルの外側に、体制を育てるもう1つのループが回っている。
方針:改善は「ルール」より「仕組み」で
止め方を4つに分類している
| 止め方 | 例 |
|---|---|
| 機械 | git フック・CI・lint・ビルド時の検査 |
| レビュー観点 | AI レビューのチェック項目に足す |
| 手順・ルール | 文書に書く |
| 置き場所 | ページ・ファイルを新設・移動する |
まず機械で止められないか考える。
ルールで済ませるなら、その理由を書く
Note:
改善の止め方は4種類に分けて記録。
一番効くのは「機械」で止めること。git フック、CI、lint、ビルド時の検査方針として、改善案を出すときはまず機械で止められないかを考え、文書のルールで済ませるときは「なぜ機械にしないか」を書くことにしている。
人や AI の注意力に頼る形は、モデルや担当が変わると崩れる。
実例①:置換が二重に当たった
失敗:sed -i で用語を置き換えたら
「作者」→「製作者」が2回当たり 「製製作者」 に
テストの期待値も同じ置換で化けて、テストは通った
↓
- Claude Code のフックで
sed -iを止める - 置換は
replace-once.mjsで
「件数」と「二重の当たり」を確かめてから書く
きっかけ:作業中の失敗 / 止め方:機械
Note:
実例をいくつか紹介。
用語をそろえるときに AI が sed -i で置換したら、同じ置換が2回当たって「製製作者」という謎の言葉が生まれた。
しかもテストの期待値も一緒に化けたので、テストは通ってしまった。
注意書きではなく、Claude Code のフックで sed -i 自体を止め、代わりに件数を宣言して二重の当たりも検査する置換スクリプトを使わせるようにした。
実例②:用語の揺れが毎回レビューで出る
失敗:「シナリオ作成者/制作者/作者」…
AI レビューが毎回見つけ、毎回直す
↓
- 旧称の一覧を持つ
check-terms.mjsを作り -
pnpm docs:buildの最後で ビルドを落とす - pre-push・CI でも止まる
きっかけ:AI レビュー / 止め方:機械(ビルド時の検査)
Note:
「作成者」「制作者」「作者」がバラバラに書かれていて、AI レビューが毎回それを見つけて、毎回直していた。
レビューで見つかるのは良いことだが、毎回同じ指摘にトークンを払うのはもったいない。
旧称の一覧を持つ検査スクリプトを作り、ドキュメントのビルドで落とすようにした。
実例③:進化ログ自体の書き漏らし
失敗:体制を変えたのに、進化ログに書き忘れた
↓
.githooks/commit-msg で止める
- ルール・
AGENTS.md・.claude/・CI などを変えたのに
進化ログが変わっていないコミットは 拒否 - 不要なら
進化ログ不要: <理由>を書けば通る
Claude Code のフックではなく git のフック = どのツールでも効く
Note:
3つ目はちょっとメタな話で、進化ログそのものの書き漏らし。
体制を変えたのにログに書き忘れることがあった。
そこで、ルールや CI、.claude 配下などを変えたのに進化ログが変わっていないコミットは、commit-msg フックで止めるようにした。
記録が要らない場合は「進化ログ不要」と理由を書けば通る。なぜ記録しなかったか、も残る。
Claude Code ではなく git のフックにしたのは、どのツールで作業しても効くようにするため。
1か月の結果
採用 44 件(却下 4 件)
| 止め方 | 件数 |
|---|---|
| 機械 | 29 |
| 手順・ルール | 21 |
| 置き場所 | 11 |
| レビュー観点 | 4 |
※1件に複数の止め方あり。
機械で止めた割合:9月 62% → 10月 68%
Note:
1か月で採用したのが 44 件、却下が 4 件。
止め方の内訳は、機械が 29 件で一番多く、44 件のうち 3 分の 2 は機械で止めている。
月別に見ると、機械で止めた割合が少しずつ上がっている。
タイムラインも自動生成
- 進化ログの「きっかけ」「止め方」を
ビルド時に読み取って年表と内訳を描く - 書き写さないので二重管理にならない
- 書式が崩れていたら ビルドが止まる
docs/process/timeline.md ← evolution.md から生成
Note:
この数字も手で数えていない。
進化ログの「きっかけ」「止め方」をビルド時に読み取って、仕様書サイトに年表と内訳を自動で出している。
書き写さないので二重管理にならないし、書式が崩れていればビルドが止まるので、記録の質も機械で守られる。
モデル・ツールが変わっても回るように
- 入口はツール非依存の
AGENTS.md-
CLAUDE.mdはそれを読み込むだけ
-
-
.claude/は 呼び出し口、手順の本文はdocs/process/ - サブエージェントの model は
inherit(固定しない) - 作業ごとに 段(強い/標準/軽い) で割り当てる
Note:
もう1つ意識しているのが、特定のモデルやツールに依存しないこと。
入口はどのエージェントでも読む AGENTS.md にして、CLAUDE.md はそれを読み込むだけ。
.claude の中のスキルやサブエージェントは呼び出し口にして、手順の本文はリポジトリのドキュメントに置いている。
モデルも製品名で固定せず、「強い・標準・軽い」の段で作業ごとに割り当てている。
これも、トークンを使いすぎだという振り返りから入った変更。
人間が決めるところは固定する
- ルールと仕様が矛盾したら → 止めて人間に聞く
- 採用 / 却下の裁定 → 人間
- 人間レビューは AI に判定させない唯一の型
AI が提案し、機械が守り、人間が決める
Note:
全部を AI と機械に任せない。
ルールと仕様が矛盾したら AI は止まって人間に聞く。改善を採用するかどうかは人間が決める。
人間レビューは、AI には説明だけさせて、判定は人間がする。
AI が提案し、機械が守り、人間が決める、という役割分担。
まとめ
- 失敗は 進化ログ に「きっかけ」と「止め方」で残す
- 止め方は ルールより機械(フック・CI・ビルド時の検査)
- 知識は モデルではなくリポジトリ に置く
注意書きを増やすより、
同じ失敗ができない仕組みを増やす
今日話すこと
- 開発用の GitHub Pages に何を載せているか
- 開発サイクルと「体制の進化」サイクル
- やりすぎて戻した話
github.io に全部載せる
hibohiboo.github.io/CarTaGraphFantasy/
| ページ | 中身 |
|---|---|
| ダッシュボード | ゴール・要望の進み具合・判断待ち |
| 仕様書 | ゲームの仕様・用語集・未解決論点 |
| アプリ | MSW 入りの Web アプリ(触れる仕様書) |
| テストレポート | E2E(スクショ付き)・Vitest |
| API ドキュメント | zod → OpenAPI → Redoc |
| 進化のタイムライン | 開発体制がどう変わったか |
main に push するたび GitHub Actions で全部ビルドし直す
Note:
ほかにティザー映像、未React化の画面のHTML試作も置いている。
方針:状況を手で書かない
docs/backlog/*.md (1要望1ファイル・frontmatterに状態)
docs/roadmap.md (マイルストーン)
docs/provisional/ (仮ルール)
docs/open-questions.md
│ ビルド時に *.data.ts が集める
▼
トップページのダッシュボード
- 「いま何をやっていて、何が決まっていないか」を書き写さない
- ファイルを1つ直せば、ダッシュボードも直る
ダッシュボードは読み手ごとに分ける
- 全体 … ゴールとマイルストーン、いま取り組んでいる所の残り
- PO 向け … 決めないといけないこと(要望の判断待ち・仮ルール・未解決論点)
- 開発者向け … 要望ごとのサイクル、既知の問題、進化ログの未評価の候補
人間がやることは「判断待ち」を見て決めるだけ
Note:
AI が人間の判断を要すると、要望ファイルの状態を「判断待ち」にして decisions に書く。それがそのままダッシュボードに出る。
ビルドが仕様書の番人
pnpm docs:build で止めているもの(一部)
- リンク切れ・見出しへのリンクのずれ
- 用語集にない 旧称 の使用
- 画面一覧とルート定義の食い違い
- 仮ルールの一覧と、仕様ページの「仮」の印の食い違い
- lint 抑制(biome-ignore)と既知の問題の一覧の食い違い
→ AI が書いても人が書いても、ずれたら落ちる
アプリとテスト結果も Pages に
- バックエンド無し・MSW なので 静的ホスティングで動く
- 仕様書の隣で、実際の画面を触って確かめられる
- テストは落ちても デプロイは止めない
- 落ちたままのレポートを載せる。気づくのは CI とレポート
- API ドキュメントは
packages/schemasの zod から自動生成
開発サイクル(1機能 = 1サイクル)
1. プラン作成(AIがインタビュー、人間が答える)
2. プランのAIレビュー
3. テスト網羅レビュー
4. 実装
5. テスト全通過(TDD)
6. 実装のAIレビュー(3体並列:設計/異常系/仕様)
7. 人間レビュー(AIが画面を操作して説明、人間が判定)
8. push・振り返り
- 正は
docs/process/、入口はAGENTS.md - Claude Code の skills / agents は 呼び出し口だけ
Note:
特定のモデル・ツールが使えなくなっても回るように、知識はリポジトリに置く。
人間がやるのは3つだけ
- プランのインタビューに 答える
- 人間レビューで 判定する(AIに判定させない唯一の型)
- 振り返りで改善案を 採用/却下する
lint・型検査・テスト・docsビルドは git フックと CI が止める
→ AI にも人にも確認させない
もう1つのループ:体制の進化
開発サイクル ──振り返り──▶ 候補
│
人間が採用/却下
│
ルール・スキル・フック・CIを更新
│
次のサイクルへ ◀┘
ゲーム本体の「進化候補の評価」と 同じ型 で、
開発プロセス自体を進化させる
却下も理由つきで残す(約50件を記録)
改善は「注意」ではなく「仕組み」で
| 起きたこと | 止め方 |
|---|---|
| AI が heredoc で書いてバックスラッシュが崩れる(2回) | Claude Code のフックで止める |
AI が勝手に --no-verify
|
設定の deny で止める |
| 用語の揺れ(制作者/作者…) | ビルドで旧称を検出 |
| 進化ログの書き忘れ | commit-msg フック |
| 依存の向きを自前テストで検査 | Biome のルールに置き換え |
ルールを読ませるだけでは、モデルが変わると崩れる
進化のタイムライン
進化ログの「きっかけ」「止め方」から年表をビルド時に自動生成
止め方の内訳(概算)
- 機械(CI・フック・lint・ビルド時検査)… 31
- 手順・ルール … 29
- 置き場所 … 6
- レビュー観点 … 3
書式が読めないとビルドが止まる
Note:
実際のページを見せるならここ。/process/timeline
やりすぎた①:完璧主義
- 10月、進め方を変えたコミット 76 vs コードを変えたコミット 78
- 振り返りの候補が ほぼ全件採用 されていた
→「楽観ロックでリスクをとれ」で見直し
- 仕組みにするのは 2回目の失敗から
- 戻せない失敗だけは1回目から止める
- P2 の指摘は直さず記録だけ
- プランのレビュー観点を中身で絞る
やりすぎた②:トークン
1週間のセッション記録を集計すると…
- 読み込み約 23億トークン、ほぼ全部がキャッシュの読み直し
- うち約20億が「1サイクルを1セッションで通した」6セッション
-
sed -n小分け読み 519回
→ サイクルの区切りで セッションを分ける
→ モデルを段(強い/標準/軽い)で作業ごとに割り当てる
→ pre-push は成功したら1行
まとめ
-
状況は書き写さず、ビルドで組み立てる
(ダッシュボード・タイムライン・API ドキュメント) - 人間は判断だけ、確認は機械に寄せる
- 開発プロセスも 候補 → 評価 → 採用/却下 で進化させる
- ただし、仕組みも重さになる。2回目から