reeval 0.0.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 (213) hide show
  1. package/LICENSE +202 -0
  2. package/THIRD_PARTY_NOTICES.md +2160 -0
  3. package/assets/package.json +9 -0
  4. package/assets/pnpm-lock.yaml +1336 -0
  5. package/dist/agent-DVHkx8aT.js +532 -0
  6. package/dist/agent-DVHkx8aT.js.map +1 -0
  7. package/dist/analysis-CxSCt1YY.js +16 -0
  8. package/dist/analysis-CxSCt1YY.js.map +1 -0
  9. package/dist/assemble-B-nmz8oH.js +695 -0
  10. package/dist/assemble-B-nmz8oH.js.map +1 -0
  11. package/dist/assemble-CmRVDZ2Q.js +2 -0
  12. package/dist/attempt-BdRQ9jKX.js +176 -0
  13. package/dist/attempt-BdRQ9jKX.js.map +1 -0
  14. package/dist/bridge/index.mjs +1911 -0
  15. package/dist/bridge/package.json +13 -0
  16. package/dist/bridge/pnpm-lock.yaml +1041 -0
  17. package/dist/bridge/pnpm-workspace.yaml +2 -0
  18. package/dist/budget-DBUrH4jX.js +8 -0
  19. package/dist/budget-DBUrH4jX.js.map +1 -0
  20. package/dist/cli--CQ3Iy9q.js +1865 -0
  21. package/dist/cli--CQ3Iy9q.js.map +1 -0
  22. package/dist/cli-spec-DKAu09Gi.js +478 -0
  23. package/dist/cli-spec-DKAu09Gi.js.map +1 -0
  24. package/dist/cli.d.ts +1 -0
  25. package/dist/cli.js +8 -0
  26. package/dist/cli.js.map +1 -0
  27. package/dist/colors-QV9dFVhN.js +34 -0
  28. package/dist/colors-QV9dFVhN.js.map +1 -0
  29. package/dist/command-BSJzHMtP.js +280 -0
  30. package/dist/command-BSJzHMtP.js.map +1 -0
  31. package/dist/command-CEm8PZ1N.js +1043 -0
  32. package/dist/command-CEm8PZ1N.js.map +1 -0
  33. package/dist/command-D-jnQWVG.js +673 -0
  34. package/dist/command-D-jnQWVG.js.map +1 -0
  35. package/dist/command-DQAvbG7d.js +432 -0
  36. package/dist/command-DQAvbG7d.js.map +1 -0
  37. package/dist/commands-A4udfyKZ.js +2 -0
  38. package/dist/commands-CF8mOfiu.js +207 -0
  39. package/dist/commands-CF8mOfiu.js.map +1 -0
  40. package/dist/config-Cuj0kVYj.js +415 -0
  41. package/dist/config-Cuj0kVYj.js.map +1 -0
  42. package/dist/context-loi9OCZv.js +106 -0
  43. package/dist/context-loi9OCZv.js.map +1 -0
  44. package/dist/core-tLN-z1Be.js +96 -0
  45. package/dist/core-tLN-z1Be.js.map +1 -0
  46. package/dist/db-Cjj2ZsfQ.js +2 -0
  47. package/dist/db-DxDzMhtB.js +827 -0
  48. package/dist/db-DxDzMhtB.js.map +1 -0
  49. package/dist/debug-D24NOQH1.js +89 -0
  50. package/dist/debug-D24NOQH1.js.map +1 -0
  51. package/dist/debug-SEmW4w8f.js +2 -0
  52. package/dist/dist-BZXYHN2X.js +1673 -0
  53. package/dist/dist-BZXYHN2X.js.map +1 -0
  54. package/dist/docker-DQDZWXF9.js +20 -0
  55. package/dist/docker-DQDZWXF9.js.map +1 -0
  56. package/dist/docker-DnWAVdEm.js +2 -0
  57. package/dist/docker-oSbCExHL.js +153 -0
  58. package/dist/docker-oSbCExHL.js.map +1 -0
  59. package/dist/doctor-CxlH1pDM.js +525 -0
  60. package/dist/doctor-CxlH1pDM.js.map +1 -0
  61. package/dist/egress-73SQfKdx.js +619 -0
  62. package/dist/egress-73SQfKdx.js.map +1 -0
  63. package/dist/env-BQqj93gu.js +21 -0
  64. package/dist/env-BQqj93gu.js.map +1 -0
  65. package/dist/environment-Mz7wvrtD.js +552 -0
  66. package/dist/environment-Mz7wvrtD.js.map +1 -0
  67. package/dist/errors-C9w_ud7g.js +160 -0
  68. package/dist/errors-C9w_ud7g.js.map +1 -0
  69. package/dist/errors-CSxfJ4qu.js +11 -0
  70. package/dist/errors-CSxfJ4qu.js.map +1 -0
  71. package/dist/files--6CEUXm7.js +2 -0
  72. package/dist/files-BLlrhU4-.js +62 -0
  73. package/dist/files-BLlrhU4-.js.map +1 -0
  74. package/dist/files-Bd25OAQH.js +2 -0
  75. package/dist/files-BvHCFWgD.js +2 -0
  76. package/dist/files-D2-qn_Dl.js +275 -0
  77. package/dist/files-D2-qn_Dl.js.map +1 -0
  78. package/dist/files-bF2fPuT9.js +99 -0
  79. package/dist/files-bF2fPuT9.js.map +1 -0
  80. package/dist/git-D6hMeieS.js +44 -0
  81. package/dist/git-D6hMeieS.js.map +1 -0
  82. package/dist/harness-ls5aX1UO.js +131 -0
  83. package/dist/harness-ls5aX1UO.js.map +1 -0
  84. package/dist/harness.d.ts +74 -0
  85. package/dist/harness.js +2 -0
  86. package/dist/header-DzFDoMCI.js +78 -0
  87. package/dist/header-DzFDoMCI.js.map +1 -0
  88. package/dist/ids-Bp6ut7ZD.js +49 -0
  89. package/dist/ids-Bp6ut7ZD.js.map +1 -0
  90. package/dist/images-Cc1-coFc.js +286 -0
  91. package/dist/images-Cc1-coFc.js.map +1 -0
  92. package/dist/index.d.ts +97 -0
  93. package/dist/index.js +1959 -0
  94. package/dist/index.js.map +1 -0
  95. package/dist/init-CFljS8BJ.js +344 -0
  96. package/dist/init-CFljS8BJ.js.map +1 -0
  97. package/dist/init-z2ZPn9Tj.js +2 -0
  98. package/dist/invocations-rXktgSAn.js +157 -0
  99. package/dist/invocations-rXktgSAn.js.map +1 -0
  100. package/dist/jiti-BOLXpKyG.js +46 -0
  101. package/dist/jiti-BOLXpKyG.js.map +1 -0
  102. package/dist/judge-D8Uf4dA9.js +146 -0
  103. package/dist/judge-D8Uf4dA9.js.map +1 -0
  104. package/dist/judge.d.ts +21 -0
  105. package/dist/judge.js +19 -0
  106. package/dist/judge.js.map +1 -0
  107. package/dist/live-Bs3LReMV.js +98 -0
  108. package/dist/live-Bs3LReMV.js.map +1 -0
  109. package/dist/matchers-DyLvm7EG.js +374 -0
  110. package/dist/matchers-DyLvm7EG.js.map +1 -0
  111. package/dist/model-BdO79gWz.js +44 -0
  112. package/dist/model-BdO79gWz.js.map +1 -0
  113. package/dist/model-CDL98xue.js +725 -0
  114. package/dist/model-CDL98xue.js.map +1 -0
  115. package/dist/model-v-0_Ik7S.js +2 -0
  116. package/dist/node-kG64XxdE.js +506 -0
  117. package/dist/node-kG64XxdE.js.map +1 -0
  118. package/dist/opencode-providers-DZuD_oYt.js +3149 -0
  119. package/dist/opencode-providers-DZuD_oYt.js.map +1 -0
  120. package/dist/options-CAQhu--C.js +452 -0
  121. package/dist/options-CAQhu--C.js.map +1 -0
  122. package/dist/patch-BkKje4cp.js +69 -0
  123. package/dist/patch-BkKje4cp.js.map +1 -0
  124. package/dist/paths-CBvm6pap.js +72 -0
  125. package/dist/paths-CBvm6pap.js.map +1 -0
  126. package/dist/plan-gwk6dJ8c.js +237 -0
  127. package/dist/plan-gwk6dJ8c.js.map +1 -0
  128. package/dist/preflight-BtubXKQ8.js +2 -0
  129. package/dist/preflight-BypZMNBG.js +185 -0
  130. package/dist/preflight-BypZMNBG.js.map +1 -0
  131. package/dist/prepare-Cwv0bHs_.js +3 -0
  132. package/dist/prepare-D6Uzcubb.js +213 -0
  133. package/dist/prepare-D6Uzcubb.js.map +1 -0
  134. package/dist/provenance-Dfb8YY5Y.js +129 -0
  135. package/dist/provenance-Dfb8YY5Y.js.map +1 -0
  136. package/dist/provider-BDbNOQhQ.js +2 -0
  137. package/dist/provider-CmAYTQQs.js +14 -0
  138. package/dist/provider-CmAYTQQs.js.map +1 -0
  139. package/dist/providers-2p3ylMHI.js +107 -0
  140. package/dist/providers-2p3ylMHI.js.map +1 -0
  141. package/dist/providers-BUOxitcT.js +2 -0
  142. package/dist/query-CFATHZmV.js +91 -0
  143. package/dist/query-CFATHZmV.js.map +1 -0
  144. package/dist/query-DR4m6CXf.js +2 -0
  145. package/dist/record-DQ8wzyco.js +99 -0
  146. package/dist/record-DQ8wzyco.js.map +1 -0
  147. package/dist/redact-C4fL_bZP.js +167 -0
  148. package/dist/redact-C4fL_bZP.js.map +1 -0
  149. package/dist/results-CeXb8Wde.js +37 -0
  150. package/dist/results-CeXb8Wde.js.map +1 -0
  151. package/dist/root-CFDjpWuc.js +110 -0
  152. package/dist/root-CFDjpWuc.js.map +1 -0
  153. package/dist/sandbox-By2gkdkC.js +133 -0
  154. package/dist/sandbox-By2gkdkC.js.map +1 -0
  155. package/dist/sandbox.d.ts +41 -0
  156. package/dist/sandbox.js +2 -0
  157. package/dist/server-Bi61uiY0.js +350 -0
  158. package/dist/server-Bi61uiY0.js.map +1 -0
  159. package/dist/server-CsSBL8NC.js +2 -0
  160. package/dist/source-BXzrmof5.js +2 -0
  161. package/dist/source-Bsfa3LZH.js +40 -0
  162. package/dist/source-Bsfa3LZH.js.map +1 -0
  163. package/dist/src-55j1zNHH.js +3 -0
  164. package/dist/src-AEwxd1UP.js +602 -0
  165. package/dist/src-AEwxd1UP.js.map +1 -0
  166. package/dist/src-BDwSuyIo.js +3 -0
  167. package/dist/src-BQyMiWri.js +490 -0
  168. package/dist/src-BQyMiWri.js.map +1 -0
  169. package/dist/src-C-LHyTSV.js +3 -0
  170. package/dist/src-Cmp-7YrD.js +1136 -0
  171. package/dist/src-Cmp-7YrD.js.map +1 -0
  172. package/dist/src-D0RdqpNb.js +252 -0
  173. package/dist/src-D0RdqpNb.js.map +1 -0
  174. package/dist/src-D8KYzxBX.js +793 -0
  175. package/dist/src-D8KYzxBX.js.map +1 -0
  176. package/dist/src-DEgff9Z7.js +4 -0
  177. package/dist/src-DXx_29pq.js +567 -0
  178. package/dist/src-DXx_29pq.js.map +1 -0
  179. package/dist/src-DwwiVLqv.js +2937 -0
  180. package/dist/src-DwwiVLqv.js.map +1 -0
  181. package/dist/src-N7E_mfcZ.js +2 -0
  182. package/dist/src-W9g-y5X5.js +3 -0
  183. package/dist/src-daS0wKH2.js +3 -0
  184. package/dist/state-Cyw3QTsN.js +2 -0
  185. package/dist/state-DZ7eqb1F.js +167 -0
  186. package/dist/state-DZ7eqb1F.js.map +1 -0
  187. package/dist/stats-BNAHlNMD.js +114 -0
  188. package/dist/stats-BNAHlNMD.js.map +1 -0
  189. package/dist/studio-app/assets/index-D6XyfFSH.js +58 -0
  190. package/dist/studio-app/assets/index-xwzWdcE_.css +2 -0
  191. package/dist/studio-app/favicon.svg +1 -0
  192. package/dist/studio-app/index.html +15 -0
  193. package/dist/summary-D7Ttky0z.js +166 -0
  194. package/dist/summary-D7Ttky0z.js.map +1 -0
  195. package/dist/text-gEcKjAyp.js +29 -0
  196. package/dist/text-gEcKjAyp.js.map +1 -0
  197. package/dist/types-C5vI3g1C.js +9 -0
  198. package/dist/types-C5vI3g1C.js.map +1 -0
  199. package/dist/types-DLec-6Cx.d.ts +1535 -0
  200. package/dist/usage-DsYUqIUM.js +24 -0
  201. package/dist/usage-DsYUqIUM.js.map +1 -0
  202. package/dist/view/index.d.ts +645 -0
  203. package/dist/view/index.js +8 -0
  204. package/dist/views-BrHOv6wg.js +220 -0
  205. package/dist/views-BrHOv6wg.js.map +1 -0
  206. package/dist/views-CwCWLWqo.js +3 -0
  207. package/dist/worker-entry-DnYkANPG.js +506 -0
  208. package/dist/worker-entry-DnYkANPG.js.map +1 -0
  209. package/dist/workspace-C2S0Z6gl.js +327 -0
  210. package/dist/workspace-C2S0Z6gl.js.map +1 -0
  211. package/dist/workspace-CyoXG6CY.js +2 -0
  212. package/docker/Dockerfile +19 -0
  213. package/package.json +79 -0
