Files
sanguo_moziplus_v2/docs/design/review-v3-vs-head-simayi.md
T
cfdaily 25863634c2 fix: v3.0→HEAD review 修复 — handler 注册 + review verdict + skill 全文注入
基于庞统+司马懿背靠背 review,修复 6 个问题:

P0 致命:
- A1: _legacy_on_complete 补回 review verdict 处理(approved→done,非 approved→@mention assignee)
- A2: 添加 TaskTypeRegistry.register() 启动初始化(注册 Task/Mail/Toolchain handler)

P1 中等:
- B11-1: RoleSkillSection 从索引提示改为全文注入(对齐设计 §2.3 + BootstrapBuilder 行为)
- A8: retry prompt is_mail 硬编码改走 TaskTypeRegistry handler 判断

P2 低:
- _mail_* 4 个方法添加 DEPRECATED 注释
- ticker.py handler check_completion 代码块缩进对齐(28→24 空格)

测试:394 passed, 0 failed
Review reports: docs/design/review-v3-vs-head-{pangtong,simayi}.md
2026-06-11 08:08:20 +08:00

31 KiB
Raw Blame History

v3.0 vs HEAD 背靠背 Review — 司马懿

日期: 2026-06-10 (v2)
范围: v3.0 tag → HEAD6 commits, +1584/-134 行, 9 个文件)
方法: git diff v3.0..HEAD 逐文件逐行比对 + v3.0 源码 git show v3.0: 回溯验证
独立判断: 不参考庞统 review,独立产出后比对


总览

v3.0 → HEAD 的核心改动是 Step 2-5 五层架构重构

新增/改动 说明
Protocol + Registry task_type_registry.py(已有,未改) TaskTypeHandler Protocol + TaskTypeRegistry
基类 base_task_handler.py(新增 +183 BaseTaskHandler — crash/verify/mark/notify 统一流程
Handler × 3 task_handler.py+378)、mail_handler.py+210)、toolchain_handler.py+277 各自实现 build_prompt / verify_completion / post_complete
引擎接入 dispatcher.py-95/+58)、spawner.py+38)、ticker.py+31/-27 _mail_* 硬编码 → TaskTypeRegistry 查表
设计文档 step5-impact-analysis.md+324)、step5-audit-report.md+74 影响分析 + 双重审计

核心结论:架构方向正确,但 handler 注册初始化缺失导致所有 handler 路径为死代码,实际运行仍走 _legacy_on_complete 旧路径。旧路径中 review verdict 处理被删除,造成 非 handler 项目的 review 流程失效


Part A: v3.0 逻辑丢失检查

方法论

逐文件追踪 v3.0 中每个 _mail / _task / project_id == "_mail" 分支,验证 HEAD 中是否存在等价实现。分三层检查:

  1. 功能等价:新代码是否完整覆盖旧逻辑
  2. 路径可达:新代码是否会被实际执行(handler 注册?legacy fallback?)
  3. 行为一致:边界条件、异常处理是否等价

检查结果

A1 🔴 致命:dispatcher.py — review verdict 处理丢失

v3.0 逻辑dispatcher.py L253-308 _task_on_complete):

if _is_review:
    if _task_db and outcome in ("completed", "session_revived"):
        # 读 verdict
        review = conn.execute(
            "SELECT verdict FROM reviews WHERE task_id=? ORDER BY created_at DESC LIMIT 1",
            (_task_id,)).fetchone()
        if review and review["verdict"] == "approved":
            _dispatcher._mark_task_status(_task_db, _task_id, "done")
        else:
            # 非 approved → @mention assignee + 保持 review
            bb.add_comment(_task_id, "daemon", f"@{assignee} 审查结论: {verdict_str}")

HEAD 逻辑dispatcher.py L246-258 _legacy_on_complete):

def _legacy_on_complete(aid, outcome):
    if outcome in ROLLBACK_CURRENT_AGENT_OUTCOMES and _task_db:
        _dispatcher._rollback_current_agent(_task_db, _task_id, aid)
    if not _is_review:  # ← review 时整个 if 被跳过
        _dispatcher._task_auto_complete(_task_id, _task_db)

