BitOnでは、Claude Code を用いた開発を Spike → Walking Skeleton → Milestone の3段階で進めている。 これは単なる社内ローカルルールではなく、Extreme Programming・Alistair Cockburn のアジャイル設計論・PMBOK / ISO/IEC/IEEE 12207 といった既存の国際標準的な設計手法を、AI支援開発時代に再構成したものだ。
この記事では、3段階それぞれの「目的」「Definition of Done」「Claude Code 上での具体的な構成内容(ディレクトリ・CLAUDE.md・サブエージェント・hooks・MCP)」を、実際に進めているプロジェクト kotonomi(失語症患者向け発話リハビリアプリ)を例にしながら、設計手法レベルで詳述する。「@katsujin」
Claude Code は、自然言語で意図を伝えるだけで、整った構造のコードを大量に生成できる。便利な反面、AI支援開発には構造的なリスクがある。
つまり、AI支援開発で起きる失敗のほとんどは「コードを書く力」ではなく「何を、どの順序で、どの解像度で書くべきか」という設計プロセス側の問題だ。 ここを支えるのが、ソフトウェア工学が長年蓄積してきた古典的な3つの概念 ── Spike・Walking Skeleton・Milestone である。
これらは三者三様の目的を持ち、混同してはいけない。
| 段階 | 主目的 | 出力物 | 捨ててよいか |
|---|---|---|---|
| Spike | 不確実性の偵察(知識獲得) | 知見ドキュメント | 基本捨てる |
| Walking Skeleton | エンド・トゥ・エンドの最小骨格 | 動くがほぼ空っぽのシステム | 捨てない(育てる) |
| Milestone | 検証可能な垂直スライス | 価値を届ける機能増分 | 捨てない(積み上げる) |
「捨てる前提のコード」と「育てるコード」を Claude Code に書き分けさせるには、それぞれを別の構成で運用する必要がある。
それぞれの概念がどこから来て、どの標準と結びついているかを整理しておく。
Extreme Programming で Ward Cunningham が提唱した概念。「不確実性の高い領域に 薄く深く一本の杭(spike)を打ち込み、リスクを定量化する」ためのタイムボックス化された探索。 本質は コードではなく知識を生産すること。実装は捨てる前提で、得られた洞察(性能の上限、ライブラリの制約、データ品質)だけを残す。
関連標準・概念:
Alistair Cockburn が Crystal Clear および Agile Software Development で定式化した概念。 「最小機能で、しかし本物のアーキテクチャを端から端まで貫通したシステム」を最初に作る。
"A Walking Skeleton is a tiny implementation of the system that performs a small end-to-end function. It need not use the final architecture, but it should link together the main architectural components."
UIから永続化層まで、すべての層に一本の細い動脈を通す。Day 1 からCIが緑で、デプロイ可能であることが要件。
関連標準・概念:
PMBOK で定義される、検証可能なプロジェクト到達点。期日ではなく、Definition of Done を満たした成果物で定義される。Scrum の Sprint Goal、SAFe の PI Objectives と同義に扱える。
関連標準・概念:
3つは「直列に並んだ別の作業」ではなく、不確実性を異なる粒度で吸収する三層だと理解するのが正確だ。
不確実性高 ─────────────────────────────────────► 不確実性低
│ │ │
▼ ▼ ▼
Spike Walking Skeleton Milestone
(知識の獲得) (構造の証明) (価値の積み上げ)
Spike が先行する Walking Skeleton も、Milestone のなかで小さく行う Spike も、両方ありうる。重要なのは その瞬間に何を確かめているのか を言語化しておくことだ。Claude Code の各段階の構成は、ここに合わせて変える。
3段階の運用に入る前に、Claude Code 側の道具立てを設計プロセス的に分類しておく。
| 構成要素 | 配置 | 設計的役割 | アナロジー |
|---|---|---|---|
CLAUDE.md |
プロジェクト直下 | 常に真の前提・制約・規約 | 建築の「設計指針書」 |
| Slash Commands | .claude/commands/*.md |
再現可能な手続きの起点 | Makefile ターゲット |
| Skills | .claude/skills/<name>/SKILL.md |
必要時に読み込まれる手順書 | プレイブック |
| Subagents | .claude/agents/*.md |
隔離されたコンテキストの専門家 | マイクロサービス |
| Hooks | settings.json / agent frontmatter |
決定論的ライフサイクル制御 | リーン生産方式の poka-yoke |
| MCP servers | settings.json |
外部ツール・データへの接続 | エンタープライズ統合パターン |
ここで強調したいのは、CLAUDE.md と Hooks は性質が全く違うということだ。CLAUDE.md は「モデルがその内容を理解し従う」前提で動くソフトな規範。Hooks は「モデルがどう解釈しようと、シェルスクリプトが実行されて結果がブロック/通過する」決定論的な統制。前者は規則、後者は反射神経に相当する。
設計プロセスでは、重要な制約ほど Hooks に落とし、揺らがせたくないものは決定論で守る。
技術リスクを最小コストで定量化し、後続の設計判断の根拠を作る。
Spike はリポジトリの本流から 物理的に隔離する。これは XP 由来の「捨てる前提」を構造で担保するためだ。
project-root/
├── CLAUDE.md # 本体用(Spikeとは無関係)
├── src/ # 本体
└── spikes/
└── 2026-05-whisper-lora-dysarthria/
├── CLAUDE.md # Spike専用・軽量
├── RISK_QUESTION.md # 何を確かめるか
├── notebook/
├── data_sample/
└── FINDINGS.md # 知見(成果物)
# Spike: Whisper LoRA fine-tuning for dysarthric speech
## Risk Question
構音障害のある音声 100 サンプルに対し、Whisper large-v3 + LoRA で
- 単語単位 WER を 0.4 以下に下げられるか
- RTX 5060 Ti 16GB VRAM で実用時間内に学習が回るか
## Constraints
- このフォルダ配下のみ。本体 src/ には絶対に触れない
- 試行錯誤・ハードコード・ノートブック化はすべて許容
- 結論が出たら FINDINGS.md に記録し、コードは破棄する想定
## Out of scope
- 本番API化
- データベース設計
- フロントエンド統合
/spike-log で FINDINGS.md に追記)# Findings: Whisper LoRA on dysarthric speech (Spike #2026-05)
## Verdict
**Conditional Yes** — WER 0.32 達成、ただし以下の条件下で。
## Evidence
- Sample size: 100 utterances, 5 speakers
- Best config: LoRA rank=8, target_modules=["q_proj","v_proj"], 3 epochs
- VRAM peak: 13.8 GB / 16 GB
- Wall time: 42 min on RTX 5060 Ti
## Constraints discovered
- 音韻性錯語(phonemic paraphasia)を「修正」してしまう挙動を確認
- → 命名課題の正誤判定を Whisper 単独で行うことは **設計上禁止** とする
## Decision
Walking Skeleton 段階では Whisper 出力に対して
**別途音素レベルの比較器**を挟む構成とする(後段 Milestone で実装)。
ここで生まれた制約「Whisper alone must not judge naming tasks」は、後続の本体 CLAUDE.md の最重要セクションに昇格する。Spike の本当の出力物は動くコードではなく、こうした 設計拘束 だ。
主要アーキテクチャコンポーネントが結線され、CIが緑で、デプロイ可能な、ほぼ空っぽのシステムを作る。 ここで実装する機能はただ一つ ── 「最も細い1本の動線」だ。例えば kotonomi なら「録音 → API → DB保存 → 結果表示」の本当に一往復だけ。
逆に DoDに含めない:
ここから 本体の CLAUDE.md を整える。揺らがせたくない構造を Hooks で守り始める。
project-root/
├── CLAUDE.md
├── .claude/
│ ├── agents/
│ │ └── skeleton-verifier.md
│ ├── commands/
│ │ ├── skeleton-verify.md
│ │ └── walk-through.md
│ ├── specs/
│ │ └── architecture.md # C4 Container 図相当
│ └── settings.json # hooks 定義
├── src/
│ ├── api/ # FastAPI
│ ├── web/ # React/TypeScript
│ ├── infer/ # Whisper ラッパー
│ └── db/ # PostgreSQL モデル
├── tests/
│ └── e2e/
│ └── test_happy_path.py
└── docker-compose.yml
# kotonomi — Speech Rehabilitation App
## Project context
失語症患者の発話リハビリ支援アプリ。病院でのベッドサイド利用を想定。
## Architectural invariants (NEVER VIOLATE)
1. Whisper の出力を命名課題の正誤判定に **単独で** 使ってはならない
→ 音素比較器を経由すること
2. すべての医療データは PostgreSQL に保存し、ファイルシステムに残さない
3. API レイヤーは FastAPI、フロントは React/TypeScript で固定
## Stage indicator
**Current stage: Walking Skeleton**
DoD: docker compose up → happy_path e2e test passes.
新機能は追加しない。骨格の貫通のみ。
## Definition of Done (current stage)
- [ ] `make skeleton-verify` がローカルで緑
- [ ] GitHub Actions の build/test/deploy ジョブが定義済み
- [ ] 自社 Docker レジストリへの push が通る
## Architecture
See `.claude/specs/architecture.md` (C4 Container view).
## Coding standards
- Python: ruff + mypy strict
- TypeScript: tsc strict, biome
- すべて型を書く。`any` 禁止。
.claude/settings.json に lint と test を PostToolUse / Stop に最低限だけ入れる。
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write|MultiEdit",
"hooks": [
{ "type": "command", "command": "./scripts/lint-changed.sh" }
]
}
],
"Stop": [
{
"hooks": [
{ "type": "command", "command": "./scripts/skeleton-verify.sh" }
]
}
]
}
}
skeleton-verify.sh は happy-path e2e テスト1本だけ を実行する。これが「Walking Skeleton が生きている」唯一の証拠であり、ここを保護するのが Hook の役目だ。
---
name: skeleton-verifier
description: Verify that the walking skeleton end-to-end path still works.
Use after any structural change.
tools: Bash, Read
---
You verify that:
1. `docker compose up -d` succeeds
2. The single happy-path test `tests/e2e/test_happy_path.py` passes
3. CI workflow files are syntactically valid
You do NOT add features. You do NOT modify business logic.
If the skeleton is broken, report which layer (UI / API / infer / DB) is the cause.
Walking Skeleton 段階で起きがちな失敗は、「動くMVP」と取り違えることだ。MVPは「市場検証可能な価値を備えた最小製品」、Walking Skeleton は「アーキテクチャの結線が証明された骨格」。前者は機能要件、後者は構造要件で評価する。
Claude Code に「ついでに〇〇機能も入れて」と指示すると Walking Skeleton が崩れる。この段階の Slash Command は意図的に少なく、新機能追加系のコマンドは置かない ことが効く。
.claude/specs/architecture.md になるWalking Skeleton の上に、ユーザー価値を持つ垂直スライスを一つずつ積む。各 Milestone はそれ単独で意味があり、デプロイ可能で、検証可能。
kotonomi なら例えば:
各 Milestone は Spike(必要なら)→ 実装 → DoD 検証、という小さなサイクルを内包する。
.claude/specs/M1-naming-task.md のような Milestone スペックファイルに書く。IEEE 1016(Software Design Description)に準拠したテンプレートを社内標準とすると、複数 Milestone の DoD 品質が安定する。
# Milestone M1: Naming Task with Phonemic Verification
## User-facing goal
セラピストが命名課題を出題でき、患者の音声回答を記録・自動採点できる。
## Architectural decisions (links to ADRs)
- ADR-003: Use phoneme-level comparator after Whisper, not Whisper-only judgment
- ADR-004: Store raw audio in S3-compatible storage, transcripts in PostgreSQL
## Definition of Done
- [ ] セラピストUIから課題を出題できる
- [ ] 患者が録音し、音声がアップロードされる
- [ ] Whisper → 音素比較器 → 採点結果がDBに保存される
- [ ] e2e テスト追加(M0の skeleton path とは別ファイル)
- [ ] 単体テストカバレッジ 70% 以上
- [ ] CHANGELOG.md に追記
- [ ] 自社レジストリにタグ `v0.1.0-m1` で push 成功
## Out of scope
- 複数患者の同時セッション(M5)
- レポート出力(M4)
ここでようやく マルチエージェント運用 に入る。各役割を最小権限で分離する。
.claude/agents/
├── planner.md # 設計フェーズ専用。実装ツールなし
├── implementer.md # コード書き込み可
├── reviewer.md # 読み取り専用、レビュー出力
├── tester.md # テスト実行とテスト追加のみ
└── skeleton-verifier.md # Walking Skeleton 段階から引き継ぎ
例えば planner.md:
---
name: planner
description: Decompose a milestone spec into implementation tasks.
Use BEFORE any code is written.
tools: Read, Grep, Glob
---
You take a milestone spec from .claude/specs/ and produce a task plan.
You produce no code. You produce a numbered list of edits with
- file paths to touch
- expected diff size
- testing strategy per task
You stop after producing the plan. Implementation is the implementer's job.
reviewer.md:
---
name: reviewer
description: Review changes against CLAUDE.md invariants and the active milestone spec.
Use after implementation, before commit.
tools: Read, Grep, Glob, Bash
---
Check each diff against:
1. CLAUDE.md "Architectural invariants" — flag any violation
2. The active spec in .claude/specs/ — flag any DoD item not covered
3. Coding standards — flag type holes, `any`, missing tests
Output a structured report. Do not modify files.
権限分離(tools フィールド)が least-privilege の原則を構造で実現していることに注目してほしい。これは Hooks の PreToolUse で検証することもできるが、エージェント単位で絞るほうがシンプルで監査もしやすい。
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{ "type": "command", "command": "./scripts/guard-dangerous.sh" }
]
}
],
"PostToolUse": [
{
"matcher": "Edit|Write|MultiEdit",
"hooks": [
{ "type": "command", "command": "./scripts/lint-changed.sh" },
{ "type": "command", "command": "./scripts/type-check.sh" }
]
}
],
"Stop": [
{
"hooks": [
{ "type": "command", "command": "./scripts/check-dod.sh" }
]
}
],
"SessionStart": [
{
"hooks": [
{ "type": "command", "command": "./scripts/load-active-spec.sh" }
]
}
]
}
}
ポイントは、Hooks は CLAUDE.md に書かれた規約を機械的に強制する補助線だということ。
たとえば check-dod.sh は、.claude/specs/ 配下の active spec を読んで、未チェックの DoD 項目があれば exit code 2 を返す。Claude Code はセッションを終わらせられない。これがリーン生産方式における poka-yoke(ポカヨケ・誤防止) の精神そのものだ。
Milestone 段階では外部統合の本数が増える。kotonomi の例:
ただし、MCP は 読み取り権限から始める。書き込み可能なMCPは個別の Subagent にのみ渡し、メインセッションには付与しない。これも least-privilege。
.claude/commands/
├── m-start.md # /m-start M1 → spec読み込み・planner起動
├── m-review.md # /m-review → reviewer起動
├── m-ship.md # /m-ship → DoD最終確認・タグ・push
└── spike.md # /spike <topic> → spikes/配下に新規Spike環境を作る
m-start.md の例:
---
name: m-start
description: Start work on a milestone. Loads the spec and invokes the planner.
---
1. Read `.claude/specs/$ARGUMENTS.md`
2. Confirm all referenced ADRs exist in `docs/adr/`
3. Invoke the `planner` subagent with the spec content
4. Present the plan to me for approval before any implementation
PMBOK の定義は明確に "a significant point or event in the project" であり、日付ではない。Claude Code 運用上も、Milestone は
m-ship が成功した瞬間」として扱う。Hook の check-dod.sh が事実上の milestone gate になる。
3段階運用で最も難しいのは 段階を進める判断だ。早すぎても遅すぎても破綻する。
進める条件:
戻る条件:
進める条件:
戻る条件:
進める条件:
m-ship 成功最頻出。Spike の本質は「捨ててよい」ことなので、本流に混ざった瞬間に捨てられなくなり、技術的負債になる。spikes/ という物理隔離と、別 CLAUDE.md による文脈分離で防ぐ。
MVP は機能要件、Walking Skeleton は構造要件。混同すると「最小機能を作るつもり」で UI や業務ロジックを膨らませてしまい、骨格が「肉付きの貧弱な MVP」になる。ステージインジケータを CLAUDE.md に明示することで防ぐ。
「次の Milestone は来週金曜まで」と書いた瞬間に、Milestone は DoD ではなくカレンダーで切られるようになり、検証可能性が消える。期日はマイルストーンの属性ではなくスケジュールの属性として別文書に置く。
両者は補完関係であって冗長関係ではない。CLAUDE.md は「なぜそうするか」を含めた規範、Hooks は「それを破ったら止める」反射神経。同じ内容を書くと、Hooks の決定論的性質が薄まる。
Spike では implementer 一人で十分(むしろ planner を挟むとオーバーヘッド)。Milestone では分離が効く。段階ごとに .claude/agents/ のサブセットを使う意識が必要だ。
Spike / Walking Skeleton / Milestone は、いずれも AI 以前から存在する設計概念だ。Claude Code の登場で、これらが古びたわけでも置き換わったわけでもない。むしろ逆で、生成速度が上がったぶん、構造的足場の重要性が増している。
BitOn での 3 段階運用が示しているのは、
ということだ。
AI支援開発は「コーディングの自動化」ではない。「設計プロセスの再記述」だと捉えるとき、Spike・Walking Skeleton・Milestone は、これからも先頭で機能し続ける。