第7章 実践 — 論文1本で機能を組み立てる

第6章では、Harnessを構成する個々の機能——CLAUDE.md、Rules、Skills、Hooks、Agents——を個別に解説した。しかし、部品の説明だけでは、実際にどう組み合わせるかは見えてこない。

本章では、一つの課題を題材に、機能をゼロから一つずつ追加していく。各ステップで「何が変わったか」「何がまだ変わらないか」を観察することで、確率的制御と決定論的制御の役割分担を体感する。Agents(タスク分割)は第8章で扱う。

本章で使用するファイル一式は examples/chapter7 に置いてある。各段階のCLAUDE.md、Rules、Skills、Hooks、出力YAMLの実物を参照できる。

7.1 課題の設定

AIに論文を渡して「読んで要約して」と頼めば、流暢な要約が返ってくる。しかしその要約を、どこまで信頼できるだろうか。

重要な概念を見落としているかもしれない。関係を誤解しているかもしれない。論文に書いていないことをもっともらしく付け加えているかもしれない。要約が自然な文章で返ってくる分、どこが正確でどこが怪しいかの判断がつきにくい。これは第3章で述べた「Harness側でできること」の問題だ——AIの出力を検証可能な形にすることで、信頼度を上げられる。

そこで、出力を「自然な文章」ではなく「構造化されたデータ」にする。やりたいことは、マインドマップを描く作業に近い。論文を読んで、キー概念を丸で囲み、概念同士を線で結んで関係を書き込む——多くの人が紙の上でやっている作業だ。ただし、手描きのマインドマップは検索できないし、別の論文のマインドマップと比較するのも難しいし、「重要な概念を描き忘れていないか」を網羅的にチェックするのも困難だ。

AIにこの作業をやらせ、結果を機械可読な形式(YAML)で出力する。YAMLの中では、マインドマップの「丸」はノード、「線」はエッジとして記述される。こうすれば、「この概念は抽出されたか」「この関係は正しいか」「見落としはないか」を一つずつ確認できる。さらにYAMLは機械可読なので、スクリプトで整合性を検証できる——これがHooksによる決定論的制御につながる。

題材には、Gianni et al., Science 2026(QT45リボザイムによるRNA自己複製の実証)という論文を使う。生命の起源に関する論文だが、読者がこの論文の内容を知っている必要はない。むしろ知らない分野だからこそ、AIの出力をそのまま信じるわけにはいかず、構造化と検証の仕組みが必要になる。もっとも、知っている分野であっても、読み飛ばしや思い込みによる誤解は起きる。構造化は「知らない分野を理解する」ためだけでなく、「知っているつもりの分野で見落としを防ぐ」ためにも有効だ。知らない分野の論文を読む——これはAI駆動の作業が最も力を発揮し、かつHarnessの設計が最も効いてくる場面だ。

input/science.adt2760.pdf  →  output/science_adt2760.yaml

出力されるYAMLは、ノード(概念)とエッジ(関係)の一覧だ——マインドマップの機械可読版と思えばよい。この形式にすることで、段階を追って3つの問いに答えられるようになる: フォーマットは安定しているか(段階2: Rules)、抽出の手順は標準化されているか(段階3: Skills)、出力の整合性は保証されているか(段階4: Hooks)。

7.2 段階1 — CLAUDE.mdだけで動かす

この段階の実ファイル: CLAUDE.md / 出力YAML / 観察記録

最小構成から始める。プロジェクトルートに CLAUDE.md を一つ置くだけだ。

# 論文構造化プロジェクト

input/ にある論文PDFを読み、概念ネットワークの構成要素
(ノードとエッジ)を抽出してYAMLファイルに出力する。

## ディレクトリ構成
- input/    — 論文PDF
- output/   — 生成されるYAMLファイル

6行。これだけで、AIに「input/の論文を読んで、概念ネットワークのノードとエッジを抽出してYAMLにして」と指示すれば、それなりの構造化が行われる。

