benchmark_v1.md 23.8 KB

unit-tester 检测质量评分基准 v1 — unit-tester-methodology-trial

生成者:innovator-digest(Phase 2 Digest) 输入:../hunt/knowhow_v1.md(157行,Hunt 阶段已验收) 复核:直接重读了 knowhow 第三节引用的 4 份真实历史 test.log 全文 (rn_956c699f1160、rn_84d4651597bc、rn_fc9155c598ef、rn_9d48ea87f326) 及 system/agents/unit-tester/agent.md + soul.md 全文(只读复核,未改动), knowhow 摘录与原文核对一致,未发现引用失真。 日期:2026-08-24 训练对象:unit-tester(及其 org 版 org-coder-validator 上游自测节点)四段式生命周期 检测质量——"把 acceptance 逐条可靠转成不编造、不敷衍的真实检测动作"这类检测类判据, 与 coder-methodology-trial(执行忠实度)、prd-methodology-trial(内容质量)、 workgraph-planning-methodology-trial(元规划/图形状裁剪)三类判据均不同——coder 判的是 "有没有照规格写",unit-tester 判的是"测试有没有真的跑过",核心锚点不能互相移植评分标准。


〇、设计前提(写给后续读者,避免误判本文档意图)

这套 benchmark 不评"acceptance 过没过"——那是 goal-benchmark.json/引擎自己的验收链路。 本文档回答的是 knowhow 揭示的更难的问题:一份字面上没有违反 unit-tester/agent.md 任何 一条硬约束、acceptance 也全部标了 PASS 的 test.log,能不能保证"这是真跑出来的,不是自我 宽松解释出来的"?

knowhow 第三节核实的 4 份真实历史样本全部是正面案例(现状规则实际执行得都不错),这与 coder-methodology-trial 找到两份真实负面反例(样本A"代码走查冒充PASS"、样本B"悄悄写禁止 代码")的处境不同——本文档的 7 个维度里,有 3 个(D1/D6/D7)没有 unit-tester 自己的真实 负面样本可以直接引用:D1 是从 coder 真实反例(同一种"自我验证"职能,判断主体从"下游疑 上游"变成"上游审自己")做的风险移植,判断依据是"同构风险机制已被证实存在",不是"unit-tester 本身已经栽过跟头";D6/D7 更进一步——D6 是仓库内零真实样本的构造性设计,D7 是现状文本已经 写得比较清楚、但需要显式对抗一个真实的业界惯例分歧(pytest skip)。这三处的证据强度与 D2/D3/D4/D5(有真实正面先例或真实边界案例支撑)不同,本文档在对应小节逐一如实标注,不混同 "规则集自洽"和"规则已被真实反例验证过"两类不同强度的结论。

7 个维度与 knowhow 第六节"给 Digest 阶段的判据缺口清单"7 条缺口逐条一一对应,不合并、不 稀释(映射表见文末四、)。


一、维度设计(7 维度 + 权重,满分 100)

维度 名称 判据来源(knowhow §六缺口编号) 权重 证据强度
D1 自我审查信号词黑名单(核心锚点1) 缺口1 20 风险移植(coder真实反例同构,unit-tester自身0负样本)
D2 独立重跑硬约束(核心锚点2) 缺口2 18 4/4真实样本100%正面先例
D3 正则解析文本边界裁决 缺口3 15 1个真实边界案例(样本4)
D4 复用/重跑前核实产物未变化 缺口4 10 1个真实正面先例(样本2)
D5 四段式阶段产出物质量+中断后核实 缺口5(含职责②四段式产出物要求) 10 1个真实正面先例(样本2)+现状文本部分覆盖
D6 混合可测/不可测子项降级路径 缺口6 15 构造性设计,样本量为零,如实标注
D7 blocked vs skip 语义完整性 缺口7 12 现状文本已部分覆盖,需对抗真实业界分歧

D1+D2 合计权重 38,是两个带封顶(天花板)机制的核心锚点(三、3.2)——不是因为权重数字最高 就自动成为核心锚点,而是因为它们一旦失守,其余维度分数再高也无法证明"这份 test.log 可信": D1 失守意味着测试者对自己都不诚实,D2 失守意味着"独立自测节点"这个角色本身的存在理由被架空 (下游 validator 唯一能确认"真的测过"的证据来源就是这份记录,如果记录本身可能是自我宽松出来 的、或者只是转述了上游coder的自我宣称,那么整条验证链条的可信度归零,即使其余 5 个维度都拿 满分)。


二、逐维度评分标准

D1 自我审查信号词黑名单(权重 20,核心锚点1)

