mcpField
A
aep-dispatch

aep-dispatch

github.com/memorysaverエージェントワークフロー1858 回インストール6 週間前に更新
リポジトリ

aep-dispatch について

aep-dispatchは、プロダクトのストーリーを機能開発ワークフローに振り分ける対話型エージェントスキルです。ワークスペースの状態を同期し、実行可能なストーリーを評価して、OpenSpecのコンテキストを組み立て、設計または起動工程へ引き継ぎます。

主な機能

  1. 01ワークスペースのシグナルから状態を同期
  2. 02依存関係を処理して準備状況を判定
  3. 03実行可能なストーリーを採点・順位付け
  4. 04コンテキストパッケージ付きOpenSpec変更を作成
  5. 05設計または起動工程へ振り分け

活用シーン

  1. 01次に開発するプロダクトストーリーを選定
  2. 02WIP制限内で実行可能なストーリーを割り当て
  3. 03エージェント向けの実装コンテキストを準備

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/memorysaver/agentic-engineering-patterns --skill aep-dispatch

インストール後、Claude Code で/aep-dispatchを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
.aep-generated
context-assembly.md
file-resolution.md
scoring.md
workflow-mode.md
yaml-guardrails.md

詳細

ディスパッチ

プロダクトコンテキスト(コントロールプレーン)と機能ライフサイクル(実行プレーン)をつなぎます。ワークスペースの状態を同期し、ストーリーをスコアリングし、次に構築するものを選び、コンテキストを組み立てて、/aep-design または /aep-launch に引き継ぎます。

この機能の位置付け:

/aep-envision → /aep-map → /aep-model (UI-facing) → /aep-scaffold
  → [ /aep-dispatch → /aep-design → /aep-launch → /aep-build → /aep-wrap ]
       ▲ you are here
  → /aep-reflect → loop

セッション: メイン、対話型
入力: product/index.yaml(分割モード)または product-context.yaml(v1 モード)のプロダクト定義、product-context.yaml の運用状態
出力: コンテキストを事前に組み立てた OpenSpec 変更、更新されたストーリーの状態、/aep-design または /aep-launch への引き継ぎ

自律的なオーケストレーションの場合: 代わりに /aep-autopilot を使用してください。Autopilot は、/loop を介したティックベースのステートマシンとして、ディスパッチ、起動、監視、レビュー、終了、ディスパッチのサイクル全体を実行します。Dispatch は引き続き、単一パスの対話型ツールです。

Claude Code で手動操作なしのバッチ処理を行う場合: 波を 「ワークフロー付き」 でディスパッチすると、波全体を 1 つの動的ワークフローとして構築します(ステップ 5 → 動的ワークフロー)。


開始前

プロダクトコンテキストがどのモードかを確認します。

ls product/index.yaml 2>/dev/null && echo "SPLIT MODE" || echo "V1 MODE"
cat product-context.yaml

モードの意味は references/file-resolution.md で規定されています。Dispatch は product/index.yaml(分割モード)または product-context.yaml(v1 モード)からプロダクト定義を読み取り、運用状態(ストーリー、トポロジー、アーキテクチャ、コスト、変更履歴)は常に product-context.yaml から読み書きします。

product-context.yaml が存在しない場合は、まず /aep-envision、次に /aep-map を実行します。stories セクションが空の場合は、/aep-map を実行してプロダクトを分解します。


ディスパッチプロトコル

すべてのディスパッチ実行は、同じ 7 ステップのプロトコルに従います。各ステップは冪等です。状態に変更がないまま /aep-dispatch を 2 回実行しても、同じ結果になります。ストーリーの状態(pending / ready / blocked / in_progress / in_review / completed / failed / deferred)は、product-context スキーマに従います。

① SYNC signals    → bring YAML up to date with workspace reality
② CASCADE states  → compute all pending→ready, pending→blocked transitions
③ SCORE stories   → rank the ready queue by dispatch_score
④ PRESENT queue   → show user the scored dispatch queue
⑤ DISPATCH        → lock stories (status→in_progress), create OpenSpec changes
⑥ MONITOR         → agents work, main session watches signals
⑦ COMPLETE        → /aep-wrap updates YAML, atomic cascade, re-invoke dispatch

ステップ 1:シグナルの同期

何かを計算する前に、ワークスペースのシグナルを YAML に同期します。YAML が古いままだと、すでに完了したストーリーが in_progress と表示されたり、実際には準備ができている後続ストーリーが pending のままになったりします。

