mcpField
S
skeptical-triage

skeptical-triage

github.com/avelikiy测试与质量10867 次安装今天更新
代码仓库

关于 skeptical-triage

Skeptical Triage 用于复核代码审查、安全审计、QA 回归和架构决策中的高风险判断。它通过三轮证据审查和独立仲裁给出最终结论及置信度评分。

主要功能

  1. 01依次进行三轮审查
  2. 02核验所引用的防护措施
  3. 03由独立仲裁者给出结论
  4. 04对投票结果计算置信度
  5. 05以追加方式记录分诊日志

适用场景

  1. 01筛除安全审查中的疑似误报
  2. 02判断测试失败是波动还是回归
  3. 03处理架构权衡方案的分歧

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/avelikiy/great_cto --skill skeptical-triage

安装后在 Claude Code 中输入/skeptical-triage确认已加载。

详细介绍

Skeptical Triage

在多角度审查、安全审计、QA 回归标记或任何高风险判断演变成阻塞项之前,过滤误报。

进行三轮怀疑式自审,再由公正的仲裁者裁定,并根据投票给出置信度分数。

何时调用

调用方发现类型是否进行分诊?
/review角度 2/4/7/9 的 P0/P1(安全、SQL、隐私、并发)是
/review --deep任意角度的 P0/P1是
security-officerCSO 审计 P0/P1是
security-officer源码/git 中的密钥、已确认的 CVE否 — 确定的问题
qa-engineer不稳定测试判定(这是回归还是偶发问题?)是
architectADR 权衡争议(选项 A 与 B 看起来都合理)是
任意P2/建议否

四步模式

依次执行。每一轮都会看到之前的推理。仲裁者会看到所有轮次。

第 1 轮 — 可达性 / 前提

问题:前提是否属实?

  • 对于安全性/可靠性:外部攻击者能否通过不可信输入触达这段代码路径?从问题所在位置沿输入流反向追踪到源头。如果只有受信任的内部调用方 → 倾向于判定为 INVALID。
  • 对于回归:在目标分支的干净状态下,能否复现失败行为?
  • 对于 ADR 权衡:迫使我们做出选择的约束是否真的具有约束力?(例如,“我们需要 <10ms p99”——这是实际要求还是理想目标?)

输出:{round: 1, verdict: VALID|INVALID|UNCERTAIN, reasoning: "...", crux: "single key fact"}

第 2 轮 — 核实所引用的防护措施 / 反证

问题:声称的防护措施是否真实且充分?

  • 对每项所引用的防护措施 → 使用 Grep 查找其实际实现所在的代码行。
  • 将常量名称解析为数值。MAX_BUF_SIZE 并非经过验证的上限——#define MAX_BUF_SIZE 64 才是。
  • 对于回归:所引用的“测试覆盖了这一点”是否真的断言了正确的不变量?
  • 对于 ADR:所引用的基准测试/先例是否真实存在(grep 查找并阅读),还是只是传闻?

如果无法指出落实防护措施的代码行,该防护措施就不存在。

输出:相同的 JSON 格式,并附带 grep_used: true/false。

第 3 轮 — 遗漏的角度

问题:第 1–2 轮没有考虑到什么?

  • 错误路径、整数溢出、竞态窗口、不同调用方、平台差异
  • 不要重复之前轮次的内容——补充新证据或承认不足
  • 对于 QA:重试逻辑是否掩盖了失败?测试是否受其他测试污染?
  • 对于 ADR:是否存在双方审查者都未提出的选项 C?

输出:相同的 JSON 格式。

仲裁者

输入:全部三轮、原始发现/问题以及源代码。

问题:最终裁定——哪一方的证据更有力?

  • 给出单一的 verdict: VALID|INVALID(不允许 UNCERTAIN——必须做出裁定)。
  • 给出一句话的 crux——决定裁定结果的关键事实。
  • 如果之前三轮意见一致,只有在出现压倒性的新证据时才可推翻,并说明原因。

输出:

{
  "verdict": "VALID",
  "crux": "memcpy at auth.c:142 copies network-controlled len bytes into 64-byte stack buffer with no bound check",
  "reasoning": "Rounds 1 and 3 verified attacker reach; Round 2 found no size check in 50 LOC radius; arbiter confirms no caller clamps len."
}

硬性规则