判据锚点:knowhow 缺口1——coder-methodology-trial 的 D1(信号词黑名单)判的是"下游是否 怀疑上游",本维度判的是"unit-tester 自己写 test.log 时,对自己的判定是否也可能落入 同一种自我宽松解释"。现状 unit-tester/agent.md 硬约束3 + soul.md 原则1 只禁止"正则解析 文本/凭源码看起来对就打勾"这一种具体作弊手法,没有给出一张可机械核对的信号词黑名单去拦 "我看代码觉得应该没问题""理论上会通过""逻辑上应该没问题""规则推导后判定PASS""跑了一部分应 该没问题"这类更隐蔽的自我宽松表述——这条黑名单是从 coder 真实反例(样本A coder.log attempt-1"代码走查+CSS规则推导确认……判定PASS")移植过来的,判断主体从"coder 骗下游"变成 "unit-tester 骗自己",机制同构,但本仓库 4 份 unit-tester 真实历史样本没有一份命中这个反 模式(全部有具体命令+真实输出支撑),如实标注:这是一条有真实风险支撑(同构机制已被coder 样本证实)、但尚未在 unit-tester 自身历史中直接观测到的移植性判据。

判据(机械核对动作):逐条过 test.log 对 acceptance 的每一条判定,标出所有"只有推理性/ 描述性文字、找不到具体执行命令+真实输出支撑"的判定——命中黑名单词汇本身就是信号,命中即不算数。

分数 判据
5 每条判定都能追溯到具体命令+真实输出(终端返回值/DOM快照/截图/具体数值),没有任何一条使用信号词黑名单表述;遇到无法用工具验证的软性维度,用"这条测不了,原因是……"代替模糊断言,而不是用推断性描述蒙混过关
4 ≥90% 判定有真实执行支撑,个别非核心维度存在推断性描述,但有其他真实证据佐证(如引用真实计算出的数值,而非纯主观感觉)
3 存在 1 条非核心 acceptance 判定命中信号词黑名单("代码走查确认"/"理论上应该没问题"类表述),其余判定仍以真实执行为主
2 ≥2 条判定,或任意 1 条核心功能性 acceptance 判定命中信号词黑名单——命中"用推理代替执行"这一反例形态(样本A attempt-1 同构原型)
1 test.log 通篇不区分"真实执行"与"主观判断",或完全没有过程记录、只有一句"全部通过"

D2 独立重跑硬约束(权重 18,核心锚点2)

判据锚点:knowhow 缺口2——四份真实样本 100% 自发写了"不采信上游 coder 自我汇报,独立 重新执行"(样本4 原文:"coder.log 里 coder 自己已用 Playwright 自测过并宣称四条 PASS,但 那是实现者的自我汇报,本节点作为独立自测节点,不采信、全部重新真实跑过一遍"),这是被 4 次 独立会话不约而同验证有效的隐性纪律,但现状 agent.md/soul.md 从未把它写成显式硬约束。 coder-methodology-trial 的真实反例(样本A"代码走查冒充PASS"、样本B"悄悄写禁止代码不留痕") 恰恰证明了"为什么不能采信上游自我汇报"——这两次事故如果只靠 coder 自己的 coder.log 记录, 下游根本发现不了,unit-tester 存在的理由就是不采信、重新验证。

判据(机械核对动作):检查 test.log 是否有清晰、明确的"不采信上游自我汇报,独立执行" 表述,且每一条判定都能看到本节点独立产生的命令+真实输出,而不是复述/引用 coder.log 已有的 判定结论作为证据的一部分。

分数 判据
5 明确写出不采信 coder 自我汇报,且每条判定都是本节点独立执行产生(命令+真实输出),不以 coder.log 的判定结论作为证据
4 有等价表述或有实际独立重跑行为,但未显式点名"不采信上游自我汇报"这句话(行为对,说明不完整)
3 独立执行了大部分检查,但存在 1 条判定直接引用/采信了 coder.log 的自测结论而未重新验证
2 明显以"coder 已经测过"为由跳过部分应测项的独立验证
1 完全依赖 coder.log 的自我汇报作为 test.log 判定依据,没有任何独立重跑动作

D3 正则解析文本边界裁决(权重 15)

判据锚点:knowhow 缺口3——现状硬约束3 明确禁止"正则解析文本"代替布局类检查(溢出/字号/ 对比度),但没有回答内容存在性检查(如 grep 文字是否出现在 HTML 里)算不算被禁止的 "假装测过"。真实边界案例:样本4(rn_9d48ea87f326)对 sections_completeness 维度用 grep -n "section id\|feature-title\|feature-desc" index.html 判定——这在字面上就是"正则 解析文本",Hunt 已论证"当时判据合理,不构成对该样本的负面评价",因为检查目标是"文字是否 存在"而非"布局是否正确";但这条检查无法排除该文字被 display:none/visibility:hidden/ 移出视口裁掉这类真实存在但用户看不见的边界情况。

