Files
sanguo_moziplus_v2/docs/design/09-rebuttal-and-goal-gate.md
T
cfdaily eccb4d2723
CI / lint (pull_request) Successful in 7s
CI / test (pull_request) Successful in 9s
CI / notify-on-failure (pull_request) Successful in 0s
docs: 设计文档编号重排(20→14, 24→15) + 已完成文档状态标注更新
2026-06-13 10:12:39 +08:00

11 KiB
Raw Blame History

#09 Rebuttal 流程自动化 + 目标一致性 Gate

版本: v1.1 日期: 2026-06-03 作者: 庞统(副军师) 状态: 已完成(rebuttal on_complete + goal gate 已实现) 前置: #04 黑板协作(@mention+ #08 Classify Outcome 关联: T4 审查体系完善 变更: v1.1 纳入司马懿评审反馈 — verdict 读 reviews 表 + rebuttal mention spawn 带 on_complete 回调

讨论决策记录

D1: 庞统持续 session

结论:不做 openclaw 层面的持续 session(受 openclaw 机制限制)。改为两个场景确保目标一致性:

  1. Round review(已实现 )— 子任务完成后庞统审查
  2. 过程中 agent 沟通(本设计覆盖)— agent 遇到问题问庞统时,庞统保持和目标高度一致,防止需求降级

D2: 动态规划 / Replan

