reeval 0.10.0 → 0.11.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 (211) hide show
  1. package/README.md +62 -39
  2. package/THIRD_PARTY_NOTICES.md +75 -106
  3. package/dist/{adapter-DWlpOtRn.js → adapter-Bwy3QxAK.js} +2 -2
  4. package/dist/{adapter-DWlpOtRn.js.map → adapter-Bwy3QxAK.js.map} +1 -1
  5. package/dist/{agent-CURAwx_q.js → agent-D483ru7D.js} +5 -5
  6. package/dist/{agent-CURAwx_q.js.map → agent-D483ru7D.js.map} +1 -1
  7. package/dist/{agent-CaS_2Sce.js → agent-DpE80WPz.js} +4 -4
  8. package/dist/{agent-CaS_2Sce.js.map → agent-DpE80WPz.js.map} +1 -1
  9. package/dist/assemble-D5KGrwnJ.js +1 -0
  10. package/dist/{assemble-B9Alds-z.js → assemble-D9GWr-HS.js} +8 -8
  11. package/dist/{assemble-B9Alds-z.js.map → assemble-D9GWr-HS.js.map} +1 -1
  12. package/dist/bridge/index.mjs +13 -6
  13. package/dist/{capture-CNb9SuU5.js → capture-BQlGHiMC.js} +5 -5
  14. package/dist/{capture-CNb9SuU5.js.map → capture-BQlGHiMC.js.map} +1 -1
  15. package/dist/capture-CYGLpWxR.js +1 -0
  16. package/dist/{cli-D303Vj5N.js → cli-ClpPT8kn.js} +166 -492
  17. package/dist/cli-ClpPT8kn.js.map +1 -0
  18. package/dist/{cli-spec-BPZbQG2p.js → cli-spec-qmEnQ25_.js} +15 -6
  19. package/dist/cli-spec-qmEnQ25_.js.map +1 -0
  20. package/dist/cli.js +2 -2
  21. package/dist/{command-Bge8F7Ko.js → command-Bj39y-Wm.js} +33 -24
  22. package/dist/command-Bj39y-Wm.js.map +1 -0
  23. package/dist/{command-CMJtHKRa.js → command-BlM0y8jN.js} +6 -6
  24. package/dist/{command-CMJtHKRa.js.map → command-BlM0y8jN.js.map} +1 -1
  25. package/dist/command-C-cVjlny.js +1 -0
  26. package/dist/{command-BLfT7vnQ.js → command-DbAe1Rzb.js} +10 -11
  27. package/dist/command-DbAe1Rzb.js.map +1 -0
  28. package/dist/{command-BT9a37ZR.js → command-TgbzPizb.js} +15 -13
  29. package/dist/command-TgbzPizb.js.map +1 -0
  30. package/dist/{commands-1p-bIWhN.js → commands-CthqwkAn.js} +1 -1
  31. package/dist/{commands-BFx16WB8.js → commands-YUwlyTbr.js} +12 -9
  32. package/dist/commands-YUwlyTbr.js.map +1 -0
  33. package/dist/{config-DEgnUiU-.js → config-DrVSEVN0.js} +29 -11
  34. package/dist/config-DrVSEVN0.js.map +1 -0
  35. package/dist/contrasts-5zsj32gk.js +101 -0
  36. package/dist/contrasts-5zsj32gk.js.map +1 -0
  37. package/dist/db-CKg5NtiW.js +2 -0
  38. package/dist/{db-CdHizc4_.js → db-DfhipHEF.js} +17 -7
  39. package/dist/{db-CdHizc4_.js.map → db-DfhipHEF.js.map} +1 -1
  40. package/dist/{dist-B8hJImYt.js → dist-CuY4ehEk.js} +81 -14
  41. package/dist/dist-CuY4ehEk.js.map +1 -0
  42. package/dist/{docker-7b_2SaH7.js → docker-D1HZDS6q.js} +4 -4
  43. package/dist/{docker-7b_2SaH7.js.map → docker-D1HZDS6q.js.map} +1 -1
  44. package/dist/{docker-yauK-9X8.js → docker-DNmMPOBb.js} +1 -1
  45. package/dist/{docker-sZrNrr82.js → docker-DOvjji9I.js} +2 -2
  46. package/dist/{docker-sZrNrr82.js.map → docker-DOvjji9I.js.map} +1 -1
  47. package/dist/{doctor-BYNok4UO.js → doctor-D2MbNO8L.js} +14 -15
  48. package/dist/doctor-D2MbNO8L.js.map +1 -0
  49. package/dist/{egress-C4PZTSSe.js → egress-2-qzPvGi.js} +12 -13
  50. package/dist/egress-2-qzPvGi.js.map +1 -0
  51. package/dist/{environment-DNjRk0nU.js → environment-Cca6a4wB.js} +2 -3
  52. package/dist/environment-Cca6a4wB.js.map +1 -0
  53. package/dist/{evaluate-D4zeRGBF.js → evaluate-DKIl54Hb.js} +14 -17
  54. package/dist/evaluate-DKIl54Hb.js.map +1 -0
  55. package/dist/{evaluate-C1UVL21l.d.ts → evaluate-DMyaGQEj.d.ts} +2 -2
  56. package/dist/{files-DQmHE7pb.js → files-BXHZFWmx.js} +2 -2
  57. package/dist/{files-DQmHE7pb.js.map → files-BXHZFWmx.js.map} +1 -1
  58. package/dist/{files-BXUdY8tr.js → files-BpUYBwGu.js} +5 -5
  59. package/dist/{files-BXUdY8tr.js.map → files-BpUYBwGu.js.map} +1 -1
  60. package/dist/files-Bw8lWEjg.js +1 -0
  61. package/dist/files-D6J0iSdx.js +1 -0
  62. package/dist/{git-DfG-YJ1u.js → git-Crl3b87o.js} +2 -2
  63. package/dist/{git-DfG-YJ1u.js.map → git-Crl3b87o.js.map} +1 -1
  64. package/dist/{harness-B8QC9u0O.js → harness-CEuntrla.js} +2 -2
  65. package/dist/{harness-B8QC9u0O.js.map → harness-CEuntrla.js.map} +1 -1
  66. package/dist/harness.d.ts +1 -1
  67. package/dist/harness.js +1 -1
  68. package/dist/{header-hK-Z_Po9.js → header-DHQv_ZrF.js} +2 -2
  69. package/dist/{header-hK-Z_Po9.js.map → header-DHQv_ZrF.js.map} +1 -1
  70. package/dist/{images-0On0cztu.js → images-Bi3aGxb9.js} +6 -6
  71. package/dist/{images-0On0cztu.js.map → images-Bi3aGxb9.js.map} +1 -1
  72. package/dist/index.d.ts +2 -2
  73. package/dist/index.js +4 -4
  74. package/dist/{init-B77Rpcqc.js → init-Cl3f3NBT.js} +4 -4
  75. package/dist/{init-B77Rpcqc.js.map → init-Cl3f3NBT.js.map} +1 -1
  76. package/dist/init-fhOXED8F.js +1 -0
  77. package/dist/{invocations-DbGfBAA_.js → invocations-BYDPe3fV.js} +2 -2
  78. package/dist/{invocations-DbGfBAA_.js.map → invocations-BYDPe3fV.js.map} +1 -1
  79. package/dist/judge.d.ts +1 -1
  80. package/dist/{model-NM3ID0uR.js → model-CXhrziBe.js} +1 -1
  81. package/dist/{model-h_cDtcRr.js → model-D0IcOQao.js} +5 -4
  82. package/dist/model-D0IcOQao.js.map +1 -0
  83. package/dist/{model-oqcDplJG.js → model-DaX4bNLZ.js} +17 -8
  84. package/dist/model-DaX4bNLZ.js.map +1 -0
  85. package/dist/model-_bxNrk2h.js +1 -0
  86. package/dist/{options-Bh2W63dK.js → options-C0d0AzeR.js} +6 -7
  87. package/dist/options-C0d0AzeR.js.map +1 -0
  88. package/dist/{patch-Zac5aIRM.js → patch-B1bnfhN-.js} +2 -2
  89. package/dist/{patch-Zac5aIRM.js.map → patch-B1bnfhN-.js.map} +1 -1
  90. package/dist/{plan-C9Cy27Ay.js → plan-DgQxp9yy.js} +13 -7
  91. package/dist/plan-DgQxp9yy.js.map +1 -0
  92. package/dist/{preflight-D7iFPKeK.js → preflight-BRzD30L5.js} +3 -3
  93. package/dist/{preflight-D7iFPKeK.js.map → preflight-BRzD30L5.js.map} +1 -1
  94. package/dist/{preflight-CPWpQeBI.js → preflight-DlQvbySb.js} +1 -1
  95. package/dist/{prepare-doGxaAGR.js → prepare-B_y-AFMv.js} +6 -6
  96. package/dist/{prepare-doGxaAGR.js.map → prepare-B_y-AFMv.js.map} +1 -1
  97. package/dist/{prepare-BGjePFQl.js → prepare-DCKTLHN3.js} +2 -2
  98. package/dist/{provenance-DmE9uPVt.js → provenance-DQ0AXn6c.js} +3 -3
  99. package/dist/{provenance-DmE9uPVt.js.map → provenance-DQ0AXn6c.js.map} +1 -1
  100. package/dist/{providers-gDMko8fl.js → providers-B9yTdIqF.js} +1 -1
  101. package/dist/{providers-tAOD1NQN.js → providers-DoTq1jHW.js} +4 -4
  102. package/dist/{providers-tAOD1NQN.js.map → providers-DoTq1jHW.js.map} +1 -1
  103. package/dist/query-BO-ux7RB.js +139 -0
  104. package/dist/query-BO-ux7RB.js.map +1 -0
  105. package/dist/query-CRQfsw0e.js +1 -0
  106. package/dist/{questions-DjAwMxZ3.js → questions-C2dym2ce.js} +3 -3
  107. package/dist/{questions-DjAwMxZ3.js.map → questions-C2dym2ce.js.map} +1 -1
  108. package/dist/{remote-HDRt16ew.js → remote-CPPW86Q9.js} +3 -3
  109. package/dist/{remote-HDRt16ew.js.map → remote-CPPW86Q9.js.map} +1 -1
  110. package/dist/{results-DuauQI3Z.js → results-BE2f-1XS.js} +6 -5
  111. package/dist/results-BE2f-1XS.js.map +1 -0
  112. package/dist/{resume-BRfa8E_s.js → resume-Ca1c8vix.js} +3 -3
  113. package/dist/{resume-BRfa8E_s.js.map → resume-Ca1c8vix.js.map} +1 -1
  114. package/dist/{sandbox-D3A8oUb7.js → sandbox-DLrsvu7U.js} +2 -2
  115. package/dist/{sandbox-D3A8oUb7.js.map → sandbox-DLrsvu7U.js.map} +1 -1
  116. package/dist/sandbox.d.ts +1 -1
  117. package/dist/sandbox.js +1 -1
  118. package/dist/server-Dp8eOeK5.js +1 -0
  119. package/dist/{server-XDleKaF_.js → server-TUY5xA_A.js} +6 -6
  120. package/dist/{server-XDleKaF_.js.map → server-TUY5xA_A.js.map} +1 -1
  121. package/dist/{shared-DYpIb1BI.js → shared-CA61BuPJ.js} +25 -3
  122. package/dist/shared-CA61BuPJ.js.map +1 -0
  123. package/dist/{source-C8xumIWj.js → source-DJGS0a0u.js} +2 -2
  124. package/dist/{source-C8xumIWj.js.map → source-DJGS0a0u.js.map} +1 -1
  125. package/dist/source-DdbLGR1M.js +1 -0
  126. package/dist/{src-C_lPtowT.js → src-BxfCKA3_.js} +1 -1
  127. package/dist/{src-ofUaYbuY.js → src-CLoOMVWI.js} +1 -1
  128. package/dist/{src-Du8H85Qq.js → src-CcrQbpG8.js} +1 -1
  129. package/dist/{src-Dj9PAroc.js → src-DCFtJRp0.js} +1 -1
  130. package/dist/{src-jzagbuqH.js → src-DSYYPEOj.js} +1 -1
  131. package/dist/src-DYO3DdnQ.js +1 -0
  132. package/dist/{src-DTbrY1hi.js → src-WD-zgQYZ.js} +1 -1
  133. package/dist/{src-DNnG4e4R.js → src-_oI9AePb.js} +1 -1
  134. package/dist/{src-B7treWa8.js → src-ftu5wPSt.js} +127 -15
  135. package/dist/src-ftu5wPSt.js.map +1 -0
  136. package/dist/{src-DdyJEh2v.js → src-qsKCqv7a.js} +1 -1
  137. package/dist/{state-C__9swoG.js → state-DfpHox6b.js} +3 -3
  138. package/dist/{state-C__9swoG.js.map → state-DfpHox6b.js.map} +1 -1
  139. package/dist/state-DpAxYyED.js +1 -0
  140. package/dist/studio-app/assets/index-CBkhNAv8.js +58 -0
  141. package/dist/studio-app/index.html +1 -1
  142. package/dist/suite-Cw_7G2RM.js +429 -0
  143. package/dist/suite-Cw_7G2RM.js.map +1 -0
  144. package/dist/suite-DamAEnNF.js +1 -0
  145. package/dist/summary-BUKfU-9l.js +611 -0
  146. package/dist/summary-BUKfU-9l.js.map +1 -0
  147. package/dist/{summary-DgyjUh_l.js → summary-Baa4rTHS.js} +6 -6
  148. package/dist/{summary-DgyjUh_l.js.map → summary-Baa4rTHS.js.map} +1 -1
  149. package/dist/testing.d.ts +2 -2
  150. package/dist/testing.js +2 -2
  151. package/dist/{tools-GCyNYSc1.js → tools-DLHgetpx.js} +3 -3
  152. package/dist/{tools-GCyNYSc1.js.map → tools-DLHgetpx.js.map} +1 -1
  153. package/dist/{types-g17bRAzt.d.ts → types-BYdlwMwo.d.ts} +12 -7
  154. package/dist/view/index.d.ts +250 -2
  155. package/dist/view/index.js +4 -4
  156. package/dist/{views-BmQF4UCI.js → views-B8w2J-gD.js} +16 -26
  157. package/dist/views-B8w2J-gD.js.map +1 -0
  158. package/dist/views-DblnI3kA.js +2 -0
  159. package/dist/{worker-entry-yOchGYYv.js → worker-entry-DNnveLqx.js} +2 -2
  160. package/dist/{worker-entry-yOchGYYv.js.map → worker-entry-DNnveLqx.js.map} +1 -1
  161. package/dist/{workspace-CgyHEM0l.js → workspace-C4RA3srV.js} +4 -4
  162. package/dist/{workspace-CgyHEM0l.js.map → workspace-C4RA3srV.js.map} +1 -1
  163. package/dist/{workspace-D8sSgpiy.js → workspace-C_X0tdv6.js} +1 -1
  164. package/package.json +8 -8
  165. package/dist/assemble-J5MukZFY.js +0 -1
  166. package/dist/capture-jquXZBKK.js +0 -1
  167. package/dist/cli-D303Vj5N.js.map +0 -1
  168. package/dist/cli-spec-BPZbQG2p.js.map +0 -1
  169. package/dist/command-BLfT7vnQ.js.map +0 -1
  170. package/dist/command-BT9a37ZR.js.map +0 -1
  171. package/dist/command-Bge8F7Ko.js.map +0 -1
  172. package/dist/command-BkFjijN2.js +0 -1
  173. package/dist/commands-BFx16WB8.js.map +0 -1
  174. package/dist/config-DEgnUiU-.js.map +0 -1
  175. package/dist/db-Dm1cRJJP.js +0 -2
  176. package/dist/dist-B8hJImYt.js.map +0 -1
  177. package/dist/doctor-BYNok4UO.js.map +0 -1
  178. package/dist/duration-CEOQww97.js +0 -26
  179. package/dist/duration-CEOQww97.js.map +0 -1
  180. package/dist/egress-C4PZTSSe.js.map +0 -1
  181. package/dist/env-BQqj93gu.js +0 -21
  182. package/dist/env-BQqj93gu.js.map +0 -1
  183. package/dist/environment-DNjRk0nU.js.map +0 -1
  184. package/dist/evaluate-D4zeRGBF.js.map +0 -1
  185. package/dist/family-D2b7WD10.js +0 -67
  186. package/dist/family-D2b7WD10.js.map +0 -1
  187. package/dist/files-BhyltlDB.js +0 -1
  188. package/dist/files-ZZPqfAo6.js +0 -1
  189. package/dist/init-BrOWin3W.js +0 -1
  190. package/dist/model-h_cDtcRr.js.map +0 -1
  191. package/dist/model-nwWJvaUR.js +0 -1
  192. package/dist/model-oqcDplJG.js.map +0 -1
  193. package/dist/options-Bh2W63dK.js.map +0 -1
  194. package/dist/plan-C9Cy27Ay.js.map +0 -1
  195. package/dist/process-CSVO_jsc.js +0 -119
  196. package/dist/process-CSVO_jsc.js.map +0 -1
  197. package/dist/query-Bes9Kh6Y.js +0 -91
  198. package/dist/query-Bes9Kh6Y.js.map +0 -1
  199. package/dist/query-C_G_svLU.js +0 -1
  200. package/dist/results-DuauQI3Z.js.map +0 -1
  201. package/dist/server-C7sg1ndo.js +0 -1
  202. package/dist/shared-DYpIb1BI.js.map +0 -1
  203. package/dist/source-fGd0SaKP.js +0 -1
  204. package/dist/src-B7treWa8.js.map +0 -1
  205. package/dist/src-pJZOrYR9.js +0 -1
  206. package/dist/state-CgjQo29K.js +0 -1
  207. package/dist/studio-app/assets/index-DrQc2Yxd.js +0 -58
  208. package/dist/summary-BLAVLySU.js +0 -385
  209. package/dist/summary-BLAVLySU.js.map +0 -1
  210. package/dist/views-BW6oCDUQ.js +0 -2
  211. package/dist/views-BmQF4UCI.js.map +0 -1