実際に起きたこと: AIは22個のノードと25個のエッジを抽出し、YAMLファイルを生成した。論文の中心概念(QT45リボザイム、RNA World仮説、自己複製サイクル)がきちんと捉えられていた。ドメイン知識を一切与えていないにもかかわらず、だ。

出力されたノードの一部を抜粋する。

nodes:
  - id: qt45
    label: QT45リボザイム
    type: molecule
    description: "QTリボザイムの最適化バリアント(45ヌクレオチド)"

  - id: rna_world
    label: RNAワールド仮説
    type: theory
    description: "触媒能を持つRNA配列が自己複製を駆動するとする仮説"

  - id: self_replication
    label: RNA自己複製
    type: process
    description: "リボザイムが自身の相補鎖と自身の両方を合成する自己複製サイクル"

  - id: fidelity
    label: 合成忠実度
    type: property
    description: "QT45の平均忠実度は92.6%/ヌクレオチド"

  - id: in_vitro_evolution
    label: in vitro進化(SELEX)
    type: method
    description: "ランダム配列プールからリボザイムを選択する手法"

  - id: eutectic_ice
    label: 共晶氷条件
    type: condition
    description: "-7°Cの凍結条件でリボザイム活性を増強"

  - id: fitness_landscape
    label: 適応度ランドスケープ
    type: analysis
    description: "QT45の全変異体の適応度を定量"

  - id: prebiotic_chemistry
    label: プレバイオティック化学
    type: context
    description: "初期地球における非酵素的RNA重合"

  - id: strand_inhibition
    label: 鎖阻害問題
    type: problem
    description: "(+)(-)鎖二本鎖形成による自己複製の障害"

ここで注目してほしいのは type フィールドだ。molecule, theory, process, property, method, condition, analysis, context, problem——9種類もある。しかもこれは定義されたリストから選ばれたのではなく、AIが論文を読みながら自由に命名したものだ。次回実行したら、molecule が substance に、theory が hypothesis に、analysis が evaluation に変わるかもしれない。type体系自体が安定しない。

エッジも見てみよう。

edges:
  - {source: qt45, target: minus_strand_synthesis, label: が触媒}
  - {source: self_replication, target: rna_world, label: を支持}
  - {source: qt45, target: fidelity, label: の性質}
  - {source: in_vitro_evolution, target: three_motifs, label: から発見}
  - {source: qt45, target: class_i_polymerase, label: より遥かに小型}
  - {source: hexamer_substrate, target: strand_inhibition, label: を緩和}
  - {source: qt45, target: fitness_landscape, label: を解析}
  - {source: five_tu, target: class_i_polymerase, label: に属する}

「が触媒」「を支持」「の性質」「から発見」「より遥かに小型」「を緩和」「を解析」「に属する」——すべて日本語動詞句で、統一されたrelation typeの定義がない。「が触媒」と「を緩和」は同じ因果関係の変種かもしれないが、ラベルからは判断できない。同じ関係が次回は異なる表現で書かれる可能性がある。

第三に、IDの命名規則がない。qt45, qt_ribozyme, minus_strand_synthesis, ph_freeze_thaw とsnake_caseではあるが、明示的なルールは何もない。

この時点で得られるもの: CLAUDE.md 6行だけで、論文の主要概念が網羅的に抽出された。これが確率的制御の強みだ——少ない指示でも「だいたいうまくいく」。

この時点で得られないもの: フォーマットの安定性。同じ指示を再度実行したら、ノード数も、type体系も、エッジの構成も変わるだろう。

7.3 段階2 — Rulesを追加する

この段階の実ファイル: Rules / 出力サマリー / 観察記録

段階1で見えた不安定さのうち、フォーマットの問題をRulesで解決する。

# ファイル: .claude/rules/structurize.md