分析

  • _legacy_on_complete_is_review=True什么也不做——无 verdict 读取、无 done 标记、无 @mention 通知
  • TaskHandler.handle_review_complete() 方法有完整 verdict 处理,但 handler 未注册(见 A2),此代码不可达
  • 影响:所有非 handler 项目(_general 等)的 review agent 完成后,任务永远停在 review 状态

补充rebuttal 路径不受影响——_rebuttal_on_completeticker.py L756-790 独立定义,直接读 verdict 并处理,不经过 _legacy_on_complete


A2 🔴 致命:Handler 注册初始化缺失

证据

$ grep -rn "TaskTypeRegistry.register" src/
# 零结果

TaskTypeRegistry.register() 在整个代码库中从未被调用TaskHandler / MailHandler / ToolchainHandler 类已定义但从未实例化和注册。

后果链

  1. TaskTypeRegistry.get_by_project() 永远返回 None
  2. 所有 if handler: 分支不进入 → 走 else / fallback 路径
  3. TaskTypeRegistry.virtual_projects() 返回空列表 → _mail / _toolchain 不被 ticker 自动发现

各路径受影响分析

路径 dispatcher spawner ticker 实际走什么
Mail _mail handler=None_legacy_on_complete handler=None → 旧 _build_mail_prompt virtual_projects() 空 → _mail 不被 tick 旧路径(无 handler),但 ticker 不扫描 _mail
Task _general handler=None_legacy_on_complete handler=None → BootstrapBuilder 不涉及 handler 旧路径,但 review 处理被删(A1)
Toolchain _toolchain N/A N/A virtual_projects() 空 → _toolchain 不被 tick 完全不可达

⚠️ A2 导致 ticker 不再扫描 _mail 虚拟项目,这是 v3.0 有、HEAD 丢失的行为——v3.0 中 _mail 硬编码在 ticker L218-229HEAD 改为 TaskTypeRegistry.virtual_projects() 但注册为空。

需要添加的初始化代码(缺失):

# 应在 server.py 或 bootstrap.py 的启动流程中
from src.daemon.task_handler import TaskHandler
from src.daemon.mail_handler import MailHandler
from src.daemon.toolchain_handler import ToolchainHandler

TaskTypeRegistry.register(TaskHandler())
TaskTypeRegistry.register(MailHandler())
TaskTypeRegistry.register(ToolchainHandler())

A3 🟡 中等:dispatcher.py — 旧 _mail_* 方法成为死代码

v3.0_mail_auto_working / _mail_auto_complete / _mail_check_reply / _mail_revert_to_pendingdispatch() 主流程调用。

HEAD:这些方法仍保留在 dispatcher.py 中(L628-860),但主流程已改走 handler 路径。由于 handler 未注册,主流程走 _legacy_on_complete(无 handler 分支),也不调用这些方法。

结论:方法体保留但无外部调用者,属于死代码。不影响当前运行(因为 _legacy_on_complete 有独立的 executor 逻辑),但增加维护混淆。


A4 🟢 低:dispatcher.py — spawn 失败回退等价

v3.0self._mail_revert_to_pending(task.id, db_path) — 调独立方法。 HEAD:内联代码(L309-327),BEGIN IMMEDIATE + 状态检查 + UPDATE ... SET status='pending'

等价:新版逻辑更通用(不限于 _mail,任何 handler 项目都可回退)。


A5 🟢 低:dispatcher.py — _legacy_dispatch 路径 handler 化

v3.0is_mail_legacy = project_id.get("project_id") == "_mail" HEADhandler_legacy = TaskTypeRegistry.get_by_project(project_id_legacy)

等价handler_legacy 为 None 时跳过 pre_spawn,与 v3.0 中 is_mail_legacy=False 行为一致。_legacy_dispatch 本身仅在 router=None 时触发,当前配置不会进入。


A6 🟢 低:spawner.py — prompt 构建双路径

v3.0if project_id == "_mail": return self._build_mail_prompt(...) → 走 BootstrapBuilder。 HEADhandler = TaskTypeRegistry.get_by_project(project_id)if handler: return handler.build_prompt(ctx) → else 走 BootstrapBuilder。