将以下规则写入每一轮的提示词中:

  1. 缺少防护措施 → 判定为 VALID,而非 UNCERTAIN。 如果你查找过防护措施但没有找到,这就是答案。“其他代码可能会处理这个问题”不是有效的防护措施。
  2. 常量名称不等于经过验证的上限——只有解析后的值才算。 使用 grep 查找 #define / const 声明。
  3. 指出代码行,否则就视为不存在。 对“此代码库中的假设”做含糊引用不算数。
  4. 不要在同一条回复中否定自己的结论。 如果你已确认防护措施不足,那就是裁定结果。不要再寻找推翻结论的理由。
  5. 代码质量问题 ≠ 安全漏洞。 诊断状态上的数据竞争、仅内部使用的 API 上的 NULL 检查、只在调试版本中出现的 UB → INVALID。
  6. 相信自己的推理。 如果你一读就看到了关键点,不要凭空编造反方论据。

置信度评分

confidence = valid_rounds_before_arbiter / 3
  • 100%(VVV)— 3/3 轮均为 VALID。仲裁者会直接认可,除非发现全新的内容。
  • 67%(VVI 或 VIV 或 IVV)— 多数为 VALID。仲裁者会根据新证据打破平局。
  • 33%(IIV 或 IVI 或 VII)— 多数为 INVALID。仲裁者通常会确认 INVALID。
  • 0%(III)— 3/3 轮均为 INVALID。仲裁者很少推翻。

仲裁者会推翻最终判定;置信度反映各轮投票结果,以便透明呈现。在输出中同时记录两者,让人们了解仲裁者在哪些地方意见不同。

将分类结果应用于严重性

仲裁者返回结果后:

仲裁者判定置信度严重性处理
VALID≥ 50%保持原严重性
VALID< 50%降级:P0→P1,P1→P2
INVALID任意从门禁统计中移除,并在报告中记录为 [FILTERED],以供审计
UNCERTAIN(仅当仲裁者无法决定时)n/a保持原严重性,标记为需要 CTO 人工审查

输出架构

每个调用方都会将分类结果记录到 .great_cto/triage-log.jsonl(仅追加,每行一个 JSON):

{
  "timestamp": "2026-04-19T12:34:56Z",
  "caller": "review|security-officer|qa-engineer|architect",
  "finding_id": "SEC-042",
  "file": "src/auth.c:142",
  "original_severity": "P0",
  "rounds": [
    {"round": 1, "verdict": "VALID",   "crux": "..."},
    {"round": 2, "verdict": "VALID",   "crux": "...", "grep_used": true},
    {"round": 3, "verdict": "INVALID", "crux": "..."}
  ],
  "arbiter": {"verdict": "VALID", "crux": "..."},
  "confidence": 0.67,
  "final_severity": "P0"
}

这份日志用于衡量分类是否发挥了作用。请每周查看:

# False-positive rate: how many findings the arbiter flipped to INVALID
jq 'select(.arbiter.verdict=="INVALID")' .great_cto/triage-log.jsonl | wc -l

# Average rounds-to-consensus (did we need all 3 or did R1+R2 agree?)
jq '[.rounds[].verdict] | unique | length' .great_cto/triage-log.jsonl

如果 50 次分类后的 FP 率 < 10%,说明分类过滤的是原本不存在的噪声。降低阈值,或跳过该角度的分类。如果 FP 率 > 40%,说明原始审查提示词过于容易触发;收紧角度规则。

令牌预算

每条分类结果约需 4 次 LLM 轮次(3 轮 + 仲裁者)。按典型审查规模估算(每个 PR 有约 5-10 条待分类结果),每次 /review 总共额外需要 20-40 次轮次。尽可能批量处理——如果多个结果的关键问题彼此独立,一个仲裁者可以在一次调用中处理它们。

对于成本敏感的运行(超大型 PR 上的 approval-level: auto),可以考虑:仅对 P0 进行分类,不对 P1 进行分类。根据 .great_cto/triage-log.jsonl 中的数据重新调整。

反模式

  • 不要对 P2/建议性结果进行分类。 这么做的目的在于决定门禁。P2 是建议性的——让作者看到后继续即可。
  • 不要让各轮反复讨论相同内容。 第 3 轮的提示词必须写明“添加新证据或认输”。如果 3 轮给出的推理完全相同,你就浪费了 2 次轮次。
  • 不要在结果为 UNCERTAIN 时跳过仲裁者。 如果 3 轮都给出 UNCERTAIN,仲裁者的职责就是做出决定,而不是加入迷雾。
  • 不要隐瞒仲裁者的推翻结果。 仲裁者推翻多数投票时,同时记录 confidence(投票结果)和 final_verdict(仲裁者的判定)。人们有权了解这场分歧。

评论

支持 Markdown