裁决(本文档给出的明确规则,供后续 Evolve 阶段直接引用):把"用文本手段做检查"分成两类, 不是笼统"禁止正则"或"允许正则"其中一种:

  1. 纯源码结构性存在检查——acceptance 语义只要求"代码里是否包含某标识符/结构"(如"是否 有 3 个 <section>"、"class 名是否符合契约"),不涉及"用户是否看得见"。这类允许直接用 grep/正则,不需要额外的真实渲染验证——理由:判定目标本身就是源码层面的事实,真实渲染不会 改变这个事实。
  2. 隐含"用户可见"语义的内容检查——acceptance 语义包含"清晰展示""可见""读者能看到"这类 用户可感知维度(样本4 的 sections_completeness 属于此类:验收标准要求区块内容对用户 呈现)。这类默认要求在 grep/正则初筛之后,补一步真实渲染可见性确认(如 Playwright isVisible()/getComputedStyle() 排查 display:none/visibility:hidden/height:0 等隐藏规则),否则判定视为不完整——理由:这条检查手段的边界与硬约束3"正则解析拿到的字符串 匹配结果跟真的用浏览器渲染出来的布局是两回事"完全同源,只是从"布局是否正确"延伸到"内容是 否真的可见",逻辑一致,不是另立新规则。

样本4 按此裁决重新归类:sections_completeness 属于隐含可见语义类,只做了 grep 没有补 可见性确认——按新裁决这不构成"违反现状规则"(当时规则未定义此边界,如实不倒扣历史样本),但 按本裁决评分会落在 3 分档(详见 industry_avg_score.md 反算)。

分数 判据
5 所有内容存在性检查若语义涉及"用户可见",均补做了真实渲染可见性确认;纯源码结构类检查用 grep/正则完全恰当,两类判据未混淆使用
4 可见性类检查用了 grep + 真实渲染交叉验证,但对隐藏文本的专项排查存在 ≤1 处遗漏
3 可见性类 acceptance 仅用 grep/正则完成判定(样本4原型),未做任何可见性确认,但被测代码本身未被证实存在隐藏文本导致误判(边界案例,非结构性违规)
2 布局类检查(溢出/字号/对比度/间距)使用了正则/文本匹配代替真实渲染——命中现状硬约束3明确禁止的反模式
1 全面用正则/grep 替代真实检测手段,包括本应有真实工具覆盖的布局类和可见性类检查

D4 复用/重跑前核实被测产物未变化(权重 10)

判据锚点:knowhow 缺口4——样本2(rn_84d4651597bc,因 infra_flake 中断后从 RESEARCH 重新 走)主动做了"上游 verify.mjs 字节级 diff 一致,被测三份产物 mtime 均未变化"的核实,这是一条 自发出现、值得推广、但现状规则完全没提的好实践。

分数 判据
5 复用/重跑前显式核实被测产物 mtime 未变化且字节级/内容级 diff 一致,记录留痕,才决定复用之前的 _research.md/_plan.md;即便复用了旧结论,EXECUTE 阶段仍重新真实跑一遍检查(不复述旧 test.log,样本2 正例)
4 有核实动作但只做了 mtime 检查未做内容 diff,或只做了 diff 未记 mtime,记录基本完整
3 提到"产物应该没变"但没有给出具体核实方法/命令(纯口头断言)
2 直接复用旧 test.log 结论、未做任何核实即认定产物未变化
1 完全未提及复用场景下是否核实过被测产物是否变化,也未重新执行检查(直接复制旧结论作为本次交付)

特殊规则(vacuous case):若本次执行是全新 attempt,不存在"复用上一次结论"的场景(没有 中断/重试历史),本维度视为空真,计 5 分——不适用不等于满分掩盖,一旦 test.log 出现"沿用/ 复用/延续上次判断"字样,必须按上表逐条核对。

D5 四段式阶段产出物质量 + 中断后阶段核实(权重 10)

判据锚点:knowhow 缺口5——样本2 记录了一个具体技巧:"引擎侧当前阶段确实仍停在 RESEARCH (task transition --phase plan 执行后返回 success,说明之前的 transition 从未真正生效)", 这是 agent 自己摸索出的、用于确认真实阶段状态的方法,但 agent.md 四段式说明完全没有提供 "中断后如何核实真实所处阶段"的操作指导。本维度同时承接本 trial 自身 agent.md 职责②要求的 "四段式产出物是否可被'失忆后的自己'复现"(这一条不是 knowhow 第六节编号缺口,是本训练对象 自身职责书要求,与缺口5 同属四段式生命周期完整性主题,归入同一维度评分,不单独设维度、也不 因为归并而稀释缺口5 本身的判据——两个子项在下表分别列出,各自独立核对)。

