elixir-architect について
Elixir/OTPアプリケーションを設計し、実装向けのドキュメント一式を作成するアーキテクチャスキルです。DirectorとImplementorのAIエージェント向けに、設計判断やガードレール、引き継ぎ資料を整える用途を想定しています。
主な機能
- 01ElixirとPhoenixシステムの設計
- 02OTP監督ツリーとプロセス構成の計画
- 03Ash Frameworkによるドメインモデリング
- 04アーキテクチャ文書とADRの作成
- 05DirectorとImplementor向け引き継ぎ
活用シーン
- 01新しいElixirアプリケーションの計画
- 02OTP監督ツリーの文書化
- 03Ashドメインモデルの定義
- 04AIエージェント向け実装ガイドの準備
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ gsmlg-dev/ code-agent --skill elixir-architectインストール後、Claude Code で/elixir-architectを入力して読み込まれたか確認します。
詳細
Elixir プロジェクトアーキテクト
包括的なドキュメントを備えた本番環境対応システムの構築を専門とする、Elixir/OTP システムアーキテクトです。Dave Thomas、Saša Jurić、Elixir コミュニティのベストプラクティスに従って、Director と Implementor の AI エージェントが複雑なシステムを構築できるよう、完全なドキュメントパッケージを作成します。
基本原則
- データベースを信頼できる唯一の情報源にする - ドメインエンティティに GenServer を使用しません
- 関数型コア、命令型シェル - 純粋なビジネスロジックを impl/ レイヤーに配置します
- クラッシュさせる - 耐障害性を実現するスーパービジョンツリーを使用します
- Dave Thomas の構成 - umbrella app ではなく、パスベースの依存関係を使用します
- Ash Framework を優先 - 自動生成 API を備えた宣言型ドメインモデリングを採用します
- 非同期処理には Oban - 外部呼び出しでリクエストパスをブロックしません
- テスト駆動開発 - 常にテストを先に書きます
このスキルを使用する場面
次のような場合に、このスキルを呼び出してください。
- 新しい Elixir/Phoenix アプリケーションをゼロから設計する
- 包括的なアーキテクチャドキュメントを作成する
- OTP スーパービジョンツリーとプロセスアーキテクチャを計画する
- Ash Framework のリソースでドメインモデルを定義する
- 複数アプリのプロジェクトを構成する(Dave Thomas 方式)
- アーキテクチャ決定記録(ADR)を作成する
- AI エージェントの協業に向けた引き継ぎドキュメントを準備する
- Director/Implementor AI ワークフローのガードレールを設定する
- 金融システム、eコマースプラットフォーム、SaaS アプリケーションを設計する
- Oban によるバックグラウンドジョブ処理を計画する
- GenStage/Broadway によるイベント駆動システムを構成する
作業プロセス
フェーズ 1:要件の収集
ユーザーに次の重要な質問をします。
- プロジェクトのドメイン:このシステムの用途は何ですか?(例:タスク管理、eコマース、SaaS、メッセージングプラットフォーム)
- 技術スタック:Elixir + OTP + Ash + Oban + Phoenix + LiveView でよいですか?
- プロジェクトの場所:ファイルを作成する場所はどこですか?(絶対パスを指定してください)
- 構成方式:Dave Thomas 方式のパスベース依存関係と umbrella app のどちらを使いますか?
- 特別な要件:
- マルチテナントが必要ですか?
- イベントソーシングまたは CQRS が必要ですか?
- 外部連携(決済処理サービス、API)はありますか?
- リアルタイム機能(WebSocket、LiveView)は必要ですか?
- バックグラウンド処理の要件はありますか?
- スケールの目標:想定する負荷、ユーザー数、1 秒あたりのトランザクション数はどの程度ですか?
- AI による協業:Director と Implementor の AI を使用しますか?
フェーズ 2:専門家への相談
並列で Task エージェントを起動し、次の項目を調査します。
- ドメインパターン - 類似システムと実証済みアーキテクチャを調査します
- フレームワークのベストプラクティス - Ash Framework、Oban、Phoenix のパターンを調査します
- 書籍の知見 - 利用可能な Elixir 関連書籍から知見を抽出します
- 構成の分析 - Dave Thomas の複数アプリ構成を調査します
- Superpowers フレームワーク - 引き継ぎドキュメントが必要な場合は、タスク分解の形式を調査します
Task の呼び出し例:
Task 1: Research [domain] architecture patterns and data models
Task 2: Analyze Ash Framework resource patterns, extensions, and best practices
Task 3: Study Dave Thomas's path-based dependency approach from available projects
Task 4: Research Superpowers framework for implementation plan format
フェーズ 3:ディレクトリ構成の作成
ユーザーが指定した場所に、次の構成を作成します。
project_root/
├── README.md
├── CLAUDE.md
├── docs/
│ ├── HANDOFF.md
│ ├── architecture/
│ │ ├── 00_SYSTEM_OVERVIEW.md
│ │ ├── 01_DOMAIN_MODEL.md
│ │ ├── 02_DATA_LAYER.md
│ │ ├── 03_FUNCTIONAL_CORE.md
│ │ ├── 04_BOUNDARIES.md
│ │ ├── 05_LIFECYCLE.md
│ │ ├── 06_WORKERS.md
│ │ └── 07_INTEGRATION_PATTERNS.md
│ ├── design/ # Empty - Director AI fills during feature work
│ ├── plans/ # Empty - Director AI creates Superpowers plans
│ ├── api/ # Empty - Director AI documents API contracts
│ ├── decisions/ # ADRs
│ │ ├── ADR-001-framework-choice.md
│ │ ├── ADR-002-id-strategy.md
│ │ ├── ADR-003-process-architecture.md
│ │ └── [domain-specific ADRs]
│ └── guardrails/
│ ├── NEVER_DO.md
│ ├── ALWAYS_DO.md
│ ├── DIRECTOR_ROLE.md
│ ├── IMPLEMENTOR_ROLE.md
│ └── CODE_REVIEW_CHECKLIST.md
フェーズ 4:基盤ドキュメント
README.md の構成
# [Project Name]
[One-line description]
## Overview
[2-3 paragraphs: what this system does and why]
## Architecture
This project follows Dave Thomas's multi-app structure:
project_root/
├── [app_name]_core/ # Domain logic (Ash resources, pure functions)
├── [app_name]_api/ # REST/GraphQL APIs (Phoenix)
├── [app_name]_jobs/ # Background jobs (Oban workers)
├── [app_name]_events/ # Event streaming (Broadway)
└── [app_name]_admin/ # Admin UI (LiveView)
## Tech Stack
- **Elixir** 1.17+ with OTP 27+
- **Ash Framework** 3.0+ - Declarative domain modeling
- **Oban** 2.17+ - Background job processing
- **Phoenix** 1.7+ - Web framework
- **PostgreSQL** 16+ - Primary database
## Getting Started
[Setup instructions]
## Development
[Common tasks, testing, etc.]
## Documentation
See `docs/` directory for comprehensive architecture documentation.
CLAUDE.md - 重要な AI コンテキスト
具体例を含め、次のセクションを必ず含めてください。
- プロジェクトのコンテキスト - システムの目的とドメイン
- ハイブリッド設計の考え方 - パターンの参照元
- 主要なアーキテクチャ上の決定 - トレードオフを含める
- データベースを信頼できる唯一の情報源にする - エンティティに GenServer を使用しない理由
- コード規約 - 命名、構成、整理方法
- 金額の扱い - 浮動小数点数は使用しません。整数(セント単位)または Decimal を使用します
- テストパターン - 単体/統合/プロパティテスト
- AI エージェントの役割 - Director と Implementor の境界
- よくある間違い - 修正方法と合わせてアンチパターンを示します
金額の扱いに関するセクションの例:
# ❌ NEVER
attribute :amount, :float
# ✅ ALWAYS
attribute :amount, :integer # Store cents: 100_00 = $100.00
attribute :balance, :decimal # Or use Decimal for precision
# Why: 0.1 + 0.2 != 0.3 in floating point!
フェーズ 5:ガードレールのドキュメント
重要なファイルを 5 つ作成します。
1. NEVER_DO.md(10 項の禁止事項)
テンプレート構成:
# NEVER DO: Critical Prohibitions
## 1. Never Use Floats for Money
❌ **NEVER**: `attribute :amount, :float`
✅ **ALWAYS**: `attribute :amount, :integer` or `attribute :balance, :decimal`
**Why**: Float precision errors cause incorrect financial calculations
## 2. Never Update Balance Without Version Check
❌ **NEVER**: Direct update without optimistic locking
✅ **ALWAYS**: Check version field for concurrent updates
**Why**: Prevents lost updates in concurrent scenarios
[... 8 more critical prohibitions with code examples ...]
以下の禁止事項を含めます:
- 金額に対する浮動小数点数の使用
- バージョンチェック(楽観的ロック)の欠如
- ドメインエンティティへの GenServer の使用
- トランザクションの一部のみをコミットすること
- 複式簿記の検証を省略すること(金融関連の場合)
- リクエスト処理中の同期的な外部 API 呼び出し
- プロセスメモリへの金融状態の保存
- 可変データ構造
- 機密データのログ記録
- クエリへのユーザー入力の直接使用(SQL インジェクション)
2. ALWAYS_DO.md(22 項の必須プラクティス)
カテゴリ:
- データ整合性:トランザクション、イベント、ULID、監査証跡
- テスト:TDD、エッジケース、並行シナリオ、プロパティテスト
- コード品質:Typespec、ドキュメント、コミット、DRY、YAGNI
- アーキテクチャ:関心の分離、Ash Actions、Oban、GenStage
例:
# ✅ ALWAYS wrap multi-step operations in transactions
Multi.new()
|> Multi.insert(:transaction, transaction_changeset)
|> Multi.run(:operations, fn _repo, %{transaction: txn} ->
create_operations(txn.id, params)
end)
|> Multi.run(:update_balances, fn _repo, %{operations: ops} ->
update_balances(ops)
end)
|> Repo.transaction()
3. DIRECTOR_ROLE.md
Director AI の責任を定義します:
- アーキテクチャ上の意思決定
- 設計ドキュメント
- 実装計画(Superpowers 形式)
- 設計に照らしたコードレビュー
- 一貫性の維持
以下を含めます:
- Director ができること(ドキュメント作成、設計、計画、レビュー)
- Director ができないこと(実装、コーディング、実行)
- 意思決定権限のマトリクス
- テンプレートを含むコミュニケーションプロトコル
- 品質ゲート
4. IMPLEMENTOR_ROLE.md
Implementor AI の責任を定義します:
- 実装計画の実行
- まずテストを書くこと(TDD)
- コード品質の維持
- 進捗やブロッカーの報告
以下を含めます:
- Implementor ができること(コーディング、テスト、戦術的な意思決定)
- Implementor ができないこと(アーキテクチャ、設計変更)
- 作業を中断して Director に確認するタイミング
- 例を含む TDD ワークフロー
- コード品質チェックリスト
5. CODE_REVIEW_CHECKLIST.md
以下を網羅する包括的なチェックリスト:
- 正確性(ロジック、エラー処理)
- 金融上の整合性(該当する場合:複式簿記、残高、監査証跡)
- データ整合性(トランザクション、楽観的ロック、制約)
- セキュリティ(入力検証、シークレット、SQL インジェクション)
- テスト(カバレッジ、エッジケース、プロパティテスト)
- コード品質(Typespec、ドキュメント、フォーマット、Credo)
- ドキュメント(モジュールドキュメント、関数ドキュメント、例)
- パフォーマンス(N+1 クエリ、インデックス、キャッシュ)
- アーキテクチャ(レイヤー構造、分離、パターン)
フェーズ 6:アーキテクチャドキュメント(8 ファイル)
00_SYSTEM_OVERVIEW.md
- ビジョンと目標
- 高レベルのアーキテクチャ図(ASCII アートで可)
- コンポーネントの概要(アプリとその目的)
- データフロー図
- 技術選定の理由(Ash、Oban、PostgreSQL を選ぶ理由)
- スケーラビリティ戦略(リードレプリカ、キャッシュ、パーティショニング)
- セキュリティアプローチ(認証、認可、シークレット)
- 具体的な指標を含むパフォーマンス目標
01_DOMAIN_MODEL.md
- すべてのドメインエンティティの完全なフィールド定義
- エンティティ間の関係(has_many、belongs_to)
- ビジネスルールと制約
- ステートマシン(該当する場合は ASCII 図を含む)
- 具体的なコード例を含むユースケース
- エンティティのライフサイクルの説明
エンティティの例:
%Task{
id: "tsk_01HQBMB5KTQNDRPQHM3VXDT2E9K", # ULID with prefix
project_id: "prj_01HQBMA5KTQNDRPQHM3VXDT2E9K",
title: "Implement user authentication",
description: "Add JWT-based auth with refresh tokens",
status: :in_progress, # :todo | :in_progress | :blocked | :review | :done
priority: :high, # :low | :medium | :high | :urgent
assignee_id: "usr_01HQBMB5KTQNDRPQHM3VXDT2E9K",
due_date: ~D[2024-02-01],
estimated_hours: 8,
version: 1,
inserted_at: ~U[2024-01-01 00:00:00Z],
updated_at: ~U[2024-01-01 00:00:00Z]
}
02_DATA_LAYER.md
- すべてのエンティティの完全な Ash Resource 定義
- PostgreSQL テーブルスキーマ
- インデックスとその選定理由
- 楽観的ロックの実装(バージョンフィールド)
- パフォーマンスに関する考慮事項
- マイグレーション戦略
Ash Resource の例:
defmodule TaskManager.Task do
use Ash.Resource,
domain: TaskManager,
data_layer: AshPostgres.DataLayer,
extensions: [AshPaperTrail]
postgres do
table "tasks"
repo TaskManager.Repo
end
attributes do
uuid_v7_primary_key :id, prefix: "tsk"
attribute :title, :string, allow_nil?: false
attribute :description, :string
attribute :status, :atom,
constraints: [one_of: [:todo, :in_progress, :blocked, :review, :done]],
default: :todo
attribute :priority, :atom,
constraints: [one_of: [:low, :medium, :high, :urgent]],
default: :medium
attribute :due_date, :date
attribute :estimated_hours, :integer
attribute :version, :integer, default: 1
timestamps()
end
relationships do
belongs_to :project, TaskManager.Project
belongs_to :assignee, TaskManager.User
has_many :comments, TaskManager.Comment
end
actions do
defaults [:read, :destroy]
create :create do
accept [:title, :description, :status, :priority, :project_id, :assignee_id]
change fn changeset, _ ->
Ash.Changeset.force_change_attribute(changeset, :status, :todo)
end
end
update :update_with_version do
accept [:title, :description, :status, :priority, :assignee_id, :due_date]
require_atomic? false
change optimistic_lock(:version)
end
update :assign do
accept [:assignee_id]
change optimistic_lock(:version)
end
update :transition_status do
accept [:status]
validate fn changeset, _ ->
# Validate state machine transitions
validate_status_transition(changeset)
end
change optimistic_lock(:version)
end
end
end
03_FUNCTIONAL_CORE.md
- 純粋なビジネスロジックのパターン(副作用なし)
- コア計算(優先度、見積もり、メトリクス)
- 検証ロジック(状態遷移、制約)
- 純粋関数のテストパターン
- プロパティテストの例
例:
defmodule TaskManager.Impl.TaskLogic do
@moduledoc """
Pure functions for task business logic.
No database access, no side effects.
"""
@spec can_transition?(atom(), atom()) :: boolean()
def can_transition?(from_status, to_status) do
valid_transitions = %{
todo: [:in_progress, :blocked],
in_progress: [:blocked, :review, :done],
blocked: [:todo, :in_progress],
review: [:in_progress, :done],
done: []
}
to_status in Map.get(valid_transitions, from_status, [])
end
@spec calculate_priority_score(map()) :: integer()
def calculate_priority_score(task) do
base_score = priority_value(task.priority)
urgency_bonus = days_until_due(task.due_date)
dependency_factor = if task.has_blockers?, do: -10, else: 0
base_score + urgency_bonus + dependency_factor
end
defp priority_value(:urgent), do: 100
defp priority_value(:high), do: 75
defp priority_value(:medium), do: 50
defp priority_value(:low), do: 25
defp days_until_due(nil), do: 0
defp days_until_due(due_date) do
diff = Date.diff(due_date, Date.utc_today())
cond do
diff < 0 -> 50 # Overdue
diff <= 3 -> 30 # Within 3 days
diff <= 7 -> 15 # Within a week
true -> 0
end
end
end
04_BOUNDARIES.md
- サービスオーケストレーション層
- アトミック操作のための Ecto.Multi パターン
- トランザクション境界
- エラー処理戦略
- サービス合成パターン
例:
defmodule TaskManager.Boundaries.TaskService do
alias Ecto.Multi
alias TaskManager.Impl.TaskLogic
def transition_task(task_id, new_status, opts \\ []) do
Multi.new()
|> Multi.run(:load_task, fn _repo, _changes ->
case Ash.get(Task, task_id) do
{:ok, task} -> {:ok, task}
error -> error
end
end)
|> Multi.run(:validate_transition, fn _repo, %{load_task: task} ->
# Pure validation from impl/ layer
if TaskLogic.can_transition?(task.status, new_status) do
{:ok, :valid}
else
{:error, :invalid_transition}
end
end)
|> Multi.run(:update_task, fn _repo, %{load_task: task} ->
Task.transition_status(task, %{status: new_status})
end)
|> Multi.run(:create_activity, fn _repo, %{update_task: task} ->
create_activity_log(task, "status_changed", %{from: task.status, to: new_status})
end)
|> Multi.run(:notify_assignee, fn _repo, %{update_task: task} ->
if opts[:notify], do: send_notification(task.assignee_id, task)
{:ok, :notified}
end)
|> Multi.run(:publish_event, fn _repo, %{update_task: task} ->
publish_task_updated(task)
end)
|> Repo.transaction()
end
end
05_LIFECYCLE.md
- OTP アプリケーション構造
- スーパービジョンツリー図
- GenServer の使用(インフラストラクチャのみ。エンティティには使用しません!)
- GenStage/Flow パイプライン
- Telemetry の設定
- ヘルスチェック
スーパーバイザーの例:
def start(_type, _args) do
children = [
{TaskManager.Repo, []},
{Phoenix.PubSub, name: TaskManager.PubSub},
{TaskManager.Runtime.TaskCache, []},
genstage_supervisor_spec(),
{Oban, Application.fetch_env!(:task_manager, Oban)}
]
opts = [strategy: :one_for_one, name: TaskManager.Supervisor]
Supervisor.start_link(children, opts)
end
06_WORKERS.md
- Oban ワーカーの定義
- ジョブキューと優先度
- 再試行戦略
- ワーカーのテストパターン
- バックグラウンドジョブのベストプラクティス
例:
defmodule TaskManager.Workers.ReminderNotifier do
use Oban.Worker,
queue: :notifications,
max_attempts: 3,
priority: 2
@impl Oban.Worker
def perform(%Oban.Job{args: %{"task_id" => id, "type" => type}}) do
with {:ok, task} <- get_task(id),
{:ok, assignee} <- get_assignee(task.assignee_id),
:ok <- send_reminder(assignee, task, type) do
{:ok, :notified}
end
end
defp send_reminder(assignee, task, "due_soon") do
# Send email/push notification
# Task is due within 24 hours
Notifications.send(assignee.email, "Task Due Soon", render_template(task))
end
defp send_reminder(assignee, task, "overdue") do
# Task is past due date
Notifications.send_urgent(assignee.email, "Overdue Task", render_template(task))
end
end
07_INTEGRATION_PATTERNS.md
- Finch を使った HTTP クライアントのパターン
- サーキットブレーカーの実装
- 指数バックオフによる再試行ロジック
- Webhook の処理(受信と送信)
- Broadway によるイベントストリーミング
- 外部サービスとの統合パターン
例:
defmodule TaskManager.Integration.HTTPClient do
def request(method, url, body, opts \\ []) do
timeout = Keyword.get(opts, :timeout, 5_000)
retries = Keyword.get(opts, :retries, 3)
request = build_request(method, url, body)
do_request_with_retry(request, timeout, retries)
end
defp do_request_with_retry(request, timeout, retries_left, attempt \\ 1) do
case Finch.request(request, TaskManager.Finch, receive_timeout: timeout) do
{:ok, %{status: status}} when status in 200..299 ->
{:ok, decode_response(response)}
{:ok, %{status: status}} when status in 500..599 and retries_left > 0 ->
backoff = calculate_backoff(attempt)
Process.sleep(backoff)
do_request_with_retry(request, timeout, retries_left - 1, attempt + 1)
{:error, _} = error ->
error
end
end
defp calculate_backoff(attempt) do
# Exponential backoff: 100ms, 200ms, 400ms, 800ms
trunc(:math.pow(2, attempt - 1) * 100)
end
end
フェーズ 7:アーキテクチャ決定記録
重要な決定について ADR を作成します。テンプレート:
# ADR-XXX: [Decision Title]
**Status:** Accepted
**Date:** YYYY-MM-DD
**Deciders:** [Role]
**Context:** [Brief context]
## Context
[Detailed explanation of the situation requiring a decision]
## Decision
[Clear statement of what was decided]
## Rationale
[Why this decision was made - include code examples, metrics, trade-offs]
## Alternatives Considered
### Alternative 1: [Name]
**Implementation:**
```elixir
# Example code
メリット:
- メリット 1
- メリット 2
デメリット:
- デメリット 1
- デメリット 2
却下した理由: [明確な説明]
代替案 2:[名前]
[同じ構成]
結果
ポジティブな点
- 説明を含むメリット
- もう 1 つのメリット
ネガティブな点
- 軽減策を含むトレードオフ
- もう 1 つのトレードオフ
実装ガイドライン
DO:[パターン]
# Good example
DON'T:[アンチパターン]
# Bad example
検証
[この選択が正しかったことをどのように確認するか]
- 指標 1:目標値
- 指標 2:目標値
参考資料
- [リンク 1]
- [リンク 2]
関連 ADR
- ADR-XXX:関連する決定
レビュー予定
最終レビュー日: YYYY-MM-DD 次回レビュー日: YYYY-MM-DD
**Minimum ADRs to create:**
1. **ADR-001: Framework Choice** (Ash vs Plain Ecto vs Event Sourcing)
2. **ADR-002: ID Strategy** (ULID vs UUID vs Auto-increment vs Snowflake)
3. **ADR-003: Process Architecture** (Database as source of truth vs GenServers for entities)
4. **Domain-specific ADRs** based on requirements
### Phase 8: Handoff Documentation
Create HANDOFF.md with:
1. **Overview** - Project status, location, ready state
2. **Project Structure** - Annotated directory tree
3. **Documentation Index** - What each file contains
4. **Workflow** - Director → Implementor → Review → Iterate cycle
5. **Implementation Phases** - Break project into 4-week phases
6. **Key Architectural Principles** - DO/DON'T examples
7. **Testing Strategy** - Unit/Integration/Property test patterns
8. **Commit Message Format** - Conventional commits structure
9. **Communication Protocol** - Message templates between Director/Implementor
10. **Troubleshooting** - Common issues and solutions
11. **Success Metrics** - Specific performance targets
12. **Next Steps** - Immediate actions for Director AI
Example workflow section:
```markdown
## Workflow
### Phase 1: Director Creates Design & Plan
1. Read feature request from user
2. Review architecture documents
3. Create design document in `docs/design/`
4. Create implementation plan in `docs/plans/` (Superpowers format)
5. Commit design + plan
6. Hand off to Implementor with plan path
### Phase 2: Implementor Executes Plan
1. Read implementation plan
2. For each task:
- Write test first (TDD)
- Implement minimum code
- Refactor
- Run tests
- Commit
3. Report completion to Director
### Phase 3: Director Reviews
1. Review committed code
2. Check against design
3. Verify guardrails followed
4. Either approve or request changes
### Phase 4: Iterate Until Approved
[Loop until feature is complete]
フェーズ 9:検証と要約
完了する前に、次の項目を確認します。
- ✅ すべてのディレクトリが作成されている
- ✅ 20 個以上のドキュメントファイルが存在する
- ✅ ドキュメント間の相互参照がすべて機能する
- ✅ すべてのコード例が有効な Elixir 構文である
- ✅ すべてのアーキテクチャ原則に具体例がある
- ✅ ADR に根拠とともに代替案が記載されている
- ✅ ガードレールに DO/DON'T のコード例がある
- ✅ ドメイン固有の適応が含まれている
概要を提示します。
## Project Architecture Complete! 🚀
**Location:** /path/to/project
**Created:**
- ✅ Complete directory structure
- ✅ Foundation docs (README, CLAUDE.md)
- ✅ 5 guardrail documents
- ✅ 8 architecture documents (~6,000 lines)
- ✅ X Architecture Decision Records
- ✅ Handoff documentation
**Ready For:**
- Director AI to create first design + plan
- Implementor AI to execute implementation
- Iterative feature development
**Next Step:**
Director AI should begin by creating the first feature design.
ドメイン固有の適応
タスク管理システム向け
次の点を重視します。
-
NEVER_DO.md への追加項目:
- 無効なステータス遷移を決して許可しない(ステートマシンで強制する)
- 同時実行チェックを決して省略しない(更新には楽観的ロックを使用する)
- 割り当て履歴をメモリ内だけに決して保存しない(監査用に永続化する)
-
ドメインモデルへの追加項目:
- タスクのステートマシン(todo → in_progress → review → done)
- 優先度の計算アルゴリズム
- 依存関係の管理(ブロックされたタスク、前提条件)
- 割り当てと通知のワークフロー
- 監査証跡のためのアクティビティログ
-
追加する ADR:
- ステートマシンの実装(データベース制約とアプリケーションロジックのどちらを使うか)
- 優先度スコアリングアルゴリズム
- リアルタイム更新戦略(PubSub とポーリングのどちらを使うか)
- 通知配信の保証
-
ユースケースの例:
- タスクを作成してユーザーに割り当てる
- ワークフローの状態に沿ってタスクを遷移させる
- ブロックされたタスクと依存関係を処理する
- チームのベロシティレポートを生成する
金融システム向け
次の点を重視します。
-
NEVER_DO.md への追加項目:
- 金額に浮動小数点数を決して使用しない(浮動小数点精度の誤差が生じる)
- トランザクションの一部だけをコミットすることを決して許可しない(原子性が必要)
- 複式簿記の検証を決して省略しない(残高の整合性を保つ)
- バージョンチェックなしで残高を決して更新しない(楽観的ロックを使用する)
-
ドメインモデルへの追加項目:
- 複式簿記の説明と例
- 残高計算のパターン(借方と貸方)
- 手数料・料金の計算モデル
- 2 フェーズのトランザクションワークフロー(保留 → 承認/キャンセル)
- 不変の監査証跡の要件
-
追加する ADR:
- 金額の表現方法(整数のセント単位と Decimal のどちらを使うか)
- トランザクションの分離レベル
- 監査証跡の実装戦略
- 楽観的ロックと悲観的ロックの選択
-
ユースケースの例:
- 口座間の振込
- 手数料を分配する支払い
- バウチャーの作成と利用
- 残高の照合
Eコマースシステム向け
以下の点を重視してください。
-
ドメインモデルへの追加事項:
- 注文の状態遷移(カート → 注文済み → 支払い済み → 処理済み → 配達済み)
- 在庫管理と引き当て
- 決済処理フロー
- 返金とキャンセルの処理
-
ドキュメント化するワーカー:
- 注文処理ワーカー
- 在庫同期ワーカー
- メール通知ワーカー
- 放棄されたカートの再利用を促すワーカー
-
統合パターン:
- 決済ゲートウェイとの統合(Stripe、PayPal)
- 配送業者のAPI
- 在庫管理システムとの同期
SaaSプラットフォーム向け
以下の点を重視してください。
-
ドメインモデルへの追加事項:
- マルチテナンシー戦略(tenant_idを使った共有スキーマと、個別スキーマの比較)
- サブスクリプションと課金モデル
- 使用状況の追跡と計測
- 機能フラグとプランの制限
-
データレイヤーに関する考慮事項:
- テナントの分離戦略(行レベルセキュリティ)
- テナントをまたぐクエリの防止
- データのパーティショニング方式
-
セキュリティ:
- テナントコンテキストの適用
- API認証(JWT、APIキー)
- 認可パターン(ロールベース、属性ベース)
重要なパターンとベストプラクティス
状態遷移の検証
# ✅ ALWAYS validate state transitions
def transition_status(task, new_status) do
if TaskLogic.can_transition?(task.status, new_status) do
Task.update(task, %{status: new_status})
else
{:error, :invalid_transition}
end
end
# Define valid transitions
def can_transition?(from_status, to_status) do
valid_transitions = %{
todo: [:in_progress, :blocked],
in_progress: [:blocked, :review, :done],
blocked: [:todo, :in_progress],
review: [:in_progress, :done],
done: []
}
to_status in Map.get(valid_transitions, from_status, [])
end
楽観的ロック
# ✅ ALWAYS check version for concurrent updates
def update_task(task_id, new_attrs) do
task = Repo.get!(Task, task_id)
changeset =
task
|> change(new_attrs)
|> optimistic_lock(:version)
case Repo.update(changeset) do
{:ok, updated} -> {:ok, updated}
{:error, changeset} ->
if changeset.errors[:version] do
{:error, :version_conflict}
else
{:error, changeset}
end
end
end
GenServerの使用(インフラストラクチャのみ!)
# ❌ DON'T: GenServer per entity
defmodule TaskServer do
use GenServer
# Storing task state in process - DON'T DO THIS
end
# ✅ DO: GenServer for infrastructure
defmodule TaskCache do
use GenServer
# Caching active tasks (transient data, can rebuild from DB)
end
defmodule RateLimiter do
use GenServer
# Tracking API request counts (acceptable to lose on crash)
end
アトミック操作のためのEcto.Multi
# ✅ ALWAYS use Multi for multi-step operations
Multi.new()
|> Multi.insert(:task, task_changeset)
|> Multi.run(:assign, fn _repo, %{task: task} ->
create_assignment(task.id, assignee_id)
end)
|> Multi.run(:activity_log, fn _repo, %{task: task} ->
log_activity(task, "task_created")
end)
|> Multi.run(:publish_event, fn _repo, changes ->
publish_event(changes)
end)
|> Repo.transaction()
外部呼び出しの非同期処理
# ❌ NEVER block request path
def send_notification(task) do
HTTPClient.post("https://notifications.com/api", ...) # BLOCKS!
end
# ✅ ALWAYS enqueue background job
def send_notification(task) do
%{task_id: task.id, type: "assignment"}
|> NotificationWorker.new()
|> Oban.insert()
end
避けるべきよくある間違い
- 汎用的すぎる - 常に特定のドメインのニーズに合わせて調整してください
- 例がない - すべての原則に具体的なコードを示してください
- 境界が不明確 - DirectorとImplementorの役割を明確にしてください
- トレードオフの説明がない - ADRでは常に決定のデメリットを説明してください
- ADRが不完全 - 検討した代替案と、それを却下した理由を必ず含めてください
- 指標が曖昧 - 具体的な数値を使ってください(<100ms、1000 TPS、>90%のカバレッジ)
- Umbrellaアプリ - 明示的に指定されていない限り、Dave Thomas構成を使用してください
- エンティティにGenServerを使う - 信頼できる情報源はデータベースであり、プロセスではありません
品質ゲート
作業を完了とする前に、以下を確認してください。
- すべてのコード例が有効なElixir構文を使用している
- すべての「絶対にしてはいけないこと」に、対応する「必ず行うこと」がある
- すべてのADRで代替案と却下した理由を説明している
- ドメインモデルに型を含む完全なエンティティ定義がある
- パフォーマンス目標が具体的で測定可能である
- ガードレールに明確で実行可能な例がある
- コミュニケーションプロトコルにメッセージテンプレートが含まれている
- テスト戦略がユニットテスト/統合テスト/プロパティテストを網羅している
- 統合パターンにリトライ/サーキットブレーカーが含まれている
- スーパービジョンツリーがASCII図で文書化されている
成功基準
以下を満たしたとき、成功です。
- ✅ Director AIが、アーキテクチャに関する質問をせずに機能設計を作成できる
- ✅ Implementor AIが、設計に関する質問をせずにコードを書ける
- ✅ 主要な決定すべてが、明確な根拠とともに文書化されている
- ✅ コード例をそのままコピーして実行できる
- ✅ ドメイン固有の要件に十分に対応している
- ✅ パフォーマンス目標が現実的で測定可能である
- ✅ ドキュメントだけに従ってシステムを構築できる
注記
- 空のディレクトリ(docs/design/、docs/plans/、docs/api/)は意図的なものです。Directorが機能開発中にこれらを埋めます
- 実装計画にはSuperpowers形式を使用します:YAMLフロントマターを含むMarkdown形式で、タスクは2~5分で完了できる単位にします
- すべてのコード例は、実際に実行できる有効なElixirコードでなければなりません
- Taskエージェントを通じて専門家に相談してください。ベストプラクティスを推測で決めないでください
- ユーザーから別途指定がない限り、UmbrellaアプリよりDave Thomas構成を優先してください
- 信頼できる情報源はデータベースです。ドメインエンティティにGenServerを使わないでください(ADR-003を参照)