状態が in_progress または in_review の各ストーリーについて、 .feature-workspaces/<story.assigned_to>/.dev-workflow/signals/status.json を読み取り、レコードをストーリーにコピーします。signal.story_status を story.status に反映し、completed の場合は completed_at / pr_url / cost_usd を、in_review の場合は pr_url を反映します。また、failed の場合は failure_log を story.failure_logs に追加します。シグナルファイルがないストーリーは、そのままにします。シグナルの形式は /aep-launch → references/signals-spec.md で規定されています。

事後条件: in_progress / in_review のすべてのストーリーで、YAML の状態がシグナルファイルと一致していること。


ステップ 2:状態遷移の連鎖

すべてのシグナルを同期した後、1 回の処理ですべての状態遷移を計算します。

For each story with status: pending:
  If any story in dependencies[] has status: failed:
    Transition → blocked
  Elif any story in dependencies[] has status: deferred:
    Transition → blocked (dependency deferred)
  Elif all stories in dependencies[] have status: completed:
    Transition → ready

For each story with status: blocked:
  If the blocking dependency is now completed:
    Transition → pending (will be re-evaluated in this same pass)

これは依存関係のゲートです。ストーリーが ready になるのは、すべての依存先が completed になった場合のみです。そのため、未充足の依存関係があるストーリーがディスパッチ可能になることはありません。

復旧時の遷移(ユーザーが開始し、要求された場合に処理):

  • failed → pending — 仕様を修正した後、ユーザーがリセットする
  • deferred → pending — ユーザーがストーリーの保留を解除する

すべて更新した後、YAML を検証します。

npx js-yaml product-context.yaml > /dev/null && echo "YAML OK"

検証に失敗した場合は、先に YAML を修正します(よくある修正方法については references/yaml-guardrails.md を参照してください)。

スコアを計算する前に、同期・連鎖処理後の状態を YAML にコミットし、dispatch_epoch をインクリメントします。

事後条件: npx js-yaml が終了コード 0 で終了し、連鎖処理後の状態がコミットされていること。


ステップ 3:ストーリーのスコアリング

アクティブレイヤーの判定
For each layer (0, 1, 2, ...):
  If any story in this layer has status not in [completed, deferred]:
    This is the active layer. Stop.

レイヤーゲートの確認: アクティブレイヤーが 0 より大きい場合は、layer_gates[active_layer - 1].status == passed であることを確認します。そうでない場合は処理をブロックし、レイヤーゲートの実行を提案します。ゲートが scripted_passed の状態(Tier-1 の仕組みは正常だが、ジャーニーのドッグフーディング/カバレッジの半分が未完了)の場合、次のレイヤーのブロックは解除されません。残りの半分を人が把握できるよう、「仕組みは正常、ドッグフーディングは保留中」と報告します。ゲートを passed に進めるのは、/aep-wrap の二段階切り替えのみです。

準備完了キューをフィルタリングする

アクティブなレイヤーにある ready ストーリーのうち、進行中の作業とファイルレベルの競合がないものだけをディスパッチします。

For each ready story:
  For each in_progress story:
    If files_affected intersection is non-empty:
      Mark as conflicted — cannot dispatch until the in_progress story completes
スコアを計算する

残りの各準備完了ストーリーについて、references/scoring.md に従って readiness_score と dispatch_score を計算し、両方をストーリーの YAML に記入します。

  • readiness_score(0~1)=仕様の完全性。ステップ 7 のルーティングに使用します。
  • dispatch_score =(ビジネス価値+ブロック解除の可能性+クリティカルパスの緊急度+再利用による効果)/(複雑さのコスト+曖昧さのペナルティ+インターフェースのリスク)。キュー内の順位付けに使用します。

change_group を共有するグループ化された変更(compile_mode: grouped_change)は、1 つの単位としてスコアを計算し、ディスパッチします。references/scoring.md → グループ化された変更のディスパッチを参照してください。

事後条件: すべての準備完了ストーリーの YAML に readiness_score と dispatch_score が記入されています。


ステップ 4:ディスパッチキューを提示する

コンテキストとともに、ソート済みのキューを表示します。最上位のストーリーを強調し、その理由(最高スコア=クリティカルパス+高い価値+最も多くのブロックを解除)を説明します。ストーリーごとに 1 行とし、競合/ブロック中/進行中のセクションも含めます。

Dispatch Queue (Layer 0 — 4 ready, 2 in_progress, WIP 3/5)

  1. ★ PROJ-003 "Setup auth middleware"           score: 14.5
     [high] S | Module: auth | Wave 1 | Critical path | Shared enabler
     Unblocks: PROJ-005, PROJ-007, PROJ-008
     → Readiness: 0.9 — skip to /aep-launch

  Conflicted (waiting):  • PROJ-006 — files overlap with in_progress PROJ-002
  Blocked (deps unmet):  • PROJ-008 — waiting on PROJ-003 (auth middleware)
  In progress:           • PROJ-001 (tab: feat-api-scaffold) — Phase 4, 60%