分析

  • handler 未注册时,等价于 v3.0(走 BootstrapBuilder
  • handler 注册后,Task/Mail/Toolchain 走新 PromptSection 路径
  • 注意:新旧路径的 Skill 注入策略不同——旧路径(BootstrapBuilder全文注入 Skill,新路径(RoleSkillSection)只给索引+引导语。这可能导致 handler 注册后 Agent 行为变化

A7 🟢 低:spawner.py — _build_api_section success_status

v3.0success_status = '"done"' if project_id == "_mail" else '"review"' HEADsuccess_status = '"done"' if handler.target_success_status == "done" else '"review"'

等价handler 未注册时走 else 分支 → '"review"',与 v3.0 非 mail 项目一致。


A8 🟡 中等:spawner.py — retry prompt 仍用硬编码

v3.0is_mail = project_id == "_mail" → 用 MAIL_RETRY_PROMPT 模板。 HEAD:同样 is_mail = project_id == "_mail" 硬编码(L1128),未改走 handler。

影响:不影响功能(retry prompt 正确),但与设计文档 §6 不一致。属于 Step 5 未覆盖的遗留点。


A9 🟢 低:ticker.py — 虚拟项目扫描

v3.0:硬编码 _mail 扫描。 HEADTaskTypeRegistry.virtual_projects() 循环。

分析:逻辑正确,但注册为空时 _mail 不被扫描(见 A2)。注册后自动发现 _mail + _toolchain,比 v3.0 更可扩展。


A10 🟢 低:ticker.py — assignee 清空条件

v3.0if self._current_project_id == "_mail": → 不清空 assignee。 HEADhandler = TaskTypeRegistry.get_by_project(...); if handler: → 不清空。

等价handler 未注册时,非 handler 项目正常清空 assignee。


A11 🟢 低:ticker.py — 跳过 claimed 状态

v3.0if project_id == "_mail": → 跳过 claimed,直接 working。 HEADhandler = TaskTypeRegistry.get_by_project(project_id); if handler: → 跳过。

等价


A12 🟢 低:ticker.py — review dispatch 跳过

v3.0if project_id == "_mail": return [] HEADhandler = TaskTypeRegistry.get_by_project(project_id); if handler: return []

等价


A13 🟢 低:ticker.py — 超时检查幻觉门控

v3.0

if self._current_project_id == "_mail":
    has_reply = self._mail_check_reply(task.id, db_path)
    if has_reply:
        ... # mark done

HEAD

handler = TaskTypeRegistry.get_by_project(self._current_project_id)
if handler and handler.check_completion(task.id, db_path):
    ... # mark done

等价MailHandler.check_completion 内部调 _check_reply,查询语义与 v3.0 的 _mail_check_reply 完全一致(SELECT id FROM tasks WHERE id != ? AND must_haves LIKE ?)。

缩进问题HEAD L1483 if handler and handler.check_completion(...): 后续 body 缩进 5 级(28 空格),与同级代码不一致。不影响运行,但增加维护混淆。


A14 🟢 低:ticker.py — startup recovery 虚拟项目列表

v3.0for virtual_id in ("_general", "_mail"): HEADvirtual_ids = ["_general"] + TaskTypeRegistry.virtual_projects()

等价:注册为空时只有 _general,注册后自动包含 _mail + _toolchain


Part A 汇总

严重度 数量 项目
🔴 致命 2 A1 review verdict 丢失, A2 handler 未注册
🟡 中等 2 A3 死代码未清理, A8 retry prompt 硬编码
🟢 10 A4A7, A9A14

A1+A2 联合根因分析

设计意图是 handler 注册后 review 走 TaskHandler.post_completehandle_review_complete。但注册代码缺失导致:

  1. 所有项目走 _legacy_on_complete(旧路径)
  2. 旧路径中 review 处理被删除(信任 handler 会处理)
  3. review agent 完成后无任何后续动作

同时ticker 不再扫描 _mail 虚拟项目(原来硬编码扫描),_mail 项目的 pending 任务无人处理。


Part B: 13 个重点专题设计-编码一致性

逐专题检查设计文档描述与 HEAD 代码的一致性。标记:

  • 一致
  • ⚠️ 设计已标注未实施/Phase N(不算差异)
  • 设计承诺但代码不一致
  • 🟡 部分一致

B1: 专题 01 四相循环

设计文档01-four-phase-loop.md — PRD Phase 1~4 完整实现方案

# 设计要求 代码现状 判定
B1-1 §3.3 Spawn Prompt 框架(任务+约束+API+准则+完成标准) BootstrapBuilder + PromptSection 实现
B1-2 §3.4 @mention 通知机制 _process_mentions + mention_queue
B1-3 §4 Review 机制(verdict → done/notify TaskHandler.handle_review_completehandler 未注册)+ _rebuttal_on_completeticker 独立) ⚠️ handler 路径不可达,但 rebuttal 路径完整

B2: 专题 02 Main Session + Delegation

设计文档02-main-session-delegation.md

# 设计要求 代码现状 判定
B2-1 §3.1 投递到 Main Session use_main_session=True 参数
B2-2 §3.3 续杯机制 use_main_session=True + session 复用
B2-3 §4.3 消息优先级与中断策略 无优先级队列 ⚠️ 设计描述但未标注 Phase
B2-4 §4.4 Subagent 背压控制 无显式背压,靠 counter 间接控制 ⚠️

B3: 专题 03 Prompt 进化

设计文档03-prompt-evolution.md — 从 SOP 到任务式指挥

# 设计要求 代码现状 判定
B3-1 §3.1 广播认领模板改写 PromptSection 组装(新路径)+ BootstrapBuilder(旧路径)
B3-2 P6 反静默降级 scope-reduction-detection 自动机制 ⚠️ 设计原则,未强制实施
B3-3 P7 经验闭环 无 IMPROVE 阶段自动触发 ⚠️

B4: 专题 04 黑板协作模型

设计文档04-blackboard-collaboration-model.md

# 设计要求 代码现状 判定
B4-1 §3.1 assignee 降级为显示字段,路由走 @mention router.py L160-166 仍有 assignee 快速路径 ⚠️ 设计说 Phase 1 双轨并行,Phase 2 废弃。当前停在 Phase 1
B4-2 §3.2 @mention 语义增强 mention_queue + comment_type 已实现
B4-3 §3.3 多人协作 co_assignees 数据库无此字段 ⚠️ Phase 3
B4-4 §3.4 output↔comment 关联 无关联字段 ⚠️ Phase 2
B4-5 §3.5 层级查询 API parent_task 支持

B5: 专题 05 上下文四层架构

设计文档05-context-layers.md

# 设计要求 代码现状 判定
B5-1 L0 铁律层 workspace 文件注入(SOUL.md/IDENTITY.md 等)
B5-2 L1 角色层 SOUL.md / IDENTITY.md
B5-3 L2 引擎注入层 BootstrapBuilder 实现
B5-4 L3 被动参考层(wiki knowledge _inject_wiki_knowledge ⚠️ 设计标注为 Phase 2

B6: 专题 06 PM2 Crash 恢复

设计文档06-pm2-crash-recovery.md

# 设计要求 代码现状 判定
B6-1 §4.1 总体流程 _startup_recover ticker.py L1614 有启动恢复
B6-2 §4.2 claimed 状态恢复
B6-3 §4.2 working 状态恢复 _recover_working_task
B6-4 §4.2 review 状态恢复 _recover_review_task

B7: 专题 07 Spawner Acquire-First

设计文档07-spawner-acquire-first.md — #07.1 已实施, #07.2 已实施

# 设计要求 代码现状 判定
B7-1 Phase 0 Pre-acquire 修复 spawner.py L499-512
B7-2 Phase 1 Counter acquire spawner.py L516-521
B7-3 Phase 2 Session check spawner.py L523-568
B7-4 Phase 2.5 假死修复 spawner.py L557-568

B8: 专题 08 Classify Outcome 优化

设计文档08-classify-outcome-optimization.md — 已实施

# 设计要求 代码现状 判定
B8-1 A0-A17 判定树 _classify_outcome 方法
B8-2 A9 api_error 特殊路径 api_retry_count
B8-3 A14-A17 可恢复 retry + cooldown 60s cooldown_seconds + set_cooldown

B9: 专题 09 Rebuttal + Goal Gate

设计文档09-rebuttal-and-goal-gate.md

# 设计要求 代码现状 判定
B9-1 §2.1 Rebuttal 自动化(review 非 approved → @mention assignee review.py RebuttalManager + ticker.py _rebuttal_on_complete
B9-2 §2.1 防止无限循环(max 2 轮) RebuttalManager.MAX_ROUNDS = 2
B9-3 §2.2 目标一致性 Gate 无自动 goal gate 检查 ⚠️ 设计为 Agent 端行为,非 Daemon 侧

B10: 专题 10 T3 需求探索 + 黑板展示

设计文档10-t3-requirement-exploration-and-blackboard-display.md

# 设计要求 代码现状 判定
B10-1 A2 需求探索过程写黑板 comments 后端支持 comment_type
B10-2 A3 TaskModal 实时刷新 SSE comment_added / checkpoint_resolved
B10-3 D1 砍掉 AI 摘要 黑板直投前端
B10-4 D2 SSE 只做通知 前端按需拉数据

B11: 专题 11 上下文四层重设计

设计文档11-context-layers-redesign.md

# 设计要求 代码现状 判定
B11-1 §2.3 L2 操作规范型 6 个 Skill 全文注入 BootstrapBuilderROLE_SKILL_MAP + _read_skill 全文注入 task_handler.py RoleSkillSection 只给索引+引导语 ⚠️ 🟡 双路径并存,策略矛盾
B11-2 §2.3 handoff.schema.json 不存在 ⚠️ Phase 3
B11-3 §2.3 review_protocols/ 目录 不存在,但 review-quality Skill 文件存在 ⚠️ 设计文档 §三归属表已改归类为 L3 Skill
B11-4 §6 Phase 3 Step 6-8 BootstrapBuilder 改造 已完成(ROLE_SKILL_MAP + _read_skill
B11-5 §2.3 token 预算 ~600 tokens bootstrap.py 有 warn 但不截断 🟡 有告警无硬限制

B11 关键发现:新旧路径的 Skill 注入策略矛盾——

  • 旧路径(BootstrapBuilder):全文注入 Skill_read_skill 读文件全文)
  • 新路径(RoleSkillSection):只给索引"请用 read 工具读取 SKILL.md"
  • 设计文档 §2.3 要求 "A 类 Skill 全文注入"
  • handler 注册后会从旧路径切换到新路径,导致 Skill 从全文注入降级为索引提示

这是一个 隐性回归:注册 handler 后 Agent 获取的操作规范信息量大幅减少。


B12: 专题 12 Pipeline 设计

设计文档12-pipeline-design.md

# 设计要求 代码现状 判定
B12-1 §3 Pipeline 注册表 不存在 ⚠️ 设计 §9 标注 Phase 2
B12-2 §4 路由逻辑 task_type router.py 无 task_type 路由
B12-3 §8 PipelineRegistry 不存在
B12-4 §10.1 task_type 默认值改 None blackboard_routes.py 已为 Nonev3.0 已修) 已实施
B12-5 §10.2 广播计数器修正 _broadcast_tracker + BroadcastRound 已实现 已实施

B12 结论:Pipeline 主体未实施符合设计路线图(Phase 2),但 §10 Phase 1 的两个 bug fix 明确标注为"立做"却未执行。


B13: 专题 13 工具链与开发工作流

设计文档13-toolchain-and-dev-workflow.md

# 设计要求 代码现状 判定
B13-1 §16 工具链事件中枢 toolchain_handler.py + toolchain_templates.py
B13-2 Gitea webhook 处理 5 模板 + 去重
B13-3 CI 前缀 [CI]

Part B 汇总

判定 数量 主要项目
一致 21 B1-1, B1-2, B2-1/2, B3-1, B4-2/5, B5-1/2/3, B6-14, B7-14, B8-13, B9-1/2, B10-14, B11-4, B13-1~3
🟡 部分一致 3 B11-1 双路径策略矛盾, B11-5 token 预算无硬限制
⚠️ 设计标注未实施 10 B1-3handler 不可达), B2-3/4, B3-2/3, B4-1/3/4, B5-4, B9-3, B11-2/3
设计承诺未交付 0

Step 5 审计报告偏差项验证

step5-audit-report.md 列出 6 项偏差(D1-D6)。逐项验证 HEAD 代码:

# 审计描述 HEAD 实际状态 判定
D1 pre_spawn 返回值未检查 已修复if not _handler.pre_spawn(...): raise RuntimeError("handler_pre_spawn_failed") 已修
D2 PromptContext 缺少 from_agent/mail_type 已修复spawner L289-296 从 must_haves JSON 提取 已修
D3 inform outcome 白名单缺失 未修复。但影响极小——CRASH_OUTCOMES 由基类处理,剩余异常 outcome 罕见 🟢 可接受
D4 retry prompt 仍用 is_mail 硬编码 未修复spawner L1128 仍硬编码 is_mail = project_id == "_mail" 🟡 遗留
D5 _check_reply 语义差异 已修复MailHandler._check_reply 用 SELECT id FROM tasks WHERE id != ? AND must_haves LIKE ?,与 v3.0 一致 已修
D6 标 done 重试机制 已修复BaseTaskHandler._mark_task_status 有 3 次重试 已修

结论D1/D2/D5/D6 已在后续 commit 修复,D3 可接受,D4 是遗留项。


与庞统 Review 的背靠背比对

维度 司马懿 庞统 差异分析
致命问题 A1 review verdict 丢失 + A2 handler 未注册 仅 #1 review verdict 丢失 关键差异:庞统未将 handler 未注册列为致命问题。庞统认为 _legacy_on_complete 仍可运行所以只关注 review 路径。但我认为 ticker 不再扫描 _mail 是 v3.0 有、HEAD 丢失的行为,这比 review 路径更严重——Mail 系统完全停止工作
_mail tick 丢失 明确指出 A2 导致 ticker 不扫描 _mail 未提及 庞统漏检了 virtual_projects() 返回空时 _mail 不被 tick 的后果
Skill 注入降级 B11-1 发现新旧路径策略矛盾 未提及 庞统未分析 handler 注册后 Skill 注入策略的变化
D1/D2/D5 修复状态 验证了审计报告的修复项 未验证 庞统的 review 早于修复 commit
专题覆盖范围 13 个全覆盖 13 个全覆盖 一致
D4 retry 硬编码 A8 独立发现 B4 独立发现 独立确认

建议优先级

优先级 项目 说明
P0 A2 handler 注册初始化 添加 TaskTypeRegistry.register() 启动代码。这是所有 handler 路径的前提
P0 A1 review verdict 处理 P0 修复后自然恢复(TaskHandler.handle_review_complete 生效)。但如果不想立即注册 handler,需先在 _legacy_on_complete 中恢复 review verdict 逻辑作为 interim fix
P1 B11-1 Skill 注入策略对齐 注册 handler 后 RoleSkillSection 只给索引——需确认这是有意降级还是遗漏。如果是遗漏,RoleSkillSection 应全文注入
P1 A8 retry prompt handler 化 spawner L1128 is_mail 硬编码改走 handler
P2 A3 死代码清理 _mail_auto_working / _mail_auto_complete 等方法在 handler 注册后确认不再需要再删除
P2 B12-4/5 已验证 v3.0 tag 时已修复,不需要再改
P3 ticker.py L1483 缩进对齐 风格问题

Cross-Check:庞统 Review 逐项验证

对庞统 review-v3-vs-head-pangtong.md 的每个发现,独立验证:是不是真问题?根因对不对?修复方案对不对?


Part A 逐项验证

庞统 #1 🔴 review verdict 丢失

庞统判定:致命。"仅影响非 handler 项目(_general"。

我的验证

  1. 是致命问题 —— _legacy_on_complete_is_review=True 时确实什么都不做。

  2. "仅影响非 handler 项目" — 表述不准确。实际情况更复杂:

    • _general 项目确实受影响(走 _legacy_on_complete
    • _mail / _toolchain 不受影响,不是因为"handler 正确处理",而是因为它们根本不走 review 流程ticker 中 _dispatch_reviews 对 handler 项目 return []
    • 庞统说"handler 项目(_mail/_toolchain)的 review 由 TaskHandler.post_complete 正确处理"——这个说法有误导性。TaskHandler 不是 _mail/_toolchain 的 handler,它们各自的 handlerMailHandler/ToolchainHandler)没有 handle_review_complete 方法。它们不走 review 是因为设计上就不走。
  3. 庞统的修复方案有隐藏缺陷。庞统说"让非 handler 项目也走 TaskHandler(注册 _general 到 TaskTypeRegistry"。但 TaskTypeRegistry.get_by_project() 匹配的是 handler.virtual_project,而 TaskHandler 的 virtual_project = None。所以:

    • get_by_project("_general") → 遍历所有 handler,检查 h.virtual_project == "_general" → TaskHandler 的 virtual_projectNone不匹配 → 返回 None
    • 即使注册了 TaskHandler_general 项目仍然走 _legacy_on_complete
    • 庞统的修复方案需要额外改 TaskHandler.virtual_project 或 registry 匹配逻辑,但他没指出这一点

结论:问题是真的,严重度判定正确。但影响范围描述和修复方案都不完整。


庞统 #2 🟢_mail_* 方法保留

庞统判定:正常重构,方法体保留标记为 deprecated。

我的验证

  1. 方法体确实保留 dispatcher.py L628-860
  2. 但"标记为 deprecated"不对——代码中没有 @deprecated 装饰器或注释。这些方法就是安静地躺在那里,没有任何标记告诉维护者"别用了"
  3. **我标 🟡 中等而非 🟢**的原因:无 deprecated 标记 + 主流程不再调用 = 未来维护者容易误用

结论:问题不大,但庞统多给了信息("标记为 deprecated")——代码中实际没有标记。


庞统 #3 🟢 spawn 失败回退

庞统判定:逻辑改进。

我的验证 确认等价,新版更通用。


庞统 #4-5 🟢 spawner prompt/api_section

庞统判定:等价实现。

我的验证 确认等价。


庞统 #6 🟢 ticker _mailvirtual_projects()

庞统判定:正常重构,可扩展。

我的验证这是庞统最大的漏检

庞统只看了代码方向(硬编码 → 注册表),没有检查注册表是否为空

实际运行时 TaskTypeRegistry.virtual_projects() 返回空列表 → _mail 不被 ticker 扫描。这是一个 v3.0 有、HEAD 丢失的行为——v3.0 中 _mail 硬编码在 ticker L218-229HEAD 中完全消失。

后果:所有 Mail 任务的 pending → claimed → working 流程中断,整个飞鸽传书系统停止工作。

这不是"正常重构",是致命回归


庞统 #7-8 🟢 ticker check_reply / dispatch_reviews

庞统判定:等价实现。

我的验证 确认等价。但 #7 说"缩进正确"——实际 ticker.py L1483 有缩进不一致(28 空格 vs 同级 24 空格),不影响运行但增加维护混淆。


Part B 逐专题验证

专题 01-03:无分歧

庞统的检查和我的结论一致。设计原则未强制实施属于正常。


专题 04:庞统更严格

庞统把 B4-3co_assignees)和 B4-4output↔comment)标 ,我标 Phase 2/3)。

