@tangle-network/agent-runtime 0.79.2 → 0.79.4

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 (48) hide show
  1. package/README.md +50 -327
  2. package/dist/agent.js +5 -5
  3. package/dist/analyst-loop.js +2 -2
  4. package/dist/{chunk-TSDKBFZP.js → chunk-44CX5JU6.js} +414 -113
  5. package/dist/chunk-44CX5JU6.js.map +1 -0
  6. package/dist/{chunk-T2HVQVB4.js → chunk-4J6RBI3K.js} +15 -1
  7. package/dist/chunk-4J6RBI3K.js.map +1 -0
  8. package/dist/{chunk-75V2XXYJ.js → chunk-AHZ3YBL6.js} +524 -12
  9. package/dist/chunk-AHZ3YBL6.js.map +1 -0
  10. package/dist/{chunk-IODKUOBA.js → chunk-C2FZ6GR6.js} +2 -2
  11. package/dist/{chunk-Z3RRRPRB.js → chunk-H7IBHAFT.js} +23 -14
  12. package/dist/chunk-H7IBHAFT.js.map +1 -0
  13. package/dist/{chunk-VMNEQHJR.js → chunk-IPEQ3ERC.js} +17 -2
  14. package/dist/chunk-IPEQ3ERC.js.map +1 -0
  15. package/dist/{chunk-PBE35ULD.js → chunk-NXZEVWKP.js} +2 -2
  16. package/dist/{chunk-SONQUREI.js → chunk-RUJZK6VH.js} +2 -2
  17. package/dist/{chunk-2DS6T46I.js → chunk-U6AP535M.js} +4 -4
  18. package/dist/{coordination-BoEPhGas.d.ts → coordination-BFVtgRax.d.ts} +30 -4
  19. package/dist/environment-provider.d.ts +1 -1
  20. package/dist/environment-provider.js +1 -1
  21. package/dist/index.d.ts +4 -4
  22. package/dist/index.js +8 -8
  23. package/dist/intelligence.d.ts +30 -2
  24. package/dist/intelligence.js +33 -23
  25. package/dist/intelligence.js.map +1 -1
  26. package/dist/{loop-runner-bin-DCr5OMe5.d.ts → loop-runner-bin-CTVja8e0.d.ts} +2 -2
  27. package/dist/loop-runner-bin.d.ts +4 -4
  28. package/dist/loop-runner-bin.js +7 -7
  29. package/dist/loops.d.ts +283 -13
  30. package/dist/loops.js +26 -6
  31. package/dist/mcp/bin.js +5 -5
  32. package/dist/mcp/index.d.ts +6 -6
  33. package/dist/mcp/index.js +7 -7
  34. package/dist/{router-client-CMAWGv1h.d.ts → router-client-Ak2IGuXq.d.ts} +33 -1
  35. package/dist/{types-C1sozrte.d.ts → types-DYW0tloU.d.ts} +2 -2
  36. package/dist/{worktree-fanout-CtQrRDME.d.ts → worktree-fanout-DaUDwCA_.d.ts} +5 -74
  37. package/dist/{worktree-CpptK3oF.d.ts → worktree-harness-Dt6s_m3z.d.ts} +74 -2
  38. package/package.json +1 -1
  39. package/skills/build-with-agent-runtime/SKILL.md +53 -23
  40. package/dist/chunk-75V2XXYJ.js.map +0 -1
  41. package/dist/chunk-T2HVQVB4.js.map +0 -1
  42. package/dist/chunk-TSDKBFZP.js.map +0 -1
  43. package/dist/chunk-VMNEQHJR.js.map +0 -1
  44. package/dist/chunk-Z3RRRPRB.js.map +0 -1
  45. /package/dist/{chunk-IODKUOBA.js.map → chunk-C2FZ6GR6.js.map} +0 -0
  46. /package/dist/{chunk-PBE35ULD.js.map → chunk-NXZEVWKP.js.map} +0 -0
  47. /package/dist/{chunk-SONQUREI.js.map → chunk-RUJZK6VH.js.map} +0 -0
  48. /package/dist/{chunk-2DS6T46I.js.map → chunk-U6AP535M.js.map} +0 -0
@@ -29,6 +29,19 @@ function extractLlmCallEvent(event, agentRunName) {
29
29
  }
30
30
  return void 0;
31
31
  }
