implement について
implementは、SPEC.mdを構造化されたユーザーストーリーに変換し、実装ループを実行するエージェントスキルです。変換、準備、実行を別々のフェーズで行い、品質チェックも設定できます。
主な機能
- 01SPEC.mdをspec.jsonに変換
- 02ストーリーと受け入れ基準を検証
- 03実装プロンプトを作成
- 04スクリプトでストーリーを反復実行
- 05テスト・型チェック・lintコマンドを設定
活用シーン
- 01機能仕様を検証可能なストーリーに分割
- 02既存のspec.jsonを実装向けに準備
- 03プロジェクト固有のチェックで実装を反復
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ inkeep/ team-skills --skill implementインストール後、Claude Code で/implementを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/execution.mdscripts/implement.shvalidate-spec.tstemplates/implement-prompt.template.md詳細
実装
SPEC.md を実装にすぐ使える成果物に変換し、反復ループを実行します。このスキルは 3 つのフェーズで構成されています。
- 変換 — SPEC.md を構造化された spec.json に変換します
- 準備 — spec.json を検証し、実装プロンプトを作成してファイルに保存します
- 実行 —
scripts/implement.shを実行し、サブプロセスを介してユーザーストーリーを反復します
各フェーズは個別に開始できます。すでに spec.json がある場合は、フェーズ 2 から始めてください。成果物の準備ができていて実行が必要な場合は、フェーズ 3 から始めてください。変換のみが必要な場合は、フェーズ 1 の後で終了してください。
/ship によって呼び出された場合、Ship は /implement を実行してライフサイクル全体を処理し、その後出力をレビューします。単独で実行した場合、/implement はエンドツーエンドで実行し、結果を直接報告します。
Ship の作業ディレクトリ
すべての実装成果物は、git rev-parse --show-toplevel から動的に特定される tmp/ship/ に保存されます。Docker/CI/分離環境では、CLAUDE_SHIP_DIR_OVERRIDE で上書きできます。implement.sh スクリプトがディレクトリを自動的に解決します。
入力
| 入力 | 必須 | デフォルト | 説明 |
|---|---|---|---|
| SPEC.md または spec.json のパス | はい | — | ソース成果物です。SPEC.md の場合:フェーズ 1 の変換に使用され、フェーズ 2 では反復時の参照情報として引き継がれます(「Spec path forwarding」を参照)。spec.json の場合:フェーズ 2 から直接開始します。 |
--test-cmd | いいえ | pnpm test --run | 品質ゲート用のテストランナーコマンドです |
--typecheck-cmd | いいえ | pnpm typecheck | 品質ゲート用の型チェッカーコマンドです |
--lint-cmd | いいえ | pnpm lint | 品質ゲート用のリンターコマンドです |
--no-browser | いいえ | ブラウザーが利用可能と想定 | UI ストーリーから「ブラウザーで確認」の基準を省き、Bash で検証可能な基準に置き換えます |
--docker [compose-file] | いいえ | — | フェーズ 3 の実行に Docker を使用します。必要に応じて compose ファイルへのパスを指定できます(例:--docker .ai-dev/docker-compose.yml)。パスを指定せずに渡した場合、compose ファイルを自動検出します。このオプションを省略した場合、実行はホスト上で行われます。 |
/ship によって呼び出された場合、フェーズ 0 のコンテキスト検出に基づいてこれらのオーバーライドが渡されます。単独で実行する場合は、デフォルトが適用されます。
Spec path forwarding
SPEC.md が指定された場合(直接指定、または呼び出し元による指定)、そのパスはフェーズ 1 の変換後も引き継がれます。フェーズ 2 では、スキルが実装プロンプトにファイルパス参照を埋め込み、各反復の最初のアクションとして反復エージェントが SPEC.md 全体を読むようにします。spec の内容はプロンプトに埋め込まれません。プロンプトに含まれるのはファイルパスのみです。
spec のパスが利用可能な場合、これは必須です。spec には、spec.json の implementationContext では完全に補えない重要な実装コンテキストが含まれています。
- 対象外事項(構築しないもの)— spec.json にはまったく含まれません
- 現在の状態を示すコードの追跡情報(ファイルパス、行番号、既存のパターン)— implementationContext では文章に圧縮されます
- 判断の根拠 — 結論のみになります
- リスクと障害モード — 受け入れ基準に一部しか取り込まれません
SPEC.md がなく spec.json のみが指定されている場合、implementationContext が唯一の実装コンテキストの情報源になります。深さの調整方法については、フェーズ 1 の implementationContext に関するガイダンスを参照してください。
ワークフロータスクの作成(最初のアクション)
作業を開始する前に、各フェーズのタスクを TaskCreate で作成し、addBlockedBy を使って順序を守ってください。各フェーズ自身のワークフローの説明から、タスクの説明と完了基準を導き出してください。
- Implement: 開始位置を検出
- Implement: フェーズ 1 — SPEC.md を spec.json に変換
- Implement: フェーズ 2 — プロンプトを検証して作成
- Implement: フェーズ 3 — 反復ループを実行
各フェーズを開始したら、そのタスクを in_progress に設定し、フェーズの終了基準を満たしたら completed に設定してください。再開時は、まず TaskList を確認し、未完了のタスクのうち最初のものから続行してください。
開始位置を判定する
| 条件 | 開始フェーズ |
|---|---|
| SPEC.md が存在し、spec.json はない | Phase 1(変換) |
| spec.json が存在し、検証/プロンプトが必要 | Phase 2(準備) |
spec.json と tmp/ship/implement-prompt.md が存在し、実行可能 | Phase 3(実行) |
| 変換リクエストのみを指定して呼び出された | Phase 1 の後、停止 |
Phase 1:変換(SPEC.md から spec.json へ)
SPEC.md を tmp/ship/spec.json に変換します。tmp/ship/ が存在しない場合は作成します(mkdir -p tmp/ship)。
出力形式
{
"project": "[Project Name]",
"branchName": "implement/[feature-name-kebab-case]",
"description": "[Feature description from SPEC.md title/intro]",
"implementationContext": "[Concise prose summary of architecture, constraints, key decisions, and current state from the SPEC.md — everything the implementer needs to know that doesn't fit in individual stories]",
"userStories": [
{
"id": "US-001",
"title": "[Story title]",
"description": "As a [user], I want [feature] so that [benefit]",
"acceptanceCriteria": [
"Criterion 1",
"Criterion 2",
"Typecheck passes"
],
"priority": 1,
"passes": false,
"notes": ""
}
]
}
ストーリーの規模:最重要ルール
各ストーリーは、1 回のイテレーション(1 つのコンテキストウィンドウ)で完了できる必要があります。
各イテレーションには、前回の作業の記憶がない状態で同じプロンプトが渡されます。保持されるのはファイルと Git の履歴だけです。ストーリーが大きすぎると、LLM は完了前にコンテキストを使い切り、壊れたコードを生成します。
適切な規模のストーリー:
- データベースの列とマイグレーションを追加する
- 既存のページに UI コンポーネントを追加する
- 新しいロジックでサーバーアクションを更新する
- リストにフィルタードロップダウンを追加する
大きすぎるストーリー(分割してください):
- 「ダッシュボード全体を構築する」— スキーマ、クエリ、UI コンポーネント、フィルターに分割する
- 「認証を追加する」— スキーマ、ミドルウェア、ログイン UI、セッション処理に分割する
- 「API をリファクタリングする」— エンドポイントまたはパターンごとに 1 つのストーリーに分割する
目安: 変更内容を 2~3 文で説明できない場合、大きすぎます。
ストーリーの順序:依存関係を先にする
ストーリーは優先順位順に実行されます。先行するストーリーが後続のストーリーに依存していてはいけません。
正しい順序:
- スキーマ/データベースの変更(マイグレーション)
- サーバーアクション/バックエンドロジック
- バックエンドを使用する UI コンポーネント
- データを集約するダッシュボード/サマリービュー
誤った順序:
- UI コンポーネント(まだ存在しないスキーマに依存する)
- スキーマの変更
受け入れ基準:検証可能であること
各基準は、イテレーションエージェントが確認できるものでなければなりません。曖昧な表現は避けてください。
良い基準(検証可能):
- 「tasks テーブルに、デフォルト値が 'pending' の
status列を追加する」 - 「フィルタードロップダウンに All、Active、Completed の選択肢がある」
- 「削除をクリックすると確認ダイアログが表示される」
- 「型チェックが通る」
- 「テストが通る」
悪い基準(曖昧):
- 「正しく動作する」
- 「ユーザーが X を簡単に実行できる」
- 「優れた UX」
- 「エッジケースに対応する」
実装に密結合した基準(壊れやすい):
- 「handleStatusChange が正しい列挙型を指定して db.update を呼び出す」
- 「コンポーネントが useTaskList フックを呼び出してレンダリングする」
- 「API ハンドラーが処理前に validateInput を実行する」
振る舞いに基づく基準(変更に強い):
- 「ステータスを変更したタスクを、新しいステータスで取得できる」
- 「タスクリストに、選択したフィルターに一致するタスクのみが表示される」
- 「無効なステータス値に対して、説明的なエラーメッセージとともに 400 が返される」
実装に密結合した基準では、振る舞いが変わっていないリファクタリングでもテストが壊れます。振る舞いに基づく基準なら、内部構造を変更してもテストが維持されます。/tdd を参照してください。
最後の基準として必ず含めてください:
"Typecheck passes"
テスト可能なロジックを含むストーリーには、次も含めてください:
"Tests pass"
UI を変更するストーリーには、ブラウザー自動化が利用可能な場合(--no-browser フラグがない場合):
"Verify in browser using browser skill"
フロントエンドのストーリーは、視覚的に検証するまで完了ではありません。視覚的な検証には、agent-browser(agent-browser open <url>、agent-browser screenshot)を優先してください。単純なページ移動と確認のフローでは、より軽量で高速です。受け入れ基準でより詳細な検証が求められる場合は、/browser スキル(Playwright スクリプト)を読み込んでください。対象には、コンソールエラーの監視(startConsoleCapture / getConsoleErrors)、ネットワークリクエストの検証(startNetworkCapture / getFailedRequests)、アクセシビリティ監査(runAccessibilityAudit)があります。
ブラウザーが利用できない場合(--no-browser):ブラウザーに関する基準は省略してください。代わりに、API 応答またはレンダリングされた出力を通じて UI の振る舞いを確認できる、Bash で検証可能な基準を追加してください(例:「API 応答に更新済みのステータスバッジのマークアップが含まれる」「サーバーでレンダリングされた HTML に、All、Active、Completed の選択肢を持つフィルタードロップダウンが含まれる」)。
変換ルール
- 各ユーザーストーリーを1つのJSONエントリーにする
- ID:連番(US-001、US-002など)
- 優先度:依存関係の順、その後ドキュメントの順
- すべてのストーリー:
passes: falseと空のnotes - branchName:機能名から導出し、ケバブケースにして、
implement/を先頭に付ける - 必ず追加:各ストーリーの受け入れ条件に「Typecheck passes」を追加する
SPEC.mdから実装コンテキストを抽出する
implementationContextフィールドには、すべてのストーリーに共通して適用される仕様レベルの知識を記述します。実装者が各イテレーションで必要とするものの、単一のストーリーの受け入れ条件には含まれない情報です。
次のSPEC.mdのセクションから抽出します。
| SPEC.mdのセクション | 抽出する内容 | 重要な理由 |
|---|---|---|
| §9 提案する解決策 — システム設計 | アーキテクチャの概要、データモデル、APIの構成、認証/権限モデル | これがないと、実装者がアーキテクチャを推測したり、仕様の設計と矛盾したりするため |
| §6 非機能要件 | パフォーマンス目標、セキュリティ上の制約、信頼性要件、運用上のニーズ | これらは各ストーリーを「何に」実装するかではなく、「どのように」実装するかを制約するため |
| §10 決定ログ | 確定した決定事項(特に後戻りできない決定)と、その簡潔な根拠 | 仕様作成中に行った決定を、実装者が再検討したり覆したりするのを防ぐため |
| §8 現状 | 現在のシステムの動作、主な統合ポイント、既知の不足点 | 実装者が、正しく統合するために既存のものを把握する必要があるため |
**記述する内容:**簡潔な文章で要約します。仕様の各セクションをそのままコピーするのではなく、すべてのストーリーに取り組む間、実装者が把握しておくべき内容を抽出します。
仕様の利用可否に応じて詳しさを調整します。
| 実装時に仕様を利用できるか | implementationContextの役割 | 推奨される詳しさ |
|---|---|---|
利用できる — 仕様のパスがフェーズ2に渡される場合(/shipによって構成されたとき、またはユーザーが両方を提供したときのデフォルト) | 要点を押さえた概要。完全なSPEC.mdには詳細なコンテキストが記載されており、イテレーションエージェントは最初のステップでそれを読みます。 | 3~5文 — アーキテクチャの概要と主な制約のみ |
利用できない — spec.jsonのみが成果物の場合(ユーザーがspec.jsonのみで/implementを実行する場合、または仕様が利用できない場合) | 唯一の主要な実装コンテキスト情報源。単独で理解できる内容にする必要があります。 | 5~10文 — アーキテクチャ、対象外事項、現状の統合ポイント、根拠を伴う主な決定事項、重要な制約を含める |
仕様を利用できるかどうか判断に迷う場合は、詳しいほうを記述してください。コンテキストを多めに含めても問題ありませんが、短すぎるとイテレーションエージェントに必要な情報が不足するおそれがあります。
良い例:
「この機能では、タスクテーブルに列挙型の
status列を追加します。APIには、/api/tasks/で既に採用しているRESTfulパターンを使用します。認証は既存のテナントスコープ対応ミドルウェアで処理するため、新しい認証ロジックを追加しないでください。現在、タスクリストはデータアクセス層のgetTasksByProject()を使って取得しています。新しいフィルターにも同じクエリパターンを使用する必要があります。決定D3:データセットが1万行を超える可能性があるため、クライアント側ではなくサーバー側でのフィルタリングを選びました。」
悪い例(曖昧すぎる):
「適切な方法に従って、タスクのステータス機能を実装してください。」
大規模な仕様の分割
SPEC.mdに大きな機能が含まれる場合は、分割します。
元の内容:
「ユーザー通知システムを追加する」
分割後:
- US-001:データベースに通知テーブルを追加する
- US-002:通知を送信する通知サービスを作成する
- US-003:ヘッダーに通知ベルアイコンを追加する
- US-004:通知ドロップダウンパネルを作成する
- US-005:既読にする機能を追加する
- US-006:通知設定ページを追加する
それぞれ、独立して完了・検証できる、焦点を絞った変更になります。
失敗パスを受け入れ基準に変換する
SPEC.md §5(ユーザージャーニー)には、各ペルソナの失敗/復旧パスとデバッグ体験が含まれています。これらは、デモで動作する機能と本番環境で動作する機能を分けることがよくあります。
変換時に失敗パスを破棄しないでください。仕様書にある失敗シナリオごとに、次の手順を実行してください。
- 該当するストーリーを特定する — 失敗を、関連する機能を実装するストーリーに対応付けます。
- 検証可能な受け入れ基準に変換する — そのストーリーに追加します。
例:
SPEC.md の失敗パス:
Failure: User sets an invalid status value via API → System returns 400 with error message "Invalid status. Allowed values: pending, in_progress, done"
関連するストーリーの受け入れ基準になります:
"API returns 400 with descriptive error when status value is not in [pending, in_progress, done]"
失敗シナリオが複数のストーリーにまたがる場合(例:「保存中にネットワークエラーが発生したら、再試行ボタンを表示する」)、ユーザー向けの動作を担うストーリー(バックエンドのストーリーではなく、UI のストーリー)に基準を追加します。
非機能要件を横断的な基準として適用する
SPEC.md §6 には、パフォーマンス、信頼性、セキュリティ/プライバシー、運用性、コストに関する非機能要件が含まれています。これらは、ストーリーを どのように 実装するかを規定します。
仕様書の非機能要件ごとに、次の手順を実行してください。
- 全般に適用されるかどうかを判断する(例:「すべてのエンドポイントでテナント分離を検証する」)、または特定のストーリーに適用されるかどうかを判断する(例:「リストクエリは 1 万行に対して 200ms 未満で返す」)。
- 全般に適用される制約:該当するすべてのストーリーに基準として追加します。
- 特定のストーリーに適用される制約:該当するストーリーのみに基準として追加します。
例:
| 非機能要件 | 基準を追加する対象 |
|---|---|
| 「すべての API エンドポイントでテナント分離を検証する」 | API エンドポイントを追加または変更するすべてのストーリー |
| 「リストクエリはページネーションを行い、200ms 未満で返す」 | リスト/フィルターを実装するストーリー |
| 「ステータスの変更は監査ログに記録する」 | ステータス切り替えを実装するストーリー |
「非機能」のストーリーを別途作成しないでください。これらの制約は、関連する機能を実装するストーリーに組み込む必要があります。
qaScenarios の導出(実装コンテキスト)
ユーザーストーリーを変換した後、SPEC.md の構造化されたセクションから qaScenarios[] 配列を導出します。これらのシナリオは、実装中にイテレーションエージェントへ QA コンテキストを提供します。つまり、実装者が何を検証するのかを理解するのに役立ちます。これらは /qa-plan の制約やスコープには影響しません。qa-plan は、SPEC.md のソース資料から独自にシナリオを導出します。
各シナリオは Given/When/Then 形式に従い、1 つ以上のユーザーストーリーに対応します。
対応表:SPEC.md のセクション → シナリオのカテゴリ → 導出ルール
| SPEC.md のセクション | シナリオのカテゴリ | 導出ルール |
|---|---|---|
| §6 受け入れ基準 | ux-flow、error-state | 各基準 → 1 つの正常系シナリオ、各失敗条件 → 1 つのエラーのバリエーション |
| §5 インタラクション状態マトリックス | visual、edge-case | 空でない各セル → 1 つの状態検証シナリオ |
| §9 データフロー図 — シャドウパス | edge-case、failure-mode | 各シャドウパス → 1 つのエッジケースシナリオ |
| §9 失敗モード表 | error-state、failure-mode | 各行 → 検出、復旧、ユーザーへの影響を網羅する 1 つのエラー状態シナリオ |
| §9 影響を受けるルート/ページ | visual、ux-flow | 各行 → 1 つの表示/ナビゲーション検証シナリオ |
| §5 ユーザージャーニー(正常系+失敗パス) | ux-flow、cross-system | 各ジャーニーのステップ → 1 つの E2E シナリオ、複数のサービスにまたがるジャーニー → cross-system カテゴリ |
| §13 デプロイ/ロールアウトに関する考慮事項 | integration | 各行 → 1 つのデプロイ/統合検証シナリオ |
oracleType の割り当て
各シナリオには、合否の判定方法を定義する oracleType を設定します。
| oracleType | 使用する場面 | 例 |
|---|---|---|
specified | 合否が決定的に判定できる場合 — 仕様で期待される結果が正確に定義されている | 「API がエラーメッセージとともに 400 を返す」 |
derived | ベースラインまたは参照対象と比較する場合 — 正しさが絶対的ではなく相対的である | 「ページがデザインモックアップと同じようにレンダリングされる」 |
human | 主観的な判断が必要な場合 — 自動判定の手段が存在しない | 「エラーメッセージが役立ち、対処方法を示している」 |
例
入力 SPEC.md(抜粋):
# Task Status Feature
Add ability to mark tasks with different statuses.
## Requirements
- Toggle between pending/in-progress/done on task list
- Filter list by status
- Show status badge on each task
- Persist status in database
## Non-functional requirements
- Status changes must be tenant-scoped
## User journeys — Failure paths
- Invalid status value via API → return 400 with descriptive error
## Current state
- Tasks stored in tasks table, accessed via getTasksByProject()
- API uses RESTful patterns under /api/tasks/
- UI uses TaskCard component in components/tasks/
出力 spec.json:
{
"project": "TaskApp",
"branchName": "implement/task-status",
"description": "Task Status Feature - Track task progress with status indicators",
"implementationContext": "Tasks are stored in a tasks table accessed via getTasksByProject() in the data-access layer. The API follows RESTful patterns under /api/tasks/. Auth uses existing tenant-scoped middleware. The status field should be an enum column with a database-level constraint. UI components use the existing TaskCard component in components/tasks/.",
"userStories": [
{
"id": "US-001",
"title": "Add status field to tasks table",
"description": "As a developer, I need to store task status in the database.",
"acceptanceCriteria": [
"Add status column: 'pending' | 'in_progress' | 'done' (default 'pending')",
"Generate and run migration successfully",
"Typecheck passes"
],
"priority": 1,
"passes": false,
"notes": ""
},
{
"id": "US-002",
"title": "Display status badge on task cards",
"description": "As a user, I want to see task status at a glance.",
"acceptanceCriteria": [
"Each task card shows colored status badge",
"Badge colors: gray=pending, blue=in_progress, green=done",
"Typecheck passes",
"Verify in browser using browser skill"
],
"priority": 2,
"passes": false,
"notes": ""
},
{
"id": "US-003",
"title": "Add status toggle to task list rows",
"description": "As a user, I want to change task status directly from the list.",
"acceptanceCriteria": [
"Each row has status dropdown or toggle",
"Changing status saves immediately",
"UI updates without page refresh",
"API returns 400 with descriptive error when status value is not in [pending, in_progress, done]",
"Status update is tenant-scoped (uses existing tenant middleware)",
"Typecheck passes",
"Verify in browser using browser skill"
],
"priority": 3,
"passes": false,
"notes": ""
},
{
"id": "US-004",
"title": "Filter tasks by status",
"description": "As a user, I want to filter the list to see only certain statuses.",
"acceptanceCriteria": [
"Filter dropdown: All | Pending | In Progress | Done",
"Filter persists in URL params",
"Typecheck passes",
"Verify in browser using browser skill"
],
"priority": 4,
"passes": false,
"notes": ""
}
],
"qaScenarios": [
{
"id": "QA-001",
"priority": "P0",
"category": "ux-flow",
"name": "User can toggle task status from list",
"given": "A task exists with status 'pending' on the task list",
"when": "User changes status to 'in_progress' via the dropdown",
"then": "Status updates immediately, UI reflects the change without page refresh",
"tracesTo": ["US-003"],
"derivedFrom": "spec",
"oracleType": "specified",
"route": "/tasks"
},
{
"id": "QA-002",
"priority": "P0",
"category": "error-state",
"name": "Invalid status value returns descriptive error",
"given": "A task exists in the system",
"when": "API receives an invalid status value via PUT /api/tasks/:id",
"then": "API returns 400 with message 'Invalid status. Allowed values: pending, in_progress, done'",
"tracesTo": ["US-003"],
"derivedFrom": "spec",
"oracleType": "specified"
},
{
"id": "QA-003",
"priority": "P1",
"category": "visual",
"name": "Status badge colors match spec for all states",
"given": "Tasks exist with each status value (pending, in_progress, done)",
"when": "User views the task list",
"then": "Badges show correct colors: gray=pending, blue=in_progress, green=done",
"tracesTo": ["US-002"],
"derivedFrom": "spec",
"oracleType": "derived",
"route": "/tasks"
}
]
}
前回の実行のアーカイブ
新しい spec.json を書き込む前に、別の機能向けのものが既に存在するか確認してください。
- 現在の
tmp/ship/spec.jsonが存在する場合は読み込みます branchNameが新しい機能のブランチ名と異なるか確認します- 異なり、かつ
tmp/ship/progress.txtにヘッダー以外の内容がある場合:- アーカイブフォルダー
tmp/ship/archive/YYYY-MM-DD-feature-name/を作成します - 現在の
tmp/ship/spec.jsonとtmp/ship/progress.txtをアーカイブにコピーします tmp/ship/progress.txtを新しいヘッダーでリセットします
- アーカイブフォルダー
フェーズ 1 のチェックリスト
spec.json を書き込む前に、以下を確認してください。
- 前回の実行をアーカイブ済み(
tmp/ship/spec.jsonが存在し、branchName が異なる場合は、最初にアーカイブする) - 各ストーリーが 1 回のイテレーションで完了できる(十分に小さい)
- ストーリーが依存関係の順に並んでいる(スキーマからバックエンド、UI の順)
- すべてのストーリーに基準として「Typecheck passes」がある
- UI ストーリーには基準として「ブラウザスキルを使用してブラウザで確認する」(ブラウザが利用可能な場合)、または Bash で検証可能な代替手段(
--no-browserの場合)がある - 受け入れ基準が検証可能で曖昧でない。機能基準は内部の仕組みではなく、観察可能な動作を記述している(/tdd を参照)
- 後続のストーリーに依存するストーリーがない
-
implementationContextを抽出済み(SPEC.md §8、§9、§10、§6 から — 簡潔な文章にし、コピー&ペーストしない) - SPEC.md §5 の失敗/復旧パスを、関連するストーリーの受け入れ基準に反映済み
- 非機能要件(SPEC.md §6)を、該当する場合に横断的な基準として適用済み
- qaScenarios[] を導出済み(SPEC.md の構造化されたセクションから — 各シナリオに id(QA-NNN)、given/when/then、tracesTo、oracleType がある)
フェーズ 2:準備
spec.json を検証し、実装プロンプトを作成して、実行用のファイルに保存します。
SPEC.md と照合して spec.json を検証する
各ユーザーストーリーを、SPEC.md の対応する要件と比較します。
- ストーリーの範囲が適切である(各ストーリーが 1 回のイテレーションで完了できる)
- ストーリーが適切な順序に並んでいる(依存関係を先にする)
- 受け入れ基準が具体的で検証可能である
- SPEC.md の要件が spec.json から漏れていない
- SPEC.md で求められている範囲を超えるストーリーがない
実行を開始する前に不整合を修正してください。ここでの誤りは、すべてのイテレーションを通じて累積します。
spec.json のスキーマを検証する
bun が利用可能な場合は、スキーマバリデーターを実行します。
bun <path-to-skill>/scripts/validate-spec.ts tmp/ship/spec.json
これにより、必須フィールド、ID 形式(US-NNN)、優先順位の連続性、重複の検出、「Typecheck passes」基準の有無など、構造上の整合性を確認します。外部依存関係はなく、bun がインストールされている環境ならどこでも実行できます。
bun が利用できない場合は、フェーズ 1 のスキーマに spec.json の構造が一致していることを手動で確認します。
spec.json を配置する
spec.json を tmp/ship/spec.json に配置します。tmp/ship/ が存在しない場合は作成します(mkdir -p tmp/ship)。
ブランチの安全性を確認する
main または master にいる場合は、続行前に警告してください。通常、implement スキルは機能ブランチで実行する必要があります。ブランチ運用モデルが存在しない場合(PR ワークフローのないコンテナ環境など)は、慎重に続行し、コミットが分離されていることを確認してください。
実装プロンプトを作成する
読み込み: templates/implement-prompt.template.md
このテンプレートには、{{PLACEHOLDER}} 構文を使用した完全なプロンプトのバリアントが 2 つあります。どちらか 1 つを選び、すべてのプレースホルダーを埋めてください。
バリアントの選択:
- バリアント A — SPEC.md のパスが利用可能な場合(直接指定されている場合、またはフェーズ 1 で取得した場合)
- バリアント B — spec.json のみ利用可能な場合(SPEC.md がない場合)
条件分岐は反復プロンプトではなく、フェーズ 2 の構築時に行います。反復エージェントが受け取るのは、条件分岐のない単一のワークフローです。両方のバリアントを含めたり、「仕様が利用可能な場合は」といった条件分岐のロジックを含めたりしないでください。
{{CODEBASE_CONTEXT}} を埋める: 変更対象の領域に固有のパターン、共通の用語、抽象化を含めてください。一般的な CLAUDE.md のガイダンスよりも、具体的で実行に役立つ内容にします。例:「API は /api/tasks/ 配下で RESTful パターンに従います」「認証には auth.ts のテナントスコープのミドルウェアを使用します」「データアクセスには data-access/ のリポジトリパターンを使用します」。また、反復エージェントに必要な CLAUDE.md のリポジトリ規約(テストパターン、ファイルの配置場所、フォーマットなど)も含めてください。
品質ゲートのコマンドを埋める: Inputs のコマンドを使用します(デフォルト:pnpm typecheck、pnpm lint、pnpm test --run)。指定されている場合は、--typecheck-cmd、--lint-cmd、--test-cmd で上書きします。
{{SPEC_PATH}} を埋める(バリアント A のみ):作業ディレクトリからの相対パスを使用します(例:.claude/specs/my-feature/SPEC.md)。相対パスは実行環境(ホスト、Docker、worktree)をまたいで使用できます。絶対パスは使用しないでください。別の環境でプロンプトを実行すると機能しなくなります。仕様の内容をプロンプトに埋め込まないでください。反復エージェントは、各反復で Read ツールを使って読み込みます。
コードベースのコンテキストを独立したファイルとして保存する
後続の利用者(修正プロンプト、レビュアー)が参照できるよう、埋めた {{CODEBASE_CONTEXT}} の内容も tmp/ship/codebase-context.md に保存してください。
mkdir -p tmp/ship
# Write codebase context as standalone file (same content that gets inlined in implement-prompt.md)
古い実行成果物をクリーンアップする
新しい成果物を書き込む前に、以前の実行で生成された成果物を削除してください。これらのファイルは毎回すべて置き換えられます。Write ツールの「ファイルが未読」ガードにより、既存ファイルを上書きできず、処理の停滞と再試行が発生します。
rm -f tmp/ship/implement-prompt.md tmp/ship/codebase-context.md
プロンプトを保存する
作成した実装プロンプトを tmp/ship/implement-prompt.md に保存してください。このファイルは、自動実行ではフェーズ 3(scripts/implement.sh)が使用し、手動で反復する場合(claude -p)はユーザーが使用します。
Docker 実行用に implement.sh をコピーする(Docker のみ)
--docker が渡された場合は、コンテナがバインドマウント経由でアクセスできるように、scripts/implement.sh を tmp/ship/implement.sh にコピーしてください。
cp <path-to-skill>/scripts/implement.sh tmp/ship/implement.sh
chmod +x tmp/ship/implement.sh
ホストで実行する場合は、この手順をスキップしてください。 ホスト上のフェーズ 3 は、スキルディレクトリから scripts/implement.sh を直接呼び出すため、コピーは不要です。コピーが必要なのは、プラグインキャッシュのパスにアクセスできない Docker コンテナのみです(references/execution.md を参照)。
フェーズ 2 のチェックリスト
- spec.json が SPEC.md と照合して検証済み(利用可能な場合)
- spec.json のスキーマを検証済み(bun が利用可能な場合は
scripts/validate-spec.tsを使用) - ストーリーのスコープと順序が適切で、検証可能な基準が設定されている
- 正しいバリアント(A または B)を使用してテンプレートから実装プロンプトを作成済み
- すべての
{{PLACEHOLDERS}}を入力済み(仕様のパス、品質ゲート、コードベースのコンテキスト) - 保存したプロンプトに完了シグナルが含まれている(テンプレートに含まれています。誤って削除されていないことを確認してください)
- コードベースのコンテキストを
tmp/ship/codebase-context.mdに保存済み - プロンプトを
tmp/ship/implement-prompt.mdに保存済み -
implement.shをtmp/ship/implement.shにコピーし、実行可能に設定済み(Docker のみ。ホストで実行する場合はスキップ)
フェーズ 3:実行
scripts/implement.sh を使って反復ループを実行します。各反復では、新しい Claude Code サブプロセスを起動します。すべての機能を利用できますが、反復間でコンテキストは共有されません。
読み込み: references/execution.md
ステップ 1:依存関係とビルド環境を確認する
イテレーションを開始する前に、作業ディレクトリに正常に動作する開発環境があることを確認してください。イテレーションエージェントが品質ゲートを実行するには、依存関係がインストールされ、ビルドが動作している必要があります。
package.jsonのpackageManagerフィールド(例:[email protected])からパッケージマネージャーを特定します。特定のバージョンが固定されている場合は、ロックファイルの不整合を避けるため、npx <pm>@<version> installを使用してください。node_modules/がないか、古くなっている場合は、依存関係をインストールします:# Example for pnpm-pinned repos: npx pnpm@<version> install- リポジトリのルートに
conductor.jsonがある場合は、conductor のセットアップを実行します。 - ビルドに問題がないことを確認します:
型チェックが失敗した場合は、既存の問題です。記録しますが、処理を止めないでください。イテレーションループで修正できる場合があります。<typecheck-cmd> # e.g., pnpm typecheck
このステップは冪等です。依存関係がすでにインストールされ、ビルドに問題がなければ、すぐに完了します。Docker 内で実行する場合(--docker)は、コンテナイメージに環境が用意されているため、このステップ全体をスキップしてください。
ステップ 2:Claude CLI を確認する
自動実行が可能かどうかを確認します:
env -u CLAUDECODE -u CLAUDE_CODE_ENTRYPOINT claude --version
失敗した場合、自動実行は利用できません。以下のフォールバックに進んでください。
ステップ 3:実行環境を選択する(ホストまたは Docker)
--docker が渡されていない場合: ホスト上で実行します(デフォルト)。ステップ 4 に進んでください。
--docker が渡されている場合: Docker を使用して実行します。
-
Compose ファイルを解決します。 パスが指定されている場合(例:
--docker .ai-dev/docker-compose.yml)は、そのファイルを使用します。指定されていない場合は、リポジトリ内を検索して、sandboxサービスを定義している**/docker-compose.ymlまたは**/compose.ymlファイルを探します。最初に見つかったファイルを使用します。見つからない場合は、次のエラーを表示します:"No compose file with a sandbox service found in this repo." -
コンテナが実行中であることを確認します:
docker compose -f <compose-file> ps --status running sandbox実行中でない場合は、
docker compose -f <compose-file> up -dで起動します。 -
続行します。ステップ 6 では Docker 用の実行方法を使用します。
ステップ 4:実行前の品質ゲート基準値を取得する
イテレーションループを開始する前に、品質ゲートを実行して基準値を取得します:
<typecheck-cmd> # e.g., pnpm typecheck
<lint-cmd> # e.g., pnpm lint
<test-cmd> # e.g., pnpm test --run
いずれかのゲートが失敗した場合、オペレーターに次の警告を表示します:"Quality gates are failing before implementation starts. Pre-existing failures will cost iterations to diagnose. Consider fixing them first."
結果にかかわらず、基準値を tmp/ship/progress.txt に記録します:
## Pre-execution baseline - [timestamp]
- Typecheck: PASS/FAIL
- Lint: PASS/FAIL
- Test: PASS/FAIL
実行を止めないでください。オペレーターは、失敗を修正するために /implement を実行している可能性があります。ただし、基準値を記録しておけば、イテレーションエージェントは既存の失敗と、自身が引き起こしたリグレッションを区別できます。
ステップ 5:implement.sh を実行する
Bash ツールの 600 秒のタイムアウトを避けるため、バックグラウンドで実行します。モデルの実行回数に上限を設けず、--max-iterations は設定しないでください。イテレーションループには、ストーリーの完了(完了シグナル)、行き詰まったストーリー(3 回失敗したら次に進む)、コンテキストの枯渇(サブプロセスが終了し、次のイテレーションが新たに開始する)といった自然な停止条件があります。進行中の実行が人為的な上限によって打ち切られてしまいます。
ホストでの実行(デフォルト):
Bash(command: "<path-to-skill>/scripts/implement.sh --force",
run_in_background: true,
description: "Implement execution run 1")
Docker での実行(--docker が渡されている場合。Compose ファイルはステップ 3 で解決済み):
Bash(command: "docker compose -f <compose-file> exec sandbox tmp/ship/implement.sh --force",
run_in_background: true,
description: "Implement Docker execution run 1")
対話型プロンプトに応答する TTY がないため、必ず --force を渡してください。
バックグラウンドの Bash 呼び出しは、タスク ID と出力ファイルのパスを返します。implement.sh が完了すると、<task-notification> が自動的に届きます。TaskOutput を使ってポーリングしないでください(非推奨)。通知を待つ間は、仕様の再読やタスクリストの確認など、軽い作業を行ってください。ただし、競合する可能性のあるコード変更は行わないでください。実行中に進捗を確認する必要がある場合は、出力ファイルのパスまたは tmp/ship/progress.txt を直接 Read してください。
実装には時間がかかります。各イテレーションでは、ユーザーストーリーに取り組むため、Claude Code の完全なサブプロセスが起動します。所要時間の目安:
| 機能の複雑さ | 所要時間の目安 |
|---|---|
| 小規模(ストーリー 1~3 件) | 合計 10~20 分 |
| 中規模(ストーリー 4~8 件) | 合計 30~60 分 |
| 大規模(ストーリー 9 件以上) | 合計 60~120 分 |
ステップ 7:結果を評価する
implement.sh の完了後、tmp/ship/spec.json と tmp/ship/progress.txt を読みます。
- すべてのストーリーが
passes: true→ 実行は成功です。フェーズ 3 のチェックリストに進みます。 - 未完了のストーリーがある →
tmp/ship/progress.txtでブロッカーを確認します。行き詰まったストーリーへの対処(references/execution.mdを参照)を行ってから、implement.sh を再度実行します。 - implement.sh がエラーで終了した → 詳細を確認するため、出力を読みます。一時的な原因(ネットワーク、レート制限)であれば、1 回だけ再試行します。解消しない場合は、手動の手順に切り替えます。
ステップ 8:行き詰まったストーリーへの対処(実行の合間)
同じブロッカーが原因で、同じストーリーが implement.sh の連続 2 回の実行で失敗した場合:
- ストーリーの規模が大きすぎる → spec.json で、より小さなストーリーに分割します
- 受け入れ基準が曖昧 → より具体的になるよう、基準を書き直します
- 外部依存関係がブロッカーになっている → ストーリーをスキップし、ブロッカーを説明する
notesを設定します - 実装方法が適切でない → 別の方法を提案するガイダンスを
tmp/ship/progress.txtに追加します - コードの不具合がストーリーのブロッカーになっている(テスト失敗、実行時エラー、イテレーションエージェントが解決できない型エラー) →
/debugスキルを読み込み、実行の合間に根本原因を診断します。修正を適用してから、implement.sh を再度実行します。
同じストーリーで連続 3 回失敗したら、停止してユーザーに相談します。
対処を行った後、implement.sh を再度実行します。ユーザーにエスカレーションするまでに実行できる implement.sh の回数は、合計最大 3 回です。
フォールバック:Claude CLI を利用できない場合
ステップ 1 での Claude CLI の確認に失敗した場合、自動実行はできません。それでも /implement はフェーズ 1〜2 を通じてすべての価値を提供します。成果物は準備できています。
ユーザーに以下を伝えます。
- 実装プロンプトが
tmp/ship/implement-prompt.mdに保存されていること - イテレーションループを使って手動で実行するには、スクリプトをコピーして実行すること:
cp <path-to-skill>/scripts/implement.sh tmp/ship/implement.sh && chmod +x tmp/ship/implement.sh tmp/ship/implement.sh --force
フェーズ 3 のチェックリスト
-
tmp/ship/spec.jsonのすべてのストーリーがpasses: trueである(または、行き詰まったストーリーについてnotesに記録されている) -
tmp/ship/progress.txtを確認済み — 未解決のブロッカーがない - 品質ゲートを通過している:typecheck、lint、test
フェーズ 3 の後:
/shipの一部として実行した場合:Ship は実装後のレビューとテストを続行します。- 単独で実行した場合:作成または変更されたファイルをすべて読みます。実装結果は出発点であり、終着点ではありません。品質ゲートを手動で実行します。