Skip to content
项目研究
超凡95 / 100
证据34/35原创24/25结构18/20实用19/20
AI 团队同时交回三份报告,怎样保证验收没有串账?
数字员工 · 项目研究

AI 团队同时交回三份报告,怎样保证验收没有串账?

展示可以辅助挂树,验收必须核对唯一任务身份、执行轮次、版本替代与独立 QA。

MANUAL-20260820-REPORT-ATTRIBUTIONCommunity Readability PASS · 2026-08-22English →

AI 团队同时交回三份报告,怎样保证验收没有串账?

开发、测试和运维三个 AI 智能体几乎同时交回报告。三份报告都说成功,系统也顺利生成“开发完成、测试通过、部署正常”的总结;但测试验收的是返工前版本,运维报告属于另一个任务,开发报告又写错了任务编号。系统没有漏掉任何文件,却拼出了一笔从未发生过的交付。

解决办法不是再让模型猜一次正文,而是把展示和验收分开:界面可以尽力帮助挂树,真正进入验收的报告必须拥有唯一、可验证的任务归属,并明确属于哪次执行。本文会给出身份门禁、报告版本状态和汇总检查清单;只要归属仍有歧义,系统就应停止,而不是替人猜一个最像的答案。

不熟悉任务归因的技术读者,可以先记住“归因三问”:

归因问题白话解释可以检查什么
谁干的这份报告来自哪个项目、哪个任务、哪次执行任务编号、父任务、项目根、运行系统记录的执行轮次
拿什么证明报告中的成功结论有没有机器证据实际命令、退出码、原始测试输出和当时的代码版本;只有真实采集过才能引用
对谁负责哪份任务合同接收这组证据,谁有权验收唯一任务绑定、报告替代关系、QA(独立质量验证)和最终接受决定

这三问分别防止三类串账:把甲的报告记给乙、把模型写出的“测试通过”当成真实日志、让执行者自己宣布验收完成。当前 CodeFlowMu 只在部分关键路径实现了下文所述硬门;“所有权威元数据都由运行系统注入”仍是目标合同,不能冒充现成功能。

整条责任链可以先看成:

text
任务派发
  → 绑定任务与执行上下文
  → Agent(智能体)调用工具
  → 采集命令、退出码、测试与版本证据
  → 封装报告
  → 归因门核对任务、轮次与报告版本
  → 独立 QA 验证
  → 有权角色接受或拒绝

其中“运行系统自动注入全部身份”和“统一采集全部工具证据”是目标方向;本文会明确指出哪些检查已经存在、哪些仍需实现。

报告存在,不等于报告属于这项任务

多 Agent(多智能体)系统常用四种简便办法归档报告:

  1. 挂到同一聊天线程;
  2. 挂到最近创建的任务;
  3. 根据正文中出现的任务编号匹配;
  4. 根据发送角色匹配,例如 DEV(开发执行者)报告挂到最近的开发任务。

这些办法适合帮助界面整理,却都不能单独支撑验收。

同一线程里可能连续出现两个根任务;返工报告会提到被驳回的旧任务;正文可能同时描述父任务与子任务;迟到的旧报告也可能在新任务创建后才被文件监听器发现。

如果系统在这些情况中“挑一个最像的”,它得到的只是概率较高的挂树,不是确定的证据归属。

一份报告至少需要四张身份证

在 CodeFlowMu 的当前实现中,报告归属涉及四类信息:

身份作用典型错误
报告文件身份表明报告本身是哪次回执文件名序号与实际任务不符
task_id声明直接工作所有者仍指向返工前任务
parent_task_id表明报告在任务树上的父节点报告被挂到根任务而不是具体子任务
references保存相关任务和历史引用把“提到过”误当成“直接属于”

这里最重要的区别是:直接所有者和相关引用不是一回事。

假设开发 Agent 在 TASK-042-REWORK-01 上返工。报告可以在 references 中保留旧的 TASK-042,说明为什么返工;但直接 task_id 应指向当前返工任务。若系统只扫描引用,旧任务就可能“偷走”新报告。

关键回执需要硬门,而不是相似度

CodeFlowMu 为一个关键 DEV(开发执行者)回执场景实现了严格的三字段检查。reportAttribution.ts 会比较:

text
REPORT 文件名推断的 TASK 编号
        ==
frontmatter.task_id(文件头中的任务编号)
        ==