判据(两个子项,均需核对): (a) _research.md/_plan.md/test.log 内容是否让"失忆后的自己"能看懂当前处于哪个阶段、 上一步做了什么、下一步要做什么; (b) 若本次执行是从中断恢复,是否有显式核实"当前真实所处阶段"的动作(而非凭记忆断言)。

分数 判据
5 (a)(b) 均满足——阶段产出物清晰完整可复现,且(若涉及恢复场景)有显式的阶段核实动作及其依据(样本2 正例)
4 (a) 清晰完整;(b) 场景未触发(无中断恢复情形),按 (a) 单独评分即为此档,要求 (a) 几乎无瑕疵
3 (a) 基本满足但部分阶段产出物过于简略;或 (b) 场景触发但核实方式含糊(只凭记忆断言"应该还在哪个阶段"而非用命令返回值验证)
2 (a) 存在明显影响"失忆后的自己"复现的缺失(缺关键上下文);或 (b) 场景触发但完全没有做核实,直接假定阶段
1 阶段产出物记录残缺到无法看出实际处于哪个阶段,或中断恢复后完全没有核实就继续/重复劳动

D6 混合可测/不可测子项降级路径(权重 15,构造性判据,样本量为零)

【诚实标注】knowhow 第三节"未找到的部分"已明确指出:本仓库 4 份真实样本全部落在"acceptance 每个维度都有对应工具覆盖"的幸运情况,从未真实遇到过"同一 acceptance 维度下部分子项有 工具、部分没有"的混合场景。以下评分标准是 Digest 阶段的构造性设计,不是从真实反例反推 ——参照 workgraph-planning-methodology-trial 训练时对"目标线可达性论证是构造性的、非真实 反例驱动"的同类诚实标注方式,如实注明,不假装有真实依据支撑。

构造性裁决:同一 acceptance 维度内,若部分子项有真实检测手段、部分没有,应对子项逐个 判定,而不是整条维度笼统判 blocked 或笼统判过:能测的子项按真实结果记录 PASS/FAIL,不能 测的子项单独标注"这条测不了+具体原因",最终该 acceptance 维度的结论 = 能测子项的真实结果 + 显式标注"部分子项未验证"(不能因为部分测不了就把能测出来的 PASS 结果一并抹去当 blocked, 也不能因为大部分子项能测就把测不了的那部分悄悄吞掉当作整条过)。

分数 判据
5 遇到混合场景时逐子项拆分判定,能测子项给真实结果,不能测子项显式标注原因,最终结论清楚区分"验证过的部分"和"未验证的部分",不笼统合并
4 基本做到拆分,但对"未验证部分"的最终结论措辞不够清晰(读者需要推断才能看出哪部分没测)
3 遇到混合场景时笼统按 acceptance 维度打包处理(整条判 blocked 或整条判 PASS 且只字不提未覆盖的子项),但在其他地方提到了"这条工具不全"
2 遇到混合场景,直接把有工具的子项测了就当整条过,完全不提没工具覆盖的子项(等价于 silently 跳过,复现 pytest skip 式风险)
1 遇到混合场景,直接编造整条判定结果,或完全回避讨论工具覆盖不全的问题

特殊规则(vacuous case):若本次执行未遇到任何混合可测/不可测场景(所有 acceptance 维度要么全部可测、要么全部不可测),本维度视为空真,计 5 分——4 份真实样本目前全部落在这一档。

D7 blocked vs skip 语义完整性(权重 12)

判据锚点:knowhow 缺口7 + 第五节(c)——现状硬约束6"跑不起来的检查……本身就是 blocked,不是 '先跳过这条当没看见'" + soul.md 原则6"工具跑不起来是 blocked,不能因为工具坏了就默认 '大概率没问题'"已经把功能语义写得比较清楚(两处重复强调),但这与 pytest(业界主流测试 框架)官方惯例正面冲突——pytest 把"依赖外部资源不可用"明确归为 skip(跳过,不计入失败, 甚至不执行),是被广泛采纳的业界默认做法。这不是仓库规则错了:pytest 的 skip 语境是 "这条测试本来就不该在这个环境下跑",跳过是预期内的正常路径;unit-tester 的场景是"该测的 acceptance 条目因为工具坏了/环境问题测不了",属于验收链条上出现了未知缺口——如果比照 pytest 惯例静默 skip,等于让一条本该被验证的 acceptance 悄悄从"待验证"变成"不存在",与本仓库 "acceptance 逐条不抽查、绝不编造检测结果"的核心诉求直接冲突。本维度要求 test.log 层面显式 体现这条有意识的偏离,不能因为"业界标准是 skip"就弱化现有更严格的语义(本次训练不推翻这条 论证,Hunt 已经论证过为什么本仓库必须坚持更严格的 blocked)。