## ノードのルール
- id は snake_case で命名する
- type は以下の7種から選択する。これ以外のtypeは使わない
  - concept: 理論・仮説・抽象概念
  - entity: 分子・物質・具体的な存在
  - process: 反応・変換・プロセス
  - property: 性質・特性・測定値
  - method: 手法・技術・実験手順
  - condition: 環境条件・制約
  - problem: 課題・障害・未解決問題

## エッジのルール
- relation は以下の8種から選択する
  - causes, requires, produces, supports, inhibits,
    contains, compares, derives
- label は不要(relationで関係を表現する)

## YAML出力のルール
- metadata, nodes, edges の3セクションを必ず含める
- description は1〜2文で簡潔に書く
- 日本語で記述する

実際に起きたこと: ノード27個、エッジ30個。重要なのは数字の変化ではなく、形式の安定だ。

段階1で見た9種のtypeが、Rulesの7種にどう変換されたかを対比で見てみよう。

段階1 のtype段階2 のtype
molecule (QT45等)entity
theory (RNA World等)concept
process (自己複製等)process(そのまま)
property (忠実度等)property(そのまま)
method (SELEX等)method(そのまま)
condition (共晶氷)condition(そのまま)
analysis (適応度)method に統合
context (プレバイオ)消滅(ノード自体がなくなるか、conceptに)
problem (鎖阻害)problem(そのまま)

9種のうち4種(process, property, method, condition)はそのまま残った。molecule は entity に、theory は concept に名前が変わった。analysis は method に統合され、context は消えた。AIが7種の定義リストを読み、最も適切なものを選択した結果だ。

エッジの変化はさらに劇的だ。段階1の自由な日本語ラベルが、定義済み8種のrelationにどう対応したか:

段階1 のlabel段階2 のrelation
「が触媒」causes
「を支持」supports
「の性質」contains
「から発見」produces
「より遥かに小型」compares
「を緩和」inhibits
「を解析」supports
「に属する」contains

「が触媒」は causes(AがBを引き起こす)に、「を支持」は supports(AがBを裏付ける)に、「より遥かに小型」は compares(AとBが比較される)に——それぞれ意味的に最も近いrelation typeが選ばれた。label フィールド自体が出力されなくなり、関係の種類は relation フィールドの8択で統一された。

ただし、定義済みの選択肢では論文の関係を表現しきれない場面も生じた。たとえば、QT45がサイズのパラドックスを「解消する」関係は、8種のrelationに適切なものがなく、inhibits(阻害する)で代用された。また、5TUリボザイムがクラスIポリメラーゼ群に「属する」関係は、contains(含む)の方向が逆だが、他に選択肢がなかった。Rulesの選択肢が概念の表現を制約する面もある。

もう一つの重要な観察: エッジの参照整合性を調べると、ribozyme_abundance(リボザイムの存在頻度)というノードが、どのエッジのsource/targetにも参照されていなかった。ノードとして抽出されたが、ネットワーク上で孤立している。この時点では検証の仕組みがないため、この問題は見過ごされた。

Rulesが効いたこと: フォーマットの統一(type 9種→7種、自由ラベル→定義済み8種のrelation)。

Rulesが効かなかったこと: 何を抽出するか、どの順序で抽出するか。ノード数が段階1の22から段階2の27に変わったのは、Rulesの追加とは無関係な確率的揺れだ。Rulesはフォーマットを固定するが、内容は固定しない。

そして最も重要なこと: 今回はRulesが100%遵守された。しかし、これは保証された結果ではない。Rulesは確率的制御であり、AIが「このノードは7種のどれにも当てはまらない」と判断すれば、Rules外のtypeを生成する可能性は残る。確率を上げるが、保証はしない——この違いが段階4で重要になる。

7.4 段階3 — Skillsで手順を標準化する

この段階の実ファイル: SKILL.md / 観察記録

段階2まででフォーマットは安定したが、「何を、どの順序で抽出するか」はAI任せだ。Skillsで手順を明示化する。

# ファイル: .claude/skills/structurize/SKILL.md