庞统的判定更严格——"设计了但没实现就是不一致" vs 我的"设计自身标注了 Phase,未实施是预期的"。两种视角都有道理,不算错误


专题 05:判定标准差异

庞统把 B5-4(L3 wiki 知识注入)标 。我标 Phase 2)。

同专题 04,判定标准差异。


专题 06:庞统更细致

庞统多了 B6-5"设计提到 7 个恢复方法只看到 2 个公开方法"——这是一个合理的疑问,我没有提出。


专题 07-10:无分歧


专题 11:庞统全标 是错的

庞统 B11-1 说"BootstrapBuilder 只注入通用 prompt,无 skill 全文注入"。

我验证了代码

# bootstrap.py L29
ROLE_SKILL_MAP = {
    "executor": "blackboard-executor",
    "reviewer": "blackboard-reviewer",
    ...
}

# bootstrap.py L68-72
skill_name = self.ROLE_SKILL_MAP.get(role)
if skill_name:
    skill_content = self._read_skill(skill_name)  # 读全文
    if skill_content:
        sections.append(skill_content)

BootstrapBuilder 有 Skill 全文注入。庞统说"无 skill 全文注入"与代码不符。他可能只看了 task_handler.py 的 RoleSkillSection(确实只给索引),没有看 bootstrap.py 的旧路径。

