niceeval 0.6.1 → 0.7.0

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 (378) hide show
  1. package/INDEX.md +23 -23
  2. package/README.zh.md +6 -6
  3. package/dist/agents/types.d.ts +69 -7
  4. package/dist/context/types.d.ts +32 -12
  5. package/dist/i18n/en.d.ts +54 -0
  6. package/dist/i18n/zh-CN.d.ts +57 -3
  7. package/dist/o11y/types.d.ts +16 -2
  8. package/dist/report/aggregate.d.ts +32 -24
  9. package/dist/report/aggregate.js +158 -50
  10. package/dist/report/built-in/index.d.ts +2 -0
  11. package/dist/report/built-in/index.js +8 -0
  12. package/dist/report/components.d.ts +93 -160
  13. package/dist/report/components.js +377 -114
  14. package/dist/report/compute.d.ts +87 -81
  15. package/dist/report/compute.js +597 -417
  16. package/dist/report/flag.d.ts +32 -6
  17. package/dist/report/flag.js +92 -4
  18. package/dist/report/format.d.ts +19 -11
  19. package/dist/report/format.js +30 -13
  20. package/dist/report/index.d.ts +16 -16
  21. package/dist/report/index.js +20 -21
  22. package/dist/report/load.js +3 -2
  23. package/dist/report/locale.d.ts +57 -33
  24. package/dist/report/locale.js +122 -56
  25. package/dist/report/metrics.d.ts +23 -4
  26. package/dist/report/metrics.js +110 -25
  27. package/dist/report/primitives.d.ts +48 -15
  28. package/dist/report/primitives.js +135 -26
  29. package/dist/report/react/AttemptList.d.ts +9 -7
  30. package/dist/report/react/AttemptList.js +17 -10
  31. package/dist/report/react/DeltaTable.js +19 -18
  32. package/dist/report/react/EvalList.d.ts +4 -4
  33. package/dist/report/react/EvalList.js +0 -0
  34. package/dist/report/react/ExperimentComparison.d.ts +10 -0
  35. package/dist/report/react/ExperimentComparison.js +12 -0
  36. package/dist/report/react/ExperimentList.d.ts +4 -3
  37. package/dist/report/react/ExperimentList.js +17 -18
  38. package/dist/report/react/MetricBars.js +5 -4
  39. package/dist/report/react/MetricLine.js +12 -5
  40. package/dist/report/react/MetricMatrix.js +1 -1
  41. package/dist/report/react/MetricScatter.js +59 -28
  42. package/dist/report/react/MetricTable.js +2 -12
  43. package/dist/report/react/ScopeSummary.d.ts +10 -0
  44. package/dist/report/react/ScopeSummary.js +17 -0
  45. package/dist/report/react/Scoreboard.js +6 -6
  46. package/dist/report/react/cell.js +2 -2
  47. package/dist/report/react/chart-math.d.ts +23 -6
  48. package/dist/report/react/chart-math.js +71 -19
  49. package/dist/report/react/fixtures.d.ts +5 -9
  50. package/dist/report/react/fixtures.js +110 -147
  51. package/dist/report/react/index.d.ts +15 -5
  52. package/dist/report/react/index.js +18 -7
  53. package/dist/report/report.d.ts +137 -16
  54. package/dist/report/report.js +259 -28
  55. package/dist/report/text/faces.d.ts +17 -19
  56. package/dist/report/text/faces.js +253 -184
  57. package/dist/report/text/plot.js +1 -1
  58. package/dist/report/text/table.js +38 -7
  59. package/dist/report/tree.d.ts +90 -40
  60. package/dist/report/tree.js +252 -94
  61. package/dist/report/types.d.ts +247 -284
  62. package/dist/report/types.js +4 -3
  63. package/dist/report/web.d.ts +21 -5
  64. package/dist/report/web.js +42 -16
  65. package/dist/results/select.d.ts +38 -16
  66. package/dist/results/select.js +73 -25
  67. package/dist/results/types.d.ts +49 -14
  68. package/dist/runner/feedback/sink.d.ts +110 -0
  69. package/dist/runner/types.d.ts +513 -22
  70. package/dist/sandbox/docker.d.ts +23 -2
  71. package/dist/sandbox/e2b.d.ts +15 -1
  72. package/dist/sandbox/errors.d.ts +30 -3
  73. package/dist/sandbox/io-retry.d.ts +17 -0
  74. package/dist/sandbox/registry.d.ts +2 -0
  75. package/dist/sandbox/resolve.d.ts +18 -5
  76. package/dist/sandbox/retry.d.ts +11 -1
  77. package/dist/sandbox/types.d.ts +39 -5
  78. package/dist/sandbox/vercel.d.ts +7 -1
  79. package/dist/scoring/coverage.d.ts +30 -0
  80. package/dist/scoring/display.d.ts +21 -0
  81. package/dist/scoring/display.js +120 -0
  82. package/dist/scoring/types.d.ts +103 -20
  83. package/dist/shared/aggregate.d.ts +4 -2
  84. package/dist/shared/aggregate.js +8 -7
  85. package/dist/shared/types.d.ts +28 -0
  86. package/dist/tty-line.d.ts +0 -4
  87. package/dist/util.d.ts +23 -0
  88. package/docs-site/zh/README.md +44 -0
  89. package/docs-site/zh/examples/ai-agent-application.mdx +63 -0
  90. package/docs-site/zh/examples/coding-agent-extensions.mdx +57 -0
  91. package/docs-site/zh/examples/index.mdx +50 -0
  92. package/docs-site/zh/{concepts → explanation}/adapter.mdx +31 -13
  93. package/docs-site/zh/{concepts → explanation}/assert.mdx +7 -7
  94. package/docs-site/zh/{concepts → explanation}/drive.mdx +8 -8
  95. package/docs-site/zh/{concepts → explanation}/evals.mdx +4 -4
  96. package/docs-site/zh/{concepts → explanation}/experiment.mdx +8 -8
  97. package/docs-site/zh/{concepts → explanation}/hitl.mdx +8 -8
  98. package/docs-site/zh/{concepts → explanation}/judge.mdx +5 -5
  99. package/docs-site/zh/{concepts → explanation}/overview.mdx +11 -11
  100. package/docs-site/zh/{guides → explanation}/runner.mdx +18 -8
  101. package/docs-site/zh/{concepts → explanation}/tier.mdx +6 -6
  102. package/docs-site/zh/{guides → how-to}/agent-feedback-loop.mdx +35 -33
  103. package/docs-site/zh/{guides → how-to}/authoring.mdx +35 -2
  104. package/docs-site/zh/{guides → how-to}/ci-integration.mdx +23 -12
  105. package/docs-site/zh/{guides → how-to}/connect-otel.mdx +6 -6
  106. package/docs-site/zh/{guides → how-to}/connect-your-agent.mdx +47 -21
  107. package/docs-site/zh/{guides → how-to}/custom-reports.mdx +34 -39
  108. package/docs-site/zh/{guides → how-to}/dataset-fanout.mdx +25 -3
  109. package/docs-site/zh/{guides → how-to}/experiments.mdx +12 -5
  110. package/docs-site/zh/how-to/publish-report.mdx +105 -0
  111. package/docs-site/zh/{guides → how-to}/reporters.mdx +2 -2
  112. package/docs-site/zh/{guides → how-to}/sandbox-agent.mdx +56 -7
  113. package/docs-site/zh/how-to/sandbox-providers.mdx +350 -0
  114. package/docs-site/zh/{guides → how-to}/scoring-guide.mdx +4 -4
  115. package/docs-site/zh/{guides → how-to}/viewing-results.mdx +82 -39
  116. package/docs-site/zh/{guides → how-to}/write-experiment.mdx +6 -4
  117. package/docs-site/zh/{guides → how-to}/write-send.mdx +30 -14
  118. package/docs-site/zh/index.mdx +24 -26
  119. package/docs-site/zh/introduction.mdx +8 -8
  120. package/docs-site/zh/reference/builtin-agents.mdx +32 -5
  121. package/docs-site/zh/reference/capabilities.mdx +8 -8
  122. package/docs-site/zh/reference/cli.mdx +40 -12
  123. package/docs-site/zh/reference/define-agent.mdx +58 -5
  124. package/docs-site/zh/reference/define-config.mdx +1 -1
  125. package/docs-site/zh/reference/define-eval.mdx +42 -9
  126. package/docs-site/zh/reference/events.mdx +3 -3
  127. package/docs-site/zh/reference/expect.mdx +26 -1
  128. package/docs-site/zh/{guides → reference}/official-adapters.mdx +32 -8
  129. package/docs-site/zh/{guides → reference}/report-components.mdx +45 -33
  130. package/docs-site/zh/{guides → reference}/results-data.mdx +21 -13
  131. package/docs-site/zh/troubleshooting/debug-sandbox.mdx +57 -0
  132. package/docs-site/zh/troubleshooting/debugging.mdx +212 -0
  133. package/docs-site/zh/{quickstart.mdx → tutorials/quickstart.mdx} +5 -17
  134. package/package.json +10 -2
  135. package/src/agents/ai-sdk-otel.test.ts +1 -0
  136. package/src/agents/ai-sdk.test.ts +3 -0
  137. package/src/agents/ai-sdk.ts +3 -0
  138. package/src/agents/bub-install-spec.test.ts +34 -0
  139. package/src/agents/bub-install-spec.ts +32 -0
  140. package/src/agents/bub.ts +31 -32
  141. package/src/agents/claude-code.test.ts +130 -9
  142. package/src/agents/claude-code.ts +76 -4
  143. package/src/agents/codex.test.ts +189 -40
  144. package/src/agents/codex.ts +155 -14
  145. package/src/agents/coding-cli-versions.test.ts +15 -0
  146. package/src/agents/coding-cli-versions.ts +3 -0
  147. package/src/agents/index.ts +13 -2
  148. package/src/agents/langgraph.test.ts +204 -0
  149. package/src/agents/langgraph.ts +495 -0
  150. package/src/agents/marketplace.ts +85 -0
  151. package/src/agents/native-config.test.ts +179 -0
  152. package/src/agents/native-config.ts +267 -0
  153. package/src/agents/openai-compat.test.ts +1 -0
  154. package/src/agents/openai-compat.ts +1 -1
  155. package/src/agents/openclaw.test.ts +31 -0
  156. package/src/agents/openclaw.ts +171 -0
  157. package/src/agents/plugin-config.test.ts +1 -0
  158. package/src/agents/sdk-streams.test.ts +79 -0
  159. package/src/agents/sdk-streams.ts +55 -10
  160. package/src/agents/skills.test.ts +1 -0
  161. package/src/agents/streaming.test.ts +3 -9
  162. package/src/agents/streaming.ts +2 -2
  163. package/src/agents/types.ts +71 -8
  164. package/src/agents/ui-message-stream.test.ts +3 -0
  165. package/src/cli.ts +446 -124
  166. package/src/context/context.test.ts +51 -12
  167. package/src/context/context.ts +162 -30
  168. package/src/context/session.test.ts +2 -1
  169. package/src/context/session.ts +115 -7
  170. package/src/context/types.ts +30 -12
  171. package/src/define.test.ts +13 -8
  172. package/src/define.ts +25 -4
  173. package/src/expect/index.ts +53 -23
  174. package/src/i18n/en.ts +81 -17
  175. package/src/i18n/zh-CN.ts +80 -17
  176. package/src/o11y/cost.test.ts +1 -0
  177. package/src/o11y/execution-tree.test.ts +1 -20
  178. package/src/o11y/otlp/mappers/claude-code.test.ts +1 -0
  179. package/src/o11y/otlp/parse.test.ts +1 -0
  180. package/src/o11y/otlp/turn-otel.test.ts +1 -0
  181. package/src/o11y/parsers/bub.test.ts +1 -0
  182. package/src/o11y/parsers/claude-code.test.ts +1 -34
  183. package/src/o11y/parsers/openclaw.test.ts +154 -0
  184. package/src/o11y/parsers/openclaw.ts +310 -0
  185. package/src/o11y/prices.json +746 -311
  186. package/src/o11y/tool-names.test.ts +1 -0
  187. package/src/o11y/types.ts +16 -2
  188. package/src/report/aggregate.ts +178 -61
  189. package/src/report/built-in/index.tsx +9 -0
  190. package/src/report/components.tsx +625 -279
  191. package/src/report/compute.ts +723 -491
  192. package/src/report/dual-render.test.tsx +741 -1024
  193. package/src/report/flag.ts +104 -12
  194. package/src/report/format.ts +32 -12
  195. package/src/report/index.ts +119 -46
  196. package/src/report/load.ts +3 -2
  197. package/src/report/locale.ts +136 -65
  198. package/src/report/metrics.ts +108 -25
  199. package/src/report/primitives.tsx +196 -45
  200. package/src/report/react/AttemptList.tsx +30 -43
  201. package/src/report/react/DeltaTable.tsx +63 -45
  202. package/src/report/react/EvalList.tsx +0 -0
  203. package/src/report/react/ExperimentComparison.tsx +73 -0
  204. package/src/report/react/ExperimentList.tsx +50 -32
  205. package/src/report/react/MetricBars.tsx +5 -4
  206. package/src/report/react/MetricLine.tsx +13 -8
  207. package/src/report/react/MetricMatrix.tsx +2 -2
  208. package/src/report/react/MetricScatter.tsx +86 -34
  209. package/src/report/react/MetricTable.tsx +4 -76
  210. package/src/report/react/ScopeSummary.tsx +86 -0
  211. package/src/report/react/Scoreboard.tsx +28 -10
  212. package/src/report/react/cell.tsx +2 -2
  213. package/src/report/react/chart-math.test.ts +85 -0
  214. package/src/report/react/chart-math.ts +101 -22
  215. package/src/report/react/enhance.js +89 -5
  216. package/src/report/react/fixtures.ts +114 -154
  217. package/src/report/react/index.tsx +24 -39
  218. package/src/report/react/render.test.tsx +138 -158
  219. package/src/report/react/styles.css +243 -82
  220. package/src/report/report.test.ts +779 -841
  221. package/src/report/report.ts +423 -41
  222. package/src/report/text/faces.ts +290 -193
  223. package/src/report/text/plot.ts +1 -1
  224. package/src/report/text/table.ts +44 -7
  225. package/src/report/tree.ts +362 -104
  226. package/src/report/types.ts +261 -271
  227. package/src/report/web.ts +63 -20
  228. package/src/results/annotated-source.test.ts +62 -9
  229. package/src/results/annotated-source.ts +64 -6
  230. package/src/results/attempt-evidence.test.ts +13 -11
  231. package/src/results/attempt-evidence.ts +20 -13
  232. package/src/results/attempt-source.ts +6 -3
  233. package/src/results/copy.ts +150 -60
  234. package/src/results/host-equivalence.test.ts +34 -20
  235. package/src/results/index.ts +12 -4
  236. package/src/results/locator.test.ts +1 -22
  237. package/src/results/open.ts +15 -5
  238. package/src/results/publish.ts +149 -0
  239. package/src/results/results.test.ts +89 -54
  240. package/src/results/select.ts +104 -34
  241. package/src/results/truncate.ts +90 -0
  242. package/src/results/types.ts +43 -14
  243. package/src/results/writer.ts +31 -13
  244. package/src/runner/attempt.test.ts +138 -7
  245. package/src/runner/attempt.ts +603 -104
  246. package/src/runner/discover.test.ts +47 -0
  247. package/src/runner/discover.ts +36 -2
  248. package/src/runner/eval-source.test.ts +1 -27
  249. package/src/runner/feedback/agent.test.ts +504 -0
  250. package/src/runner/feedback/agent.ts +409 -0
  251. package/src/runner/feedback/ci.test.ts +562 -0
  252. package/src/runner/feedback/ci.ts +401 -0
  253. package/src/runner/feedback/coordinator.test.ts +317 -0
  254. package/src/runner/feedback/coordinator.ts +397 -0
  255. package/src/runner/feedback/failure.ts +40 -0
  256. package/src/runner/feedback/human.test.ts +616 -0
  257. package/src/runner/feedback/human.ts +535 -0
  258. package/src/runner/feedback/index.ts +66 -0
  259. package/src/runner/feedback/io.ts +78 -0
  260. package/src/runner/feedback/profile.test.ts +50 -0
  261. package/src/runner/feedback/profile.ts +58 -0
  262. package/src/runner/feedback/reducer.test.ts +395 -0
  263. package/src/runner/feedback/reducer.ts +260 -0
  264. package/src/runner/feedback/renderer.ts +82 -0
  265. package/src/runner/feedback/sink.ts +203 -0
  266. package/src/runner/feedback/testing.ts +106 -0
  267. package/src/runner/ledger.test.ts +230 -0
  268. package/src/runner/ledger.ts +329 -0
  269. package/src/runner/report.test.ts +128 -3
  270. package/src/runner/report.ts +33 -9
  271. package/src/runner/reporters/artifacts.ts +8 -2
  272. package/src/runner/reporters/braintrust.test.ts +8 -7
  273. package/src/runner/reporters/braintrust.ts +9 -2
  274. package/src/runner/reporters/index.ts +2 -2
  275. package/src/runner/reporters/json.test.ts +162 -0
  276. package/src/runner/reporters/json.ts +35 -8
  277. package/src/runner/reporters/shared.ts +1 -5
  278. package/src/runner/run.test.ts +760 -3
  279. package/src/runner/run.ts +243 -37
  280. package/src/runner/sandbox-prep.ts +3 -42
  281. package/src/runner/timing.ts +158 -0
  282. package/src/runner/types.ts +518 -22
  283. package/src/sandbox/checkpoint.test.ts +55 -0
  284. package/src/sandbox/checkpoint.ts +29 -8
  285. package/src/sandbox/cli-commands.ts +407 -0
  286. package/src/sandbox/docker.ts +115 -16
  287. package/src/sandbox/e2b-agent-template.test.ts +56 -0
  288. package/src/sandbox/e2b-agent-template.ts +94 -0
  289. package/src/sandbox/e2b.ts +74 -9
  290. package/src/sandbox/errors.ts +111 -4
  291. package/src/sandbox/index.ts +2 -0
  292. package/src/sandbox/io-retry.test.ts +58 -0
  293. package/src/sandbox/io-retry.ts +45 -0
  294. package/src/sandbox/keep-registry.test.ts +86 -0
  295. package/src/sandbox/keep-registry.ts +142 -0
  296. package/src/sandbox/keep.ts +178 -0
  297. package/src/sandbox/paths.test.ts +1 -0
  298. package/src/sandbox/paths.ts +19 -8
  299. package/src/sandbox/registry.ts +20 -3
  300. package/src/sandbox/resolve.ts +76 -11
  301. package/src/sandbox/retry.test.ts +70 -0
  302. package/src/sandbox/retry.ts +46 -4
  303. package/src/sandbox/types.ts +44 -6
  304. package/src/sandbox/vercel.ts +43 -20
  305. package/src/scoring/collector.ts +60 -17
  306. package/src/scoring/coverage.ts +95 -0
  307. package/src/scoring/diff.ts +81 -0
  308. package/src/scoring/display.test.ts +121 -0
  309. package/src/scoring/display.ts +133 -0
  310. package/src/scoring/evidence.test.ts +189 -0
  311. package/src/scoring/judge.test.ts +142 -0
  312. package/src/scoring/judge.ts +15 -18
  313. package/src/scoring/scoped.ts +217 -50
  314. package/src/scoring/types.ts +117 -20
  315. package/src/scoring/verdict.ts +16 -4
  316. package/src/shared/aggregate.ts +8 -6
  317. package/src/shared/types.ts +31 -0
  318. package/src/show/compose.ts +50 -67
  319. package/src/show/index.ts +127 -56
  320. package/src/show/render.ts +662 -131
  321. package/src/show/report-host.test.ts +188 -0
  322. package/src/show/report-host.ts +375 -0
  323. package/src/show/show.test.ts +320 -54
  324. package/src/tty-line.ts +8 -26
  325. package/src/util.test.ts +1 -0
  326. package/src/util.ts +41 -0
  327. package/src/view/app/App.test.tsx +69 -0
  328. package/src/view/app/App.tsx +144 -48
  329. package/src/view/app/components/AttemptModal.tsx +423 -11
  330. package/src/view/app/components/CodeView.tsx +41 -14
  331. package/src/view/app/components/CopyControls.tsx +2 -2
  332. package/src/view/app/i18n.ts +37 -17
  333. package/src/view/app/lib/attempt-route.test.ts +1 -0
  334. package/src/view/app/lib/verdict.ts +7 -9
  335. package/src/view/app/main.tsx +13 -8
  336. package/src/view/app/pages/{RunsPage.tsx → AttemptsPage.tsx} +6 -6
  337. package/src/view/app/types.ts +4 -1
  338. package/src/view/artifact-serving.test.ts +2 -1
  339. package/src/view/client-dist/app.css +1 -1
  340. package/src/view/client-dist/app.js +17 -17
  341. package/src/view/data.test.ts +10 -3
  342. package/src/view/data.ts +155 -49
  343. package/src/view/index.ts +56 -41
  344. package/src/view/server.ts +37 -15
  345. package/src/view/shared/types.ts +34 -5
  346. package/src/view/styles.css +227 -0
  347. package/src/view/view-report.test.ts +167 -62
  348. package/dist/report/built-ins/experiment-comparison.d.ts +0 -1
  349. package/dist/report/built-ins/experiment-comparison.js +0 -13
  350. package/dist/report/built-ins/index.d.ts +0 -1
  351. package/dist/report/built-ins/index.js +0 -2
  352. package/dist/report/react/GroupSummary.d.ts +0 -8
  353. package/dist/report/react/GroupSummary.js +0 -8
  354. package/dist/report/react/RunOverview.d.ts +0 -8
  355. package/dist/report/react/RunOverview.js +0 -12
  356. package/docs-site/zh/example/ai-agent-application.mdx +0 -152
  357. package/docs-site/zh/example/claude-code-codex-plugin.mdx +0 -167
  358. package/docs-site/zh/example/claude-code-codex-skill.mdx +0 -152
  359. package/docs-site/zh/example/showcase.mdx +0 -39
  360. package/docs-site/zh/guides/publish-report.mdx +0 -91
  361. package/docs-site/zh/guides/sandbox-providers.mdx +0 -102
  362. package/src/report/built-in-user-parity.test.tsx +0 -640
  363. package/src/report/built-ins/experiment-comparison.tsx +0 -19
  364. package/src/report/built-ins/index.ts +0 -2
  365. package/src/report/react/GroupSummary.tsx +0 -66
  366. package/src/report/react/RunOverview.tsx +0 -109
  367. package/src/runner/reporters/console.ts +0 -70
  368. package/src/runner/reporters/live.test.ts +0 -56
  369. package/src/runner/reporters/live.ts +0 -247
  370. package/src/runner/reporters/quiet.test.ts +0 -66
  371. package/src/runner/reporters/quiet.ts +0 -49
  372. package/src/runner/reporters/table.ts +0 -277
  373. /package/docs-site/zh/{example/tier1-ai-sdk-v7.mdx → examples/integrations/ai-sdk-v7.mdx} +0 -0
  374. /package/docs-site/zh/{example/tier1-claude-sdk.mdx → examples/integrations/claude-sdk.mdx} +0 -0
  375. /package/docs-site/zh/{example/tier1-codex-sdk.mdx → examples/integrations/codex-sdk.mdx} +0 -0
  376. /package/docs-site/zh/{example/tier1-langgraph.mdx → examples/integrations/langgraph.mdx} +0 -0
  377. /package/docs-site/zh/{example/tier1-pi-sdk.mdx → examples/integrations/pi-sdk.mdx} +0 -0
  378. /package/docs-site/zh/{guides → how-to}/fixtures.mdx +0 -0