---
name: structurize
description: 論文PDFからノードとエッジを抽出してYAMLに出力する
---

# 論文構造化スキル

**手順を飛ばさず、順番通りに実行すること。**

## 手順

### Step 1: 論文の概要把握
論文の主張・手法・結果・意義を特定する。
結果をYAMLファイルのコメントに記録してから次に進む。

### Step 2: ノード候補の抽出
以下の優先順で探す:
1. 論文の中心対象
2. 直接の関連要素
3. 比較対象
4. 理論的枠組み
5. 課題・障害

### Step 3: エッジの特定
因果→依存→支持→阻害→構成→比較→派生の観点で探す。

### Step 4: 整合性の自己チェック
- 全エッジのsource/targetがnodesのIDに存在するか
- 孤立ノードがないか。あれば削除するか、エッジを追加する
- 重複エッジがないか

### Step 5: YAML出力

Skillには5つの手順を明記した。特に注目すべきは二つ: 手順1の「概要把握をYAMLコメントに記録してから次に進む」と、手順4の「孤立ノードがあれば削除するかエッジを追加する」だ。前者は段階1・2では存在しなかった新しい出力要件、後者は段階2で発見された孤立ノード ribozyme_abundance の問題への直接的な対策である。

実際に起きたこと: Skillは自動発動した。Claude Codeがタスク内容(「論文を構造化してYAMLにして」)とSkillのdescription(「論文PDFからノードとエッジを抽出してYAMLに出力する」)をマッチングし、SKILL.mdを読み込んで手順に従った。明示的に「structurize skillを使って」と指示する必要はなかった。

しかし、出力は段階2とほぼ同一だった。

段階2段階3
ノード数2727
エッジ数3030
type分布同一同一
relation分布同一同一

同じ27個のノード、同じ30個のエッジ、同じ7種のtype分布、同じ8種のrelation分布。Skillsが手順を定義したが、出力の内容自体には変化が見られなかった。

Skillsの効果が見えにくかった理由: 同じモデルが同じ論文を読んでいるので、手順を定義しても抽出される概念は概ね収束する。Skillsの本来の効果は再現性——同じ手順が繰り返し適用されること——であり、「複数の論文に同じ手順を適用する」場面(第8章)で威力を発揮する。1本の論文に対して1回実行するだけでは、効果が見えにくい。

そして最も注目すべき観察: Skillに明記した5つの手順のうち、少なくとも二つがスキップされた。

スキップ1: 概要把握の記録

Skillの手順1に「結果をYAMLファイルのコメントに記録してから次に進む」と書いた。しかし、出力されたYAMLファイルの冒頭はこうなっていた:

# 概念ネットワーク: A small polymerase ribozyme...
# Gianni et al., Science (2026) DOI: 10.1126/science.adt2760

metadata:
  title: "A small polymerase ribozyme..."

段階2の出力と同じだ。「## 概要把握」セクションはどこにもない。「記録してから次に進む」という指示は無視された。

スキップ2: 孤立ノードの修正

Skillの手順4に「孤立ノードがないか。あれば削除するか、エッジを追加する」と書いた。しかし、段階2で発見された孤立ノード ribozyme_abundance は、段階3でも依然として孤立していた:

nodes:
  - id: ribozyme_abundance
    label: リボザイムモチーフの存在頻度
    type: property
    description: "QTリボザイムの配列空間における存在頻度は9.5×10^-17と推定"

edges:
  # ribozyme_abundance をsourceまたはtargetとするエッジ: 0件

ノードは存在するが、30個のエッジのどこからも参照されていない。Skillに「確認して修正する」と明記したにもかかわらず、この検証は実行されなかった——あるいは実行されたが、孤立ノードの検出に失敗した。

一つのSkillの中で、二つの指示がスキップされた。 「手順を飛ばさず順番通りに実行すること」という太字の強調指示があっても、だ。

