跳到主要内容

自主阶段契约

以下为中文参考翻译,权威版本以 English 节为准 / The English section above is authoritative. 中文节标题降一级(###)是刻意的:守护测试 tests/unit/test_phase_b_acceptance.py 按二级标题解析英文契约,中文节不得引入同形态二级标题。 / Chinese headings are deliberately one level lower (###): the guard test parses the English contract by level-2 headings, so the Chinese half must not introduce same-shaped H2s.

目的(Purpose)​

Issue #2044(Phase A)。本文档是 AutonomousOrchestrator 中每个工作流阶段的契约规范, 是"阶段何时提交、以何种结果提交"的权威来源。代码必须与本文档一致;此处的变更需要 同步更新 orchestrator 以及 tests/unit/test_orchestrator_characterization.py 中的特征化测试。

AutonomousOrchestrator(约 13k 行)历史上允许每个 _do_* 阶段方法通过 _update_workflow 内联修改 current_phase / status。这使得一个阶段可能在自身 副作用尚未确认之前就部分成功并写入下一阶段的状态——这正是 #2044 要解决的 核心风险。

Phase A 在不移动阶段方法的前提下引入了一套契约:

  • WorkflowContext —— 阶段接收的只读快照。
  • PhaseResult —— 阶段返回的结构化结果。
  • _commit_phase_result —— 阶段/状态迁移的唯一权威路径。只有 outcome="completed" 才能推进 current_phase。

全部八个阶段现在都返回经由 _commit_phase_result 提交的 PhaseResult;没有任何 阶段再内联提交。其中四个位于 phases/*.py、挂在 PHASE_HANDLERS 注册表之后 (development、pr_review、merge、acceptance_verification —— 通过 resolve_phase_handler 解析);另外四个(preparation、planning、report、wait) 仍是 orchestrator 中的 _do_* 方法,但已经遵循 (ctx, deps) -> PhaseResult 契约。调度器中的 _legacy(...) 包装分支仅作为防御性兜底,实际永远不会触发。

契约字段(Contract fields)​

每个阶段都记录以下八个属性:

字段含义
preconditions(前置条件)阶段运行前必须成立的工作流/DB/git 状态。
inputs(输入)阶段从工作流 dict 中读取的字段。
authoritative evidence(权威证据)其状态决定结果的里程碑(milestone)。
side effects(副作用)外部变更:git、GitHub API、agent 子进程、DB 写入。
postconditions(后置条件)成功运行后保证的状态。
re-entry point(重入点)重启时从何处恢复(持久化的 current_phase + 里程碑)。
recovery behavior(恢复行为)阶段中途重试/重启/关机时的行为。
terminal outcomes(终态结果)本阶段可能产生的 PhaseResult 结果。

阶段顺序(Phase ordering)​

preparation → planning → development → pr_review → report → merge
↓
acceptance_verification
↓
(completed)

PHASE_ORDER 与 PHASE_STATUS_MAP(位于 orchestrator.py)是权威迁移表。 merge 的后继阶段是 acceptance_verification(#2335); _next_phase("acceptance_verification") == "acceptance_verification" (终态);_next_phase(<unknown>) == "planning"(恢复默认值)。提交入口只放行 PHASE_ORDER 中的 phase 以及它同样放行的两个伪 phase(wait、completed), 其余 next_phase 一律拒绝。


准备阶段(preparation)​

创建 GitHub 仓库(新项目)、issue、分支和 worktree。它是唯一创建 worktree 的 阶段,因此 advance() 会对它跳过 worktree 自愈。

  • preconditions(前置条件):current_phase == "preparation"、 status == "preparing"。此时尚不存在 worktree(主仓库是唯一有效的 repo_path)。
  • inputs(输入):project_path、is_new_project、requirements_text / requirements_issue_url、branch_strategy、parent_workflow_id(fork)。
  • authoritative evidence(权威证据):branch_created 里程碑 (status == "completed")。新项目还包括 repo_setup 与 issue_created。
  • side effects(副作用):gh.create_repo、gh.create_issue、 gh.create_worktree / gh.add_worktree,DB 里程碑/工作流写入。
  • postconditions(后置条件):worktree_path、branch_name、 branch_strategy 已设置;current_phase == "planning"、 status == "planning"。
  • re-entry point(重入点):current_phase == "preparation"。fork 快速路径 会探测是否有存活的分支(本地或远端),并通过 add_worktree 重新挂载而非重建, 因此此前不完整的尝试是幂等的(#814)。
  • recovery behavior(恢复行为):重新抛出异常前会记录 status == "failed" 的 branch_created 里程碑;advance() 将工作流标记为失败(网络错误则做 临时性重试)。
  • terminal outcomes(终态结果):completed → planning;git/GitHub 错误时 failed。

规划阶段(planning)​

运行"先规划后审查"的轮次,直到计划获批或达到 max_plan_rounds。使用主会话线 (main session line),只读工具且带超时上限。

  • preconditions(前置条件):worktree 已存在(advance() 会先对其自愈); current_phase == "planning"。
  • inputs(输入):requirements_text、current_round、max_plan_rounds、 github_issue_number、此前的 plan_created/plan_refined/plan_reviewed 里程碑、user_feedback。
  • authoritative evidence(权威证据):plan_finalized 里程碑(获批)或 max_plan_rounds 耗尽。每轮:plan_created/plan_refined + plan_reviewed 里程碑。
  • side effects(副作用):每轮两次 agent 运行(规划、审查);附带计划的 issue 评论;将 user_feedback 注入提示词后清除。
  • postconditions(后置条件):获批时 current_phase == "development"、 status == "developing"、current_round == 0。超时时 status == "planning_timeout"(用户可延长)。其他失败时 status == "failed"。
  • re-entry point(重入点):current_round 已持久化;重启后从下一轮恢复。 round_num 由 current_round + 1 推导,绝不依赖内存。
  • recovery behavior(恢复行为):临时性错误通过 advance() 重试; WorkflowPaused(关机)不改动状态。
  • terminal outcomes(终态结果):completed → development;规划超时时 pause(planning_timeout 状态);规划失败时 failed。

开发阶段(development)​

实现变更并运行针对性测试。驱动主会话线(main session line)。测试失败时最多 循环 MAX_DEV_RETRIES_ON_TEST_FAIL 次,并可选用 CI 修复与重新开发。

  • preconditions(前置条件):worktree 存在且位于 branch_name 上;已存在 获批计划(plan_finalized 里程碑);current_phase == "development"。
  • inputs(输入):定稿计划内容、dev_round、重试计数器(test_retries、 dev_retries_on_test_fail、skip_retries)、测试里程碑证据。
  • authoritative evidence(权威证据):dev_completed 里程碑 + 测试结果 里程碑(带 result_summary 的 tests_run)。测试由结构化命令证据判定 (#2046),而非自由文本启发式。
  • side effects(副作用):agent 运行(写代码)、测试执行、CI 修复 agent 运行、分支推送、issue 评论。
  • postconditions(后置条件):成功时 current_phase == "pr_review"、 status == "pr_review"、current_round == 0、重试计数器清零。不可恢复的 测试失败时 status == "failed"。
  • re-entry point(重入点):重试计数器与 dev_round 已持久化;重启后在 同一开发轮次重入。重入防护避免进程重启后重复启动开发。
  • recovery behavior(恢复行为):测试失败 → 开发重试(达上限为止)→ CI 修复 → 硬失败。关机时抛出 WorkflowPaused。
  • terminal outcomes(终态结果):completed → pr_review;不可恢复的测试 失败时 failed;循环内为 retry。

PR 审查阶段(pr_review)​

创建/更新 PR 并运行独立的代码审查轮次。使用审查会话线(review session line)。循环直到审查通过或达到 max_pr_review_rounds。

  • preconditions(前置条件):开发已完成(dev_completed 里程碑);分支已 推送;current_phase == "pr_review"。
  • inputs(输入):github_pr_number、current_round、 max_pr_review_rounds、require_full_review_rounds、PR diff。
  • authoritative evidence(权威证据):pr_reviewed 里程碑;结构化批准 判定(_derive_review_passed)。CI 状态经由外部证据层(#2045)。
  • side effects(副作用):gh.create_pull_request / 更新、审查 agent 运行、CI 轮询、issue 评论。
  • postconditions(后置条件):批准时 current_phase == "report"、 status == "reporting"。审查轮次耗尽 → 退回开发 (current_phase == "development")进行新一轮开发。
  • re-entry point(重入点):current_round 已持久化;round_num 防护同时 覆盖重入与进程重启后的恢复。已存在的 PR 会被更新而非重建。
  • recovery behavior(恢复行为):CI pending → 等待并轮询;CI 失败 → CI 修复(重入 pr_review);审查失败 → 回到 development。关机经由 WorkflowPaused。
  • terminal outcomes(终态结果):completed → report;completed → development(审查失败,新一轮开发);merge/PR 错误时 failed。

报告阶段(report)​

生成结构化进度报告并发布。轻量阶段:无 agent 运行、无 git 变更。读取里程碑 证据并渲染 i18n。

  • preconditions(前置条件):current_phase == "report";planning + development + pr_review 里程碑已存在。
  • inputs(输入):dev_round、定稿计划、diff 统计、测试摘要、审查里程碑、 content_language。
  • authoritative evidence(权威证据):progress_reported + round_completed + wait_started 里程碑。
  • side effects(副作用):GitHub issue 评论(以 content_language 渲染); 结构化 metadata.report 载荷(唯一事实源,由前端按查看者渲染)。无 git 变更。
  • postconditions(后置条件):current_phase == "wait"、 status == "waiting";记录 wait_started_at 用于评论过滤。
  • re-entry point(重入点):幂等 —— 里程碑去重;重跑只会重新发布报告。
  • recovery behavior(恢复行为):GitHub 评论失败为非致命(尽力发布)。
  • terminal outcomes(终态结果):wait(停驻在 waiting,不推进到 merge)。

等待阶段(wait)​

轮询新需求或完成信号。绝不能改动 git 工作树 —— 调度器的 waiting-bypass 假定本阶段只触碰 DB/API 状态。

  • preconditions(前置条件):current_phase == "wait"、 status == "waiting"。
  • inputs(输入):user_feedback(来自 cancel-with-feedback)、 auto_merge、github_pr_number、github_issue_number。
  • authoritative evidence(权威证据):requirement_received 里程碑 (新反馈);无新评论(保持 waiting)。
  • side effects(副作用):GitHub issue 评论轮询。无 git/agent 操作。
  • postconditions(后置条件):三条分支 ——
    1. 存在 user_feedback → 从被取消里程碑所属的阶段恢复,dev_round += 1 (通常回到 development)。
    2. auto_merge 且 PR 存在 → current_phase == "merge"、 status == "merging"。
    3. 否则保持 waiting(下一周期再轮询)。
  • re-entry point(重入点):只要 status == waiting,调度器每个周期 (约 10 秒)重入 _do_wait。不需要任何内存态。
  • recovery behavior(恢复行为):没有失败路径;临时性 GitHub 错误经 advance() 重试。
  • terminal outcomes(终态结果):completed → merge(auto_merge); completed → cancelled_phase(反馈);否则保持 wait。

合并阶段(merge)​

同步基线、解决冲突(含 #2050 的 SIGKILL 韧性 worktree 迁移)、合并 PR 并 清理。可能 fork 出一个冲突解决子工作流。冲突解决使用一次性 fresh 会话。

  • preconditions(前置条件):current_phase == "merge"、 status == "merging";PR 存在且可合并。
  • inputs(输入):github_pr_number、branch_name、 worktree_transition_state(进行中的冲突迁移)、CI 状态。
  • authoritative evidence(权威证据):merge_completed / merge_failed 里程碑;冲突解决 fork 里程碑。
  • side effects(副作用):gh.merge_pull_request、基线同步、冲突 worktree 创建/移除、分支/worktree 清理。
  • postconditions(后置条件):成功时 current_phase == "acceptance_verification"、 status == "verification_pending"。工作流只能从验证侧到达 completed (确认性落账、人工覆盖或该阶段被禁用);completed_at 由确认性落账补丁、 覆盖路径或 completed 伪 phase 的统一提交写入 —— 而非由 merge 本身写入。 冲突 → fork 子工作流并暂停父工作流。不可恢复的冲突 → status == "failed"。
  • re-entry point(重入点):worktree_transition_state 已持久化;被 SIGKILL 打断的迁移会在任何阶段运行之前于 advance() 顶部完成对账 (#2050),因此重启绝不会回退到主检出。清理重试单独跟踪(#2043)。
  • recovery behavior(恢复行为):冲突 → fork → 父工作流暂停 → 子工作流 解决 → 父工作流恢复 merge。对账失败会 fail-close(status=failed),而不是 在错误的检出上运行阶段。
  • terminal outcomes(终态结果):completed → acceptance_verification (合并成功;终态 completed 状态从验证侧到达);pause(冲突 fork); 不可恢复的冲突/合并错误时 failed。

phase_change 发射契约:_commit_phase_result 不发射 phase_change 事件。已迁移的 handler 通过 deps.host.emit_phase_change 自行发射;merge 的成功尾部在返回 next_phase="acceptance_verification" 之前发射 phase_change{"phase":"completed"},为 UI 消费者保留遗留事件流。


验收验证阶段(acceptance_verification)​

独立的合并后验证(#2335,phases/acceptance_verification.py)。在已合并的 main SHA 上运行无凭据只读验证器,应用确定性的机械门禁加上逐项判定聚合,只有 confirmed 判定才会关闭 issue。禁用时 (autonomous.acceptance_verification_enabled=false)handler 立即完成,不 运行验证器。

  • preconditions(前置条件):current_phase == "acceptance_verification"、status == "verification_pending";PR 已合并, 因此 merge SHA 可解析。
  • inputs(输入):merge SHA(verification_merge_sha,缺失时从 PR 的 merge commit 解析)、基线 SHA(base_commit_sha)、issue 的验收快照 (issue_acceptance_hash)、verification_status、verification_attempt、 此前的 acceptance_verification 里程碑。
  • authoritative evidence(权威证据):acceptance_verification 里程碑 —— 验证器启动时在 verification 会话线上以 in_progress ("Acceptance verification: running")铸造,并就地随判定落账(#3003)。
  • side effects(副作用):验证器 agent 运行(只读工具、verification 会话线上的临时 merged-main 检出)、issue 报告评论、confirmed 时关闭 issue、向运行中的 acceptance 行写入用量(prior_usage 基线 + 运行内增量)、 milestone_updated 事件;人工覆盖经 verification_override 路径将人工 身份记录到 verified_by。
  • postconditions(后置条件):confirmed → status == "completed"、 issue 关闭、completed_at 已设置。rejected / indeterminate → paused 等待人工审查(已交付的代码绝不会被标记为 failed)。基础设施故障 在同一阶段重试,最多 3 次(确定性解析失败上限 2 次,#2867),随后暂停。
  • re-entry point(重入点):按 (merge_sha, issue_acceptance_hash) 去重; 已落账的 confirmed 结果是终态 no-op。新的 merge SHA 或被编辑过的 issue 会自然地重新运行验证器。同一尝试会复用早期里程碑行,较旧的 in_progress 行会被清扫为 failed("interrupted");验证中途的配额暂停只有在写入其已消耗 用量后才终结该行。
  • recovery behavior(恢复行为):基础设施故障 → 同阶段重试;验证器配额 暂停 → 工作流 paused(可恢复);关机 → 该行被终结为 cancelled 并在 恢复时由同一尝试复活(硬 kill 会使其留在 in_progress,同样会被复用)。
  • terminal outcomes(终态结果):completed(confirmed 判定或阶段被 禁用);pause(rejected / indeterminate / 重试耗尽);retry(未达上限的 基础设施故障)。

迁移状态(Migration status)​

全部八个阶段都经由 _commit_phase_result 提交;没有任何阶段仍停留在遗留的 内联提交路径上。

  • phases/*.py + PHASE_HANDLERS 注册表(经 resolve_phase_handler 解析): development、pr_review、merge、acceptance_verification。调度器中 针对它们的 _legacy(self._do_*) 分支仅是防御性兜底。
  • 直接遵循契约的 orchestrator _do_* 方法(#2044 T6–T9):preparation、 planning、report、wait。

一个阶段被视为已迁移的条件是:它返回 PhaseResult 且不含任何直接的 _update_workflow({"current_phase": ...}) / _create_milestone 调用 —— 所有状态都流经 _commit_phase_result。