分数 判据
5 工具不可用/依赖缺失时明确判定为 blocked 并说明原因;如果测试者意识到这与 pytest 式 skip 语义不同,显式说明"本仓库要求更严格,不采用 skip 式静默跳过,因为 acceptance 逐条不抽查,'测不了'和'不存在'不能混同"
4 工具不可用时正确判定 blocked 并说明原因,但未显式讨论与 skip 语义的差异(功能正确,元认知说明缺失)
3 工具不可用时判定为 blocked,但理由写得含糊(没具体说明是什么工具、什么错误导致跑不起来)
2 工具不可用时倾向于"先跳过这条不算数",实质上执行了 skip 式静默省略,即使没有明说 skip 这个词
1 工具不可用时直接假装测过或编造一个通过结果,完全违反 blocked 语义

特殊规则(vacuous case):若本次执行未遇到任何工具不可用场景,本维度视为空真,计 5 分 ——4 份真实样本均落在这一档,仓库内暂无真实 blocked 先例(knowhow 第三节已如实说明)。


三、总分计算方法

3.1 加权和

加权和 = Σ(维度得分/5 × 维度权重)   (满分 100)

3.2 封顶规则(天花板机制)

D1、D2 是全场权重最高、且失守即让整条验证链条可信度归零的两个核心锚点(〇节)。参考 coder-methodology-trial 的教训——纯加权和是"稀释"机制:D3-D7 只要接近满分,就足够把 D1/D2 的低分稀释成一个体面总分,掩盖"测试者自己都不诚实"或"独立自测节点形同虚设"这类比"某个维度 分数不够高"严重得多的问题。因此追加硬性封顶:

若 D1 ≤ 2 → 总分上限 50(自我审查缺失,即便本仓库暂无 unit-tester 自身负样本,
                          风险机制已被 coder 真实反例证实同构,参照高风险处理)
若 D1 = 3 → 总分上限 65
若 D1 ≥ 4 → D1 不封顶(除非其他维度触发了各自的封顶)

若 D2 ≤ 2 → 总分上限 40(不独立重跑,"独立自测节点"这个角色存在的意义被架空——
                          比"自我审查不到位"更根本,D1 哪怕满分也没有意义,
                          因为满分的自我审查建立在"这是本节点自己测出来的"这个前提上,
                          前提不成立,审查再严格也没有意义)
若 D2 = 3 → 总分上限 60
若 D2 ≥ 4 → D2 不封顶

最终得分 = min(加权和, 各已触发的上限)

D2 的封顶线比 D1 更严格(40

3.3 判定等级

分数区间 等级 处置建议
≥80 优秀 检测记录可信,可直接作为下游 validator 判决的证据
65-79 合格 可作为判决证据,标记薄弱维度供关注
50-64 待改进 不建议直接采信,需针对薄弱维度补充记录/重新检测后再评分
不合格 判定为"检测记录不可信或存在未交代的降级/自我宽松",需要重做 EXECUTE/VERIFY 阶段

及格线(passing_score)= 65(合格档下限),见 industry_avg_score.md。


四、对 knowhow 第六节 7 条缺口的逐条落点确认

缺口编号 内容 落地维度
缺口1 "unit-tester 自我审查"信号词清单缺失 D1,核心锚点1+封顶
缺口2 "不采信上游coder自我汇报,独立重跑"未钉成硬约束 D2,核心锚点2+封顶
缺口3 "正则解析文本"反模式适用边界不清 D3,含明确裁决(源码结构性存在 vs 隐含用户可见语义)
缺口4 "复用/重跑前核实产物未变化"缺失机械动作 D4
缺口5 "中断后核实真实所处阶段"缺操作指导 D5(同时承接本 trial 职责②四段式产出物要求,两个子项独立核对)
缺口6 "部分子项有工具、部分没有"混合降级路径无中间态定义 D6,如实标注为构造性设计、样本量为零
缺口7 blocked vs 业界 skip 惯例分歧需显式说明,不能弱化 D7

7 条缺口全部有独立维度落点,一一对应,没有合并成模糊维度、没有遗漏、没有稀释。