Skip to content

Latest commit

 

History

History
416 lines (311 loc) · 18.3 KB

File metadata and controls

416 lines (311 loc) · 18.3 KB

Ducer — SPEC.md

Own your creativity.

思想

プログラミングツールの多くは「速く作ること」を目指す。DucerはAIが全部やるのではなく、人間がクリエイティブであり続けることを中心に設計されている。

Ducerは、自分でコーディングするスタイルと、バイブコーディングの間に位置する。

  • 勉強と制作は別々じゃない。作りながら理解する(Learning by doing)
  • AIはコーチ。主役は常にユーザー
  • 共に進むから、先が見える

概要

ユーザーがソフトウェアを理解しながら作るための、AIコーチングMCPサーバー。 Claude Codeに接続し、AIが実装を進めながら音声で逐一解説する。ユーザーが事前に指定した箇所だけをユーザーに渡す(ハンドオフ)。

名前の由来:ラテン語 "educere"(内側から引き出す)から。AIが教え込むのではなく、ユーザーの能力を引き出す。


ユーザージャーニー

  1. ユーザーがClaude Codeに「作りたいもの」を伝える。
  2. Claude Codeが start_session でDucerセッションを開始し、使用IDEを確認する
  3. Claude Codeが**理解の順序(cognitive ordering)**でプランを設計し、set_plan で登録する。Ducerが音声でプランを読み上げ、ユーザーに確認を取る
  4. ユーザーが「次」と言うたびに、Claude Codeが write_step を呼ぶ。DucerがIDEのファイルにコードをブロック単位で書きながら、VoiceManagerが内容をリアルタイムで解説する
  5. ユーザー担当箇所に来たら execute_handoff で停止し、音声で「ここからはあなたです」と渡す
  6. ユーザーが実装したら、Claude Codeが check_user_code で評価し、次へ進む
  7. ビルドエラー等が起きた場合、アドホックステップを write_step で挿入して修正する
  8. 間違えたら goto_step でロールバックし、やり直せる
  9. 最終的にソフトウェアが完成し、ユーザーは内部構造を理解している

想定ユーザー

  • プログラミングを自分の興味のあることで学習したい人
  • システムの全体概要を捉えた上で表現の検討をしたいアーティスト、プログラマー
  • 技術書を読み終え、自分の作りたいものをどう作るか知りたい人
  • 業務の中で効率よく仕様を学びながら経験を積みたいエンジニア

モード

モードは明示的に選ぶものではなく、user_owned の内容によって自動的に決まる。

モード 条件 動作
Watch user_owned が空 AIが全部書く。ユーザーは見て理解するだけ
Pair user_owned に何か入っている AIが担当部分を書き、handoff でユーザーに渡す

仕組みは同じ。ユーザーの担当箇所があるかどうかだけが違い。


アーキテクチャ

DucerはMCPサーバーとしてClaude Codeに接続する。Claude Code自体がオーケストレーターおよびプランナーの役割を担い、Ducerはコード書き込み・音声ナレーション・セッション管理を提供する。

┌──────────────────────────────────────────────┐
│              Claude Code (AI)                │
│  プランニング・オーケストレーション・対話      │
└──────────┬───────────────────────────────────┘
           │ MCP Protocol
           ↓
┌──────────────────────────────────────────────┐
│           Ducer MCP Server                   │
│  ┌─────────┐  ┌─────────┐  ┌──────────────┐ │
│  │ Session │  │  Coder  │  │ VoiceManager │ │
│  └─────────┘  └─────────┘  └──────────────┘ │
└──────────────────────────────────────────────┘

役割分担

担当 役割
Claude Code ユーザーとの対話、プラン設計、ステップの実行判断、コード生成
Ducer ファイル書き込み、音声ナレーション、セッション状態管理、IDE連携

コンポーネント詳細

