LobeHub Deep Review 技能深度解析:多 Agent 代码审查中的“全局发现合并”步骤——同根合并语义、触发条件与 JSON 输出契约
LobeHub Deep Review 技能深度解析:多 Agent 代码审查中的“全局发现合并”步骤——同根合并语义、触发条件与 JSON 输出契约
📅 发布时间:2026/9/5 18:36:24👁 浏览次数:
LobeHub Deep Review 技能深度解析多 Agent 代码审查中的“全局发现合并”步骤——同根合并语义、触发条件与 JSON 输出契约【免费下载链接】lobehub LobeHub is your Chief Agent Operator, organizing your agents into 7×24 operations by hiring, scheduling, and reporting on your entire AI team.项目地址: https://gitcode.com/GitHub_Trending/lo/lobehub本文围绕 LobeHub 仓库中 deep-review 技能的 consolidate-prompt.md 展开完整讲解深度多 Agent 代码审查流水线中“全局发现合并”Global Finding Consolidation这一步骤的触发条件、输入实例化、同根判定语义、JSON 输出契约以及它如何被 Zod 校验脚本验证并最终折叠进审查报告。读完之后你将理解一个不改动任何审查结论、只做跨审查器去重的独立 Prompt 工程化设计并能在本仓库中找到它的完整实现与测试证据。1. 合并步骤在 Deep Review 流水线中的位置deep-review 是 LobeHub 仓库内置的一个 Agent 技能入口为 SKILL.md用于对 PR、分支或粘贴的 diff 做多维度代码审查。其 Deep 模式的完整编排是dimension review agents → pipelined verification → global consolidation → structured report → interactive fix flow“全局发现合并”就是其中的第三环由两份环境手册分别规定为 Step 4Claude Code 手册的 Step 4 — Consolidate duplicate rootsCodex 手册的 Step 4 — Consolidate duplicate roots两份手册对该步骤的约束一致可以归纳为三条触发门槛只有当队列排空后仍然至少存在 2 条confirmed发现时才运行0 条或 1 条 confirmed 发现直接跳过Claude Code 手册明确写着 Zero or one confirmed finding skips this step。一次性、验证之后该步骤在整个 Deep 运行中只跑一次且必须等待 pipelined verification 阶段完全结束。SKILL.md 的预算规则还规定同一次 Deep 运行内的 review / verify / consolidate 三波全部计入一次 Deep 预算。职责边界正如 consolidate-prompt.md 开头所言——This pass does not re-verify correctness; it identifies roots duplicated across verifier payloads。它不做第二次正确性验证只识别跨审查器verifierpayload 之间重复出现的根因。为什么要单独开一个步骤而不是让验证器顺手去重从 review-prompt.md 的设计看每个审查子代理只被允许报告自己维度dimension内的发现do not report findings outside your assignment在 Claude Code 环境里甚至一个维度就是一个独立 Task。这意味着同一个根因很可能被不同维度的审查器各自独立发现——例如文档自带示例中的style-2与ai-1就分属 code-style 与 ai-coding-bad-habits 两个维度。任何单个审查器都看不到全局只有把所有 confirmed 发现集中起来的独立合并步骤才能完成这种跨维度去重。2. 输入{confirmed_findings}的实例化规则consolidate-prompt.md 对输入有明确的实例化约定Instantiate{confirmed_findings}with the confirmed findings after applying verifier overrides, including id, dimension, location, summary, evidence, and fix options.拆开来看有三个要点来源只取 verify 阶段结论为confirmed的发现。验证器的三向判定confirmed/false_positive/need_more_context定义在 verify-prompt.md 的返回契约中false_positive只进统计need_more_context进入needsContext池二者都不会进入合并输入。应用 override 之后验证器允许输出severity_override、nature_override、exposure_override、likelihood_override、fix_options_override等纠正字段。主 Agent 必须在喂给合并步骤之前应用这些 override即合并步骤看到的是生效值而非审查器原始值。字段集每条输入至少携带id、dimension、location、summary、evidence与fix_options。其中fix_options尤其关键——第 4 节会说明同根判定的核心测试正是基于能否用一个具体修复同时解决两条发现而判断这一点必须能看到候选修复项。两份环境手册还规定了输入顺序Pass confirmed findings after verifier overrides, in report order.即按照最终报告的排序P0 → P1 → P2维度按 SKILL.md 维度表顺序传入。这个顺序不是随便选的它决定了下一节中根的归属规则。3. 完整 Prompt 契约同根判定的语义规则以下是 consolidate-prompt.md 中模板的完整内容占位符{confirmed_findings}由主 Agent 注入Consolidate duplicate code-review findings. Do not change verdicts, severity, likelihood, evidence, or fix options. ## Confirmed findings {confirmed_findings} Two findings share a root only when one concrete fix resolves both. Similar location, theme, or dimension is not enough. Choose the earliest finding in input order as the root. Return only later duplicate ids. Never: - map an id to itself; - invent an id; - create a cycle; - merge findings that require separate fixes; or - merge a release-risk consequence with a code defect when fixing the defect would not also remove the release consequence. Return exactly one valid JSON object in a json fence. No prose or comments. json { same_root: [ { id: style-2, same_root_as: ai-1 } ] } When no duplicates exist, return {same_root:[]}.这段不到 30 行的 Prompt 实际上是一份非常严格的语义契约值得逐条拆解3.1 不可变性约束Do not change verdicts, severity, likelihood, evidence, or fix options合并步骤对五条核心字段只读。这体现了流水线中职责分离的原则判定正确性属于 verify 阶段去重属于 consolidate 阶段渲染属于 report 阶段。如果合并步骤被允许顺手调整 severity 或 fix options整个验证器是唯一裁判的审计链条就被破坏了。这一约束与 SKILL.md 核心原则 1Anti-hallucination一脉相承——每一个字段的所有权都归属产生它的那个阶段。3.2 同根判定唯一的充分条件是一个具体修复同时解决两者Two findings share a root only when one concrete fix resolves both. Similar location, theme, or dimension is not enough.这是整个 Prompt 中最关键的一句。它把同一根因从模糊的主题相似度问题收敛成一个可操作的判据是否存在一个具体修复concrete fix使得两条发现同时消失。仅满足以下任一条件都不算同根位置相近同一个文件或相邻函数主题相似都关于错误处理维度相同都出自 code-style。这个判据的实战价值在于防止过度合并。两条 P1 发现可能位于同一文件、描述相似但一个需要改输入校验、另一个需要修状态机——它们共享的是位置而非修复。若按位置合并报告里会丢失一条独立的修复项导致其中一个缺陷永远不会被修。把判据锚定在fix_options上恰好利用了第 2 节要求输入携带该字段的设计。3.3 根的选择与输出形态最早者即根Choose the earliest finding in input order as the root. Return only later duplicate ids.同根组内输入顺序上最早的那条发现被选为根输出里只需要列出更晚的重复 id每个重复项用same_root_as指回根。这套设计有两个工程上的好处确定性。最早者规则不依赖模型做任何选择重跑同一输入必然得到同一输出避免了 LLM 在并列候选间摇摆导致的输出不稳定。最小输出面。输出是一个部分映射partial map没有被映射到的 confirmed id 隐式就是根。输出条目越少模型凭空捏造 id的空间越小——这也呼应了下文 Never 清单。3.4 Never 清单五类硬性禁止Prompt 用五条 Never 封死了合并步骤所有典型的失败模式禁止行为防御的失败模式map an id to itself自映射same_root_as指向自己无意义且说明模型对映射语义理解错误invent an id输出中出现输入里不存在的 id——典型的 LLM 幻觉create a cycle出现a→b且b→a或更长环的映射渲染时无法确定根merge findings that require separate fixes违反 3.2 节的同根判据把需要独立修复的发现强行合并merge a release-risk consequence with a code defect when fixing the defect would not also remove the release consequence见下节专门分析最后一条是针对 LobeHub 这种代码 发布风险双维度审查场景的定制规则。release-risk 维度既产出代码缺陷类发现也产出release_checks预部署确认项。一条发布风险后果例如某配置未在某环境生效可能由一个代码缺陷引起但修复该缺陷并不必然消除该后果比如还依赖人工核对生产数据形态。此时若把两者合并后果项会被折叠进缺陷条目预部署检查项就永远无人执行。Prompt 因此要求只有当修掉缺陷也同时消除了该发布后果时二者才允许同根。3.5 输出契约单个 JSON 对象 json fence 无重复时的空数组必须返回恰好一个有效 JSON 对象包在jsonfence 里No prose or comments——这为第 4 节的机器提取器留出了确定性的解析入口结构固定为same_root数组元素只有id与same_root_as两个字符串字段无重复时返回{same_root:[]}而不是省略字段或输出其他变体。文档自带的示例{id: style-2, same_root_as: ai-1}恰好跨维度code-style 的style-2指回 ai-coding-bad-habits 的ai-1再次印证了第 1 节的判断这个步骤存在的意义就是处理单个审查器看不见的跨维度重复。4. 程序化验证validate-output.ts 如何守住这道门Prompt 约束只是软契约真正保证输出可用的是仓库内的校验脚本。validate-output.ts 为 Deep 模式的三种子代理输出review/verify/consolidate分别定义了 Zod schema合并步骤对应的是ConsolidationOutputSchemavalidate-output.ts#L144-L161const ConsolidationOutputSchema z .object({ same_root: z.array( z .object({ id: z.string().min(1), same_root_as: z.string().min(1), }) .strict(), ), }) .strict() .superRefine(({ same_root }, context) { const ids same_root.map(({ id }) id); if (new Set(ids).size ! ids.length) { context.addIssue({ code: custom, message: consolidation ids must be unique }); } });它提供了三层机器检查顶层.strict()拒绝same_root以外的任何多余顶层字段比如模型顺手加的note元素.strict()min(1)每个条目只允许id/same_root_as且都不能是空串——从结构上杜绝了输出里夹带解释性字段superRefine唯一性约束同一个id不允许出现两次即一条发现不能同时被映射到两个不同的根对应错误信息为consolidation ids must be unique。对应的测试用例在 validate-output.test.ts#L109-L118it(rejects duplicate consolidation ids, () { expect(() validateOutput(consolidate, { same_root: [ { id: style-2, same_root_as: ai-1 }, { id: style-2, same_root_as: logic-1 }, ], })).toThrow(); });值得注意的是schema 只覆盖结构不覆盖语义。Never 清单里的后三条——捏造 id、自映射、成环、根出现在重复项之后——无法用静态 schema 表达需要对照输入 id 集合和拓扑分析因此由环境手册规定为主 Agent 的额外运行时检查。以 claude-code/main.md#L73-L75 为例Validate the result withvalidate-output.ts consolidate, then reject any invented id, self-map, cycle, or root that occurs after its duplicate. Invalid output → re-spawn consolidation. Apply the map only after validation.即完整的验收流程是两级闸门第一级机器bun run .agents/skills/deep-review/scripts/validate-output.ts consolidatestdin 或临时文件传入子代理响应。脚本先经extractJsonPayloadvalidate-output.ts#L171-L185提取 fence 内 JSON——发现多个jsonfence 抛Multiple JSON fences foundfence 未闭合抛JSON fence is not closed——再走 Zod 解析第二级主 Agent对照输入 id 集合逐一核对是否存在捏造 id、自映射、环、以及根晚于其重复项违反earliest finding in input order as the root的确定性规则。任何一级失败都触发用同一 Prompt 重新派发合并子代理且 Apply the map only after validation——校验未过之前映射一律不生效。5. 合并结果如何折叠进最终报告合并映射通过校验后被 report-template.md 的消费规则直接决定报告形态report-template.md#L21-L24Same-root merge: findings mapped tosame_root_as: Xby the global consolidation pass fold into Xs entry — no separate number; add**Same root**: id (location, issue_type), ...at the entrys end; entry severity upgrades to the highest among merged; statistics count merged entries once.落到报告上有四个具体效果折叠重复项不再拥有独立编号并入根的条目条目末尾追加一行**Same root**: id (location, issue_type)模板渲染格式见 report-template.md#L114severity 升级合并后条目的严重级别取组内最高值blocks_release 取值报告渲染规则明确 Same-root merged entries take the value belonging to the highest merged severityreport-template.md#L16保证合并不弱化 ship/no-ship 信号统计口径Statistics 一节中合并条目只计一次避免同根缺陷在确认数里虚高。在 PR 模式下这一口径继续传导到Merge verdict判定表只统计 in-scope 的 confirmed P0/P1合并升级后的 severity 决定该条目是否构成 fix before merge 的前置项。也就是说consolidate 步骤虽然不改变单条发现的任何字段却通过折叠 升级间接影响了合并结论与报告篇幅——这正是它必须在渲染之前完成、且校验未过绝不应用的原因。6. 设计要点归纳为什么是这样一个步骤把 consolidate-prompt.md 与 SKILL.md 的核心原则对照起来可以提炼出这个 Prompt 的几个设计取向用规则代替模型判断对应原则 3 Rules over model。同根判定、根的选择、输出形态全部被写成无歧义的硬规则模型只需执行不需要权衡把聪明省给了真正需要判断的 verify 阶段。确定性优先。最早者即根 只输出较晚的 id使输出成为输入的确定函数天然可复现、可测试也让主 Agent 的运行时检查环、自映射保持廉价。最小化输出面以抑制幻觉。单 JSON fence、无 prose、无重复时返回空数组而非省略——配合extractJsonPayload对 fence 数量的硬拒绝见 validate-output.test.ts#L37-L41 中rejects multiple JSON fences用例任何多嘴的输出都会被直接拦下重跑。不重复做昂贵的事。does not re-verify correctness 使该步骤的上下文只需携带 6 个字段的发现摘要而不需要重新打开源文件从成本结构看这是一次廉价的报告整形与 deep-mode 预算规则一次逻辑需求至多一次 Deep相契合。7. 在本仓库中查看与验证该步骤技能入口与模式划分、维度表、预算规则SKILL.md合并 Prompt 本体本文核心references/consolidate-prompt.md两个环境的 Step 4 调用约定claude-code/main.md、codex/main.md输出契约的机器校验scripts/validate-output.ts、scripts/validate-output.test.ts映射的消费方渲染与统计规则references/report-template.md实际验证方式可以直接对校验脚本投喂样例载荷观察两级闸门的分工——# 通过 stdin 校验一个无重复的合法输出 echo json {same_root:[{id:style-2,same_root_as:ai-1}]} | bun run .agents/skills/deep-review/scripts/validate-output.ts consolidate # 期望输出: Valid consolidate output # 同一 id 映射两个根 → 触发 consolidation ids must be unique 并以非零码退出 echo json {same_root:[{id:style-2,same_root_as:ai-1},{id:style-2,same_root_as:logic-1}]} | bun run .agents/skills/deep-review/scripts/validate-output.ts consolidate需要说明适用前提consolidate-prompt.md 只在 Deep 模式下、且 confirmed 发现数 ≥ 2 时才会被实例化Light 模式没有 verify 阶段自然也不存在合并步骤。此外该技能支持扩展包机制任意deep-review-*兄弟目录可作为扩展包注入自有维度文件见 SKILL.md 的 Extension packs 一节但合并步骤本身的语义契约不受扩展包影响——它消费的是所有维度最终汇总出的 confirmed 发现集合。【免费下载链接】lobehub LobeHub is your Chief Agent Operator, organizing your agents into 7×24 operations by hiring, scheduling, and reporting on your entire AI team.项目地址: https://gitcode.com/GitHub_Trending/lo/lobehub创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考