広告

Harness as Code:AIワークフローをインフラとして扱う

Dev.to / 2026/4/1

💬 オピニオンDeveloper Stack & InfrastructureIdeas & Deep AnalysisTools & Practical Usage

要点

  • この記事は、生成されたコードを保存していても、プロセス(プロンプト、反復、判断)が記録されないため、今日のAIによるコーディングセッションは再現が難しいと主張している。
  • それは Infrastructure as Code(IaC)との類似性を示し、チャット主導の対話的手順ではなく、AI支援ワークフローを決定論的なコード成果物として定義する「Harness as Code」を提案する。
  • 提案手法では、場当たり的なプロンプト入力を置き換え、CLI/YAML/スクリプトベースのワークフローとすることで、バージョン管理やレビューが可能になり、AIの判断を監査可能かつ再現可能にする。
  • 具体的な概念実証として著者は、CoDD(Coherence-Driven Development)を構築した。これはMarkdown仕様から、計画→波(ウェーブ)ごとの生成→検証→スプリント単位での実装→組み立て、というパイプラインを通じて設計ドキュメントとコードを作るPython CLIである。
  • パイプラインには「AIの手抜き」を検出するための品質ゲートが含まれており、一般的なコピペ中心のチャットワークフローよりも出力の堅牢性を高めることを狙っている。

私がこれまで行ってきたAIによるコーディングセッションは、いつも同じ流れをたどります。Claude/ChatGPTを開いて、やりたいことを説明し、20分ほど行ったり来たりして、「だいたい動くもの」を手に入れてからタブを閉じます。コードは存在する。でも、それを生んだプロセスは残らない。

明日、そのセッションを再現しようとしてみてください。同僚が使ったプロンプトを見直してみてください。あの一度だけ、AIがうまいコードを出した「雰囲気(vibe)」をバージョン管理しようとしてみてください。

できません。そこが問題です。

IaC Parallel

インフラのデプロイといえば、AWSコンソールでクリックして進めることでしたよね。ロードバランサを設定して、セキュリティグループを用意して、自動スケーリングを微調整する——全部手作業。うまくいっていましたが、「同じやり方で、もう一度できる?」と誰かが聞いてくると、答えはいつも「たぶんね」でした。

そしてTerraformが登場しました。Infrastructure as Code。すべてを.tfファイルで定義し、planを実行して、applyを実行する。再現可能。バージョン管理可能。レビュー可能。コンソールはまだ存在するけれど、真面目なチームは触りません。

AI支援の開発は、いま「コンソールであちこちクリックしている段階」にあります。AIとチャットして、コードをコピペして、人手で手動検証して、繰り返す。それは動きます——でも動かなくなったとき、デバッグするための痕跡がありません。

もしAIのワークフローをコードで定義できたら? CLIコマンド。YAML設定。シェルスクリプト。チャット画面なし。インタラクティブなセッションなし。すべての手順が再現可能で、すべての判断がバージョン管理可能。

私はこれをHarness as Codeと呼んでいます。

CoDD: A Concrete Implementation

私はこのアイデアを検証するためにCoDD(Coherence-Driven Development)を作りました。Markdownの仕様を受け取り、決定論的なパイプラインによってデザインドキュメントとコードを生成するPython製CLIです。

pip install codd-dev

完全なパイプライン:

spec.md (要件をMarkdownで記述)
  → codd init                    # プロジェクト設定をブートストラップ
  → codd plan --init             # AIがドキュメントの依存関係グラフを設計
  → codd generate --wave 1..N   # 波(wave)ごとにデザインドキュメントを生成
  → codd validate                # 品質ゲート:AIの手抜きを検出
  → codd implement --sprint 1..M # デザインドキュメントからコードを生成
  → codd assemble                # フラグメントを統合して動作するプロジェクトにする
  → build                        # 標準のビルド((npm, cargo, etc)

どのステップでもインタラクティブなAIチャットはありません。AIへの呼び出しはすべてclaude --printを通ります。Claude Code CLIの非インタラクティブなSTDIOモードです:

claude --print --model claude-opus-4-6 --tools "" \
  "$(cat prompt.txt)"