结论:不需要专门的 replan 模块。在当前架构中 replan 已通过自然组合实现:

  • Task 失败 → crash_limit 标 failed → round review → 庞统看全局后决定调整
  • Task 产出改变理解 → agent 自主读黑板(#05 上下文注入)→ agent 自己判断调整
  • 发现新依赖 → 庞统在 round review 中发现 → 创建新子任务
  • 依赖链自动推进 → _advance_dependenciesblocked→pending
  • Per-task timeout + crash limit → _check_timeoutsdeadline 优先,默认 30mcrash 3/30m 标 failed

不做独立的 replan 代码模块。

D3: Rebuttal 触发方式

结论:靠 agent 自主 + @mention 现有机制,不做 daemon 层面的自动触发。原因:

  1. 减少系统复杂度
  2. Agent 有自主判断能力(#05 上下文注入)
  3. @mention 机制已成熟(#04

D4: B8 BUG-7 planning 暂停

结论planning 状态已从状态机中移除,BUG 不再存在。但前端 resume 映射为 executing(非法状态),应改为恢复到 resumed_from 记录的状态。记为后续前端修复项。

D5: 司马懿评审反馈(v1.0 → v1.1)

问题1verdict 读取方式 → on_complete 回调中从 reviews 表查最新 verdictSELECT verdict FROM reviews WHERE task_id=? ORDER BY created_at DESC LIMIT 1),和 ticker _recover_review_task 一致。

问题2:review 保持状态不会被重复 dispatch → 确认无问题,_dispatch_reviews 已有 if reviews: continue 保护。

问题3rebuttal @mention 缺 on_complete → 选方案 1mention spawn 带回调。触发条件:task status=review + comment_type=rebuttal → spawn 时带 _review_on_complete 回调。改动点在 _process_mentions,约 10 行。

问题4assignee 而非 current_agent → 确认 @mention 对象用 assignee(执行者),不用 current_agent(审查者)。

MAX_ROUNDS 确认RebuttalManager.MAX_ROUNDS = 2rebuttal round 1(司马懿重审)+ rebuttal round 2(庞统仲裁)= 2 轮。对齐。


一、问题陈述

1.1 Rebuttal 缺失

当前审查流程:

Agent 完成 → review → 司马懿审查 → verdict(approved/rejected/needs_revision) → 结束

问题:审查结论是单方面的。Agent 对 rejected/needs_revision 没有反驳渠道。尤其是:

  • 复杂设计方案,司马懿可能误判
  • 需求降级场景,agent 认为自己做了正确的事但被 reviewer 要求改回去
  • 没有 1-2 轮辩论,结论质量无法保证

已有基础

  • RebuttalManager 类已实现(2 轮反驳,round 1→司马懿重审,round 2→庞统仲裁)
  • comment_type 支持 rebuttalrebuttal_responsedebate_argument
  • reviews 表结构完整

缺什么ticker/dispatcher 层面没有自动串联 rebuttal 流程。submit_rebuttal 存在但无人调用。

1.2 目标一致性 Gate

当前 agent 遇到需求不清晰时:

  • executor prompt 说"不确定时停下来问(黑板 comment"
  • @mention 机制可以把庞统 spawn 起来

缺什么

  1. executor/reviewer prompt 没有明确指引"需求不清晰时 @pangtong-fujunshi 提问"
  2. 庞统收到提问时,没有注入原始任务目标和验收标准来校准回答
  3. 庞统的回复可能无意中做了需求降级("这个太复杂了,简化一下吧")

二、设计方案

2.1 Rebuttal 自动化流程

流程图

Agent 完成任务 → review
  → 司马懿审查 → verdict
    ├─ approved → done(无争议)
    ├─ rejected/needs_revision → 通知被审 agent
    │   → Agent 选择:
    │     ├─ 接受 verdict → 按 verdict 修改 → 重新提交 review
    │     └─ 反驳 → submit_rebuttal(黑板 comment_type=rebuttal
    │       → Ticker 检测到 rebuttal → spawn 司马懿重审(round 2
    │         ├─ 司马懿改判 → done/needs_revision
    │         └─ 司马懿坚持 → 通知庞统仲裁(round 3,最终轮)
    │           → 庞统裁决 → done/needs_revision/创建新任务
    └─ rebuttal 最多 2 轮,超限庞统最终裁决)

触发机制

关键设计决策:谁触发 rebuttal?

不是 daemon 自动触发,而是 agent 自主选择。流程:

  1. 司马懿审查完成 → verdict 写入 reviews 表 + comment_type=review
  2. Ticker 检测到新 review verdict → 通知被审 agent@mention agent
  3. Agent 看到 verdict + 自己的产出 → 决定接受或反驳
  4. 如果反驳 → agent 写 comment_type=rebuttal + @simayi-challenger
  5. Ticker 的 mention 处理循环 spawn 司马懿重审
  6. 司马懿重审后如果坚持 → @pangtong-fujunshi 请求仲裁
  7. 庞统仲裁 → 最终结论

这个流程几乎不需要新代码——主要靠 @mention 现有机制 + prompt 引导。

需要改的代码

文件 改动 说明
dispatcher.py _task_on_complete 修改 review completed → 读 verdict → approved 标 done / 非 approved @mention assignee
ticker.py _process_mentions 修改 rebuttal mention spawn 时带 _review_on_complete 回调
prompt_templates/executor.md 修改 加入“需求不清晰时 @pangtong-fujunshi 提问”
prompt_templates/reviewer.md 修改 加入 rebuttal 流程指引
prompt_templates/review_pangtong.md 修改 加入仲裁指引 + 目标一致性检查
prompt_templates/review_simayi.md 修改 加入 rebuttal 处理指引

_task_on_complete 改动细节(dispatcher.py

当前逻辑(L244-250):review completed → 直接标 done。

改为:

if _is_review:
    if 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 被审 agent(用 assignee,非 current_agent
            task = conn.execute("SELECT assignee FROM tasks WHERE id=?", (_task_id,)).fetchone()
            if task and task["assignee"]:
                bb.add_comment(_task_id, "daemon",
                    f"@{task['assignee']} 审查结论: {review['verdict'] if review else '未知'},请查看详情并决定接受或反驳",
                    comment_type="review")
            # 不标 done,保持 review
    else:
        # crash/error → 保持 review 等 ticker 处理
        pass

_process_mentions 改动细节(ticker.py

当前 mention spawn 不带 on_complete。rebuttal 场景需要带,否则新 verdict 无人处理。

触发条件:task status=review + mention 的 comment_type 包含 rebuttal

# 在 mention spawn 时检查:如果是 rebuttal 场景
has_rebuttal = any(
    item.get("comment_type") == "rebuttal"
    for item in items
)
task_status = bb.get_task(items[0]["task_id"]).status if items else None

if has_rebuttal and task_status == "review":
    # rebuttal 重审:带 on_complete 回调处理新 verdict
    result = await self.spawner.spawn_full_agent(
        agent_id=agent_id,
        message=prompt,
        task_id=tid,
        use_main_session=True,
        on_complete=_review_on_complete,  # 处理新 verdict
    )
else:
    # 普通 mention:不带回调
    result = await self.spawner.spawn_full_agent(
        agent_id=agent_id,
        message=prompt,
        task_id=tid,
        use_main_session=True,
    )

其中 _review_on_complete 复用 dispatcher 中 review verdict 的处理逻辑(读 verdict → approved 标 done / 非 approved @mention)。

防止无限循环

  • RebuttalManager.MAX_ROUNDS = 2(已有,rebuttal round 1 司马懿重审 + round 2 庞统仲裁)
  • 超过 2 轮 → 庞统最终裁决
  • 每个 review 记录在 reviews 表中,rebuttal_count 可追溯
  • _dispatch_reviews 已有 if reviews: continue 保护,有 review 结论的任务不会被重复 dispatch

2.2 目标一致性 Gate

Agent 端

executor.md 改动

在"工作方式"和"约束"之间新增一节:

## 需求不清晰时的处理
- 任务描述有歧义、验收标准不明确、多个理解方式 → @pangtong-fujunshi 提问
- 不要自行假设。宁可多问一句,也不要做错方向
- 提问时:列出你的理解、可能的选项、你倾向的方案,让庞统确认
- 庞统回复后,以回复为准继续执行

庞统端

review_pangtong.md 改动

新增"代理提问处理"部分:

## 回答 Agent 提问时的原则
- 对照原始任务目标和验收标准回答,不做需求降级
- 如果 agent 觉得目标太难 → 讨论替代方案,但必须说清楚代价(缩小的范围、降低的质量)
- 如果原始目标确实不可行 → 升级用户,不要自己做主降级
- 回答要具体到可操作,不要给模糊方向

Bootstrap 注入

当庞统被 @mention spawn 回答问题时,bootstrap 已经会注入任务上下文(#05 L2 层)。不需要额外改动。

2.3 司马懿 Rebuttal 处理

reviewer.md / review_simayi.md 改动

## Rebuttal 处理
- 被反驳时,重新审视自己的结论
- 如果 agent 的反驳有理有据 → 改判
- 如果坚持原判 → 给出更具体的理由,不要只说"我认为不行"
- Rebuttal 不是对抗,是共同追求正确答案
- 第 2 轮 rebuttal 如果仍无法达成一致 → @pangtong-fujunshi 请求仲裁

三、改动总览

文件 改动 行数
src/daemon/ticker.py review verdict 非 approved 时 @mention 被审 agent ~15 行
prompt_templates/executor.md 新增"需求不清晰时 @pangtong-fujunshi" ~8 行
prompt_templates/reviewer.md 新增 rebuttal 处理指引 ~8 行
prompt_templates/review_pangtong.md 新增仲裁指引 + 反需求降级 ~10 行
prompt_templates/review_simayi.md 新增 rebuttal 处理指引 ~8 行
净增 ~49 行

四、验收标准

  1. 司马懿审完 rejected/needs_revision → 自动 @mention 被审 agent
  2. Agent prompt 明确引导"需求不清晰 → @pangtong-fujunshi"
  3. 庞统回复时对照原始目标,不做需求降级
  4. Rebuttal 最多 2 轮,超限庞统裁决
  5. 现有测试不 regression

五、不做的事

  • 不做 daemon 层面的自动 rebuttal 触发(靠 agent 自主 + @mention
  • 不做专门的 rebuttal API 端点(复用 comment + mention
  • 不做 rebuttal 状态机扩展(复用 RebuttalManager 已有逻辑)