Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 150 additions & 4 deletions evals/baseline.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

首次跑通 `evals/runbook.md` 的三种问法,记录结果作为后续改动的对照点。

> **口径提示**:本文件记录的是**首轮 12 条 ground truth 口径**下的分数。随后 `ground-truth.md` 已扩充到 25 条(补进首轮实测发现的 13 条真缺陷,见 #14 / #15),`rubric.md` 的分母同步改为 25。
> **本文件的分数与新口径不可直接比较**——要比较,必须按新口径重跑一轮。
> 新口径下的重跑结果尚未产生,本文件暂按首轮事实保留。
> **口径提示**:本文件上半部分是**首轮 12 条 ground truth 口径**下的分数,保留为历史事实、不覆盖。
> 下半部分「v4 轮」是**25 条口径**下的重跑结果——改完标准答案、重跑、锁定判分口径之后才有资格谈发版。
> **两轮分数不可直接比较**:GT 条目数(12→25)、归类分母、命中判据三样都变了。要比较必须按同一口径重跑。

**结论先行**

Expand Down Expand Up @@ -199,4 +199,150 @@ B 轮提出的另一个角度更接近真实问题:承诺里提到的「订单
| `evals/rubric.md` | 评分表与五维口径 |
| `evals/runbook.md` | 怎么跑一次评测 |
| `evals/fixtures/tiny-shop/` | 样本(约 150 行 Go) |
| 仓外 `scratchpads\dcr-eval\runs\round-{A,B,C}.md` | 三轮原始输出,不入版本控制 |
| 仓外 `scratchpads\dcr-eval\runs\round-{A,B,C}.md` | 首轮三轮原始输出,不入版本控制 |

---

# v4 轮(25 条口径 · 冻结提交 `7c1c4ea`)

改完标准答案(G4 改判、GT 扩到 25 条、硬编码细则去矛盾)之后重跑的一轮。**这一轮的分数是 v1.1.0 的发版依据。**

## 运行条件

| 项 | 值 |
|---|---|
| 日期 | 2026-10-21 |
| skill 版本 | 冻结提交 `7c1c4ea`(`fix/consistency-and-lint`)——三轮全程未改任何 skill 文件 |
| 被测上下文 | 三个全新子 Agent 上下文,互不污染,轮间不共享结论 |
| 样本 | `evals/fixtures/tiny-shop` 逐字节复制到仓外 `scratchpads\dcr-eval\tiny-shop`,README 中性化 |
| 隔离 | 只禁仓库 `evals/` 目录;skill 路径显式指向装线 `C:\Users\LUOYN\.minimax\skills\deep-code-review`(与仓库同 hash) |
| 原始输出 | 仓外 `scratchpads\dcr-eval-archive\round-{A,B,C}-v4.md`,**不入版本控制** |
| 输出指纹 | A `BA1FFA73…C691B4` / B `A13EA522…F48912` / C `3037B600…238DC`(SHA256) |

这一轮之前有两次重跑作废:一次跑在「边改边测」的移动靶上,一次让子 Agent 读到了磁盘上的旧 skill 副本。两条都写进了 `evals/runbook.md` 的卫生规则。

## 结论先行

1. **误报三轮全 0**。包名/目录名这条三处都守住了边界(A 排除、B/C 进拍板且明写「不进必须修」),没有一条混进修复项。
2. **命中 15.5 / 13.0 / 19.5(满分 25)**。C 轮(模块体检)最好,A 轮(快模式)次之,B 轮最低——B 掉的主要是 G14(单位不一致)这类**设计面**条目,快模式按契约本就不报,符合预期。
3. **C 轮命中最高、raw 反而最低**(151.6 vs A 的 163.4)。差距全在证据:C 的证据均值 4.20,A 是 4.93。**C 靠「读完 + 读懂」拿命中,A 靠「跑探针」拿证据。** 想提分,方向是让全量轮也像快模式那样去跑探针。
4. **「文档维度整体失灵」是错的说法**。三轮报出的文档类问题都落在 G3/G11/G14 上——说明模型**能**发现「文档与实现不一致」。真正系统性漏掉的是两种更窄的形态:**位置指代型**(G19:注释说「第二个返回值」,实际 bool 是第一个)和**承诺无对应对象型**(G4:godoc 里的「订单存储」在这个模块里根本不存在)。
5. **共同漏报(作为条目报出 = 0)只有 3 条**:G4、G19、G22。另有 G23(`Order.ID` 零使用)三轮都没当成条目报出。G9/G25 的 0 是「同一根因只算一次」的结构性结果,不是能力漏报。
6. **首轮票面的三条断言,第三条不成立**:① 硬编码维度**部分成立**(B、C 结论一致,但只有 B 明确区分「协议固定值 100 不算」,C 全文没提 100);② 包名处置**成立**;③ 「真正的文档缺陷仍报得出来」**不成立**——GT 点名的 G4/G19 三轮都没报出来,三轮报的文档类问题全落在 G3/G11/G14,不能充数。

## 汇总

| 维度 | A(快模式·合并判定) | B(全量·按七维审) | C(全量·模块体检) |
|---|---|---|---|
| 命中 | 15.5 / 25(62.0%) | 13.0 / 25(52.0%) | 19.5 / 25(78.0%) |
| 误报 | 0 条 | 0 条 | 0 条 |
| 归类合计 / 已报条目数 | 10.5 / 14(75.0%) | 8.0 / 15(53.3%) | 12.0 / 15(80.0%) |
| 证据强度均值 | 4.93(69/14) | 4.73(71/15) | 4.20(63/15) |
| 表达质量 | 14.1 / 14.5 | 15.1 / 15.5 | 15.1 / 15.5 |
| **raw** | **163.4** | **154.4** | **151.6** |

**分母说明**:归类的分母是**报告实际交付的 finding 条目数**(必须修 + 建议修 + 拍板),不是 25——未报出的 GT 条目按 0 计进归类合计,所以归类同时受漏报拖累。表达质量的满分是「条目数 + 0.5」(C1 的加分)。

## 逐条对照

`命中/归类`。`—` 表示完全没涉及。

| GT | 级别 | A | B | C | 说明 |
|---|---|---|---|---|---|
| G1 零值 `Checkout` panic | P1 | 1/1 | 1/0.5 | 1/1 | B 报 P2,偏一级 |
| G2 `timeout` 形同虚设 | P1 | 1/1 | 1/1 | 1/1 | 三轮都给了零引用证据 |
| G3 `Code` 从未被读取 | P1 | 1/1 | 1/1 | 1/0.5 | C 判成拍板(GT 判缺陷) |
| G4 承诺没有对应对象 | P2 | 0.5/0 | 0.5/0 | 0/0 | A/B 只说了「模块内没有 IO」就判「承诺成立」;C 说的是镜像问题 |
| G5 批次中途失败计数残留 | P1 | 1/0.5 | 1/0.5 | 1/1 | A/B 报 P2,偏一级 |
| G6 两份元→分换算漂移 | P2 | 1/0.5 | 1/0 | 1/0 | B/C 都报 P0,偏两级;A 报 P1 最接近 |
| G7 `E_INVALID` 两个真相源 | P2 | 1/1 | 1/1 | 1/1 | 三轮都给了 `errors.Is` 恒假的论证 |
| G8 `refundWindow` 硬编码 | P2 | 1/1 | 1/0.5 | 1/0.5 | B/C 判成拍板(GT 判缺陷) |
| G9 折扣接口过度设计 | P2 | — | — | — | 同一根因并入 G3,不重复计分 |
| G10 测试盲区 | P2 | 1/0.5 | 0.5/0 | 1/0.5 | A/C 在覆盖行里点到了变体;B 只说了并发路径零覆盖 |
| G11 测试用字符串比较断言 | P2 | 1/0.5 | 1/0.5 | 1/0.5 | 三轮都写进了 E_INVALID 条目的证据与修法,但都无独立级别 |
| G12 `Percent` 无范围校验 | 拍板 | 0.5/0 | 0/0 | 1/0.5 | A 明确排除;B 完全未提;C 在别的拍板项里顺带提到 |
| G13 退款窗口从查询时刻起算 | P1 | 1/0.5 | 1/1 | 1/1 | A 没说业务前提;B/C 的拍板项问了「24h 是不是统一口径」 |
| G14 `Issue` 收元 / 返分 | P1 | 1/1 | — | 1/0.5 | B 漏报;C 判成 P2,偏一级 |
| G15 0 元退款被记成已退款 | P2 | — | — | 1/0.5 | C 判成拍板(GT 判缺陷) |
| G16 `Refunder{}` 零值 panic | P2 | 1/1 | — | 1/0.5 | B 漏报;C 与 G1 并成一条,宿主级别 P1 |
| G17 共享指针 + 非原子自增 | P1 | 1/1 | 1/0.5 | 1/0.5 | B/C 报 P2,偏一级 |
| G18 `issued` map 只增不减 | P2 | — | — | 1/0.5 | B 的性能维度写了「无无界缓存」——**与 G18 相反的覆盖声明**(不扣误报,但属假阴性) |
| G19 注释「第二个返回值」写反 | P2 | — | — | — | B 引了那段 godoc 去**背书**幂等语义,没核返回顺序 |
| G20 NaN/Inf 绕过校验 | P2 | — | 1/0.5 | 1/1 | A 漏报;B 报 P1 偏一级 |
| G21 两个计数口径不一致 | P2 | 0.5/0 | 1/1 | 1/0.5 | A 明确判为不报 |
| G22 状态持久性接缝缺失 | P2 | 0.5/0 | — | — | A 划进「本次没覆盖」;B 兼容性维度未扫;C 判「无发现」 |
| G23 `Order.ID` 零使用 | P3 | — | — | 0.5/0 | C 全文提及但判为「无注入面可报」 |
| G24 折扣先截断再减 | P3 | 0.5/0 | — | 1/0.5 | C 判成拍板(GT 判缺陷) |
| G25 折扣机制整体未接线 | P2 | — | — | — | 同一根因并入 G3 |
| **命中合计 / 25** | | **15.5** | **13.0** | **19.5** | |
| **归类合计** | | **10.5** | **8.0** | **12.0** | 未报出记 0 |

## 证据强度明细

分母 = 该轮交付的全部 finding 条目数(含拍板项)。无一条触发「声称强度高于实际」或「已查过没问题没给验证方式」的扣分。

| 轮 | 条目与分数 |
|---|---|
| A | P1-1 换算重复 5、折扣未接线 5、timeout 5、nil Stats 5、计数器竞态 5、Issue 单位 5、窗口滑动 5、**P2-8 硬编码 4**、错误身份 5、零值 Refunder 5、计数残留 5、拍板1 5、拍板2 5、拍板3 5 → **69/14 = 4.93** |
| B | P0 换算 5、P1 折扣 5、timeout 5、窗口 5、NaN/Inf 5、P2 并发 5、错误路径 5、口径 5、零值 5、E_INVALID 5、**过度设计 3**、拍板1 5、拍板2 5、**拍板3 硬编码 3**、拍板4 包名 5 → **71/15 = 4.73** |
| C | P0 换算 5、P1 零值 5、窗口 5、**timeout 4**、计数器 5、P2 上界/NaN 5、并发 5、重复 5、**文档单位 2**、可观测性 4、测试盲区 4、拍板1 折扣 5、**拍板2 硬编码 2**、拍板3 幂等 5、**拍板4 包名 2** → **63/15 = 4.20** |

**A 轮最强**:11 条 P1/P2 全部有探针。**C 轮最弱**:3 条只读码没跑探针(拍板2 硬编码、拍板4 包名、P2 文档单位),1 条只 grep 确认未覆盖。

## 表达质量明细

| 轮 | 说明 |
|---|---|
| A | P1-1…P1-7 各 1.0;**P2-8 硬编码 0.6**(讲清机制,只给了「改成 48h 或 7 天」的场景,没有对照例子);P2-9…P2-11 各 1.0;拍板1–3 各 1.0;**C1 +0.5**(`-race` 无告警 + 锁范围推理)→ **14.1 / 14.5** |
| B | P0、P1×4 各 1.0;P2 并发/错误路径/口径/零值/E_INVALID 各 1.0;**过度设计 0.6**(讲清机制,无对照例子);拍板1–4 各 1.0;**C1 +0.5**(8 goroutine × 300 次 `-race` 无告警)→ **15.1 / 15.5** |
| C | P0、P1 零值/窗口/计数器、P2 上界/并发/重复/文档/可观测性/测试盲区 各 1.0;**P1 timeout 0.6**(讲清机制,无对照例子);拍板1–4 各 1.0;**C1 +0.5**(`-race` 报告 PASS)→ **15.1 / 15.5** |

## 首轮票面三条断言的复核结果

| 断言 | 结论 | 依据 |
|---|---|---|
| ① 硬编码维度:B、C 结论一致,且能区分「协议固定值 100 不算」与「业务政策值 24h 算」 | **部分成立** | B 明写「`100` 是协议固定值(分/元),按规则不算」,C **全文未提 100**——从报告文本无法证明它做了这个区分。两轮都把 24h 当业务政策值、都给「参数/配置项」两条路,结论一致 ✔ |
| ② 包名/目录名不进「必须修/建议修」 | **成立** | A 排除候选「按命名细则属口味,不报」;B「这条本身按规则属于命名口味,所以不进必须修」;C「只是风格统一建议,不影响正确性」 |
| ③ 真正的文档缺陷仍报得出来 | **不成立** | GT 点名的 G4、G19 三轮都没报出来。三轮报出的文档类问题全部落在 G3/G11/G14(外加 G1/G17/G7 的 godoc 缺口),不能充数 |

**断言③ 的正确表述**(建议替换票面原文):

> 三轮都能报出「文档与实现不一致」类问题(G3/G11/G14),但**位置指代型**(G19)与**承诺无对应对象型**(G4)两类文档缺陷仍系统性漏报。

## 共同漏报 / 共同命中

- **共同命中(命中 = 1,三轮全中,11 条)**:G1、G2、G3、G5、G6、G7、G8、G11、G13、G17、G21。真正的差别在**归类**:A 全部 1 分;B 的 G6=0、G13=0.5、G1/G5/G17/G20=0.5;C 的 G6=0、G13=0.5。
- **共同漏报(命中 = 0,三轮全不中)**:G4、G19、G22(能力性漏报)+ G9、G25(结构性,按「同一根因只算一次」不重复计分)。**G23** 三轮都没作为条目报出,建议追加为实质共同漏报。
- **部分触碰**:G10(A 1/0.5、B 0.5、C 1/0.5)、G12(A 0.5、B 0、C 1/0.5)、G24(A 0.5、B 0、C 1/0.5)、G23(仅 C 0.5)。
- **单轮独有命中**:G14(G15/G16/G18/G20 同理)——A 漏 G18/G20,B 漏 G14/G15/G16/G18,**C 漏得最少**。

## 口径待裁定:6 处分歧与数字影响

判分细则已经写进 `evals/rubric.md`(「打分细则」八节),本轮基线按该细则算。下列 6 处是**判分规则本身的宽窄选择**,不是事实分歧——换个读法分数会变,列在这里是为了让基线可被挑战、可被复算。

| # | 分歧点 | 本基线采用 | 另一种读法 | 数字影响 |
|---|---|---|---|---|
| 1 | 在别的条目里顺带说对了,算不算命中 1 | **算 1**(细则 §一) | 算 0.5 | A 命中 −1.0;C 命中 −1.0~−2.0 |
| 2 | G4 三轮记 0 还是 0.5 | **A/B 各 0.5、C 0**(细则 §一:「只陈述了相邻事实」算 0.5) | 三轮全 0 | A 命中 −0.5;B 命中 −0.5 |
| 3 | G22 在 A 轮算不算 0.5 | **算 0.5**(「没有持久化层」是相邻事实) | 记 0 | A 命中 −0.5 |
| 4 | G13 归类:「谈没谈业务前提」的最低标准 | **B/C 记 1**(拍板项问了「24h 是不是全平台统一口径 / 按商户渠道区分」就算谈业务前提),A 记 0.5 | B/C 各 0.5 | B 归类 −0.5;C 归类 −0.5 |
| 5 | G8 被放进拍板时归类 | **0.5**(GT 判 P2 缺陷,报告判成拍板 → 偏一级) | 记 1 | B 归类 +0.5;C 归类 +0.5 |
| 6 | 表达质量「最小对照例子」的宽窄 | **保守档 0.6**(只有静态断言 + 场景描述记 0.6) | 宽松档记 1.0 | 三轮表达各 +0.4,raw 各 +0.4 |

**为什么这样定**:第 1 条按 `worksheet` 明文(「独立成条、或作为别的条目里的一段正确陈述都算 1」),它消掉了「同一条 finding 里顺带提到的到底给 0.5 还是 1」这个每轮都要吵的问题。第 2、3 条选宽档,是因为「陈述了相邻事实」确实比「完全没涉及」多走了一步。第 4 条取「只要把窗口口径摆成需要人来定的问题就算谈业务前提」——B/C 的拍板项原话正是这个形状。第 6 条取保守档,因为「`NewRefunder(window time.Duration)`」这类签名形状是**修法**不是**对照例子**,读者看不出「原来会怎样、现在会怎样」。

**独立复算**:本轮分数由一个独立子 Agent 按同一份细则复算过一次(不参考本文件)。复算方在第 2、3、4 条上取窄档,得 raw **A 162.3 / B 153.4 / C 151.1**——与本基线相差 ≤ 1.7 分。**结论方向完全一致**:C 轮命中最高但 raw 最低、误报全 0、断言③不成立、G4/G19/G22 共同漏报。窄档的完整数字留在这份复算报告里,不入版本控制。

## 一处措辞过时(不计分)

A、B 两轮仍写「编译器不报错(起个别名即可)」——这个理由在 `7c1c4ea` 已被实测纠正为 `shop redeclared in this block`(两个同名包一起 import 不起别名,编译器**会**报错)。**处置结论三处都正确**(都没进必须修/建议修),所以不计分;但说明模型在新措辞下仍会把理由压缩回旧说法。已开票(v1.2.0 措辞候选)。

## 方法论局限(v4 轮补充)

- **样本与标准答案同一人写**:基线偏乐观,真实水平要打折看。
- **每种问法只跑 1 轮**:没有方差估计。单轮差异小于 2 个百分点的结论不要当结论。
- **快模式轮的 GT 覆盖天然不全**:G8–G11、G14–G25 多数属设计面与测试面,快模式按契约本就不报。拿 A 轮的命中分去比全量轮不公平。
- **B 轮有一条假阴性**:性能维度写「无…无界缓存」,与 GT 的 G18 相反。不构成编造缺陷、不扣误报分,但它是覆盖声明失真。
- **原始输出与评分表分离**:原始输出留在仓外(`scratchpads\dcr-eval-archive\`),版本控制里只有评分表——第三方可复算分数,但看不到原始报告全文。
- **数值复算以 Go 1.24.0 windows/amd64 实跑为主**;`int64(NaN)` 属平台相关的未定义转换,不同架构结果可能不同。
- **没有做变异对照**:没改坏代码去验证每条 finding 是否真能让测试变红,「finding 是真的」靠读码 + 探针实测,不是测试红。
Loading