ステップ 5:ディスパッチする

ディスパッチモード
  • インタラクティブ(デフォルト) — ユーザーがストーリーを 1 つずつ選択します。初期レイヤーやシステムの学習に最適です。
  • ウェーブバッチ(--batch wave) — 現在のウェーブにある準備完了ストーリーをすべて一度にディスパッチします(WIP 制限内)。/aep-launch 経由で N 個のワークスペースを作成します。
  • ダイナミックワークフロー(--batch wave +「…ワークフローで」) — ホストが Workflow ツールを備えた Claude Code で、かつユーザーがワークフローを要求した場合、バッチをワークフローモード(ロックされたストーリーごとに 1 つのエージェントを割り当てる動的ワークフローを 1 つ)にルーティングします。N 個の /aep-launch ワーカーは使用しません。references/workflow-mode.md を読み、マシンが組み立てる STEP-0 ブリーフの要件(古いベースによる危険性)と、/aep-launch を迂回する際にディスパッチが行う必要のあるモードの告知を確認してください。
WIP 制限
max_wip = topology.routing.concurrency_limit  (default: 5)
current_wip = count of stories with status: in_progress
available_slots = max_wip - current_wip

available_slots 件を超えてストーリーをディスパッチしないでください。この上限は、ダイナミックワークフローを含むすべてのモードで適用されます。available_slots が保護するのは、統合/マージのボトルネック(通常はエージェントの速度ではなく、人による PR レビュー)です。リトルの法則では Lead Time = WIP / Throughput となるため、処理能力を超えてディスパッチすると、速度が上がるのではなく渋滞が発生します。

ゲート: available_slots > 0 の間はディスパッチします。0 の場合、WIP 制限が答えです。

ディスパッチロック

選択した各ストーリーを、次の手順でアトミックにディスパッチします。

1. Re-read story.status from YAML (not from cache)
2. If status != ready → SKIP (already dispatched by another run)
3. Write to YAML:
     status: in_progress
     assigned_to: <workspace-name>
     openspec_change: <story-id>
     started_at: <ISO 8601 now>
     dispatched_at_epoch: <current dispatch_epoch>
4. Commit YAML immediately (this IS the lock)
5. THEN create OpenSpec change and workspace

ワークスペースを作成する前にコミットすることで、2 回目の実行が安全になります。1 回目の実行で in_progress を書き込んでコミットし、2 回目の実行では in_progress を読み取ってスキップします。

機械的な順序不変条件[lock-before-workspace]。 ディスパッチを拡張するプロジェクトでは、この順序を型付きゲートの背後に置きます。ゲートで使用する動詞は、[story-not-ready]/[dependencies-completed] を名前で指定して拒否します。aep-autopilot の references/deterministic-orchestration.md を参照してください。


ステップ 6:コンテキストパッケージを含む OpenSpec 変更を作成する

ディスパッチする各ストーリーについて、OpenSpec 変更 openspec/changes/<story-id>/ を作成します。内容は proposal.md、design.md、specs/<module>.md、tasks.md、および .context/ パッケージ(stable-prefix.md、dependencies.md、retrieval.md)です。仕様が十分に定義されたストーリーであっても、必ず OpenSpec 変更を作成してください。エージェントが読み取るのは .context/ ディレクトリです。

references/context-assembly.md に従ってハンドオフパッケージを組み立て、トポロジーで定められたロールのトークン予算に合わせて内容を絞り込みます。このパッケージには、ストーリーの暫定検証ティア(導出方法は context-assembly.md に記載)が含まれます。確定する再導出はビルド側が担当します。/aep-build は Phase 5 の開始時に実際の差分から再導出し、ティアは引き上げのみ可能です。

組み立て時のディスパッチ阻止ゲート: キャリブレーションが必要なストーリー(calibration_type が設定されている、または .5 のアライメントレイヤー — 概念の正規定義は /aep-map の references/alignment-layers.md)では、calibration/<type>.yaml が存在する必要があります。存在しない場合は /aep-calibrate にルーティングします。UI に関わるストーリー(object_model_refs、calibration_type が {visual-design, ux-flow} のいずれか、または ui 種別のモジュール)では、そのストーリーをカバーする approved 状態の Object Map が必要です。存在しない場合は /aep-model にルーティングします。両方のゲートの詳細は references/context-assembly.md に記載されています。いずれかのゲートを通過できない場合は、ディスパッチしないでください。

事後条件: ディスパッチした各ストーリーに対して、openspec/changes/<story-id>/.context/ が存在すること。


