niceeval 0.5.4 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (337) hide show
  1. package/INDEX.md +55 -0
  2. package/dist/agents/types.d.ts +321 -0
  3. package/dist/context/types.d.ts +335 -0
  4. package/dist/i18n/core.d.ts +11 -0
  5. package/dist/i18n/en.d.ts +181 -0
  6. package/dist/i18n/index.d.ts +5 -0
  7. package/dist/i18n/zh-CN.d.ts +183 -0
  8. package/dist/o11y/otlp/parse.d.ts +3 -0
  9. package/dist/o11y/otlp/receiver.d.ts +21 -0
  10. package/dist/o11y/otlp/turn-otel.d.ts +43 -0
  11. package/dist/o11y/types.d.ts +190 -0
  12. package/dist/report/aggregate.d.ts +57 -0
  13. package/dist/report/aggregate.js +212 -0
  14. package/dist/report/built-ins/experiment-comparison.d.ts +1 -0
  15. package/dist/report/built-ins/experiment-comparison.js +13 -0
  16. package/dist/report/built-ins/index.d.ts +1 -0
  17. package/dist/report/built-ins/index.js +2 -0
  18. package/dist/report/components.d.ts +180 -0
  19. package/dist/report/components.js +132 -0
  20. package/dist/report/compute.d.ts +106 -0
  21. package/dist/report/compute.js +600 -0
  22. package/dist/report/flag.d.ts +6 -0
  23. package/dist/report/flag.js +8 -0
  24. package/dist/report/format.d.ts +26 -0
  25. package/dist/report/format.js +109 -0
  26. package/dist/report/index.d.ts +19 -0
  27. package/dist/report/index.js +30 -0
  28. package/dist/report/load.d.ts +12 -0
  29. package/dist/report/load.js +56 -0
  30. package/dist/report/locale.d.ts +94 -0
  31. package/dist/report/locale.js +183 -0
  32. package/dist/report/metrics.d.ts +21 -0
  33. package/dist/report/metrics.js +115 -0
  34. package/dist/report/primitives.d.ts +64 -0
  35. package/dist/report/primitives.js +113 -0
  36. package/dist/report/react/AttemptList.d.ts +23 -0
  37. package/dist/report/react/AttemptList.js +19 -0
  38. package/dist/report/react/DeltaTable.d.ts +8 -0
  39. package/dist/report/react/DeltaTable.js +24 -0
  40. package/dist/report/react/EvalList.d.ts +10 -0
  41. package/dist/report/react/EvalList.js +0 -0
  42. package/dist/report/react/ExperimentList.d.ts +11 -0
  43. package/dist/report/react/ExperimentList.js +67 -0
  44. package/dist/report/react/GroupSummary.d.ts +8 -0
  45. package/dist/report/react/GroupSummary.js +8 -0
  46. package/dist/report/react/MetricBars.d.ts +10 -0
  47. package/dist/report/react/MetricBars.js +48 -0
  48. package/dist/report/react/MetricLine.d.ts +9 -0
  49. package/dist/report/react/MetricLine.js +68 -0
  50. package/dist/report/react/MetricMatrix.d.ts +10 -0
  51. package/dist/report/react/MetricMatrix.js +23 -0
  52. package/dist/report/react/MetricScatter.d.ts +9 -0
  53. package/dist/report/react/MetricScatter.js +96 -0
  54. package/dist/report/react/MetricTable.d.ts +11 -0
  55. package/dist/report/react/MetricTable.js +26 -0
  56. package/dist/report/react/RunOverview.d.ts +8 -0
  57. package/dist/report/react/RunOverview.js +12 -0
  58. package/dist/report/react/Scoreboard.d.ts +8 -0
  59. package/dist/report/react/Scoreboard.js +26 -0
  60. package/dist/report/react/cell.d.ts +9 -0
  61. package/dist/report/react/cell.js +9 -0
  62. package/dist/report/react/chart-math.d.ts +14 -0
  63. package/dist/report/react/chart-math.js +68 -0
  64. package/dist/report/react/colors.d.ts +14 -0
  65. package/dist/report/react/colors.js +45 -0
  66. package/dist/report/react/fixtures.d.ts +19 -0
  67. package/dist/report/react/fixtures.js +398 -0
  68. package/dist/report/react/format.d.ts +3 -0
  69. package/dist/report/react/format.js +7 -0
  70. package/dist/report/react/index.d.ts +6 -0
  71. package/dist/report/react/index.js +14 -0
  72. package/dist/report/report.d.ts +24 -0
  73. package/dist/report/report.js +49 -0
  74. package/dist/report/text/faces.d.ts +29 -0
  75. package/dist/report/text/faces.js +541 -0
  76. package/dist/report/text/layout.d.ts +75 -0
  77. package/dist/report/text/layout.js +173 -0
  78. package/dist/report/text/plot.d.ts +37 -0
  79. package/dist/report/text/plot.js +81 -0
  80. package/dist/report/text/table.d.ts +8 -0
  81. package/dist/report/text/table.js +86 -0
  82. package/dist/report/tree.d.ts +99 -0
  83. package/dist/report/tree.js +228 -0
  84. package/dist/report/types.d.ts +408 -0
  85. package/dist/report/types.js +4 -0
  86. package/dist/report/web.d.ts +15 -0
  87. package/dist/report/web.js +37 -0
  88. package/dist/results/locator.d.ts +75 -0
  89. package/dist/results/locator.js +0 -0
  90. package/dist/results/select.d.ts +45 -0
  91. package/dist/results/select.js +230 -0
  92. package/dist/results/source-hash.d.ts +9 -0
  93. package/dist/results/types.d.ts +204 -0
  94. package/dist/runner/eval-source.d.ts +22 -0
  95. package/dist/runner/fingerprint.d.ts +23 -0
  96. package/dist/runner/types.d.ts +332 -0
  97. package/dist/sandbox/docker-stream.d.ts +24 -0
  98. package/dist/sandbox/docker.d.ts +84 -0
  99. package/dist/sandbox/e2b.d.ts +31 -0
  100. package/dist/sandbox/errors.d.ts +4 -0
  101. package/dist/sandbox/local-files.d.ts +6 -0
  102. package/dist/sandbox/paths.d.ts +4 -0
  103. package/dist/sandbox/registry.d.ts +13 -0
  104. package/dist/sandbox/resolve.d.ts +40 -0
  105. package/dist/sandbox/retry.d.ts +10 -0
  106. package/dist/sandbox/shell.d.ts +11 -0
  107. package/dist/sandbox/source-files.d.ts +13 -0
  108. package/dist/sandbox/types.d.ts +203 -0
  109. package/dist/sandbox/vercel.d.ts +37 -0
  110. package/dist/scoring/types.d.ts +70 -0
  111. package/dist/shared/aggregate.d.ts +29 -0
  112. package/dist/shared/aggregate.js +55 -0
  113. package/dist/shared/types.d.ts +27 -0
  114. package/dist/shared/verdict.d.ts +27 -0
  115. package/dist/shared/verdict.js +34 -0
  116. package/dist/tty-line.d.ts +6 -0
  117. package/dist/types.d.ts +7 -0
  118. package/dist/util.d.ts +22 -0
  119. package/docs-site/zh/concepts/adapter.mdx +7 -7
  120. package/docs-site/zh/concepts/assert.mdx +19 -18
  121. package/docs-site/zh/concepts/evals.mdx +12 -11
  122. package/docs-site/zh/concepts/experiment.mdx +2 -2
  123. package/docs-site/zh/concepts/judge.mdx +9 -9
  124. package/docs-site/zh/concepts/overview.mdx +3 -3
  125. package/docs-site/zh/concepts/tier.mdx +6 -6
  126. package/docs-site/zh/example/claude-code-codex-plugin.mdx +9 -5
  127. package/docs-site/zh/example/claude-code-codex-skill.mdx +12 -7
  128. package/docs-site/zh/guides/agent-feedback-loop.mdx +237 -78
  129. package/docs-site/zh/guides/connect-otel.mdx +3 -3
  130. package/docs-site/zh/guides/connect-your-agent.mdx +2 -2
  131. package/docs-site/zh/guides/custom-reports.mdx +196 -36
  132. package/docs-site/zh/guides/experiments.mdx +7 -1
  133. package/docs-site/zh/guides/fixtures.mdx +4 -2
  134. package/docs-site/zh/guides/official-adapters.mdx +31 -9
  135. package/docs-site/zh/guides/publish-report.mdx +4 -4
  136. package/docs-site/zh/guides/report-components.mdx +194 -55
  137. package/docs-site/zh/guides/reporters.mdx +2 -2
  138. package/docs-site/zh/guides/results-data.mdx +61 -34
  139. package/docs-site/zh/guides/runner.mdx +2 -2
  140. package/docs-site/zh/guides/sandbox-agent.mdx +3 -2
  141. package/docs-site/zh/guides/{sandbox-backends.mdx → sandbox-providers.mdx} +12 -12
  142. package/docs-site/zh/guides/viewing-results.mdx +200 -79
  143. package/docs-site/zh/guides/write-experiment.mdx +9 -1
  144. package/docs-site/zh/guides/write-send.mdx +4 -3
  145. package/docs-site/zh/index.mdx +4 -3
  146. package/docs-site/zh/introduction.mdx +2 -1
  147. package/docs-site/zh/quickstart.mdx +5 -3
  148. package/docs-site/zh/reference/builtin-agents.mdx +38 -13
  149. package/docs-site/zh/reference/capabilities.mdx +1 -1
  150. package/docs-site/zh/reference/cli.mdx +36 -13
  151. package/docs-site/zh/reference/define-agent.mdx +15 -13
  152. package/docs-site/zh/reference/define-config.mdx +1 -1
  153. package/docs-site/zh/reference/define-eval.mdx +3 -3
  154. package/docs-site/zh/reference/events.mdx +9 -3
  155. package/docs-site/zh/reference/expect.mdx +13 -8
  156. package/package.json +10 -6
  157. package/src/agents/bub.ts +129 -42
  158. package/src/agents/claude-code.test.ts +152 -0
  159. package/src/agents/claude-code.ts +127 -13
  160. package/src/agents/codex.test.ts +192 -0
  161. package/src/agents/codex.ts +151 -12
  162. package/src/agents/index.ts +9 -3
  163. package/src/agents/manifest.ts +41 -0
  164. package/src/agents/plugin-config.test.ts +94 -0
  165. package/src/agents/shared.ts +33 -2
  166. package/src/agents/skills.test.ts +214 -0
  167. package/src/agents/skills.ts +304 -0
  168. package/src/agents/streaming.ts +5 -5
  169. package/src/agents/types.ts +59 -3
  170. package/src/cli.ts +74 -47
  171. package/src/context/context.test.ts +20 -2
  172. package/src/context/control-flow.ts +1 -1
  173. package/src/context/session.test.ts +92 -1
  174. package/src/context/session.ts +23 -1
  175. package/src/context/types.ts +4 -4
  176. package/src/define.test.ts +8 -8
  177. package/src/define.ts +11 -11
  178. package/src/expect/index.ts +5 -5
  179. package/src/i18n/en.ts +33 -15
  180. package/src/i18n/zh-CN.ts +37 -21
  181. package/src/index.ts +1 -1
  182. package/src/o11y/execution-tree.test.ts +452 -0
  183. package/src/o11y/execution-tree.ts +367 -0
  184. package/src/o11y/otlp/receiver.ts +1 -1
  185. package/src/o11y/otlp/select.ts +7 -3
  186. package/src/o11y/parsers/claude-code.test.ts +175 -0
  187. package/src/o11y/parsers/claude-code.ts +32 -0
  188. package/src/o11y/types.ts +6 -1
  189. package/src/report/aggregate.ts +26 -20
  190. package/src/report/built-in-user-parity.test.tsx +640 -0
  191. package/src/report/built-ins/experiment-comparison.tsx +19 -0
  192. package/src/report/built-ins/index.ts +2 -0
  193. package/src/report/components.tsx +225 -50
  194. package/src/report/compute.ts +335 -54
  195. package/src/report/dual-render.test.tsx +1129 -0
  196. package/src/report/flag.ts +1 -1
  197. package/src/report/format.ts +35 -2
  198. package/src/report/index.ts +47 -14
  199. package/src/report/load.ts +1 -1
  200. package/src/report/locale.ts +229 -0
  201. package/src/report/metrics.ts +39 -15
  202. package/src/report/primitives.tsx +100 -2
  203. package/src/report/react/AttemptList.tsx +113 -0
  204. package/src/report/react/DeltaTable.tsx +9 -6
  205. package/src/report/react/EvalList.tsx +0 -0
  206. package/src/report/react/ExperimentList.tsx +220 -0
  207. package/src/report/react/GroupSummary.tsx +66 -0
  208. package/src/report/react/MetricBars.tsx +24 -13
  209. package/src/report/react/MetricLine.tsx +21 -21
  210. package/src/report/react/MetricMatrix.tsx +8 -4
  211. package/src/report/react/MetricScatter.tsx +126 -96
  212. package/src/report/react/MetricTable.tsx +115 -15
  213. package/src/report/react/RunOverview.tsx +48 -26
  214. package/src/report/react/Scoreboard.tsx +15 -7
  215. package/src/report/react/cell.tsx +18 -9
  216. package/src/{view/app/lib/chart.ts → report/react/chart-math.ts} +2 -6
  217. package/src/report/react/colors.ts +24 -15
  218. package/src/report/react/enhance.js +168 -0
  219. package/src/report/react/fixtures.ts +169 -34
  220. package/src/report/react/format.ts +1 -1
  221. package/src/report/react/index.tsx +21 -6
  222. package/src/report/react/render.test.tsx +180 -31
  223. package/src/report/react/styles.css +432 -213
  224. package/src/report/report.test.ts +398 -94
  225. package/src/report/report.ts +29 -11
  226. package/src/report/text/faces.ts +344 -96
  227. package/src/report/text/layout.ts +76 -11
  228. package/src/report/text/table.ts +98 -0
  229. package/src/report/tree.ts +103 -20
  230. package/src/report/types.ts +184 -25
  231. package/src/report/web.ts +46 -19
  232. package/src/results/annotated-source.test.ts +146 -0
  233. package/src/results/annotated-source.ts +128 -0
  234. package/src/results/attempt-evidence.test.ts +158 -0
  235. package/src/results/attempt-evidence.ts +158 -0
  236. package/src/results/attempt-source.ts +48 -0
  237. package/src/results/copy.ts +154 -139
  238. package/src/results/format.ts +54 -47
  239. package/src/results/host-equivalence.test.ts +527 -0
  240. package/src/results/index.ts +56 -14
  241. package/src/results/locator.test.ts +198 -0
  242. package/src/results/locator.ts +0 -0
  243. package/src/results/open.ts +392 -175
  244. package/src/results/results.test.ts +943 -494
  245. package/src/results/select.ts +129 -23
  246. package/src/results/skipped-notice.ts +0 -0
  247. package/src/results/source-hash.ts +28 -0
  248. package/src/results/types.ts +98 -62
  249. package/src/results/writer.ts +304 -176
  250. package/src/runner/attempt.test.ts +170 -0
  251. package/src/runner/attempt.ts +48 -13
  252. package/src/runner/discover.test.ts +65 -0
  253. package/src/runner/discover.ts +6 -2
  254. package/src/runner/eval-source.test.ts +121 -0
  255. package/src/runner/eval-source.ts +45 -0
  256. package/src/runner/fingerprint.ts +54 -1
  257. package/src/runner/remote-sandbox.ts +1 -1
  258. package/src/runner/report.test.ts +6 -8
  259. package/src/runner/report.ts +5 -4
  260. package/src/runner/reporters/artifacts.ts +27 -41
  261. package/src/runner/reporters/braintrust.test.ts +3 -3
  262. package/src/runner/reporters/braintrust.ts +1 -1
  263. package/src/runner/reporters/console.ts +6 -6
  264. package/src/runner/reporters/json.ts +4 -4
  265. package/src/runner/reporters/live.test.ts +56 -0
  266. package/src/runner/reporters/live.ts +36 -10
  267. package/src/runner/reporters/quiet.test.ts +66 -0
  268. package/src/runner/reporters/quiet.ts +49 -0
  269. package/src/runner/reporters/shared.ts +5 -5
  270. package/src/runner/reporters/table.ts +17 -17
  271. package/src/runner/run.ts +61 -102
  272. package/src/runner/types.ts +43 -32
  273. package/src/sandbox/checkpoint.ts +1 -1
  274. package/src/sandbox/docker.ts +15 -2
  275. package/src/sandbox/e2b.ts +11 -5
  276. package/src/sandbox/errors.ts +13 -0
  277. package/src/sandbox/index.ts +3 -3
  278. package/src/sandbox/local-files.ts +1 -1
  279. package/src/sandbox/registry.ts +6 -5
  280. package/src/sandbox/resolve.ts +38 -23
  281. package/src/sandbox/retry.test.ts +68 -0
  282. package/src/sandbox/retry.ts +44 -0
  283. package/src/sandbox/types.ts +24 -24
  284. package/src/sandbox/vercel.ts +17 -3
  285. package/src/scoring/collector.ts +3 -3
  286. package/src/scoring/judge.ts +2 -2
  287. package/src/scoring/scoped.ts +13 -1
  288. package/src/scoring/types.ts +7 -7
  289. package/src/scoring/verdict.ts +4 -4
  290. package/src/shared/aggregate.ts +23 -3
  291. package/src/shared/types.ts +2 -2
  292. package/src/shared/{outcome.ts → verdict.ts} +15 -15
  293. package/src/show/compose.ts +12 -132
  294. package/src/show/index.ts +119 -95
  295. package/src/show/render.ts +462 -159
  296. package/src/show/show.test.ts +471 -253
  297. package/src/source-loc.ts +1 -1
  298. package/src/tty-line.ts +32 -0
  299. package/src/types.ts +2 -2
  300. package/src/util.test.ts +21 -1
  301. package/src/util.ts +5 -1
  302. package/src/view/app/App.tsx +33 -198
  303. package/src/view/app/components/AttemptModal.tsx +6 -6
  304. package/src/view/app/components/CodeView.tsx +2 -2
  305. package/src/view/app/components/CopyControls.tsx +32 -36
  306. package/src/view/app/components/SkippedRunsBanner.tsx +140 -0
  307. package/src/view/app/components/ui/badge.tsx +1 -1
  308. package/src/view/app/components/ui/dialog.tsx +2 -2
  309. package/src/view/app/i18n.ts +40 -31
  310. package/src/view/app/lib/artifact-url.ts +1 -1
  311. package/src/view/app/lib/attempt-route.test.ts +37 -47
  312. package/src/view/app/lib/attempt-route.ts +26 -26
  313. package/src/view/app/lib/rows.ts +9 -112
  314. package/src/view/app/lib/verdict.ts +25 -0
  315. package/src/view/app/main.tsx +9 -12
  316. package/src/view/app/pages/RunsPage.tsx +4 -4
  317. package/src/view/app/pages/TracesPage.tsx +3 -3
  318. package/src/view/app/shared.ts +0 -1
  319. package/src/view/app/types.ts +6 -51
  320. package/src/view/artifact-serving.test.ts +136 -0
  321. package/src/view/client-dist/app.css +1 -1
  322. package/src/view/client-dist/app.js +21 -21
  323. package/src/view/data.test.ts +214 -143
  324. package/src/view/data.ts +166 -120
  325. package/src/view/index.ts +23 -11
  326. package/src/view/server.ts +52 -17
  327. package/src/view/shared/types.ts +22 -31
  328. package/src/view/styles.css +117 -327
  329. package/src/view/view-report.test.ts +146 -98
  330. package/src/report/default-report.tsx +0 -222
  331. package/src/report/dual-face.test.tsx +0 -527
  332. package/src/report/react/CaseList.tsx +0 -70
  333. package/src/view/app/components/CostScoreChart.tsx +0 -147
  334. package/src/view/app/components/ExperimentTable.tsx +0 -284
  335. package/src/view/app/components/GroupSelector.tsx +0 -61
  336. package/src/view/app/components/primitives.tsx +0 -43
  337. package/src/view/app/lib/outcome.ts +0 -82