@@ -1,30 +1,28 @@
1
1
  import { n as isOneOf } from "./object-CLf2-tNq.js";
2
2
  import { n as UsageError } from "./errors-B6BSMs03.js";
3
- import { t as parseDuration } from "./duration-CEOQww97.js";
4
- import { f as sandboxId, s as harnessId } from "./options-Bh2W63dK.js";
5
- import { A as workspaceLabel, p as environmentSandbox } from "./environment-DNjRk0nU.js";
6
- import { a as fromCwd, i as evalSlug, n as attemptKey, o as newRunId } from "./ids-Bp6ut7ZD.js";
7
- import { a as configPathFor, c as findConfig, d as malformedCredentials, f as missingCredentials, h as selectProfile, i as configLabel, l as hostCapacity, m as resolveConcurrency, p as requireConfig, u as loadConfig } from "./config-DEgnUiU-.js";
8
- import { n as loadEnvFiles, t as inCI } from "./env-BQqj93gu.js";
3
+ import { p as parseDuration } from "./shared-CA61BuPJ.js";
4
+ import { f as sandboxId, s as harnessId } from "./options-C0d0AzeR.js";
5
+ import { A as workspaceLabel, p as environmentSandbox } from "./environment-Cca6a4wB.js";
6
+ import { a as fromCwd, o as newRunId } from "./ids-Bp6ut7ZD.js";
7
+ import { _ as selectProfile, a as configLabel, d as hostCapacity, f as loadConfig, g as resolveConcurrency, h as requireConfig, l as findConfig, m as missingCredentials, o as configPathFor, p as malformedCredentials, u as hasAnalysisModel, v as inCI, y as loadEnvFiles } from "./config-DrVSEVN0.js";
9
8
  import { o as redactSecrets, s as registerSecret } from "./redact-DJ9JCShu.js";
10
9
  import { o as PACKAGE_VERSION } from "./root-DICDHCtp.js";
11
- import { I as LABEL, X as imageInfo } from "./src-B7treWa8.js";
10
+ import { I as LABEL, X as imageInfo } from "./src-ftu5wPSt.js";
12
11
  import { s as debugTime } from "./debug-D24NOQH1.js";
13
12
  import { i as sandboxWarningLine, n as clip, r as formatDuration } from "./text-gEcKjAyp.js";
14
13
  import { t as PrepareError } from "./provider-CmAYTQQs.js";
