niceeval 0.6.2 → 0.7.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 (218) hide show
  1. package/INDEX.md +23 -23
  2. package/README.zh.md +6 -6
  3. package/dist/agents/types.d.ts +2 -2
  4. package/dist/i18n/zh-CN.d.ts +3 -3
  5. package/dist/report/aggregate.d.ts +32 -26
  6. package/dist/report/aggregate.js +157 -76
  7. package/dist/report/built-in/index.d.ts +2 -0
  8. package/dist/report/built-in/index.js +8 -0
  9. package/dist/report/components.d.ts +91 -164
  10. package/dist/report/components.js +377 -114
  11. package/dist/report/compute.d.ts +86 -73
  12. package/dist/report/compute.js +592 -432
  13. package/dist/report/flag.d.ts +28 -17
  14. package/dist/report/flag.js +86 -16
  15. package/dist/report/format.d.ts +11 -11
  16. package/dist/report/format.js +17 -15
  17. package/dist/report/index.d.ts +16 -17
  18. package/dist/report/index.js +20 -22
  19. package/dist/report/load.js +3 -2
  20. package/dist/report/locale.d.ts +49 -34
  21. package/dist/report/locale.js +106 -58
  22. package/dist/report/metrics.d.ts +10 -3
  23. package/dist/report/metrics.js +46 -12
  24. package/dist/report/primitives.d.ts +42 -15
  25. package/dist/report/primitives.js +135 -26
  26. package/dist/report/react/AttemptList.d.ts +10 -8
  27. package/dist/report/react/AttemptList.js +18 -10
  28. package/dist/report/react/DeltaTable.js +19 -18
  29. package/dist/report/react/EvalList.d.ts +3 -3
  30. package/dist/report/react/EvalList.js +0 -0
  31. package/dist/report/react/ExperimentComparison.d.ts +4 -2
  32. package/dist/report/react/ExperimentComparison.js +5 -4
  33. package/dist/report/react/ExperimentList.d.ts +3 -3
  34. package/dist/report/react/ExperimentList.js +16 -15
  35. package/dist/report/react/MetricBars.js +5 -4
  36. package/dist/report/react/MetricLine.js +12 -5
  37. package/dist/report/react/MetricMatrix.js +1 -1
  38. package/dist/report/react/MetricScatter.js +54 -17
  39. package/dist/report/react/MetricTable.js +2 -12
  40. package/dist/report/react/ScopeSummary.d.ts +10 -0
  41. package/dist/report/react/ScopeSummary.js +17 -0
  42. package/dist/report/react/Scoreboard.js +6 -6
  43. package/dist/report/react/cell.js +2 -2
  44. package/dist/report/react/fixtures.d.ts +5 -9
  45. package/dist/report/react/fixtures.js +105 -149
  46. package/dist/report/react/index.d.ts +15 -5
  47. package/dist/report/react/index.js +18 -7
  48. package/dist/report/report.d.ts +137 -20
  49. package/dist/report/report.js +261 -34
  50. package/dist/report/text/faces.d.ts +17 -19
  51. package/dist/report/text/faces.js +225 -157
  52. package/dist/report/text/plot.js +1 -1
  53. package/dist/report/text/table.js +2 -2
  54. package/dist/report/tree.d.ts +90 -40
  55. package/dist/report/tree.js +252 -94
  56. package/dist/report/types.d.ts +245 -300
  57. package/dist/report/types.js +4 -3
  58. package/dist/report/web.d.ts +21 -5
  59. package/dist/report/web.js +42 -16
  60. package/dist/results/select.d.ts +38 -16
  61. package/dist/results/select.js +73 -25
  62. package/dist/results/types.d.ts +38 -14
  63. package/dist/shared/aggregate.d.ts +3 -2
  64. package/dist/shared/aggregate.js +5 -4
  65. package/docs-site/zh/README.md +44 -0
  66. package/docs-site/zh/examples/ai-agent-application.mdx +63 -0
  67. package/docs-site/zh/examples/coding-agent-extensions.mdx +57 -0
  68. package/docs-site/zh/examples/index.mdx +50 -0
  69. package/docs-site/zh/{concepts → explanation}/adapter.mdx +11 -11
  70. package/docs-site/zh/{concepts → explanation}/assert.mdx +7 -7
  71. package/docs-site/zh/{concepts → explanation}/drive.mdx +8 -8
  72. package/docs-site/zh/{concepts → explanation}/evals.mdx +4 -4
  73. package/docs-site/zh/{concepts → explanation}/experiment.mdx +8 -8
  74. package/docs-site/zh/{concepts → explanation}/hitl.mdx +8 -8
  75. package/docs-site/zh/{concepts → explanation}/judge.mdx +5 -5
  76. package/docs-site/zh/{concepts → explanation}/overview.mdx +5 -5
  77. package/docs-site/zh/{guides → explanation}/runner.mdx +1 -1
  78. package/docs-site/zh/{concepts → explanation}/tier.mdx +6 -6
  79. package/docs-site/zh/{guides → how-to}/agent-feedback-loop.mdx +7 -7
  80. package/docs-site/zh/{guides → how-to}/authoring.mdx +2 -2
  81. package/docs-site/zh/{guides → how-to}/connect-otel.mdx +6 -6
  82. package/docs-site/zh/{guides → how-to}/connect-your-agent.mdx +18 -18
  83. package/docs-site/zh/{guides → how-to}/custom-reports.mdx +6 -6
  84. package/docs-site/zh/{guides → how-to}/experiments.mdx +3 -3
  85. package/docs-site/zh/{guides → how-to}/publish-report.mdx +2 -2
  86. package/docs-site/zh/{guides → how-to}/sandbox-agent.mdx +2 -2
  87. package/docs-site/zh/{guides → how-to}/sandbox-providers.mdx +1 -1
  88. package/docs-site/zh/{guides → how-to}/viewing-results.mdx +6 -6
  89. package/docs-site/zh/{guides → how-to}/write-experiment.mdx +3 -3
  90. package/docs-site/zh/{guides → how-to}/write-send.mdx +13 -13
  91. package/docs-site/zh/index.mdx +23 -25
  92. package/docs-site/zh/introduction.mdx +8 -8
  93. package/docs-site/zh/reference/builtin-agents.mdx +5 -5
  94. package/docs-site/zh/reference/capabilities.mdx +6 -6
  95. package/docs-site/zh/reference/cli.mdx +9 -7
  96. package/docs-site/zh/reference/define-agent.mdx +1 -1
  97. package/docs-site/zh/reference/events.mdx +3 -3
  98. package/docs-site/zh/{guides → reference}/official-adapters.mdx +7 -7
  99. package/docs-site/zh/{guides → reference}/report-components.mdx +5 -5
  100. package/docs-site/zh/{guides → reference}/results-data.mdx +5 -5
  101. package/docs-site/zh/{guides → troubleshooting}/debug-sandbox.mdx +2 -2
  102. package/docs-site/zh/{guides → troubleshooting}/debugging.mdx +4 -2
  103. package/docs-site/zh/{quickstart.mdx → tutorials/quickstart.mdx} +5 -17
  104. package/package.json +6 -2
  105. package/src/agents/index.ts +2 -2
  106. package/src/agents/openai-compat.ts +1 -1
  107. package/src/agents/streaming.ts +2 -2
  108. package/src/agents/types.ts +3 -3
  109. package/src/cli.ts +42 -23
  110. package/src/context/context.ts +1 -1
  111. package/src/context/session.test.ts +1 -1
  112. package/src/context/session.ts +1 -1
  113. package/src/i18n/en.ts +18 -16
  114. package/src/i18n/zh-CN.ts +16 -15
  115. package/src/report/aggregate.ts +175 -87
  116. package/src/report/built-in/index.tsx +9 -0
  117. package/src/report/components.tsx +625 -285
  118. package/src/report/compute.ts +717 -515
  119. package/src/report/dual-render.test.tsx +738 -1148
  120. package/src/report/flag.ts +97 -33
  121. package/src/report/format.ts +18 -22
  122. package/src/report/index.ts +113 -58
  123. package/src/report/load.ts +3 -2
  124. package/src/report/locale.ts +120 -69
  125. package/src/report/metrics.ts +42 -12
  126. package/src/report/primitives.tsx +190 -45
  127. package/src/report/react/AttemptList.tsx +32 -20
  128. package/src/report/react/DeltaTable.tsx +63 -45
  129. package/src/report/react/EvalList.tsx +0 -0
  130. package/src/report/react/ExperimentComparison.tsx +12 -7
  131. package/src/report/react/ExperimentList.tsx +38 -26
  132. package/src/report/react/MetricBars.tsx +5 -4
  133. package/src/report/react/MetricLine.tsx +13 -8
  134. package/src/report/react/MetricMatrix.tsx +2 -2
  135. package/src/report/react/MetricScatter.tsx +74 -20
  136. package/src/report/react/MetricTable.tsx +4 -76
  137. package/src/report/react/ScopeSummary.tsx +86 -0
  138. package/src/report/react/Scoreboard.tsx +28 -10
  139. package/src/report/react/cell.tsx +2 -2
  140. package/src/report/react/enhance.js +57 -5
  141. package/src/report/react/fixtures.ts +109 -156
  142. package/src/report/react/index.tsx +24 -39
  143. package/src/report/react/render.test.tsx +139 -104
  144. package/src/report/react/styles.css +181 -91
  145. package/src/report/report.test.ts +761 -1031
  146. package/src/report/report.ts +425 -47
  147. package/src/report/text/faces.ts +257 -164
  148. package/src/report/text/plot.ts +1 -1
  149. package/src/report/text/table.ts +2 -2
  150. package/src/report/tree.ts +362 -104
  151. package/src/report/types.ts +257 -287
  152. package/src/report/web.ts +63 -20
  153. package/src/results/attempt-evidence.test.ts +4 -4
  154. package/src/results/attempt-evidence.ts +5 -5
  155. package/src/results/copy.ts +6 -6
  156. package/src/results/host-equivalence.test.ts +26 -14
  157. package/src/results/index.ts +10 -4
  158. package/src/results/open.ts +8 -4
  159. package/src/results/results.test.ts +4 -3
  160. package/src/results/select.ts +104 -34
  161. package/src/results/types.ts +36 -14
  162. package/src/runner/feedback/human.test.ts +1 -1
  163. package/src/runner/run.ts +1 -1
  164. package/src/sandbox/cli-commands.ts +2 -2
  165. package/src/scoring/judge.test.ts +1 -1
  166. package/src/shared/aggregate.ts +5 -4
  167. package/src/show/compose.ts +50 -67
  168. package/src/show/index.ts +107 -56
  169. package/src/show/render.ts +43 -27
  170. package/src/show/report-host.test.ts +188 -0
  171. package/src/show/report-host.ts +375 -0
  172. package/src/show/show.test.ts +86 -36
  173. package/src/view/app/App.test.tsx +69 -0
  174. package/src/view/app/App.tsx +144 -48
  175. package/src/view/app/components/AttemptModal.tsx +324 -63
  176. package/src/view/app/components/CodeView.tsx +10 -4
  177. package/src/view/app/i18n.ts +31 -17
  178. package/src/view/app/lib/artifact-url.ts +14 -3
  179. package/src/view/app/main.tsx +13 -8
  180. package/src/view/app/pages/{RunsPage.tsx → AttemptsPage.tsx} +6 -6
  181. package/src/view/app/types.ts +4 -1
  182. package/src/view/artifact-serving.test.ts +21 -1
  183. package/src/view/client-dist/app.css +1 -1
  184. package/src/view/client-dist/app.js +6 -6
  185. package/src/view/data.test.ts +9 -3
  186. package/src/view/data.ts +145 -49
  187. package/src/view/index.ts +48 -44
  188. package/src/view/server.ts +35 -15
  189. package/src/view/shared/types.ts +34 -5
  190. package/src/view/styles.css +224 -0
  191. package/src/view/view-report.test.ts +161 -57
  192. package/dist/report/built-ins/experiment-comparison.d.ts +0 -39
  193. package/dist/report/built-ins/experiment-comparison.js +0 -119
  194. package/dist/report/built-ins/index.d.ts +0 -2
  195. package/dist/report/built-ins/index.js +0 -2
  196. package/dist/report/react/GroupSummary.d.ts +0 -8
  197. package/dist/report/react/GroupSummary.js +0 -8
  198. package/dist/report/react/RunOverview.d.ts +0 -8
  199. package/dist/report/react/RunOverview.js +0 -12
  200. package/docs-site/zh/example/ai-agent-application.mdx +0 -152
  201. package/docs-site/zh/example/claude-code-codex-plugin.mdx +0 -167
  202. package/docs-site/zh/example/claude-code-codex-skill.mdx +0 -152
  203. package/docs-site/zh/example/showcase.mdx +0 -39
  204. package/src/report/built-in-user-parity.test.tsx +0 -597
  205. package/src/report/built-ins/experiment-comparison.tsx +0 -179
  206. package/src/report/built-ins/index.ts +0 -7
  207. package/src/report/react/GroupSummary.tsx +0 -66
  208. package/src/report/react/RunOverview.tsx +0 -109
  209. /package/docs-site/zh/{example/tier1-ai-sdk-v7.mdx → examples/integrations/ai-sdk-v7.mdx} +0 -0
  210. /package/docs-site/zh/{example/tier1-claude-sdk.mdx → examples/integrations/claude-sdk.mdx} +0 -0
  211. /package/docs-site/zh/{example/tier1-codex-sdk.mdx → examples/integrations/codex-sdk.mdx} +0 -0
  212. /package/docs-site/zh/{example/tier1-langgraph.mdx → examples/integrations/langgraph.mdx} +0 -0
  213. /package/docs-site/zh/{example/tier1-pi-sdk.mdx → examples/integrations/pi-sdk.mdx} +0 -0
  214. /package/docs-site/zh/{guides → how-to}/ci-integration.mdx +0 -0
  215. /package/docs-site/zh/{guides → how-to}/dataset-fanout.mdx +0 -0
  216. /package/docs-site/zh/{guides → how-to}/fixtures.mdx +0 -0
  217. /package/docs-site/zh/{guides → how-to}/reporters.mdx +0 -0
  218. /package/docs-site/zh/{guides → how-to}/scoring-guide.mdx +0 -0
