关于 aep-build
aep-build 是在隔离 Git worktree 中自主实现功能的开发技能,依据 OpenSpec 任务逐项编码、提交、审查、测试并处理 PR。它通过进度文件和验证流程跟踪任务,且在人工判断关卡处升级处理。
主要功能
- 01在隔离 worktree 中实现
- 02按任务逐项提交代码
- 03生成进度与验证记录
- 04代码审查和测试
- 05创建并处理 PR
适用场景
- 01按 OpenSpec 任务实施功能
- 02在独立分支中执行自动化开发
- 03核对任务提交和验收条件
- 04测试并跟进 PR 反馈
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ memorysaver/ agentic-engineering-patterns --skill aep-build安装后在 Claude Code 中输入/aep-build确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/contract-template.mdharness-artifacts.mdmerge-decision-cases.mdprogress-template.mdstory-status.md详细介绍
构建
在隔离的 Git 工作树中的全新 feat/<name> 分支上自主实现功能。初始化工作框架,按顺序实现任务(tasks.md 每行对应一个提交),进行审查和测试、创建 PR、处理反馈并合并——全程无需用户交互。
**阶段编号:**阶段 1–3(探索、提议、审查)已通过
/aep-design在集成分支上完成。本技能从阶段 0(工作区初始化)开始,并从阶段 4(实现)继续。
循环规范:每个阶段都受统一的
--max-turns失控预算限制。达到上限不代表完成——应将其视为“可能无法解决 → 升级处理”(人工关卡协议),并与正常结束区分开来,以免卡住的阶段(例如阶段 5 中无法收敛的循环)被误认为已完成。
适用场景:
/aep-onboard → /aep-scaffold → [ /aep-design → /aep-launch → /aep-build → /aep-wrap ]
▲ you are here
**会话:**工作区会话,自主运行
**输入:**磁盘上的 OpenSpec 工件(由 /aep-design 提交到集成分支)
**输出:**已合并的 PR
阶段 0:初始化跟踪
设置跟踪基础设施和环境。分支已存在(/aep-launch 已创建 feat/<name>)。按顺序执行以下步骤;每步结束时都应满足可检查的后置条件。
**步骤 0 — 工作树检查,优先执行。**阶段 4–12 必须在此功能对应的工作树中运行,并在此处验证,而不是假定如此。在 Codex codex-subagent 上,工作树绑定只是软提示契约(spawn_agent 没有 cwd 参数),因此工作进程可能从主检出目录启动,并在那里创建 feat/<name>,导致阶段 12 的自动驾驶检测失效。此检查用于防止这种情况:
WS="<name>" # your story/change name from the bootstrap prompt — your worktree is
# .feature-workspaces/<name> on branch feat/<name>, matching the active
# OpenSpec change (ls openspec/changes/). If WS is still the literal
# "<name>", resolve it from the prompt/change BEFORE continuing.
TOP=$(git rev-parse --show-toplevel)
BRANCH=$(git branch --show-current)
if [[ "$TOP" != *"/.feature-workspaces/$WS" || "$BRANCH" != "feat/$WS" ]]; then
echo "GUARD: not in worktree .feature-workspaces/$WS on feat/$WS (top=$TOP branch=$BRANCH)"
# /aep-launch OWNS worktree creation; the guard only ENTERS the worktree it
# already made (cd, never `git switch` / `git worktree add -b`).
ROOT=$(git worktree list --porcelain | sed -n '1s/^worktree //p') # main worktree root
if [ -n "$ROOT" ] && [ -d "$ROOT/.feature-workspaces/$WS" ]; then
cd "$ROOT/.feature-workspaces/$WS" # launch made it; just enter it
else
# No worktree for $WS: escalate (Human-Gate Protocol / needs-human.md)
# rather than improvising one — "run /aep-launch first, or it misfired."
echo "ESCALATE: no .feature-workspaces/$WS — run /aep-launch first"; exit 1
fi
fi
# Re-verify before doing ANY work:
TOP=$(git rev-parse --show-toplevel); BRANCH=$(git branch --show-current)
[[ "$TOP" == *"/.feature-workspaces/$WS" && "$BRANCH" == "feat/$WS" ]] \
|| { echo "STILL NOT IN feat/$WS WORKTREE — STOP and escalate"; exit 1; }
工作树应由 /aep-launch 创建;如果缺失,应升级处理,绝不能在主检出目录中临时创建,因为这会导致无法恢复,而不只是出错。**后置条件:**检查以 0 退出(show-toplevel 以 .feature-workspaces/<name> 结尾,分支为 feat/<name>)。
-
**发现 OpenSpec 变更。**列出
openspec/changes/以查找当前变更;读取proposal.md、design.md、specs/**/*.md、tasks.md。**后置条件:**已确定变更目录并读取工件。 -
创建跟踪文件夹:
mkdir -p .dev-workflow。**后置条件:**目录存在。 -
将其加入 Git 忽略列表:
grep -q '.dev-workflow' .gitignore || echo '\n# Development workflow tracking (per-workspace)\n.dev-workflow/' >> .gitignore。后置条件:grep -q以 0 退出——.dev-workflow/已被 Git 忽略。 -
**根据此已安装技能的模板创建进度文件。**从工作树根目录解析软件包,优先使用 Codex 的标准安装路径:
ROOT=$(git rev-parse --show-toplevel); AEP_BUILD_DIR="$ROOT/.agents/skills/aep-build"; [ -f "$AEP_BUILD_DIR/references/progress-template.md" ] || AEP_BUILD_DIR="$ROOT/.claude/skills/aep-build"; [ -f "$AEP_BUILD_DIR/references/progress-template.md" ] || { echo "aep-build progress template not installed" >&2; exit 1; }; cp "$AEP_BUILD_DIR/references/progress-template.md" ".dev-workflow/progress-$(git rev-parse --short HEAD).md"。填写功能名称、基准 SHA、日期、变更名称和模式;将设计阶段 1–3 标记为预先完成。**后置条件:**文件存在。 -
**读取
tasks.md。**它_就是_骨架——你将在阶段 4 按顺序实现其中各行,每行对应一个提交,因此提交历史将与其逐项一一对应。**后置条件:**已掌握任务列表。 -
**运行项目设置。**如果存在
.claude/hooks/workspace-setup.sh,则运行bash(负责依赖、开发服务器、端口、数据库/种子数据和.env);否则阅读 README,或询问用户如何设置。该钩子会写入.dev-workflow/ports.env,至少包含以下四个键:WEB_PORT=<port> SERVER_PORT=<port> BASE_URL=http://localhost:<web-port> SERVER_URL=http://localhost:<server-port>后置条件:
.dev-workflow/ports.env存在并包含这四个键。 -
生成冲刺契约到
.dev-workflow/contracts.md,每个任务对应一个章节,依据specs/*.md+design.md+tasks.md生成。格式:references/contract-template.md。**完成标志:**文件存在,且每个任务对应一个章节。 -
生成特性验证清单
.dev-workflow/feature-verification.json(骨架和生成器所有权规则见references/harness-artifacts.md)。生成器只写入commit_sha——verification_steps和passes由评估器负责。**完成标志:**文件存在。 -
生成会话恢复脚本
.dev-workflow/init.sh(脚本内容见references/harness-artifacts.md);为其设置可执行权限:chmod +x。**完成标志:**文件存在且可执行。 -
**初始化信号:**运行
mkdir -p .dev-workflow/signals,创建status.json(骨架见references/harness-artifacts.md),并读取.dev-workflow/signals/feedback.md获取主会话输入。完整规范:/aep-launchreferences/signals-spec.md。完成标志:status.json存在。 -
创建经验文件
.dev-workflow/lessons.md(模板见references/harness-artifacts.md);根据此次变更填写文件头。第 4 阶段(自选)和第 9 阶段(总结)会填充各个章节。**完成标志:**文件存在。
更新进度文件中的第 0 阶段复选框。**信号:**将 status.json 中的 "phase": 0, "phase_name": "initialized", "completion_pct": 10 设为相应值。
**产品周期模式:**如果此次变更对应
product-context.yaml中的某个故事(变更名称与该故事的openspec_change相匹配),请阅读references/story-status.md,了解构建时依赖项的重新验证和基于信号的状态协议。独立模式(没有product-context.yaml):跳过此步骤。
第 4 阶段:应用 OpenSpec
按顺序实现 tasks.md 中的每项任务,一次一项任务,每项任务对应一个提交,然后记录提交 SHA。每项任务都要:实现(直接编辑文件)、检查(git status / git diff)、运行针对性测试,然后提交 feat(<scope>): <task description>,并将 8 位短 SHA 写入 feature-verification.json 对应条目的 commit_sha(绝不修改 verification_steps 或 passes)。提交格式、修正提交规则和恢复方法以规范的每项任务一个提交模式为准——参见 /aep-git-ref 中的 “The One-Commit-per-Task Pattern (Phase 4 of /aep-build)”。
调用应用技能获取逐项任务的指导:
/opsx:apply
**面向 UI 的故事——遵循对象映射。**如果分派的上下文包中包含对象映射切片(对象、属性、关系、CTA、屏幕),则必须将其作为约束结构:以对象为先构建所列屏幕(名词→动词——对象集合/详情,以及指定的 CTA 位置),使用指定的核心属性;不得引入切片之外的对象/屏幕,也不得将流程改为逐步向导,除非切片将其标记为
task_oriented。视觉风格(calibration/visual-design.yaml)、文案语气(copy-tone)和旅程/转场(ux-flow)仍决定设计取向——对象映射决定对象结构和 CTA 语法。
**记录经验(每项任务可选):**完成某项任务后,如果遇到值得记录的内容——例如不明显的解决方案、经过多次尝试才解决的错误、缺失的文档——请使用 ### <title> 子标题,将其追加到 .dev-workflow/lessons.md 中的 ## Solutions / ## Errors / ## Missing 章节下。仅在确实值得传递经验时记录。
逐项任务更新进度复选框;所有任务均已提交后,将第 4 阶段标记为完成。**信号:**开始时将 status.json 的 "phase": 4 设为相应值;随任务进度及时更新 task_current、task_index、task_total、completion_pct。
第 5 阶段:代码审查与验证
测试前先验证代码。本阶段采用生成器/评估器模式——完整机制见 /aep-gen-eval references:scoring-framework.md(维度、阈值、预设)、agent-contracts.md(角色分离、提示词模板)、eval-protocol.md(请求/响应格式、验证 JSON、收敛规则)。
第 5 阶段入口——在任何评估轮次消耗上限之前,确定绑定等级。根据实际差异(git diff --name-only "$BASE"...HEAD)对照 policy.md 的 sensitive_paths 和评审资源规则,重新推导验证等级,并生成 .dev-workflow/verification-recipe.json——包括等级、维度预设、硬性下限、scope_drift/tier_escalated。推导规则、下限和配方架构见:/aep-gen-eval references/verification-economics.md → The Two-Point Derivation(生成的 e2e 技能附带可运行脚本)。这里有两条约束:等级只能在调度简报的暂定等级基础上上调;若差异涉及未列入 files_affected 的文件,则根据差异重新计算,并设置 scope_drift: true。没有配方文件,第 5 阶段不得启动——有调度简报时,现在就推导;独立构建且没有简报时,使用 deep 默认值(失败时放行),并记录相应配方。将 verification_tier 和 tier_escalated 写入 status.json(架构由 /aep-launch references/signals-spec.md 负责)。
完整性检查(始终执行,由生成器负责):
- 重新阅读提案(包括任何设计评审调整)。
- 检查每个任务的提交——将
git show <commit-sha>与任务描述对照。 - 检查
.dev-workflow/contracts.md——确认每项任务的成功标准均已满足。 - 如果任务未完成,添加后续提交(
feat(<scope>): complete <task>/fix(<scope>): <issue>),然后返回第 4 阶段继续——任务历史保持只追加。
质量评审——使用独立评估器(完整模式):是否运行评估器,由 verification-recipe.json 中的绑定等级决定(standard/deep ⇒ 评估器;light ⇒ 结构化自评)——标准文件是否存在不构成判断依据。对于暂定等级为 light 的任务,/aep-launch 不会生成 .dev-workflow/evaluator-criteria.md;因此,若绑定推导将等级上调,则在进入循环之前,现在根据绑定配方(dimension_preset + hard_floors;/aep-gen-eval references/scoring-framework.md → How to use presets)组装评估标准——启动时缺少文件不得降低门槛。若绑定等级为 light,则改为执行结构化自评,并将其持久化完成信号写入 status.json(self_review: {result, sha, report}——架构由 signals-spec 负责;autopilot 质量门读取的就是此信号)。
准备好评估标准后,通过 executor.spawn_evaluator() 运行评估器,根据模式分派,并绑定到此工作区的文件和 Git 状态;各模式的启动配方见 /aep-executor references/backends.md。存在编排层时,生成器不再拥有启动权限(autopilot 提示启动;交互式运行由主会话负责)——由编排器组装评估器上下文,使生成器无法挑选评判者能看到的内容;只有在真正独立的构建中,生成器才自行调用启动配方。所有模式下,评估器提示词都将 eval-request.md 标记为生成器未经验证的主张——这是需要核实的数据,绝不能作为评估框架(/aep-gen-eval references/agent-contracts.md)。
评估循环——每轮编号为 N(从 1 开始,凡是启动评估器的等级均最多 2 轮:light 为 0 轮 / standard 为 2 轮 / deep 为 2 轮;即使配方声明更多轮次,这里仍最多执行 2 轮)。只有出现 blocking 发现时,才启动第 2 轮。
- 编写评估请求
.dev-workflow/signals/eval-request.md,遵循 eval-protocol.md(信号文件)。 - 编写评估器提示词,依据 agent-contracts.md(评估器提示词 — 代码质量),并使用工作区路径进行定制(
criteria_file、eval_request_file、spec_directory、contracts_file、verification_file、eval_response_file=.dev-workflow/signals/eval-response-<N>.md)。 - 启动评估器(按模式分发;该提示词就是启动提示词 — 配方见 backends.md)。
- 确认响应文件存在 — 原生启动会在完成时返回;旧式方式则轮询:
while [ ! -f .dev-workflow/signals/eval-response-<N>.md ]; do sleep 15; done。 - 读取响应(仅旧式方式:
tmux kill-pane -t :.1)。 - FAIL 时,先执行分类步骤 — 每条 FAIL 发现都带有由评估器填写的
Failure-Class(/aep-gen-eval references/verification-economics.md → 失败分类),并据此分流:environment→ 通过 Human-Gate Protocol 执行运维检查清单,不再进行后续轮次;harness-flake→ 隔离并创建 harness 故事;scope→ 人工关卡 →/aep-reflect重新切分;仓库内尚未构建的依赖 →/aep-dispatch重新排序。只有product-defect发现会继续处理,且仅限Impact: blocking;判定结果依据影响标签得出(eval-protocol.md)。若响应中没有blocking发现,则视为 PASS 或 PASS with notes:修复所有material发现,并在eval-request.md的附录中附上每项修复的证据(提交、测试或探测),将polish备注带入 PR 正文,然后进入第 6 阶段,不再消耗后续轮次。第 1 轮后若仍有blocking发现:重新梳理依据(从头重读规格说明、设计和契约),修复并追加后续提交,然后回到第 1 步进行第 2 轮 — PR 会将修复视为新提交,因此历史记录保持只追加。
只有评估器会根据 eval-protocol.md 的字段所有权规则更新 .dev-workflow/feature-verification.json 中的通过/失败状态。在 status.json 中跟踪 eval_round 和 recovery_rung;每次 FAIL 时,将响应中按发现统计的类别数量原样抄录到 status.json.failure_classes(值由评估器填写 — 生成器只负责抄录,绝不重新分类;架构由 signals-spec 负责,混合类别分流规则也由其负责)。
明确规定上限耗尽的处理方式,不得静默处理: 第 2 轮后仍未解决的 blocking 发现,无论层级如何,都必须通过 Human-Gate Protocol 提交升级,类型为 eval_not_converging;不得从 standard 升级到 deep(保持 tier_escalated: false)。关卡记录须包含两轮历史,并提出人类或自动驾驶策略可选择的策略变更:告知新的生成器“先前的方法在 X 处失败;请采用不同的设计路径”(继承此工作树),或将故事拆分为最小可行切片,并明确呈现拆分方案。
恢复阶梯(生成器端,两级) — 第 1 轮:同一生成器就地修复 blocking 发现;第 2 轮之前:重新梳理依据,然后修复。评估器只负责评分,因此重新梳理依据和两种关卡选项都由生成器处理。该阶梯仅适用于 product-defect — 在选择任何一级之前,第 6 步的分类流程会将其他所有类别分流出去。遇到严重失败 / 安全 FAIL(授权模型缺口、数据暴露风险)、规格矛盾(scope)或缺少外部依赖(environment — 需要指定拒绝标签)时,跳过阶梯并立即升级:这些情况需要人工判断。理由和新生成器的启动契约:/aep-gen-eval references/recovery-ladder.md。
质量审查 — 不使用评估器(轻量模式): 针对正确性、安全性、性能和约定进行结构化自审,并手动逐项检查 feature-verification.json 中的步骤。将发现记录在 .dev-workflow/code-review-<feature>.md 中,并修复发现的问题。
更新第 5 阶段的复选框。信号: 将 status.json 设置为 "phase": 5, "phase_name": "code-review"。
人工决策关卡协议(适用于任意阶段)
遇到只有人工才能做出的决策时——例如规范未能解决的设计歧义、达到最大轮数后评估仍未收敛,或需要做出产品判断——请设置关卡:
-
**记录(始终执行):**追加到
.dev-workflow/signals/needs-human.md:## <ISO8601> — Phase <N> **Question:** <the decision needed, with the options you considered> **Context:** <why you can't decide autonomously>并在
status.json中设置"blocked_on": "human"。 -
通过启动模式对应的传输方式提出关卡(
/aep-executorreferences/backends.md → The Human-Gate Protocol)。答案会通过主 Agent返回(中心辐射式架构),因此人工可以在原本所在的位置作答。在无推送模式(native-bg-subagent、claude-bg、codex-exec、workflow、headless)下,这意味着设置关卡并暂停:提交 WIP,更新status.json,然后干净地结束本次运行——状态保存在 worktree 和.dev-workflow/中,协调器会在此处收到答案后恢复一个工作进程。 -
**仅适用于可原地阻塞的模式:**继续处理不依赖该答案的事项;否则等待,并重新检查
feedback.md。 -
收到答案后(通过推送,或暂停后在恢复提示词中收到):在对应条目下追加
resolved: <summary>,清除blocked_on,然后继续。
阶段 6:浏览器测试(实测)
本阶段以用户旅程为先:步骤 A 根据该层的验收标准编写用户旅程;步骤 B 执行该旅程。步骤 A 始终执行(不受构建模式、dogfood_target、journey_timing 影响)。只有_执行_(步骤 B)会有所不同:在 Light 模式或 dogfood_target == none 时跳过;在 journey_timing: post-deploy 时,延后至 /aep-wrap 关卡执行。
步骤 A — 编写该层的用户旅程(始终执行,合并前)
如果项目有 e2e-test 技能和 journeys/ 目录(dogfood_target != none),且没有用户旅程覆盖此层——或者新增的验收标准缺少对应场景——则现在就在 skills/e2e-test/journeys/<NN-slug>.md 中编写或扩展用户旅程(路径规划见 layer_gates[N].journeys;复制 journeys/README.md 中的模板,设置 front-matter 中的 target:、layer:、covers:——即此用户旅程验证的验收标准 ID;参见 /aep-e2e-skill-scaffolding references/bdd-journeys.md):
- 每项验收标准对应一个场景(来自
stories[].acceptance_criteria),每个Then都对应一项具体的Verify(API 响应 / DB 记录 / 检查器检查),以意图为准,不绑定具体工具。 - 用户旅程必须在执行前,将每项验收标准映射到某个场景的
Verify(或者映射到用于验证确定性行为的 Tier-1 脚本测试用例,或用于验证后端 / 异步状态的 Tier-3 API 检查);有意推迟的验收标准须附上WAIVER: <reason>行。/aep-wrap会在将关卡设为passed前检查这些覆盖情况。 - 现在就将用户旅程文件与功能一起提交(合并前)——即使
journey_timing: post-deploy也是如此,此时仅推迟用户旅程的_执行_(步骤 B)。
dogfood_target == cli(CLI / 库):编写target: cli用户旅程——使用 bash 驱动构建好的二进制文件,每个Then都对应一项针对退出代码 / stdout / stderr / 文件系统的Verify。编写规则相同;只有工具路径不同。dogfood_target == none(没有可运行界面——配置 / schema / 文档,没有journeys/目录):无需编写用户旅程——改为将每项验收标准映射到 Tier-1 脚本测试用例 / Tier-3 API 检查,然后跳到步骤 B 的覆盖说明。
各 Tier 的适用性取决于项目类型(CLI / 库层为 [1,2];只有真正的 none 目标层才全部采用 Tier-1,不编写用户旅程):/aep-e2e-skill-scaffolding references/three-tier-model.md。
步骤 B — 执行编写好的旅程(dogfood 测试)
**轻量模式:**跳过步骤 B(步骤 A 仍会执行)。在轻量模式之外,步骤 B 会使用任何可用的、适配宿主环境的方法运行;如果没有
agent-browser,则降级使用下一种方法,而不是跳过。
**环境预检(在旅程产生任何开销之前)。**运行 skills/e2e-test/policy.md 中声明的探测(/aep-gen-eval references/verification-economics.md → Environment Preflight Gate):
- 不依赖部署的探测在此处对每个故事都运行,不受
journey_timing影响——检查 CI 配置中是否存在必需密钥的_名称_、预期账户指纹是否与实际身份验证身份一致,以及部署配置中是否接入环境变量名称。这些探测不需要运行中的目标。 - 绑定目标的探测(目标可访问、绑定已配置、可以植入测试数据)仅在
journey_timing: pre-merge时于此处运行;在post-deploy时则在/aep-wrap门禁处运行。
未满足的必需前置条件属于具名拒绝(REFUSING [dogfood-secret-absent:<NAME>])——通过 Human-Gate Protocol 将其作为运维检查清单列出,并停止旅程:运行 0 个场景,消耗 0 轮,按定义归类为 environment,并作为运维工作提交,而不是代码故事。缺少可选能力(live_policy: milestone_gates_only 下非里程碑门禁的实时部分)应标记为跳过,而非拒绝——它不会阻塞任何内容。
运行该层的旅程(描述意图,而非点击脚本),并根据每一行 Verify 验证状态。旅程的 target:(web/mobile/desktop/cli)以及 skills/e2e-test/tool-selection.md(即 e2e_tool(target_type) 的项目本地映射)共同决定使用哪种自动化工具;适配宿主环境的选择方式及其降级顺序见 /aep-executor references/dogfood-validation.md(e2e_tool(target_type)、web 封装器 dogfood_method())。
根据 skills/e2e-test/policy.md(dogfood_target)解析目标:
cli→ 通过 bash 在本地运行已构建的二进制文件(不使用 URL);如有需要,使用bash skills/e2e-test/scripts/seed.sh植入本地测试数据。none→ 跳过旅程 dogfood 测试(Tier-2 不适用);通过 Tier-1 / Tier-3 证明验收标准。local→ 运行source .dev-workflow/ports.env并使用$BASE_URL(target_url(local))。deployed:<url>→ 使用该 URL(例如 Cloudflare 预览环境/生产环境),并为同一目标植入测试数据(SERVER_URL=<url> bash skills/e2e-test/scripts/seed.sh),而不是本地环境。如果journey_timing是post-deploy,则将执行推迟到/aep-wrap门禁处(合并前目标尚未启动)——此处的阶段 6 仅运行 Tier-1/Tier-3,但步骤 A 的旅程文件仍需现在提交。
source .dev-workflow/ports.env # local target → $BASE_URL (deployed target: use the URL from policy.md)
无论采用哪种方法,都要输出统一的严重性/类别/复现报告格式(dogfood-validation.md → Unified report format),以便分类器不依赖宿主环境,并将报告写入 .dev-workflow/dogfood-<feature>.md,而不是发到聊天中——/aep-watch 的 dogfood_report 来源会读取该路径,并据此自动创建问题单。
**确认覆盖矩阵。**执行后,重新计算该层的覆盖矩阵:每条验收标准都必须对应一个能证明其满足的场景 Verify / 脚本化用例 / API 检查。由于步骤 A 已为每条验收标准编写了一个场景,此处只需确认——任何未覆盖的验收标准都表示步骤 A 有遗漏:现在补写该场景并重新运行,直至 coverage.criteria_covered == coverage.criteria_total(延期项需附带 WAIVER: <reason> 行)。
**信号:**设置 status.json:"phase": 6, "phase_name": "dogfood-testing"。
Phase 7:完成旅程并记录层级门禁
如果项目没有
e2e-testskill,请跳过。**轻量模式:**跳过此阶段。
该旅程已在 Phase 6 Step A 编写完成。此阶段将执行过程中发现的实际情况纳入该持久化 BDD 回归产物,完成最终定稿。在 skills/e2e-test/journeys/ 中:
- 完善此层级现有的旅程——纳入选择器/路由偏差、额外的
Verify行以及修正后的前置条件。在journey_timing: post-deploy下,该旅程稍后会在/aep-wrap门禁处执行,因此此次合并前定稿只纳入本地/Tier-3 检查发现的内容。 - 每个
Then都要保留一行具体的 Verify(API 响应/状态检查)。保持工具无关;API 级断言使用.dev-workflow/ports.env中的$BASE_URL/$SERVER_URL(绝不硬编码端口)。
**记录层级门禁。**将证据写入 docs/layer-gates/<layer>.md(生成的 e2e-test skill 附带 layer-gate-evidence 模板):两份覆盖矩阵——验收可追溯性(标准 → 验证测试 → Verify → PASS/FAIL)和 脚本覆盖(用例 → 断言 → PASS/FAIL)——以及手动检查清单、截图/API JSON 和任何 WAIVER: 行。在 product-context.yaml 中更新 layer_gates[N].coverage 和 evidence.{scripted,journeys,matrix}。两阶段状态翻转(scripted_passed → passed)在 /aep-wrap 进行(参见 references/layer-advance.md)。
Phase 8:审查结果
**轻量模式:**跳过此阶段。
- 加载
.dev-workflow/ports.env,获取正确的端口。 - 运行项目的框架测试(Tier 1)、适用的 Tier-3 API 驱动程序,以及重放受影响的先前层级旅程集(回归)——根据合并后的差异而非声明的
files_affected进行选择:当某个旅程的covers:标准属于此 story、其可选的paths:front-matter glob 与差异相交,或者它完全未声明paths:时,该旅程就会受到影响(默认放行——未声明的旅程仍保留在重放集中)。此外,始终将 walking-skeleton 旅程作为金丝雀执行——执行一次,立即发现“应用已无法启动”这类问题。完整的先前层级重放应在/aep-wrap层级门禁及其中层检查点进行,而不是每个 story 都执行——但有一个例外:deep层级的 story 要在此处重放完整的先前层级旅程集。仅当journey_timing: pre-merge时,才在此处重放此层级的 Tier-2 旅程——在post-deploy下,其执行推迟到/aep-wrap门禁(deployed:<url>目标在合并前尚未启动)。验证所有适用项均通过,并且coverage.criteria_covered == criteria_total(或为缺口添加WAIVER:)。 - 展示(或记录在进度文件中):Phase 5 代码审查、Phase 6 试用报告(若已运行),以及 Phase 7 旅程结果 + 层级门禁证据 + 覆盖率摘要(若已运行,格式为
criteria_covered / criteria_total)。 - 如果测试失败,返回相应阶段重新处理。
**状态标记:**将 status.json 设为 "phase": 8, "phase_name": "review-results"。
Phase 9:清理并发布
此处不要运行
/opsx:archive——归档会在合并后通过/aep-wrap于集成分支上进行。
- **撰写经验总结。**发布前,在
.dev-workflow/lessons.md中写一段最终的## Summary for Next Agent(1–3 句话):你会告诉下一个在此模块中开发的 Agent 什么?即使没有其他条目也要写(“实现过程很顺利,没有意外”也是有用的信息)。 - **审查提交历史:**运行
git log --oneline "$BASE"..HEAD(按照/aep-git-ref的“Resolving$BASE”说明解析$BASE)。提交历史应当是干净的线性序列——每个tasks.md任务对应一个提交,之后可以有用于修复审查问题的提交。 - 变基到最新的集成分支并推送(首次推送时使用
-u):运行git fetch origin && git rebase origin/"$BASE",解决冲突,然后运行git push -u origin feat/<name>。完整操作步骤(包括中止流程)请参阅/aep-git-ref的“Publishing & PR Conventions”。
阶段 10:创建 PR / MR
创建 PR/MR 时必须显式传入基分支:gh pr create --base "$BASE"(GitHub)/ glab mr create --target-branch "$BASE"(GitLab),并根据 /aep-git-ref 中的“Resolving $BASE”解析 $BASE。主机自动检测和完整流程见 /aep-git-ref 中的“Publishing & PR Conventions” → “Open the PR”。如果主机无法识别,则手动创建 PR/MR,但仍须传入基分支。
显式指定基分支,是因为 gh pr create 否则会根据本地分支状态推断基分支,可能导致 PR 指向过期的基分支,或者在双分支模式下指向生产分支 main。后置条件:gh pr view --json baseRefName 返回 $BASE。
在 PR/MR 正文中包含:变更摘要(根据提案编写)、测试覆盖说明,以及手动测试计划链接(如果已创建)。
阶段 11:PR 审查与 CI 反馈循环
监控 CI 和审查反馈。
对每条评论进行分类: 修复——正确性问题、CI 失败、规范违规、安全问题。确认但跳过——风格偏好、过度设计、外观问题。讨论——会扩大范围的架构建议、相互冲突的评论。
修复循环:(1)对所有评论进行分类;(2)在 .dev-workflow/pr-fix-plan-<round>.md 中编写修复计划;(3)回复已跳过或待讨论的评论;(4)针对每项修复添加后续提交(fix(<scope>): address review feedback on <topic>);(5)重新运行测试;(6)重新推送(git push origin feat/<name>);(7)重复上述步骤,直到 CI 全部通过且审查问题均已解决。提交和推送规范:/aep-git-ref 中的“Publishing & PR Conventions”。
阶段 11.5:人工评估与迭代
PR 审查修复完成后,由人工测试人员评估该功能(通常通过在工作区运行应用来进行)。如果发现小问题(UX 调整、遗漏的边缘情况、行为不匹配),则在此阶段进行迭代。
**如果未发现问题:**跳至阶段 12。
迭代轮次:
- 在
.dev-workflow/human-eval-round-<N>.md中记录发现:发现的问题(描述和复现步骤)、严重程度(轻微/中等)、类别(UX/逻辑/边缘情况/视觉)。 - 针对每项修复添加后续提交(
fix(<scope>): <human-eval finding>)。 - 同步更新 OpenSpec 变更,路径为
openspec/changes/<name>/:在tasks.md中将已完成的任务标记为完成;如果行为发生变化,则更新specs/;仅当方案发生变化时才更新design.md;保持proposal.md中的范围不变。 - 重新测试——针对已更改的部分重新执行阶段 5(代码审查)和阶段 6(dogfood)。
- 推送(
git push origin feat/<name>)。 - 如果测试人员发现更多问题,则重复上述步骤。
**信号:**准备好进行人工评估时,创建 .dev-workflow/signals/ready-for-review.flag;将 status.json 设置为 "phase": 11.5, "phase_name": "human-evaluation"。这是一个人工关卡——还应遵循 Human-Gate Protocol,以便协调器将其呈现出来,而不是将你计为卡住。
阶段 12:合并前检查与合并
-
确保与集成分支保持同步(按照
/aep-git-ref中的“Resolving$BASE”解析$BASE):git fetch origin && git rebase origin/"$BASE" && git push --force-with-lease origin feat/<name>— 带租约的推送仅在远程分支自上次获取后未前进时才会推送(参见/aep-git-ref中的“Publishing & PR Conventions”)。 -
读取 GitHub 自身的就绪状态:
gh pr view <number> --json mergeStateStatus,mergeable --jq '{state: .mergeStateStatus, mergeable}'CLEAN→ 当前可合并(必需检查均已通过或没有必需检查;没有缺少必需审核)→ 继续(没有必需检查的CLEANPR 仍可合并 — 缺少检查不是等待的理由)。- 其他任何状态(
UNKNOWN、UNSTABLE、BLOCKED、DIRTY、BEHIND)→ 操作前加载references/merge-decision-cases.md,查看各状态的处理方式。
-
没有未解决的审核评论。
-
E2E 测试已通过(如适用)。
-
重新检查后续提交的层级:如果上次评估通过后又有提交落地(第 11 阶段的审核修复、第 11.5 阶段的人工评估修复),请基于更新后的差异重新推导层级。如果变更涉及
sensitive_paths,则层级上调,并且合并前需要在上调后的层级重新完成一轮评估 — 这是过期评估规则,因为上次评估后代码已有变更。 -
提供最终状态摘要。
-
合并决策。
mode标记是检测的唯一依据:第 0 阶段的防护会将所有构建(包括交互式构建)移至工作树,因此无法通过当前工作目录区分自主模式和交互模式。MODE=$(cat "$(git rev-parse --show-toplevel)/.dev-workflow/signals/mode" 2>/dev/null) # anchored — a build phase may have cd'd into a subdirmode的值恰好为autopilot→ 自主模式:满足合并前条件后立即合并(编排器通过信号进行监控;没有人在等待确认)。- 其他任何情况(缺失、空值或其他值)→ 交互模式:合并前请求确认。信号含糊时按交互模式处理。
**“PR 已就绪”不是停止条件。**在自主模式下,只有 6 个合理条件会阻止合并 — 这些条件、完整的各状态处理方式以及示例均以
references/merge-decision-cases.md为准;其他情况一律合并。**合并后,将status.json中的story_status: "completed"— 到此你的工作结束。**Wrap 会在集成分支上运行/opsx:archive,因此从此工作树运行/aep-wrap会破坏并发协议;由编排器执行收尾。
合并:
- GitHub:
gh pr merge <number> --squash --delete-branch - GitLab:
glab mr merge <number> --squash --remove-source-branch
防护规则
适用于多个阶段、无法归入单一步骤的规则:
- 只有主会话可以写入
product-context.yaml— 工作区通过.dev-workflow/signals/status.json报告状态(并发协议;/aep-launch参考signals-spec.md)。 - **恢复流程:**如果返回继续执行进行中的工作流,请在
.dev-workflow/init.sh存在时运行它,然后读取进度文件。 - **信号:**在每个阶段的开始和结束时更新
status.json,并在阶段边界检查.dev-workflow/signals/feedback.md中来自主会话的反馈。
下一步
合并后,通知主会话运行:
/aep-wrap