15
- import { B as judgeRatesLabel, H as summaryJudgeRates, I as collapsedJudgeLabel, P as cellUsage, T as runOutcome, Y as cellContrast, g as formatUsage, l as evalMarkOutcome, tt as effortLabel, v as hasUngatedCells, x as isUngatedMiss } from "./model-oqcDplJG.js";
16
- import { a as familyLiftLabel, i as familyHeadLabel, n as familyCases, o as familyRateLabel, r as familyEffortLabel, t as caseLabel } from "./family-D2b7WD10.js";
17
- import { n as headToHeadLines, s as sampleReasons } from "./pairs-CnInRu-G.js";
18
- import { a as contrastLines, f as undiscriminating, i as checksLabel, n as answersLabel, o as gateLabel, p as undiscriminatingLabel, s as liftLabel } from "./summary-BLAVLySU.js";
19
- import { c as writeLiveProgress, i as prepareResume, o as resolveResume, r as loadPrevious, s as writeCurrent, t as completedKeysFor } from "./resume-BRfa8E_s.js";
20
- import { a as commandHelpText, n as FLAGS, r as GLOBAL, s as helpText, t as COMMANDS } from "./cli-spec-BPZbQG2p.js";
21
- import { i as runtimeInfo, n as gitInfo, r as runnerInfo, t as author } from "./provenance-DmE9uPVt.js";
22
- import { t as budgetMarker } from "./budget-DBUrH4jX.js";
23
- import { n as prepareAll, o as writePrepared, r as prepareTargets, t as RunStopError } from "./preflight-D7iFPKeK.js";
24
- import { n as imageHarness } from "./prepare-doGxaAGR.js";
25
- import { r as createProviders, t as attemptImage } from "./providers-tAOD1NQN.js";
26
- import { a as redactArgv, r as commandOf, t as logInvocation } from "./invocations-DbGfBAA_.js";
14
+ import { T as runOutcome, g as formatUsage } from "./model-DaX4bNLZ.js";
15
+ import { s as suiteResult } from "./suite-Cw_7G2RM.js";
27
16
  import { n as stripAnsi, t as colors } from "./colors-QV9dFVhN.js";
17
+ import { a as render } from "./summary-BUKfU-9l.js";
18
+ import { c as writeLiveProgress, i as prepareResume, o as resolveResume, r as loadPrevious, s as writeCurrent, t as completedKeysFor } from "./resume-Ca1c8vix.js";
19
+ import { a as commandHelpText, n as FLAGS, r as GLOBAL, s as helpText, t as COMMANDS } from "./cli-spec-qmEnQ25_.js";
20
+ import { i as runtimeInfo, n as gitInfo, r as runnerInfo, t as author } from "./provenance-DQ0AXn6c.js";
21
+ import { t as budgetMarker } from "./budget-DBUrH4jX.js";
22
+ import { n as prepareAll, o as writePrepared, r as prepareTargets, t as RunStopError } from "./preflight-BRzD30L5.js";
23
+ import { n as imageHarness } from "./prepare-B_y-AFMv.js";
24
+ import { r as createProviders, t as attemptImage } from "./providers-DoTq1jHW.js";
25
+ import { a as redactArgv, r as commandOf, t as logInvocation } from "./invocations-BYDPe3fV.js";
28
26
  import { existsSync, mkdirSync, readdirSync, writeFileSync } from "node:fs";
29
27
  import { dirname, join } from "node:path";
30
28
  import { inspect } from "node:util";
@@ -58,6 +56,7 @@ function parseCli(argv) {
58
56
  });