Session

  • セッション全体の状態管理(プラン、完了ステップ、書き込みファイル)
  • .ducer/session.json に永続化。MCPサーバー再起動やClaude Codeセッション変更を跨いで復元可能
  • ステップごとに書き込んだファイルを追跡(written_files)。ロールバック時のファイル削除に使用
  • セッション状態: idleactivehandoffcomplete

Coder

  • プランに従ってIDEのファイルに直接コードを書く
  • ブロック単位書き込み: ソースコードを空行で区切ったブロックに分割し、1ブロックずつファイルに追記する。各ブロックの間にナレーションを挟むことで、ユーザーがリアルタイムでコードの成長を見られる
  • ファイル作成時にIDEで自動オープン(Xcode / VS Code / Cursor対応)
  • スケルトンコードの書き込み(ハンドオフ用)

VoiceManager

  • TTS: macOS say コマンドによる日本語音声ナレーション
    • デフォルト音声: Kyoko、速度: 200 WPM
    • コードブロックの間に挟まる形でリアルタイム解説
    • enabled=False でサイレントモード(テスト/CI用)
  • 割り込み: interrupt() で発話を即座に停止可能

VoiceManagerのペルソナ・プロンプト設計原則

VoiceManagerに渡すナレーションは以下の原則に基づく:

  1. Why優先:何を書くかより、なぜそう書くかを先に説明する

    • ❌「ifブロックを書きます」
    • ✅「隣のセルが生きているか死んでいるかを確認します。条件によって処理を分けたいので、ifを使います」
  2. 具体的な例えを使う:抽象的な概念を日常的なものに置き換える

    • 例:「配列はエクセルの表のようなものです」
  3. 難しい言葉を使わない:専門用語を使う場合は必ず一言で説明を添える

  4. ユーザーレベルに合わせるgranularity の値に応じて説明の深さを変える

    • 1(粗い):大きな流れだけ説明、詳細は省く
    • 3(標準):概念とコードの対応を説明
    • 5(細かい):1行ごとに丁寧に、背景知識も含めて説明
  5. テンポを保つ:説明が長くなりすぎない。1ブロックあたり2〜3文を目安にする


MCPツール

セッション管理

ツール 説明
start_session セッション開始/再開。プロジェクトルート、名前、granularity、音声設定、IDE名を指定
get_session_status 現在のセッション状態とプラン進捗を取得

プラン操作

ツール 説明
set_plan 実装プランを設定(構造のみ、コードなし)。音声でプランを読み上げて確認を取る
revise_plan 指定ステップ以降のプランを差し替え

ステップ実行

ツール 説明
write_step blocks配列でコード・ナレーション・コメントを一体で書き込む。各blockが1つの書き込み単位。プランにないステップIDの場合、アドホックステップとして自動挿入される
execute_handoff ユーザーにバトンを渡す。スケルトンコードを書き込み、音声で案内する
check_user_code ユーザーが書いたファイルの内容を読み取って返す

ナビゲーション

ツール 説明
goto_step ステップNにロールバック。N以降のステップで書いたファイルを削除し、進捗をリセットする。goto_step(0) で全リセット
speak 任意のテキストを音声で読み上げる

MCPリソース

URI 説明
ducer://guide コーチングガイド。Claude Codeが従うべき原則(cognitive ordering、ナレーションスタイル、ツール使用順序)
ducer://plan/current 現在のプランと進捗状況(JSON)

コーチングガイドの主要原則

コーチングガイド全文は ducer://guide リソースとして提供される。主要原則のみここに記載する。

A. インタラクティブフロー

  • セッション開始時にIDEを確認する
  • AIがプロジェクト足場(Package.swift、xcodeproj等)を作成する
  • 1ステップずつ進める。複数ステップを連続実行しない
  • ステップ実行前に意図を説明し、ユーザーの確認を得る

