第8章 設計原理 — 反復サイクルとHarness設計
第7章では、論文1本という限定された課題に対して、機能を一つずつ追加する体験をした。CLAUDE.md 6行で始めて、Rules、Skills、Hooksと段階的に馬具を装着していった。しかし実際の研究や開発では、タスクはもっと複雑だ。たとえば同じ概念分析でも、論文が3本に増えれば、1本のときには起きなかった問題が生じる。データ量が増えてコンテキストに収まらなくなる。チャンクに分割すればチャンク間の整合性が問題になる。並列処理すればWorker間の成果物を統合する仕組みが必要になる。セッションをまたぐと「前回どこまで進んだか」が失われる。途中で「ノードの粒度が粗すぎた」と気づけば、仕様に戻って方針を変えなければならない。CLAUDE.md 6行では到底足りず、プロジェクト全体を通じた設計が必要になる。
この構造は概念分析に限らない。実験画像群から物理量を抽出する解析でも、仕様書に基づいてシミュレーションを実装するタスクでも、Webアプリを構築するプロジェクトでも、同じことが起きる。
実は、こうした反復サイクルはAIの登場ではじめて生まれたものではない。科学研究では「仮説を立て、実験し、結果を分析し、仮説を修正する」というプロセスが、科学的方法の核心として古くから認識されてきた。ソフトウェア開発の世界でも同様だ。1950年代のNASA Mercury計画の頃から、反復的開発はウォーターフォール型の一方向プロセスに代わる手法として実践されてきた。反復的開発の手法は進化を続け、現在では科学的方法の構造をソフトウェア開発に直接持ち込んだアプローチも広く実践されている(Agile開発、Hypothesis-Driven Developmentなど)。つまり研究も開発も、「問いを立て、構造化し、実行し、評価して、問題があれば戻る」という同じ骨格のサイクルを回している。違うのは内容であってプロセスではない。
AIを使ったプロジェクトでも、このサイクルの構造は同じだ。ただし、AIが加わることで新しい設計判断が生まれる。サイクルの各段階でAIにどの程度の自由を与えるか——この「自由度の配置」が、従来の研究プロセスや開発プロセスにはなかった設計変数になる。概念分析ではAIの意味解釈に大きく依存する一方、画像解析では手順の遵守が最優先だ。シミュレーションではテストが通るかどうかで成否が決まる。失敗のコストが高いタスクほど、決定論的制御の比重が上がる。
| 概念分析 | 画像解析 | シミュレーション | ソフトウェア | |
|---|---|---|---|---|
| 確率的制御の比重 | 高 | 中 | 低 | 中 |
| 決定論的制御の比重 | 低 | 高 | 最高 | 中〜高 |
| 失敗のコスト | 低 | 高 | 高 | 中 |
| Hooksの必要度 | 低〜中 | 高 | 必須 | 高 |
| satisficingの明確さ | 低(形式的) | 中(統計的) | 高(テスト通過) | 中(要件充足) |
プロセスは共通だが自由度の配置がタスクの性質で変わる。この共通のプロセスを一般原理として整理し、自由度の配置をどう設計するかを論じるのが本章の目的だ。
8.1 反復サイクル — 自由度の配置がHarness設計の核心
冒頭で述べたように、科学的方法もソフトウェア開発も反復サイクルを回す。科学では「仮説→実験→分析→修正」、ソフトウェア開発では「計画→実装→テスト→レビュー」だ。AI駆動のプロジェクトでもこの骨格は変わらないが、各段階の呼び方と役割をHarness設計の文脈で整理すると、以下の4段階になる。
科学的方法と対応させると、「意図の表明」は研究課題の設定に、「構造化」は実験計画の策定に、「実装」は実験の遂行に、「評価」は結果の分析に相当する。ソフトウェア開発なら、「意図の表明」は要件定義、「構造化」は設計、「実装」は開発、「評価」はテスト・レビューにあたる。呼び方は違うが、構造は同じだ。
ただし、このサイクルには従来の科学的方法やソフトウェア開発にはない特徴が一つある。各段階に「自由度」と「制御の種類」が明示されている点だ。科学的方法では、研究者が各段階の厳密さを暗黙に判断している。ソフトウェア開発では、チームの規律や文化に依存している。AI駆動のプロジェクトでは、この判断をHarnessの設計として明示的に行う必要がある。なぜなら、AIは人間と違って「空気を読む」ことも「暗黙のルール」を汲み取ることもできないからだ。自由にしていい範囲を明示しなければ自由に振る舞い、制約すべき範囲を明示しなければ制約を守らない。
サイクルが一方向の直線と根本的に異なるのは、評価の後に「どこに戻るか」の判断がある点だ。
出力フォーマットがスキーマに合っていない——これは実装の修正で済む。自由度は低いまま、Hooksの範囲内で直せる。タスクの分割方針が間違っていた——これは仕様の修正が必要で、自由度が中程度に開く。そもそも作りたいものが違った——これは提案書まで遡る必要があり、自由度が最大に戻る。
つまり、「自由度が最大に戻る」のではなく、問題の粒度に応じた自由度に戻る。これがサイクルの核心だ。この「戻り先の判断」も、科学的方法と同じ構造を持っている。実験結果がおかしければ実験手順を見直す。実験計画自体に問題があれば計画を立て直す。仮説そのものが間違っていれば研究課題に立ち戻る。問題の粒度に応じて戻る先が変わるのは、分野を問わず反復サイクルに共通する性質だ。
各段階の自由度が異なるのは構造的な必然による。意図の表明では、コンテキストウィンドウにまだ何も入っていない。制約が少ないほど探索の範囲が広い。何を制約すべきかが分からない段階でHooksやRulesを設定しても意味がない。実装段階では、コンテキストウィンドウに仕様・手順・制約が詰め込まれ、さらにHooksが外側から行動を監視する。AIの「自由な判断」は最小化され、決められた手順に沿って進む。評価段階では、成果物を前にして人間が「これでいいか」を判断する。「良い」「惜しい」「方向性が違う」のような直感的な評価は、構造化できない。
AI駆動開発の肝は、このサイクルの各段階にどう自由度を配置するかだ。全体を通じて同じレベルの制御をかけようとするのは間違いだ。構想段階でガチガチに制約すると探索の幅が狭まるし、実行段階で自由に任せると手順がスキップされる。「今サイクルのどこにいるか」に応じて、適切な制御レベルを選ぶ——これがHarness設計の根本原理であり、以降の各節はこの原理を支える仕組みを述べる。
8.2 意図の文書化 — サイクルの起点
8.1のサイクル図で、最初に来るのは「意図の表明」だ。科学研究では研究計画書がこれにあたる。なぜこの研究をするのか、何を明らかにしたいのか、どのような方法で検証するのか。ソフトウェア開発ではプロジェクト憲章や要件定義書が同じ役割を果たす。いずれも「これから何をするか」を言語化し、関係者の間で共有する文書だ。
AI駆動のプロジェクトでも、意図を文書化する必要がある。ただし、従来の研究計画書や要件定義書にはなかった要素が一つ加わる。AIに委ねてよい範囲——自由度の配置——を明示的に書くことだ。
研究計画書では、研究者自身が実験を行うため、「この判断は研究者に任せる」とわざわざ書く必要がない。要件定義書でも、開発者がどこまで自由に設計してよいかは、チームの経験や暗黙の了解で調整される。しかしAIには暗黙の了解がない。8.1で述べたように、自由にしていい範囲を明示しなければ自由に振る舞い、制約すべき範囲を明示しなければ制約を守らない。だからこそ、意図の文書に「AIが判断してよい範囲」を書く必要がある。
この文書——本稿では提案書(proposal.md)と呼ぶ——は、Harnessのすべてのファイルを生成するための「設計図の設計図」になる。
提案書
│
├── CLAUDE.md を生成する根拠
├── 仕様書のタスク分解を導出する根拠
├── Rules を生成する根拠
├── Skills の手順を導出する根拠
├── Hooks の検証条件を導出する根拠
└── Agents の分割方針を決める根拠
この文書に含めるべき要素は、第3章で述べた対話のインプット4要素と対応する。目的(Why)、文脈(Context)、判断基準(Criteria)、そしてAIに委ねてよい範囲(自由度の配置)だ。
自由度の配置を具体的に書くとはどういうことか。たとえば概念分析なら、「ノードIDの命名規則はAIに任せる」「エッジの5基準スコアの解釈はAIに委ねる」と書く一方で、「YAMLスキーマの構造は変更不可」「ノードのtype体系は7種に固定」と書く。前者が確率的制御に委ねる領域、後者が決定論的制御で守る領域だ。書かなかった項目はAIが勝手に変えるべきではない——この暗黙のルールを文書化することで、確率的制御の精度が上がる。
意図の文書がサイクルの起点である理由は、もう一つある。8.1で述べた「どこに戻るか」の判断で、戻り先の基準になるのがこの文書だからだ。評価段階で「何かがおかしい」と感じたとき、意図の文書と現状を照合すれば、問題が意図レベルなのか、仕様レベルなのか、実装レベルなのかを判定できる。科学研究で実験結果が期待と異なるとき、研究計画書に立ち戻って「仮説が間違っていたのか、実験手順が不適切だったのか」を切り分けるのと同じだ。この文書がなければ、「元々何がしたかったか」がセッションをまたいで失われ、修正のたびに方向がぶれる。
8.3 構造化 — 意図から仕様への変換
8.1のサイクル図で、意図の表明と実装の間に「構造化」がある。提案書を仕様書(spec.md)に変換するステップだ。
科学研究では、これは研究計画書から実験プロトコルを作成するプロセスにあたる。「この仮説を検証したい」という意図を、「どの試薬をどの順序で、どの条件で、何回測定するか」という実行可能な手順に落とし込む。ソフトウェア開発では、要件定義からアーキテクチャ設計や開発計画を導出するプロセスだ。いずれも、抽象的な意図を実行可能な粒度に分解する作業である。
AI駆動のプロジェクトでも同じことが起きるが、一つ大きな違いがある。構造化自体をAIが行える点だ。研究者が自分で実験プロトコルを書き、開発者が自分でアーキテクチャを設計する従来のプロセスと異なり、ここではAIが提案書を読んで仕様書を生成する。これは強力だが、同時にリスクも伴う。AIの「解釈」が入るため、人間が意図したものと異なる仕様が生まれる可能性があるからだ。
提案書には人間の意図が書かれている。「論文3本から概念ネットワークを構築したい」「5基準でエッジを評価する」「チャンクに分割して並列処理する」——目的と方針は明確だが、AIが実行できる粒度にはなっていない。仕様書は、この意図をタスク分解・Phase構成・検証基準に変換した文書だ。
| 提案書(意図) | 仕様書(実行可能な設計) |
|---|---|
| 「概念ネットワークを構築」 | Phase A: 前処理(テキスト抽出・チャンク分割)、Phase B: 構造化(ノード・エッジ抽出、5基準スコアリング)、Phase C: 統合(マージ・検証・可視化) |
| 「5基準でエッジを評価」 | 検証基準: 全エッジにscore_*フィールドが存在すること。Hookの条件: validate_phase.pyが0を返すこと |
| 「チャンクに分割して並列処理」 | Worker A: チャンク1-3を担当、Worker B: チャンク4-6を担当、Lead: Workerの結果をmerge.pyで統合 |
この変換で重要なのは、何をAIの解釈に委ね、何を人間が決めるかが明確になることだ。提案書に「Claude判断可」と書かれた項目——たとえばノードIDの命名規則やPhase内のタスク順序——はAIが決定する。それ以外の項目——成功基準、スキーマ定義、品質の優先順位——は提案書の記述がそのまま仕様書に転写される。科学研究に例えるなら、研究課題と検証すべき仮説は研究者が決め、具体的な試薬の配合や測定の時間間隔は実験担当者の判断に委ねる——この線引きが実験計画書に書かれているのと同じ構造だ。
構造化ステップ自体は確率的制御の範囲内にある。AIが提案書を「解釈」して仕様書を生成するため、同じ提案書を別のセッションで処理すれば、異なるタスク分解が生まれる可能性がある。しかし、提案書で自由度の配置が明示されていれば、揺れは「AIに委ねた範囲」に限定される。提案書の精度が構造化の精度を決める——これが8.2で「設計図の設計図」と呼んだ理由だ。
自由度の観点: 提案書は自由度が最大の状態だ。構造化を経て仕様書になると、自由度の配置が確定する。「どこをAIに任せ、どこを制御するか」が仕様書の中で具体的なPhase・タスク・検証条件として記述される。仕様書が完成した時点で、実装段階のHarness——Rules、Skills、Hooks、Agents定義——を生成するための情報が揃う。
8.1のサイクルで「仕様の修正に戻る」とは、この構造化ステップに戻ることを意味する。タスク分解を変える、Phase構成を組み替える、検証基準を修正する——いずれも仕様書レベルの変更であり、提案書(意図)は変わらない。逆に「提案書の見直しに戻る」は、意図そのものが変わる場合だ。この区別ができるのは、構造化ステップで意図と設計が分離されているからだ。科学研究で「実験手順を変える」のと「仮説を変える」のが質的に異なるように、仕様の修正と意図の修正は戻り先の自由度が異なる。
8.4 外部永続化 — サイクルを維持する仕組み
サイクルを回すには、状態を保持しなければならない。8.1のサイクル図でいえば、「今どの段階にいるか」「何が完了して何が残っているか」「どんな問題が発見されたか」——これらの情報がセッションをまたいで失われたら、サイクルは途切れる。
科学研究では、実験ノートがこの役割を果たしてきた。何を試み、何が起き、何を次に試すべきか。実験ノートが失われれば、研究者は同じ実験をゼロからやり直すしかない。ソフトウェア開発では、バージョン管理システム(git)、課題トラッカー(Issues)、進捗管理ボードが同じ機能を担う。いずれも「サイクルのどこにいるか」を外部に記録し、中断と再開を可能にする仕組みだ。
AI駆動のプロジェクトでは、この外部記録の重要性が格段に高まる。第1章で述べたステートレス性を思い出してほしい。人間の研究者は、昨日の実験の続きを「記憶」に基づいて再開できる。開発チームは、朝のスタンドアップで互いの文脈を共有できる。しかしAIにはセッション間の記憶がない。セッションが終わるとモデルの側には何も残らない。翌日の続きは、外部ファイルに書き出された情報だけが手がかりになる。
メモリ機能では不十分な理由: 第1章で述べたように、AIサービスにはメモリ機能——過去の会話から情報を抽出し、次の会話のコンテキストに注入する仕組み——がある。「それがあるなら、わざわざファイルに書き出す必要はないのでは」と思うかもしれない。しかし、メモリ機能と外部永続化は、性質が根本的に異なる。
メモリ機能はシステムが自動的に管理する確率的な仕組みだ。何を記憶するかはシステムが選別し、次の会話で注入されるかどうかも検索アルゴリズムの判断に依存する。ユーザーは「この情報を確実に覚えておいてくれ」と指示できない。日常的な対話——文体の好み、過去に話した趣味、前回の会話の大まかな流れ——にはこれで十分だ。
外部永続化はユーザーが設計する決定論的な仕組みだ。何を書き出すか、どのファイルにどの形式で書くか、次のセッションで何を読み込むか——すべてをユーザーが明示的に決める。progress.mdに「Phase Bが進行中、現在のタスクはB-2」と書けば、次のセッションでAIはその文字列を確実に読む。メモリの検索結果として注入されるかどうかに賭ける必要がない。
| メモリ機能 | 外部永続化(ファイル) | |
|---|---|---|
| 管理主体 | システム(自動) | ユーザー(設計) |
| 何が保持されるか | システムが選別 | ユーザーが決める |
| 注入の確実性 | 確率的(検索で見つかれば) | 決定論的(ファイルを読めば確実) |
| スコープ | 全会話を横断 | プロジェクト固有 |
| 情報の構造 | 断片的な要約 | 構造化されたデータ |
| 適する場面 | 日常的な対話の継続 | プロジェクトの状態管理 |
この対比は、本稿を貫く確率的制御と決定論的制御の区別のもう一つの現れだ。メモリ機能はContext Engineering層の確率的制御に属し、外部永続化は決定論的な仕組みとして機能する。前者で十分な場面と後者が必要な場面を見分けることが、5.6で述べた「困ったら入れる」の判断基準になる。プロジェクトの状態管理でメモリ機能に頼るのは、手順遵守をRulesだけに頼るのと同じ構造の問題だ——「多くの場合はうまくいくが、保証はない」。
反復サイクルを維持するために必要な外部ファイルは、役割で整理できる。
| 役割 | ファイル | 説明 |
|---|---|---|
| 意図の記録 | 提案書 | サイクルの起点。人間が書く |
| 仕様の記録 | 仕様書 | 提案書から構造化。AIが生成し、人間が承認する |
| 進捗の記録 | 進捗ファイル | 今どこにいるか。AIが更新する |
| 問題の記録 | 課題管理 | 評価で発見された問題。「どこに戻るか」の判断材料 |
科学研究の実験ノートとの違いは、これらのファイルがAIによって読み書きされることを前提に設計されている点だ。実験ノートは人間が読むために書かれる。走り書きでも、図でも、矢印でも、本人が分かれば機能する。しかしAIが読む外部ファイルは、構造化されている必要がある。進捗ファイルには「Phase Aが完了、Phase Bが進行中、現在のタスクはB-2」のように、AIが状態を一意に判定できる形式で記録する。課題管理には、問題の重要度と対処方針が構造化された形で蓄積される。
これらのファイルがサイクルの「記憶」として機能する。新しいセッションを開始するとき、AIはまず進捗ファイルを読んで「サイクルのどこにいるか」を把握し、次に仕様書を読んで「何をすべきか」を理解し、課題管理を読んで「何が問題だったか」を確認する。こうしてセッションが途切れても、サイクルは途切れない。
重要な時点で書き出す: 対話の中で重要な結論や判断が出たら、その時点でファイルに書き出す。auto-compactは会話が長くなると発動するため、「後でまとめて書き出そう」は危険だ。これは習慣ではなく仕組みとして設計する——Stop Hookで「進捗が記録されていなければ完了を拒否する」といったゲートを設けることで、書き出し忘れを防げる。科学研究でも「実験ノートをつけ忘れた実験は、やっていないのと同じ」と言われる。AI駆動のプロジェクトでは、Hooksがこの規律をシステムとして強制する。
8.5 Satisficing — サイクルの出口
8.1で述べたサイクルには、出口が一つある。「閾値を満たした → 完了」だ。しかし、この出口の設計は見た目ほど簡単ではない。
「いつ終わりにするか」は、サイクルを回すあらゆる営みに共通する問題だ。科学研究では、仮説の検証にどこまで実験を重ねるかに明確な終わりはない。追加の実験をすれば新しい知見が得られるかもしれないが、論文を書くためにはどこかで「この検証で十分だ」と判断する必要がある。ソフトウェア開発でも同様で、レビューで「もう少し改善できる」と感じても、次のフェーズに進む判断をする。完璧を待っていたらリリースは永遠に来ない。
AI駆動のプロジェクトでは、この問題がさらに先鋭化する。AIに「もっと良くして」と言えば、AIは何かを変更してくれる。変更が本当に改善かどうかは別として。人間同士の開発では、チームメンバーが「これ以上やっても変わらない」と判断して手を止める。研究者は経験から「この精度で十分だ」と見切りをつける。しかしAIはそのような判断をしない。指示がある限り修正を続ける。
この問題に対する答えは、satisficing(満足化)だ。経済学者Herbert Simonが提唱した概念で、「最適解ではなく、十分に良い解を受け入れる」という意思決定原理である。科学研究では、統計的有意差が得られたら追加実験を打ち切るのがsatisficingの一例だ。ソフトウェア開発では、全テストが通りユーザー受入テストを通過したらリリースする——コードの美しさは次のサイクルに回す。
AI駆動のプロジェクトでは、このsatisficingの基準を提案書の段階で設計し、Hooksで強制することができる。これが従来の研究やソフトウェア開発にはなかったAI固有の利点だ。研究者のsatisficingは暗黙の経験則に依存し、ソフトウェア開発のリリース判断はチームの合意に依存する。どちらも属人的だ。AI駆動のプロジェクトでは、「致命的バグが0かつ重要バグが2以下なら完了を許可」「レビュー回数が3回を超えたら人間に判断を委ねる」のような条件をスクリプトで実装し、Stop Hookに組み込める。閾値自体は人間が設計し(確率的制御では定義できない判断)、遵守はHooksが保証する(決定論的制御)。科学研究で統計的検定の有意水準を事前に決めておくのと同じ構造だ——基準は研究者が決め、判定は計算が行う。
なぜ収束しないか: AIによるレビュー→修正ループが収束しない理由は構造的だ。各レビューで「改善点」が見つかるが、修正すると別の箇所に影響が出る。新たなレビューで別の「改善点」が見つかる。各ステップは確率的に正しいが、全体としては振動する——これは8.1の「どこに戻るか」の判断が、毎回異なるレビュー結果に基づいて異なる場所に戻るために起きる。科学研究でも、実験条件を一つ変えると別の変数が動き、それを制御するためにさらに条件を変え…というループに陥ることがある。違いは、人間の研究者は「これは収束しない」と気づいて戦略を変えられるが、AIはそのメタ判断ができない点だ。だからこそ、外部からの停止条件が必要になる。
satisficingは8.1のサイクルと組み合わせて初めて機能する。サイクルがなければ「いつ終わるか」の問題自体が生じない。サイクルがあってもsatisficingがなければ、ループが永遠に続く。両者はセットだ。
#### 5つの原理の連動
8.1〜8.5を振り返ると、5つの原理は独立した話ではなく、サイクルの各段階で生じる構造的な問題への対処として連動している。
| サイクルの段階 | 構造的な問題 | 対処する原理 |
|---|---|---|
| サイクル全体 | AIにどこまで任せるか | 自由度の配置(8.1) |
| 起点 | 何をしたいかが言語化されていない | 意図の文書化(8.2) |
| 意図→実装の間 | 意図が実行可能な粒度になっていない | 構造化(8.3) |
| セッションをまたぐ | 状態が失われてサイクルが途切れる | 外部永続化(8.4) |
| 出口 | 改善の余地がある限り止まらない | Satisficing(8.5) |
この表を逆に読むと、新しいプロジェクトで何を設計すべきかが分かる。「セッションをまたぐか」を問えば外部永続化の要否が決まり、「AIに委ねる範囲が広いか」を問えば自由度の配置の設計に力を入れるべきかが分かる。すべてを均等に設計する必要はない——プロジェクトの性質に応じて、重点的に設計すべき原理が異なる。
8.6では、この5つの原理が3本の論文の実践でどのように機能するかを体験する。
実用上のポイント(原理): 5つの原理に「これを最初に設計せよ」という固定的な優先順位はない。プロジェクトの性質——タスクの複雑さ、セッションをまたぐか、AIに委ねる範囲の広さ——に応じて、重点的に設計すべき原理が変わる。上の表の「構造的な問題」列を自分のプロジェクトに当てはめて、該当するものから着手すればよい。停止条件(satisficing)もまた、最初から完璧に設計できるものではない。サイクルを回す中で「何が十分か」の基準が見えてくる——8.6のサイクル3で一度完了と判断し、構造的な問題に気づいてサイクル4に戻った事例がそれを示している。重要なのは、問題が見えたときにこの表を参照して「どの原理に戻るべきか」を判断できることだ。
8.6 実践 — 概念分析を3本の論文に拡張する
ここまでの原理を、第7章の課題を拡張して実践する。
第7章では論文1本の概念構造化をCLAUDE.md 6行で始め、4段階で馬具を装着した。本節では同じ概念分析を論文3本に拡張する。データ量が増えることで、第7章では不要だった仕組み——提案書、構造化、Agents、外部永続化——が必要になる過程を体験する。
#### 基盤構造
題材は生命の起源に関する3本の論文だ。Gianni et al. (2026) のQT45リボザイムによるRNA自己複製、Moody et al. (2024) のLUCAのゲノム再構成、Yarus et al. (2009) の遺伝暗号の起源。これらから概念ネットワークを個別に抽出し、統合された1つのネットワークにまとめる。3本の論文はいずれも「生命の起源」に関わるが、扱う対象は異なる。Gianniは分子レベルのRNA触媒反応を、Moodyはゲノムレベルの祖先型生物を、Yarusは情報システムとしての遺伝暗号の起源を扱う。それぞれの概念世界を独立に構造化し、共通する概念(RNAワールド、プレバイオティック化学など)を接点として統合する。
1本なら1セッションで済んだ。3本になると、第7章では起きなかった問題が構造的に生じる。第一に、3本分の論文テキストと出力YAMLをすべて1つのコンテキストウィンドウに収めるのは困難であり、処理を分割する必要がある。第二に、分割された処理の間で命名規則やスキーマを統一する仕組みがなければ、統合時に破綻する。第三に、処理が複数セッションにまたがるため、「前回どこまで進んだか」を外部に記録しなければならない。第四に、統合された結果が品質基準を満たしているかを検証する手段が必要になる。これらの問題は、8.1〜8.5で述べた原理——反復サイクル、意図の文書化、構造化、外部永続化、satisficing——がなぜ必要かを具体的に示している。
Worker 3体が独立に処理し、結果をマージし、品質を検証する——この一連の流れを再現可能にするために、以下のファイル群がプロジェクトの骨格を形成する。
この図の構造は、第3章で述べたHarnessの二重構造——確率的制御と決定論的制御の組み合わせ——をそのまま反映している。上段の/setupは提案書(自然言語)から仕様書やWorker定義(自然言語)を生成する確率的制御の層であり、下段の/executeではStop Hook(決定論的)とvalidate_phase.py(決定論的)がWorkerの出力(確率的)を監視・検証する。図の左側(proposal.md → spec.md → worker_*.md)は意図が段階的に具体化する流れであり、右側(validate_phase.py → issues.md)は品質が遡及的に検証される流れだ。
流れは2段階ある。
第1段階(/setup): 提案書を起点に、プロジェクトに必要なファイル一式を自動生成する。提案書の成功基準(A3)からspec.mdの検証テーブルが導出され、エージェント構成(D4)からWorker定義が生成され、検証方法(D5)からvalidate_phase.pyのチェック項目が決まる。提案書の1箇所を変更して/setupを再実行すれば、これらのファイルが一貫して更新される。この性質が反復サイクルを支えている——サイクルのたびにファイルを手動で整合させる必要がない。8.3(構造化)で述べた「意図から仕様への変換」の実装がこの/setupであり、提案書と仕様書の分離を機械的に維持する仕組みだ。
第2段階(/execute): 生成されたファイル群を使って実際に処理を実行する。Leadがspec.mdを読み、Worker 3体にPhaseを割り当てる。Worker 3体が並列に論文を読み、個別YAMLを生成する(Phase 1〜3)。Leadがmerge.pyで統合し、論文間エッジを追加する(Phase 4)。validate_phase.pyが出力を検証し、問題があればissues.mdに自動記録する。この間、Stop Hookがprogress.mdの更新とgit commitを監視し、違反があれば実行を差し戻す。/executeの1回の実行が8.1のサイクル図における「実装→評価」に対応し、問題が見つかれば提案書に戻って修正する——これがサイクル1〜4の反復を駆動する。
基盤構造の実ファイル: setup.md / execute.md / Stop Hook設定 / 説明
以下、各ファイルの役割を述べる。
CLAUDE.md — プロジェクトの概要とファイル構成を記述する。第7章の段階1ではこのファイル6行だけで概念分析を開始した。3本に拡張した本プロジェクトでは、CLAUDE.mdの役割はセッション開始時のナビゲーションに限定される。プロジェクトの目的を1〜2行で示し、proposal.md・docs/spec.md・docs/progress.mdへの参照を記載する。行動規則や手順はCLAUDE.mdには書かず、RulesとSkillsに分離する。6.2で述べた「何を書かないか」の原則がここでも適用されている。
Skills(.claude/commands/setup.md, execute.md) — /setupと/executeの実体ファイルであり、6.4で述べたワークフロー定義にあたる。setup.mdは「proposal.mdを読み、仕様書・Worker定義・検証スクリプトを生成する」手順を、execute.mdは「spec.mdを読み、Worker割り当て→並列実行→マージ→検証の流れを実行する」手順を定義する。呼び出されたときだけコンテキストに注入される点がCLAUDE.mdやRulesと異なる。手順の記述は自然言語であり確率的制御だが、Stop Hookと組み合わせることで「手順をスキップしたら差し戻す」という決定論的保証が加わる——6.4で述べた「確率的制御が決定論的制御を呼び出す」構造だ。
Rules(.claude/rules/) — 第7章の段階2で導入した確率的制御の層。プロジェクト全体に適用される行動規則を記述する。本プロジェクトでは、ファイル整理規則(output/の命名規則、ログの書式)、問題発生時の対処手順(issues.mdへの記録フォーマット)、ワークフロー規則(Phase完了条件、レビュー手順)の3ファイルを/setupが生成する。CLAUDE.mdやSkillsと異なり、Rulesはセッション全体を通じて常時読み込まれる。
提案書(proposal.md) — プロジェクトの意図を記録するファイルであり、反復サイクルの起点になる。セクションA〜Fで構成され、前半(A〜C)がプロジェクトの「何を」を、後半(D〜F)が「どうやって」を記述する。Aでは成功基準を定義する——本プロジェクトでは「3本すべてのYAMLがスキーマ準拠」「統合YAMLに3本すべてのDOIが含まれる」など4項目を設定した。Bではデータの扱い方を決める。収束条件(いつ「十分」とみなすか)と表記ルール(ノードIDの命名規則など)がここに入る。Cでは概念ネットワークのスキーマ——ノードの粒度、エッジの種類、許可リスト——を定義する。Dでは実装の具体的な設計を記述する。Phase構成(論文ごとにWorkerを分離する)、エージェント構成(Worker 3体 + Lead)、検証方法(validate_phase.pyのチェック項目)がここに含まれる。Eには過去の経験と設計判断の理由を記録し、Fにはペルソナレビューの定義を置く(本プロジェクトでは未使用)。
v1.0の時点では、いくつかの項目を意図的に、あるいは気づかずに空白のまま残した。B5(表記ルール)にはノードIDの命名規則を書かなかった。B3(収束条件)は「論文間エッジが1本以上」と緩く設定した。D5(検証方法)は構造的整合性の10項目に限定し、論文間接続のチェックは含めなかった。これらの不足は、サイクルを回して初めて問題として現れる——サイクル1では命名の揺れとして、サイクル2では接続密度の低さとして、サイクル3では数値基準の甘い評価として。提案書が「最初から完璧であること」ではなく「問題が見えたときにどのセクションに戻るべきかが明確であること」に価値がある理由は、ここにある。変更履歴がv1.0→v1.1→v1.2→v1.3と積み重なることで、4サイクルの判断の軌跡が1つのファイルに残る。
仕様書(docs/spec.md) — 提案書から導出された技術仕様であり、/executeが実際に参照するファイルだ。提案書が「何をしたいか」を記述するのに対し、仕様書は「どう作るか」を記述する。提案書のA3(成功基準)は仕様書の検証テーブルに、B5(表記ルール)はスキーマ定義と命名規則セクションに、D4(エージェント構成)はエージェント定義テーブルに変換される。/setupがこの変換を行うため、提案書を修正して/setupを再実行すれば、仕様書は自動的に提案書と整合する。サイクル2で提案書B5にseed listを追加したとき、/setupは仕様書にseed listセクションを新設し、各Worker定義に論文別のseed list使用指示を生成した。提案書の1箇所の変更が、仕様書を介して複数のファイルに一貫して波及した例だ。
仕様書にはバージョン履歴がある。v1.0(初期実装)、v1.1(seed list追加)、v1.2(収束条件強化・seed list厳格化)、v1.3(定量的基準のスクリプト検証追加)。この履歴は提案書の変更履歴と対応しており、「どの変更がどこに影響したか」を追跡できる。8.3で述べた「意図と設計の分離」が具体的にどう機能するかは、この2つのファイルの対応関係に現れている。
Worker定義(.claude/agents/worker_*.md) — 各Workerへの指示書。worker_gianni.md、worker_moody.md、worker_yarus.mdの3ファイルが/setupで生成される。中身は論文の割り当て、スキーマ、命名規則、seed listであり、提案書のD4(エージェント構成)とB5(表記ルール)がWorkerが読める形に変換されたものだ。各Workerは独立したセッション(コンテキストウィンドウ)で動作するため、Worker間で暗黙の慣習を共有する手段がない。サイクル1で命名の揺れが起きたのはこの独立性のためであり、サイクル2でseed listを提案書に追加したとき、/setupが3体のWorker定義すべてにseed listを注入することで解決された。Worker定義の中身は自然言語であり、確率的制御だ——Workerがseed listを「使うべき」と理解しても「使わないこともありうる」のは、サイクル2の「言及があれば使用」の事例が示している。
検証スクリプト(scripts/validate_phase.py) — 出力の品質を数値で判定する決定論的制御の実装。v1.0では構造的整合性の10項目(スキーマ準拠9項目 + DOI存在1項目)を検査する。YAMLの構文エラー、必須フィールドの欠落、エッジのsource/targetが存在するノードを指しているか——これらは人間が目視で確認するには煩雑だが、スクリプトなら確実に検出できる。サイクル4で論文間接続チェック2項目が追加され全12項目になるが、この追加がもたらした質的変化はサイクル3→4の比較で詳述する。--finalフラグで全項目を実行し、失敗時はexit code 1を返してissues.mdに自動記録する。
マージスクリプト(scripts/merge.py) — 3本の個別YAMLを1つの統合YAMLにまとめる。マッチング方式はexact-match(ノードIDの完全一致)であり、ファジーマッチは意図的に入れていない。ファジーマッチを入れると、マッチングの精度がスクリプトの実装に依存し、なぜその2つのノードが同一と判定されたかの説明が困難になる。命名の統一は下流(スクリプト)ではなく上流(提案書のseed list)で対処する——この設計判断はサイクル1の教訓から導かれたものだ。Leadはmerge.py実行後に、共有ノードを接点とする論文間エッジを手動で追加する。
Stop Hook(.claude/settings.json) — /execute実行中に2つの条件を監視する決定論的制御の仕組み。第一に、各Phase完了時にprogress.mdが更新されているか。第二に、git commitが行われているか。違反を検出したら実行を差し戻し、Leadに修正を求める。サイクル3では、worker_moodyがまだ処理中のタイミングでLeadがPhase 4(マージ)に進もうとした。Hookが「Worker agents are still running」と検出して差し戻した。確率的制御(Leadの判断)では見落とされる問題を、決定論的制御が確実に捕捉した例だ。8.4(外部永続化)で述べた「ステートレス性への対処」を強制する装置である。
進捗管理(docs/progress.md) — 現在のPhase、タスクの完了状況、検証結果を記録する。Stop Hookがこのファイルの更新を強制するため、「書き忘れ」が構造的に排除される。セッションが途中で切断された場合、次のセッションはprogress.mdを読むことで「前回どこまで進んだか」を復元できる——ステートレスなLLMにとって、このファイルが外部記憶の役割を果たす。8.1のサイクル図で「評価→問題が実装の範囲内→実装へ戻る」というループが機能するのは、progress.mdが現在地を記録しているからだ。
問題記録(logs/issues.md) — validate_phase.pyが検出した問題を自動記録する。各問題にはAUTO-001のようなIDが採番され、重大度、検出Phase、具体的な数値(「孤立ノード率75.0%、基準: 60%以下」)が記録される。issues.mdは問題の「発見」と「対処」を紐づける仕組みであり、サイクルをまたいで「何が問題で、どう対処したか」を追跡可能にする。この仕組みがサイクル4でどう機能したかは後述する。
これらのファイルの実物は、すべてexamples/chapter8/で閲覧できる。特に提案書の変更履歴(v1.0→v1.3)は、4サイクルの判断の記録そのものだ。各サイクルの実行結果と分析はsnapshots/に保存されている。
#### サイクル1 — 命名規則がないと何が起きるか
提案書v1.0で/setupと/executeを実行した結果、62ノード・71エッジの統合ネットワークが得られた。validate_phase.pyの9項目チェックはすべて通過しており、構造的には正しい。しかし3本の論文から抽出した63ノードのうち、merge.pyのexact-matchで統合されたのはin_vitro_selectionの1件だけだった。GianniとMoodyの間にはexact-matchがゼロである。生命の起源という共通テーマを持つ3本の論文なのに、Workerが独立に抽出したノードにほとんど共通IDが存在しない。
最も象徴的な例がRNAワールドの扱いだ。Gianniを担当したWorkerはrna_world_hypothesis、Yarusを担当したWorkerはrna_worldというIDをつけた。同一の概念に対して、一方は「仮説」を含み他方は含まない。merge.pyはIDの完全一致でマッチングするため、この2つは別概念として素通りした。Leadはマージ時にこの2つの間に「支持関係」エッジを張っている。本来同一であるべきノードが、関係を持つ2つの別概念として統合ネットワークに残った。
原因は明確で、提案書にノードIDの命名規則を記述していなかったことにある。提案書に書かなかった項目はWorkerの自由裁量になる。基盤構造で述べたとおり、各Workerは独立したコンテキストウィンドウで動作し、命名の慣習を共有する手段がない。これは実装の問題ではなく、8.1で述べた「自由度の配置」の問題——Workerに委ねてよい自由度と、提案書で統制すべき自由度の線引きを誤った結果だ。
修正の方針として、merge.pyにファジーマッチを追加するのではなく、提案書に命名規則を追加する方針とした。下流(スクリプト)で吸収するより上流(提案書)で統一する方がシンプルであり、/setupがWorker定義に波及させるためスクリプト変更も不要になる。
提案書v1.1では、B5(表記ルール)にノードID命名規則を追加した。snake_case・英語統一に加えて、3論文にまたがる共通概念6個をseed listとして定義し、全Workerに同一IDの使用を要求した。/setupを再実行すると、seed listがspec.mdとWorker定義3体に一貫して波及した。
#### サイクル2 — 曖昧な指示は確率的にスキップされる
提案書v1.1で再実行した結果、共有ノードが1個から3個に増え、rna_worldはGianniとYarusで同一IDに統一された。サイクル1の命名の揺れは解消されている。しかし統合ネットワーク全体を見ると、60ノード中47ノード(78%)が他論文と一切接続していない。3つの論文はそれぞれ孤立した島を形成し、3個の共有ノードで辛うじてつながっているだけだ。
個別YAMLを調べると、この低い接続密度の主因が特定できる。Moody論文(LUCAのゲノム再構成)がseed listのrna_worldノードを使用していない。LUCAの論文がRNAワールドに言及しないのはドメイン知識として不自然である。seed listを確認すると、rna_worldの該当論文欄には「Gianni, Yarus(Moodyでも言及があれば使用)」と記載されていた。
「言及があれば使用」という文言が問題だった。人間にとっては「使ってほしい」のニュアンスを含むが、Worker_moodyは文字通りに解釈し、必須でないならスキップしてよいと判断した。同様にgenetic_codeも「Yarus(Moodyでも言及があれば使用)」となっていたが、やはりMoody論文には使用されていなかった。
この事例は、確率的制御の精度が指示の明確さに直接依存することを示している。seed listというメカニズム自体はサイクル1の命名問題を解決したが、その運用ルールに曖昧さを残したために、共有ノードの生成が確率的にスキップされた。
提案書v1.2では2箇所を変更した。第一に、seed listでrna_worldの該当論文を「Gianni, Moody, Yarus」に変更し、genetic_codeも「Yarus, Moody」とした。さらに運用ルールとして「該当する論文に名前が挙がっている場合、その論文でノードが登場しないことはありえない」を追加した。第二に、収束条件を「論文間エッジが1本以上」から「各論文ペア間にそれぞれ2本以上」+「孤立ノード率が60%以下」に引き上げた。後者の基準はサイクル3以降で重要な役割を果たすことになる。
#### サイクル3 — 数値基準をLeadの判断に委ねるとどうなるか
提案書v1.2で再実行した結果、seed listの必須化は正しく機能した。Moodyがrna_worldとgenetic_codeを使用し、共有ノードが3個から5個に増え、rna_worldが3論文すべてに存在する中心ハブとなった。Moody-Yarus間は特に改善が著しく、exact-matchがゼロだったペアにgenetic_codeとrna_worldの2つが共有され、論文間エッジが2本から9本に増加した。
実行中に、基盤構造で述べたStop Hookが実際に発動している。worker_moodyが処理中にLeadがPhase 4に進もうとし、Hookが差し戻した。この決定論的制御は正しく機能した。
ここで注目すべきは、同じサイクルの中で起きたもう一つの出来事との対比だ。/executeの完了後、Leadは「収束条件: 全4項目PASS」と報告した。しかし独立に検証すると、孤立ノード率は70%であり、B3条件4の閾値60%を超えている。Leadは条件4を正しく判定できていなかった。
| 制御の種類 | 対象 | 結果 |
|---|---|---|
| 決定論的(Hook) | Worker未完了の検出 | ✅ 差し戻された |
| 確率的(Leadの判断) | B3条件4の孤立ノード率 | ❌ 甘く評価されて通った |
Hookに入れた検査項目は確実に機能し、入れなかった検査項目は甘い評価が通った。この差は偶然ではなく構造的なものだ。
Leadが条件4を正しく判定できなかった原因は、数値基準と検証方法のミスマッチにある。条件4は「他論文と接続のないノードが全体の60%以下」と数値で定義されている。しかしこの判定には、60ノードそれぞれについて他論文との接続を走査し、割合を計算する手順が必要であり、その手順はspec.mdにもWorker定義にも記載されていない。LLMが60ノードの接続状況を暗算で正確に判定するのは困難であり、数値基準を設けたのに検証を確率的制御に委ねたこと自体が設計上の問題だった。
この時点で一度satisficingの判断を行い、「条件4は未達だが改善の方向は正しい(78%→70%)ため完了」とした。しかし「数値基準の確率的評価が甘い」という問題は、このプロジェクト固有ではなく構造的な問題である。satisficingは「問題に気づかないふりをする」ことではない。サイクル4に戻ることにした。
#### サイクル4 — スクリプトに入れたら何が変わったか
サイクル1〜3の修正はすべて提案書への変更だった。サイクル4で初めて、修正の対象が提案書の外に出る——検証スクリプト(validate_phase.py)への数値チェックの追加だ。
提案書v1.3でD5(検証方法)に2項目を追加した。「各論文ペア間に2本以上の論文間エッジが存在すること」と「他論文と接続のないノードが全体の60%以下であること」。/setupを再実行してvalidate_phase.pyに条件11・12が反映されたことを確認し、/executeを走らせた。
Worker 3体の出力とmerge.pyの結果は、サイクル3とほぼ同等の60ノード・67エッジである。ここまでの工程に差はない。差が生じたのは、validate_phase.py --finalの実行時だ。スクリプトが孤立ノード率75%を算出し、閾値60%との比較で❌と判定した。issues.mdに「AUTO-001: 孤立ノード率 75.0%(基準: 60%以下)」が自動記録され、/executeはexit code 1で停止した。
サイクル3では、同程度の品質の出力に対してLeadが「全項目PASS」と報告して完了していた。同じ基準がスクリプト化された途端に、問題が検出された。
Leadはissues.mdのAUTO-001を確認し、論文間エッジの追加による修正を行った。17本のエッジを追加した結果、孤立ノード率は50%に低下し、validate_phase.py --finalの再実行でPASSとなった。
サイクル3とサイクル4の比較が、本節で最も重要な観察だ。
| サイクル3 | サイクル4 | |
|---|---|---|
| B3条件4の検証方法 | Leadの判断(確率的) | validate_phase.py(決定論的) |
| Leadの報告 | 「全項目PASS」(実際は70%で❌) | AUTO-001検出 → 修正 → 再検証でPASS |
| 最終的な孤立率 | 70% | 50% |
| 論文間エッジ | 17 | 28 |
条件は同じだ——同じ提案書の基準(60%以下)、同じWorker出力、同じmerge.py。異なるのは、validate_phase.pyに数値チェックを入れたかどうかだけである。決定論的制御が問題を検出したことで、Leadが実際に修正を行い、ネットワークの品質が実質的に改善された。
サイクル4の実ファイル: 観察記録 / validate_phase.pyの差分 / 統合YAML / 統合ネットワーク可視化
#### 4サイクルの教訓
4回のサイクルを振り返ると、毎回「どこに戻るか」が異なっている。
| サイクル | 問題の焦点 | 戻り先 | 修正対象 |
|---|---|---|---|
| 1→2 | 命名規則がない | 仕様レベル | proposal.md B5 |
| 2→3 | 曖昧な指示がスキップされた | 成功基準 + 仕様 | proposal.md B3, B5 |
| 3→4 | 数値基準がスクリプト化されていない | 実装レベル | validate_phase.py + proposal.md D5 |
| 4→(継続) | 本稿ではここで区切る | — | 実プロジェクトではサイクル継続 |
8.1で述べた「問題の粒度に応じた自由度に戻る」がそのまま現れている。仕様の不備なら提案書に戻り、成功基準の甘さなら基準を強化し、検証の不備ならスクリプトに戻る。
確率的制御と決定論的制御の使い分けについて、4サイクルを通じた観察を整理する。
| 制御の種類 | 対象 | 結果 |
|---|---|---|
| 確率的 | 命名規則(サイクル2で改善) | ✅ 指示を明確にすれば機能する |
| 確率的 | seed listの「言及があれば」(サイクル3で改善) | ✅ 必須化すれば機能する |
| 確率的 | 数値基準の判定(サイクル3で失敗) | ❌ 60ノードの接続状況は暗算できない |
| 決定論的 | Stop Hook(全サイクルで機能) | ✅ 一貫して正しく動作 |
| 決定論的 | validate_phase.py条件12(サイクル4で機能) | ✅ 問題を検出しLeadが修正 |
確率的制御は定性的な判断——「この概念は重要か」「この命名は適切か」——に有効である。指示の明確さに応じて精度が上がることも、サイクル1→2→3で確認された。しかし定量的な判断——「60%以下か」「各ペアに2本以上あるか」——には決定論的制御が必要だ。自由度の配置を設計するとき、「定性的か定量的か」は有効な判断基準になる。
最後に、本稿ではサイクル4で区切ったが、これはデモとしての区切りであり、satisficingの判断ではない。実際のプロジェクトでは、孤立ノード率50%はまだ改善の余地がある。共有ノードの粒度を見直す、seed listを拡充する、5基準スコアの閾値を調整する——サイクルを回すたびに新たな問題が見えてくる。サイクル3で一度完了と判断してサイクル4に再入場したように、satisficingは「二度と戻らない」という決定ではなく、「今の時点でこの問題は十分か」というサイクルごとの判断だ。本当の完了——satisficingの出口——は、プロジェクトの目的と制約の中で決まるものであり、4サイクルという数に意味があるわけではない。
実用上のポイント(実践): 4サイクルから得られた具体的な指針を3つ挙げる。第一に、提案書は最初から完璧でなくてよい——サイクル1で命名規則を書き忘れ、サイクル2で曖昧な指示を残し、サイクル3で検証方法を確率的制御に委ねすぎた。いずれも実行して初めて見えた問題だ。重要なのは問題が見えたときに「どこに戻るか」を判断できる構造があることであり、命名ならB5、基準の甘さならB3、検証の不備ならスクリプトに戻る。第二に、数値で表現した基準は確率的制御に委ねず、スクリプトに入れるべきだ。「60%以下か」をLeadに暗算させてはいけない。第三に、定性的な判断(「この概念は重要か」)は確率的制御に、定量的な判断(「閾値を満たしているか」)は決定論的制御に——この線引きが、自由度の配置を設計するときの実用的な指針になる。
8.7 まとめ
4サイクルを通じて見えたのは、5つの原理は事前に設計するものではなく、サイクルを回す中で段階的に整えていくものだということだ。サイクル1では提案書v1.0だけで始め、命名の問題が見えてから自由度の配置を修正し(v1.1)、接続密度の低さが見えてから収束条件を強化し(v1.2)、数値検証の甘さが見えてからスクリプトを追加した(v1.3)。第7章でCLAUDE.md 6行から始めて4段階で馬具を足していったのと同じ原理が、ここではプロジェクト全体の設計レベルで機能している。
次の第9章では、このHarnessを別のAIツールに移植する。Harnessの設計がモデルやツールの違いによってどのような影響を受けるかを、移植テストを通じて観察する。