ハンドオフ前にコミットしてプッシュする

すべてのディスパッチ成果物(YAML の更新、OpenSpec 変更、変更履歴)を /aep-launch に引き渡す前にリモートへプッシュしてください。ワークスペース PR がインテグレーションブランチにマージされてリベースすると、ローカルにしかないディスパッチコミットは失われます。

changelog セクションに追記します。

- date: <today>
  type: dispatch
  author: human
  summary: "Dispatched PROJ-003 (auth middleware), PROJ-004 (user model) — Layer 0, Wave 1"
  sections_changed: [stories]

次に、/aep-git-ref の「Control-Plane Commits」に従ってコミットしてプッシュします。git add product-context.yaml openspec/changes/ を実行し、コミット(feat: dispatch <ids> — Layer N Wave M)を作成して、$BASE にプッシュします($BASE は /aep-git-ref の「Resolving $BASE」に従って解決します)。

事後条件: ディスパッチコミットが origin/$BASE に存在すること。プッシュに失敗した場合(リモートの競合)、ワークスペースを起動する前に解決してください。


ステップ 7:引き渡す

通常、起動モードはここではなく /aep-launch で決定します。 デフォルトの パスでは、ディスパッチは実行方式に依存せず、仕様が十分に定義された変更を /aep-launch に渡します。/aep-launch はホストを検出し、aep-executor を 介してモードを選択します。 唯一の例外は、ステップ 5 の Dynamic Workflow オプトインです。 このパスでは、 /aep-launch を経由せず、ディスパッチから直接 workflow モードを実行するため、 その場合のモード選択と告知はディスパッチ自体が担当します。

ステップ 3 で算出した readiness_score のバンドに基づいてルーティングします。バンドの定義は references/scoring.md § Routing Thresholds が正規の定義元です。このセクションでは、対話的なアクションのみを定めます。

  • dispatch-ready → /aep-launch に進みます
  • borderline → /aep-launch と /aep-design のどちらにするかをユーザーに提示します
  • under-specified → /aep-design にルーティングします
full-auto / auto-design ルーティング(準備度が中または低の場合)

borderline または under-specified のストーリーのルーティングは、topology.routing の 2 つのフラグ、すなわち full_auto マスタースイッチ(デフォルトは false)と、より細かい制御を行う auto_design(デフォルトは false)に応じて決まります。full_auto は auto_design より上位です。full_auto: true は auto_design: true を意味します。

  • full_auto: true または auto_design: true → 対話型の /aep-design にエスカレーションする代わりに、非対話型の生成/評価デザインリゾルバー(人間を介さずに仕様を精緻化してから /aep-launch にルーティングするデザインエージェント)でストーリーを解決します。戦略的な一時停止はありません。
  • full_auto: false かつ auto_design: false(デフォルト) → 起動前に人間がデザインを精緻化できるよう、対話型の /aep-design にルーティングします。「何を作るか」という戦略的なゲートは、人間が引き続き担当します。

単一ストーリーのハンドオフ例:

Story PROJ-003 dispatched (score: 14.5, critical path, shared enabler).
OpenSpec change: openspec/changes/PROJ-003/   Context: .../.context/
Recommendation: Readiness 0.9 — well-specified → /aep-launch
  /aep-launch    ← start building immediately
  /aep-design    ← refine the spec first
バッチハンドオフ

バッチでディスパッチする場合は、/aep-launch を使ってすべてのワークスペースを作成します。

Batch dispatched: PROJ-003 (score 23.0), PROJ-004 (score 12.0)
  /aep-launch PROJ-003  → tab: auth-middleware
  /aep-launch PROJ-004  → tab: user-model

エッジケース

  • 準備できているストーリーがない場合: すべての保留中ストーリーに未解決の依存関係があります。in_progress のストーリーが停滞していないか(attempt_count が多い、started_at が古い)を確認してください。ワークスペースの進捗を確認するか、/aep-reflect を実行することを提案します。
  • アクティブなレイヤーのすべてのストーリーが完了した場合: レイヤーゲートテストを実行します。合格したら次のレイヤーに進み、ディスパッチを再実行します。
  • すべてのレイヤーのすべてのストーリーが完了した場合: プロダクトは完成です。最終レビューとして /aep-reflect を提案します。
  • レイヤーゲートに失敗した場合: 失敗内容から修正ストーリーを作成し、現在のレイヤーに追加して、ディスパッチを再実行します。ゲートに合格するまで、レイヤーはオープンのままです。
  • WIP 上限に達した場合: 利用可能な枠はありません。進行中の内容を表示し、枠を空けるために待つか PR をレビューすることを提案します。

コメント