references[0]

例如:

yaml
filename: REPORT-20260820-042-DEV-to-PM.md
task_id: TASK-20260820-042
references:
  - TASK-20260820-042

三处一致,归因门才通过。若文件名是 REPORT-...-043,但 task_id 和引用仍是 TASK-...-042,系统会返回归因失败,而不是选择两个字段中的“多数”。缺少 task_id 或首个引用也会失败。

必须说明:这是 CodeFlowMu 当前某个关键 DEV 验收路径的应用级硬门,不是 FCoP(文件协作协议)对所有 REPORT(执行报告)、所有角色和所有文件名的普遍规则。FCoP 定义报告信封和引用能力;具体项目可以在宿主 Runtime(运行系统)中增加更严格的归因合同。

这道门只能排除“三处互相矛盾”,不能排除“三处一致地写错”。模型若复制了旧报告模板,可能在文件名、task_id 和首个引用中填入同一个旧任务,静态检查仍会通过。三字段一致因此是必要条件,不是任务归属的充分证明。

更强的目标设计是:智能体只提交报告正文和执行证据,权威元数据由运行系统根据当前会话注入。文件名、任务编号、父任务、执行轮次和逻辑序号不由模型自由书写;运行系统再把封包后的完整工件交给归因门复核。当前 CodeFlowMu 的三字段门已经能发现明显错配,但本文没有证据证明所有报告入口都统一采用了这种“运行系统封包”流程,所以这部分明确作为下一步合同,而不是现成功能。

任务身份与执行轮次绑定开发事实和 QA 验证;报告新旧由替代关系裁决,错属工件被隔离

图 1:报告从身份、执行轮次、版本替代到 QA 验证的归属链。来源:本文根据 CodeFlowMu 固定提交与 W3C/OpenTelemetry 的身份传播边界整理。运行系统注入全部权威元数据仍是目标合同。

哪些情况必须直接拒绝验收

归因门不仅要说明什么可以通过,还要给出 Veto List(否决清单)。“否决”表示证据当前不足或发生冲突,不等于认定提交者恶意欺诈:

  • 报告声明的代码版本与实际受测工作区不一致:判定为过期证据或版本冲突,隔离等待复核;
  • 只写“测试通过”,却没有实际命令、退出码或原始输出:证据不足,不得进入成功总结;
  • 文件名、任务编号和首个引用三处一致,却与运行系统的真实派工记录不符:归属失败;
  • 同一任务存在多份报告,却没有执行轮次或明确的替代关系:不得自行选择“最新”文件;
  • 只靠文件修改时间判断先后:不能证明因果顺序,必须结合事件序号、执行轮次或明确的替代记录;
  • 若某条执行路径确实采用有时限的执行权,超过期限的报告只能进入复核;没有实现该机制的路径,不能虚构“租约过期”规则。

这份清单把“看起来像成功”转换成可执行的停止条件:系统宁可返回“归属未确定”,也不能把三份真实报告拼成一笔虚假的交付。

为什么需要身份传播,但不能把 Trace 当验收

分布式系统已经遇到过类似问题。W3C 的 Trace Context(链路追踪上下文)trace-id(整条调用链编号)关联一条跨服务调用链;parent-id(上游操作编号)是调用方为当前请求携带的上游标识,接收方创建下游请求时会用新的当前操作标识继续传播。OpenTelemetry 的追踪 API(编程接口)规定每个 span(一次调用片段)最多有一个父片段,父子操作共享 TraceId(调用链编号),从而构成因果树。

这为 Agent 报告提供一个重要启发:任务身份和父关系必须随着工作传递,不能等报告回来以后再靠正文猜。

但类比到这里必须停止。Trace 能说明两次操作在同一调用链中,不证明输出内容正确;span 正常结束也不代表业务验收通过。Agent 报告同样需要把“关联到了哪个任务”和“是否满足任务合同”分开。

text
身份关联正确

报告内容真实

测试角色已验证

业务已经接受

展示挂树可以尽力,验收门禁不能猜

CodeFlowMu 的 reportParenting.ts 需要面对现实世界的不完整旧数据。它优先使用显式 source_task_idtask_id;缺失时,还会参考 references、文件名序号、正文重合和最近开放任务,帮助把报告展示在合理位置。

这种“最佳努力”对账本界面很有价值:历史数据不至于全部变成孤儿。