これが確率的制御の本質的な限界だ。Rulesが「何をするな」(禁止事項)を定義するのに対し、Skillsは「何をどの順序でやれ」(手順)を定義する。しかしどちらも確率的制御の枠内にある。「確認してね」と書いても確認されない。 Skillsは手順を定義するが、その手順の実行を保証しない。段階2のRulesが「今回はたまたま100%遵守された」のと同様に、Skillsも「今回はたまたま一部がスキップされた」——どちらも確率的な結果だ。

7.5 段階4 — Hooksで手順遵守を保証する

この段階の実ファイル: 検証スクリプト / Hooks設定 / 観察記録

ここで初めて、確率的制御の外に出る。

段階2でRulesに書いた「typeは7種から選択する」「relationは8種から選択する」は、今回はたまたま100%遵守された。段階3でSkillに書いた「孤立ノードを修正する」「概要把握を記録する」は無視された。どちらも確率的制御であり、遵守されるかどうかはAIの判断に委ねられている。

Hooksはこの構造を根本的に変える。AIの判断ではなく、コードの実行によって条件を検証する。

// ファイル: .claude/settings.json
{
  "hooks": {
    "Stop": [
      {
        "matcher": "",
        "hook": {
          "type": "command",
          "command": "bash scripts/validate_yaml.sh"
        }
      }
    ]
  }
}

Stop hookは、AIが「完了」と判断したタイミングで自動的に発動する。AIがこのhookをスキップすることはできない——hookの実行はモデルの外側で行われるからだ。

検証スクリプト scripts/validate_yaml.sh の核心部分を抜粋する:

#!/bin/bash
errors=""

# ノードIDの一覧を取得
node_ids=$(grep "^  - id:" "$yaml_file" | sed 's/^  - id: //')

# エッジのsource/targetを取得
sources=$(grep "    source:" "$yaml_file" | sed 's/.*source: //')
targets=$(grep "    target:" "$yaml_file" | sed 's/.*target: //')

# エッジのsource/targetがnodesのIDに存在するか
for src in $sources; do
  if ! echo "$node_ids" | grep -q "^${src}$"; then
    errors="${errors}エッジのsource '${src}' がnodesに存在しません。\n"
  fi
done

# 孤立ノードの検出
all_refs=$(echo -e "${sources}\n${targets}" | sort -u)
for nid in $node_ids; do
  if ! echo "$all_refs" | grep -q "^${nid}$"; then
    errors="${errors}ノード '${nid}' はどのエッジからも参照されていません。\n"
  fi
done

# typeが許可リストに含まれるか
allowed_types="concept entity process property method condition problem"
for t in $types; do
  if ! echo "$allowed_types" | grep -qw "$t"; then
    errors="${errors}許可されていないtype '${t}' が使用されています。\n"
  fi
done

# 結果判定
if [ -n "$errors" ]; then
  echo "BLOCKED"
  echo -e "$errors"
  exit 1  # ← 完了をブロック
fi
exit 0    # ← 完了を許可

ポイントは exit 1exit 0 だ。スクリプトが exit 1 を返すと、Claude Codeはタスクの完了を許可せず、AIにエラー内容をフィードバックする。AIはエラーを読み、問題を修正し、再度完了を試みる。修正後に再びスクリプトが走り、今度は exit 0 が返って初めてタスクが完了する。

全チェック項目は以下の9つ:

1. output/にYAMLファイルが存在するか

2. nodesセクションが存在するか

3. edgesセクションが存在するか

4. ノードが1個以上あるか

5. エッジが1個以上あるか

6. 全エッジのsource/targetがnodesのIDに存在するか(参照整合性)

7. 孤立ノード(どのエッジからも参照されないノード)がないか

8. typeが許可リスト7種に含まれるか

9. relationが許可リスト8種に含まれるか

項目6〜7は段階3でSkillに「確認してね」と書いて無視された検証そのものだ。項目8〜9は段階2でRulesに書いて「今回はたまたま守られた」制約だ。これらすべてが、テキスト指示ではなくコード実行によって保証される。