@@ -0,0 +1,168 @@
1
+ // niceeval 报告的渐进增强 runtime:纯 vanilla JS、零依赖、IIFE、幂等。
2
+ // 只作用于 .nre DOM 与 data-nre-* 属性;三个行为——表格排序、行过滤、SVG 点 tooltip。
3
+ // 静态 HTML 无 JS 时内容完整可读是硬约束:排序有数据侧预排、tooltip 退化为原生
4
+ // <title>、过滤输入框静默无功能。全部经 document 级事件委托绑定,重复注入本文件
5
+ // 只在首次生效(window.__nreEnhanced 守卫),DOM 被搬动(如 view 把 <template> 内容
6
+ // 摆进报告槽)也无需重新绑定。
7
+
8
+ (function () {
9
+ "use strict";
10
+ if (typeof window === "undefined" || window.__nreEnhanced) return;
11
+ window.__nreEnhanced = true;
12
+
13
+ function closest(target, selector) {
14
+ return target && target.closest ? target.closest(selector) : null;
15
+ }
16
+
17
+ // ───────────────────────── 排序:th[data-nre-sort] ─────────────────────────
18
+ // 点击按该列排序 tbody 行(td/th 的 data-sort-value,数值优先、退回字符串;
19
+ // 空值恒沉底),再点反向;方向指示由 th 上的 nre-sort-asc / nre-sort-desc 类驱动。
20
+
21
+ function sortValue(row, index) {
22
+ var cell = row.cells[index];
23
+ if (!cell) return "";
24
+ var v = cell.getAttribute("data-sort-value");
25
+ return v !== null ? v : cell.textContent.trim();
26
+ }
27
+
28
+ document.addEventListener("click", function (e) {
29
+ var th = closest(e.target, ".nre table th[data-nre-sort]");
30
+ if (!th) return;
31
+ var table = th.closest("table");
32
+ var tbody = table && table.tBodies[0];
33
+ if (!tbody) return;
34
+ var index = Array.prototype.indexOf.call(th.parentNode.children, th);
35
+ var dir = th.classList.contains("nre-sort-asc") ? "desc" : "asc";
36
+ var siblings = th.parentNode.querySelectorAll("th[data-nre-sort]");
37
+ for (var i = 0; i < siblings.length; i++) siblings[i].classList.remove("nre-sort-asc", "nre-sort-desc");
38
+ th.classList.add(dir === "asc" ? "nre-sort-asc" : "nre-sort-desc");
39
+
40
+ var rows = Array.prototype.slice.call(tbody.rows);
41
+ rows.sort(function (a, b) {
42
+ var va = sortValue(a, index);
43
+ var vb = sortValue(b, index);
44
+ // 空值 = 缺数据:恒沉底,与「缺数据不编 0」同一姿势
45
+ if (va === "" && vb === "") return 0;
46
+ if (va === "") return 1;
47
+ if (vb === "") return -1;
48
+ var na = Number(va);
49
+ var nb = Number(vb);
50
+ var out;
51
+ if (!isNaN(na) && !isNaN(nb)) out = na - nb;
52
+ else out = String(va).localeCompare(String(vb));
53
+ return dir === "asc" ? out : -out;
54
+ });
55
+ for (var u = 0; u < rows.length; u++) tbody.appendChild(rows[u]);
56
+ });
57
+
58
+ // ───────────────────────── 过滤:input[data-nre-filter] ─────────────────────────
59
+ // 对同容器内的表格行做 textContent 匹配,不匹配者加隐藏类(样式在 styles.css)。
60
+
61
+ document.addEventListener("input", function (e) {
62
+ var input = closest(e.target, "input[data-nre-filter]");
63
+ if (!input) return;
64
+ var scope = input.parentElement;
65
+ var table = scope ? scope.querySelector("table") : null;
66
+ if (!table || !table.tBodies[0]) return;
67
+ var query = input.value.trim().toLowerCase();
68
+ var rows = table.tBodies[0].rows;
69
+ for (var i = 0; i < rows.length; i++) {
70
+ var row = rows[i];
71
+ var hide = query !== "" && row.textContent.toLowerCase().indexOf(query) === -1;
72
+ row.classList.toggle("nre-row-hidden", hide);
73
+ }
74
+ });
75
+
76
+ // ExperimentList 的 web 面以原生 details 表达「八列主行 + 展开明细」,不是 table/tbody。
77
+ // 单独按 summary 的列排序、按整条 details 文本过滤;无 JS 时保持数据侧成功率降序。
78
+ document.addEventListener("click", function (e) {
79
+ var control = closest(e.target, "[data-nre-experiment-sort]");
80
+ if (!control) return;
81
+ var board = control.closest(".nre-experiment-table");
82
+ if (!board) return;
83
+ var index = Number(control.getAttribute("data-nre-experiment-sort"));
84
+ var dir = control.classList.contains("nre-sort-asc") ? "desc" : "asc";
85
+ var controls = board.querySelectorAll("[data-nre-experiment-sort]");
86
+ for (var i = 0; i < controls.length; i++) controls[i].classList.remove("nre-sort-asc", "nre-sort-desc");
87
+ control.classList.add(dir === "asc" ? "nre-sort-asc" : "nre-sort-desc");
88
+ var entries = Array.prototype.slice.call(board.querySelectorAll(":scope > .nre-experiment-entry"));
89
+ entries.sort(function (a, b) {
90
+ var ac = a.querySelector(".nre-experiment-summary").children[index];
91
+ var bc = b.querySelector(".nre-experiment-summary").children[index];
92
+ var av = ac ? ac.getAttribute("data-sort-value") || ac.textContent.trim() : "";
93
+ var bv = bc ? bc.getAttribute("data-sort-value") || bc.textContent.trim() : "";
94
+ if (av === "" && bv === "") return 0;
95
+ if (av === "") return 1;
96
+ if (bv === "") return -1;
97
+ var an = Number(av), bn = Number(bv);
98
+ var out = !isNaN(an) && !isNaN(bn) ? an - bn : String(av).localeCompare(String(bv));
99
+ return dir === "asc" ? out : -out;
100
+ });
101
+ for (var j = 0; j < entries.length; j++) board.appendChild(entries[j]);
102
+ });
103
+
104
+ document.addEventListener("input", function (e) {
105
+ var input = closest(e.target, "input[data-nre-experiment-filter]");
106
+ if (!input) return;
107
+ var scope = input.parentElement;
108
+ var entries = scope ? scope.querySelectorAll(".nre-experiment-entry") : [];
109
+ var query = input.value.trim().toLowerCase();
110
+ for (var i = 0; i < entries.length; i++) {
111
+ entries[i].classList.toggle("nre-row-hidden", query !== "" && entries[i].textContent.toLowerCase().indexOf(query) === -1);
112
+ }
113
+ });
114
+
115
+ // ───────────────────────── tooltip:.nre-scatter-point / .nre-line-point ─────────────────────────
116
+ // 首次 hover 时把点内 <title> 的内容搬进 data-nre-title(避免与原生 tooltip 重影),
117
+ // 渲染样式化 tooltip div(定位在点上方,挂在所属 figure 里)。无 JS 时 <title> 原样生效。
118
+
119
+ var tooltip = null;
120
+
121
+ function hideTooltip() {
122
+ if (tooltip && tooltip.parentNode) tooltip.parentNode.removeChild(tooltip);
123
+ tooltip = null;
124
+ }
125
+
126
+ function tooltipText(point) {
127
+ var text = point.getAttribute("data-nre-title");
128
+ if (text === null) {
129
+ var title = point.querySelector("title");
130
+ text = title ? title.textContent : "";
131
+ if (title && title.parentNode) title.parentNode.removeChild(title);
132
+ point.setAttribute("data-nre-title", text);
133
+ }
134
+ return text;
135
+ }
136
+
137
+ document.addEventListener("mouseover", function (e) {
138
+ var point = closest(e.target, ".nre-scatter-point, .nre-line-point");
139
+ if (!point) return;
140
+ var text = tooltipText(point);
141
+ if (!text) return;
142
+ var figure = point.closest("figure") || document.body;
143
+ hideTooltip();
144
+ tooltip = document.createElement("div");
145
+ tooltip.className = "nre-tooltip";
146
+ var lines = text.split("\n");
147
+ for (var i = 0; i < lines.length; i++) {
148
+ var line = document.createElement(i === 0 ? "b" : "div");
149
+ if (i > 0) line.className = "nre-tooltip-meta";
150
+ line.textContent = lines[i];
151
+ tooltip.appendChild(line);
152
+ }
153
+ if (getComputedStyle(figure).position === "static") figure.style.position = "relative";
154
+ figure.appendChild(tooltip);
155
+ var pointBox = point.getBoundingClientRect();
156
+ var figureBox = figure.getBoundingClientRect();
157
+ tooltip.style.left = pointBox.left + pointBox.width / 2 - figureBox.left + "px";
158
+ tooltip.style.top = pointBox.top - figureBox.top + "px";
159
+ });
160
+
161
+ document.addEventListener("mouseout", function (e) {
162
+ var point = closest(e.target, ".nre-scatter-point, .nre-line-point");
163
+ if (!point) return;
164
+ // 移入 tooltip 自身不算离开(pointer-events: none 下 relatedTarget 不会是它,防御性判断)
165
+ if (e.relatedTarget && point.contains(e.relatedTarget)) return;
166
+ hideTooltip();
167
+ });
168
+ })();
@@ -4,8 +4,11 @@
4
4
  // 稀疏矩阵、缺数据的散点、delta 的 null 不硬算、truncated 计数。