プロンプトを投入して、テキストが出てくる。AIを純粋関数として扱う。CoDDの設定内のai_commandが、AIをどう呼び出すかを定義します:

# codd.yaml
ai_command: claude --print --model claude-opus-4-6 --tools ""

claudeを別の任意のCLIに置き換えても、パイプラインは動き続けます。CoDDは、どのLLMを使うかにはこだわりません。重要なのはstdin/stdoutだけです。

What "Coherence-Driven" Actually Means

ほとんどのAIコード生成器は、各プロンプトを独立して扱います。CoDDは、明示的な依存関係グラフによってデザインドキュメントを連鎖させます:

Requirements
  ├→ Acceptance Criteria        (Wave 1)
  ├→ ADR: Technology Stack      (Wave 1)
  │    └→ System Design          (Wave 2, 上記の両方に依存)
  │         ├→ Component Design   (Wave 3)
  │         └→ Task Flows         (Wave 3)
  │              └→ Implementation Plan (Wave 4)

Wave 2のSystem Designを生成するとき、AIにはWave 1の出力の全文がコンテキストとして渡されます。ADRには「static export only」と書いてある → System DesignはReact Server Componentの境界を尊重します。Acceptance Criteriaには「ARIAラベルが必要」と書いてある → Component Designはaria-pressed、フォーカストラップ、キーボードバインディングを指定します。

上流の意思決定が、下流の生成を制約します。これがコヒーレンス(coherence)です。

Real Numbers

Todoアプリ用に、37行の仕様を書きました(Next.js 15、TypeScript strict、ダークテーマ、localStorage):

# TaskFlow — Personal Todo App

## Functional Requirements
- Task CRUD: create, read, update, delete tasks
- 各タスクには:タイトル、説明(任意)、期限日(任意)、
  優先度(low/medium/high)、完了ステータス
- ステータス(all/active/completed)と優先度でフィルタできるタスクリスト
- インラインでのタスク完了トグル(チェックボックス)
- ローカル状態の管理(バックエンドなし、localStorage)

