@tangle-network/agent-runtime 0.101.1 → 0.102.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 (78) hide show
  1. package/dist/agent.d.ts +1 -1
  2. package/dist/agent.js +5 -3
  3. package/dist/agent.js.map +1 -1
  4. package/dist/analyst-loop.d.ts +1 -1
  5. package/dist/candidate-execution/index.d.ts +13 -2
  6. package/dist/candidate-execution/index.js +8 -3
  7. package/dist/chunk-377GOJHJ.js +578 -0
  8. package/dist/chunk-377GOJHJ.js.map +1 -0
  9. package/dist/{chunk-DI677IPX.js → chunk-3DW5DEKQ.js} +3 -3
  10. package/dist/{chunk-KVJQV342.js → chunk-6MR4IJRW.js} +25 -1777
  11. package/dist/chunk-6MR4IJRW.js.map +1 -0
  12. package/dist/{chunk-RJPQLUDA.js → chunk-7FJJUC73.js} +336 -43
  13. package/dist/chunk-7FJJUC73.js.map +1 -0
  14. package/dist/{chunk-TA4RBJLE.js → chunk-CI7WS6S2.js} +5 -5
  15. package/dist/{chunk-U4PRAATQ.js → chunk-CK76OZPM.js} +3 -3
  16. package/dist/{chunk-KSBUSEUA.js → chunk-KJ2Q4T7F.js} +2 -2
  17. package/dist/{chunk-MAONWP4R.js → chunk-KPHTCHQ4.js} +611 -1419
  18. package/dist/chunk-KPHTCHQ4.js.map +1 -0
  19. package/dist/{chunk-BXZ7GPL4.js → chunk-KSM6GFHP.js} +2 -2
  20. package/dist/chunk-L5DST3QC.js +351 -0
  21. package/dist/chunk-L5DST3QC.js.map +1 -0
  22. package/dist/{chunk-HGSHPVJ6.js → chunk-LJLG734E.js} +200 -441
  23. package/dist/chunk-LJLG734E.js.map +1 -0
  24. package/dist/chunk-ROILMKDL.js +1338 -0
  25. package/dist/chunk-ROILMKDL.js.map +1 -0
  26. package/dist/{chunk-N2CEE5Q3.js → chunk-RTB3TC73.js} +3 -3
  27. package/dist/chunk-SQ3ZJH3Y.js +3082 -0
  28. package/dist/chunk-SQ3ZJH3Y.js.map +1 -0
  29. package/dist/chunk-UPWGXKXB.js +254 -0
  30. package/dist/chunk-UPWGXKXB.js.map +1 -0
  31. package/dist/{completion-gate-C80jiRfN.d.ts → completion-gate-C6dhVN-N.d.ts} +2 -2
  32. package/dist/{coordination-BFE3Den7.d.ts → coordination-D9l_YmwW.d.ts} +6 -6
  33. package/dist/environment-provider.d.ts +2 -2
  34. package/dist/{improve-g75IE2Cx.d.ts → improve-B40dRu0X.d.ts} +47 -19
  35. package/dist/index.d.ts +331 -23
  36. package/dist/index.js +544 -136
  37. package/dist/index.js.map +1 -1
  38. package/dist/intelligence.d.ts +63 -62
  39. package/dist/intelligence.js +62 -471
  40. package/dist/intelligence.js.map +1 -1
  41. package/dist/knowledge.d.ts +8 -8
  42. package/dist/knowledge.js +9 -7
  43. package/dist/{local-harness-ZqCx51u7.d.ts → local-harness-CtK9dSny.d.ts} +14 -2
  44. package/dist/{loop-runner-bin-Cn1N2rRo.d.ts → loop-runner-bin-PnWslIw4.d.ts} +2 -2
  45. package/dist/loop-runner-bin.d.ts +6 -6
  46. package/dist/loop-runner-bin.js +6 -4
  47. package/dist/loops.d.ts +231 -460
  48. package/dist/loops.js +58 -37
  49. package/dist/mcp/bin.js +2 -2
  50. package/dist/mcp/index.d.ts +184 -12
  51. package/dist/mcp/index.js +31 -9
  52. package/dist/mcp/index.js.map +1 -1
  53. package/dist/mcp/memory-bin.d.ts +1 -0
  54. package/dist/mcp/memory-bin.js +22 -0
  55. package/dist/mcp/memory-bin.js.map +1 -0
  56. package/dist/profiles.d.ts +3 -3
  57. package/dist/structural-rollout-D7xik9XR.d.ts +446 -0
  58. package/dist/{substrate-DO2GHNg2.d.ts → substrate-Dyiqmd3o.d.ts} +1 -1
  59. package/dist/{supervise-BLPI50-w.d.ts → supervise-BQdNAXtK.d.ts} +4 -4
  60. package/dist/testing.js +255 -211
  61. package/dist/testing.js.map +1 -1
  62. package/dist/{types-B3vAW0Oq.d.ts → types-CLat4bT9.d.ts} +1 -1
  63. package/dist/{types-CmnA2iL3.d.ts → types-D870JlH0.d.ts} +2 -2
  64. package/dist/{worktree-fanout-DCA3G4bO.d.ts → worktree-fanout-DsIR4d6w.d.ts} +234 -234
  65. package/package.json +6 -5
  66. package/dist/chunk-HGSHPVJ6.js.map +0 -1
  67. package/dist/chunk-IKGCKPDX.js +0 -1115
  68. package/dist/chunk-IKGCKPDX.js.map +0 -1
  69. package/dist/chunk-KVJQV342.js.map +0 -1
  70. package/dist/chunk-MAONWP4R.js.map +0 -1
  71. package/dist/chunk-RJPQLUDA.js.map +0 -1
  72. package/dist/{chunk-DI677IPX.js.map → chunk-3DW5DEKQ.js.map} +0 -0
  73. package/dist/{chunk-TA4RBJLE.js.map → chunk-CI7WS6S2.js.map} +0 -0
  74. package/dist/{chunk-U4PRAATQ.js.map → chunk-CK76OZPM.js.map} +0 -0
  75. package/dist/{chunk-KSBUSEUA.js.map → chunk-KJ2Q4T7F.js.map} +0 -0
  76. package/dist/{chunk-BXZ7GPL4.js.map → chunk-KSM6GFHP.js.map} +0 -0
  77. package/dist/{chunk-N2CEE5Q3.js.map → chunk-RTB3TC73.js.map} +0 -0
  78. package/dist/{sanitize-BTSsdBXw.d.ts → sanitize-DEbPNtyI.d.ts} +58 -58