32
+ function sumSandboxUsage(events, agentRunName = "agent") {
33
+ let input = 0;
34
+ let output = 0;
35
+ let costUsd = 0;
36
+ for (const ev of events) {
37
+ const call = extractLlmCallEvent(ev, agentRunName);
38
+ if (!call) continue;
39
+ input += call.tokensIn ?? 0;
40
+ output += call.tokensOut ?? 0;
41
+ costUsd += call.costUsd ?? 0;
42
+ }
43
+ return { input, output, costUsd };
44
+ }
32
45
  function buildLlmCall(data, agentRunName) {
33
46
  const tokensIn = pickFiniteNumber(data, ["tokensIn", "inputTokens", "prompt_tokens"]);
34
47
  const tokensOut = pickFiniteNumber(data, ["tokensOut", "outputTokens", "completion_tokens"]);
@@ -73,6 +86,7 @@ function mapSandboxEvent(event, opts = {}) {
73
86
 
74
87
  export {
75
88
  extractLlmCallEvent,
89
+ sumSandboxUsage,
76
90
  mapSandboxEvent
77
91
  };
78
- //# sourceMappingURL=chunk-T2HVQVB4.js.map
92
+ //# sourceMappingURL=chunk-4J6RBI3K.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime/sandbox-events.ts"],"sourcesContent":["/**\n * Sandbox-event → runtime-event mapping.\n *\n * The sandbox SDK emits a polymorphic `SandboxEvent = { type, data, id? }`\n * whose `type` vocabulary is backend-determined (opencode, etc.) rather than\n * enumerated by the SDK. Two consumers project it:\n * - the loop kernel's cost ledger (`extractLlmCallEvent`) — sums usage off\n * every cost-bearing event, regardless of stream shape;\n * - the `AgentRuntime.act` streaming contract (`mapSandboxEvent`) — projects\n * incremental events to the `RuntimeStreamEvent` chat-UX vocabulary.\n *\n * Both live here so the empirically-observed `type` vocabulary has one home.\n */\n\nimport type { SandboxEvent } from '@tangle-network/sandbox'\nimport type { RuntimeStreamEvent } from '../types'\n\n/**\n * Extract a `RuntimeStreamEvent`-shaped `llm_call` from a sandbox event when\n * the event carries usage/cost data. Returns `undefined` for non-cost events\n * so the kernel can iterate the full stream without branching.\n *\n * Canonical cost-carrying types observed in the wild:\n * - `llm_call` — `data: { model, tokensIn, tokensOut, costUsd, ... }`\n * - `message.completed` / `result` — `data: { usage: { inputTokens,\n * outputTokens, totalCostUsd? } }`\n * - `cost.usage` / `usage` — same shape under a dedicated type\n *\n * Numeric coercion is strict: `Number.isFinite` gates every accumulator write\n * so a sentinel `NaN` from a misbehaving backend cannot poison the ledger.\n */\nexport function extractLlmCallEvent(\n event: SandboxEvent,\n agentRunName: string,\n): (RuntimeStreamEvent & { type: 'llm_call' }) | undefined {\n if (!event || typeof event !== 'object') return undefined\n const type = String(event.type ?? '')\n const data =\n event.data && typeof event.data === 'object'\n ? (event.data as Record<string, unknown>)\n : ({} as Record<string, unknown>)\n\n if (type === 'llm_call' || type === 'cost.usage' || type === 'usage') {\n return buildLlmCall(data, agentRunName)\n }\n if (type === 'message.completed' || type === 'result' || type === 'final') {\n const usage = data.usage as Record<string, unknown> | undefined\n if (!usage || typeof usage !== 'object') return undefined\n return buildLlmCall({ ...usage, model: data.model ?? usage.model }, agentRunName)\n }\n // sandbox 0.4.0 terminal event: `data = { tokenUsage: { inputTokens, outputTokens,\n // reasoningTokens, cacheReadInputTokens }, totalCostUsd }`. Usage lives under\n // `tokenUsage` (not `usage`) and the cost is top-level — neither matched the\n // branches above, so an in-process loopDispatch run reported {0,0} and the\n // backend-integrity guard misread a real run as a stub. Reasoning tokens are\n // billed output (reasoning models), so they fold into the output count.\n if (type === 'done') {\n const usage = data.tokenUsage as Record<string, unknown> | undefined\n if (!usage || typeof usage !== 'object') return undefined\n const out = pickFiniteNumber(usage, ['outputTokens', 'completion_tokens', 'tokensOut'])\n const reasoning = pickFiniteNumber(usage, ['reasoningTokens'])\n const mergedOut =\n out !== undefined || reasoning !== undefined ? (out ?? 0) + (reasoning ?? 0) : undefined\n return buildLlmCall(\n {\n inputTokens: usage.inputTokens,\n outputTokens: mergedOut,\n totalCostUsd: data.totalCostUsd,\n model: data.model ?? usage.model,\n },\n agentRunName,\n )\n }\n return undefined\n}\n\n/**\n * Sum the token usage + USD cost of a sandbox turn's events — the one honest way to meter an\n * `openSandboxRun` cell. Folds `extractLlmCallEvent` over the stream (which reads usage off EVERY backend\n * event shape), so a `runProfileMatrix` dispatch can report it to `ctx.cost`:\n *\n * const turn = await run.start(prompt)\n * const u = sumSandboxUsage(turn.events)\n * if (u.input || u.output) ctx.cost.observeTokens({ input: u.input, output: u.output })\n * if (u.costUsd) ctx.cost.observe(u.costUsd, 'sandbox-cell')\n *\n * Without this a cell reads `{tokens:0, cost:0}` and the backend-integrity guard correctly aborts the\n * matrix as a stub. `agentRunName` is the fallback model label for cost-only events (default `'agent'`).\n */\nexport function sumSandboxUsage(\n events: readonly SandboxEvent[],\n agentRunName = 'agent',\n): { input: number; output: number; costUsd: number } {\n let input = 0\n let output = 0\n let costUsd = 0\n for (const ev of events) {\n const call = extractLlmCallEvent(ev, agentRunName)\n if (!call) continue\n input += call.tokensIn ?? 0\n output += call.tokensOut ?? 0\n costUsd += call.costUsd ?? 0\n }\n return { input, output, costUsd }\n}\n\nfunction buildLlmCall(\n data: Record<string, unknown>,\n agentRunName: string,\n): (RuntimeStreamEvent & { type: 'llm_call' }) | undefined {\n const tokensIn = pickFiniteNumber(data, ['tokensIn', 'inputTokens', 'prompt_tokens'])\n const tokensOut = pickFiniteNumber(data, ['tokensOut', 'outputTokens', 'completion_tokens'])\n const costUsd = pickFiniteNumber(data, ['costUsd', 'totalCostUsd', 'cost_usd', 'cost'])\n if (tokensIn === undefined && tokensOut === undefined && costUsd === undefined) {\n return undefined\n }\n const model = typeof data.model === 'string' && data.model.length > 0 ? data.model : agentRunName\n const event: RuntimeStreamEvent & { type: 'llm_call' } = {\n type: 'llm_call',\n model,\n }\n if (tokensIn !== undefined) event.tokensIn = tokensIn\n if (tokensOut !== undefined) event.tokensOut = tokensOut\n if (costUsd !== undefined) event.costUsd = costUsd\n return event\n}\n\nfunction pickFiniteNumber(data: Record<string, unknown>, keys: string[]): number | undefined {\n for (const key of keys) {\n const value = data[key]\n if (typeof value === 'number' && Number.isFinite(value)) return value\n }\n return undefined\n}\n\n/**\n * Project one `SandboxEvent` onto the `RuntimeStreamEvent` chat-UX vocabulary,\n * for runtimes that bridge a sandbox `streamPrompt` into the\n * `AgentRuntime.act` streaming contract. Returns `undefined` for events that\n * have no faithful projection — the raw stream is preserved separately for the\n * `OutputAdapter`, so an unmapped event never loses data.\n *\n * Mapped (the task-optional incremental variants — no synthesized task\n * lifecycle, no guessed tool-part shapes):\n * - `message.part.updated` text part → `text_delta`\n * - `message.part.updated` reasoning/thinking part → `reasoning_delta`\n * - cost-bearing events → `llm_call` (shared with the ledger extractor)\n *\n * The opencode backend emits incremental text as\n * `{ type: 'message.part.updated', data: { part: { type, text }, delta } }`;\n * `delta` is the increment, `part.text` the running accumulation.\n */\nexport function mapSandboxEvent(\n event: SandboxEvent,\n opts: { agentRunName?: string } = {},\n): RuntimeStreamEvent | undefined {\n if (!event || typeof event !== 'object') return undefined\n const type = String(event.type ?? '')\n const data =\n event.data && typeof event.data === 'object'\n ? (event.data as Record<string, unknown>)\n : ({} as Record<string, unknown>)\n\n if (type === 'message.part.updated') {\n const part =\n data.part && typeof data.part === 'object' ? (data.part as Record<string, unknown>) : {}\n const partType = String(part.type ?? '')\n const delta = typeof data.delta === 'string' ? data.delta : undefined\n const text = delta ?? (typeof part.text === 'string' ? part.text : undefined)\n if (text === undefined) return undefined\n if (partType === 'text') return { type: 'text_delta', text }\n if (partType === 'reasoning' || partType === 'thinking')\n return { type: 'reasoning_delta', text }\n return undefined\n }\n\n return extractLlmCallEvent(event, opts.agentRunName ?? 'agent')\n}\n"],"mappings":"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","names":[]}
@@ -12,8 +12,9 @@ import {
12
12
  routerToolLoop,
13
13
  runLoop,
14
14
  settledToIteration,
15
+ supervise,
15
16
  withDriverExecutor
16
- } from "./chunk-TSDKBFZP.js";
17
+ } from "./chunk-44CX5JU6.js";
17
18
  import {
18
19
  addTokenUsage,
19
20
  isAbortError,
@@ -21,7 +22,7 @@ import {
21
22
  sleep,
22
23
  stringifySafe,
23
24
  zeroTokenUsage
24
- } from "./chunk-Z3RRRPRB.js";
25
+ } from "./chunk-H7IBHAFT.js";
25
26
  import {
26
27
  AnalystError,
27
28
  PlannerError,
@@ -205,6 +206,355 @@ Audit the route: revealed intent, verdict, evidence, one recommendation.`
205
206
  };
206
207
  }
207
208
 
209
+ // src/runtime/benchmark-report.ts
210
+ import {
211
+ benjaminiHochberg,
212
+ confidenceInterval,
213
+ pairedBootstrap,
214
+ pairedTTest,
215
+ wilson
216
+ } from "@tangle-network/agent-eval";
217
+ var defaultScoreOf = (r) => {
218
+ const o = r.outcome;
219
+ if (typeof o.holdoutScore === "number") return o.holdoutScore;
220
+ if (typeof o.searchScore === "number") return o.searchScore;
221
+ const raw = o.raw ?? {};
222
+ for (const k of ["composite", "score", "passed", "resolved"]) {
223
+ if (typeof raw[k] === "number") return raw[k];
224
+ }
225
+ return void 0;
226
+ };
227
+ var defaultProfileKeyOf = (r) => {
228
+ const cell = r.agentProfile;
229
+ const harness = cell?.harness;
230
+ return harness ? `${harness}\xB7${r.model}` : r.model;
231
+ };
232
+ var defaultGroupOf = (r) => r.scenarioId ?? r.experimentId;
233
+ function quantile(sorted, q) {
234
+ if (sorted.length === 0) return 0;
235
+ const idx = Math.min(sorted.length - 1, Math.floor(q * (sorted.length - 1)));
236
+ return sorted[idx] ?? 0;
237
+ }
238
+ function mean(xs) {
239
+ return xs.length === 0 ? 0 : xs.reduce((a, b) => a + b, 0) / xs.length;
240
+ }
241
+ function meanByScenario(records, scoreOf) {
242
+ const sums = /* @__PURE__ */ new Map();
243
+ for (const r of records) {
244
+ const s = scoreOf(r);
245
+ if (typeof s !== "number") continue;
246
+ const id = r.scenarioId;
247
+ if (!id) {
248
+ throw new Error(
249
+ `benchmark-report: RunRecord (candidate ${r.candidateId ?? "unknown"}) is missing scenarioId \u2014 cannot pair or interval it honestly. Pass opts.stats only on a scenario-tagged corpus.`
250
+ );
251
+ }
252
+ const acc = sums.get(id) ?? { total: 0, n: 0 };
253
+ acc.total += s;
254
+ acc.n += 1;
255
+ sums.set(id, acc);
256
+ }
257
+ const out = /* @__PURE__ */ new Map();
258
+ for (const [id, acc] of sums) out.set(id, acc.n ? acc.total / acc.n : 0);
259
+ return out;
260
+ }
261
+ function leaderboard(records, opts = {}) {
262
+ const scoreOf = opts.scoreOf ?? defaultScoreOf;
263
+ const profileKeyOf = opts.profileKeyOf ?? defaultProfileKeyOf;
264
+ const groupOf = opts.groupOf ?? defaultGroupOf;
265
+ const labelOf = opts.labelOf ?? ((k) => k);
266
+ const axisSet = /* @__PURE__ */ new Set();
267
+ if (opts.axisScoresOf) {
268
+ for (const r of records) for (const k of Object.keys(opts.axisScoresOf(r))) axisSet.add(k);
269
+ } else {
270
+ for (const r of records) axisSet.add(groupOf(r));
271
+ }
272
+ const axes = [...axisSet].sort();
273
+ const byProfile = /* @__PURE__ */ new Map();
274
+ for (const r of records) {
275
+ const key = profileKeyOf(r);
276
+ const bucket = byProfile.get(key);
277
+ if (bucket) bucket.push(r);
278
+ else byProfile.set(key, [r]);
279
+ }
280
+ const rows = [];
281
+ for (const [profileKey, recs] of byProfile) {
282
+ const scores = recs.map(scoreOf).filter((s) => typeof s === "number");
283
+ const axisBuckets = /* @__PURE__ */ new Map();
284
+ for (const r of recs) {
285
+ if (opts.axisScoresOf) {
286
+ for (const [axis, s] of Object.entries(opts.axisScoresOf(r))) {
287
+ const b = axisBuckets.get(axis) ?? [];
288
+ b.push(s);
289
+ axisBuckets.set(axis, b);
290
+ }
291
+ } else {
292
+ const s = scoreOf(r);
293
+ if (typeof s === "number") {
294
+ const axis = groupOf(r);
295
+ const b = axisBuckets.get(axis) ?? [];
296
+ b.push(s);
297
+ axisBuckets.set(axis, b);
298
+ }
299
+ }
300
+ }
301
+ const perAxis = {};
302
+ for (const [axis, b] of axisBuckets) perAxis[axis] = mean(b);
303
+ const latencies = recs.map((r) => r.wallMs).sort((a, b) => a - b);
304
+ const pass = opts.passThreshold ?? 0.999;
305
+ let scoreCi;
306
+ let passCi;
307
+ if (opts.stats) {
308
+ const collapsed = [...meanByScenario(recs, scoreOf).values()];
309
+ if (collapsed.length > 0) {
310
+ const ci2 = confidenceInterval(collapsed, 0.95, { seed: 7 });
311
+ scoreCi = { lower: ci2.lower, upper: ci2.upper };
312
+ const w = wilson(collapsed.filter((s) => s >= pass).length, collapsed.length, 0.95);
313
+ passCi = { lower: w.lower, upper: w.upper };
314
+ }
315
+ }
316
+ rows.push({
317
+ profileKey,
318
+ label: labelOf(profileKey),
319
+ model: recs[0]?.model ?? profileKey,
320
+ n: recs.length,
321
+ meanScore: mean(scores),
322
+ solveRate: scores.length === 0 ? 0 : scores.filter((s) => s >= pass).length / scores.length,
323
+ perAxis,
324
+ costUsd: recs.reduce((a, r) => a + r.costUsd, 0),
325
+ tokensIn: recs.reduce((a, r) => a + (r.tokenUsage?.input ?? 0), 0),
326
+ tokensOut: recs.reduce((a, r) => a + (r.tokenUsage?.output ?? 0), 0),
327
+ latencyP50Ms: quantile(latencies, 0.5),
328
+ latencyP90Ms: quantile(latencies, 0.9),
329
+ ...scoreCi ? { scoreCi } : {},
330
+ ...passCi ? { passCi } : {}
331
+ });
332
+ }
333
+ rows.sort(
334
+ (a, b) => b.meanScore - a.meanScore || a.costUsd - b.costUsd || a.label.localeCompare(b.label)
335
+ );
336
+ const models = [...new Set(records.map((r) => r.model))].sort();
337
+ return {
338
+ title: opts.title ?? "Benchmark report",
339
+ axes,
340
+ profiles: rows,
341
+ meta: opts.meta ?? {},
342
+ provenance: {
343
+ records: records.length,
344
+ profiles: rows.length,
345
+ axes: axes.length,
346
+ models,
347
+ totalCostUsd: records.reduce((a, r) => a + r.costUsd, 0)
348
+ }
349
+ };
350
+ }
351
+ function pairwiseSignificance(records, opts = {}) {
352
+ const scoreOf = opts.scoreOf ?? defaultScoreOf;
353
+ const profileKeyOf = opts.profileKeyOf ?? defaultProfileKeyOf;
354
+ const labelOf = opts.labelOf ?? ((k) => k);
355
+ const minPairs = opts.minPairs ?? 12;
356
+ const byProfile = /* @__PURE__ */ new Map();
357
+ for (const r of records) {
358
+ const k = profileKeyOf(r);
359
+ const b = byProfile.get(k);
360
+ if (b) b.push(r);
361
+ else byProfile.set(k, [r]);
362
+ }
363
+ const keys = [...byProfile.keys()].sort();
364
+ const collapsed = new Map(keys.map((k) => [k, meanByScenario(byProfile.get(k) ?? [], scoreOf)]));
365
+ const raw = [];
366
+ for (let i = 0; i < keys.length; i += 1) {
367
+ for (let j = i + 1; j < keys.length; j += 1) {
368
+ const ka = keys[i];
369
+ const kb = keys[j];
370
+ const am = collapsed.get(ka);
371
+ const bm = collapsed.get(kb);
372
+ const aScores = [];
373
+ const bScores = [];
374
+ for (const sid of [...am.keys()].sort()) {
375
+ const bv = bm.get(sid);
376
+ if (bv !== void 0) {
377
+ aScores.push(am.get(sid));
378
+ bScores.push(bv);
379
+ }
380
+ }
381
+ if (aScores.length === 0) continue;
382
+ const boot = pairedBootstrap(aScores, bScores, { seed: 7, statistic: "median" });
383
+ const p = pairedTTest(aScores, bScores).p;
384
+ raw.push({
385
+ a: labelOf(ka),
386
+ b: labelOf(kb),
387
+ pairs: aScores.length,
388
+ delta: boot.median,
389
+ ciLow: boot.low,
390
+ ciHigh: boot.high,
391
+ p
392
+ });
393
+ }
394
+ }
395
+ const { significant } = benjaminiHochberg(
396
+ raw.map((r) => r.p),
397
+ opts.fdr ?? 0.05
398
+ );
399
+ return raw.map((r, i) => ({
400
+ ...r,
401
+ significant: (significant[i] ?? false) && r.pairs >= minPairs
402
+ }));
403
+ }
404
+ var pct = (x) => `${(100 * x).toFixed(1)}%`;
405
+ var ci = (iv) => iv ? ` [${pct(iv.lower)}, ${pct(iv.upper)}]` : "";
406
+ function renderLeaderboardMarkdown(report) {
407
+ const lines = [];
408
+ lines.push(`# ${report.title}`, "");
409
+ const p = report.provenance;
410
+ lines.push(
411
+ `**${p.profiles} profiles \xD7 ${p.axes} axes**, ${p.records} runs, ${p.models.length} models \xB7 total $${p.totalCostUsd.toFixed(2)}`,
412
+ ""
413
+ );
414
+ for (const [k, v] of Object.entries(report.meta)) lines.push(`- **${k}:** ${v}`);
415
+ if (Object.keys(report.meta).length) lines.push("");
416
+ lines.push("## Leaderboard", "");
417
+ lines.push(
418
+ "| # | Profile | Score (95% CI) | Solved (95% CI) | Runs | Cost | Tok in/out | p50 | p90 |"
419
+ );
420
+ lines.push("|---|---|--:|--:|--:|--:|--:|--:|--:|");
421
+ report.profiles.forEach((r, i) => {
422
+ lines.push(
423
+ `| ${i + 1} | ${r.label} | ${pct(r.meanScore)}${ci(r.scoreCi)} | ${pct(r.solveRate)}${ci(r.passCi)} | ${r.n} | $${r.costUsd.toFixed(3)} | ${r.tokensIn}/${r.tokensOut} | ${(r.latencyP50Ms / 1e3).toFixed(1)}s | ${(r.latencyP90Ms / 1e3).toFixed(1)}s |`
424
+ );
425
+ });
426
+ lines.push("");
427
+ lines.push("## Score matrix \u2014 profile \xD7 axis", "");
428
+ lines.push(`| Profile | ${report.axes.join(" | ")} |`);
429
+ lines.push(`|---|${report.axes.map(() => "--:").join("|")}|`);
430
+ for (const r of report.profiles) {
431
+ const cells = report.axes.map((a) => {
432
+ const v = r.perAxis[a];
433
+ return v === void 0 ? "\xB7" : pct(v);
434
+ });
435
+ lines.push(`| ${r.label} | ${cells.join(" | ")} |`);
436
+ }
437
+ lines.push("");
438
+ lines.push("> `\xB7` = the profile never ran that axis (blank, never zero).");
439
+ return lines.join("\n");
440
+ }
441
+ function renderPairwiseMarkdown(verdicts, title = "Pairwise significance (paired, BH-corrected)") {
442
+ const lines = [`## ${title}`, ""];
443
+ if (verdicts.length === 0) return lines.concat("_no comparable pairs_").join("\n");
444
+ lines.push("| A vs B | \u0394(b\u2212a) median | 95% CI | pairs | p | verdict |");
445
+ lines.push("|---|--:|--:|--:|--:|---|");
446
+ for (const v of verdicts) {
447
+ const verdict = v.significant ? `**${v.delta >= 0 ? v.b : v.a} wins**` : "ns";
448
+ lines.push(
449
+ `| ${v.a} vs ${v.b} | ${v.delta >= 0 ? "+" : ""}${pct(v.delta)} | [${pct(v.ciLow)}, ${pct(v.ciHigh)}] | ${v.pairs} | ${v.p.toFixed(3)} | ${verdict} |`
450
+ );
451
+ }
452
+ lines.push(
453
+ "",
454
+ "> `ns` = not significant after Benjamini\u2013Hochberg (or below the paired-count floor)."
455
+ );
456
+ return lines.join("\n");
457
+ }
458
+ function esc(s) {
459
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
460
+ }
461
+ function ramp(score) {
462
+ const x = Math.max(0, Math.min(1, score));
463
+ const r = Math.round(x < 0.5 ? 220 : 220 - (x - 0.5) * 2 * 160);
464
+ const g = Math.round(x < 0.5 ? x * 2 * 170 : 170);
465
+ return `rgb(${r},${g},60)`;
466
+ }
467
+ function renderLeaderboardSvg(report) {
468
+ const rowH = 26;
469
+ const labelW = 220;
470
+ const cellW = 54;
471
+ const pad = 16;
472
+ const barAreaW = 360;
473
+ const profiles = report.profiles;
474
+ const barsH = profiles.length * rowH + pad;
475
+ const heatTop = barsH + 48;
476
+ const heatW = labelW + report.axes.length * cellW + pad;
477
+ const heatH = profiles.length * rowH + pad;
478
+ const width = Math.max(labelW + barAreaW + pad * 2, heatW);
479
+ const height = heatTop + heatH + pad;
480
+ const out = [];
481
+ out.push(
482
+ `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" font-family="ui-sans-serif,system-ui,sans-serif" font-size="12">`
483
+ );
484
+ out.push(`<rect width="${width}" height="${height}" fill="white"/>`);
485
+ out.push(
486
+ `<text x="${pad}" y="${pad + 4}" font-weight="700" font-size="14">${esc(report.title)} \u2014 score</text>`
487
+ );
488
+ profiles.forEach((r, i) => {
489
+ const y = pad + 12 + i * rowH;
490
+ out.push(`<text x="${pad}" y="${y + 14}">${esc(r.label)}</text>`);
491
+ const w = Math.round(r.meanScore * barAreaW);
492
+ out.push(`<rect x="${labelW}" y="${y + 4}" width="${barAreaW}" height="16" fill="#eef0f2"/>`);
493
+ out.push(
494
+ `<rect x="${labelW}" y="${y + 4}" width="${w}" height="16" fill="${ramp(r.meanScore)}"/>`
495
+ );
496
+ out.push(`<text x="${labelW + barAreaW + 6}" y="${y + 16}">${pct(r.meanScore)}</text>`);
497
+ });
498
+ out.push(
499
+ `<text x="${pad}" y="${heatTop - 12}" font-weight="700" font-size="14">profile \xD7 axis</text>`
500
+ );
501
+ report.axes.forEach((a, c) => {
502
+ const x = labelW + c * cellW;
503
+ out.push(
504
+ `<text x="${x + cellW / 2}" y="${heatTop}" text-anchor="middle" fill="#555">${esc(a.length > 8 ? `${a.slice(0, 7)}\u2026` : a)}</text>`
505
+ );
506
+ });
507
+ profiles.forEach((r, i) => {
508
+ const y = heatTop + 8 + i * rowH;
509
+ out.push(`<text x="${pad}" y="${y + 16}">${esc(r.label)}</text>`);
510
+ report.axes.forEach((a, c) => {
511
+ const x = labelW + c * cellW;
512
+ const s = r.perAxis[a];
513
+ if (s !== void 0) {
514
+ out.push(
515
+ `<rect x="${x}" y="${y}" width="${cellW - 3}" height="${rowH - 4}" fill="${ramp(s)}"/>`
516
+ );
517
+ out.push(
518
+ `<text x="${x + (cellW - 3) / 2}" y="${y + 15}" text-anchor="middle" fill="white" font-size="10">${Math.round(100 * s)}</text>`
519
+ );
520
+ } else {
521
+ out.push(
522
+ `<rect x="${x}" y="${y}" width="${cellW - 3}" height="${rowH - 4}" fill="#f3f4f6"/>`
523
+ );
524
+ }
525
+ });
526
+ });
527
+ out.push("</svg>");
528
+ return out.join("\n");
529
+ }
530
+ function renderLeaderboardHtml(report) {
531
+ const svg = renderLeaderboardSvg(report);
532
+ const p = report.provenance;
533
+ const rows = report.profiles.map(
534
+ (r, i) => `<tr><td>${i + 1}</td><td>${esc(r.label)}</td><td class="n">${pct(r.meanScore)}</td><td class="n">${pct(r.solveRate)}</td><td class="n">${r.n}</td><td class="n">$${r.costUsd.toFixed(3)}</td>${report.axes.map((a) => {
535
+ const v = r.perAxis[a];
536
+ return `<td class="n">${v === void 0 ? "\xB7" : pct(v)}</td>`;
537
+ }).join("")}</tr>`
538
+ ).join("\n");
539
+ const axisHead = report.axes.map((a) => `<th>${esc(a)}</th>`).join("");
540
+ return `<!doctype html><html><head><meta charset="utf-8"><title>${esc(report.title)}</title>
541
+ <style>
542
+ body{font:14px ui-sans-serif,system-ui,sans-serif;margin:2rem;color:#111}
543
+ h1{font-size:1.4rem}.sub{color:#555;margin:.2rem 0 1.2rem}
544
+ table{border-collapse:collapse;margin-top:1rem}td,th{border:1px solid #e5e7eb;padding:.35rem .6rem}
545
+ th{background:#f9fafb;text-align:left}.n{text-align:right;font-variant-numeric:tabular-nums}
546
+ tr:first-child td{font-weight:600}
547
+ </style></head><body>
548
+ <h1>${esc(report.title)}</h1>
549
+ <div class="sub">${p.profiles} profiles \xD7 ${p.axes} axes \xB7 ${p.records} runs \xB7 ${p.models.length} models \xB7 total $${p.totalCostUsd.toFixed(2)}</div>
550
+ ${svg}
551
+ <table><thead><tr><th>#</th><th>Profile</th><th>Score</th><th>Solved</th><th>Runs</th><th>Cost</th>${axisHead}</tr></thead>
552
+ <tbody>
553
+ ${rows}
554
+ </tbody></table>
555
+ </body></html>`;
556
+ }
557
+
208
558
  // src/runtime/completion.ts
209
559
  function completionAuthorizes(v, policy) {
210
560
  if (!v?.done) return false;
@@ -608,6 +958,9 @@ function campaignTraceToLoopEmitter(trace) {
608
958
  }
609
959
  async function runLoopForCell(opts, scenario, profile, ctx) {
610
960
  const loopOptions = opts.toLoopOptions(scenario, profile);
961
+ return runLoopWithCampaignContext(opts, loopOptions, ctx);
962
+ }
963
+ async function runLoopWithCampaignContext(opts, loopOptions, ctx) {
611
964
  const result = await runLoop({
612
965
  ...loopOptions,
613
966
  ctx: {
@@ -620,6 +973,9 @@ async function runLoopForCell(opts, scenario, profile, ctx) {
620
973
  const toArtifact = opts.toArtifact ?? ((r) => r.winner?.output);
621
974
  return toArtifact(result);
622
975
  }
976
+ function loopCampaignDispatch(opts) {
977
+ return (scenario, ctx) => runLoopWithCampaignContext(opts, opts.toLoopOptions(scenario), ctx);
978
+ }
623
979
  function loopDispatch(opts) {
624
980
  return (profile, scenario, ctx) => runLoopForCell(opts, scenario, profile, ctx);
625
981
  }
@@ -1863,7 +2219,7 @@ function promotionGate(opts) {
1863
2219
  }
1864
2220
 
1865
2221
  // src/runtime/run-benchmark.ts
1866
- import { pairedBootstrap, paretoFrontier } from "@tangle-network/agent-eval";
2222
+ import { pairedBootstrap as pairedBootstrap2, paretoFrontier } from "@tangle-network/agent-eval";
1867
2223
 
1868
2224
  // src/runtime/strategy.ts
1869
2225
  import { createChatClient, estimateCost, isModelPriced } from "@tangle-network/agent-eval";
@@ -2560,15 +2916,15 @@ async function runBenchmark(cfg) {
2560
2916
  const ok = perTask.filter(
2561
2917
  (r) => !!r.cells
2562
2918
  );
2563
- const mean = (xs) => xs.length ? xs.reduce((s, x) => s + x, 0) / xs.length : 0;
2919
+ const mean2 = (xs) => xs.length ? xs.reduce((s, x) => s + x, 0) / xs.length : 0;
2564
2920
  const perStrategy = {};
2565
2921
  for (const s of strategies) {
2566
2922
  const cells = ok.map((r) => r.cells[s.name]).filter((c) => !!c);
2567
2923
  perStrategy[s.name] = {
2568
- score: mean(cells.map((c) => c.score)),
2569
- resolved: mean(cells.map((c) => c.resolved ? 1 : 0)),
2570
- usd: mean(cells.map((c) => c.usd)),
2571
- ms: mean(cells.map((c) => c.ms))
2924
+ score: mean2(cells.map((c) => c.score)),
2925
+ resolved: mean2(cells.map((c) => c.resolved ? 1 : 0)),
2926
+ usd: mean2(cells.map((c) => c.usd)),
2927
+ ms: mean2(cells.map((c) => c.ms))
2572
2928
  };
2573
2929
  }
2574
2930
  const frontier = paretoFrontier(
@@ -2587,7 +2943,7 @@ async function runBenchmark(cfg) {
2587
2943
  };
2588
2944
  const names = strategies.map((s) => s.name);
2589
2945
  if (names.includes("refine") && names.includes("sample") && ok.length >= 2) {
2590
- const b = pairedBootstrap(
2946
+ const b = pairedBootstrap2(
2591
2947
  ok.map((r) => r.cells.sample?.score ?? 0),
2592
2948
  ok.map((r) => r.cells.refine?.score ?? 0)
2593
2949
  );
@@ -2596,7 +2952,7 @@ async function runBenchmark(cfg) {
2596
2952
  return report;
2597
2953
  }
2598
2954
  function printBenchmarkReport(report) {
2599
- const pct = (x) => `${(x * 100).toFixed(1)}%`;
2955
+ const pct2 = (x) => `${(x * 100).toFixed(1)}%`;
2600
2956
  const pp = (x) => `${x >= 0 ? "+" : ""}${(x * 100).toFixed(1)}pp`;
2601
2957
  console.log(
2602
2958
  `
@@ -2607,7 +2963,7 @@ function printBenchmarkReport(report) {
2607
2963
  );
2608
2964
  for (const [s, v] of Object.entries(report.perStrategy))
2609
2965
  console.log(
2610
- ` ${(report.pareto.includes(s) ? `${s} *` : s).padEnd(16)} ${pct(v.score).padStart(7)} ${pct(v.resolved).padStart(9)} ${`$${v.usd.toFixed(3)}`.padStart(8)} ${(v.ms / 1e3).toFixed(0).padStart(6)}s`
2966
+ ` ${(report.pareto.includes(s) ? `${s} *` : s).padEnd(16)} ${pct2(v.score).padStart(7)} ${pct2(v.resolved).padStart(9)} ${`$${v.usd.toFixed(3)}`.padStart(8)} ${(v.ms / 1e3).toFixed(0).padStart(6)}s`
2611
2967
  );
2612
2968
  if (report.pareto.length) console.log(` * = on the (score, $) Pareto frontier`);
2613
2969
  for (const row of report.perTask)
@@ -3824,6 +4180,153 @@ function worktreeFanout(options) {
3824
4180
  });
3825
4181
  }
3826
4182
 
4183
+ // src/runtime/supervise-surface.ts
4184
+ function captureFailures(base) {
4185
+ let lastReport = "";
4186
+ const surface = {
4187
+ name: base.name,
4188
+ open: (t) => base.open(t),
4189
+ tools: (t, h) => base.tools(t, h),
4190
+ async call(h, name, args) {
4191
+ const out = await base.call(h, name, args);
4192
+ if (name === "run_tests") lastReport = out;
4193
+ return out;
4194
+ },
4195
+ score: (t, h) => base.score(t, h),
4196
+ close: (h) => base.close(h)
4197
+ };
4198
+ const failing = () => {
4199
+ const body = /FAILING:\s*(.+)/i.exec(lastReport)?.[1];
4200
+ return body ? body.split(",").map((s) => s.trim()).filter(Boolean) : [];
4201
+ };
4202
+ return { surface, failing };
4203
+ }
4204
+ function failuresAnalyst() {
4205
+ return {
4206
+ kinds: [
4207
+ {
4208
+ id: "failures",
4209
+ description: "Surface the worker's still-failing tests so the driver targets them next.",
4210
+ area: "progress"
4211
+ }
4212
+ ],
4213
+ run: async (_kindId, trace) => {
4214
+ const w = trace ?? {};
4215
+ if (!(typeof w === "object" && w !== null && "resolved" in w))
4216
+ return { summary: `worker produced: ${JSON.stringify(trace).slice(0, 300)}` };
4217
+ if (w.resolved) return { summary: "worker RESOLVED \u2014 every check passed; stop." };
4218
+ const failing = w.failing ?? [];
4219
+ const head = `worker did NOT resolve \u2014 score ${(100 * (w.score ?? 0)).toFixed(0)}%, ${w.shots ?? "?"} shot(s)`;
4220
+ return {
4221
+ summary: failing.length ? `${head}. STILL FAILING (${failing.length}): ${failing.slice(0, 12).join(", ")}. Spawn the next worker to fix exactly these; if a test keeps failing across workers, give it concrete guidance about that case.` : `${head}. (no failing-test list available this round)`
4222
+ };
4223
+ }
4224
+ };
4225
+ }
4226
+ function surfaceWorkerExecutor(surface, task, worker, strategy) {
4227
+ let artifact;
4228
+ return {
4229
+ runtime: "surface-worker",
4230
+ async execute(brief) {
4231
+ const guidance = typeof brief === "string" ? brief.trim() : brief ? JSON.stringify(brief) : "";
4232
+ const attemptTask = guidance ? {
4233
+ ...task,
4234
+ systemPrompt: `${task.systemPrompt ?? ""}
4235
+
4236
+ \u2014 Supervisor guidance for THIS attempt (incorporate it; do not just repeat a prior approach) \u2014
4237
+ ${guidance}`
4238
+ } : task;
4239
+ const cap = captureFailures(surface);
4240
+ const r = await runAgentic({
4241
+ surface: cap.surface,
4242
+ task: attemptTask,
4243
+ strategy,
4244
+ budget: worker.budget ?? 1,
4245
+ routerBaseUrl: worker.routerBaseUrl,
4246
+ routerKey: worker.routerKey,
4247
+ model: worker.model,
4248
+ ...worker.maxTokens !== void 0 ? { maxTokens: worker.maxTokens } : {},
4249
+ ...worker.innerTurns !== void 0 ? { innerTurns: worker.innerTurns } : {}
4250
+ });
4251
+ const out = {
4252
+ resolved: r.resolved,
4253
+ score: r.score,
4254
+ shots: r.shots,
4255
+ summary: `${strategy.name} ${r.shots} shot(s) \u2192 ${(100 * r.score).toFixed(0)}% (${r.resolved ? "resolved" : "unresolved"})`,
4256
+ failing: r.resolved ? [] : cap.failing()
4257
+ };
4258
+ const spent = { iterations: r.completions, tokens: r.tokens, usd: r.usd, ms: r.ms };
4259
+ artifact = {
4260
+ outRef: `surface-worker:${task.id}:${r.shots}:${r.resolved ? "ok" : "no"}`,
4261
+ out,
4262
+ verdict: { valid: r.resolved, score: r.score },
4263
+ spent
4264
+ };
4265
+ return artifact;
4266
+ },
4267
+ teardown: () => Promise.resolve({ destroyed: true }),
4268
+ resultArtifact() {
4269
+ if (!artifact) throw new Error("surfaceWorkerExecutor: resultArtifact before execute");
4270
+ return artifact;
4271
+ }
4272
+ };
4273
+ }
4274
+ async function superviseSurface(profile, task, opts) {
4275
+ const strategy = opts.strategy ?? refine;
4276
+ const innerTurns = opts.worker.innerTurns ?? 6;
4277
+ const router = opts.router ?? {
4278
+ routerBaseUrl: opts.worker.routerBaseUrl,
4279
+ routerKey: opts.worker.routerKey,
4280
+ model: opts.worker.model
4281
+ };
4282
+ const budget = opts.budget ?? {
4283
+ maxIterations: (innerTurns + 2) * 5 + 16,
4284
+ maxTokens: (opts.worker.maxTokens ?? 4e3) * 8
4285
+ };
4286
+ const makeWorkerAgent = (rawProfile) => {
4287
+ const p = rawProfile ?? {};
4288
+ const name = typeof p.name === "string" && p.name.length > 0 ? p.name : "surface-worker";
4289
+ const spec = {
4290
+ profile: rawProfile,
4291
+ harness: null,
4292
+ executor: surfaceWorkerExecutor(
4293
+ opts.surface,
4294
+ task,
4295
+ opts.worker,
4296
+ strategy
4297
+ )
4298
+ };
4299
+ return { name, act: async () => "", executorSpec: spec };
4300
+ };
4301
+ const deliverable = {
4302
+ describe: `resolve the surface task ${task.id} (every required check passes)`,
4303
+ check: (out2) => out2?.resolved === true
4304
+ };
4305
+ const analysts = opts.analysts === null ? void 0 : opts.analysts ?? failuresAnalyst();
4306
+ const result = await supervise(profile, task, {
4307
+ makeWorkerAgent,
4308
+ deliverable,
4309
+ budget,
4310
+ maxLiveWorkers: opts.maxLiveWorkers ?? 1,
4311
+ // A SMALL per-worker reservation so MULTIPLE workers fit the pool (the default reserves the whole pool
4312
+ // per worker → only one ever spawns, defeating the spawn-a-targeted-worker steering).
4313
+ perWorker: { maxIterations: innerTurns + 2, maxTokens: opts.worker.maxTokens ?? 4e3 },
4314
+ router,
4315
+ ...analysts ? { analysts, analyzeOnSettle: analysts.kinds.map((k) => k.id) } : {}
4316
+ });
4317
+ const out = result.kind === "winner" ? result.out : void 0;
4318
+ const sp = result.spentTotal;
4319
+ return {
4320
+ resolved: out?.resolved ?? false,
4321
+ score: out?.score ?? 0,
4322
+ usd: sp.usd,
4323
+ tokensIn: sp.tokens.input,
4324
+ tokensOut: sp.tokens.output,
4325
+ ms: sp.ms,
4326
+ completions: sp.iterations
4327
+ };
4328
+ }
4329
+
3827
4330
  // src/runtime/verifier-environment.ts
3828
4331
  var submitTool = {
3829
4332
  type: "function",
@@ -4116,6 +4619,12 @@ export {
4116
4619
  renderAnytimeTable,
4117
4620
  defaultAuditorInstruction,
4118
4621
  auditIntent,
4622
+ leaderboard,
4623
+ pairwiseSignificance,
4624
+ renderLeaderboardMarkdown,
4625
+ renderPairwiseMarkdown,
4626
+ renderLeaderboardSvg,
4627
+ renderLeaderboardHtml,
4119
4628
  completionAuthorizes,
4120
4629
  stopSentinel,
4121
4630
  sentinelCompletion,
@@ -4127,6 +4636,7 @@ export {
4127
4636
  inProcessSandboxClient,
4128
4637
  inlineSandboxClient,
4129
4638
  reportLoopUsage,
4639
+ loopCampaignDispatch,
4130
4640
  loopDispatch,
4131
4641
  createMcpEnvironment,
4132
4642
  assertTraceDerivedFindings,
@@ -4182,6 +4692,8 @@ export {
4182
4692
  sandboxSessionTraceSource,
4183
4693
  analyzeTrace,
4184
4694
  worktreeFanout,
4695
+ failuresAnalyst,
4696
+ superviseSurface,
4185
4697
  createVerifierEnvironment,
4186
4698
  createWaterfallCollector,
4187
4699
  localShell,
@@ -4191,4 +4703,4 @@ export {
4191
4703
  computeFindingId,
4192
4704
  makeFinding2 as makeFinding
4193
4705
  };
4194
- //# sourceMappingURL=chunk-75V2XXYJ.js.map
4706
+ //# sourceMappingURL=chunk-AHZ3YBL6.js.map