# unit-tester 检测执行手册 SKILL.md v1 > 训练对象:`unit-tester-methodology-trial`(独立试验节点) > 依据:`../digest/benchmark_v1.md`(7 维度评分标准)+ `../hunt/knowhow_v1.md`(4 份真实历史样本) > 定位:本文档不复述评分标准,只回答"照着做,RESEARCH/PLAN/EXECUTE/VERIFY 每一步具体输出什么"。 > 版本说明:v1 已根据独立样本 `rn_fc9155c598ef` 的真实压力测试做过一轮修正 > (见 `sample_verification.md` 与 `iteration_log.md` Round 2),不是未经检验的初稿。 --- ## 〇、四段式 × 七维度速查表 | 阶段 | 主要产出 | 对应维度 | |---|---|---| | RESEARCH | `_research.md`(acceptance→检测手段映射表 + 场景判定) | D3 分类前置、D4/D5(b) 场景判定 | | PLAN | `_plan.md`(逐条命令 + D2 声明草稿 + 降级预案) | D2 模板、D6/D7 预案 | | EXECUTE | `test.log`(真实命令+真实输出+判定) | D1 自审、D2 独立执行、D3 裁决、D6/D7 落地 | | VERIFY | `test.log` 收尾自查段 | D1 复查、D2 措辞核对、D5(a) 可复现性核对 | D1(权重20)、D2(权重18)是核心锚点,任一 ≤2 分会把总分封顶到 50/40 ——**EXECUTE 阶段每写一句判定,先过 D1 黑名单和 D2 独立性检查,不要留到 VERIFY 才补救**。 --- ## 一、RESEARCH 阶段 ### 动作1:读齐上游产物 路径以任务描述"上游输入"段为准(硬约束2),至少读:`goal-benchmark.json`(acceptance 原文+权重+pass_threshold)、`coder.log`(上游自测记录——**只读不采信**,只用来知道上游做了什么,不能当证据引用)、被测产物本身。 ### 动作2:建立 acceptance→检测手段映射表(写入 `_research.md`) 逐条 acceptance,填这张表: | acceptance 项 | 语义分类 | 可用工具 | 是否可测 | |---|---|---|---| | (原文) | 结构性存在 / 隐含可见语义 / 布局类 | `visual-acceptance-check.mjs` / 自写 Playwright / grep / 无 | 是 / 否 / 部分 | **语义分类判据(D3 裁决,来自 `benchmark_v1.md` 二、D3)**: - **结构性存在**:只问"代码里有没有这个标识符/结构",不涉及用户能不能看见(如"是否有 3 个 `
`"、CSS 变量种类数、class 名是否符合契约)→ 允许直接 grep/正则,不需要补渲染验证。 - **隐含可见语义**:acceptance 措辞含"清晰展示""可见""用户能看到"等(如"区块内容对用户呈现")→ 判"是否可测"时就要预先标注"需要 grep 初筛 + 真实渲染可见性确认(`isVisible()`/`getComputedStyle()` 排查 `display:none`/`visibility:hidden`/`height:0`)",不能只填 grep。 - **布局类**(溢出/字号/对比度/间距)→ 只能填真实渲染工具,grep/正则在这一类里**禁止**出现在"可用工具"列。 分类做错不是小事——这张表决定 PLAN 阶段该敲定几条命令,EXECUTE 阶段才不会漏掉可见性确认。 ### 动作3:判定是否为中断恢复场景(D5(b) 前置) 检查会话/引擎侧是否有"上一次已经做到哪一步"的痕迹(如 `_plan.md` 已存在、`task transition` 历史)。若存在,**不要凭记忆断言现在在哪个阶段**——执行一次状态核实动作(例:`task transition --phase <当前认为所在的阶段>`,若返回 success 说明之前的 transition 从未真正生效,真实阶段其实还停在更早一步;样本2`rn_84d4651597bc`原始技巧),把核实命令+返回值写进 `_research.md`。若不是中断恢复(全新 attempt),在 `_research.md` 写明"本次为全新 attempt,无中断恢复场景",D5(b) 按 vacuous 处理。 ### 动作4:判定是否为复用场景(D4 前置) 检查是否存在"沿用上一次 `_research.md`/`_plan.md`/`test.log` 结论"的意图。若有,**复用前必须做**: ``` 被测产物 mtime 检查 + 上游产物(如 verify.mjs)字节级/内容级 diff ``` 两项都做才能进 5 分档,只做一项是 4 分档;只口头说"应该没变"不算数(3 分档,参照 `benchmark_v1.md` 二、D4)。把核实命令+结果写进 `_research.md`。若非复用场景(全新 attempt),写明"无复用场景",D4 按 vacuous 处理。 ### RESEARCH 产出物验收标准 `_research.md` 必须让"失忆后的自己"看懂:读了哪些上游产物、acceptance 映射表长什么样、是否为中断恢复/复用场景及其核实结论。缺任意一项,D5(a) 会扣分。 --- ## 二、PLAN 阶段 ### 动作1:为映射表每条 acceptance 敲定具体命令 把 RESEARCH 阶段"可用工具"列的抽象描述,落成 PLAN 阶段的具体命令行(含参数),写入 `_plan.md`。"隐含可见语义"类必须列两行命令(grep 初筛 + 渲染确认),不能只列一行就默认够用。 ### 动作2:写下 D2 声明草稿——**使用固定模板,不要自由改写** `benchmark_v1.md` D2 五分档的最高档要求"**明确写出**不采信 coder 自我汇报"这句话本身要出现在 `test.log` 里,不是"做到了独立重跑的事实"就自动算数。压力测试样本 `rn_fc9155c598ef`(见 `sample_verification.md`)证明:只写"未复用 coder.log 结论"这类语义等价但换了说法的表述,会被判定为"有独立重跑行为但未显式点名",只拿 4 档而非 5 档——这不是评分标准吹毛求疵,是 D2 rubric 本身逐字要求的差异,必须提前在 PLAN 阶段把原话定下来,不要到 EXECUTE 阶段临场发挥措辞。 **固定模板(EXECUTE 阶段直接抄进 test.log 开头)**: > "以下全部是本次独立跑出的真实命令输出。本节点作为独立自测节点,**不采信**上游 `coder.log` / 自带 `verify.mjs` 的自我汇报结论,全部重新真实执行一遍。" 模板里"不采信"三个字必须原样出现,这是 D2 5 分档唯一逐字核对的锚点词。 ### 动作3:预判降级路径(D6/D7) 过一遍映射表"是否可测"列: - 全部"是" → `_plan.md` 注明"未遇到混合可测/不可测场景",D6 按 vacuous 处理,不需要额外设计。 - 存在"否"或"部分" → 必须在 `_plan.md` 写清楚:能测的子项按什么命令测、不能测的子项写"这条测不了,原因是 XXX",EXECUTE 阶段逐子项分别下结论,**不允许**整条 acceptance 因为部分子项没工具就笼统判 `blocked`,也不允许因为大部分子项能测就把测不了的部分悄悄吞掉。 - 若预判会遇到工具跑不起来的情况 → 提前写好 D7 模板(动作见下 EXECUTE 三、动作5)。 --- ## 三、EXECUTE 阶段 ### 动作1:逐条独立执行,`test.log` 开头贴 D2 固定模板 把 PLAN 阶段敲定的命令逐条真实跑一遍,**不参考 `coder.log` 的判定结论**(可以读它知道被测产物在哪,不能拿它的"PASS"字样当证据)。每条 acceptance 的判定都必须能看到"本节点独立产生"的命令+真实输出。 ### 动作2:D1 自我审查信号词黑名单——写判定前先过一遍 下面这些词/句式一旦出现在某条 acceptance 的判定文字里,**这条判定不算数**,必须换成真实命令+真实输出: | 禁用信号词/句式 | 替代做法 | |---|---| | "代码走查确认"/"代码看起来没问题" | 换成具体命令输出,或如实写"这条测不了,原因是……" | | "理论上应该会通过"/"理论上没问题" | 同上 | | "规则推导后判定" | 同上(除非"规则推导"本身就是从**真实测得的数值**做算术,如"width A = width B 的 100%,≥50%门槛达标"这种基于真实输出的计算允许,因为判据是"已测得的真实数值",不是"没测就猜") | | "逻辑上应该没问题"/"跑了一部分应该没问题" | 同上 | | "大概率"/"估计"/"应该没有" | 同上 | | "看起来"/"感觉" | 同上 | 命中黑名单本身就是信号,**不是靠事后删词遮盖**——遇到真的没法用工具验证的软性维度,用"这条测不了,原因是……"(硬约束5原文句式)代替,而不是换个说法继续模糊断言。 ### 动作3:D3 两类裁决实操 执行 RESEARCH 阶段映射表时按分类严格执行: - 结构性存在类:grep/正则输出直接作为判定依据,不需要额外步骤。 - 隐含可见语义类:grep 初筛之后,**必须**补一条真实渲染可见性确认命令(Playwright `isVisible()` / `getComputedStyle()` 检查 `display:none`/`visibility:hidden`/`height:0`),两步都要出现在 `test.log` 里,只做 grep 不做渲染确认最多拿 3 分档。 - 布局类:只能用真实渲染工具(`visual-acceptance-check.mjs` 或等价 Playwright 脚本),出现 grep/正则代替真实检测直接命中 2 分档以下的反模式。 ### 动作4:D6 混合降级逐子项落地 按 PLAN 阶段预案,能测的子项写真实结果,不能测的子项显式写"这条测不了,原因是……",最终该 acceptance 维度的结论 = 能测子项真实结果 + 显式标注未验证部分,不笼统合并成一句"整体 PASS"或"整体 blocked"。 ### 动作5:D7 blocked 判定 + pytest 对照说明模板 工具跑不起来(依赖缺失/环境问题/命令报错)时,`test.log` 该条写: > "工具 `<工具名>` 因 `<具体错误/依赖缺失>` 无法执行,判定为 `blocked`。本仓库要求比 pytest 式 `skip` 更严格:`skip` 语境下的测试本来就不该在当前环境跑,跳过是预期内路径;这里是该测的 acceptance 因环境问题测不了,'测不了'和'不存在'不能混同,因此显式记 `blocked` 而非静默跳过。" 理由句不是套话,是 D7 5 分档要求的"显式说明与 skip 语义的差异"这一元认知说明,缺了只能拿 4 分档。 ### EXECUTE 产出物验收标准 `test.log` 必须包含:D2 固定模板开头、每条 acceptance 的真实命令+真实输出+判定、(若触发)D6 逐子项标注、(若触发)D7 blocked+对照说明、结尾综合结论。 --- ## 四、VERIFY 阶段 提交前逐条自查,不是走个形式: 1. **D1 复查**:通读全篇 `test.log`,用二、动作2 的黑名单表逐句核对,确认没有漏网的自我宽松表述。 2. **D2 措辞核对**:确认开头模板"不采信"三个字原样出现,且没有任何一条判定引用了 `coder.log` 的结论作为证据的一部分。 3. **D5(a) 可复现性核对**:假设自己突然失忆重新打开 `test.log`,能不能看懂当前处于哪个阶段、上一步做了什么——若 `test.log` 完全不提 `_research.md`/`_plan.md` 里记录的场景判定(是否中断恢复/是否复用),在 `test.log` 末尾补一句"本次为全新 attempt / 本次从 `_plan.md` 记录的 XXX 阶段恢复",避免只交 `test.log` 单独一份文件时可复现性不完整(详见 `sample_verification.md` 关于 D5(a) 的发现)。 4. **D5(b) 场景核对**:若 RESEARCH 阶段判定是中断恢复场景,确认核实命令+返回值确实写进了记录,不是凭记忆断言。 5. **D4 场景核对**:若 RESEARCH 阶段判定是复用场景,确认 mtime+diff 两项核实都写进了记录。 全部核对通过才算 VERIFY 完成,不是把 `test.log` 写完就直接交付。 --- ## 五、已知局限(诚实标注,不夸大规则可靠性) - D1、D6、D7 三个维度在仓库现存 4 份真实历史样本 + 本次独立验证样本里,**均未真实触发过负面场景**(D1 无 unit-tester 自身真实反例,D6/D7 均为 vacuous 命中)——本手册对应部分的操作指导是**风险移植/构造性设计**,不是从真实反例逐条校准出来的,若未来真实遇到这几类场景,指导是否够用仍需再验证。 - D2 的"固定模板"是本轮压力测试后新加的修正(见 `iteration_log.md` Round 2),只验证过"套用模板能不能拿到 5 分档"这一层,**未验证**"若上游自我汇报确实有误导性内容时,模板句式本身是否足够让 unit-tester 真正做到独立怀疑"——模板解决的是措辞层面的可核对性,不直接等于实质独立性的充分保证。