package/dist/index.js CHANGED
@@ -1,14 +1,26 @@
1
+ import {
2
+ DELEGATED_LOOP_MODES,
3
+ auditLoopRunner,
4
+ isDelegatedLoopMode,
5
+ parseLoopRunnerArgv,
6
+ researchLoopRunner,
7
+ runDelegatedLoop,
8
+ runLoopRunnerCli,
9
+ selfImproveLoopRunner,
10
+ worktreeLoopRunner
11
+ } from "./chunk-RTB3TC73.js";
1
12
  import {
2
13
  FileAgentCandidateExecutionClaimStore,
3
14
  buildAgentCandidateBundle,
4
15
  createProtectedAgentCandidateModelPort,
5
16
  disposePreparedAgentCandidateExecution,
6
17
  recoverExpiredAgentCandidateExecution
7
- } from "./chunk-U4PRAATQ.js";
18
+ } from "./chunk-CK76OZPM.js";
8
19
  import {
9
20
  mcpToolsForRuntimeMcp,
10
21
  mcpToolsForRuntimeMcpSubset
11
- } from "./chunk-KSBUSEUA.js";
22
+ } from "./chunk-KJ2Q4T7F.js";
23
+ import "./chunk-SGKPNBXE.js";
12
24
  import {
13
25
  DEFAULT_ROUTER_BASE_URL,
14
26
  cleanModelId,
@@ -17,18 +29,6 @@ import {
17
29
  resolveRouterBaseUrl,
18
30
  validateChatModelId
19
31
  } from "./chunk-NURIQBJQ.js";
20
- import {
21
- DELEGATED_LOOP_MODES,
22
- auditLoopRunner,
23
- isDelegatedLoopMode,
24
- parseLoopRunnerArgv,
25
- researchLoopRunner,
26
- runDelegatedLoop,
27
- runLoopRunnerCli,
28
- selfImproveLoopRunner,
29
- worktreeLoopRunner
30
- } from "./chunk-N2CEE5Q3.js";
31
- import "./chunk-SGKPNBXE.js";
32
32
  import {
33
33
  CircuitBreakerState,
34
34
  CircuitOpenError,
@@ -55,7 +55,13 @@ import {
55
55
  slugifySpeaker,
56
56
  turnId
57
57
  } from "./chunk-2KGAN2HM.js";
58
- import "./chunk-MAONWP4R.js";
58
+ import {
59
+ exactProcessProviderAsCandidateExecutor
60
+ } from "./chunk-377GOJHJ.js";
61
+ import {
62
+ McpSpawnFault,
63
+ connectStdioMcp
64
+ } from "./chunk-KPHTCHQ4.js";
59
65
  import {
60
66
  InMemoryRuntimeSessionStore,
61
67
  createIterableBackend,
@@ -76,23 +82,40 @@ import {
76
82
  knowledgeReadinessDeliverable,
77
83
  runKnowledgeImprovementJob,
78
84
  runSupervisedKnowledgeUpdate
79
- } from "./chunk-TA4RBJLE.js";
85
+ } from "./chunk-CI7WS6S2.js";
80
86
  import "./chunk-5QOB7H74.js";
81
87
  import {
82
88
  captureAgentCandidateWorkspace,
83
89
  captureAgentCandidateWorkspaceFiles,
84
90
  createAgentCandidateWorkspacePort,
85
91
  sealAgentCandidateBundle
86
- } from "./chunk-BXZ7GPL4.js";
87
- import "./chunk-DI677IPX.js";
92
+ } from "./chunk-KSM6GFHP.js";
93
+ import "./chunk-3DW5DEKQ.js";
88
94
  import {
89
95
  AGENTIC_PROFILE_RESOURCE_ROOT,
96
+ LIFTED_FINDING_ANALYST_ID,
97
+ ROLLOUT_POLICY_BOUNDS,
98
+ ROLLOUT_POLICY_EXTENSION,
90
99
  agenticGenerator,
100
+ applyRolloutPolicyToProfile,
91
101
  commandVerifier,
102
+ defaultBuildPrompt,
103
+ enumerateNeighborPolicies,
92
104
  improve,
93
105
  improvementDriver,
94
- rawTraceDistiller
95
- } from "./chunk-RJPQLUDA.js";
106
+ isAnalystFinding,
107
+ normalizeRolloutPolicy,
108
+ parseRolloutPolicy,
109
+ rawTraceDistiller,
110
+ rawTraceEvidenceProblem,
111
+ requiresRawTraceEvidence,
112
+ rolloutPolicyProposer,
113
+ serializeRolloutPolicy,
114
+ structuralRolloutPolicyFromProfile,
115
+ summarizeFindings,
116
+ toAnalystFindings,
117
+ worktreeChangedPaths
118
+ } from "./chunk-7FJJUC73.js";
96
119
  import {
97
120
  AGENT_CANDIDATE_EXECUTION_SUPPORT,
98
121
  CANDIDATE_KNOWLEDGE_RETRIEVAL_CONFIG_ENV,
@@ -110,14 +133,16 @@ import {
110
133
  persistCandidateOutputArtifact,
111
134
  prepareAgentCandidateExecution,
112
135
  verifyAgentCandidateBundle
113
- } from "./chunk-HGSHPVJ6.js";
114
- import {
115
- composeRuntimeHooks,
116
- defineRuntimeHooks,
117
- notifyRuntimeDecisionPoint,
118
- notifyRuntimeHookEvent
119
- } from "./chunk-KVJQV342.js";
136
+ } from "./chunk-LJLG734E.js";
137
+ import "./chunk-6MR4IJRW.js";
120
138
  import "./chunk-DPEUKJRO.js";