5
5
 
6
6
  import type {
7
- CaseListData,
7
+ AttemptListItem,
8
8
  DeltaData,
9
+ EvalListItem,
10
+ ExperimentListItem,
11
+ GroupSummaryData,
9
12
  LineData,
10
13
  MatrixData,
11
14
  MetricColumn,
@@ -14,6 +17,9 @@ import type {
14
17
  ScoreboardData,
15
18
  TableData,
16
19
  } from "../types.ts";
20
+ import type { AttemptLocator } from "../../results/locator.ts";
21
+
22
+ const locator = (s: string): AttemptLocator => s as AttemptLocator;
17
23
 
18
24
  export const passRateColumn: MetricColumn = { key: "pass-rate", label: "pass rate", unit: "%", better: "higher" };
19
25
  export const codeLinesColumn: MetricColumn = { key: "code-lines", label: "code lines", unit: "lines", better: "lower" };
@@ -31,6 +37,9 @@ export const overviewData: OverviewData = {
31
37
  failed: 8,
32
38
  errored: 2,
33
39
  skipped: 2,
40
+ // 两级聚合口径(computeCell)刻意不等于 36/(36+8+2)≈78% 的 attempt 原始占比:
41
+ // 组件必须原样渲染这个字段,不得从上面四个 verdict 计票现场重算。
42
+ passRate: { value: 0.7, display: "70%", samples: 46, total: 48, refs: [] },
34
43
  costUSD: null, // 全部 attempt 都没报成本:null,组件必须显示缺数据而不是 $0
35
44
  durationMs: 261_000,
36
45
  },
@@ -51,6 +60,19 @@ export const overviewWithCost: OverviewData = {
51
60
  warnings: [],
52
61
  };
53
62
 
63
+ /** GroupSummary.data 的产物形态:eval 级折叠计票 + 旧 GroupSelector 口径的通过率(包成 MetricCell)。 */
64
+ export const groupSummaryData: GroupSummaryData = {
65
+ experiments: 2,
66
+ // evals = 全部 verdicts 之和(3+1+1+1=6);passRate 分母只数非 skipped 的 5 道
67
+ evals: 6,
68
+ attempts: 9,
69
+ verdicts: { passed: 3, failed: 1, errored: 1, skipped: 1 },
70
+ // 3 passed / (3 + 1 + 1) = 60%;samples=ran=5 < total=evals=6:1 道 skipped 未计入分母的覆盖率角标
71
+ passRate: { value: 0.6, display: "60%", samples: 5, total: 6, refs: [] },
72
+ totalCostUSD: 1.5,
73
+ lastRunAt: "2026-07-01T11:30:00Z",
74
+ };
75
+
54
76
  export const tableData: TableData<"pass-rate" | "code-lines"> = {
55
77
  dimension: "agent",
56
78
  // 行顺序故意不按 passRate 排:组件必须按传入顺序渲染,不重排
@@ -72,7 +94,7 @@ export const tableData: TableData<"pass-rate" | "code-lines"> = {
72
94
  display: "87%",
73
95
  samples: 6,
74
96
  total: 6,
75
- refs: [{ run: "run-a", result: 0 }],
97
+ refs: [locator("@1a0a0a0")],
76
98
  },
77
99
  // samples < total:有 attempt 测不了 → 覆盖率角标 5/6
78
100
  "code-lines": { value: 120, display: "120 lines", samples: 5, total: 6, refs: [] },
@@ -81,6 +103,31 @@ export const tableData: TableData<"pass-rate" | "code-lines"> = {
81
103
  ],
82
104
  };
83
105
 
106
+ /** rows: "experiment" 的榜单形态:行携带 agent/model 元信息与 eval 级折叠计票。 */
107
+ export const tableDataWithMeta: TableData<"pass-rate"> = {
108
+ dimension: "experiment",
109
+ columns: [passRateColumn],
110
+ rows: [
111
+ {
112
+ key: "compare/bub",
113
+ cells: { "pass-rate": { value: 0.5, display: "50%", samples: 2, total: 2, refs: [] } },
114
+ meta: {
115
+ agent: "bub",
116
+ model: "gpt-5.4",
117
+ verdicts: { passed: 1, failed: 1, errored: 0, skipped: 0 },
118
+ },
119
+ },
120
+ {
121
+ key: "compare/codex",
122
+ cells: { "pass-rate": { value: 1, display: "100%", samples: 2, total: 2, refs: [] } },
123
+ meta: {
124
+ agent: "codex",
125
+ verdicts: { passed: 2, failed: 0, errored: 0, skipped: 0 },
126
+ },
127
+ },
128
+ ],
129
+ };
130
+
84
131
  export const matrixData: MatrixData = {
85
132
  rows: "eval",
86
133
  columns: "agent",
@@ -95,10 +142,7 @@ export const matrixData: MatrixData = {
95
142
  display: "100%",
96
143
  samples: 2,
97
144
  total: 2,
98
- refs: [
99
- { run: "run-b", result: 3 },
100
- { run: "run-b", result: 7 },
101
- ],
145
+ refs: [locator("@1b3b3b3"), locator("@1b7b7b7")],
102
146
  },
103
147
  },
104
148
  {
@@ -264,35 +308,126 @@ export const deltaData: DeltaData<"pass-rate" | "cost"> = {
264
308
  ],
265
309
  };
266
310
 
267
- export const caseListData: CaseListData = {
268
- rows: [
269
- {
270
- eval: "algebra/quadratic",
271
- experimentId: "compare/bub",
272
- agent: "bub",
273
- outcome: "failed",
274
- failedAssertions: [
275
- {
276
- name: "roots-correct",
277
- score: 0,
278
- detail: "expected x=2, got x=3",
279
- evidence: "judge: sign flipped when substituting into the quadratic formula",
280
- },
281
- ],
282
- durationMs: 32_000,
283
- costUSD: 0.12,
284
- ref: { run: "run-a", result: 4 },
285
- },
311
+ // ───────────────────────── 实体列表(ExperimentList / EvalList / AttemptList)─────────────────────────
312
+
313
+ /** algebra/quadratic 在 compare/bub 上失败的那次 attempt——两条子失败夹具共用同一条。 */
314
+ const failedAttempt: AttemptListItem = {
315
+ evalId: "algebra/quadratic",
316
+ experimentId: "compare/bub",
317
+ attempt: 3,
318
+ agent: "bub",
319
+ verdict: "failed",
320
+ assertions: [
286
321
  {
287
- eval: "geometry/angles",
288
- experimentId: "compare/codex",
289
- agent: "codex",
290
- outcome: "errored",
291
- error: "TypeError: cannot read properties of undefined (reading 'foo')",
292
- failedAssertions: [],
293
- durationMs: 4_500,
294
- ref: { run: "run-c", result: 1 },
322
+ name: "roots-correct",
323
+ severity: "gate",
324
+ score: 0,
325
+ passed: false,
326
+ detail: "expected x=2, got x=3",
327
+ evidence: "judge: sign flipped when substituting into the quadratic formula",
295
328
  },
296
329
  ],
297
- truncated: 2,
330
+ durationMs: 32_000,
331
+ costUSD: 0.12,
332
+ locator: locator("@1a4a4a4"),
333
+ };
334
+
335
+ const erroredAttempt: AttemptListItem = {
336
+ evalId: "geometry/angles",
337
+ experimentId: "compare/codex",
338
+ attempt: 0,
339
+ agent: "codex",
340
+ verdict: "errored",
341
+ error: "TypeError: cannot read properties of undefined (reading 'foo')",
342
+ assertions: [],
343
+ durationMs: 4_500,
344
+ locator: locator("@1c1c1c1"),
298
345
  };
346
+
347
+ const failedRetryAttempt: AttemptListItem = {
348
+ ...failedAttempt,
349
+ attempt: 4,
350
+ durationMs: 35_000,
351
+ locator: locator("@1b5b5b5"),
352
+ };
353
+
354
+ export const attemptListItems: AttemptListItem[] = [failedAttempt, erroredAttempt];
355
+
356
+ export const evalListItems: EvalListItem[] = [
357
+ {
358
+ evalId: "algebra/quadratic",
359
+ experimentId: "compare/bub",
360
+ verdict: "failed",
361
+ reason: "roots-correct: expected x=2, got x=3",
362
+ score: { value: 0, display: "0%", samples: 1, total: 1, refs: [failedAttempt.locator] },
363
+ duration: { value: 32_000, display: "32.0s", samples: 1, total: 1, refs: [failedAttempt.locator] },
364
+ cost: { value: 0.12, display: "$0.12", samples: 1, total: 1, refs: [failedAttempt.locator] },
365
+ attempts: [failedAttempt],
366
+ },
367
+ {
368
+ evalId: "geometry/angles",
369
+ experimentId: "compare/codex",
370
+ verdict: "errored",
371
+ reason: erroredAttempt.error,
372
+ score: { value: 0, display: "0%", samples: 1, total: 1, refs: [erroredAttempt.locator] },
373
+ duration: { value: 4_500, display: "4.5s", samples: 1, total: 1, refs: [erroredAttempt.locator] },
374
+ cost: { value: null, display: "—", samples: 0, total: 1, refs: [] },
375
+ attempts: [erroredAttempt],
376
+ },
377
+ ];
378
+
379
+ export const experimentListItems: ExperimentListItem[] = [
380
+ {
381
+ experimentId: "compare/bub",
382
+ agent: "bub",
383
+ model: "gpt-5.4",
384
+ flags: { memory: true },
385
+ verdicts: { passed: 1, failed: 1, errored: 0, skipped: 0 },
386
+ passRate: { value: 0.5, display: "50%", samples: 2, total: 2, refs: [] },
387
+ cost: { value: 0.12, display: "$0.12", samples: 1, total: 2, refs: [failedAttempt.locator] },
388
+ duration: { value: 32_000, display: "32.0s", samples: 2, total: 2, refs: [] },
389
+ tokens: { value: null, display: "—", samples: 0, total: 2, refs: [] },
390
+ evals: 2,
391
+ attempts: 3,
392
+ lastRunAt: "2026-07-01T10:00:00Z",
393
+ evalRows: [
394
+ {
395
+ evalId: "algebra/quadratic",
396
+ verdict: "failed",
397
+ reason: "roots-correct: expected x=2, got x=3",
398
+ duration: { value: 32_000, display: "32.0s", samples: 1, total: 1, refs: [failedAttempt.locator] },
399
+ cost: { value: 0.12, display: "$0.12", samples: 1, total: 1, refs: [failedAttempt.locator] },
400
+ attempts: [failedAttempt, failedRetryAttempt],
401
+ },
402
+ {
403
+ evalId: "algebra/simple",
404
+ verdict: "passed",
405
+ duration: { value: 5_000, display: "5.0s", samples: 1, total: 1, refs: [] },
406
+ cost: { value: 0.02, display: "$0.02", samples: 1, total: 1, refs: [] },
407
+ attempts: [],
408
+ },
409
+ ],
410
+ },
411
+ {
412
+ experimentId: "compare/codex",
413
+ agent: "codex",
414
+ verdicts: { passed: 0, failed: 0, errored: 1, skipped: 0 },
415
+ passRate: { value: 0, display: "0%", samples: 1, total: 1, refs: [] },
416
+ cost: { value: null, display: "—", samples: 0, total: 1, refs: [] },
417
+ duration: { value: 4_500, display: "4.5s", samples: 1, total: 1, refs: [] },
418
+ tokens: { value: null, display: "—", samples: 0, total: 1, refs: [] },
419
+ evals: 1,
420
+ attempts: 1,
421
+ lastRunAt: "2026-07-01T11:30:00Z",
422
+ evalRows: [
423
+ {
424
+ evalId: "geometry/angles",
425
+ verdict: "errored",
426
+ reason: erroredAttempt.error,
427
+ duration: { value: 4_500, display: "4.5s", samples: 1, total: 1, refs: [erroredAttempt.locator] },
428
+ cost: { value: null, display: "—", samples: 0, total: 1, refs: [] },
429
+ attempts: [erroredAttempt],
430
+ },
431
+ ],
432
+ },
433
+ ];
@@ -1,7 +1,7 @@
1
1
  // web 面的小工具:展示格式化统一住在计算侧的 ../format.ts(两个渲染面同一份),
2
2
  // 这里 re-export 并补 class 名拼接。MetricCell 一律自带 display,组件不重算。
3
3
 
4
- export { MISSING_TEXT, formatDurationMs, formatPercent, formatUSD } from "../format.ts";
4
+ export { MISSING_TEXT, formatDurationMs, formatPercent, formatUSD, verdictMark } from "../format.ts";
5
5
 
6
6
  /** 拼 class 名:过滤空值,末尾接使用者透传的 className。 */
7
7
  export function cx(...parts: (string | undefined | false)[]): string {
@@ -9,8 +9,11 @@
9
9
  // - 跨块配色一致:维度键 → 稳定散列 → 固定调色板下标(colors.ts)。
10
10
 
11
11
  export {
12
- CaseList,
12
+ AttemptList,
13
13
  DeltaTable,
14
+ EvalList,
15
+ ExperimentList,
16
+ GroupSummary,
14
17
  MetricBars,
15
18
  MetricLine,
16
19
  MetricMatrix,
@@ -20,8 +23,11 @@ export {
20
23
  Scoreboard,
21
24
  } from "../components.tsx";
22
25
  export type {
23
- CaseListProps,
26
+ AttemptListProps,
24
27
  DeltaTableProps,
28
+ EvalListProps,
29
+ ExperimentListProps,
30
+ GroupSummaryProps,
25
31
  MetricLineProps,
26
32
  MetricMatrixProps,
27
33
  MetricScatterProps,
@@ -32,9 +38,13 @@ export type {
32
38
 
33
39
  // 数据契约类型(家在 ../types.ts,「算」与「画」两侧共用同一份)
34
40
  export type {
35
- AttemptRef,
36
- CaseListData,
41
+ AttemptListItem,
42
+ AttemptLocator,
37
43
  DeltaData,
44
+ EvalListItem,
45
+ ExperimentListEvalRow,
46
+ ExperimentListItem,
47
+ GroupSummaryData,
38
48
  LineAxis,
39
49
  LineData,
40
50
  MatrixData,
@@ -45,7 +55,12 @@ export type {
45
55
  ScoreboardData,
46
56
  SelectionWarning,
47
57
  TableData,
58
+ TableRowMeta,
48
59
  } from "../types.ts";
49
60
 
50
- // 稳定配色(自定义组件想与官方组件同键同色时用)
51
- export { NRE_PALETTE, colorClassForKey, colorHexForKey, colorIndexForKey } from "./colors.ts";
61
+ // locale(官方组件 chrome 文案;指标 label 的按 locale 字典也用它解析)
62
+ export { DEFAULT_REPORT_LOCALE, resolveMetricLabel } from "../locale.ts";
63
+ export type { LocalizedLabel, ReportLocale } from "../locale.ts";
64
+
65
+ // 稳定配色(自定义组件想与官方组件同键同色时用;seriesClassForKey 配 CSS 的 --nre-series)
66
+ export { NRE_PALETTE, colorClassForKey, colorHexForKey, colorIndexForKey, seriesClassForKey } from "./colors.ts";