记录已实现的蜂后闭环(M2-M4+P0)现状与诚实差距,标注剩余(SC-7 落main/SC-8 authoritative/M5 北极星)。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
12 KiB
蜂群收敛协议(共识 / 冲突消解 / 终止函数)
状态:已无条件接入
refresh_swarm_run_status(去中心化重构,无开关)。每次 run 终态都产ConvergenceReport存run.metadata["convergence"],并把termination_reason附到timeline.updated。当前为解释性——产出termination_reason/共识/冲突,但不覆盖run.status(今天 next_status 与报告对 completed/failed 一致);authoritative 状态覆盖为后续。对应 Issue #12:「蜂群收敛机制缺失:缺少共识、冲突消解与终止函数,无法解释 Swarm 为什么结束」。
实现:
orchestrator/convergence.py(纯计算,无 I/O)+main.py: compute_convergence_report(装配 run_state,shadow 落库);单测scripts/test-convergence.py+ 集成测试scripts/test-swarm-convergence.py。计划见 decentralized-rework-plan.md。
0. 问题:今天「为什么结束」是不可解释的
当前一次 run 走到终态,唯一判定在 orchestrator/main.py:refresh_swarm_run_status:
- 所有已知任务到达终态后,
next_status = "failed"(任一任务FAILED)否则"completed"; - 可选地(仅
ENABLE_REVIEW_LOOP)先跑主控评审,被拒则重开任务再 finalize。
也就是说,今天的终止 = 「所有任务做完 + (可选)评审通过」,没有:
- 共识模型:没有任何「多少产出处于一致状态」的度量;
- 一等公民的冲突检测 / 消解:两个 Agent 对同一文件写出不同内容、依赖未满足却标记完成等,均无显式识别;
- 可机读的终止原因:
completed/failed无法区分「质量达标」「预算耗尽」「轮次上限」「被风险阻断」。
本协议补齐上述三者。已无条件接入(无开关),但当前作为解释层:产出报告 + termination_reason 存 run,不覆盖 run 的终态语义(规则 #9:authoritative 覆盖为后续)。
1. 设计原则
- 纯函数、可测:
evaluate_convergence(run_state)不做任何 I/O,不修改 run;调用方(main.py: compute_convergence_report)负责持久化。 - 无条件(无开关):
refresh_swarm_run_status每次终态都计算报告——本仓即 swarm 运行时,无ENABLE_*门控。 - 不伪造信号(规则 #9):无质量评分 ≠ 通过;无测试信号 ≠ 失败;无预算 ≠ 充足。缺信号一律退出判定,不补 0、不补 100。
- 解释优先于干预:本版只解释「为什么结束」,不自动改写终态、不自动 merge 冲突产物。
2. 数据结构(orchestrator/convergence.py)
@dataclass
class ConvergenceReport:
status: ConvergenceStatus # running / converged / failed / blocked
termination_reason: TerminationReason | None # 终态必有,running 时为 None
consensus_score: float # [0,100],无冲突牵连的已完成产出占比
conflicts: list[Conflict] # 全部检出冲突
resolved_conflicts: list[Conflict] # 已消解
unresolved_risks: list[dict] # 阻断性风险 + 未消解硬冲突
budget_state: dict # 预算限额 / 消耗 / exhausted
quality_state: dict # fixture 评分 / 阈值 / reached
2.1 终止原因枚举(TerminationReason)
| 值 | 含义 | 触发输入 |
|---|---|---|
quality_reached |
质量 / 验收门达标 | quality.test_pass_rate ≥ acceptance_threshold(默认 1.0) |
budget_exhausted |
token / 成本 / 时长预算耗尽 | usage ≥ budget 任一限额 |
max_rounds_reached |
评审 / 重做轮次达上限 | review_cycles ≥ max_review_cycles |
risk_blocked |
被未消解阻断性风险终止 | 输入阻断风险或未消解硬冲突 |
tasks_completed |
诚实回退:仅「所有任务做完」 | 以上均不适用——即今天唯一真实信号 |
tasks_completed明确对应「现状」:当没有质量评分、预算、轮次或风险信号时,我们能说的只有「任务都做完了」,不冒充更强的解释。
2.2 冲突类型(ConflictType)
| 类型 | 检测器 | 判据 |
|---|---|---|
artifact_mismatch |
detect_artifact_mismatch |
两个已完成任务对同一 files_modified 路径记录了不同 file_hashes/file_contents 指纹 |
test_failure |
detect_test_failures |
任务结果 tests_passed is False 或 test_pass_rate < 1 |
review_disagreement |
detect_review_disagreement |
主控评审 accepted=False(沿用 master_agent.review_and_decide 的 verdict 形状) |
dependency_inconsistency |
detect_dependency_inconsistency |
任务已完成,但其 depends_on 依赖在同 run 内未完成 |
3. 终止函数判定顺序
evaluate_convergence(run_state) 依次判断,先匹配先返回:
- 无任务 / 任一任务处于
pending|assigned|in_progress→RUNNING(无 reason)。 - 存在阻断风险或未消解硬冲突 →
BLOCKED+risk_blocked。 - 仅有
blocked任务(无阻断风险) →RUNNING(与refresh_swarm_run_status中「blocked 但有活跃子任务保持 running」对齐)。 - 任一任务
failed→FAILED,原因取(预算耗尽→budget_exhausted;否则轮次到顶→max_rounds_reached;否则tasks_completed)。 - 全部完成且预算耗尽 →
CONVERGED+budget_exhausted。 - 全部完成且轮次到顶 →
CONVERGED+max_rounds_reached。 - 全部完成且质量达标 →
CONVERGED+quality_reached。 - 其余(全部完成) →
CONVERGED+tasks_completed(诚实回退)。
不变式:任何终态(converged/failed/blocked)必带且仅带一个 termination_reason;running 必为 None。单测逐条断言。
3.1 共识分(compute_consensus_score)
consensus = 100 × (未被任何冲突牵连的已完成任务数 / 已完成任务总数)
无已完成任务 → 0.0。这是一个可解释的真实代理量(仅来自任务状态 + 检出冲突),不是模型主观打分。
3.2 消解(resolve_conflicts)——保守首版
artifact_mismatch:仅当评审accepted=True(评审隐式选定了胜出版本)才标记 resolved;否则 unresolved。review_disagreement:verdict 给出可操作retry_tasks时标记 resolved(蜂群可通过重开任务行动);空泛拒绝无可操作项 → unresolved。test_failure/dependency_inconsistency:视为硬阻断,本版不自动消解,留给重做循环或人工。
每个冲突就地写回 resolved 与 resolution(消解方式或无法消解的原因)。
4. 事件载荷构造器
按 SwarmRuntime.emit_event(run, event_type, payload=...) 约定,每个构造器返回 (event_type, payload),payload 为 JSON 安全 dict:
| 函数 | event_type | 用途 |
|---|---|---|
event_convergence_started |
convergence.started |
收敛评估开始 |
event_conflict_detected |
conflict.detected |
每检出一个冲突 |
event_conflict_resolved |
conflict.resolved |
每消解一个冲突 |
event_consensus_updated |
consensus.updated |
当前共识分与冲突计数 |
event_convergence_reached |
convergence.reached |
终态成功,附 termination_reason |
event_convergence_failed |
convergence.failed |
终态失败/阻断,附 termination_reason |
⚠️ 上述六个
event_type尚未登记进 Manager 事件契约(heicodeagent_callback.go)。在订阅或回调消费前,必须先按下方集成说明走 Manager 侧契约登记,否则属于未登记事件。
5. 测试
..\.venv\Scripts\python.exe scripts\test-convergence.py
模块级、无 WS/Redis/模型。覆盖:两个冲突产物 → 检出 artifact_mismatch + review_disagreement;review_disagreement 可消解、artifact_mismatch 未消解;产出带具体 termination_reason 的 ConvergenceReport;断言每个终态都带 termination_reason;断言至少一个冲突「检出 + 消解」闭环;以及五个终止原因各自的终态用例。全部 PASS。
6. 接入现状与诚实差距(规则 #9)
已接入(main.py: compute_convergence_report + refresh_swarm_run_status,无开关):每次 run 终态装配 run_state(tasks/budget/usage/quality/review_cycles)→ evaluate_convergence → 报告存 run.metadata["convergence"],termination_reason 附到 timeline.updated 载荷。
诚实差距:
- 解释性,非权威:报告不覆盖
run.status(今天 next_status 与报告对 completed/failed 一致)。authoritative 模式(如BLOCKED→置 runblocked)改变 Manager 面终态语义,须先过scripts/test-runtime-contract.py+ 契约评审——列为后续。 - 质量/预算/风险输入有条件:
quality依赖 Group B fixture 评分(绑定 fixture 时);budget/usage需 run 提供;risks需上游注入。缺失时相应原因不触发,回退tasks_completed(不伪造)。 - 消解为保守首版:不做自动 merge / 自动选胜,硬冲突留待重做或人工。
- 收敛事件不进 Manager 流:六个
convergence.*/conflict.*/consensus.*事件构建器已实现但不经emit_event外发(未在 Manageragent_callback.go注册;与swarm.health同策略,避免向订阅全部的回调投递未登记事件)。登记后方可启用 Manager 侧发送。termination_reason以新增可选字段附在timeline.updated,对旧消费方向后兼容。
7. 蜂后收敛闭环(Queen,agent_swarm#8,orchestrator/queen.py)
fan-out 后的「收口」由蜂后(Queen)承担——一个不执行、不分配任务的终态仲裁层,把「任务完成即停」升级为「质量驱动收敛」。对齐公开 Swarm 范式的「感知→决策→交互→更新」迭代循环 + 终止「任务完成 ∨ 质量阈值 ∨ 预算/轮次」。
职责(已实现):
- best-of-N 选最优(M2 / SC-5·6·7):
queen.aggregate_run收集各 agent 候选产物 →score_candidates(共享 test 跑各 impl,复用sandbox.run_tests)→select_best(测试通过率最高,纯函数)。winner 标到deliverable.selected,verdict 存run.metadata["queen"]。这是单模型没有的涌现杠杆。 - 质量门打回(M3 / SC-9):
queen_quality_gate在run_cross_review之后、状态提交之前——最优分 <QUEEN_ACCEPTANCE_THRESHOLD且review_cycles < MAX_REVIEW_CYCLES→reopen_task回灌迭代;达标/触顶 → 收敛。should_bounce为纯函数。 - 失败隔离(M4 / SC-12):单 task 失败不拖垮整个 run;仅「全失败且无完成产物」才 failed,否则交蜂后/convergence 判定。
- 防跨 run 抢夺(P0 / #8):
extract_swarm_from_agent/_agent_belongs_to_run——agent 只能竞争/认领自己 run 的 task;swarm_dispatch过滤、handle_task_bid/yield/takeover拒绝跨 run(cross_run_denied)。
诚实差距:
- 落 main 待端到端:SC-7 的「git push 最优产物到产物仓
main」需 orchestrator 加 git CLI + 凭据持久化;当前先标记 winner(SWE-bench 语境产物是 patch,选最优即够)。 - 质量门默认禁用:需 operator 设
QUEEN_ACCEPTANCE_THRESHOLD才打回;评分依赖沙箱隔离(HEICODE_SANDBOX_ISOLATED),未确认隔离则不评分(unscored ≠ 0,不打回,规则 #9)。 - convergence 全 authoritative(SC-8):质量驱动收敛已由
queen_quality_gate实现;让ConvergenceReport.status完全覆盖run.status(BLOCKED 等)动 Manager 终态语义,列为后续。 - 北极星(M5,后续):在 SWE-bench Pro 50 上对比单 Opus 4.8 的 resolved 率,客观验证涌现是否超越——前提是上述闭环 + 接入真实代码执行环境。
- 测试:
scripts/test-queen.py(select_best + should_bounce)、scripts/test-run-isolation.py(防抢)。