@@ -0,0 +1,695 @@
1
+ import { n as isTimeout } from "./errors-CSxfJ4qu.js";
2
+ import "./environment-Mz7wvrtD.js";
3
+ import { i as redactSecrets } from "./redact-C4fL_bZP.js";
4
+ import { i as evalSlug, l as sha256, n as attemptKey, s as recordFileName, t as attemptId } from "./ids-Bp6ut7ZD.js";
5
+ import { s as judgeModelName } from "./judge-D8Uf4dA9.js";
6
+ import { s as harnessId, u as sandboxId } from "./options-CAQhu--C.js";
7
+ import { n as collapseDependencies, r as patchForJudge } from "./patch-BkKje4cp.js";
8
+ import { o as round3, t as liftInterval } from "./stats-BNAHlNMD.js";
9
+ import { n as promptTokens, r as sumUsage } from "./usage-DsYUqIUM.js";
10
+ import { a as packageVersions, r as judgeVersion, t as FINGERPRINT_SCOPE } from "./state-DZ7eqb1F.js";
11
+ import { dirname, join, relative, resolve, sep } from "node:path";
12
+ import { readFile, stat } from "node:fs/promises";
13
+ //#region src/history/sources.ts
14
+ /** `from '…'`, `import '…'`, `import('…')` and `export … from '…'`, with a literal specifier. */
15
+ const SPECIFIER = /(?:\bfrom\s*|\bimport\s*\(\s*|\bimport\s+)(['"])((?:\.{1,2}\/|\/)[^'"]+)\1/g;
16
+ const CANDIDATES = (path) => {
17
+ return [
18
+ path,
19
+ .../\.(m?js|cjs)$/.exec(path) ? [path.replace(/\.(m?js|cjs)$/, ".ts"), path.replace(/\.(m?js|cjs)$/, ".tsx")] : [],
20
+ `${path}.ts`,
21
+ `${path}.tsx`,
22
+ `${path}.js`,
23
+ `${path}.mjs`,
24
+ join(path, "index.ts"),
25
+ join(path, "index.js")
26
+ ];
27
+ };
28
+ async function isFile(path) {
29
+ return (await stat(path).catch(() => null))?.isFile() ?? false;
30
+ }
31
+ async function resolveImport(from, specifier) {
32
+ const base = specifier.startsWith("/") ? specifier : resolve(dirname(from), specifier);
33
+ for (const candidate of CANDIDATES(base)) if (await isFile(candidate)) return candidate;
34
+ return null;
35
+ }
36
+ /**
37
+ * The eval file and every local module it imports, transitively, by path from `root` and
38
+ * content hash, sorted by path. Only relative and absolute specifiers are followed: packages
39
+ * (`reeval`, `node:*`, anything in `node_modules`) aren't traced.
40
+ */
41
+ async function traceSources(root, file) {
42
+ const seen = /* @__PURE__ */ new Map();
43
+ const queue = [resolve(root, file)];
44
+ while (queue.length) {
45
+ const path = queue.shift();
46
+ if (seen.has(path) || path.split(sep).includes("node_modules")) continue;
47
+ const bytes = await readFile(path).catch(() => null);
48
+ if (!bytes) continue;
49
+ seen.set(path, {
50
+ path: relative(root, path).split(sep).join("/"),
51
+ sha256: sha256(bytes)
52
+ });
53
+ for (const match of bytes.toString("utf8").matchAll(SPECIFIER)) {
54
+ const found = await resolveImport(path, match[2]);
55
+ if (found && !seen.has(found)) queue.push(found);
56
+ }
57
+ }
58
+ return [...seen.values()].sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
59
+ }
60
+ //#endregion
61
+ //#region src/history/assemble.ts
62
+ /** Final messages are cut at this size in the record; `transcript.jsonl` keeps them whole. */
63
+ const TURN_TEXT_LIMIT = 8192;
64
+ const TURN_ERROR_LIMIT = 1024;
65
+ /** A turn's first error event, such as the provider's "Credit balance is too low". */
66
+ function turnError(transcript) {
67
+ const found = transcript?.find((e) => e.type === "error");
68
+ if (found?.type !== "error") return null;
69
+ const message = found.message.trim();
70
+ return message.length > TURN_ERROR_LIMIT ? `${message.slice(0, TURN_ERROR_LIMIT)}…` : message;
71
+ }
72
+ /** Tokens across every turn that reported them. */
73
+ function costOf(attempts) {
74
+ const usage = sumUsage(attempts.map((a) => a.usage));
75
+ if (!usage) return {
76
+ inputTokens: null,
77
+ outputTokens: null,
78
+ usage: null,
79
+ source: "unreported"
80
+ };
81
+ return {
82
+ inputTokens: promptTokens(usage),
83
+ outputTokens: usage.output,
84
+ usage,
85
+ source: "reported"
86
+ };
87
+ }
88
+ /** A single tool output, check stream or file diff bigger than this keeps its head and tail. */
89
+ const OUTPUT_CAP = 131072;
90
+ const HEAD = 98304;
91
+ const TAIL = 16384;
92
+ /** Keeps evidence readable without letting one `cat` of a lockfile dominate the record. */
93
+ function capText(text, cap = OUTPUT_CAP) {
94
+ if (text.length <= cap) return text;
95
+ const omitted = text.length - HEAD - TAIL;
96
+ return `${text.slice(0, HEAD)}\n[reeval: truncated ${omitted} of ${text.length} characters, sha256 ${sha256(text)}]\n${text.slice(-16384)}`;
97
+ }
98
+ const readRecord = async (path) => JSON.parse(await readFile(path, "utf8").catch(() => "null"));
99
+ /** The engine and the worker's record can disagree, e.g. when a timeout fails the eval first. */
100
+ function mergeOutcome(e, record) {
101
+ if (e.state === "skipped" && record && record.outcome !== "pass") return {
102
+ outcome: record.outcome,
103
+ error: record.error
104
+ };
105
+ if (e.state === "skipped") return {
106
+ outcome: "skipped",
107
+ error: null
108
+ };
109
+ if (e.state === "passed") return {
110
+ outcome: "pass",
111
+ error: null
112
+ };
113
+ const message = e.errors[0] ?? "Eval failed";
114
+ const error = record?.error ?? (isTimeout(message) ? {
115
+ kind: "timeout",
116
+ message
117
+ } : {
118
+ kind: "assertion",
119
+ message
120
+ });
121
+ return {
122
+ outcome: record?.outcome === "infra_error" ? "infra_error" : "fail",
123
+ error
124
+ };
125
+ }
126
+ /** Any failure fails; then infra errors; then all-skipped; else pass. */
127
+ function worstOutcome(outcomes) {
128
+ if (outcomes.includes("fail")) return "fail";
129
+ if (outcomes.includes("infra_error")) return "infra_error";
130
+ if (outcomes.length > 0 && outcomes.every((o) => o === "skipped")) return "skipped";
131
+ return outcomes.length ? "pass" : "skipped";
132
+ }
133
+ const passRateOf = (outcomes) => {
134
+ const pass = outcomes.filter((o) => o === "pass").length;
135
+ const counted = pass + outcomes.filter((o) => o === "fail").length;
136
+ return counted ? pass / counted : null;
137
+ };
138
+ /** Concurrency caps change how fast a run goes, not what it measures. */
139
+ /** Without the operational limits (`maxConcurrent`, `startTimeout`), which don't change results. */
140
+ const withoutCaps = ({ maxConcurrent: _, startTimeout: __, ...rest }) => rest;
141
+ const harnessModel = (h) => h.kind === "fake" ? null : h.model ?? null;
142
+ /** A cell fingerprint: the hash of its parts, so each part can be compared on its own. */
143
+ const fingerprintOf = (parts) => sha256(JSON.stringify(parts));
144
+ /** `<index>:<question hash>`, which follows one verdict across runs. */
145
+ const judgementKey = (index, question) => `${index}:${sha256(question).slice(0, 12)}`;
146
+ /** Collects artifact files, redacting before anything is hashed. */
147
+ var Artifacts = class {
148
+ files = /* @__PURE__ */ new Map();
149
+ add(path, content) {
150
+ const bytes = Buffer.from(redactSecrets(content));
151
+ this.files.set(path, bytes);
152
+ return {
153
+ path,
154
+ sha256: sha256(bytes),
155
+ bytes: bytes.length
156
+ };
157
+ }
158
+ json(path, value) {
159
+ return this.add(path, `${JSON.stringify(value, null, 2)}\n`);
160
+ }
161
+ };
162
+ const endOf = (startedAt, durationMs) => new Date(Date.parse(startedAt) + durationMs).toISOString();
163
+ /** One JSON object per line: each turn's prompt, its events, then a `turn-end`. */
164
+ function transcriptLines(record) {
165
+ const lines = [];
166
+ record.turns.forEach((turn, index) => {
167
+ lines.push(JSON.stringify({
168
+ ts: turn.startedAt,
169
+ atMs: 0,
170
+ turn: index,
171
+ type: "prompt",
172
+ text: turn.prompt
173
+ }));
174
+ for (const event of turn.transcript) {
175
+ if (event.type === "tool") {
176
+ const raw = typeof event.output === "string" ? event.output : JSON.stringify(event.output, null, 2);
177
+ if (raw !== void 0 && raw.length > 131072) {
178
+ lines.push(JSON.stringify({
179
+ turn: index,
180
+ ...event,
181
+ output: capText(raw)
182
+ }));
183
+ continue;
184
+ }
185
+ }
186
+ lines.push(JSON.stringify({
187
+ turn: index,
188
+ ...event
189
+ }));
190
+ }
191
+ lines.push(JSON.stringify({
192
+ ts: endOf(turn.startedAt, turn.durationMs),
193
+ atMs: turn.durationMs,
194
+ turn: index,
195
+ type: "turn-end",
196
+ status: turn.status,
197
+ durationMs: turn.durationMs
198
+ }));
199
+ });
200
+ return `${lines.join("\n")}\n`;
201
+ }
202
+ /** Every stream part the harness sent, for debugging the normaliser (`REEVAL_RAW_TRANSCRIPT=1`). */
203
+ function rawLines(record) {
204
+ if (!record.turns.some((t) => t.raw)) return null;
205
+ return `${record.turns.flatMap((turn, index) => (turn.raw ?? []).map((part) => JSON.stringify({
206
+ turn: index,
207
+ ...part
208
+ }))).join("\n")}\n`;
209
+ }
210
+ function activity(record) {
211
+ const events = record.turns.flatMap((t) => t.transcript);
212
+ const count = (type) => events.filter((e) => e.type === type).length;
213
+ const web = (type) => {
214
+ const n = count(type);
215
+ return n === 0 && record.turns.some((t) => t.unreported?.includes(type)) ? null : n;
216
+ };
217
+ const reasoningMs = events.reduce((n, e) => n + (e.type === "reasoning" ? e.durationMs ?? 0 : 0), 0);
218
+ return {
219
+ tools: count("tool"),
220
+ fileEdits: count("file-edit"),
221
+ webSearches: web("web-search"),
222
+ webFetches: web("web-fetch"),
223
+ reasoningMs
224
+ };
225
+ }
226
+ const block = (label, text) => {
227
+ const body = capText(text);
228
+ return `--- ${label}\n${body}${body.endsWith("\n") || !body ? "" : "\n"}`;
229
+ };
230
+ const checkLog = (c) => `$ ${c.command}\nexit ${c.exitCode}\n${block("stdout", c.stdout)}${block("stderr", c.stderr)}`;
231
+ /** Dependency and binary noise dropped, and each remaining file's diff capped. */
232
+ function historyPatch(patch) {
233
+ return patchForJudge(patch).split(/(?=^diff --git )/m).map((part) => capText(part)).join("");
234
+ }
235
+ function changedFiles(files) {
236
+ const { kept, dirs } = collapseDependencies(files, (f) => f.path);
237
+ return [...kept, ...dirs.map((d) => ({
238
+ path: d.dir,
239
+ status: "added",
240
+ count: d.count
241
+ }))];
242
+ }
243
+ /** Judge inputs whose diff is the recorded diff point at `diff.patch` instead of repeating it. */
244
+ function judgeInputs(record, diff, diffPath) {
245
+ return (record.judgeInputs ?? []).map((input) => {
246
+ if (diff === null || input.state.diff !== diff) return input;
247
+ return {
248
+ ...input,
249
+ state: {
250
+ ...input.state,
251
+ diff: {
252
+ $ref: diffPath,
253
+ sha256: sha256(diff)
254
+ }
255
+ }
256
+ };
257
+ });
258
+ }
259
+ /** What the run's attempts have in common, gathered while their records are read. */
260
+ var Seen = class {
261
+ sources = /* @__PURE__ */ new Map();
262
+ byEval = /* @__PURE__ */ new Map();
263
+ contexts = /* @__PURE__ */ new Map();
264
+ resolvedJudges = /* @__PURE__ */ new Set();
265
+ images = /* @__PURE__ */ new Map();
266
+ environments = /* @__PURE__ */ new Map();
267
+ harnesses = /* @__PURE__ */ new Map();
268
+ resolvedHarnesses = /* @__PURE__ */ new Map();
269
+ /** Registry digests found by the preflight, by image id. */
270
+ digests;
271
+ constructor(sandbox) {
272
+ this.digests = new Map(sandbox.images.map((i) => [i.id, i.repoDigests]));
273
+ }
274
+ add(record, cell, e) {
275
+ for (const c of record?.context ?? []) this.contexts.set(`${c.path}\0${c.sha256}`, c);
276
+ for (const j of record?.judgements ?? []) if (j.resolvedModel) this.resolvedJudges.add(j.resolvedModel);
277
+ if (record?.image) {
278
+ const repoDigests = this.digests.get(record.image.id) ?? [];
279
+ this.images.set(record.image.id, {
280
+ ...record.image,
281
+ repoDigests
282
+ });
283
+ }
284
+ if (record?.environment && record.environment.name !== "-") {
285
+ const key = `${record.environment.name}\0${record.environment.digest}`;
286
+ this.environments.set(key, record.environment);
287
+ }
288
+ if (e.attempt) {
289
+ const h = e.attempt.harness;
290
+ this.harnesses.set(cell.harness, {
291
+ id: cell.harness,
292
+ kind: h.kind,
293
+ model: harnessModel(h)
294
+ });
295
+ }
296
+ const resolved = this.resolvedHarnesses.get(cell.harness) ?? /* @__PURE__ */ new Set();
297
+ for (const t of record?.turns ?? []) if (t.model) resolved.add(t.model);
298
+ this.resolvedHarnesses.set(cell.harness, resolved);
299
+ }
300
+ entry(e, sources) {
301
+ let entry = this.byEval.get(e.id);
302
+ if (!entry) {
303
+ const key = e.id;
304
+ entry = {
305
+ id: e.id,
306
+ key,
307
+ slug: evalSlug(key),
308
+ file: e.file,
309
+ group: e.group,
310
+ name: e.name,
311
+ tags: e.attempt?.tags ?? [],
312
+ fingerprint: "",
313
+ sources,
314
+ outcome: "skipped",
315
+ todo: e.todo === true,
316
+ passRate: null,
317
+ cells: [],
318
+ attempts: []
319
+ };
320
+ this.byEval.set(e.id, entry);
321
+ }
322
+ return entry;
323
+ }
324
+ };
325
+ const UNKNOWN_CELL = {
326
+ key: "unknown",
327
+ harness: "unknown",
328
+ environment: "unknown",
329
+ sandbox: "unknown",
330
+ role: "control"
331
+ };
332
+ /** minLift per cell, kept aside while attempts are added; see `rollUp`. */
333
+ const minLifts = /* @__PURE__ */ new WeakMap();
334
+ const EMPTY_PARTS = {
335
+ sources: "",
336
+ harness: "",
337
+ environment: null,
338
+ image: null,
339
+ agentCli: null,
340
+ judge: "",
341
+ context: ""
342
+ };
343
+ function cellOf(entry, cell, gate, harness) {
344
+ let found = entry.cells.find((c) => c.key === cell.key);
345
+ if (!found) {
346
+ found = {
347
+ ...cell,
348
+ fingerprint: "",
349
+ fingerprintParts: EMPTY_PARTS,
350
+ environmentDigest: null,
351
+ harnessKind: harness?.kind ?? "unknown",
352
+ model: harness ? harnessModel(harness) : null,
353
+ gate,
354
+ overrides: [],
355
+ runs: 0,
356
+ pass: 0,
357
+ fail: 0,
358
+ infraError: 0,
359
+ skipped: 0,
360
+ passRate: null,
361
+ outcome: "skipped"
362
+ };
363
+ entry.cells.push(found);
364
+ }
365
+ return found;
366
+ }
367
+ /** Reads one attempt's worker record, files its artifacts and adds it to its eval and cell. */
368
+ async function addAttempt(e, ctx, seen, out, judge) {
369
+ const cell = e.attempt?.cell ?? UNKNOWN_CELL;
370
+ const n = e.attempt?.n ?? 1;
371
+ const record = await readRecord(join(ctx.stagingDir, "evals", recordFileName(e.key)));
372
+ const { outcome, error } = mergeOutcome(e, record);
373
+ if (!seen.sources.has(e.file)) seen.sources.set(e.file, await traceSources(ctx.config.root, e.file));
374
+ const sources = seen.sources.get(e.file) ?? [];
375
+ const context = record?.context ?? [];
376
+ seen.add(record, cell, e);
377
+ const entry = seen.entry(e, sources);
378
+ const cellRecord = cellOf(entry, cell, e.attempt?.gate ?? "all", e.attempt?.harness);
379
+ if (e.attempt?.minLift !== void 0) minLifts.set(cellRecord, e.attempt.minLift);
380
+ if (record?.environment?.overrides.length && cellRecord.overrides.length === 0) cellRecord.overrides = [...record.environment.overrides];
381
+ const environment = record?.environment;
382
+ if (environment && environment.name !== "-") cellRecord.environmentDigest = environment.digest;
383
+ if (!cellRecord.fingerprint || record) {
384
+ const parts = {
385
+ sources: sha256(JSON.stringify(sources)),
386
+ harness: sha256(JSON.stringify(e.attempt ? withoutCaps(e.attempt.harness) : null)),
387
+ environment: environment?.digest ?? null,
388
+ image: record?.image?.id ?? null,
389
+ agentCli: record?.image?.agentCli ?? null,
390
+ judge,
391
+ context: sha256(JSON.stringify(context))
392
+ };
393
+ cellRecord.fingerprintParts = parts;
394
+ cellRecord.fingerprint = fingerprintOf(parts);
395
+ }
396
+ entry.attempts.push({
397
+ key: attemptKey(entry.key, cell.key, n),
398
+ id: attemptId(cell.key, n),
399
+ cell: cell.key,
400
+ n,
401
+ seq: null,
402
+ startedAt: record?.startedAt ?? null,
403
+ imageId: record?.image?.id ?? null,
404
+ env: record?.env ?? {
405
+ vars: [],
406
+ secrets: [],
407
+ brokered: []
408
+ },
409
+ context,
410
+ egress: record?.egress ?? null,
411
+ servedModels: record?.servedModels ?? null,
412
+ outcome,
413
+ error,
414
+ durationMs: e.durationMs,
415
+ ...attemptEvidence(record, `${entry.slug}/${evalSlug(cell.key)}/${n}`, out)
416
+ });
417
+ }
418
+ /** Turns, timings, activity, verdicts, checks and changed files, with their artifact files. */
419
+ function attemptEvidence(record, dir, out) {
420
+ const files = {};
421
+ if (record?.setup?.length) {
422
+ const log = record.setup.map((s) => `$ ${s.run}\n${s.exitCode === null ? "timed out" : `exit ${s.exitCode}`} after ${s.durationMs}ms\n${capText(s.output)}${s.output.endsWith("\n") || !s.output ? "" : "\n"}`).join("\n");
423
+ files.setupLog = out.add(`${dir}/setup.log`, log);
424
+ }
425
+ if (record && record.turns.length > 0) {
426
+ files.transcript = out.add(`${dir}/transcript.jsonl`, transcriptLines(record));
427
+ const raw = rawLines(record);
428
+ if (raw) files.rawTranscript = out.add(`${dir}/transcript.raw.jsonl`, raw);
429
+ }
430
+ const patch = record?.diff ? historyPatch(record.diff.patch) : null;
431
+ if (patch !== null) files.diff = out.add(`${dir}/diff.patch`, patch);
432
+ if (record?.judgeInputs?.length) files.judgeInput = out.json(`${dir}/judge-input.json`, judgeInputs(record, patch, "diff.patch"));
433
+ const judgements = (record?.judgements ?? []).map((j, i) => ({
434
+ ...j,
435
+ key: judgementKey(i, j.question)
436
+ }));
437
+ return {
438
+ turns: (record?.turns ?? []).map((t) => ({
439
+ prompt: t.prompt,
440
+ status: t.status,
441
+ startedAt: t.startedAt,
442
+ durationMs: t.durationMs,
443
+ usage: t.usage ?? null,
444
+ model: t.model ?? null,
445
+ unreported: t.unreported ?? [],
446
+ error: turnError(t.transcript),
447
+ text: t.text.length > TURN_TEXT_LIMIT ? `${t.text.slice(0, TURN_TEXT_LIMIT)}… [reeval: truncated ${t.text.length} characters; the whole message is the turn's last text event in transcript.jsonl]` : t.text
448
+ })),
449
+ usage: sumUsage((record?.turns ?? []).map((t) => t.usage)),
450
+ timings: record?.timings ?? {
451
+ setupMs: 0,
452
+ agentMs: 0,
453
+ diffMs: 0,
454
+ checksMs: 0,
455
+ judgeMs: 0
456
+ },
457
+ activity: record ? activity(record) : {
458
+ tools: 0,
459
+ fileEdits: 0,
460
+ webSearches: 0,
461
+ webFetches: 0,
462
+ reasoningMs: 0
463
+ },
464
+ judgements,
465
+ ...record?.startRetries?.length ? { startRetries: record.startRetries } : {},
466
+ checks: (record?.checks ?? []).map((c, i) => ({
467
+ command: c.command,
468
+ exitCode: c.exitCode,
469
+ durationMs: c.durationMs,
470
+ log: out.add(`${dir}/checks/${i + 1}.log`, checkLog(c))
471
+ })),
472
+ changedFiles: changedFiles(record?.diff?.files ?? []),
473
+ files
474
+ };
475
+ }
476
+ /** Lift of a variant cell over the control on the same harness and sandbox, with its interval. */
477
+ function liftOf(control, variant) {
478
+ if (control.passRate === null || variant.passRate === null) return void 0;
479
+ const minLift = minLifts.get(variant);
480
+ const c = {
481
+ pass: control.pass,
482
+ counted: control.pass + control.fail
483
+ };
484
+ const v = {
485
+ pass: variant.pass,
486
+ counted: variant.pass + variant.fail
487
+ };
488
+ const { points, low, high } = liftInterval({
489
+ pass: v.pass,
490
+ n: v.counted
491
+ }, {
492
+ pass: c.pass,
493
+ n: c.counted
494
+ });
495
+ return {
496
+ vs: control.key,
497
+ control: c,
498
+ variant: v,
499
+ points: round3(points),
500
+ interval: {
501
+ lo: round3(low),
502
+ hi: round3(high),
503
+ level: .95,
504
+ method: "newcombe-wilson"
505
+ },
506
+ withinNoise: low < 0 && high > 0,
507
+ ...minLift !== void 0 ? { minLift } : {}
508
+ };
509
+ }
510
+ /**
511
+ * A cell's outcome by its gate. `'all'` and `'none'` take the worst attempt; `{ passRate }` passes
512
+ * when enough of the passes and fails are passes, and is an infra error only when nothing counted.
513
+ */
514
+ function cellOutcome(outcomes, gate) {
515
+ if (gate === "all" || gate === "none") return worstOutcome(outcomes);
516
+ const rate = passRateOf(outcomes);
517
+ if (rate === null) return worstOutcome(outcomes);
518
+ return rate >= gate.passRate ? "pass" : "fail";
519
+ }
520
+ /** Per-cell and per-eval counts, pass rates, lift, outcomes and fingerprints, once every attempt is in. */
521
+ function rollUp(evals) {
522
+ for (const entry of evals) {
523
+ for (const c of entry.cells) {
524
+ const outcomes = entry.attempts.filter((a) => a.cell === c.key).map((a) => a.outcome);
525
+ c.runs = outcomes.length;
526
+ c.pass = outcomes.filter((o) => o === "pass").length;
527
+ c.fail = outcomes.filter((o) => o === "fail").length;
528
+ c.infraError = outcomes.filter((o) => o === "infra_error").length;
529
+ c.skipped = outcomes.filter((o) => o === "skipped").length;
530
+ c.passRate = passRateOf(outcomes);
531
+ c.outcome = cellOutcome(outcomes, c.gate);
532
+ }
533
+ for (const c of entry.cells) {
534
+ if (c.role !== "variant") continue;
535
+ const control = entry.cells.find((x) => x.role === "control" && x.harness === c.harness && x.sandbox === c.sandbox);
536
+ const lift = control && liftOf(control, c);
537
+ if (!lift) continue;
538
+ c.lift = lift;
539
+ if (lift.minLift !== void 0 && lift.interval.lo < lift.minLift && c.outcome === "pass") c.outcome = "fail";
540
+ }
541
+ entry.outcome = worstOutcome(entry.cells.map((c) => c.gate === "none" && c.outcome === "fail" ? "pass" : c.outcome));
542
+ const gated = new Set(entry.cells.filter((c) => c.gate !== "none").map((c) => c.key));
543
+ entry.passRate = passRateOf(entry.attempts.filter((a) => gated.has(a.cell)).map((a) => a.outcome));
544
+ entry.fingerprint = sha256(JSON.stringify(entry.cells.map((c) => [c.key, c.fingerprint]).sort()));
545
+ }
546
+ }
547
+ /** Start order across the run, by when each attempt's worker began it. */
548
+ function sequence(evals) {
549
+ evals.flatMap((e) => e.attempts).filter((a) => a.startedAt !== null).sort((a, b) => a.startedAt < b.startedAt ? -1 : a.startedAt > b.startedAt ? 1 : a.key < b.key ? -1 : 1).forEach((a, i) => {
550
+ a.seq = i + 1;
551
+ });
552
+ }
553
+ /** The run's git state, with the uncommitted changes kept as `worktree.patch` when they fit. */
554
+ function gitState(input, out) {
555
+ const git = input.git;
556
+ if (!git?.dirty) return git;
557
+ const patch = input.worktreePatch;
558
+ const state = {
559
+ ...git,
560
+ diffHash: patch ? sha256(patch) : null
561
+ };
562
+ if (!patch) state.worktreePatchNote = "git could not produce a patch";
563
+ else if (patch.length > 5242880) state.worktreePatchNote = `too large to keep (${patch.length} bytes)`;
564
+ else {
565
+ out.files.set("worktree.patch", patch);
566
+ state.worktreePatch = {
567
+ path: "worktree.patch",
568
+ sha256: sha256(patch),
569
+ bytes: patch.length
570
+ };
571
+ }
572
+ return state;
573
+ }
574
+ const byName = (key) => (a, b) => key(a) < key(b) ? -1 : key(a) > key(b) ? 1 : 0;
575
+ function stackOf(input, seen, judgeModel) {
576
+ const { config } = input.ctx;
577
+ const packages = packageVersions(input.enginePackages);
578
+ return {
579
+ es: input.es,
580
+ node: process.versions.node,
581
+ os: process.platform,
582
+ arch: process.arch,
583
+ images: [...seen.images.values()].sort(byName((i) => i.ref)),
584
+ packages,
585
+ harnesses: [...seen.harnesses.values()].map((h) => ({
586
+ ...h,
587
+ resolvedModels: [...seen.resolvedHarnesses.get(h.id) ?? []].sort()
588
+ })).sort(byName((h) => h.id)),
589
+ judge: {
590
+ model: judgeModel,
591
+ resolvedModels: [...seen.resolvedJudges].sort(),
592
+ threshold: config.judge.threshold,
593
+ version: judgeVersion(input.es, packages, judgeModel ?? "")
594
+ },
595
+ context: [...seen.contexts.values()].sort(byName((c) => c.path)),
596
+ fingerprintScope: FINGERPRINT_SCOPE
597
+ };
598
+ }
599
+ async function assembleRun(input) {
600
+ const { ctx, engine } = input;
601
+ const { config, runId } = ctx;
602
+ const out = new Artifacts();
603
+ const judgeModel = config.judge.model === void 0 ? null : judgeModelName(config.judge.model);
604
+ const configHash = sha256(JSON.stringify({
605
+ include: config.include,
606
+ harness: config.harness.map(withoutCaps),
607
+ sandbox: withoutCaps(config.sandbox),
608
+ environment: config.environment ?? null,
609
+ runs: config.runs,
610
+ env: config.env,
611
+ judge: withoutCaps(config.judge),
612
+ timeoutMs: config.timeoutMs
613
+ }));
614
+ const seen = new Seen(input.sandbox);
615
+ const judge = sha256(JSON.stringify({
616
+ model: judgeModel,
617
+ threshold: config.judge.threshold,
618
+ version: judgeVersion(input.es, packageVersions(input.enginePackages), judgeModel ?? "")
619
+ }));
620
+ for (const e of engine.evals) await addAttempt(e, ctx, seen, out, judge);
621
+ const evals = [...seen.byEval.values()];
622
+ rollUp(evals);
623
+ sequence(evals);
624
+ const attempts = evals.flatMap((e) => e.attempts);
625
+ const count = (o) => attempts.filter((a) => a.outcome === o).length;
626
+ const notGated = evals.flatMap((e) => e.attempts.filter((a) => e.cells.find((c) => c.key === a.cell)?.gate === "none")).filter((a) => a.outcome === "fail").length;
627
+ const { profile } = ctx;
628
+ const ids = (list) => list === void 0 ? void 0 : [list].flat().map(harnessId);
629
+ return {
630
+ record: {
631
+ kind: "es-run",
632
+ schemaVersion: 1,
633
+ runId,
634
+ status: input.interrupted ? "interrupted" : input.budgetReached ? "budget" : "complete",
635
+ startedAt: input.startedAt.toISOString(),
636
+ endedAt: input.endedAt.toISOString(),
637
+ durationMs: input.endedAt.getTime() - input.startedAt.getTime(),
638
+ author: input.author,
639
+ git: gitState(input, out),
640
+ runner: input.runner,
641
+ dependencies: { lockfiles: input.lockfiles },
642
+ stack: stackOf(input, seen, judgeModel),
643
+ environments: [...seen.environments.values()].sort(byName((e) => e.name)),
644
+ profile: profile ? {
645
+ name: profile.name,
646
+ reason: profile.reason,
647
+ defaults: JSON.parse(JSON.stringify({
648
+ harness: ids(profile.defaults.harness),
649
+ environment: profile.defaults.environment?.name,
650
+ sandbox: profile.defaults.sandbox && sandboxId(profile.defaults.sandbox),
651
+ runs: profile.defaults.runs,
652
+ timeout: profile.defaults.timeout,
653
+ env: profile.defaults.env && Object.keys(profile.defaults.env).sort()
654
+ })),
655
+ limit: profile.limit
656
+ } : null,
657
+ plan: {
658
+ evals: input.plan.evals,
659
+ cells: input.plan.cells,
660
+ attempts: input.plan.attempts,
661
+ estimateMs: Math.round(input.plan.estimateMs),
662
+ sandboxWarnings: input.plan.sandboxWarnings
663
+ },
664
+ budget: Object.keys(input.plan.budget).length ? input.plan.budget : null,
665
+ config: {
666
+ sandbox: sandboxId(config.sandbox),
667
+ environment: config.environment?.name ?? null,
668
+ runs: config.runs,
669
+ judgeModel,
670
+ threshold: config.judge.threshold,
671
+ timeoutMs: config.timeoutMs,
672
+ concurrency: input.ctx.concurrency,
673
+ configHash
674
+ },
675
+ cost: costOf(attempts),
676
+ artifacts: "all",
677
+ redaction: { version: 1 },
678
+ summary: {
679
+ evals: evals.length,
680
+ attempts: attempts.length,
681
+ pass: count("pass"),
682
+ fail: count("fail"),
683
+ notGated,
684
+ infraError: count("infra_error"),
685
+ skipped: count("skipped")
686
+ },
687
+ evals
688
+ },
689
+ artifacts: out.files
690
+ };
691
+ }
692
+ //#endregion
693
+ export { fingerprintOf as a, worstOutcome as c, cellOutcome as i, assembleRun as n, judgementKey as o, capText as r, transcriptLines as s, OUTPUT_CAP as t };
694
+
695
+ //# sourceMappingURL=assemble-B-nmz8oH.js.map