139
+ import {
140
+ buildDriverSystem,
141
+ optimizerMethod,
142
+ researchDriverNote,
143
+ strategyAuthorMethod
144
+ } from "./chunk-ROILMKDL.js";
145
+ import "./chunk-UPWGXKXB.js";
121
146
  import {
122
147
  INTELLIGENCE_WIRE_VERSION,
123
148
  buildLoopOtelSpans,
@@ -132,7 +157,14 @@ import {
132
157
  sanitizeKnowledgeReadinessReport,
133
158
  sanitizeRuntimeStreamEvent
134
159
  } from "./chunk-2VZYRB55.js";
135
- import "./chunk-IKGCKPDX.js";
160
+ import {
161
+ composeRuntimeHooks,
162
+ defineRuntimeHooks,
163
+ notifyRuntimeDecisionPoint,
164
+ notifyRuntimeHookEvent,
165
+ runBrainLoop,
166
+ runLocalHarness
167
+ } from "./chunk-SQ3ZJH3Y.js";
136
168
  import "./chunk-IMSNJSXH.js";
137
169
  import "./chunk-M6MD6JBS.js";
138
170
  import "./chunk-3MDZX7YU.js";
@@ -245,130 +277,483 @@ function findingLines(findings) {
245
277
  }
246
278
  function toolBuildPrompt(args) {
247
279
  return [
248
- "You are building a new TOOL for this codebase to address the gaps below.",
249
- "Write the tool as a small, self-contained module PLUS tests that exercise it.",
250
- "The tool must compile and its tests must pass \u2014 they will be run automatically;",
251
- "if verification fails you will get the error and another attempt. Do not commit;",
252
- "leave the changes in the working tree.",
280
+ "You are building a new TOOL for this codebase \u2014 a capability the agent measurably lacks,",
281
+ "evidenced by the failure findings at the bottom. The tool is an experiment: after it is",
282
+ "built and verified, its marginal lift is measured on held-out tasks, and only a real lift",
283
+ "promotes it.",
284
+ "",
285
+ optimizerMethod,
286
+ "",
287
+ "THE SURFACE \u2014 what a deliverable tool looks like here:",
288
+ "- ONE small, self-contained module PLUS tests that exercise its contract (what callers rely",
289
+ " on), not its internals. The tests are the experiment for sub-goal correctness \u2014 write the",
290
+ " test that would fail if your hypothesis about the gap were wrong.",
291
+ "- It must compile and its tests must pass \u2014 they run automatically; on failure you get the",
292
+ " verifier output and another attempt, resuming on top of your own edits (fix in place, do",
293
+ " not start over).",
294
+ "- Match the codebase grain: reuse its existing helpers, style, and test framework; a tool",
295
+ " that fights the codebase is the wrong tool even if it passes.",
296
+ "- Do not commit; leave the changes in the working tree.",
253
297
  "",
254
- "Gaps the tool should close:",
298
+ "FINDINGS \u2014 ranked evidence from real failed runs (the gaps the tool must close):",
255
299
  ...findingLines(args.findings)
256
300
  ].join("\n");
257
301
  }
258
302
  function mcpBuildPrompt(args) {
259
303
  return [
260
- "You are building a new MCP SERVER (Model Context Protocol) that exposes",
261
- "tool(s) addressing the gaps below, so any harness can mount it.",
262
- "Requirements that WILL be checked by booting the server:",
304
+ "You are building a new MCP SERVER (Model Context Protocol) exposing tool(s) that close the",
305
+ "capability gaps evidenced by the failure findings at the bottom, so any harness can mount",
306
+ "them. The server is an experiment: after it is built and boot-verified, its marginal lift is",
307
+ "measured on held-out tasks, and only a real lift promotes it.",
308
+ "",
309
+ optimizerMethod,
310
+ "",
311
+ "RESEARCH FIRST \u2014 ADOPT BEFORE BUILD: you may discover and ADOPT an existing external MCP",
312
+ "server if it fits the gaps better than building one. Registries and vendor docs list",
313
+ "maintained servers for most common capabilities (web search, fetch, GitHub, filesystems,",
314
+ "databases). To adopt, deliver a short adoption note instead of an implementation: the",
315
+ "server's launch command or HTTP endpoint, and the API key it needs BY NAME (e.g.",
316
+ "EXA_API_KEY) \u2014 never a key value; provisioning injects the value at materialize time. If",
317
+ "your environment has no web access, decide from what you already know and say so.",
318
+ "",
319
+ "THE SURFACE \u2014 what a deliverable MCP server looks like here (checked by BOOTING it):",
263
320
  "- it starts over stdio and answers the MCP `initialize` handshake,",
264
- "- `tools/list` returns at least one tool with a valid input schema.",
265
- "Newline-delimited JSON-RPC 2.0, protocol version 2024-11-05. Include a start",
266
- "command (e.g. a package.json `start` script or a clear entrypoint). If the",
267
- "boot-and-probe fails you will get the error and another attempt. Do not",
268
- "commit; leave the changes in the working tree.",
321
+ "- `tools/list` returns at least one tool with a valid input schema,",
322
+ "- newline-delimited JSON-RPC 2.0, protocol version 2024-11-05,",
323
+ "- a clear start command (a package.json `start` script or an obvious entrypoint).",
324
+ "Design the tool surface for the FINDINGS, not for generality: each exposed tool should map to",
325
+ "a named failure mechanism, with a description that tells the agent when to reach for it (a",
326
+ "tool the agent never calls measures zero). If the boot-and-probe fails you get the error and",
327
+ "another attempt, resuming on top of your own edits. Do not commit; leave the changes in the",
328
+ "working tree.",
269
329
  "",
270
- "Capabilities the server should provide:",
330
+ "FINDINGS \u2014 ranked evidence from real failed runs (the capabilities the server must provide):",
271
331
  ...findingLines(args.findings)
272
332
  ].join("\n");
273
333
  }
274
334
 
275
- // src/improvement/mcp-serve-verifier.ts
276
- import { spawn } from "child_process";
277
- import { createInterface } from "readline";
278
- var PROTOCOL_VERSION = "2024-11-05";
279
- function mcpServeVerifier(spec) {
280
- const timeoutMs = spec.timeoutMs ?? 3e4;
281
- const minTools = spec.minTools ?? 1;
282
- return (worktreePath) => new Promise((resolve, reject) => {
283
- const child = spawn(spec.command, spec.args ?? [], {
284
- cwd: worktreePath,
285
- stdio: ["pipe", "pipe", "pipe"],
286
- env: { ...process.env, ...spec.env }
287
- });
288
- const stderr = [];
289
- let settled = false;
290
- let nextId = 1;
291
- const initId = nextId++;
292
- let listId = -1;
293
- const settle = (fn) => {
294
- if (settled) return;
295
- settled = true;
296
- clearTimeout(timer);
297
- rl.close();
298
- child.kill("SIGKILL");
299
- fn();
300
- };
301
- const withStderr = (msg) => stderr.length > 0 ? `${msg}
302
- stderr:
303
- ${stderr.join("").slice(-2e3)}` : msg;
304
- const pass = () => settle(() => resolve({ ok: true }));
305
- const failCandidate = (msg) => settle(() => resolve({ ok: false, feedback: withStderr(msg) }));
306
- const setupFault = (err) => settle(() => reject(err));
307
- const failStdin = (err) => failCandidate(`writing to MCP server stdin failed: ${err.message}`);
308
- const send = (msg) => {
309
- try {
310
- child.stdin.write(`${JSON.stringify(msg)}
311
- `);
312
- return true;
313
- } catch (err) {
314
- failStdin(err);
315
- return false;
335
+ // src/improvement/campaign-otlp.ts
336
+ import { readdirSync, readFileSync } from "fs";
337
+ import { basename, dirname, join, resolve } from "path";
338
+ import { OPENINFERENCE_SPAN_KIND } from "@tangle-network/agent-eval/traces";
339
+ var MAX_WALK_DEPTH = 4;
340
+ function campaignCellSpansToOtlp(content, cell, opts = {}) {
341
+ const records = parseCampaignSpans(content, cell.cellId);
342
+ if (records.length === 0) return [];
343
+ const serviceName = opts.serviceName ?? "campaign";
344
+ const key = cell.cellKey ?? cell.cellId;
345
+ const traceId = foldTo32Hex(key);
346
+ const rootSpanId = foldTo16Hex(`${key}::root`);
347
+ const startMs = Math.min(...records.map((r) => r.startMs));
348
+ const endMs = Math.max(...records.map((r) => r.startMs + (r.durationMs ?? 0)));
349
+ const anyError = records.some((r) => r.error !== void 0);
350
+ const resource = {
351
+ attributes: {
352
+ "service.name": serviceName,
353
+ "campaign.cell_id": cell.cellId,
354
+ ...cell.cellKey ? { "campaign.cell_dir": cell.cellKey } : {}
355
+ }
356
+ };
357
+ const lines = [
358
+ JSON.stringify({
359
+ trace_id: traceId,
360
+ span_id: rootSpanId,
361
+ parent_span_id: "",
362
+ name: `cell.${cell.cellId}`,
363
+ start_time: msToIso(startMs),
364
+ end_time: msToIso(endMs),
365
+ status: anyError ? { code: "STATUS_CODE_ERROR", message: "one or more spans errored" } : { code: "STATUS_CODE_OK", message: "" },
366
+ resource,
367
+ attributes: {
368
+ [OPENINFERENCE_SPAN_KIND]: "AGENT",
369
+ "agent.name": cell.cellId
316
370
  }
317
- };
318
- child.on("error", (err) => {
319
- const code = err.code;
320
- setupFault(
321
- code === "ENOENT" ? new Error(
322
- `mcpServeVerifier: '${spec.command}' not found in PATH (setup bug, not a failed candidate)`
323
- ) : new Error(`mcpServeVerifier: '${spec.command}' failed to spawn: ${err.message}`)
324
- );
325
- });
326
- child.on("exit", (code, signal) => {
327
- failCandidate(`MCP server exited (code ${code}, signal ${signal}) before serving`);
371
+ })
372
+ ];
373
+ for (let i = 0; i < records.length; i++) {
374
+ const r = records[i];
375
+ lines.push(
376
+ JSON.stringify({
377
+ trace_id: traceId,
378
+ span_id: foldTo16Hex(`${key}::${i}`),
379
+ parent_span_id: rootSpanId,
380
+ name: r.name,
381
+ start_time: msToIso(r.startMs),
382
+ end_time: msToIso(r.startMs + (r.durationMs ?? 0)),
383
+ status: r.error === void 0 ? { code: "STATUS_CODE_OK", message: "" } : { code: "STATUS_CODE_ERROR", message: r.error },
384
+ resource,
385
+ attributes: r.attributes
386
+ })
387
+ );
388
+ }
389
+ return lines;
390
+ }
391
+ function convertCampaignDirToOtlp(dir, opts = {}) {
392
+ const root = resolve(dir);
393
+ const files = findSpansFiles(root, MAX_WALK_DEPTH);
394
+ const lines = [];
395
+ for (const file of files) {
396
+ let content;
397
+ try {
398
+ content = readFileSync(file, "utf8");
399
+ } catch {
400
+ continue;
401
+ }
402
+ const cellDir = dirname(file);
403
+ lines.push(
404
+ ...campaignCellSpansToOtlp(content, { cellId: basename(cellDir), cellKey: cellDir }, opts)
405
+ );
406
+ }
407
+ return lines.length > 0 ? `${lines.join("\n")}
408
+ ` : "";
409
+ }
410
+ function campaignTraceResolver(opts) {
411
+ return (ctx) => {
412
+ const priorDir = ctx.generation <= 0 ? join(opts.runDir, "baseline") : join(opts.runDir, `gen-${ctx.generation - 1}`);
413
+ const prior = convertCampaignDirToOtlp(priorDir, opts);
414
+ if (prior) return prior;
415
+ return convertCampaignDirToOtlp(opts.runDir, opts);
416
+ };
417
+ }
418
+ function parseCampaignSpans(content, cellId) {
419
+ const out = [];
420
+ for (const line of content.split("\n")) {
421
+ const trimmed = line.trim();
422
+ if (!trimmed) continue;
423
+ let raw;
424
+ try {
425
+ raw = JSON.parse(trimmed);
426
+ } catch {
427
+ continue;
428
+ }
429
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) continue;
430
+ const o = raw;
431
+ if (typeof o.name !== "string" || typeof o.startMs !== "number") continue;
432
+ const attributes = { "campaign.cell_id": cellId };
433
+ for (const [k, v] of Object.entries(o)) {
434
+ if (k === "name" || k === "cellId" || k === "startMs" || k === "durationMs") continue;
435
+ attributes[k] = v;
436
+ }
437
+ out.push({
438
+ name: o.name,
439
+ cellId,
440
+ startMs: o.startMs,
441
+ ...typeof o.durationMs === "number" ? { durationMs: o.durationMs } : {},
442
+ attributes,
443
+ ...typeof o.error === "string" ? { error: o.error } : {}
328
444
  });
329
- child.stdin.on("error", failStdin);
330
- child.stderr.on("data", (d) => stderr.push(String(d)));
331
- const rl = createInterface({ input: child.stdout });
332
- rl.on("line", (line) => {
333
- let msg;
334
- try {
335
- msg = JSON.parse(line);
336
- } catch {
337
- return;
338
- }
339
- if (!msg || typeof msg !== "object") return;
340
- if (msg.id === initId) {
341
- if (msg.error) return failCandidate(`initialize errored: ${JSON.stringify(msg.error)}`);
342
- if (!send({ jsonrpc: "2.0", method: "notifications/initialized" })) return;
343
- listId = nextId++;
344
- send({ jsonrpc: "2.0", id: listId, method: "tools/list" });
345
- return;
346
- }
347
- if (msg.id === listId) {
348
- if (msg.error) return failCandidate(`tools/list errored: ${JSON.stringify(msg.error)}`);
349
- const tools = msg.result?.tools;
350
- if (!Array.isArray(tools)) return failCandidate("tools/list result has no tools array");
351
- if (tools.length < minTools) {
352
- return failCandidate(`tools/list returned ${tools.length} tool(s), need >= ${minTools}`);
445
+ }
446
+ return out;
447
+ }
448
+ function findSpansFiles(dir, depth) {
449
+ const out = [];
450
+ let entries;
451
+ try {
452
+ entries = readdirSync(dir, { withFileTypes: true });
453
+ } catch {
454
+ return out;
455
+ }
456
+ for (const entry of entries) {
457
+ const full = join(dir, entry.name);
458
+ if (entry.isFile() && entry.name === "spans.jsonl") {
459
+ out.push(full);
460
+ } else if (depth > 0 && entry.isDirectory() && !entry.isSymbolicLink()) {
461
+ out.push(...findSpansFiles(full, depth - 1));
462
+ }
463
+ }
464
+ return out.sort();
465
+ }
466
+ function msToIso(ms) {
467
+ return Number.isFinite(ms) && ms > 0 ? new Date(ms).toISOString() : (/* @__PURE__ */ new Date(0)).toISOString();
468
+ }
469
+ function foldTo16Hex(s) {
470
+ const a = fnv1a(s);
471
+ const b = fnv1a(`${s}::salt`);
472
+ return a + b;
473
+ }
474
+ function foldTo32Hex(s) {
475
+ return foldTo16Hex(s) + foldTo16Hex(`${s}::trace`);
476
+ }
477
+ function fnv1a(s) {
478
+ let h = 2166136261;
479
+ for (let i = 0; i < s.length; i++) {
480
+ h ^= s.charCodeAt(i);
481
+ h = Math.imul(h, 16777619) >>> 0;
482
+ }
483
+ return h.toString(16).padStart(8, "0");
484
+ }
485
+
486
+ // src/improvement/driver-loop-generator.ts
487
+ import { spawnSync } from "child_process";
488
+ import { readFileSync as readFileSync2, statSync } from "fs";
489
+ import { resolve as resolve2, sep } from "path";
490
+ var workerOutputTailChars = 2e3;
491
+ var diffMaxChars = 6e3;
492
+ var readFileDefaultBytes = 8192;
493
+ var researchResultMaxChars = 8e3;
494
+ function driverLoopGenerator(opts) {
495
+ const harness = opts.harness ?? "claude";
496
+ const buildPrompt = opts.buildPrompt ?? defaultBuildPrompt;
497
+ const run = opts.runHarness ?? runLocalHarness;
498
+ const changed = opts.changedPaths ?? worktreeChangedPaths;
499
+ const readDiff = opts.readDiff ?? worktreeDiff;
500
+ const verify = opts.verify;
501
+ return {
502
+ kind: `driver-loop:${harness}`,
503
+ async generate({ worktreePath, report, findings, maxShots, signal }) {
504
+ signal.throwIfAborted();
505
+ const briefing = buildPrompt({ report, findings });
506
+ const needsRawTraceEvidence = requiresRawTraceEvidence(findings);
507
+ const sessionCap = Math.max(1, maxShots);
508
+ let sessionsUsed = 0;
509
+ const groundVerify = async () => {
510
+ signal.throwIfAborted();
511
+ if (changed(worktreePath).length === 0) {
512
+ return { ok: false, feedback: "the working tree has no changes \u2014 nothing to verify" };
513
+ }
514
+ if (needsRawTraceEvidence) {
515
+ const problem = rawTraceEvidenceProblem(worktreePath, findings);
516
+ if (problem) return { ok: false, feedback: problem };
517
+ }
518
+ if (!verify) {
519
+ return { ok: true, feedback: "no verifier configured: a dirty tree is the candidate" };
353
520
  }
354
- return pass();
521
+ const result = await verify(worktreePath, signal);
522
+ signal.throwIfAborted();
523
+ return result;
524
+ };
525
+ const execute = async (name, args) => {
526
+ signal.throwIfAborted();
527
+ switch (name) {
528
+ case "run_worker": {
529
+ const instruction = typeof args.instruction === "string" ? args.instruction.trim() : "";
530
+ if (instruction.length === 0) {
531
+ return "error: run_worker requires a non-empty `instruction`";
532
+ }
533
+ if (sessionsUsed >= sessionCap) {
534
+ return `error: worker-session budget exhausted (${sessionsUsed}/${sessionCap} used). Inspect and verify what exists, then stop with your final assessment.`;
535
+ }
536
+ sessionsUsed += 1;
537
+ const result = await run({
538
+ harness,
539
+ cwd: worktreePath,
540
+ taskPrompt: instruction,
541
+ ...opts.timeoutMs !== void 0 ? { timeoutMs: opts.timeoutMs } : {},
542
+ signal
543
+ });
544
+ signal.throwIfAborted();
545
+ if (result.aborted) {
546
+ throw new Error("driverLoopGenerator: worker session was cancelled by the caller");
547
+ }
548
+ return JSON.stringify({
549
+ session: `${sessionsUsed}/${sessionCap}`,
550
+ exitCode: result.exitCode,
551
+ timedOut: result.timedOut,
552
+ aborted: result.aborted ?? false,
553
+ killedBySignal: result.killedBySignal,
554
+ durationMs: result.durationMs,
555
+ changedPaths: changed(worktreePath),
556
+ stdoutTail: tail(result.stdout, workerOutputTailChars),
557
+ stderrTail: tail(result.stderr, workerOutputTailChars)
558
+ });
559
+ }
560
+ case "inspect_worktree": {
561
+ const paths = changed(worktreePath);
562
+ const diff = truncate(readDiff(worktreePath), diffMaxChars);
563
+ return JSON.stringify({
564
+ changedPaths: paths,
565
+ diff: diff.length > 0 ? diff : "(no tracked-file diff \u2014 new files are untracked; read_file them)"
566
+ });
567
+ }
568
+ case "read_file":
569
+ return readWorktreeFile(worktreePath, args);
570
+ case "research": {
571
+ if (!opts.research) return "error: research tool is not provisioned in this run";
572
+ const query = typeof args.query === "string" ? args.query.trim() : "";
573
+ if (query.length === 0) return "error: research requires a non-empty `query`";
574
+ const result = await opts.research(query);
575
+ signal.throwIfAborted();
576
+ return truncate(result, researchResultMaxChars);
577
+ }
578
+ case "run_verifier": {
579
+ const result = await groundVerify();
580
+ return JSON.stringify({
581
+ ok: result.ok,
582
+ feedback: truncate(result.feedback ?? "", 4e3)
583
+ });
584
+ }
585
+ default:
586
+ return `error: unknown tool: ${name}`;
587
+ }
588
+ };
589
+ await runBrainLoop({
590
+ chat: opts.brain,
591
+ tools: opts.research ? [...driverToolSpecs, researchToolSpec] : driverToolSpecs,
592
+ execute,
593
+ initialMessages: [
594
+ {
595
+ role: "system",
596
+ content: opts.research ? `${buildDriverSystem}
597
+
598
+ ${researchDriverNote}` : buildDriverSystem
599
+ },
600
+ {
601
+ role: "user",
602
+ content: [
603
+ `THE BUILD BRIEF (the contract your workers must satisfy \u2014 fold what each needs into its instruction; workers never see this brief):`,
604
+ "",
605
+ briefing,
606
+ "",
607
+ `Worker-session budget: ${sessionCap}. The worktree is a fresh checkout at ${worktreePath}.`
608
+ ].join("\n")
609
+ }
610
+ ],
611
+ maxTurns: opts.maxTurns ?? Math.max(8, 2 + sessionCap * 3),
612
+ hooks: { stopBefore: () => signal.aborted }
613
+ });
614
+ signal.throwIfAborted();
615
+ const verdict = await groundVerify();
616
+ signal.throwIfAborted();
617
+ if (!verdict.ok) return { applied: false, summary: "" };
618
+ return { applied: true, summary: summarizeFindings(findings) };
619
+ }
620
+ };
621
+ }
622
+ var driverToolSpecs = [
623
+ {
624
+ type: "function",
625
+ function: {
626
+ name: "run_worker",
627
+ description: "Run ONE coding-harness session in the worktree with your instruction as its entire goal. The worktree persists between sessions. Sessions are capped \u2014 author each instruction richly (outcome, context, placement, the check it is held to).",
628
+ parameters: {
629
+ type: "object",
630
+ properties: {
631
+ instruction: {
632
+ type: "string",
633
+ description: "The complete, self-contained goal for this worker session."
634
+ }
635
+ },
636
+ required: ["instruction"]
355
637
  }
356
- });
357
- const timer = setTimeout(
358
- () => failCandidate(`MCP server did not complete the handshake within ${timeoutMs}ms`),
359
- timeoutMs
638
+ }
639
+ },
640
+ {
641
+ type: "function",
642
+ function: {
643
+ name: "inspect_worktree",
644
+ description: "Current git state of the worktree: changed paths + the tracked-file diff (truncated). New untracked files show in changedPaths only \u2014 read_file them.",
645
+ parameters: { type: "object", properties: {} }
646
+ }
647
+ },
648
+ {
649
+ type: "function",
650
+ function: {
651
+ name: "read_file",
652
+ description: "Read one file from the worktree (paths are worktree-relative).",
653
+ parameters: {
654
+ type: "object",
655
+ properties: {
656
+ path: { type: "string", description: "Worktree-relative file path." },
657
+ maxBytes: { type: "number", description: "Byte cap (default 8192)." }
658
+ },
659
+ required: ["path"]
660
+ }
661
+ }
662
+ },
663
+ {
664
+ type: "function",
665
+ function: {
666
+ name: "run_verifier",
667
+ description: "Run the intrinsic check of the surface (compile+tests / boot-and-probe). Its result \u2014 not your judgment \u2014 decides whether the candidate is kept.",
668
+ parameters: { type: "object", properties: {} }
669
+ }
670
+ }
671
+ ];
672
+ var researchToolSpec = {
673
+ type: "function",
674
+ function: {
675
+ name: "research",
676
+ description: "Search external sources (MCP registries, vendor docs) for an EXISTING server that closes the capability gap \u2014 the adopt-not-build check. Returns text findings.",
677
+ parameters: {
678
+ type: "object",
679
+ properties: {
680
+ query: { type: "string", description: "What capability / server to search for." }
681
+ },
682
+ required: ["query"]
683
+ }
684
+ }
685
+ };
686
+ function worktreeDiff(worktreePath) {
687
+ const result = spawnSync("git", ["diff"], { cwd: worktreePath, encoding: "utf-8" });
688
+ if (result.error) {
689
+ throw new Error(
690
+ `driverLoopGenerator: git diff failed to spawn in ${worktreePath}: ${result.error.message}`
691
+ );
692
+ }
693
+ if (result.status !== 0) {
694
+ throw new Error(
695
+ `driverLoopGenerator: git diff exited ${result.status} in ${worktreePath}: ${result.stderr.trim()}`
360
696
  );
361
- send({
362
- jsonrpc: "2.0",
363
- id: initId,
364
- method: "initialize",
365
- params: {
366
- protocolVersion: PROTOCOL_VERSION,
367
- capabilities: {},
368
- clientInfo: { name: "agent-runtime-mcp-verify", version: "0" }
697
+ }
698
+ return result.stdout;
699
+ }
700
+ function readWorktreeFile(worktreePath, args) {
701
+ const rel = typeof args.path === "string" ? args.path : "";
702
+ if (rel.length === 0) return "error: read_file requires `path`";
703
+ const root = resolve2(worktreePath);
704
+ const target = resolve2(root, rel);
705
+ if (target !== root && !target.startsWith(root + sep)) {
706
+ return `error: path escapes the worktree: ${rel}`;
707
+ }
708
+ const maxBytes = typeof args.maxBytes === "number" && args.maxBytes > 0 ? Math.min(args.maxBytes, 65536) : readFileDefaultBytes;
709
+ try {
710
+ const size = statSync(target).size;
711
+ const body = readFileSync2(target, "utf-8").slice(0, maxBytes);
712
+ return size > maxBytes ? `${body}
713
+ \u2026 (${size - maxBytes} bytes truncated)` : body;
714
+ } catch (e) {
715
+ return `error: ${e instanceof Error ? e.message : String(e)}`;
716
+ }
717
+ }
718
+ function tail(s, n) {
719
+ const trimmed = s.trim();
720
+ return trimmed.length <= n ? trimmed : `\u2026${trimmed.slice(-n)}`;
721
+ }
722
+ function truncate(s, n) {
723
+ return s.length <= n ? s : `${s.slice(0, n - 1)}\u2026`;
724
+ }
725
+
726
+ // src/improvement/mcp-serve-verifier.ts
727
+ function mcpServeVerifier(spec) {
728
+ const minTools = spec.minTools ?? 1;
729
+ return async (worktreePath) => {
730
+ let conn;
731
+ try {
732
+ conn = await connectStdioMcp({
733
+ command: spec.command,
734
+ ...spec.args ? { args: spec.args } : {},
735
+ cwd: worktreePath,
736
+ ...spec.env ? { env: spec.env } : {},
737
+ ...spec.timeoutMs !== void 0 ? { timeoutMs: spec.timeoutMs } : {}
738
+ });
739
+ } catch (err) {
740
+ if (err instanceof McpSpawnFault) {
741
+ throw new Error(`mcpServeVerifier: ${err.message}`);
369
742
  }
370
- });
371
- });
743
+ return { ok: false, feedback: err instanceof Error ? err.message : String(err) };
744
+ }
745
+ try {
746
+ if (conn.tools.length < minTools) {
747
+ return {
748
+ ok: false,
749
+ feedback: `tools/list returned ${conn.tools.length} tool(s), need >= ${minTools}`
750
+ };
751
+ }
752
+ return { ok: true };
753
+ } finally {
754
+ await conn.close();
755
+ }
756
+ };
372
757
  }
373
758
 
374
759
  // src/improvement/profile-diff-proposer.ts
@@ -436,7 +821,7 @@ function parseSerializedProfile(surface) {
436
821
  }
437
822
 
438
823
  // src/improvement/reflective-generator.ts
439
- import { spawnSync } from "child_process";
824
+ import { spawnSync as spawnSync2 } from "child_process";
440
825
  function reflectiveGenerator(opts) {
441
826
  return {
442
827
  kind: "reflective",
@@ -454,7 +839,7 @@ function reflectiveGenerator(opts) {
454
839
  };
455
840
  }
456
841
  function applyPatch(patch, cwd) {
457
- const result = spawnSync("git", ["apply", "--whitespace=fix", "-p0", "-"], {
842
+ const result = spawnSync2("git", ["apply", "--whitespace=fix", "-p0", "-"], {
458
843
  cwd,
459
844
  input: patch,
460
845
  encoding: "utf-8"
@@ -1537,22 +1922,29 @@ export {
1537
1922
  InMemoryConversationJournal,
1538
1923
  InMemoryRuntimeSessionStore,
1539
1924
  JudgeError,
1925
+ LIFTED_FINDING_ANALYST_ID,
1540
1926
  NotFoundError,
1541
1927
  PlannerError,
1542
1928
  RESEARCH_SUPERVISOR_SYSTEM_PROMPT,
1929
+ ROLLOUT_POLICY_BOUNDS,
1930
+ ROLLOUT_POLICY_EXTENSION,
1543
1931
  RuntimeRunStateError,
1544
1932
  SqlConversationJournal,
1545
1933
  ValidationError,
1546
1934
  agenticGenerator,
1547
1935
  applyExactAgentProfileDiff,
1936
+ applyRolloutPolicyToProfile,
1548
1937
  applyRunRecordDefaults,
1549
1938
  auditLoopRunner,
1550
1939
  buildAgentCandidateBundle,
1940
+ buildDriverSystem,
1551
1941
  buildForwardHeaders,
1552
1942
  buildKnowledgeImprovementExperimentBundles,
1553
1943
  buildLoopOtelSpans,
1554
1944
  buildLoopSpanNodes,
1555
1945
  buildRuntimeEventOtelSpans,
1946
+ campaignCellSpansToOtlp,
1947
+ campaignTraceResolver,
1556
1948
  candidateExecutionClaim,
1557
1949
  candidateKnowledgeExecutionPaths,
1558
1950
  captureAgentCandidateWorkspace,
@@ -1561,6 +1953,7 @@ export {
1561
1953
  commandVerifier,
1562
1954
  composeRuntimeHooks,
1563
1955
  computeBackoff,
1956
+ convertCampaignDirToOtlp,
1564
1957
  createAgentCandidateWorkspacePort,
1565
1958
  createAgentKnowledgeReadinessCheck,
1566
1959
  createConversationBackend,
@@ -1575,18 +1968,24 @@ export {
1575
1968
  createSupervisedKnowledgeUpdater,
1576
1969
  d1ToSqlAdapter,
1577
1970
  decideKnowledgeReadiness,
1971
+ defaultBuildPrompt,
1578
1972
  defaultIsRetryable,
1579
1973
  defineConversation,
1580
1974
  defineRuntimeHooks,
1581
1975
  deriveExecutionId,
1582
1976
  disposePreparedAgentCandidateExecution,
1977
+ driverLoopGenerator,
1978
+ enumerateNeighborPolicies,
1979
+ exactProcessProviderAsCandidateExecutor,
1583
1980
  executePreparedAgentCandidate,
1584
1981
  exportEvalRuns,
1982
+ findingLines,
1585
1983
  formatSupervisedKnowledgeTask,
1586
1984
  getModels,
1587
1985
  handleChatTurn,
1588
1986
  improve,
1589
1987
  improvementDriver,
1988
+ isAnalystFinding,
1590
1989
  isDelegatedLoopMode,
1591
1990
  isDepthExceeded,
1592
1991
  knowledgeReadinessDeliverable,
@@ -1596,11 +1995,14 @@ export {
1596
1995
  mcpServeVerifier,
1597
1996
  mcpToolsForRuntimeMcp,
1598
1997
  mcpToolsForRuntimeMcpSubset,
1998
+ normalizeRolloutPolicy,
1599
1999
  notifyRuntimeDecisionPoint,
1600
2000
  notifyRuntimeHookEvent,
2001
+ optimizerMethod,
1601
2002
  parseExactAgentProfile,
1602
2003
  parseExactAgentProfileDiff,
1603
2004
  parseLoopRunnerArgv,
2005
+ parseRolloutPolicy,
1604
2006
  persistCandidateOutputArtifact,
1605
2007
  prepareAgentCandidateExecution,
1606
2008
  profileDiffProposer,
@@ -1609,10 +2011,12 @@ export {
1609
2011
  readinessServerSentEvent,
1610
2012
  recoverExpiredAgentCandidateExecution,
1611
2013
  reflectiveGenerator,
2014
+ researchDriverNote,
1612
2015
  researchLoopRunner,
1613
2016
  resolveAgentBackend,
1614
2017
  resolveChatModel,
1615
2018
  resolveRouterBaseUrl,
2019
+ rolloutPolicyProposer,
1616
2020
  runAgentTask,
1617
2021
  runAgentTaskStream,
1618
2022
  runConversation,
@@ -1630,10 +2034,14 @@ export {
1630
2034
  sanitizeRuntimeStreamEvent,
1631
2035
  sealAgentCandidateBundle,
1632
2036
  selfImproveLoopRunner,
2037
+ serializeRolloutPolicy,
1633
2038
  sleep,
1634
2039
  slugifySpeaker,
1635
2040
  startRuntimeRun,
2041
+ strategyAuthorMethod,
1636
2042
  streamToolLoop,
2043
+ structuralRolloutPolicyFromProfile,
2044
+ toAnalystFindings,
1637
2045
  toolBuildPrompt,
1638
2046
  turnId,
1639
2047
  validateChatModelId,