实际情况:双路径并存。旧路径(BootstrapBuilder)全文注入,新路径(RoleSkillSection)只给索引。handler 注册后从旧路径切换到新路径,Skill 信息量降级。这才是真正的问题。


专题 12:我之前的 B12-4/5 判定有误

我在 Part B 中说"B12-4 task_type 默认值仍为 \"coding\""和"B12-5 广播计数器 retry_count 不递增"是 Phase 1 承诺未交付。

cross-check 时我重新验证了代码

  • B12-4blackboard_routes.py L138 已是 body.get("task_type", None)默认值已经是 None。v3.0 tag 中也是 None。设计文档 §10.1 的 bug fix 可能在 v3.0 之前就修了,或者设计文档基于旧版本写的。不是问题,我之前的判定有误。

  • B12-5ticker.py_broadcast_tracker + BroadcastRound + round_number >= 3 升级庞统的机制已实现。mark_mention_retryretry_count = retry_count + 1。设计 §10.2 描述的问题已在 v3.0 或更早修复。不是问题,我之前的判定有误。

庞统对专题 12 的判定("设计文档 §9 自身标记为待实现")比我准确。

修正我的报告Part B 中 B12-4 和 B12-5 应从 改为 (设计自标 Phase 2,主体未实施是预期的)。