B. 認知的順序(Cognitive Ordering)

  • 各ステップは前のステップの土台になっている
  • 画面に何かが出ることを最優先(単色の四角形でもいい)
  • 1ステップ = 1ファイル。ナレーションとコードブロックの整合性を保つため
  • ユーザー担当箇所は、前後の文脈が理解できた状態で渡す
  • コア先行確認(後述)に従い、プロジェクトのコアを最優先で体験可能にする
  • 観測可能状態ルール: ステップのタイトル・descriptionは完了時にユーザーが観測できる状態を記述する。未接続のコードは「定義する」「準備する」と書き、「描画する」「表示する」を使わない

C. アドホックステップ

  • ビルドエラー修正等、プランにない作業も write_step で対応
  • プランに存在しない step_id を指定すると、最後に完了したステップの直後に自動挿入される

D. ロールバック(goto_step)

  • goto_step(0): 全リセット。全ファイル削除、プランクリア
  • goto_step(N): ステップN以降をロールバック。該当ファイルを削除し、進捗をリセット
  • ロールバック後、削除されたファイルが過去ステップでも書かれていた場合、そのステップを先に再実行する

データモデル

PlanStep

@dataclass
class PlanStep:
    id: int                          # ステップ番号
    title: str                       # タイトル
    description: str                 # 説明
    rationale: str                   # なぜこの順番か
    owner: Literal["ai", "handoff"]  # 実行者
    files: list[str]                 # 対象ファイル(相対パス)
    completion_criteria: str         # 完了条件(任意)
    message: str                     # ハンドオフメッセージ(任意)

プランのJSON構造例

{
  "project": "Game of Life",
  "user_owned": [
    {
      "file": "Sources/Logic/GameLogic.swift",
      "description": "Game of Lifeのアルゴリズム。nextGeneration関数を実装してください",
      "skeleton": "func nextGeneration(grid: [[Bool]]) -> [[Bool]] {\n    // ここを実装してください\n}"
    }
  ],
  "steps": [
    {
      "id": 1,
      "title": "エントリーポイント作成",
      "description": "アプリの起動地点を作ります",
      "rationale": "まずアプリが起動することを確認します",
      "owner": "ai",
      "files": ["GameOfLife/GameOfLifeApp.swift"],
      "completion_criteria": "アプリが起動する"
    },
    {
      "id": 2,
      "title": "Metalシェーダー",
      "description": "画面に色を表示するシェーダーを作ります",
      "rationale": "早期に画面出力を実現します",
      "owner": "ai",
      "files": ["GameOfLife/Shaders/GridShaders.metal"],
      "completion_criteria": "シェーダーがコンパイルできる"
    }
  ]
}

セッション永続化

セッション状態は {project_root}/.ducer/session.json に自動保存される。

{
  "project_name": "Game of Life",
  "granularity": 3,
  "plan_steps": [...],
  "completed_steps": [1, 2],
  "written_files": {
    "1": ["GameOfLife/GameOfLifeApp.swift"],
    "2": ["GameOfLife/Shaders/GridShaders.metal"]
  },
  "state": "active"
}

MCPサーバーが再起動しても、start_session 時に既存セッションを検出して自動復元する。


スキル

/ducer-step — ステップ操作

Claude Codeのスラッシュコマンドとして提供。

コマンド 動作
/ducer-step 次の未完了ステップを実行
/ducer-step N ステップNに移動(ロールバック含む)
/ducer-step 0 セッション全体をリセット

技術スタック

コンポーネント 技術
全体 Python 3.11+
サーバー MCP (Model Context Protocol) / fastmcp
TTS macOS say コマンド(日本語 Kyoko)
AI Claude Code(MCPクライアントとして接続)
セッション保存 JSON (.ducer/session.json)
IDEファイル操作 直接ファイル書き込み + IDE自動オープン

起動方法