実際に起きたこと: ノード28個、エッジ32個。全9項目合格。

段階1〜3からの変化を具体的に見よう。

まず、段階2・段階3で孤立していた ribozyme_abundance が修正された。段階3の出力では:

nodes:
  - id: ribozyme_abundance
    label: リボザイムモチーフの存在頻度
    type: property
    description: "QTリボザイムの配列空間における存在頻度は9.5×10^-17と推定"

edges:
  # ribozyme_abundance をsourceまたはtargetとするエッジ: 0件

段階4の出力では:

nodes:
  - id: ribozyme_abundance
    label: リボザイムモチーフの存在頻度
    type: property
    description: "QTリボザイムの配列空間における存在頻度は9.5×10^-17と推定"

edges:
  - source: qt45_ribozyme
    target: ribozyme_abundance
    relation: supports
    description: >
      QT45の発見がRNA配列空間におけるポリメラーゼモチーフの
      存在頻度が従来想定より高いことを示唆

新しいエッジが追加された。検証スクリプトが「ノード ribozyme_abundance はどのエッジからも参照されていません」とブロックした。AIはこれを受けて qt45_ribozyme → ribozyme_abundance (supports) というエッジを追加し、修正した。Skillの手順4では「確認して修正する」と書いても無視されたことが、Hookでは「確認できるまで完了させない」ことで強制された。

次に、段階3で無視されていた「概要把握の記録」が出現した。段階3の出力冒頭:

# 概念ネットワーク: A small polymerase ribozyme...
# Gianni et al., Science (2026) DOI: 10.1126/science.adt2760

metadata:

段階4の出力冒頭:

# 概念ネットワーク: A small polymerase ribozyme...
# Gianni et al., Science (2026) DOI: 10.1126/science.adt2760
#
# ## 概要把握
# - 主要な主張: 45ヌクレオチドの小型RNAポリメラーゼリボザイム(QT45)が
#   自身と相補鎖の両方を合成できる
# - 研究手法: ランダム配列プールからのde novo選択により、トリプレット基質を
#   用いたRNA重合活性を持つ小さなリボザイムモチーフを発見
# - 主要な結果: QT45は共晶氷条件下で相補鎖と自身のコピーを合成可能
# - 理論的意義: ポリメラーゼ活性が小さなRNAモチーフでも実現可能であり、
#   RNAワールド仮説を強く支持

metadata:

Skillの手順1で指示した「概要把握をYAMLコメントに記録する」が、段階4で初めて出力された。ただしこれはHookで直接検証した項目ではない(検証スクリプトの9項目に「概要把握の有無」は含まれていない)。Hookの存在がAI全体の手順遵守の意識を高めた可能性があるが、確率的な効果であり、次回も出力される保証はない。Hookで検証しない項目は、依然として確率的制御の世界にある。

最後に、数値の変化をまとめる:

段階2段階3段階4
ノード数272728 (+1)
エッジ数303032 (+2)
孤立ノード110
概要把握なしなしあり

ノード+1とエッジ+2は、孤立ノード修正のためのエッジ追加(+1)に加え、確率的な揺れの範囲。重要なのは数値の変化ではなく、孤立ノード0件が保証されていることだ。段階2・段階3の「孤立ノード1件」は「たまたまそうだった」結果だが、段階4の「孤立ノード0件」は「検証スクリプトが保証した」結果である。

Hookが保証すること、しないこと

ここで、Hookの限界も明確にしておく。

検証スクリプトが保証するのは構造的な整合性だ。ノードが存在すること、エッジが有効なIDを参照すること、typeとrelationが許可リストに含まれること——これらは grep や文字列比較で機械的に検証できる条件だ。