@@ -62,17 +62,6 @@
62
62
  .nre-attempt-list .nre-attempt-duration,
63
63
  .nre-attempt-list .nre-attempt-cost { color:var(--muted); font-size:.9em; font-variant-numeric:tabular-nums; }
64
64
  .nre-attempt-list .nre-attempt-result { display:-webkit-box; overflow:hidden; -webkit-box-orient:vertical; -webkit-line-clamp:2; margin:.4rem 0 0; color:color-mix(in oklch,var(--muted),var(--text) 12%); overflow-wrap:anywhere; }
65
- .nre-attempt-list .nre-attempt-error { margin:.4rem 0 0; padding:6px 10px; border:1px solid color-mix(in oklch,var(--bad),var(--line) 50%); border-radius:7px; background:color-mix(in oklch,var(--bad),var(--panel) 92%); color:var(--bad); font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:.85em; white-space:pre-wrap; word-break:break-word; }
66
- .nre-attempt-list .nre-assertions { list-style:none; margin:.4rem 0 0; padding:0; display:grid; gap:6px; }
67
- .nre-attempt-list .nre-assertion { padding-left:.25rem; }
68
- .nre-attempt-list .nre-assertion-failed { color: var(--bad); }
69
- .nre-attempt-list .nre-assertion-severity { color:var(--soft); font-size:.8em; text-transform:uppercase; letter-spacing:.04em; margin-right:.5em; }
70
- .nre-attempt-list .nre-assertion-name { font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:.92em; }
71
- .nre-attempt-list .nre-assertion-score { color:var(--muted); margin-left:.75em; font-size:.9em; }
72
- .nre-attempt-list .nre-assertion-more summary { cursor:pointer; color:var(--muted); font-size:.85em; user-select:none; }
73
- .nre-attempt-list .nre-assertion-more summary:hover { color:var(--text); }
74
- .nre-attempt-list .nre-assertion-detail { margin:.25rem 0; white-space:pre-wrap; }
75
- .nre-attempt-list .nre-assertion-evidence { margin:.25rem 0 .25rem .75rem; padding-left:.5rem; border-left:2px solid var(--line-strong); color:var(--muted); white-space:pre-wrap; }
76
65
  .nre-attempt-list .nre-truncated { color:var(--warn); font-size:.9em; }