1. MCP接続設定(.mcp.json

{
  "mcpServers": {
    "ducer": {
      "command": "python",
      "args": ["-m", "ducer.server"],
      "cwd": "/path/to/ducer"
    }
  }
}

注意: python コマンドは仮想環境有効化後に使えるようになる。source .venv/bin/activate が必要。

2. セッション開始(Claude Codeから)

Claude Code → start_session(project_root, project_name, granularity, ide)
Claude Code → set_plan(steps)
Claude Code → write_step(step_id, blocks, mode) を繰り返す

重要な設計原則

  1. 理解優先:速く作ることより、ユーザーが理解することを優先する
  2. 動くものを見せる:毎ステップ、何かが動く状態にする。画面出力を最優先
  3. ユーザーの主体性:AIはあくまでコーチ。ユーザーが書きたい部分は必ず渡す
  4. 説明のスタイル:丁寧で体系的に説明しながら、ユーザーの状況を読んで柔軟に導く
  5. 1ステップ = 1ファイル:ナレーションとコードの整合性を保つための基本単位
  6. ロールバック可能:いつでも過去のステップに戻れる。失敗を恐れずに進められる
  7. 永続性:セッション状態は自動保存。中断しても続きから再開できる
  8. コア先行確認:プロジェクトのコア(最も重要なアルゴリズムや概念)を実装した直後に、その動作を体験できなければならない

コア先行確認(Core-First Verification)

Ducerの存在意義は「理解しながら作る」ことにある。ユーザーの理解がピークに達するのは、プロジェクトのコア — 最も重要なアルゴリズムや概念 — を実装した瞬間である。この理解のピークと動作確認が離れていると、理解は保留され、薄れ、Ducerの価値が損なわれる。

原則

コアを実装した直後の1ステップ以内に、その動作を視覚的・機能的に確認できなければならない。

確認できない場合、ステップの順序を再構成するか、確認用の中間ステップを挿入する。

ステップ設計の3フェーズ

ステップの順序は「依存関係の順」ではなく「理解と体験の順」で設計する。

Phase 1: 最小足場(scaffold)
  コアを「見せる」ために必要な最低限のインフラを構築する。
  ここでは表示系・描画系・通信系など、コアの出力先を先に整える。

Phase 2: コア実装 + 即時確認(core → verify)
  プロジェクトの核心を実装し、直後のステップでそれが動くのを見る。
  この2ステップの間に無関係なステップを挟んではならない。

Phase 3: 段階的拡張(extend)
  追加機能を一つずつ実装する。各ステップで即確認できる状態を維持する。

適用例

アプリ コア 最小足場 即時確認
Game of Life セルオートマトン 描画パイプライン + セル色分け タイマーで自動進化
画像フィルタ フィルタアルゴリズム カメラ/画像入力 + 表示 フィルタ適用結果
チャットアプリ リアルタイム同期 最小UI + 接続 メッセージが流れる
物理シミュレーション 物理方程式 レンダリング + オブジェクト 物体が落下・衝突

.ducerファイルでの表現

プロジェクト定義に core_concept を記述し、各ステップに purpose を指定する。

project:
  core_concept: >
    Conway's cellular automaton — 隣接セルを数えて誕生・生存・死亡を判定する
    単純なルールから複雑なパターンが創発する。

steps:
  - id: 1
    purpose: scaffold   # コアのための土台
  - id: 8
    purpose: core       # コアの実装
  - id: 9
    purpose: verify     # コアの動作確認(core直後であること)
  - id: 10
    purpose: extend     # 追加機能

purpose の4種類:

  • scaffold — コアを動かすために必要な土台
  • core — プロジェクトの核心
  • verify — コアが動くことを確認できるステップ(core直後に配置)
  • extend — 追加機能・UI改善

今後の拡張(スコープ外・将来)

  • より自然なTTS(OpenAI TTS API)
  • STT(Whisper APIによるマイク入力・音声割り込み)
  • FileWatcher(watchdogによるユーザーコード変更の自動検知)
  • セッション履歴のエクスポート・共有
  • Web/クラウドIDE対応
  • 複数プロジェクト同時セッション