专题 13:无分歧


庞统未引用 Step 5 审计报告

庞统的 review 完全没引用 step5-audit-report.mdv3.0..HEAD diff 中新增的文件)。这意味着 D1/D2/D5 的修复状态未经庞统验证。我逐项验证了 D1/D2/D5 已修复D4 未修复retry 硬编码),D3 可接受D6 已修复


庞统漏检的额外行为回归

handler 未注册还导致一个庞统完全没提到的问题:

guardrail 回归。v3.0 中 dispatcher L127-128

is_mail = project_config.get("project_id") == "_mail" if project_config else False
if self.guardrails and not is_mail:

HEAD dispatcher L128-131

handler = TaskTypeRegistry.get_by_project(project_config.get("project_id", "") ...)
is_handler_task = handler is not None
if self.guardrails and not is_handler_task:

handler 未注册 → is_handler_task = False_mail 项目也要过 guardrail 检查了。v3.0 中 _mail 是跳过 guardrail 的。这可能导致某些 Mail 任务被 guardrail 拦截。


Cross-Check 总结

维度 庞统 review 质量
致命问题发现 发现 A1 ,漏检 A2handler 注册 + ticker 不可达 + guardrail 回归)
根因分析 A1 根因正确。修复方案不完整(没指出 TaskHandler.virtual_project=None 导致注册也匹配不到 _general
Part B 专题覆盖 13/13 全覆盖
Part B 事实准确性 B11 "无 skill 全文注入"与代码不符 。B12 比我准确
Part B 多给信息 #2 说"标记为 deprecated"但代码无标记 ⚠️
Part B 更严格处 B04-3/4 标 (合理),B06-5 恢复方法数量疑问(合理)
审计报告验证 未引用,未验证 D1-D6 修复状态
遗漏的行为回归 guardrail 对 _mail 的回归

我的自我修正B12-4/5 判定有误,应改为 。v3.0 tag 时这两个问题已修复,设计文档描述的是更早期的问题。


— 司马懿 仲达,质量总监 🗡️