mcpField
A
aep-dispatch

aep-dispatch

github.com/memorysaverAgent 工作流1858 次安装6 周前更新
代码仓库

关于 aep-dispatch

aep-dispatch 是一项交互式 Agent 技能,可将产品故事送入功能开发流程。它同步工作区状态、处理依赖并为可执行故事评分,随后组装 OpenSpec 上下文并交接给设计或启动步骤。

主要功能

  1. 01从工作区信号同步故事状态
  2. 02处理依赖并判断就绪状态
  3. 03为就绪故事评分排序
  4. 04创建含上下文包的 OpenSpec 变更
  5. 05将故事交接至设计或启动步骤

适用场景

  1. 01选择下一项待开发的产品故事
  2. 02在 WIP 限制内分派就绪故事
  3. 03为 Agent 准备实现上下文

安装

复制下面的命令,在终端中运行。

$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

详细介绍

Dispatch

连接产品上下文(控制平面)与功能生命周期(执行平面)。同步工作区状态、评估 Story、选择下一步构建内容、组装上下文,并转交给 /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

会话: Main,交互式
输入: 来自 product/index.yaml(拆分模式)或 product-context.yaml(v1 模式)的产品定义;来自 product-context.yaml 的运行状态
输出: 预先组装好上下文的 OpenSpec 变更、已更新的 Story 状态,以及转交给 /aep-design 或 /aep-launch

用于自主编排: 请改用 /aep-autopilot。Autopilot 通过 /loop,以基于 tick 的状态机运行完整的 dispatch-launch-monitor-review-wrap-dispatch 循环。Dispatch 仍是单次交互式工具。

在 Claude Code 下实现免操作批处理: 使用“with workflow”分派一个波次,将整个波次构建为一个动态工作流(Step 5 → Dynamic Workflow)。


开始之前

探查产品上下文所处的模式:

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 读取/写入运行状态(Story、拓扑、架构、成本、变更日志)。

如果 product-context.yaml 不存在,请先运行 /aep-envision,然后运行 /aep-map。如果 stories 部分为空,请运行 /aep-map 来拆解产品。


Dispatch 协议

每次 dispatch 运行都遵循相同的 7 步协议。每一步都是幂等的——如果状态没有变化,连续运行两次 /aep-dispatch 会产生相同结果。Story 状态(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

Step 1:信号同步

在计算任何内容之前,先将工作区信号同步到 YAML 中——过时的 YAML 会将已完成的 Story 显示为 in_progress,并在下游 Story 实际已就绪时仍将其保留为 pending。

对于状态为 in_progress 或 in_review 的每个 Story,读取 .feature-workspaces/<story.assigned_to>/.dev-workflow/signals/status.json,并将记录复制 到该 Story 中:signal.story_status → story.status;当状态为 completed 时,还需复制 completed_at / pr_url / cost_usd;当状态为 in_review 时,复制 pr_url;当状态为 failed 时,将 failure_log 追加到 story.failure_logs。如果 Story 的信号文件不存在,则保持 原样。信号结构以 /aep-launch → references/signals-spec.md 中的定义为准。

后置条件: 每个状态为 in_progress/in_review 的 Story,其 YAML 状态都与信号文件一致。


Step 2:级联状态转换

同步完所有信号后,一次性计算所有状态转换:

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)

这是依赖门控:只有当某个 Story 的所有依赖均为 completed 时,它才会变为 ready,因此依赖未满足的 Story 永远不会被分派。

恢复转换(由用户发起,按需处理):

  • failed → pending — 用户修复规格后重置
  • deferred → pending — 用户取消对 Story 的延期

所有更新完成后,验证 YAML:

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

如果验证失败,请在继续之前修复 YAML(常见修复方法见 references/yaml-guardrails.md)。

在计算分数之前,将同步并级联后的状态提交到 YAML,并递增 dispatch_epoch。

后置条件: npx js-yaml 以 0 退出,且级联后的状态已提交。


Step 3:评估 Story

确定活动层
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 机制正常,但旅程 dogfood / 覆盖率部分尚未完成)不会解锁下一层——请报告为“机制正常,dogfood 待完成”,以便用户了解剩余部分。只有 /aep-wrap 的两阶段切换会将门控推进到 passed。

筛选就绪队列

仅调度活动层中处于 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)作为一个单元评分和调度——参见 references/scoring.md → Grouped Change Dispatch。

后置条件: 每个就绪故事的 YAML 中都写入了 readiness_score 和 dispatch_score。


步骤 4:展示调度队列

展示按顺序排列的队列及其上下文。突出显示排名第一的故事并说明原因(最高评分 = 关键路径 + 高价值 + 解锁最多)。每个故事占一行,并附上冲突 / 阻塞 / 进行中部分:

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:调度

调度模式
  • 交互模式(默认) — 用户一次选择一个故事。适合早期层,或用于熟悉系统。
  • 波次批处理(--batch wave) — 一次调度当前波次中的所有就绪故事(不超过 WIP 限制),通过 /aep-launch 创建 N 个工作区。
  • 动态工作流(--batch wave + “...with workflow”) — 当宿主是带有 Workflow 工具的 Claude Code 且用户要求使用工作流时,通过工作流模式调度批次(一个动态工作流,每个锁定的故事对应一个 Agent),而不是创建 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 审查,而非 Agent 速度):根据利特尔法则,Lead Time = WIP / Throughput,因此超出容量调度只会造成拥堵,而不会提升速度。

门控条件: 当 available_slots > 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

提交发生在创建工作区之前,因此第二次运行是安全的:运行 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 变更——Agent 读取的是 .context/ 目录。

按照 references/context-assembly.md 组装交接包,并根据拓扑中的角色令牌预算进行精简。该包附带故事的暂定验证等级(推导方式见 context-assembly.md);最终生效的重新推导由构建阶段负责——/aep-build 在第 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/ 均已存在。


交接前提交并推送

在移交给 /aep-launch 之前,将所有分派产物(YAML 更新、OpenSpec 变更、变更日志)推送到远程:仅保留在本地的分派提交会在工作区 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(按照 /aep-git-ref 中的 “Resolving $BASE” 解析 $BASE)。

**后置条件:**分派提交已存在于 origin/$BASE 上——若推送失败(远程冲突),请在启动工作区之前解决冲突。


步骤 7:移交

**启动模式通常在 /aep-launch 确定,而非在此处确定。**默认 路径中的分派与执行器无关——它会将规格完善的变更移交给 /aep-launch,由其检测宿主环境,并通过 aep-executor 选择模式。 **唯一例外是选择加入的 Dynamic Workflow(步骤 5):**该路径从分派阶段起就以 workflow 模式运行,绕过 /aep-launch,因此在此情况下由分派本身负责 模式选择和公告。

根据步骤 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 路由(准备度中等或偏低)

边界或规格不足的故事如何路由,取决于两个 topology.routing 标志——full_auto 主开关(默认 false)和更细粒度的 auto_design(默认 false)。full_auto 的优先级高于 auto_design: full_auto: true 表示 auto_design: true。

  • full_auto: true 或 auto_design: true → 使用非交互式 gen/eval 设计解析器处理故事(由设计 Agent 在没有人工参与的情况下完善规格,然后路由至 /aep-launch),而不是升级到交互式 /aep-design。不设置策略暂停点。
  • 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 以释放名额。

评论

支持 Markdown