## UI Requirements
- モバイルファーストのレスポンシブレイアウトを備えたシングルページアプリ
- アクセントカラー(#3b82f6)のダークテーマ
- 浮動アクションボタンでモーダルフォームを開く
- 作成/更新/削除時のトースト通知
- キーボードショートカット:送信はEnter、モーダルを閉じるのはEscape

## Constraints
- React Server Components を使う Next.js 15 App Router
- Tailwind CSS
- TypeScript strict モード
- static export としてデプロイ可能

結果:

入力 出力
spec.md(37行) 6つのデザインドキュメント(1,353行)
102のコードファイル(6,445行)
TypeScript strict mode のビルド:エラーなし

生成されたデザインドキュメントには、Mermaid図、RSC境界を含むコンポーネントツリー、状態機械の定義、17スプリントからなる完全な実装計画が含まれており、すべて依存メタデータを通じて仕様書にたどり着けます。

Model Role Separation

ここから面白くなります。--ai-cmdフラグにより、パイプラインの各段階で別々のモデルを割り当てられます:

# デザインドキュメント — 判断が必要なので Opus を使用
codd generate --wave 1 \
  --ai-cmd 'claude --print --model claude-opus-4-6 --tools ""'

返却形式: {"translated": "翻訳されたHTML"}

# コード生成 — ボリュームが必要なので Codex(または Sonnet)を使う codd implement --sprint 1 \ --ai-cmd 'codex --full-auto -q' # 品質チェック — 厳密さが必要なので Opus に戻る codd validate

建築には Opus。実装には Codex。QCには Opus。各モデルは得意分野を生かします。これは何らかの独自のオーケストレーション層ではなく、シェルスクリプトであなたが定義します。

動的パイプライン(マジックナンバーなし)

ウェーブ数やスプリント数は仕様次第です。複雑なアプリなら 8 ウェーブで 40 スプリントかもしれませんし、単純なものなら 3 ウェーブで 5 スプリントかもしれません。CoDD はシェルスクリプト用にこれらの数を返します:

waves=$(codd plan --waves)      # → 4
sprints=$(codd plan --sprints)  # → 17

つまり、完全な自動化スクリプトにはハードコード値がゼロです:

#!/bin/bash
set -e

codd init --requirements spec.md
codd plan --init

waves=$(codd plan --waves)
for wave in $(seq 1 $waves); do
  codd generate --wave $wave
done

codd validate

sprints=$(codd plan --sprints)
for sprint in $(seq 1 $sprints); do
  codd implement --sprint $sprint
done

codd assemble

仕様を変えて、同じスクリプトを実行します。ウェーブ構造もスプリント数も変わるけれど、パイプラインは同じ。この「Harness as Code」の意味はここです——ワークフローはコードで定義され、入力に適応し、人間による調整は不要です。

人間によるチェックポイントの追加

完全自動化は一つのモードです。進める前にレビューしたいこともあります:

#!/bin/bash
set -e

codd init --requirements spec.md
codd plan --init
waves=$(codd plan --waves)

# ウェーブ1を生成してから、人間によるレビューで一時停止
codd generate --wave 1
echo "受け入れ基準とADRを docs/ 内で確認してください"
echo "続行するには Enter、中止するには Ctrl+C"
read

# 残りのウェーブは自動で実行されます
for wave in $(seq 2 $waves); do
  codd generate --wave $wave
done

codd validate

sprints=$(codd plan --sprints)
for sprint in $(seq 1 $sprints); do
  codd implement --sprint $sprint
done

codd assemble

human-in-the-loop は、シェルスクリプト内の read だけです。特別なAPIはありません。Webhookの設定も不要です。標準的な Unix で十分です。

品質ゲート

AIモデルは、できる限り手を抜きます。codd validate が次を検出します:

チェック 理由
TODO/TBD の検出 AI は「TODO: 後で実装する」と書いて先に進む
メタコメントの削除 「以下のセクションで説明します...」— いや、説明しない。空のまま
セクション構造 必須セクション(Overview、Architecture)が存在しなければならない
Mermaid 図 図のない詳細設計は却下される
依存関係の一貫性 depends_on であるフロントマター内の参照が解決される必要がある

検証に失敗するとパイプラインが止まります。修正して再生成するか、ビルドは進みません。これは terraform validate と同じ発想です——問題が伝播する前に検知します。

比較

インタラクティブなAIチャット Harness as Code(CoDD)
再現可能 No Yes — 同じ仕様、同じパイプライン
バージョン管理可能 No Yes — 仕様+設定を git に置ける
レビュー可能 No Yes — 仕様をPRし、差分をレビューできる
モデル切り替え可能 手動 各ステップで --ai-cmd 経由
CI/CD 対応 No Yes — ただのシェルコマンドだから
人間のチェックポイント 常に(あなたが人間) 任意(必要なところで read

学んだこと

仕様の品質がボトルネックです。 Todo アプリの最初の仕様には UI 要件がありませんでした。その結果は機能しているようには見えますが、見た目は醜いものでした。UI 仕様に10行を追加(ダークテーマ、FAB、トースト通知、キーボードショートカット)したところ、出力は大きく変わりました。CoDD は、あなたが書いた内容を忠実に拡張します。あなたが書いていないものは発明しません。

AIの怠けは現実的で、予測可能です。 品質ゲートがないと、生成されたデザインドキュメントの約15〜20%に TODO やプレースホルダのセクションが含まれます。validate ステップがそれらをすべて検出します。

「ウェーブ」という抽象化が重要です。 すべてのデザインドキュメントを一度に生成すると、不整合が生まれます。依存関係の順序で、上流のドキュメントを文脈として生成すると、お互いを正しく参照し合うドキュメントが得られます。

まず試してみる

pip install codd-dev
codd init --requirements spec.md
codd plan --init

リポジトリはこちら:github.com/yohey-w/codd-dev

CoDD はまだ初期段階(v1.1.0、週あたりの PyPI ダウンロードは約900)ですが、パイプラインはエンドツーエンドで動きます。37行の仕様で動く TypeScript アプリを作るのはデモではありません——これは私が実際に使っているワークフローです。

Terraformが「インフラはコードの中にあるべきだ」と教えてくれたのなら、AIワークフローも同様に受け入れる時かもしれません。

あなたのAI開発ワークフローはどのようなものですか?再現可能ですか?

広告