検証スクリプトが保証しないのは意味的な妥当性だ。「QT45→ribozyme_abundance がsupportsで正しいか」「そもそもribozyme_abundanceをノードにすべきだったか」「もっと重要な概念が見落とされていないか」——これらは機械的には検証できない。意味的な判断は、依然として確率的制御(CLAUDE.md、Rules、Skillsの記述)とモデルの推論能力に委ねられている。

つまり、Harnessの構造はこうなっている:

意味的な判断   → 確率的制御(CLAUDE.md, Rules, Skills)
                  「理解して従う」が、スキップされうる

構造的な検証   → 決定論的制御(Hooks)
                  「コードで検証する」ので、スキップできない

段階2のRulesが「意図を伝え」、段階3のSkillsが「手順を定義し」、段階4のHooksが「条件を検証する」。この三層が噛み合って初めて、「意味を理解した上で、条件を確実に満たす」成果物が生まれる。どれか一つでは不十分だ——Rulesなしでは意図が伝わらず、Skillsなしでは手順が標準化されず、Hooksなしでは整合性が保証されない。

7.6 4ステップの構造

4つのステップを振り返ると、制御の追加は以下のパターンを描いている。

段階追加した制約効果
段階1CLAUDE.md全体像の把握。概ねうまくいくが揺らぐ
段階2+ Rulesフォーマットの固定。精度は上がるが保証なし
段階3+ Skills手順の標準化。指示しても実行が保証されない
段階4+ Hooks決定論的制御の導入。条件の遵守が保証される
観点段階1段階2段階3段階4
ノード数22272728
エッジ数25303032
type体系9種(自由発明)7種(固定)7種(固定)7種(検証済み)
relation体系自由な日本語8種(固定)8種(固定)8種(検証済み)
孤立ノード未確認1件(未検出)1件(修正指示が無視)0件(強制修正)

段階4の出力: 概念ネットワーク可視化

段階4の出力YAMLを可視化すると、7.1で述べた「マインドマップの機械可読版」が実際にどのような図になるかが見える。28個のノードが7色(typeごと)で色分けされ、32本のエッジが関係の種類ごとに色と線種で区別される。中心にはQT45リボザイムが最も多くの接続を持つハブとして位置し、そこからRNA自己複製、RNAワールド仮説、鎖阻害問題といった概念へ放射状にエッジが伸びている。CLAUDE.md 6行から始めて、4段階を経てこのネットワークが得られた。

最初の3段階は確率的制御の世界だ。精度は段階的に上がるが、どこまで行っても「守られない可能性」が残る。段階4で初めて決定論的制御が導入され、質的な変化が起きる。

重要なのは、すべての段階が常に必要なわけではないということだ。論文の概要を把握したいだけなら、段階1で十分かもしれない。出力フォーマットを安定させたいなら段階2まで。手順の再現性が重要なら段階3まで。出力の整合性を保証する必要があるなら段階4まで。タスクの性質に応じて「どこまで馬具を装着するか」を判断する——これが第5章で述べた「確率的制御の柔軟さを活かす場面と、決定論的制御の確実さが必要な場面を見極める」ことの具体化だ。

そして、本章ではAgentsを使わなかった。論文1本の構造化にはこの4ステップで十分だからだ。Agentsが必要になるのは、複数の論文を横断的に比較分析するとき——つまり、タスクの複雑さが増したときだ。タスクが複雑になると、「機能を足す」だけでは対処できない。プロジェクト全体を通じてHarnessをどう設計し運用するかの原理が必要になる。第8章では、研究にも開発にも共通する「反復サイクル」を軸に、その原理を整理する。

実用上のポイント: 新しいタスクを始めるとき、最初からすべての機能を構築しようとしない。段階1(CLAUDE.mdだけ)から始めて、実際に問題が起きたら次の段階を追加する。「フォーマットがばらつく」→ Rulesを追加。「手順が安定しない」→ Skillsを追加。「整合性チェックが無視される」→ Hooksを追加。問題駆動で段階的に馬具を足していく方が、最初から全部揃えるより効率的で、かつ過剰設計を避けられる。