# 06-验收与测试锚点 对应架构文档第 11 节 MVP 验收标准,逐条映射到 requirement_id,并给出 M/V/C/P 覆盖和至少 3 类验收用例(happy / boundary / failure)。场景统一采用"贪吃蛇游戏"作为验收任务。 ## REQ-01:Org Graph 三节点链路可触发 - 覆盖:M=`org_graph_definition`,`task`;C=`c_task_create`,`c_org_node_trigger`;P=`p_org_task_lifecycle` - 验收用例: - happy:创建 `goal_text="实现贪吃蛇游戏"` 的 task,依次触发 planner/coder/validator 三个 org_node,`task.status` 按状态机正确流转 - boundary:`max_concurrent_goals=1` 时,同时创建第二个 task,验证其落 `queued` 而不被立即调度 - failure:`goal_text` 为空时 `c_task_create` 返回 `INVALID_PARAM` ## REQ-02:Planner 产出四类 Artifact 并通过校验 - 覆盖:M=`artifact`,`work_graph_run`;V=`v_task_detail`;C=`c_work_graph_plan`,`c_work_graph_execute`,`c_artifact_write`;P=`p_work_graph_execution` - 验收用例: - happy:Planner Work Graph 跑完后,`artifact` 表中存在 `brd`/`prd`/`sdd`/`benchmark` 四条记录,且 `depends_on_artifact_ids` 血缘链完整(`sdd`→`prd`→`brd`) - boundary:PRD 中出现互相矛盾的场景假设时,一致性校验应在 `verifying` 态被拦截,触发 `reflecting` 而非直接放行 - failure:`sdd` 生成时找不到对应 `prd` 版本引用,`c_artifact_write` 应拒绝写入(`depends_on_artifact_ids` 指向不存在的 `artifact_id`) ## REQ-03:Coder 依据 SDD 完成编码并自测通过 - 覆盖:M=`work_node_execution`;C=`c_work_node_run`;P=`p_work_graph_execution` - 验收用例: - happy:Coder Work Graph 完成后产出 `code_diff` 与 `test_report` 两类 artifact,且 unit + integration test 全部通过 - boundary:两个无依赖的模块并行编码,验证各自 `git_worktree_ref` 不冲突,合并后代码无冲突残留 - failure:某模块单测失败,`work_node_execution.status` 应为 `reflecting`→`retrying`,达到节点级重试上限后冒泡为 `blocked` ## REQ-04:Validator 完成测试/Benchmark + 根因归属 + 结构化 bug list - 覆盖:M=`bug_record`;C=`c_bug_record_create`;P=`p_validator_root_cause_trace` - 验收用例: - happy:人为植入一个"边界撞墙判定错误"的 bug,Validator 应判定 `root_cause_category=coder`(而非 planning 或 skill_defect),且 `root_cause_detail` 引用具体 SDD 章节和代码位置 - boundary:植入一个"PRD 未定义撞墙行为"的需求缺口型 bug,Validator 应判定 `root_cause_category=planning` - failure:三视角判断不一致时,流程应落在 `inconclusive_escalate` 而不是强行给出一个归因结论 ## REQ-05:Org-level Loop 完整闭环 - 覆盖:C=`c_org_loop_route`;P=`p_org_task_lifecycle` - 验收用例: - happy:REQ-04 的 bug 记录经 `suggested_route=fast_lane` 路由后直达 Coder,修复后重新进入 Validator,最终 `task.status=done`,全程 `loop_round` 从 0 增至 1 - boundary:`suggested_route=full_replan` 时应回到 Planner 而非 Coder,验证路由分支正确 - failure:连续 3 轮同一 bug 未收敛,`task.status` 应转 `blocked_pending_human` 且调度器继续执行队列中其他任务(若有) ## REQ-06:Graph Engine 断点恢复 - 覆盖:M=`work_graph_run`,`work_node_execution`;P=`p_work_graph_execution` - 验收用例: - happy:在 `work_graph_run.status=running` 时人为中断进程,重启后能从已持久化的 `work_node_execution` 状态继续,不重跑已 `done` 的节点 - boundary:中断发生在某节点 `retrying` 中途,重启后应恢复到该节点重试逻辑而非跳过 - failure:持久化数据损坏(模拟)时,系统应明确报错并转 `blocked_pending_human`,而不是静默丢失进度继续跑 ## REQ-07:执行器抽象层(Claude Code ACP 后端)可用 - 覆盖:C=`c_work_graph_execute`;对应 05 节 5.3(架构文档 7.2 节决策,2026-07-29:MVP 阶段只用 Claude Code ACP 一种后端,不再考虑 Hermes CLI) - 验收用例: - happy:Claude Code ACP 后端下完整跑通 REQ-01~06 全部场景 - boundary:`claude -p` 调用不加 `--bare`(见 A-1 spike 结论),确认额外冷启动开销在可接受范围内 - failure:auto mode 分类器连续拦截 3 次或累计 20 次,返回 `CLASSIFIER_BLOCKED`,task 转 `blocked_pending_human`,`blocked_reason=classifier_blocked` ## REQ-08:Skill 自主迭代 + Git 可追溯可回滚 - 覆盖:M=`skill`,`skill_iteration`;V=`v_skill_audit_log`;C=`c_skill_update`,`c_skill_rollback` - 验收用例: - happy:REQ-04 中判定 `root_cause_category=skill_defect` 的 bug 触发 `c_skill_update`,生成独立 Git commit,`v_skill_audit_log` 可查看该次变更 - boundary:`triggered_by_bug_id` 缺失时 `c_skill_update` 应拒绝(不允许无来源变更) - failure:`c_skill_rollback` 到不存在的 `iteration_id` 应返回 `ITERATION_NOT_FOUND` ## REQ-09:循环终止与人工升级 - 覆盖:P=`p_org_task_lifecycle` 的 `blocked_pending_human` 分支 - 验收用例:(与 REQ-05 failure 用例共享验证场景) - happy:`blocked_pending_human` 后,人工在 `v_task_detail` 点击"人工干预"(`manual_resume`),任务能恢复到触发前状态继续执行 - boundary:多个任务同时有一个 `blocked_pending_human`、其余 `queued` 时,调度器应继续调度 `queued` 任务,不被阻塞任务卡住 - failure:`manual_resume` 在任务已经是 `done` 终态时调用,应返回明确错误而非误操作已完成任务 ## REQ-10:预算护栏双层机制 - 覆盖:M=`budget_guardrail_config`;V=`v_budget_settings`;C=`c_budget_check`,`c_budget_config_update`;P=`p_budget_guardrail` - 验收用例: - happy:配置 `limit_type=token_count, limit_value=<小值>`,运行到超限后任务自动转 `blocked_pending_human`,`blocked_reason='budget_exceeded'` - boundary:调高额度后(`c_budget_config_update`),`paused` 态任务能恢复调度 - failure:`budget_guardrail_config` 触发的超限走 `blocked_pending_human`;Claude Code plan 额度耗尽走独立的 `p_usage_limit_wait` 子流程(见 REQ-14),两者不应共用同一个 `blocked_reason` ## REQ-14:Claude Code plan 额度耗尽的等待重试(架构文档 7.5 节决策,2026-07-29) - 覆盖:M=`work_node_execution`(`status=waiting_for_quota`、`quota_wait_started_at`、`quota_limit_type`);V=`v_dashboard`,`v_graph_visualizer`;C=`c_work_node_run`,`c_org_node_trigger`;P=`p_usage_limit_wait` - 验收用例: - happy:模拟 `claude -p` 返回 `You've hit your session limit`,`work_node_execution.status` 转 `waiting_for_quota`,退避轮询后探测成功恢复正常执行,全程不产生 `blocked_pending_human` - boundary:`quota_limit_type=opus` 时不走退避轮询,直接降级到非 Opus 模型重试 - failure:模拟超过超时阈值(`session` 8 小时 / `weekly` 9 天)仍未恢复,转 `blocked_pending_human`,`blocked_reason='usage_limit_wait_timeout'` ## REQ-11:项目创建与人机交互入口(架构文档第 13 节) - 覆盖:M=`project`,`bug_record`;V=`v_project_setup`,`v_goal_composer`,`v_bug_feedback`;C=`c_project_create`,`c_task_create`,`c_bug_report_create`;P=`p_validator_root_cause_trace`(human_reported 起点) - 验收用例: - happy:选择一个已有 Git 仓库的本地文件夹创建项目 → `.graphlemon/` 子目录被创建 → 通过 `v_goal_composer` 提出"实现贪吃蛇游戏"目标 → 成功创建 task 并进入 Org Graph - boundary:选择一个非 Git 仓库的文件夹,用户确认初始化后应执行 `git init` 并继续;用户不确认则整个创建流程中止,不留下任何写入 - failure:对同一 `target_folder_path` 重复调用 `c_project_create`,应幂等返回已有项目而非报错或创建重复记录;`v_bug_feedback` 提交空 `description` 应被前端和后端双重拦截 ## REQ-12:实时看板(架构文档 13.1 节决策 3) - 覆盖:M=`execution_event`;V=`v_dashboard`,`v_graph_visualizer`,`v_task_detail`;C=`c_ws_subscribe` - 验收用例: - happy:某 `work_node_execution.status` 变化后,`v_graph_visualizer` 对应节点应在可感知的短时间内(作为非功能验收目标,建议 ≤2 秒)完成着色更新,无需人工刷新页面 - boundary:WebSocket 连接断开后自动重连,重连期间页面展示"实时连接已断开,正在重连"而不是冻结或报错崩溃;重连后能补齐断线期间遗漏的关键状态(通过重新拉取 `task`/`work_graph_run` 当前快照兜底,不要求完整补齐每一条中间事件) - failure:订阅一个不存在的 `project_id`,连接应被拒绝并返回 `PROJECT_NOT_FOUND`,而不是建立空连接后无声无息不推送任何数据 ## REQ-13:原始日志控制台内查看 + 定时清理(架构文档 13.1 节决策 4) - 覆盖:M=`execution_log_file`,`log_retention_config`;V=`v_log_viewer`,`v_log_retention_settings`;C=`c_execution_log_get`,`c_ws_log_tail`,`c_log_retention_config_update`;P=`p_log_retention_cleanup` - 验收用例: - happy:某 Work Node 运行中,`v_log_viewer` 能实时滚动显示新追加的日志内容;节点结束后自动切换为静态模式,仍可完整查看 - boundary:配置 `retention_days=1`,构造一条 `created_at` 超过 1 天的 `closed` 状态日志,清理任务运行后应转为 `purged` 且物理文件被删除;`v_log_viewer` 打开该日志时展示"已被清理"提示而非报错 - failure:订阅一个不存在的 `node_exec_id` 的日志流,应返回 `NODE_EXEC_NOT_FOUND`;清理任务遇到某个文件删除失败(如被占用)时,应仅记录该项失败、不影响其余候选项的清理,且该条目下次周期继续重试 ## REQ-15:Deploy Supervisor 蓝绿部署与自动回滚(PH5 新增,2026-07-30,见 `docs/supervisor-auto-rollback-design.md`) - 覆盖:M=`deployment`,`deploy_health_signal`,`bug_record`(`root_cause_category=core_engine`);C=`c_deploy_supervisor_stage`,`c_deploy_supervisor_health_check`,`c_deploy_supervisor_cutover`,`c_deploy_supervisor_monitor`,`c_deploy_supervisor_rollback`,`c_org_loop_route`;P=`p_deploy_supervisor_blue_green` - 验收用例: - happy(正常 cutover 到 finalize):graphlemon 自身仓库一处真实植入 bug(`self-development-feasibility.md` 第 3 节场景),标记 `root_cause_category=core_engine`,Coder 修复、Validator PASS、worktree 合并主分支后,Deploy Supervisor 依次完成 `staged→candidate_starting→health_check_running→health_check_passed→cutover_in_progress→live→monitoring`,监控窗口内四类信号均正常,最终 `monitoring_window_clean→finalized`,全程无需人工评审代码内容 - boundary(路径 A:健康检查失败):人为让候选实例的 `canary_task` 检查失败(如返回结果与预期不符),Deploy Supervisor 应立即判定 `health_check_failed`,不重试,直接走回滚路径 A(终止候选、`git revert`、发 `bug_record`),Live 全程未受影响,可通过对比 Live 进程 PID/端口在 cutover 前后未发生变化来验证 - boundary(路径 B:post-cutover 异常回滚):cutover 完成后,人为把 `validator_approval_rate` 信号推到偏离历史基线阈值(`VALIDATOR_RATE_DEVIATION_THRESHOLD`,05 节 §5.9)之外,Deploy Supervisor 应判定 `anomaly_detected`,走回滚路径 B,最终 `previous_instance_dir` 重新成为 Live,`rolled_back`,生产库数据在整个过程中未丢失(因为生产库本身没有被替换,只是替换了跑在它前面的代码进程) - failure(回滚本身失败):人为让 `previous_instance_dir` 也无法正常启动(如故意损坏该目录),路径 B 的回滚应终态到 `rollback_failed→blocked_pending_human`,`blocked_reason='rollback_failed'`,且控制台展示的原因应清楚区分"自动恢复机制本身失效"与"代码内容有问题"两种情况,不能让用户误以为又需要人工评审代码