@@ -2,12 +2,25 @@
2
2
 
3
3
  import type { Severity, SourceLoc } from "../shared/types.ts";
4
4
  import type { DerivedFacts, StreamEvent, Usage } from "../o11y/types.ts";
5
+ import type { ResolvedCoverage } from "./coverage.ts";
5
6
 
6
- /** 值断言(expect 匹配器)。纯函数 score + 可链式改严重度 / 阈值。 */
7
+ // 覆盖代数(解析 / 降级 / 聚合)住在 coverage.ts;类型经这里进聚合 facade(src/types.ts)。
8
+ export type {
9
+ CoverageChannel,
10
+ ResolvedCoverage,
11
+ ResolvedCoverageChannel,
12
+ ResolvedCoverageStatus,
13
+ } from "./coverage.ts";
14
+
15
+ /** 值断言(expect 匹配器)。纯函数 score + 可链式改严重度 / 阈值 / optional。 */
7
16
  export interface ValueAssertion {
8
17
  readonly name: string;
9
18
  readonly severity: Severity;
10
19
  readonly threshold?: number;
20
+ /** `.optional()` 链过的标记:评不了只记 unavailable,不把 attempt 拖成 errored。 */
21
+ readonly isOptional?: boolean;
22
+ /** 期望条件的有界文本描述(如 `contains "Brooklyn"`),失败时进 AssertionResult.expected。 */
23
+ readonly expected?: string;
11
24
  score(value: unknown): number | Promise<number>;
12
25
  /** 转成硬门槛断言:未达阈值(省略 threshold 则按 score > 0 判定)整条 eval 判为 failed。返回新实例,不改原对象。 */
13
26
  gate(threshold?: number): ValueAssertion;
@@ -16,37 +29,82 @@ export interface ValueAssertion {
16
29
  * `--strict` 运行下,软阈值失败也会把整条 eval 的 verdict 计为 failed。返回新实例,不改原对象。
17
30
  */
18
31
  atLeast(threshold: number): ValueAssertion;
32
+ /**
33
+ * 允许这条断言证据缺席:评不了时只记录 `outcome: "unavailable"`,不影响判定。
34
+ * 与 severity 正交(severity 说影不影响质量判定,optional 说证据允不允许缺席)。返回新实例,不改原对象。
35
+ */
36
+ optional(): ValueAssertion;
19
37
  }
20
38
 
21
- /** 收集到 collector 里的一条断言记录(评估前)。 */
22
- export interface AssertionSpec {
39
+ /**
40
+ * 断言记录的公共字段(见 docs/feature/scoring/architecture.md「断言记录」——字段契约的单点定义)。
41
+ */
42
+ export interface AssertionBase {
43
+ /** 断言标题:t.group 内是该断言自己的摘要,组外是 matcher 摘要或 judge 问题;show/view 失败行的标题。 */
23
44
  name: string;
45
+ /** 所属分组路径:外层在前的 t.group 标题数组;无分组省略。纯报告用,不影响判定。 */
46
+ groupPath?: string[];
24
47
  severity: Severity;
25
- threshold?: number;
26
- /** 延迟评估:final 时拿到完整运行结果再算分。 */
27
- evaluate(ctx: ScoringContext): Promise<number> | number;
48
+ /** 作者用 .optional() 显式允许该断言缺席;只改变 unavailable 的折叠方式(见 Severity 与 Verdict),不改变 severity 语义。 */
49
+ optional?: true;
50
+ /** matcher / judge 摘要,如 `equals(4)`、`closedQA("…")`;与 name 分开,供 show/view 同时展示分组标题与检查方式。 */
51
+ detail?: string;
52
+ /** 断言在 eval 源码中的调用点,`--eval` 把结果标回源码行的锚。 */
53
+ loc?: SourceLoc;
28
54
  }
29
55
 
30
- /** 断言评估完的结果(进判定 / 报告)。 */
31
- export interface AssertionResult {
32
- name: string;
56
+ /**
57
+ * 断言评估完的结果(进判定 / 报告)。判别键是 `outcome`——`unavailable` 是没有分数的独立态,
58
+ * 普通聚合代码按 `outcome` 分支就不可能把证据缺口算成零分。判定只消费
59
+ * `severity` / `outcome` / `optional` / `score` / `threshold`。
60
+ */
61
+ export type AssertionResult =
62
+ | (AssertionBase & {
63
+ outcome: "passed" | "failed";
64
+ /** 归一化得分:值断言 0/1,judge 等打分断言 0..1。 */
65
+ score: number;
66
+ /** soft 断言的 .atLeast(x) 阈值;没有设阈值则省略。 */
67
+ threshold?: number;
68
+ /** 失败证据摘要:期望值的有界文本预览,供 show/view 直接展示。 */
69
+ expected?: string;
70
+ /** 失败证据摘要:实际值的有界文本预览。 */
71
+ received?: string;
72
+ /** 这条分数看着什么材料算出(judge 输入或被检查值预览);view 展开排查用,默认不展示。 */
73
+ evidence?: string;
74
+ })
75
+ | (AssertionBase & {
76
+ outcome: "unavailable";
77
+ /** 机器可读原因,如 "judge-model-unresolved"、"coverage:actions=partial"。 */
78
+ reason: string;
79
+ });
80
+
81
+ /**
82
+ * 摘要面从完整 `AssertionResult[]` 选出的一条主失败断言。它只负责展示,不参与 verdict;
83
+ * `show @locator` / view Attempt 详情仍读取完整断言数组。字段保持结构化,使 CI 不必解析
84
+ * Human 的 `gate: …` 文案。
85
+ */
86
+ export interface PrimaryAssertionSummary {
33
87
  severity: Severity;
88
+ /** `groupPath.join(" > ")`,无 group 时回退到断言 name。 */
89
+ assertion: string;
90
+ /** `detail ?? name`;与 assertion 相同时省略,避免重复。 */
91
+ matcher?: string;
92
+ expected?: string;
93
+ received?: string;
94
+ score?: number;
34
95
  threshold?: number;
35
- score: number;
36
- passed: boolean;
37
- detail?: string;
38
- /** 这条分数是看着什么材料算出来的(judge 收到的输入,或 t.check 失败时实际被检查的值)。view 展开排查「为什么是这个分」,默认不展示。 */
39
- evidence?: string;
40
- /** 所属分组(t.group 标题)。纯报告用,不影响 passed/score。 */
41
- group?: string;
42
- /** 断言在 eval 源码里的调用点(栈回溯抠出);view 把判定叠回这一行。 */
43
- loc?: SourceLoc;
96
+ /** unavailable 断言的结构化原因。 */
97
+ reason?: string;
98
+ /** 同类因果失败中除主失败外的条数。 */
99
+ additionalFailures: number;
44
100
  }
45
101
 
46
102
  /** eval 作者拿到的可链式句柄(t.judge.autoevals.closedQA(...).atLeast(0.7))。 */
47
103
  export interface AssertionHandle {
48
104
  atLeast(threshold: number): AssertionHandle;
49
105
  gate(threshold?: number): AssertionHandle;
106
+ /** 允许这条断言证据缺席:unavailable 只保留在记录里,不影响判定(见 Severity 与 Verdict)。 */
107
+ optional(): AssertionHandle;
50
108
  }
51
109
 
52
110
  /** scoped / judge 断言在 final 评估时拿到的运行结果。 */
@@ -57,6 +115,8 @@ export interface ScoringContext {
57
115
  readonly scripts: Record<string, ScriptResult>;
58
116
  readonly usage: Usage;
59
117
  readonly status: "completed" | "failed" | "waiting";
118
+ /** 当前作用域(turn / session / attempt)解析后的证据覆盖;断言按它做三值折叠(见 scoped.ts)。 */
119
+ readonly coverage: ResolvedCoverage;
60
120
  /** 读沙箱里某文件的最终内容(judge / file 断言用)。 */
61
121
  readFile(path: string): Promise<string | undefined>;
62
122
  }
@@ -66,9 +126,46 @@ export interface ScriptResult {
66
126
  output: string;
67
127
  }
68
128
 
129
+ // ── agent 归因增量(见 docs/feature/results/architecture.md「diff.json」与
130
+ // docs/feature/sandbox/architecture.md「变更归因:send 窗口与分类账」)──
131
+
132
+ /** diff.json 的落盘形状:按时序的窗口数组(逐窗口 delta 序列,不做跨窗口压缩)。 */
133
+ export type DiffArtifact = DiffWindow[];
134
+
135
+ export interface DiffWindow {
136
+ /** send 窗口标签,与时间树 turn 节点、--execution 轮次同源(如 "s1/t2")。 */
137
+ window: string;
138
+ /** 该窗口内 agent 改动的文件;窗口内没有 workspace 变化时窗口仍落一条、changes 为空对象。 */
139
+ changes: Record<string, WindowChange>;
140
+ }
141
+
142
+ export interface WindowChange {
143
+ status: "added" | "modified" | "deleted";
144
+ /** 窗口开始时的内容;added 无此字段。 */
145
+ before?: string;
146
+ /** 窗口结束时的内容;deleted 无此字段。 */
147
+ after?: string;
148
+ /** 二进制文件不内联内容,只记字节数。 */
149
+ binary?: { beforeBytes?: number; afterBytes?: number };
150
+ }
151
+
152
+ /** 读取面在窗口序列之上派生的文件级视图(派生物可随时重算,不落盘)。 */
153
+ export interface DiffFileSummary {
154
+ /** 净效果:首个触及窗口的起点 vs 最后触及窗口的终点;"none" = 动过但净无变化(创建又删除、改回原样)。 */
155
+ net: "added" | "modified" | "deleted" | "none";
156
+ /** 触及该文件的窗口标签,按时序。 */
157
+ windows: string[];
158
+ binary?: true;
159
+ }
160
+
161
+ /** agent 归因 diff 的消费视图:窗口序列(落盘事实)+ 派生的文件级摘要与终态读取。 */
69
162
  export interface DiffData {
70
- generatedFiles: Record<string, string>;
71
- deletedFiles: string[];
163
+ /** 落盘事实,原样。 */
164
+ windows: DiffWindow[];
165
+ /** 派生:每个被 agent 触及的文件一条。 */
166
+ files: Record<string, DiffFileSummary>;
167
+ /** 该文件最后一个触及窗口结束时的内容;净删除或从未触及返回 undefined。t.sandbox.diff.get 同一语义。 */
168
+ get(path: string): string | undefined;
72
169
  }
73
170
 
74
171
  export type Verdict = "passed" | "failed" | "errored" | "skipped";
@@ -1,17 +1,29 @@
1
- // 判定:把执行结果 + 断言 + 跳过原因折叠成一个 Verdict(见 docs/feature/scoring/README.md)。
1
+ // 判定:把执行结果 + 断言 + 跳过原因折叠成一个 Verdict
2
+ // (见 docs/feature/scoring/architecture/severity-and-verdict.md)。固定优先级取第一个成立项:
3
+ // 执行异常 / 任一非 optional 断言 unavailable → errored
4
+ // 任一 gate 不通过,或 strict 下 soft 低于阈值 → failed
5
+ // 显式 t.skip(reason) → skipped
6
+ // 否则 → passed
7
+ // errored 压过一切(执行证据已不可信);failed 压过 skipped(t.skip 不掩盖已记录的硬失败)。
2
8
 
3
- import type { AssertionResult, Verdict } from "../types.ts";
9
+ import type { AssertionResult, AttemptError, Verdict } from "../types.ts";
4
10
 
5
11
  export function computeVerdict(input: {
6
- error?: string;
12
+ error?: AttemptError;
7
13
  assertions: readonly AssertionResult[];
8
14
  skipReason?: string;
9
15
  strict?: boolean;
10
16
  }): Verdict {
11
17
  if (input.error !== undefined) return "errored";
12
18
 
19
+ // 作者写下的每条断言默认都要求可评估:非 optional 的 unavailable 使 attempt errored,
20
+ // 不分 gate / soft——「soft 全部评不了但 attempt 还绿着」是没有测量的绿,不允许出现。
13
21
  for (const a of input.assertions) {
14
- if (a.passed) continue;
22
+ if (a.outcome === "unavailable" && !a.optional) return "errored";
23
+ }
24
+
25
+ for (const a of input.assertions) {
26
+ if (a.outcome !== "failed") continue;
15
27
  if (a.severity === "gate" || input.strict) return "failed";
16
28
  }
17
29
 
@@ -1,4 +1,4 @@
1
- // CLI 表格(runner/reporters/table.ts)与 view 榜单(view/aggregate.ts)共用的聚合小工具。
1
+ // report 聚合(report/aggregate.ts)与 view 榜单(view/app/lib/rows.ts)共用的聚合小工具。
2
2
  // 实验标签推导、token/成本求和、verdict 排序各只有一份 —— 否则同一个实验在终端和网页上
3
3
  // 会显示成两个名字 / 两组数。保持环境无关(纯函数,只 type import)。
4
4
 
@@ -45,22 +45,24 @@ export function experimentGroupOf(experimentId: string): string | undefined {
45
45
  }
46
46
 
47
47
  /**
48
- * eval id 前缀过滤,同 CLI 位置参数的分段语义(src/runner/discover.ts):
49
- * "algebra" 匹配自身与 "algebra/..." 子级,不误配 "algebra2";允许 "algebra/" 尾斜杠写法,等价。
48
+ * eval id 前缀过滤,同 CLI 位置参数语义(docs/feature/reports/show.md「打开与收窄」):
49
+ * eval 位置参数是收窄过滤,按**裸前缀宽松匹配**——"algebra" 命中 "algebra""algebra/..."
50
+ * 也命中 "algebra2",多命中正是它的用途(与 `--experiment` 的按路径段匹配有意不同)。
50
51
  */
51
52
  export function evalPrefixPredicate(evals?: string | string[]): (id: string) => boolean {
52
53
  if (evals === undefined) return () => true;
53
- const prefixes = (Array.isArray(evals) ? evals : [evals]).map((p) => p.replace(/\/+$/, ""));
54
- return (id) => prefixes.some((prefix) => id === prefix || id.startsWith(prefix + "/"));
54
+ const prefixes = Array.isArray(evals) ? evals : [evals];
55
+ return (id) => prefixes.some((prefix) => id.startsWith(prefix));
55
56
  }
56
57
 
57
58
  /** 无 experimentId 时的兜底标签。 */
58
59
  export function fallbackExperimentLabel(result: {
60
+ experimentId?: string;
59
61
  experiment?: ExperimentRunInfo;
60
62
  agent: string;
61
63
  model?: string;
62
64
  }): string {
63
- if (result.experiment?.id) return displayExperimentName(result.experiment.id) ?? result.experiment.id;
65
+ if (result.experimentId) return displayExperimentName(result.experimentId) ?? result.experimentId;
64
66
  if (result.model) return `${result.agent}/${result.model}`;
65
67
  return result.agent || "ad hoc run";
66
68
  }
@@ -33,6 +33,37 @@ export interface SourceArtifact {
33
33
  /** 通用清理闭包(setup 返回值 / teardown 的形状),异步同步皆可,统一在 finally 里执行。 */
34
34
  export type Cleanup = () => Promise<void> | void;
35
35
 
36
+ /** `ScopedFeedback.progress` 的入参:此刻正在做什么(短命状态,可被后续更新覆盖)。 */
37
+ export interface ProgressUpdate {
38
+ message: string;
39
+ current?: number;
40
+ total?: number;
41
+ }
42
+
43
+ /** `ScopedFeedback.diagnostic` 的入参:运行结束后仍应保留的问题(永久事件)。 */
44
+ export interface DiagnosticInput {
45
+ code: string;
46
+ level: "warning" | "error";
47
+ message: string;
48
+ data?: Readonly<Record<string, JsonValue>>;
49
+ /** 并发 attempt 产生同一问题时的去重键;相同 key 折叠成一条并累计次数。 */
50
+ dedupeKey?: string;
51
+ }
52
+
53
+ /**
54
+ * 作用域反馈 API(见 docs/feature/experiments/library.md「生命周期代码怎样向这次运行反馈」):
55
+ * sandbox provider、sandbox hook、eval 与 Agent Adapter 从 runner 注入的上下文获得同一套入口。
56
+ * - `progress` 是短命状态:Human profile 更新 active 行,Agent/CI 不逐条打印,不进最终结果;
57
+ * - `diagnostic` 是永久事件:进 Human/Agent/CI 的永久输出流并落进 attempt 的 diagnostics;
58
+ * 即使 level 为 "error" 也不自动改变 verdict(要 errored 抛异常,要 failed 用断言)。
59
+ * 两个方法都不接受 phase / scope / 颜色 / 输出流——runner 知道当前回调属于哪个生命周期阶段,
60
+ * 调用方不能冒充其它阶段。
61
+ */
62
+ export interface ScopedFeedback {
63
+ progress(update: ProgressUpdate): void;
64
+ diagnostic(input: DiagnosticInput): void;
65
+ }
66
+
36
67
  /**
37
68
  * 可本地化文案:纯字符串,或按 locale 代码(如 "en"、"zh-CN")映射多语言。
38
69
  * view 按当前界面语言挑一条,挑不到回退到 en / 第一条。
@@ -1,95 +1,78 @@
1
- // show 专属的跨 run 时间轴口径(--history;docs-site/zh/guides/viewing-results.mdx 是行为规范)。
1
+ // show 专属的执行时间轴口径(--history;契约:docs/feature/reports/show.md「--history:一个 eval
2
+ // 的执行时间轴」)。逐 attempt 而非逐快照:对 Scope 中匹配的每个 experimentId + evalId 分节,
3
+ // 节内按 startedAt 升序列出跨快照按 attempt 身份键去重后的历次 attempt——时间、verdict、
4
+ // 单行结果摘要(Scoring display 契约)、耗时、成本与 locator。resume 携带的复印件不占行。
2
5
  //
3
- // 现刻水位 Selection(两个宿主共用)住在 ../results/select.ts selectCurrentResults;
4
- // 本文件只留 show 独有的时间轴计算:每个快照 / 每次真实执行一行,resume 携带的复印件不占行。
6
+ // 现刻水位 Scope(两个宿主共用)住在 ../results/select.ts;本文件只留 show 独有的时间轴计算。
5
7
  // 数据只消费 niceeval/results 的读取面。
6
8
 
7
- import { foldEvalVerdict } from "../shared/verdict.ts";
8
9
  import { attemptCostUSD } from "../report/metrics.ts";
9
- import type { Verdict } from "../types.ts";
10
+ import { compactAssertionSummary, primaryAssertionSummary, summaryText } from "../scoring/display.ts";
11
+ import type { EvalResult, Verdict } from "../types.ts";
10
12
  import type { AttemptHandle, Experiment } from "../results/index.ts";
11
13
 
12
14
  // ───────────────────────── 时间轴(--history)─────────────────────────
13
15
 
14
- export interface EvalHistoryRow {
15
- /** 该次真实执行所在 run(快照)的时刻。 */
16
- startedAt: string;
16
+ export interface AttemptHistoryRow {
17
+ /** attempt 自己的开始时刻(ISO);第三方落盘可能缺失,如实缺省、排序沉底。 */
18
+ startedAt?: string;
17
19
  verdict: Verdict;
18
- attempts: number;
20
+ /** 单行结果摘要(display 契约):主失败断言 / 结构化 error 一层摘要 / skip 理由;passed 缺省。 */
21
+ summary?: string;
22
+ durationMs: number;
19
23
  costUSD: number | null;
20
- /** 最新一次 attempt 的第一条失败断言("gate calledTool(...)")。 */
21
- failedAssertion?: string;
22
- /** errored 时的错误摘要。 */
23
- error?: string;
24
+ /** attempt 的稳定引用(`@` 前缀),复制给 `niceeval show @<locator>` 下钻。 */
25
+ locator?: string;
24
26
  }
25
27
 
26
- /** attempt 的身份键(去重口径与 dedupeAttempts 一致);缺 startedAt 时不参与去重(宁可多列不误删)。 */
28
+ /** attempt 的身份键(去重口径与 results 的 dedupeAttempts 一致);缺 startedAt 时不参与去重(宁可多列不误删)。 */
27
29
  function attemptKey(attempt: AttemptHandle): string | undefined {
28
30
  const r = attempt.result;
29
31
  return r.startedAt === undefined ? undefined : `${r.attempt}|${r.startedAt}`;
30
32
  }
31
33
 
32
34
  /**
33
- * eval 的跨 run 时间轴:每次真实执行一行,新→旧。--resume 携带的复印件
34
- * (身份键与原判定相同的条目)不占行 —— 否则趋势会被复印件灌满假数据。
35
+ * 单行结果摘要:与榜单 Result 单元格同一条 display 契约(docs/feature/scoring/library/display.md)——
36
+ * 结构化 error 取一层 message 摘要,skipped 取理由,failed 取主失败断言的紧凑单行;passed 无摘要。
35
37
  */
36
- export function evalHistory(exp: Experiment, evalId: string): EvalHistoryRow[] {
37
- const rows: EvalHistoryRow[] = [];
38
+ function rowSummary(result: EvalResult): string | undefined {
39
+ if (result.error !== undefined) return summaryText(result.error.message);
40
+ if (result.skipReason !== undefined) return summaryText(result.skipReason);
41
+ const summary = primaryAssertionSummary(result.assertions, result.verdict);
42
+ return summary === undefined ? undefined : compactAssertionSummary(summary);
43
+ }
44
+
45
+ /**
46
+ * 一个 experimentId + evalId 的执行时间轴:跨快照收集全部 attempt,按身份键去重
47
+ * (--resume 携带的复印件不占行),startedAt 升序;缺 startedAt 的行按发现顺序沉底。
48
+ */
49
+ export function attemptHistory(exp: Experiment, evalId: string): AttemptHistoryRow[] {
38
50
  const seen = new Set<string>();
39
- // 旧→新扫描,首次出现的身份键 = 真实执行;最后整体反转成新→旧
40
- for (const snapshot of [...exp.snapshots].reverse()) {
51
+ const dated: AttemptHistoryRow[] = [];
52
+ const undated: AttemptHistoryRow[] = [];
53
+ // 新→旧扫描(exp.snapshots 已按新→旧排序):同一身份键保留最新落盘里的那份
54
+ // (locator 在携带条目上原样复制,取哪份行内容相同;取最新与 dedupeAttempts 口径一致)。
55
+ for (const snapshot of exp.snapshots) {
41
56
  const ev = snapshot.evals.find((e) => e.id === evalId);
42
57
  if (!ev) continue;
43
- const fresh: AttemptHandle[] = [];
44
58
  for (const attempt of ev.attempts) {
45
59
  const key = attemptKey(attempt);
46
- if (key === undefined) {
47
- fresh.push(attempt);
48
- continue;
60
+ if (key !== undefined) {
61
+ if (seen.has(key)) continue;
62
+ seen.add(key);
49
63
  }
50
- if (seen.has(key)) continue;
51
- seen.add(key);
52
- fresh.push(attempt);
53
- }
54
- if (fresh.length === 0) continue; // 纯复印件:判定在更早的行里已经出现过
55
- let cost: number | null = null;
56
- for (const attempt of fresh) {
57
- const c = attemptCostUSD(attempt.result);
58
- if (c !== null) cost = (cost ?? 0) + c;
64
+ const r = attempt.result;
65
+ const row: AttemptHistoryRow = {
66
+ ...(r.startedAt !== undefined ? { startedAt: r.startedAt } : {}),
67
+ verdict: r.verdict,
68
+ ...(rowSummary(r) !== undefined ? { summary: rowSummary(r) } : {}),
69
+ durationMs: r.durationMs,
70
+ costUSD: attemptCostUSD(r),
71
+ ...(attempt.locator !== undefined ? { locator: attempt.locator } : {}),
72
+ };
73
+ (row.startedAt === undefined ? undated : dated).push(row);
59
74
  }
60
- const latest = fresh[fresh.length - 1];
61
- const failed = latest.result.assertions.find((a) => !a.passed);
62
- rows.push({
63
- startedAt: snapshot.startedAt,
64
- verdict: foldEvalVerdict(fresh.map((a) => a.result)),
65
- attempts: fresh.length,
66
- costUSD: cost,
67
- ...(failed ? { failedAssertion: `${failed.severity} ${failed.name}` } : {}),
68
- ...(latest.result.error !== undefined ? { error: latest.result.error } : {}),
69
- });
70
75
  }
71
- return rows.reverse();
72
- }
73
-
74
- export interface ExperimentHistoryRow {
75
- startedAt: string;
76
- passedEvals: number;
77
- totalEvals: number;
78
- costUSD: number | null;
79
- }
80
-
81
- /** 实验级 per-run 通过率序列(裸 `show --history`):每个快照一行,新→旧。 */
82
- export function experimentHistory(exp: Experiment): ExperimentHistoryRow[] {
83
- return exp.snapshots.map((snapshot) => {
84
- let passed = 0;
85
- for (const ev of snapshot.evals) {
86
- if (foldEvalVerdict(ev.attempts.map((a) => a.result)) === "passed") passed += 1;
87
- }
88
- let cost: number | null = null;
89
- for (const attempt of snapshot.attempts) {
90
- const c = attemptCostUSD(attempt.result);
91
- if (c !== null) cost = (cost ?? 0) + c;
92
- }
93
- return { startedAt: snapshot.startedAt, passedEvals: passed, totalEvals: snapshot.evals.length, costUSD: cost };
94
- });
76
+ dated.sort((a, b) => (a.startedAt! < b.startedAt! ? -1 : a.startedAt! > b.startedAt! ? 1 : 0));
77
+ return [...dated, ...undated.reverse()];
95
78
  }