59
57
  for (const [name, spec] of Object.entries(COMMANDS)) {
60
58
  const command = configure(program.command(name), `reeval ${name}`, spec.flags);
59
+ if (name === "query") takeStatements(command);
61
60
  command.argument("[args...]").action(() => {
62
61
  const max = spec.sub && !spec.help ? Number.POSITIVE_INFINITY : spec.positionals;
63
62
  parsed = done(program, command, [name], spec.flags, max);
@@ -86,6 +85,28 @@ function configure(command, name, flags) {
86
85
  for (const flag of flags) command.addOption(OPTIONS[flag]());
87
86
  return command;
88
87
  }
88
+ /**
89
+ * Makes an argument that starts with `-` but has whitespace before any `=` (SQL opening with a
90
+ * `-- comment`) a positional: no flag looks like that, and commander would refuse it as one.
91
+ */
92
+ function takeStatements(command) {
93
+ const parseOptions = command.parseOptions.bind(command);
94
+ command.parseOptions = (args) => {
95
+ const held = /* @__PURE__ */ new Map();
96
+ const masked = args.map((arg, i) => {
97
+ if (!arg.startsWith("-") || !/\s/.test(arg.split("=")[0] ?? "")) return arg;
98
+ const token = `\0statement-${i}`;
99
+ held.set(token, arg);
100
+ return token;
101
+ });
102
+ const restore = (list) => list.map((arg) => held.get(arg) ?? arg);
103
+ const { operands, unknown } = parseOptions(masked);
104
+ return {
105
+ operands: restore(operands),
106
+ unknown: restore(unknown)
107
+ };
108
+ };
109
+ }
89
110
  function done(program, command, path, flags, max) {
90
111
  const values = {
91
112
  ...valuesOf(program, GLOBAL),
@@ -119,16 +140,17 @@ function valuesOf(command, flags) {
119
140
  }
120
141
  /** Commander's error, in reeval's words, naming the command whose flag it is. */
121
142
  function usageError(error, command) {
122
- const [first = "", ...rest] = error.message.replace(/^error: /, "").split("\n");
143
+ const text = error.message.replace(/^error: /, "");
144
+ const [first = ""] = text.split("\n");
123
145
  if (error.code === "commander.unknownOption") {
124
- const arg = /'([^']+)'/.exec(first)?.[1] ?? "";
146
+ const [, arg = "", suggestion] = /^unknown option '([\s\S]*)'(?:\n\((.*)\))?$/.exec(text) ?? [];
125
147
  const [flag = "", value] = arg.replace(/^--?/, "").split("=");
126
148
  const known = arg.startsWith("--") ? FLAGS[flag] : Object.entries(FLAGS).find(([, s]) => "short" in s && s.short === flag)?.[1];
127
149
  const long = arg.startsWith("--") ? flag : Object.entries(FLAGS).find(([, s]) => "short" in s && s.short === flag)?.[0];
128
150
  if (known && value !== void 0 && known.type === "boolean") return new UsageError(`--${flag} doesn't take a value: pass --${flag} on its own.`);
129
151
  if (known) return new UsageError(`--${long} isn't an option of ${command}. Run reeval --help.`);
130
- const hint = rest.join(" ").replace(/^\(|\)$/g, "");
131
- return new UsageError(`Unknown option '${arg}'. ${hint ? `${hint} ` : ""}Run reeval --help.`);
152
+ const shown = arg.replace(/\r/g, "\\r").replace(/\n/g, "\\n");
153
+ return new UsageError(`Unknown option '${shown}'. ${suggestion ? `${suggestion} ` : ""}Run reeval --help.`);
132
154
  }
133
155
  if (error.code === "commander.optionMissingArgument") {
134
156
  const usage = /'([^']+)'/.exec(first)?.[1] ?? "";
@@ -221,24 +243,10 @@ function outcomeOf(e) {
221
243
  if (e.meta?.errorKind === "aborted") return "cancelled";
222
244
  return e.meta?.outcome ?? (e.state === "passed" ? "pass" : "fail");
223
245
  }
224
- function attemptOutcome(a) {
225
- return a.error?.kind === "aborted" ? "cancelled" : a.outcome;
226
- }
227
246
  /** What tells an eval's attempts apart: the axes that vary (`cursor:composer-2.5 · with-skill`), else the harness. */
228
247
  function attemptAxes(a, fallback) {
229
248
  return a?.label.replace(/\s*#\d+$/, "") || a?.harness.kind || fallback;
230
249
  }
231
- function mark(c, outcome) {
232
- return {
233
- pass: c.green("✓"),
234
- fail: c.red("✗"),
235
- infra_error: c.yellow("!"),
236
- skipped: c.dim("↓"),
237
- cancelled: c.yellow("✗")
238
- }[outcome];
239
- }
240
- /** An expected miss's mark: neutral, since it doesn't fail the run. */
241
- const MISS_MARK = (c) => c.dim("○");
242
250
  const plural = (n, word) => `${n} ${word}${n === 1 ? "" : "s"}`;
243
251
  /** A command on one line: the first line, cut to 80 characters at a word boundary. */
244
252
  function oneLine(text, max = 80) {
@@ -363,330 +371,25 @@ function prepareLines(c, e, max) {
363
371
  return [`${c.red("✗")} ${outcome.target.label} failed to prepare ${c.dim(`(set by ${who}; only its attempts fail)`)}`, ...tailLines(outcome.failure.message, max).map((l) => ` ${c.yellow(l)}`)];
364
372
  }
365
373
  //#endregion
366
- //#region src/ui/summary.ts
367
- const FAILURE_LINES = 30;
368
- const KINDS = [
369
- {
370
- title: "Judge failures",
371
- test: (a) => a.error?.kind === "judge"
372
- },
373
- {
374
- title: "Assertion failures",
375
- test: (a) => a.error?.kind === "assertion"
376
- },
377
- {
378
- title: "Timeouts",
379
- test: (a) => a.error?.kind === "timeout"
380
- },
381
- {
382
- title: "Infra errors",
383
- test: (_, o) => o === "infra_error"
384
- },
385
- {
386
- title: "Cancelled",
387
- test: (_, o) => o === "cancelled"
388
- }
389
- ];
390
- /** The engine's result for an attempt, or one rebuilt from the record (e.g. cancelled ones). */
391
- function resultFor(entry, attempt, results) {
392
- const key = attemptKey(entry.id, attempt.cell, attempt.n);
393
- const found = results.find((r) => r.key === key);
394
- const errorKind = attempt.error?.kind ?? null;
395
- const meta = {
396
- outcome: attempt.outcome === "skipped" ? "pass" : attempt.outcome,
397
- errorKind,
398
- judgements: attempt.judgements.map((j) => ({ ...j })),
399
- turnErrors: attempt.turns.flatMap((t, i) => t.error ? [`turn ${i + 1} error: ${t.error}`] : []),
400
- recordPath: ""
401
- };
402
- if (found) return {
403
- ...found,
404
- meta: found.meta ? {
405
- ...found.meta,
406
- errorKind
407
- } : meta
408
- };
409
- return {
410
- id: entry.id,
411
- key,
412
- file: entry.file,
413
- group: entry.group,
414
- name: entry.name,
415
- attempt: void 0,
416
- state: attempt.outcome === "pass" ? "passed" : attempt.outcome === "skipped" ? "skipped" : "failed",
417
- durationMs: attempt.durationMs,
418
- errors: attempt.error ? [attempt.error.message] : [],
419
- formattedErrors: [],
420
- meta
421
- };
422
- }
423
- function entryOutcome(e) {
424
- const outcomes = e.attempts.map(attemptOutcome);
425
- if (outcomes.length && outcomes.every((o) => o === "cancelled")) return "cancelled";
426
- return evalMarkOutcome(e);
427
- }
428
- /** Every cell is `gate: 'none'`: the eval reports its attempts but nothing gates it. */
429
- const allUngated = (e) => e.cells.length > 0 && e.cells.every((c) => c.gate === "none");
430
- const pct = (rate) => rate === null ? " – " : `${Math.round(rate * 100)}%`.padStart(4);
431
- function evalColumns(c, e) {
432
- const [attempt, ...more] = e.attempts;
433
- if (e.todo) return c.dim("todo");
434
- if (!attempt || e.outcome === "skipped") return c.dim("skipped");
435
- if (more.length) {
436
- const pass = e.attempts.filter((a) => a.outcome === "pass").length;
437
- const counted = e.attempts.filter((a) => a.outcome === "pass" || a.outcome === "fail").length;
438
- const rate = allUngated(e) ? " · not gated" : hasUngatedCells(e.cells) ? ` · pass@1 ${pct(e.passRate).trim()} gated` : ` pass@1 ${pct(e.passRate)}`;
439
- return c.dim(`${`${pass}/${counted}`.padStart(7)}${rate} ${e.attempts.length} attempts`);
440
- }
441
- if (attemptOutcome(attempt) === "cancelled") return c.yellow("cancelled");
442
- const cols = [formatDuration(attempt.durationMs).padStart(7)];
443
- const judges = collapsedJudgeLabel(attempt.judgements);
444
- if (judges) cols.push(judges);
445
- const turns = attempt.turns.length;
446
- cols.push(`${turns} turn${turns === 1 ? "" : "s"}`);
447
- const tokens = formatUsage(attempt.usage);
448
- if (tokens) cols.push(tokens);
449
- return c.dim(cols.join(" "));
450
- }
451
- /** pass@1 per cell for evals with several attempts; with compare, each cell's role and lift. */
452
- function cellRows(c, e, indent) {
453
- if (e.attempts.length < 2) return [];
454
- const compare = e.cells.some((cell) => cell.role === "variant");
455
- const width = Math.max(...e.cells.map((cell) => cell.key.length));
456
- return e.cells.flatMap((cell) => {
457
- const role = compare ? ` ${cell.role.padEnd(7)}` : "";
458
- const counts = `${cell.pass}/${cell.pass + cell.fail}`.padStart(5);
459
- const infra = cell.infraError ? c.yellow(` ${cell.infraError} infra`) : "";
460
- let note = "";
461
- if (cell.lift) {
462
- const { minLift } = cell.lift;
463
- const below = minLift !== void 0 && cell.lift.interval.lo < minLift;
464
- const text = `${liftLabel(cell.lift)}${minLift !== void 0 ? ` (minLift ${Math.round(minLift * 100)})` : ""}`;
465
- note = ` ${below ? c.red(`${text} ✗`) : text}`;
466
- } else if (compare && cell.gate === "none" && cell.fail > 0) note = ` ${c.dim("not gated")}`;
467
- if (cell.gate !== "all" && cell.gate !== "none") note += ` ${c.dim(`gate ${gateLabel(cell.gate)}`)}`;
468
- const tokens = formatUsage(cellUsage(e, cell.key));
469
- const usage = tokens ? ` ${c.dim(tokens)}` : "";
470
- const rows = [`${indent}${c.dim(cell.key.padEnd(width))}${role} ${counts} pass@1 ${pct(cell.passRate)}${note}${infra}${usage}`];
471
- const rates = judgeRatesLabel(summaryJudgeRates(e, cell));
472
- if (rates) rows.push(`${indent} ${c.dim(rates)}`);
473
- const effort = cellContrast(e, cell.key);
474
- if (effort) rows.push(`${indent} ${c.dim(`effort: ${effortLabel(effort)}`)}`);
475
- const checks = checksLabel(cell);
476
- if (checks) rows.push(`${indent} ${c.dim(`checks: ${checks}`)}`);
477
- if (cell.overrides.length) rows.push(`${indent} ${c.dim(`overrides: ${cell.overrides.join(", ")}`)}`);
478
- return rows;
479
- });
480
- }
481
- /** With two variants or more, each pair of arms on one harness: lift, checks and effort. */
482
- function contrastRows(c, e, indent) {
483
- const lines = contrastLines(e);
484
- if (!lines.length) return [];
485
- return [`${indent}${c.dim("contrasts (each pair of arms, same harness)")}`, ...lines.map((line) => `${indent} ${c.dim(line)}`)];
486
- }
487
- /** One row per compare question: its win rates, or why it has none. They never gate. */
488
- function questionRows(c, e, indent) {
489
- return (e.answers ?? []).flatMap((a) => {
490
- const label = answersLabel(a);
491
- return [
492
- `${indent}${c.dim("question")} ${a.error !== void 0 ? c.yellow(label) : label}`,
493
- ...headToHeadLines(a.votes).map((line) => `${indent} ${line}`),
494
- ...sampleReasons(a.votes).map((reason) => `${indent} ${c.dim(reason)}`)
495
- ];
496
- });
497
- }
498
- /** A family's mark: its pooled gate's and its cases' worst. */
499
- function familyOutcome(family, cases) {
500
- const outcomes = [family.outcome, ...cases.map(entryOutcome)];
501
- for (const o of [
502
- "fail",
503
- "infra_error",
504
- "cancelled"
505
- ]) if (outcomes.includes(o)) return o;
506
- return outcomes.every((o) => o === "skipped") ? "skipped" : "pass";
507
- }
508
- /** The width case marks wrap at. */
509
- const CASE_WIDTH = 96;
510
- /** A pooled family's rows under its header: its cases' marks, then each pooled rate or lift. */
511
- function familyRows(c, family, cases, indent) {
512
- const marks = cases.map((e) => `${mark(c, entryOutcome(e))} ${caseLabel(family.name, e.name)}`);
513
- const plain = cases.map((e) => `x ${caseLabel(family.name, e.name)}`);
514
- const rows = [];
515
- let line = [];
516
- let width = 0;
517
- marks.forEach((m, i) => {
518
- const w = plain[i].length + 2;
519
- if (line.length && width + w > CASE_WIDTH) {
520
- rows.push(`${indent}${line.join(" ")}`);
521
- line = [];
522
- width = 0;
523
- }
524
- line.push(m);
525
- width += w;
526
- });
527
- if (line.length) rows.push(`${indent}${line.join(" ")}`);
528
- if (family.lifts.length) {
529
- const keyWidth = Math.max(...family.lifts.map((l) => l.variant.length));
530
- for (const lift of family.lifts) {
531
- const below = lift.outcome === "fail";
532
- const gate = lift.minLift !== void 0 ? ` (minLift ${Math.round(lift.minLift * 100)}${below ? " ✗" : ""})` : "";
533
- const text = `${familyLiftLabel(lift)}${gate}`;
534
- rows.push(`${indent}${c.dim(lift.variant.padEnd(keyWidth))} ${below ? c.red(text) : text}`);
535
- const effort = familyEffortLabel(lift);
536
- if (effort) rows.push(`${indent} ${c.dim(`effort: ${effort}`)}`);
537
- }
538
- } else if (family.rates.length === 1) rows.push(`${indent}${familyRateLabel(family.rates[0])}`);
539
- else {
540
- const keyWidth = Math.max(...family.rates.map((r) => r.cell.length));
541
- for (const rate of family.rates) rows.push(`${indent}${c.dim(rate.cell.padEnd(keyWidth))} ${familyRateLabel(rate)}`);
542
- }
543
- return rows;
544
- }
545
- /**
546
- * The run's evals as a file › group tree, one row per eval and per cell of a matrix. A pooled
547
- * family is one row, its template, with its cases' marks and the pooled results under it.
548
- */
549
- function tree(c, evals, families = []) {
550
- const rows = [];
551
- const shown = /* @__PURE__ */ new Set();
552
- let path = [];
553
- for (const e of evals) {
554
- const family = e.family && families.find((f) => f.id === e.family?.id);
555
- if (family && shown.has(family.id)) continue;
556
- const next = [e.file, ...e.group];
557
- let same = 0;
558
- while (same < path.length && same < next.length && path[same] === next[same]) same++;
559
- for (let i = same; i < next.length; i++) rows.push({
560
- indent: i,
561
- text: i === 0 ? c.bold(next[i] ?? "") : next[i] ?? ""
562
- });
563
- path = next;
564
- if (family) {
565
- shown.add(family.id);
566
- rows.push({
567
- indent: next.length,
568
- text: family.name,
569
- family
570
- });
571
- } else rows.push({
572
- indent: next.length,
573
- text: e.name,
574
- entry: e
575
- });
576
- }
577
- const width = Math.max(...rows.filter((r) => r.entry || r.family).map((r) => r.indent * 2 + 2 + r.text.length));
578
- return rows.flatMap(({ indent, text, entry, family }) => {
579
- const pad = " ".repeat(indent);
580
- const fill = " ".repeat(Math.max(0, width - indent * 2 - 2 - text.length));
581
- if (family) {
582
- const cases = familyCases(family, evals);
583
- return [` ${pad}${mark(c, familyOutcome(family, cases))} ${text}${fill} ${c.dim(familyHeadLabel(family))}`, ...familyRows(c, family, cases, ` ${pad} `)];
584
- }
585
- if (!entry) return [` ${pad}${text}`];
586
- return [
587
- ` ${pad}${`${entryOutcome(entry) === "pass" && allUngated(entry) && entry.attempts.some((a) => isUngatedMiss(entry, a)) ? MISS_MARK(c) : mark(c, entryOutcome(entry))} ${text}`}${fill} ${evalColumns(c, entry)}`,
588
- ...cellRows(c, entry, ` ${pad} `),
589
- ...contrastRows(c, entry, ` ${pad} `),
590
- ...questionRows(c, entry, ` ${pad} `)
591
- ];
592
- });
593
- }
594
- function totals(c, s, cancelled = 0) {
595
- const fail = s.fail - s.notGated - cancelled;
596
- const parts = [
597
- s.pass && c.green(`${s.pass} passed`),
598
- fail > 0 && c.red(`${fail} failed`),
599
- s.notGated > 0 && c.dim(`${s.notGated} missed, not gated`),
600
- s.infraError && c.yellow(`${s.infraError} infra error`),
601
- cancelled && c.yellow(`${cancelled} cancelled`),
602
- s.skipped && c.dim(`${s.skipped} skipped`)
603
- ].filter(Boolean);
604
- const scope = s.attempts === s.evals ? `${s.evals}` : `${s.attempts} attempts, ${s.evals} evals`;
605
- return parts.length ? `${parts.join(c.dim(" · "))} ${c.dim(`(${scope})`)}` : "no evals ran";
606
- }
607
- /** `1 passed · 1 failed (2)`: the families' pooled gates. */
608
- function familyTotals(c, families) {
609
- const fail = families.filter((f) => f.outcome === "fail").length;
610
- const pass = families.length - fail;
611
- return `${[pass && c.green(`${pass} passed`), fail && c.red(`${fail} failed`)].filter(Boolean).join(c.dim(" · "))} ${c.dim(`(${families.length})`)}`;
612
- }
613
- /** Failing attempts, in run order, including expected misses. */
614
- function failingAttempts(evals) {
615
- return evals.flatMap((entry) => entry.attempts.map((attempt) => ({
616
- entry,
617
- attempt,
618
- outcome: attemptOutcome(attempt)
619
- })).filter(({ outcome }) => outcome !== "pass" && outcome !== "skipped"));
620
- }
621
- function renderSummary(c, e, attemptDir) {
374
+ //#region src/ui/result.ts
375
+ function resultLines(c, e, verbose) {
622
376
  const { record } = e;
623
- const lines = [];
624
- if (record.evals.length) lines.push(c.bold("Summary"), ...tree(c, record.evals, record.families));
625
- const all = failingAttempts(record.evals);
626
- const missed = all.filter(({ entry, attempt }) => isUngatedMiss(entry, attempt));
627
- const failing = all.filter((f) => !missed.includes(f));
628
- if (failing.length) {
629
- lines.push("", c.bold(c.red(`Failures (${failing.length})`)));
630
- for (const kind of KINDS) {
631
- const members = failing.filter(({ attempt, outcome }) => kind.test(attempt, outcome));
632
- if (!members.length) continue;
633
- lines.push("", c.bold(`${kind.title} (${members.length})`));
634
- for (const { entry, attempt, outcome } of members) {
635
- const result = resultFor(entry, attempt, e.results);
636
- const which = entry.attempts.length > 1 ? ` ${c.dim(attempt.id)}` : "";
637
- const gated = entry.cells.find((x) => x.key === attempt.cell)?.gate !== "none";
638
- lines.push(` ${mark(c, outcome)} ${entry.id}${which}${gated ? "" : ` ${c.dim("(not gated)")}`}`);
639
- if (outcome !== "cancelled") for (const line of failureLines(c, result, { max: FAILURE_LINES })) lines.push(` ${line}`);
640
- if (!attempt.error?.prepare) lines.push(` ${c.dim("record")} ${attemptDir(entry.id, attempt.cell, attempt.n)}`);
641
- }
642
- }
643
- }
644
- if (missed.length) {
645
- lines.push("", c.bold(`Expected misses, not gated (${missed.length})`));
646
- const pooled = /* @__PURE__ */ new Map();
647
- for (const { entry, attempt } of missed) {
648
- if (!entry.family) continue;
649
- const key = `${entry.family.id}\0${attempt.cell}`;
650
- pooled.set(key, (pooled.get(key) ?? 0) + 1);
651
- }
652
- for (const [key, n] of pooled) {
653
- const [id, cell] = key.split("\0");
654
- lines.push(` ${MISS_MARK(c)} ${id} ${c.dim(`${n} ${n === 1 ? "attempt" : "attempts"} on ${cell}`)}`);
655
- }
656
- for (const { entry, attempt } of missed) {
657
- if (entry.family) continue;
658
- const which = entry.attempts.length > 1 ? ` ${c.dim(attempt.id)}` : "";
659
- const [reason] = failureLines(colors(false), resultFor(entry, attempt, e.results), { max: 1 }).filter((l) => l.trim());
660
- lines.push(` ${MISS_MARK(c)} ${entry.id}${which}`);
661
- if (reason) lines.push(` ${c.dim(reason.trim())}`);
662
- lines.push(` ${c.dim("record")} ${attemptDir(entry.id, attempt.cell, attempt.n)}`);
663
- }
664
- }
665
- for (const error of e.unhandledErrors) lines.push("", c.red(`error: ${error}`));
666
- const cancelled = failing.filter((f) => f.outcome === "cancelled").length;
667
- const label = record.summary.attempts === record.summary.evals ? " Evals" : "Attempts";
668
- const lifted = record.evals.flatMap((entry) => entry.cells.flatMap((cell) => cell.lift?.minLift !== void 0 && cell.lift.interval.lo < cell.lift.minLift ? [`${entry.id} ${cell.key} ${liftLabel(cell.lift)}: its lower bound is below minLift ${Math.round(cell.lift.minLift * 100)}`] : []));
669
- for (const family of record.families ?? []) for (const lift of family.lifts) {
670
- if (lift.outcome !== "fail" || lift.minLift === void 0) continue;
671
- lifted.push(`${family.id} ${lift.variant} pooled ${familyLiftLabel(lift)}: its lower bound is below minLift ${Math.round(lift.minLift * 100)}`);
672
- }
673
- const idle = undiscriminating(record.evals);
674
- if (idle.length) {
675
- lines.push("", c.bold(`Checks that don't discriminate (${idle.length})`));
676
- for (const x of idle) lines.push(` ${c.dim("·")} ${undiscriminatingLabel(x)}`);
677
- }
678
- if (lifted.length) {
679
- lines.push("", c.bold(c.red(`Lift below minLift (${lifted.length})`)));
680
- for (const line of lifted) lines.push(` ${c.red("✗")} ${line}`);
681
- }
682
- if (record.status === "budget") lines.push("", c.yellow("Budget reached: attempts that hadn’t started were skipped"));
683
- lines.push("");
684
- if (record.families?.length) lines.push(`${c.dim("Families")} ${familyTotals(c, record.families)}`);
685
- lines.push(`${c.dim(label)} ${totals(c, record.summary, cancelled)}`, `${c.dim("Duration")} ${formatDuration(record.durationMs)}`);
686
377
  const tokens = formatUsage(record.cost.usage);
687
- if (tokens) lines.push(` ${c.dim("Tokens")} ${tokens}`);
688
- lines.push(` ${c.dim("Results")} ${e.summaryPath}`);
689
- return lines;
378
+ const notes = [
379
+ ...record.status === "budget" ? [c.yellow("Budget reached: attempts that hadn’t started were skipped")] : [],
380
+ ...record.status === "interrupted" ? [c.yellow("Interrupted: attempts that hadn’t finished were cancelled")] : [],
381
+ c.dim([
382
+ formatDuration(record.durationMs),
383
+ tokens,
384
+ `results ${e.summaryPath}`
385
+ ].filter(Boolean).join(" · "))
386
+ ];
387
+ return [...e.unhandledErrors.flatMap((error) => [c.red(`error: ${error}`), ""]), ...render(suiteResult(record), null, {
388
+ color: c.enabled,
389
+ verbose,
390
+ notes,
391
+ hint: e.hint
392
+ })];
690
393
  }
691
394
  //#endregion
692
395
  //#region src/ui/tags.ts
@@ -749,16 +452,9 @@ var Tagger = class {
749
452
  //#endregion
750
453
  //#region src/ui/agent.ts
751
454
  const MAX_LINES = 12;
752
- const WORD = {
753
- fail: "FAIL",
754
- infra_error: "INFRA",
755
- cancelled: "CANCELLED"
756
- };
757
455
  var AgentRenderer = class {
758
456
  #o;
759
457
  #c = colors(false);
760
- #logs = /* @__PURE__ */ new Map();
761
- #printed = /* @__PURE__ */ new Set();
762
458
  /** `[key]` prefixes for `-v` lines, from each attempt's start. */
763
459
  #labels = /* @__PURE__ */ new Map();
764
460
  #tags = new Tagger();
@@ -768,30 +464,6 @@ var AgentRenderer = class {
768
464
  #write(text) {
769
465
  this.#o.out.write(`${text.trimEnd()}\n`);
770
466
  }
771
- #failure(result, cell, n) {
772
- const outcome = outcomeOf(result);
773
- if (outcome === "pass" || outcome === "skipped") return;
774
- this.#printed.add(result.key);
775
- const kind = outcome === "fail" ? result.meta?.errorKind ?? "assertion" : null;
776
- const detail = [
777
- formatDuration(result.durationMs),
778
- kind,
779
- result.attempt?.gate === "none" ? "not gated" : ""
780
- ].filter(Boolean).join(", ");
781
- const which = result.attempt?.label ? ` [${result.attempt.label}]` : "";
782
- const missed = outcome === "fail" && result.attempt?.gate === "none";
783
- this.#write(`${missed ? "MISS" : WORD[outcome]} ${result.id}${which} (${detail})`);
784
- if (outcome !== "cancelled") {
785
- const lines = failureLines(this.#c, result, { max: MAX_LINES });
786
- for (const line of missed ? lines.filter((l) => l.trim()).slice(0, 1) : lines) this.#write(` ${line}`);
787
- }
788
- const logs = missed ? void 0 : this.#logs.get(result.key);
789
- if (logs?.length) {
790
- this.#write(" console:");
791
- for (const line of capLines(logs.join("\n"), MAX_LINES)) this.#write(` ${line}`);
792
- }
793
- if (!result.meta?.prepare) this.#write(` record: ${this.#o.attemptDir(result.id, cell, n)}`);
794
- }
795
467
  onEvent(e) {
796
468
  switch (e.type) {
797
469
  case "plan":
@@ -814,65 +486,22 @@ var AgentRenderer = class {
814
486
  for (const line of debugLines(this.#c, e.line, this.#o.verbosity === 2)) this.#write(`${label} ${line}`);
815
487
  return;
816
488
  }
817
- case "log": {
818
- if (!e.key) return;
819
- const logs = this.#logs.get(e.key) ?? [];
820
- logs.push(...e.text.replace(/\n$/, "").split("\n"));
821
- this.#logs.set(e.key, logs);
822
- return;
823
- }
824
489
  case "eval-progress": {
825
490
  if (e.progress.kind !== "browser-download") return;
826
491
  const label = this.#labels.get(e.key) ?? `[${e.key}]`;
827
492
  this.#write(`${label} ${progressLine(this.#c, e.progress)}`);
828
493
  return;
829
494
  }
830
- case "eval-end": {
831
- const { attempt } = e.result;
832
- this.#failure(e.result, attempt?.cell.key ?? "", attempt?.n ?? 1);
833
- return;
834
- }
835
495
  case "prepare":
836
496
  for (const line of prepareLines(this.#c, e, MAX_LINES)) this.#write(line);
837
497
  return;
838
498
  case "notice":
839
499
  if (e.level !== "info") this.#write(e.text);
840
500
  return;
841
- case "run-end": {
842
- const failing = failingAttempts(e.record.evals);
843
- for (const { entry, attempt, outcome } of failing) {
844
- const result = resultFor(entry, attempt, e.results);
845
- if (outcome === "cancelled" && !this.#printed.has(result.key)) this.#failure(result, attempt.cell, attempt.n);
846
- }
847
- for (const error of e.unhandledErrors) this.#write(`ERROR ${error}`);
848
- for (const entry of e.record.evals) for (const a of entry.answers ?? []) {
849
- this.#write(`question ${entry.id}: ${answersLabel(a)}`);
850
- for (const line of headToHeadLines(a.votes)) this.#write(` ${line}`);
851
- for (const reason of sampleReasons(a.votes)) this.#write(` ${reason}`);
852
- }
853
- for (const x of undiscriminating(e.record.evals)) this.#write(`check doesn't discriminate: ${undiscriminatingLabel(x)}`);
854
- for (const family of e.record.families ?? []) {
855
- const pooled = family.lifts.length ? family.lifts.map((l) => {
856
- const gate = l.minLift === void 0 ? "" : ` (minLift ${Math.round(l.minLift * 100)}${l.outcome === "fail" ? ", FAIL" : ""})`;
857
- return `${l.variant} ${familyLiftLabel(l)}${gate}`;
858
- }) : family.rates.map((r) => `${r.cell} ${familyRateLabel(r)}`);
859
- this.#write(`family ${family.id}: ${familyHeadLabel(family)} · ${pooled.join(" · ")}`);
860
- }
861
- const s = e.record.summary;
862
- const cancelled = failing.filter((f) => f.outcome === "cancelled").length;
863
- const parts = [
864
- s.pass && `${s.pass} passed`,
865
- s.fail - s.notGated - cancelled > 0 && `${s.fail - s.notGated - cancelled} failed`,
866
- s.notGated > 0 && `${s.notGated} missed, not gated`,
867
- s.infraError && `${s.infraError} infra error`,
868
- cancelled && `${cancelled} cancelled`,
869
- s.skipped && `${s.skipped} skipped`
870
- ].filter(Boolean);
871
- const scope = s.attempts === s.evals ? "" : ` (${s.attempts} attempts, ${s.evals} evals)`;
872
- this.#write(parts.length ? `${parts.join(", ")}${scope}` : "no evals ran");
873
- this.#write(`summary: ${e.summaryPath}`);
501
+ case "run-end":
502
+ this.#write("");
503
+ for (const line of resultLines(this.#c, e, (this.#o.verbosity ?? 0) > 0)) this.#write(line);
874
504
  return;
875
- }
876
505
  default: return;
877
506
  }
878
507
  }
@@ -889,6 +518,8 @@ const STARTS = {
889
518
  "browser-download": "browser-download"
890
519
  };
891
520
  const ERROR_LINES = 12;
521
+ /** Back to the start of the line and clear it, for the live status line. */
522
+ const CLEAR = "\r\x1B[2K";
892
523
  /** GitHub Actions workflow-command escaping. */
893
524
  const ghEscape = (s, property = false) => {
894
525
  const out = s.replace(/%/g, "%25").replace(/\r/g, "%0D").replace(/\n/g, "%0A");
@@ -914,10 +545,18 @@ var PlainRenderer = class {
914
545
  #runStartedAt = 0;
915
546
  #lastWrite = 0;
916
547
  #timer;
548
+ /** On a TTY: the status line is drawn under everything else, and redrawn after each write. */
549
+ #live;
550
+ #status = "";
551
+ /** Evals and tries collected (not skipped), and the tries that ended. */
552
+ #evals = /* @__PURE__ */ new Set();
553
+ #tries = /* @__PURE__ */ new Set();
554
+ #ended = /* @__PURE__ */ new Set();
917
555
  constructor(options) {
918
556
  this.#o = options;
919
557
  this.#c = options.colors;
920
558
  this.#now = options.now ?? Date.now;
559
+ this.#live = options.output.requested === "live";
921
560
  const { heartbeatMs } = options.output;
922
561
  if (options.timers !== false && heartbeatMs > 0) {
923
562
  this.#timer = setInterval(() => this.tick(), Math.min(heartbeatMs, 5e3));
@@ -925,9 +564,24 @@ var PlainRenderer = class {
925
564
  }
926
565
  }
927
566
  #write(text) {
928
- this.#o.out.write(`${text.trimEnd()}\n`);
567
+ const line = `${text.trimEnd()}\n`;
568
+ this.#o.out.write(this.#status ? `${CLEAR}${line}${this.#status}` : line);
929
569
  this.#lastWrite = this.#now();
930
570
  }
571
+ /** `7 evals · 12/28 tries`: what's collected so far and how many tries ended. */
572
+ #drawStatus() {
573
+ if (!this.#live || !this.#tries.size) return;
574
+ const evals = `${this.#evals.size} eval${this.#evals.size === 1 ? "" : "s"}`;
575
+ const status = this.#c.dim(`${evals} · ${this.#ended.size}/${this.#tries.size} tries`);
576
+ if (status === this.#status) return;
577
+ this.#o.out.write(`${CLEAR}${status}`);
578
+ this.#status = status;
579
+ }
580
+ #clearStatus() {
581
+ if (!this.#status) return;
582
+ this.#o.out.write(CLEAR);
583
+ this.#status = "";
584
+ }
931
585
  #attempt(ref, startedAt) {
932
586
  const n = ref.attempt?.n ?? 1;
933
587
  const label = `[${this.#tags.label(ref.id, n)} ${attemptAxes(ref.attempt, this.#o.harness)}]`;
@@ -973,14 +627,20 @@ var PlainRenderer = class {
973
627
  return;
974
628
  case "collected":
975
629
  this.#tags.addFile(e.evals);
976
- for (const x of e.evals) if (!x.skipped) this.#queued.add(x.key);
630
+ for (const x of e.evals) {
631
+ if (x.skipped) continue;
632
+ this.#queued.add(x.key);
633
+ this.#evals.add(x.id);
634
+ this.#tries.add(x.key);
635
+ }
636
+ this.#drawStatus();
977
637
  return;
978
638
  case "eval-start": {
979
639
  const a = this.#attempt(e, e.at);
980
640
  a.last = e;
981
641
  this.#queued.delete(e.key);
982
642
  this.#running.set(e.key, a);
983
- this.#write(`${this.#prefix(a)} ${c.dim("▶")} ${e.id}`);
643
+ if (this.#streaming) this.#write(`${this.#prefix(a)} ${c.dim("▶")} ${e.id}`);
984
644
  return;
985
645
  }
986
646
  case "eval-progress": {
@@ -1028,6 +688,8 @@ var PlainRenderer = class {
1028
688
  }
1029
689
  case "eval-end":
1030
690
  this.#end(e.result, e.at);
691
+ if (this.#tries.has(e.result.key)) this.#ended.add(e.result.key);
692
+ this.#drawStatus();
1031
693
  return;
1032
694
  case "prepare":
1033
695
  for (const line of prepareLines(c, e, ERROR_LINES)) this.#write(line);
@@ -1048,8 +710,9 @@ var PlainRenderer = class {
1048
710
  return;
1049
711
  }
1050
712
  case "run-end":
713
+ this.#clearStatus();
1051
714
  this.#write("");
1052
- for (const line of renderSummary(c, e, this.#o.attemptDir)) this.#write(line);
715
+ for (const line of resultLines(c, e, (this.#o.verbosity ?? 0) > 0)) this.#write(line);
1053
716
  return;
1054
717
  }
1055
718
  }
@@ -1062,6 +725,11 @@ var PlainRenderer = class {
1062
725
  const title = w.kind === "root" ? "Sandbox runs as root" : "Sandbox has extra capabilities";
1063
726
  this.#write(`::warning ${file}title=${ghEscape(title, true)}::${ghEscape(w.message)}`);
1064
727
  }
728
+ /**
729
+ * An ended attempt's logs, as `--output-logs` picks: grouped, its block under a `▶` header;
730
+ * streamed, only its error lines, since the rest already printed. A sandbox that failed to
731
+ * prepare was annotated once, for all its attempts.
732
+ */
1065
733
  #end(result, at) {
1066
734
  const c = this.#c;
1067
735
  const a = this.#running.get(result.key) ?? this.#attempt(result, at - result.durationMs);
@@ -1069,18 +737,17 @@ var PlainRenderer = class {
1069
737
  this.#queued.delete(result.key);
1070
738
  const outcome = outcomeOf(result);
1071
739
  const failed = outcome !== "pass" && outcome !== "skipped";
1072
- const time = outcome === "skipped" ? "" : ` ${c.dim(formatDuration(result.durationMs))}`;
1073
- const ungated = failed && result.attempt?.gate === "none" ? ` ${c.dim("(not gated)")}` : "";
1074
- const missed = ungated !== "" && outcome === "fail";
1075
- const head = `${this.#prefix(a)} ${missed ? MISS_MARK(c) : mark(c, outcome)} ${result.id}${time}${ungated}`;
740
+ const ungated = failed && result.attempt?.gate === "none";
741
+ const missed = ungated && outcome === "fail";
1076
742
  const { outputLogs, githubActions, logPrefix } = this.#o.output;
1077
743
  const showDetail = !this.#streaming && a.lines.length > 0 && (outputLogs === "full" || outputLogs === "errors-only" && failed);
1078
744
  const judged = result.meta?.errorKind === "judge" && (showDetail || this.#streaming);
1079
745
  const errors = failed && outputLogs !== "none" && !judged ? missed ? failureLines(colors(false), result, { max: 1 }).filter((l) => l.trim()).slice(0, 1).map((l) => c.dim(l)) : failureLines(c, result, { max: ERROR_LINES }) : [];
1080
746
  const lines = a.lines.filter((l) => l.kind !== "cleanup").sort((x, y) => x.at - y.at);
1081
747
  const prefixed = logPrefix === "task";
748
+ const head = `${this.#prefix(a)} ${c.dim("▶")} ${result.id}`;
1082
749
  const group = githubActions && showDetail && (!failed || missed);
1083
- this.#write(group ? `::group::${stripAnsi(head)}` : head);
750
+ if (showDetail || !this.#streaming && errors.length) this.#write(group ? `::group::${stripAnsi(head)}` : head);
1084
751
  if (showDetail) for (const line of lines) this.#write(this.#detail(a, line, prefixed));
1085
752
  for (const line of errors) this.#write(prefixed ? `${this.#prefix(a)} ${line}` : ` ${line}`);
1086
753
  if (group) this.#write("::endgroup::");
@@ -1096,7 +763,7 @@ var PlainRenderer = class {
1096
763
  /** Prints the heartbeat if nothing was written for `heartbeatMs` and evals are running. */
1097
764
  tick(now = this.#now()) {
1098
765
  const { heartbeatMs } = this.#o.output;
1099
- if (heartbeatMs <= 0 || this.#running.size === 0) return;
766
+ if (this.#live || heartbeatMs <= 0 || this.#running.size === 0) return;
1100
767
  if (now - this.#lastWrite < heartbeatMs) return;
1101
768
  const c = this.#c;
1102
769
  const running = [...this.#running.values()].map((a) => {
@@ -1109,6 +776,7 @@ var PlainRenderer = class {
1109
776
  }
1110
777
  close() {
1111
778
  clearInterval(this.#timer);
779
+ this.#clearStatus();
1112
780
  }
1113
781
  };
1114
782
  //#endregion
@@ -1172,7 +840,7 @@ function resolveOutput(input) {
1172
840
  mode,
1173
841
  logOrder,
1174
842
  logPrefix,
1175
- outputLogs: logs && logs !== "auto" ? logs : "full",
843
+ outputLogs: logs && logs !== "auto" ? logs : flags.verbose ? "full" : "errors-only",
1176
844
  color: env.NO_COLOR ? false : env.FORCE_COLOR !== void 0 && env.FORCE_COLOR !== "" ? set(env, "FORCE_COLOR") : mode === "agent" ? false : input.isTTY || githubActions,
1177
845
  githubActions,
1178
846
  heartbeatMs: mode === "agent" ? 0 : parseHeartbeat(env.REEVAL_HEARTBEAT)
@@ -1248,7 +916,7 @@ async function run(argv) {
1248
916
  return values.help ? EXIT.ok : EXIT.usage;
1249
917
  }
1250
918
  if (command === "init") {
1251
- const { initCommand } = await import("./init-BrOWin3W.js");
919
+ const { initCommand } = await import("./init-fhOXED8F.js");
1252
920
  return initCommand(values, filters, {
1253
921
  out: (s) => console.log(s),
1254
922
  input: process.stdin,
@@ -1257,7 +925,7 @@ async function run(argv) {
1257
925
  });
1258
926
  }
1259
927
  if (command === "doctor") {
1260
- const { doctorCommand } = await import("./doctor-BYNok4UO.js");
928
+ const { doctorCommand } = await import("./doctor-D2MbNO8L.js");
1261
929
  return doctorCommand(values, {
1262
930
  out: (s) => console.log(s),
1263
931
  color: !!process.stdout.isTTY && !process.env.NO_COLOR,
@@ -1265,7 +933,7 @@ async function run(argv) {
1265
933
  });
1266
934
  }
1267
935
  if (command === "report") {
1268
- const { reportCommand } = await import("./command-BLfT7vnQ.js");
936
+ const { reportCommand } = await import("./command-DbAe1Rzb.js");
1269
937
  return reportCommand(values, filters, {
1270
938
  out: (s) => console.log(s),
1271
939
  err: (s) => console.error(dim(s)),
@@ -1280,7 +948,7 @@ async function run(argv) {
1280
948
  }
1281
949
  if (command === "studio") {
1282
950
  const config = await loadConfig(configPath, "studio");
1283
- const { studioCommand } = await import("./command-CMJtHKRa.js");
951
+ const { studioCommand } = await import("./command-BlM0y8jN.js");
1284
952
  return studioCommand({
1285
953
  config,
1286
954
  flags: values,
@@ -1291,7 +959,7 @@ async function run(argv) {
1291
959
  if (command === "mcp") {
1292
960
  if (!values.http) console.log = console.info = console.debug = console.error;
1293
961
  const config = await loadConfig(configPath, "mcp");
1294
- const { mcpCommand } = await import("./command-BT9a37ZR.js");
962
+ const { mcpCommand } = await import("./command-TgbzPizb.js");
1295
963
  return mcpCommand({
1296
964
  config,
1297
965
  flags: values,
@@ -1300,7 +968,7 @@ async function run(argv) {
1300
968
  }
1301
969
  if (command in HISTORY_COMMANDS) {
1302
970
  const config = await loadConfig(configPath, command);
1303
- const commands = await import("./commands-1p-bIWhN.js");
971
+ const commands = await import("./commands-CthqwkAn.js");
1304
972
  const ctx = {
1305
973
  config,
1306
974
  flags: values,
@@ -1313,7 +981,7 @@ async function run(argv) {
1313
981
  case "compare": return commands.compareCommand(ctx, filters);
1314
982
  case "checkout": return commands.checkoutCommand(ctx, filters);
1315
983
  case "query": {
1316
- const { queryCommand } = await import("./query-C_G_svLU.js");
984
+ const { queryCommand } = await import("./query-CRQfsw0e.js");
1317
985
  return queryCommand({
1318
986
  ...ctx,
1319
987
  err: (s) => console.error(dim(s))
@@ -1321,7 +989,7 @@ async function run(argv) {
1321
989
  }
1322
990
  case "analyze": {
1323
991
  loadEnvFiles(configPath);
1324
- const { analyzeCommand } = await import("./command-BkFjijN2.js");
992
+ const { analyzeCommand } = await import("./command-C-cVjlny.js");
1325
993
  return analyzeCommand({
1326
994
  ...ctx,
1327
995
  err: (s) => console.error(dim(s))
@@ -1360,8 +1028,8 @@ async function cleanCommand(flags, configPath) {
1360
1028
  const where = fromCwd(debugRoot(config.root)) || ".";
1361
1029
  console.log(runs.length ? `Removed debug data for ${runs.length} run${runs.length === 1 ? "" : "s"} (${formatBytes(bytes)}) from ${where}` : `No debug data to remove in ${where}`);
1362
1030
  if (flags.images) {
1363
- const { dockerAvailable, pruneImages } = await import("./src-pJZOrYR9.js");
1364
- const { requireDocker } = await import("./providers-gDMko8fl.js");
1031
+ const { dockerAvailable, pruneImages } = await import("./src-DYO3DdnQ.js");
1032
+ const { requireDocker } = await import("./providers-B9yTdIqF.js");
1365
1033
  const engines = [];
1366
1034
  for (const engine of ["docker", "podman"]) if (await dockerAvailable(engine)) engines.push(engine);
1367
1035
  if (!engines.length) await requireDocker();
@@ -1382,7 +1050,7 @@ function verbosityOf(flags) {
1382
1050
  * does. Needs a config, as `reeval run` does: there is no default image.
1383
1051
  */
1384
1052
  async function imageBuildCommand(flags, configPath, filters) {
1385
- const { buildImages, imagePlanLines, imageTargets, plannedImageUses } = await import("./images-0On0cztu.js");
1053
+ const { buildImages, imagePlanLines, imageTargets, plannedImageUses } = await import("./images-Bi3aGxb9.js");
1386
1054
  const { runId, stagingDir, config, runs, tags, concurrency, profile } = await startRun(await prepareRun({
1387
1055
  ...flags,
1388
1056
  "dry-run": true
@@ -1444,11 +1112,10 @@ async function runCommand(flags, configPath, filters) {
1444
1112
  if (stepStart) await appendFile(stepStart, `run ${ctx.runId}\n`).catch(() => {});
1445
1113
  const { engineVersions } = await import("./node-B3ydHo6t.js");
1446
1114
  const renderer = createRenderer({
1447
- out: setup.json ? { write: () => true } : process.stdout,
1115
+ out: setup.json ? setup.dryRun ? { write: () => true } : process.stderr : process.stdout,
1448
1116
  output: setup.output,
1449
1117
  verbosity: ctx.verbosity ?? 0,
1450
- harness: setup.config.harness[0]?.kind ?? "agent",
1451
- attemptDir: (id, cell, n) => fromCwd(join(ctx.scratch, ctx.runId, evalSlug(id), evalSlug(cell), String(n)))
1118
+ harness: setup.config.harness[0]?.kind ?? "agent"
1452
1119
  });
1453
1120
  let executed;
1454
1121
  try {
@@ -1465,14 +1132,14 @@ async function runCommand(flags, configPath, filters) {
1465
1132
  invocation.unhandledErrors = engineRun.unhandledErrors;
1466
1133
  const engines = [...new Set(plan?.sandboxes.flatMap((s) => s.kind === "docker" ? [s.engine ?? "docker"] : []))];
1467
1134
  if ((interrupted || engineRun.cancelled) && engines.length) {
1468
- const { removeRunContainers } = await import("./docker-yauK-9X8.js");
1135
+ const { removeRunContainers } = await import("./docker-DNmMPOBb.js");
1469
1136
  await removeRunContainers(ctx.runId, engines);
1470
1137
  }
1471
1138
  if (notes) {
1472
1139
  const cancelled = interrupted || engineRun.cancelled;
1473
1140
  const written = await notes.finish(cancelled);
1474
1141
  if (!cancelled && written.length) {
1475
- const { notesLine } = await import("./agent-CURAwx_q.js");
1142
+ const { notesLine } = await import("./agent-D483ru7D.js");
1476
1143
  const text = notesLine(ctx.config.root, ctx.runId, written);
1477
1144
  renderer.onEvent({
1478
1145
  type: "notice",
@@ -1489,8 +1156,8 @@ async function runCommand(flags, configPath, filters) {
1489
1156
  }
1490
1157
  const stopped = interrupted || engineRun.cancelled;
1491
1158
  const answers = questions && !stopped ? await questions.settle() : void 0;
1492
- const { lockfiles } = await import("./state-CgjQo29K.js");
1493
- const { writeScratchRun } = await import("./results-DuauQI3Z.js");
1159
+ const { lockfiles } = await import("./state-DpAxYyED.js");
1160
+ const { writeScratchRun } = await import("./results-BE2f-1XS.js");
1494
1161
  const run = await writeScratchRun({
1495
1162
  ctx,
1496
1163
  author: ctx.author,
@@ -1515,8 +1182,8 @@ async function runCommand(flags, configPath, filters) {
1515
1182
  }, () => live?.stop());
1516
1183
  const { record } = run;
1517
1184
  if (notes && !stopped) {
1518
- const { summarizeRun } = await import("./agent-CURAwx_q.js");
1519
- const { resolveAnalysisModel } = await import("./model-NM3ID0uR.js");
1185
+ const { summarizeRun } = await import("./agent-D483ru7D.js");
1186
+ const { resolveAnalysisModel } = await import("./model-CXhrziBe.js");
1520
1187
  const model = resolveAnalysisModel(ctx.config, "agent");
1521
1188
  const { level, text } = await summarizeRun(ctx.config, record.runId, model);
1522
1189
  renderer.onEvent({
@@ -1535,7 +1202,8 @@ async function runCommand(flags, configPath, filters) {
1535
1202
  record,
1536
1203
  summaryPath: fromCwd(summary),
1537
1204
  results: engineRun.evals,
1538
- unhandledErrors: engineRun.unhandledErrors
1205
+ unhandledErrors: engineRun.unhandledErrors,
1206
+ hint: !hasAnalysisModel(ctx.config)
1539
1207
  });
1540
1208
  renderer.close();
1541
1209
  const stepSummary = process.env.GITHUB_STEP_SUMMARY;
@@ -1543,12 +1211,18 @@ async function runCommand(flags, configPath, filters) {
1543
1211
  const { config } = ctx;
1544
1212
  const mode = setup.record;
1545
1213
  if ((flags.record || mode === "always" || mode === "ci" && inCI()) && record.status !== "interrupted") {
1546
- const { record: recordCmd } = await import("./commands-1p-bIWhN.js");
1214
+ const { record: recordCmd } = await import("./commands-CthqwkAn.js");
1547
1215
  const allow = record.status === "budget" ? { "allow-incomplete": true } : {};
1548
- console.log(await recordCmd(config, record.runId, {
1216
+ const line = await recordCmd(config, record.runId, {
1549
1217
  ...flags,
1550
1218
  ...allow
1551
- }));
1219
+ });
1220
+ if (setup.json) console.error(line);
1221
+ else console.log(line);
1222
+ }
1223
+ if (setup.json) {
1224
+ const { suiteResult } = await import("./suite-DamAEnNF.js");
1225
+ process.stdout.write(`${JSON.stringify(suiteResult(record), null, 2)}\n`);
1552
1226
  }
1553
1227
  if (interrupted || engineRun.cancelled) return stopCode;
1554
1228
  if (engineRun.unhandledErrors.length > 0) return EXIT.failed;
@@ -1562,13 +1236,13 @@ async function prepareRun(flags, configPath) {
1562
1236
  ui: flags.ui,
1563
1237
  logOrder: flags["log-order"],
1564
1238
  logPrefix: flags["log-prefix"],
1565
- outputLogs: flags["output-logs"]
1239
+ outputLogs: flags["output-logs"],
1240
+ verbose: verbosityOf(flags) > 0
1566
1241
  },
1567
1242
  env: process.env,
1568
- isTTY: !!process.stdout.isTTY,
1243
+ isTTY: !!(flags.json && !flags["dry-run"] ? process.stderr : process.stdout).isTTY,
1569
1244
  agent: detectAgent().name
1570
1245
  });
1571
- if (flags.json && !flags["dry-run"]) throw new UsageError("reeval run --json only prints the plan: add --dry-run. A run writes its record to .reeval/runs; read it with reeval show --json.");
1572
1246
  const path = requireConfig(configPath);
1573
1247
  loadEnvFiles(path);
1574
1248
  const named = flags.profile ?? (process.env.REEVAL_PROFILE || void 0);
@@ -1583,7 +1257,7 @@ async function prepareRun(flags, configPath) {
1583
1257
  const concurrency = await resolveConcurrency(config, flags.concurrency, async () => {
1584
1258
  const container = sandboxes.find((s) => s.kind === "docker");
1585
1259
  if (!container) return hostCapacity();
1586
- const { dockerCapacity } = await import("./src-pJZOrYR9.js");
1260
+ const { dockerCapacity } = await import("./src-DYO3DdnQ.js");
1587
1261
  return await dockerCapacity(container.engine) ?? hostCapacity();
1588
1262
  });
1589
1263
  return {
@@ -1610,11 +1284,11 @@ async function prepareRun(flags, configPath) {
1610
1284
  async function startRun({ config, profile, runs, tags, concurrency, verbosity, configFile, resume, dryRun }) {
1611
1285
  const startedAt = /* @__PURE__ */ new Date();
1612
1286
  const git = await gitInfo(config.root, [config.history.dir]);
1613
- const { worktreePatch } = await import("./state-CgjQo29K.js");
1287
+ const { worktreePatch } = await import("./state-DpAxYyED.js");
1614
1288
  const patch = git?.dirty ? await worktreePatch(config.root, [config.history.dir]) : null;
1615
1289
  const who = await author(config.root);
1616
- const { stagingDir, sweepStaging } = await import("./results-DuauQI3Z.js");
1617
- const { scratchDir } = await import("./files-ZZPqfAo6.js");
1290
+ const { stagingDir, sweepStaging } = await import("./results-BE2f-1XS.js");
1291
+ const { scratchDir } = await import("./files-Bw8lWEjg.js");
1618
1292
  const scratch = scratchDir(config.root);
1619
1293
  if (resume !== void 0) {
1620
1294
  const target = await resolveResume(config.root, resume || void 0);
@@ -1625,7 +1299,7 @@ async function startRun({ config, profile, runs, tags, concurrency, verbosity, c
1625
1299
  artifacts: target.previousArtifacts
1626
1300
  } : await loadPrevious(stagingDir(config.root, target.runId));
1627
1301
  if (!dryRun) try {
1628
- const { removeRunContainers } = await import("./docker-yauK-9X8.js");
1302
+ const { removeRunContainers } = await import("./docker-DNmMPOBb.js");
1629
1303
  await removeRunContainers(target.runId, ["docker", "podman"]);
1630
1304
  } catch {}
1631
1305
  return {
@@ -1697,7 +1371,7 @@ async function executeRun(ctx, setup, filters, renderer) {
1697
1371
  completed: []
1698
1372
  }));
1699
1373
  const { runEngine } = await import("./node-B3ydHo6t.js");
1700
- const { buildPlan, checkAttemptBudget, planDocument, planLine, planTable } = await import("./plan-C9Cy27Ay.js");
1374
+ const { buildPlan, checkAttemptBudget, planDocument, planLine, planTable } = await import("./plan-DgQxp9yy.js");
1701
1375
  let plan;
1702
1376
  let sandboxVersions = { images: [] };
1703
1377
  let preflightStop;
@@ -1724,7 +1398,7 @@ async function executeRun(ctx, setup, filters, renderer) {
1724
1398
  } : p);
1725
1399
  toRun = skipped;
1726
1400
  for (const p of skipped) for (const name of p.attempt.secretVars) registerSecret(process.env[name]);
1727
- const models = skipped.some((p) => !p.attempt.plan.skip && p.attempt.plan.questions?.length) ? await import("./model-NM3ID0uR.js") : void 0;
1401
+ const models = skipped.some((p) => !p.attempt.plan.skip && p.attempt.plan.questions?.length) ? await import("./model-CXhrziBe.js") : void 0;
1728
1402
  plan = await buildPlan({
1729
1403
  planned: skipped,
1730
1404
  profile,
@@ -1740,13 +1414,13 @@ async function executeRun(ctx, setup, filters, renderer) {
1740
1414
  completed: completed.size
1741
1415
  };
1742
1416
  run.completed = [...completed];
1743
- const { imageStages, imageTargets } = await import("./images-0On0cztu.js");
1417
+ const { imageStages, imageTargets } = await import("./images-Bi3aGxb9.js");
1744
1418
  const targets = imageTargets(skipped.filter((p) => !p.attempt.plan.skip).map((p) => ({
1745
1419
  id: p.id,
1746
1420
  harness: p.attempt.harness,
1747
1421
  sandbox: p.attempt.sandbox
1748
1422
  })));
1749
- if (setup.json) {
1423
+ if (setup.json && setup.dryRun) {
1750
1424
  const images = await Promise.all(targets.map(async (t) => ({
1751
1425
  id: t.id,
1752
1426
  harness: t.harness,
@@ -1761,8 +1435,8 @@ async function executeRun(ctx, setup, filters, renderer) {
1761
1435
  if (setup.dryRun) {
1762
1436
  const todos = excluded.filter((e) => e.mode === "todo").map((e) => e.id);
1763
1437
  lines.push(...planTable(plan, todos));
1764
- const { imageStatusLines } = await import("./images-0On0cztu.js");
1765
- const { dockerAvailable, engineSpec } = await import("./src-pJZOrYR9.js");
1438
+ const { imageStatusLines } = await import("./images-Bi3aGxb9.js");
1439
+ const { dockerAvailable, engineSpec } = await import("./src-DYO3DdnQ.js");
1766
1440
  const engines = [...new Set(targets.map((t) => t.sandbox.engine ?? "docker"))];
1767
1441
  const down = [];
1768
1442
  for (const engine of engines) if (!await dockerAvailable(engine)) down.push(engine);
@@ -1782,7 +1456,7 @@ async function executeRun(ctx, setup, filters, renderer) {
1782
1456
  });
1783
1457
  if (setup.dryRun) return false;
1784
1458
  checkAttemptBudget(plan, setup.force, config.file);
1785
- const analysis = config.analysis.agent ? await import("./model-NM3ID0uR.js") : null;
1459
+ const analysis = config.analysis.agent ? await import("./model-CXhrziBe.js") : null;
1786
1460
  analysis?.analysisModelName(config, "agent");
1787
1461
  const questionModels = /* @__PURE__ */ new Set();
1788
1462
  const asked = [];
@@ -1814,7 +1488,7 @@ async function executeRun(ctx, setup, filters, renderer) {
1814
1488
  });
1815
1489
  if (malformed.length) throw new UsageError(`Credentials with whitespace or a line break in them: ${malformed.join(", ")}. A key copied from a wrapped terminal line picks these up; set it again as one line.`);
1816
1490
  if (analysis) {
1817
- const { startNotes } = await import("./agent-CURAwx_q.js");
1491
+ const { startNotes } = await import("./agent-D483ru7D.js");
1818
1492
  notes = startNotes({
1819
1493
  config,
1820
1494
  model: analysis.resolveAnalysisModel(config, "agent"),
@@ -1830,7 +1504,7 @@ async function executeRun(ctx, setup, filters, renderer) {
1830
1504
  });
1831
1505
  }
1832
1506
  if (asked.length) {
1833
- const { questionRunner } = await import("./questions-DjAwMxZ3.js");
1507
+ const { questionRunner } = await import("./questions-C2dym2ce.js");
1834
1508
  questions = questionRunner({
1835
1509
  evals: asked,
1836
1510
  stagingDir,
@@ -1847,7 +1521,7 @@ async function executeRun(ctx, setup, filters, renderer) {
1847
1521
  }
1848
1522
  });
1849
1523
  }
1850
- const { prepareWorkspaces, workspaceKey } = await import("./workspace-D8sSgpiy.js");
1524
+ const { prepareWorkspaces, workspaceKey } = await import("./workspace-C_X0tdv6.js");
1851
1525
  const live = skipped.filter((p) => !p.attempt.plan.skip);
1852
1526
  const outcomes = await prepareWorkspaces(live.flatMap(({ attempt: a }) => a.workspace ? [{
1853
1527
  workspace: a.workspace,
@@ -1995,9 +1669,9 @@ async function executeRun(ctx, setup, filters, renderer) {
1995
1669
  throw error;
1996
1670
  } finally {
1997
1671
  clearTimeout(budgetTimer);
1998
- const { removePrepared } = await import("./preflight-CPWpQeBI.js");
1672
+ const { removePrepared } = await import("./preflight-DlQvbySb.js");
1999
1673
  removePrepared(config.root, runId);
2000
- const { removePreparedWorkspaces } = await import("./workspace-D8sSgpiy.js");
1674
+ const { removePreparedWorkspaces } = await import("./workspace-C_X0tdv6.js");
2001
1675
  removePreparedWorkspaces(config.root, runId);
2002
1676
  }
2003
1677
  if (preflightStop) throw preflightStop;
@@ -2080,4 +1754,4 @@ run(process.argv.slice(2)).finally(() => {
2080
1754
  //#endregion
2081
1755
  export {};
2082
1756
 
2083
- //# sourceMappingURL=cli-D303Vj5N.js.map
1757
+ //# sourceMappingURL=cli-ClpPT8kn.js.map