77
66
  .nre-attempt-list .nre-attempt-list-empty { border:1px dashed var(--line-strong); border-radius:8px; padding:18px; color:var(--muted); text-align:center; background:var(--panel); }
78
67
 
@@ -100,10 +89,6 @@
100
89
  outline:2px solid var(--nre-c0);
101
90
  outline-offset:2px;
102
91
  }
103
- .nre-experiment-comparison .nre-experiment-group-tab[aria-selected="true"] {
104
- border-color:var(--nre-c0);
105
- box-shadow:inset 3px 0 0 var(--nre-c0);
106
- }
107
92
  .nre-experiment-comparison .nre-experiment-group-name {
108
93
  display:block;
109
94
  margin-bottom:10px;
@@ -111,17 +96,33 @@
111
96
  font-size:15px;
112
97
  overflow-wrap:anywhere;
113
98
  }
114
- .nre-experiment-comparison .nre-experiment-group-tab .nre-group-kpis {
99
+ /* 组卡里嵌的 ScopeSummary 降为紧凑行:去掉满宽 KPI 条的边框,收小数字 */
100
+ .nre-experiment-comparison .nre-experiment-group-tab .nre-scope-summary { margin:0; }
101
+ .nre-experiment-comparison .nre-experiment-group-tab .nre-scope-kpis {
102
+ display:flex;
103
+ flex-wrap:wrap;
115
104
  column-gap:16px;
116
- }
117
- .nre-experiment-comparison .nre-experiment-group-tab .nre-group-kpi {
105
+ row-gap:6px;
106
+ margin:0 0 6px;
107
+ border:0;
108
+ border-radius:0;
109
+ background:transparent;
110
+ overflow:visible;
111
+ }
112
+ .nre-experiment-comparison .nre-experiment-group-tab .nre-scope-kpi {
118
113
  min-width:58px;
114
+ padding:0;
115
+ border-right:0;
119
116
  }
117
+ .nre-experiment-comparison .nre-experiment-group-tab .nre-scope-kpi dd {
118
+ margin:3px 0 0;
119
+ font-size:16px;
120
+ line-height:1.15;
121
+ font-weight:650;
122
+ }
123
+ .nre-experiment-comparison .nre-experiment-group-tab .nre-scope-kpi-rate dd { font-size:18px; }
120
124
  .nre-experiment-comparison .nre-experiment-group-panel {
121
- border:1px solid var(--line);
122
- border-radius:9px;
123
- padding:16px;
124
- background:var(--panel);
125
+ padding:16px 0;
125
126
  }
126
127
  .nre-experiment-comparison .nre-experiment-group-panel > summary {
127
128
  cursor:pointer;
@@ -135,6 +136,15 @@
135
136
  .nre-experiment-comparison .nre-experiment-group-panel > .nre {
136
137
  margin:0 0 18px;
137
138
  }
139
+ /* group panel 已经是内容的唯一外框;内嵌图表不再重复套一层卡片边框 */
140
+ .nre-experiment-comparison .nre-experiment-group-panel .nre-metric-scatter,
141
+ .nre-experiment-comparison .nre-experiment-group-panel .nre-metric-line,
142
+ .nre-experiment-comparison .nre-experiment-group-panel .nre-metric-bars {
143
+ border:0;
144
+ border-radius:0;
145
+ background:transparent;
146
+ padding:14px 0 8px;
147
+ }
138
148
  .nre-experiment-comparison .nre-experiment-group-panel > .nre:last-child {
139
149
  margin-bottom:0;
140
150
  }
@@ -211,10 +221,8 @@
211
221
  .nre-experiment-list .nre-experiment-list-empty { border:1px dashed var(--line-strong); border-radius:8px; padding:18px; color:var(--muted); text-align:center; background:var(--panel); }
212
222
  @media(max-width:1000px){.nre-experiment-table{overflow-x:auto}.nre-experiment-head,.nre-experiment-summary{min-width:1040px}.nre-experiment-detail{min-width:1040px}}
213
223
 
214
- /* ---- verdict 判定色(AttemptList/EvalList/ExperimentList verdict 文字与判定符共用) ---- */
215
- .nre .nre-verdict-passed { color:var(--good); }
216
- .nre .nre-eval-verdict.nre-verdict-passed,
217
- .nre-attempt-list .nre-attempt-verdict.nre-verdict-passed { color:var(--good); }
224
+ /* ---- verdict 判定色(EvalList/ExperimentList 的判定符;errored 在这里按 bad 收敛) ---- */
225
+ .nre .nre-eval-verdict.nre-verdict-passed { color:var(--good); }
218
226
  .nre .nre-eval-verdict.nre-verdict-failed,
219
227
  .nre .nre-eval-verdict.nre-verdict-errored { color:var(--bad); }
220
228
  .nre .nre-eval-verdict.nre-verdict-skipped { color:var(--soft); }
@@ -272,14 +280,6 @@ table.nre,
272
280
  .nre tbody th[scope="row"] {
273
281
  font-weight: 610;
274
282
  }
275
- /* rows: "experiment" 专属:行键下的紧凑摘要(eval/attempt 数、最后运行时间) */
276
- .nre .nre-row-meta-sub {
277
- margin-top: 2px;
278
- color: var(--muted);
279
- font-weight: 400;
280
- font-size: 0.82em;
281
- font-variant-numeric: tabular-nums;
282
- }
283
283
  .nre td {
284
284
  font-variant-numeric: tabular-nums;
285
285
  font-feature-settings: "tnum";
@@ -363,6 +363,11 @@ table.nre,
363
363
  .nre .nre-td-empty {
364
364
  background: var(--panel-2);
365
365
  }
366
+ /* 数据侧没给的格子:呈现层画软色缺失符,不进 textContent、不参与排序取值 */
367
+ .nre .nre-empty::before {
368
+ content: "—";
369
+ color: var(--soft);
370
+ }
366
371
 
367
372
  /* ---- verdict 语义色与计票 pill ---- */
368
373
  .nre .nre-verdict-passed { color: var(--good); }
@@ -389,8 +394,9 @@ table.nre,
389
394
  .nre .nre-verdict-pill.nre-verdict-failed { border-color: color-mix(in oklch, var(--bad), var(--line) 55%); }
390
395
  .nre .nre-verdict-pill.nre-verdict-errored { border-color: color-mix(in oklch, var(--warn), var(--line) 55%); }
391
396
 
392
- /* ---- RunOverview:KPI 条(对齐 view 的 .summary/.metric 密度) ---- */
393
- .nre-overview .nre-kpis {
397
+ /* ---- ScopeSummary:范围摘要卡,满宽 KPI 条(对齐 view 的 .summary/.metric 密度);
398
+ 嵌进 ExperimentComparison 组卡时降为紧凑行(规则在上面的比较块里) ---- */
399
+ .nre-scope-summary .nre-scope-kpis {
394
400
  display: grid;
395
401
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
396
402
  border: 1px solid var(--line);
@@ -399,19 +405,19 @@ table.nre,
399
405
  margin: 0 0 10px;
400
406
  background: var(--panel);
401
407
  }
402
- .nre-overview .nre-kpi {
408
+ .nre-scope-summary .nre-scope-kpi {
403
409
  padding: 12px 16px 13px;
404
410
  border-right: 1px solid var(--line);
405
411
  min-width: 0;
406
412
  }
407
- .nre-overview .nre-kpi:last-child { border-right: 0; }
408
- .nre-overview .nre-kpi dt {
413
+ .nre-scope-summary .nre-scope-kpi:last-child { border-right: 0; }
414
+ .nre-scope-summary .nre-scope-kpi dt {
409
415
  color: var(--soft);
410
416
  font-size: 11px;
411
417
  text-transform: uppercase;
412
418
  letter-spacing: 0.08em;
413
419
  }
414
- .nre-overview .nre-kpi dd {
420
+ .nre-scope-summary .nre-scope-kpi dd {
415
421
  margin: 6px 0 0;
416
422
  font-size: 20px;
417
423
  line-height: 1;
@@ -419,25 +425,21 @@ table.nre,
419
425
  font-variant-numeric: tabular-nums;
420
426
  white-space: nowrap;
421
427
  }
422
- .nre-overview .nre-verdicts {
423
- margin: 0.25rem 0;
424
- color: var(--muted);
425
- font-variant-numeric: tabular-nums;
426
- }
427
- .nre-overview .nre-verdict {
428
- margin-right: 1em;
428
+ /* 计票格装的是 pill 组:允许换行,行高回到常规 */
429
+ .nre-scope-summary .nre-scope-kpi-verdicts dd {
430
+ white-space: normal;
431
+ line-height: 1.4;
429
432
  }
430
- .nre-overview .nre-source {
433
+ .nre .nre-scope-summary-range {
431
434
  color: var(--soft);
432
435
  font-size: 0.85em;
433
- margin: 0.25rem 0;
434
- }
435
- .nre-overview .nre-source-snapshot {
436
- margin-left: 0.75em;
436
+ margin: 0.25rem 0 0;
437
437
  }
438
+
439
+ /* ---- 宿主警告块:.nre-report-warnings 外壳 + ul.nre-warnings + li.nre-warning[data-kind] ---- */
438
440
  .nre .nre-warnings {
439
441
  list-style: none;
440
- margin: 0.5rem 0 0;
442
+ margin: 0;
441
443
  padding: 10px 14px;
442
444
  border: 1px solid color-mix(in oklch, var(--warn), var(--line) 45%);
443
445
  border-left: 3px solid var(--warn);
@@ -446,37 +448,26 @@ table.nre,
446
448
  color: var(--text);
447
449
  font-size: 13px;
448
450
  }
449
-
450
- /* ---- GroupSummary:组摘要块(嵌在 Section 内的紧凑统计,不是 RunOverview 那种满宽页头 KPI 条)---- */
451
- .nre-group-summary .nre-group-kpis {
452
- display: flex;
453
- flex-wrap: wrap;
454
- column-gap: 22px;
455
- row-gap: 6px;
456
- margin: 0 0 6px;
457
- }
458
- .nre-group-summary .nre-group-kpi {
459
- min-width: 68px;
460
- }
461
- .nre-group-summary .nre-group-kpi dt {
462
- color: var(--soft);
463
- font-size: 11px;
464
- text-transform: uppercase;
465
- letter-spacing: 0.08em;
466
- }
467
- .nre-group-summary .nre-group-kpi dd {
468
- margin: 3px 0 0;
469
- font-size: 16px;
470
- line-height: 1.15;
471
- font-weight: 650;
472
- font-variant-numeric: tabular-nums;
473
- white-space: nowrap;
474
- }
475
- .nre-group-summary .nre-group-kpi-rate dd { font-size: 18px; }
476
- .nre-group-summary-time {
477
- color: var(--soft);
478
- font-size: 0.85em;
479
- margin: 0 0 0.75rem;
451
+ .nre .nre-warning + .nre-warning { margin-top: 8px; }
452
+ /* 警告携带的下一步命令:等宽块,无 JS 时点击即全选;enhance.js 在场时点击复制 */
453
+ .nre .nre-warning-command {
454
+ display: block;
455
+ margin-top: 6px;
456
+ padding: 6px 10px;
457
+ border: 1px solid var(--line);
458
+ border-radius: 7px;
459
+ background: var(--panel);
460
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
461
+ font-size: 0.9em;
462
+ overflow-wrap: anywhere;
463
+ user-select: all;
464
+ }
465
+ :root.nre-js .nre .nre-warning-command { cursor: copy; }
466
+ :root.nre-js .nre .nre-warning-command:hover { border-color: var(--line-strong); }
467
+ .nre .nre-warning-command[data-nre-copied]::after {
468
+ content: "✓";
469
+ margin-left: 0.6em;
470
+ color: var(--good);
480
471
  }
481
472
 
482
473
  /* ---- MetricMatrix ---- */
@@ -501,10 +492,23 @@ table.nre,
501
492
  font-weight: 400;
502
493
  margin-left: 0.25em;
503
494
  }
504
- .nre-scoreboard .nre-subject-missing {
495
+ /* 两种 0 分的注脚分开着色:没去考(notRun)偏警示,考了判不了(unscorable)偏软 */
496
+ .nre-scoreboard .nre-total-not-run,
497
+ .nre-scoreboard .nre-total-unscorable,
498
+ .nre-scoreboard .nre-subject-not-run,
499
+ .nre-scoreboard .nre-subject-unscorable {
505
500
  display: block;
506
- color: var(--warn);
507
501
  font-size: 0.8em;
502
+ font-weight: 400;
503
+ }
504
+ .nre-scoreboard .nre-total-not-run,
505
+ .nre-scoreboard .nre-subject-not-run { color: var(--warn); }
506
+ .nre-scoreboard .nre-total-unscorable,
507
+ .nre-scoreboard .nre-subject-unscorable { color: var(--soft); }
508
+ .nre-scoreboard .nre-scoreboard-ignored {
509
+ color: var(--muted);
510
+ font-size: 0.85em;
511
+ margin: 0.25rem 0 0;
508
512
  }
509
513
  .nre-scoreboard .nre-weights {
510
514
  color: var(--muted);
@@ -633,11 +637,21 @@ table.nre,
633
637
  color: var(--soft);
634
638
  font-size: 0.8em;
635
639
  }
636
- .nre .nre-delta-good { color: var(--good); }
637
- .nre .nre-delta-bad { color: var(--bad); }
638
- .nre .nre-delta-flat { color: var(--muted); }
639
- .nre .nre-delta-neutral { color: var(--text); }
640
- .nre .nre-delta-missing { color: var(--soft); }
640
+ /* Δ 行按数据侧算好的 outcome 着色:涨跌好坏不由正负号决定 */
641
+ .nre .nre-delta-d[data-outcome="improved"] { color: var(--good); }
642
+ .nre .nre-delta-d[data-outcome="regressed"] { color: var(--bad); }
643
+ .nre .nre-delta-d[data-outcome="unchanged"] { color: var(--muted); }
644
+ .nre .nre-delta-d[data-outcome="unavailable"] { color: var(--soft); }
645
+ /* 0 对不是错误:明确空态,与各列表 empty 同一姿势 */
646
+ .nre-delta-table-empty {
647
+ border: 1px dashed var(--line-strong);
648
+ border-radius: 8px;
649
+ padding: 18px;
650
+ color: var(--muted);
651
+ text-align: center;
652
+ background: var(--panel);
653
+ }
654
+ .nre-delta-table-empty .nre-missing { margin: 0; }
641
655
 
642
656
  /* ---- 排版原语 Row / Col / Section / Text ---- */
643
657
  .nre-col {
@@ -667,3 +681,79 @@ table.nre,
667
681
  color: var(--muted);
668
682
  margin: 0.25rem 0;
669
683
  }
684
+
685
+ /* ---- Tabs:静态 HTML 每 tab 一个 <details> 且仅首个 open(无 JS = 手风琴卡片,内容完整);
686
+ enhance.js 在 <html> 上打 nre-js 后升级为单选 tab 条:收起的 tab 缩成一枚标题排在首行,
687
+ 唯一展开的 tab 以 100% 宽 + order:1 换行到下方,活动标题带高亮下划线、贴着面板顶部。
688
+ 不能用 display:contents 把 summary/body 直接投影进 flex 容器——Chrome 里 <details> 的
689
+ UA shadow slot 会成为 flex item,子元素的 order 失效、收起面板还留 0 宽盒 ---- */
690
+ .nre-tabs > .nre-tab {
691
+ border: 1px solid var(--line);
692
+ border-radius: 8px;
693
+ background: var(--panel);
694
+ margin-bottom: 8px;
695
+ }
696
+ .nre-tabs > .nre-tab > .nre-tab-title {
697
+ padding: 10px 14px;
698
+ cursor: pointer;
699
+ user-select: none;
700
+ font-weight: 620;
701
+ list-style: none;
702
+ }
703
+ .nre-tabs > .nre-tab > .nre-tab-title::-webkit-details-marker { display: none; }
704
+ .nre-tabs > .nre-tab > .nre-tab-title::before {
705
+ content: "";
706
+ display: inline-block;
707
+ width: 7px;
708
+ height: 7px;
709
+ margin-right: 10px;
710
+ border-right: 1.5px solid var(--muted);
711
+ border-bottom: 1.5px solid var(--muted);
712
+ transform: rotate(-45deg);
713
+ transition: transform 0.15s;
714
+ vertical-align: 1px;
715
+ }
716
+ .nre-tabs > .nre-tab[open] > .nre-tab-title::before { transform: rotate(45deg); }
717
+ .nre-tabs > .nre-tab > .nre-tab-body { padding: 2px 14px 12px; }
718
+ .nre-tabs .nre-tab-body > .nre:first-child { margin-top: 0; }
719
+ .nre-tabs .nre-tab-body > .nre:last-child { margin-bottom: 0; }
720
+
721
+ :root.nre-js .nre-tabs {
722
+ display: flex;
723
+ flex-wrap: wrap;
724
+ align-items: stretch;
725
+ column-gap: 2px;
726
+ }
727
+ :root.nre-js .nre-tabs > .nre-tab {
728
+ margin: 0;
729
+ border: 0;
730
+ border-radius: 0;
731
+ background: transparent;
732
+ flex: 0 0 auto;
733
+ min-width: 0;
734
+ }
735
+ :root.nre-js .nre-tabs > .nre-tab[open] {
736
+ flex: 1 1 100%;
737
+ order: 1;
738
+ }
739
+ :root.nre-js .nre-tabs > .nre-tab > .nre-tab-title {
740
+ padding: 8px 14px 9px;
741
+ border-radius: 7px 7px 0 0;
742
+ color: var(--muted);
743
+ font-weight: 560;
744
+ box-shadow: inset 0 -1px 0 var(--line);
745
+ }
746
+ :root.nre-js .nre-tabs > .nre-tab > .nre-tab-title::before { content: none; }
747
+ :root.nre-js .nre-tabs > .nre-tab > .nre-tab-title:hover {
748
+ color: var(--text);
749
+ background: color-mix(in oklch, var(--panel-2), var(--panel) 35%);
750
+ }
751
+ :root.nre-js .nre-tabs > .nre-tab[open] > .nre-tab-title {
752
+ width: max-content;
753
+ max-width: 100%;
754
+ color: var(--text);
755
+ font-weight: 650;
756
+ box-shadow: inset 0 -2px 0 var(--nre-c0);
757
+ cursor: default;
758
+ }
759
+ :root.nre-js .nre-tabs > .nre-tab > .nre-tab-body { padding: 14px 0 0; }