但如果把同一启发式直接用于自动验收,就会出现风险。正文相似可能因为两个任务都修改同一模块;最近任务可能只是刚好创建得晚;同一角色可能并行处理多个任务。

因此需要两条不同的结果:

text
display_parent = best_effort_match(...)
acceptance_owner = deterministic_contract_or_undetermined(...)

前者可以标记“推测挂载”并允许人工修正;后者只能返回明确唯一所有者,或者 undetermined。不确定不是系统失败,而是阻止串账的有效结果。

同一线程出现两个根任务时,线程不能当父亲

真实协作中,一个聊天线程可能先处理缺陷 A,稍后又加入独立需求 B。若所有报告只带同一个 thread_key,旧的最终报告可能被新任务误用。

当前 reportParenting.ts 会在同一线程存在多个 ADMIN 根任务时按 lineage 和任务前缀分桶。只有引用或父链能唯一指向某个根时,报告才进入该桶;否则留在孤立区域,而不是挂到“线程中的第一个根任务”。

这条规则解决的是账本重建,不保证所有历史文件都能自动恢复。缺少身份的旧报告可能需要人工裁决。系统不应为了让界面更整齐而伪造确定性。

同一任务交两次报告,必须明确哪一份有效

任务编号相同,不代表两份报告可以互相覆盖。开发智能体第一次提交失败报告,修复后又提交成功报告时,系统至少需要执行轮次、报告自身身份、前一版本引用,以及明确的“替代了哪一份”关系。旧报告继续保留,但不再作为当前完成证据。

CodeFlowMu 当前账本已经识别 submission_attemptrevision_ofsupersedessuperseded_by 等字段;汇总门也会排除标记为无效或已被替代的报告。这些是版本治理的可用零件,却不能证明每个报告入口都会自动递增执行轮次、并发提交一定得到唯一裁决。生产系统仍应把报告版本写成显式状态机:

text
attempt-1 / report-v1 / failed
          └─ superseded_by → report-v2
attempt-2 / report-v2 / candidate
          └─ verified_by   → qa-report-v2

覆盖原文件会抹掉失败历史;按“最新时间”自动获胜又会受时钟漂移影响。更稳妥的做法是用任务事件序号或执行轮次建立因果顺序,再由明确的替代关系决定哪份报告进入验收。

报告归属通过以后,还不能生成最终总结

即使开发报告已经正确挂到任务,项目经理也不能立刻宣布完成。CodeFlowMu 的 PmSummaryGate 还会检查:

  • 下游子任务是否已经进入结算状态;
  • 是否存在有效的 worker-to-PM 报告;
  • 报告是否晚于对应任务创建;
  • 产品任务是否具备要求的 QA 报告;
  • QA 是否给出 PASS;
  • 需要浏览器验证时是否存在浏览器证据;
  • 是否已经存在一份有效的最终总结。

因此,“诊断列表为空”不能替代归因通过,“开发报告存在”不能替代 QA 通过,“PM 写了总结”也不能替代管理员或业务负责人的最终接受。

这正是 TMPA 中事实与接受分离的工程意义:执行者提交事实,验证者检查事实,有权角色决定是否接受。三者不能由同一份报告中的 status: done 合并。

这里还要收紧“晚于”的含义。当前汇总代码优先读取工件中的显式创建时间;部分兼容分支会参考账本时间或文件修改时间。Git 同步、解压、跨设备复制和本机时钟漂移都可能改变这些时间,因此物理时间只能作为辅助证据。涉及返工、重复提交和跨设备同步时,应优先比较由运行系统产生的事件序号、执行轮次和明确替代关系。

44 个测试覆盖了哪些串账路径

本次写作在独立工作树固定 CodeFlowMu Open commit ed5634c718b9e238c44bb70851020c9793546fe6,重新运行报告挂树、归因和最终汇总测试,结果为 44/44 通过

测试包含:

  • 文件名指向任务 003,而 task_id 与引用指向 002:拒绝;
  • 缺少 task_id 或引用:拒绝;
  • 三字段一致:通过;
  • 返工报告显式指向当前任务,即使引用提到旧任务,也保持当前所有者;
  • 同一线程两个根任务,旧 PM 最终报告不能挂到新根;
  • 迟到报告早于子任务创建:不视为有效交付;
  • QA 报告缺失或 FAIL:阻止最终总结;
  • QA 未提供要求的浏览器证据:阻止总结;
  • diagnostics 为零但报告归因失败:整体验收仍失败。

