| name | review |
| description | 本地 ultrareview——多代理、对抗验证、只读的 PR 级 review;默认 base=main;并发 5 个 finder(质量/安全/简洁/鲁棒性/文档同步),每条 🔴/🟡 发现交 3 个独立怀疑视角对抗验证、多数决去留;可选追加本次 review 重点,注入每个 finder 优先关注(不替代其他维度)。触发:/review、给当前分支做深度审查、PR 前 ultrareview。跳过:不在 git 仓库、当前分支=base。 |
本地 ultrareview
多代理、对抗验证、只读的 PR 级 review 协调者。
核心原则:prompt 自包含 / 只读不写 / 发现者与验证者隔离 / 基于 file:line 事实。
1. 输入与前置检查
$ARGUMENTS 形如 [base] [本次 review 重点...],两段都可选:
- 拿到
$ARGUMENTS 后按空白切成 tokens;为空则 base 走默认、focus 为空
- 第一个 token 用
git rev-parse --verify --quiet <token> 探测:
- 成功 → 该 token 当 base,剩余 tokens 用空格拼回当 focus(本次 review 重点,自然语言)
- 失败 → base 走默认,全部 tokens 拼回当 focus
- base 默认:
main,不存在则 master,再不存在则提示用户
例:/review 关注鉴权和密钥落盘 → base=main,focus=关注鉴权和密钥落盘;/review develop 性能 → base=develop,focus=性能;/review → base=main,focus 空。
前置检查:
- 确认 git 仓库 / 当前分支 ≠ base / base 存在 / 未提交改动仅警告不中止
回显:review 范围:<base> .. HEAD | 分支:<name> | commits:N | diff:M 文件 +L1/-L2 | 重点:<focus 或「未指定」>
修复主题摘要(≤ 300 字)
从 commit messages + AGENTS.md/CLAUDE.md 提取"想解决什么 / 修复策略 / 关键约束",注入每个 finder prompt。
本次 review 重点(focus)
focus 是用户希望优先关注的方向(如"鉴权链路"/"新加的限流"/"重构后的事务边界"),不是"只看这块"——其他维度发现仍应照常报出,但凡命中 focus 的发现在 finder 内部应优先排序、严重度判定可酌情偏严。focus 为空时显式写「本次未指定,按各 finder 默认维度全面审视」。
2. 组装 finder
五个 finder 都是插件注册的 opencode subagent,各自的审查维度与产出要求已在其系统提示中。派工只需组装本次 review 上下文——四个小节(Review 范围 / 修复主题摘要 / 约束清单 / 本次重点)写进任务消息;「本次重点」为空时填入「本次未指定,按默认维度全面审视」。
| key | 图标 | subagent |
|---|
| quality | 📐 | bb-spec-review-code-quality |
| security | 🛡️ | bb-spec-review-security |
| simplicity | 🧹 | bb-spec-review-simplicity |
| robustness | 🪨 | bb-spec-review-robustness |
| doc-sync | 📄 | bb-spec-review-doc-sync |
图标是 finder 在最终报告中的身份标识(报告表格 by 列写图标 + 文字名,如 📐质量,多个 finder 空格分隔);刻意用物体类 emoji,与严重度的 🔴🟡🟢 圆点在视觉上分属两类,避免混淆。
3. 并行编排(task 工具)
编排走 task 工具两阶段执行。每个任务消息自包含(子代理看不到本对话),数据全部内嵌进消息文本;finder / 验证者沿用会话模型。
Find 阶段
在同一条回复里同时发出全部 finder 的 task 调用(并行,禁止逐个串行等待):每个 finder 一个 task,subagent 按上表,任务消息 = 四个上下文小节 + 结构化返回要求:
最终回复只输出一个 ```json 代码块:{"findings": [{"title", "file", "lines", "severity", "fact", "impact", "suggestion"}, ...]}。severity ∈ BLOCKER|IMPORTANT|NIT;file 为相对仓库根路径;lines 为行号或区间(如 "12" / "12-34");title ≤ 20 字;fact 3-5 行;suggestion ≤ 3 行;无发现返回 {"findings": []}。
去重(纯代码,禁手工判重)
汇总全部 finder 返回的 findings(每条标注 by = finder key 数组),写入 .bb-spec/.cache/review/findings.json(.cache/.gitignore 不存在则先创建,内容单行 *);把下面脚本写入同目录 dedup.ts 后 bun .bb-spec/.cache/review/dedup.ts(bun 不可用则用 node 跑等价逻辑),产出即合并结果:
const raw = JSON.parse(await Bun.file(".bb-spec/.cache/review/findings.json").text())
const span = (l) => { const m = String(l).match(/(\d+)\D*(\d+)?/); const a = m ? +m[1] : 0; return [a, m && m[2] ? +m[2] : a] }
const SEV = { BLOCKER: 3, IMPORTANT: 2, NIT: 1 }
const merged = []
for (const f of raw) {
const [s, e] = span(f.lines)
const dup = merged.find((g) => g.file === f.file && span(g.lines)[0] <= e && s <= span(g.lines)[1])
if (dup) {
dup.by = [...new Set([...dup.by, ...f.by])]
if (SEV[f.severity] > SEV[dup.severity]) dup.severity = f.severity
} else merged.push({ ...f })
}
console.log(JSON.stringify(merged, null, 2))
NIT 不值得验证成本,直接带回报告;🔴/🟡(BLOCKER/IMPORTANT)逐条进对抗验证。回显:去重后 N 条:🔴/🟡 X 条进入对抗验证,🟢 Y 条直接列出。
Verify 阶段
三个独立怀疑视角,每个只裁决一个维度,多数决(≥2/3)定去留:
- importance:这个问题对用户/业务/维护者真的重要吗,还是风格偏好或凑数?
- root-cause:它指出的是根因还是表层症状?建议是根本修复还是缓解/绕过?
- risk:不修复会在真实场景触发正确性/安全/重大可维护性问题吗?
每条待验证发现在同一条回复里并行派 3 个 task(subagent 用通用 general;发现多时按批推进,每批 ≤ 3 条发现即 ≤ 9 个 task),任务消息模板:
你是独立的 review 仲裁者,立场是怀疑:优先尝试否决下面这条发现,证据不足或站不住脚就判 valid=false。
仲裁视角(只回答这一个维度):<该视角问题>
Review 上下文:
<CONTEXT:范围、主题摘要、约束清单、本次重点>
待仲裁发现(由 <by> 提出):
标题:<title>
位置:<file>:<lines>
严重度:<severity>
事实:<fact>
影响:<impact>
建议:<suggestion>
要求:先用 read/grep 实地核对 <file> 相关代码再裁决,不得仅凭描述判断。只读,不修改任何文件、不操作 git。
最终回复只输出一个 ```json 代码块:{"valid": true|false, "reason": "一句话裁决理由"}
全部裁决完成后汇总三份清单:confirmed(≥2 票 valid)/ rejected(<2 票)/ nits。
4. 输出
主 agent 拿汇总结果(confirmed / rejected / nits)写最终报告。
输出节奏:先全景简表,后逐个展开。 开局只给概览 + 简表表格(让用户知道有几个问题、严重度分布、各由哪个 finder 发现),禁止一次性平铺所有问题的详细分析与修复方案——详细内容只在逐个解决模式中一次一条给出。理由:前面的修复可能让后面的问题自然消失,提前展开既浪费也误导。
测试缺陷类 finding 处理
当 finding 指向测试本身(断言写错、用例设计不合理、覆盖场景缺失)而非实现代码时:
- 在该 finding 标题后追加
[测试缺陷] 标签
- 逐个解决模式展开该项时,修复方向不给修测试的代码方案,只给 /revise 归因提示:写
测试层 impl-defect;若 finding 暗示 spec 对预期行为描述不清导致测试写错,写 疑似 spec-defect
概览
本地 ultrareview 完成 · <base>..HEAD(N commits / M 文件 / +L1 -L2)
重点:<focus 一句话;未指定时写「未指定,全面审视」>
finder:📐质量 🛡️安全 🧹简洁 🪨鲁棒 📄文档(5/5 就绪)
去重 N 条 → ✅ A 确认 / ❌ B 否决 / 🟢 C 未验证 | 🔴 a(⭐a')· 🟡 b(⭐b')
消耗:X agents · ~Y tokens · Z 分钟
finder 行必须完整列出;后续表格 by 列写图标 + 文字名(与 finder 行一致,如 📐质量)。⭐ = 被 ≥ 2 个 finder 命中的交叉验证强信号,由表格里的 ⭐ 标记与 by 列多 finder 直接呈现,不设独立汇总行。
✅ 确认问题表(质量/安全优先排序)
排序键依次为:①by 含 📐质量 或 🛡️安全 的优先;②其中"风险"仲裁视角 ✓(不修会出真实问题)的优先;③严重度 🔴 → 🟡;④⭐ 交叉验证优先。逐个解决模式按此表顺序处理。
**✅ 确认问题**(回复编号即从该项开始讲解)
| # | 级 | 问题 | 位置 | by |
|---|----|------|------|----|
| 1 | 🔴⭐ | 标题 | file:lines | 📐质量 🧹简洁 |
| 2 | 🟡 | 标题 | file:lines | 🪨鲁棒 |
- 标题 ≤ 20 字(
[测试缺陷] 标签不计入)——详细分析本就留给逐个解决模式,压短无信息损失,且防止表格在窄终端折行
- 位置列保留完整相对路径
file:lines(保持可点击),不得截断
🟢 NIT 表(未对抗验证)
**🟢 NIT**(未对抗验证)
| 问题 | 位置 | by |
|------|------|----|
| 标题 | file:lines | 📐质量 |
❌ 否决表(透明化,用户可质询)
**❌ 否决**(多数视角判不成立,未展开;回复"展开否决项"可质询)
| 原级 | 问题 | 重要 | 根源 | 风险 | 票 | 关键理由 |
|------|------|:--:|:--:|:--:|----|----------|
| 🔴 | 标题 | ✗ | ✗ | ✗ | 3:0 | 一句话(多数 ✗ 维度的核心依据) |
票 = 否决:通过。用户回复 展开否决项 / 展开第 N 项 才给完整内容。
询问是否逐个解决
简表之后立即向用户提问下一步怎么走(不预先展开任何一项),列出选项等用户选择:
· 开始(推荐)→ 从第 1 个问题起,逐个讲解、逐项确认后修
· 展开否决项 → 看看被对抗验证否决的那些,怕误杀
· 结束 → 看完了,不修了
(要从指定项开始讲解,用 Other 直接填项目编号,如 "3")
逐个解决模式
用户选择开始后进入循环,一轮只展开、只处理一个问题,处理顺序 = 确认问题表顺序(质量/安全 → 风险 ✓ → 严重度 → ⭐)。
修复一律走 /revise:用户确认修某个问题后,用 skill 工具加载 revise,把该 finding 的完整上下文(标题、位置、事实、影响、初步修复方向,[测试缺陷] 类附归因提示)作为其输入执行。归因诊断及确认、修复方案、TDD 修正、全量测试、本地 commit、完成简报全部由 revise 闭环——review 端不自行改代码、不另跑测试、不另做前后对照确认,禁止绕过 revise 在对话里直接改代码。
文档同步类例外(自动修复,不询问):finding 同时满足 ①仅由 📄文档 发现 ②修复只涉及文档/注释、不改变任何代码行为 → 展开后不等待用户确认、不走 /revise,直接外科手术式修好,单行说明改动后进入复核与下一条。两个条件任一不满足 → 按普通问题处理。
-
展开当前问题(仅此一条)。骨架中「背景 / 时间线 / 结果对比 / 修复方向」是四个必须原样输出的段标题,段名后的文字是该段的写法要求而非可选指导;四段缺一、或用「问题概要」「是否必要」「影响」等自创段名替代/合并任何一段,都算违规输出:
### [🔴/🟡] 项N · 标题 [⭐ 交叉验证](第 i / 共 K 个)
位置:file:lines
发现者:<图标+名,如 📐质量 + 🧹简洁> · 对抗验证:X/3 票通过(重要性 ✓/✗ · 根源性 ✓/✗ · 风险 ✓/✗)
**背景**:用业务语言讲清问题所处机制的全貌——这套机制为何存在、分哪几条路径 /
哪几层,并单独点出理解本问题所必需的"关键设计"事实;问题源于多条路径行为
不一致时,附一张逐路径对比表(路径 | 行为 | 代码位置)。目标:隔几天再看的
读者不翻代码也能进入上下文
**时间线**(执行触发时间线,非 git 提交史;按 finding 性质二选一,不许只给抽象描述):
· 行为类(正确性 / 安全 / 性能)→ 虚构一个具名触发方带具体参数(如"玩家
小明的 150 元"),把抽象缺陷讲成具体故事:按"时刻 T0..Tn | 事件"表格推进,
每行一个事件并落到代码位置(file:line / 函数名),最后一行停在出问题的
代码行为上
· 非行为类(可维护性 / 简洁性 / 文档同步)→ 无执行时间线,改用代码证据 +
后果场景:摘录实际片段,说明"下次有人改 X 会因 Y 踩坑" / "文档说 A 代码
做 B,照文档写会错"
**结果对比**(问题造成的"应然 vs 实然",不是修复前后对比——那是第 3 步的事):
逐项对比应然(真实发生的 / 文档承诺的 / 预期的)与实然(系统账面 / 代码
实际),✅/❌ 标注且每个 ❌ 旁注一句成因;表后用一段业务语言讲清后果有多重
(谁受损、损失为何无人知晓);若某项设计初衷反而被该缺陷放大 / 架空,单独
一小段点破
**修复方向**(初步,只给一个;先做三问自审再写):先自审 ①指向根源还是缓解
症状?②是最优解还是次优妥协?(次优必须点名"更优做法是什么、为何不做")
③是否只是暂时绕过 / 打补丁 / 加临时开关?把自审结论用「根源解 / 缓解症
状 / 临时绕过」三选一开门给出,且——非「根源解」时必须紧跟一句更根源的替
代方向 + 选当前方向的代价(如"成本高 X 倍,本次先绕过"),只写建议不写"其
实还有 A/B/C"式含糊列举;再一句说明改哪个文件哪几行、怎么改,优先复用既有
的同类处理路径,让同类场景走同一道安全网。仅供用户决策修/不修,并作为
/revise 的输入——归因(spec/impl/需求哪层出错)与最终修法由 /revise 诊断
裁定,此处不写完整代码改动
-
对话解决:展开当前问题后必须结束回合,停下等用户回应——确认修 / 讨论调整方案 / 跳过。「开始」选项与回复编号只是进入讲解流程,不构成任何一项的修复授权;每项的修复授权必须是用户看到该项完整展开后针对该项的显式回复。用户确认后调用 /revise 修复(见上方规则),一次只修当前这一个问题;revise 的完成简报即该项闭环。
-
复核剩余问题:每闭环一个,先用 read 实地核对队列中剩余每条是否仍然成立——前面的修复可能已顺带解决后面的问题。已自然解决的单行说明(项M 已被项N 的修复顺带解决:<一句话原因>)并移出队列,不再展开。
-
进入下一条,直到队列清空或用户喊停。
-
收尾小结:修复 a 条 / 跳过 b 条 / 自然解决 c 条,列出涉及的文件清单。
5. 硬约束
- review 过程不修代码、不操作 git、不扩大范围(只看 base..HEAD);唯一例外是逐个解决模式中的修复——普通问题经用户逐条确认后走 /revise,文档同步类按例外规则自动修复
- focus 仅影响关注优先级与排序,不缩小审视面:finder 不得因「不在 focus 内」而丢弃本应报出的发现,尤其安全/正确性维度
- 逐个解决模式的修复必须经 /revise 执行(文档同步类例外),禁止在对话里直接改代码
- 逐个解决模式中,任何一项未完整展开并获得用户对该项的显式确认前,禁止调用 /revise 或改动任何文件(文档同步类例外除外)
- 详细分析与修复方案只在逐个解决模式中一次一条给出,禁止开局全量平铺
- 逐个解决模式每次展开必须完整输出「背景 / 时间线 / 结果对比 / 修复方向」四段后才能结束回合等待用户;用户回复「下一个 / 继续」即要求完整展开下一条,禁止只给摘要或预告
- finder / 验证者任务消息自包含(agent 看不到本对话)
- Find / Verify 都必须经
task 子代理执行且同批并行发出;禁止主 agent 亲自 review、禁止逐个串行等待
- 去重必须跑纯代码脚本,禁止主 agent 手工判重
- 发现者与验证者隔离:验证者必须实地核对代码,不得只复读 finding 描述
- 输出语言跟随用户工作语言