测试同时证明辅助挂树确实包含正文和最近任务回退。因此本文不会把 CodeFlowMu 描述成“所有历史报告都只靠三字段决定”。准确边界是:账本展示兼容不完整数据;关键验收路径使用更严格合同。

当前 44 项没有覆盖“三字段一致但共同指向错误任务”。该场景是根据门禁逻辑得到的反例,也是下一轮应新增的故障测试,不能写成已经通过的用例。

六个值得复制的失败用例

编号错配

报告文件名、显式任务编号和首个引用中任意一处不同。期望:归因失败,保留原文件,不自动改名覆盖现场。

三处一致地写错

从旧模板复制报告,让文件名、task_id 和首个引用都指向同一个错误任务。期望:若元数据不是由运行系统注入,就不能仅凭三字段一致进入验收;至少还要核对当前会话、执行轮次或签发上下文。

旧报告迟到

报告创建时间早于目标子任务,却在监听器重启后才被发现。期望:可以展示为历史孤儿,不满足当前任务的有效报告条件。

同一任务重复提交

同一任务先后出现失败和成功报告。期望:保留两份工件,用执行轮次和 supersedes 关系选择候选;禁止覆盖旧文件,也禁止只按文件修改时间决定胜者。

同线程多根

同一 thread_key 下存在两个独立根任务,报告只提供 thread。期望:undetermined,不得挂到第一个或最新根。

QA 缺失或失败

开发报告正确、代码也存在,但必需 QA 报告缺失或 verdict 为 FAIL。期望:不生成成功总结,下游发布保持阻塞。

报告创建与汇总清单

报告创建时:

  1. 在领取任务时就把任务身份、父任务和执行轮次放入运行上下文;
  2. 智能体只提交正文与证据,文件名和权威元数据由 Runtime 封包注入;
  3. 直接所有者放在固定字段,历史相关项放在引用列表;
  4. 记录发送角色、执行轮次、逻辑事件序号和创建时间;
  5. 对返工创建新尝试身份,用 supersedes 指向被替代报告,并保留旧任务引用。

报告摄入时:

  1. 先解析显式身份,再考虑辅助匹配;
  2. 多个候选同分时返回不确定,不随机选择;
  3. 保留原始文件、解析结果和冲突原因;
  4. 展示推测挂树时明确标注“未用于验收”。

最终汇总前:

  1. 优先用执行轮次、事件序号和替代关系核对报告新旧;物理时间只作辅助;
  2. 核对角色、任务所有者和必需证据;
  3. QA 缺失、失败或证据不足时阻止成功总结;
  4. 把执行事实、验证裁决和业务接受保存为不同记录。

限制与待验证问题

三字段一致可以排除一类明显串账,却不能证明报告正文真实,也不能阻止模型三处一致地引用错误任务。运行系统封包可以显著缩小这类错误面,但当前资料不足以证明所有 CodeFlowMu 报告入口都已执行该合同。

正文匹配算法也没有误挂率基准;本文不主张它适合验收。跨仓库、跨组织的任务身份还需要命名空间或全局身份,单纯日期和三位序号可能碰撞。

44 个测试来自第一方固定提交,不是外部审计。下一步应加入随机生成的任务树、三处一致但上下文错误、同任务多执行轮次、报告乱序、重复监听事件、时钟漂移和跨重启重建测试,量化 undetermined、误挂和漏挂比例。

结论

多 Agent 协作最危险的错误不一定是报告丢失,而是报告存在、内容也合理,却被算进了错误任务。

展示系统可以努力帮人找到报告;验收系统没有权力在归属不清时替人猜。

让任务身份和父关系随执行传递,让关键报告通过确定性归因门,让 QA 和最终接受继续保持独立。这样,三份报告才能形成三条可审查证据,而不是被拼成一笔看似完整的假交付。

主要来源

  1. W3C Trace Context
  2. OpenTelemetry Tracing API
  3. FCoP v3 中文规范,固定提交
  4. CodeFlowMu reportAttribution 固定提交
  5. CodeFlowMu reportParenting 固定提交
  6. CodeFlowMu PmSummaryGate 固定提交
  7. CodeFlowMu LedgerBuilder 固定提交
  8. TMPA 核心规范 S1.0,固定提交

访问日期:2026-08-20。

Last updated: