@tangle-network/agent-runtime 0.69.0 → 0.70.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 (67) hide show
  1. package/README.md +81 -13
  2. package/dist/agent.d.ts +4 -5
  3. package/dist/agent.js +3 -4
  4. package/dist/agent.js.map +1 -1
  5. package/dist/analyst-loop.d.ts +3 -4
  6. package/dist/{chunk-K4FQSEXQ.js → chunk-BGOLR66M.js} +6 -6
  7. package/dist/{chunk-G6U3GVK2.js → chunk-CRAH5EY2.js} +2 -2
  8. package/dist/{chunk-RTDI2DHD.js → chunk-HY4YOQM2.js} +6 -6
  9. package/dist/chunk-HY4YOQM2.js.map +1 -0
  10. package/dist/{chunk-QZ6FA5LM.js → chunk-LJZ5GC6C.js} +3 -3
  11. package/dist/{chunk-NLRA6434.js → chunk-YFOPWG74.js} +577 -525
  12. package/dist/chunk-YFOPWG74.js.map +1 -0
  13. package/dist/{coordination-Curpzeyc.d.ts → coordination-C7WxwHXq.d.ts} +8 -1
  14. package/dist/{delegates-CLFNAKyi.d.ts → delegates-DqAgo32T.d.ts} +105 -10
  15. package/dist/{improvement-adapter-BC4HhuAR.d.ts → improvement-adapter-CioiEE2z.d.ts} +1 -1
  16. package/dist/index.d.ts +439 -100
  17. package/dist/index.js +591 -130
  18. package/dist/index.js.map +1 -1
  19. package/dist/intelligence.d.ts +2 -3
  20. package/dist/{loop-runner-bin-B6dzNZC8.d.ts → loop-runner-bin-a8bu4O5-.d.ts} +4 -4
  21. package/dist/loop-runner-bin.d.ts +7 -10
  22. package/dist/loop-runner-bin.js +6 -7
  23. package/dist/loops.d.ts +3149 -16
  24. package/dist/loops.js +33 -60
  25. package/dist/mcp/bin.js +13 -14
  26. package/dist/mcp/bin.js.map +1 -1
  27. package/dist/mcp/index.d.ts +8 -12
  28. package/dist/mcp/index.js +10 -12
  29. package/dist/mcp/index.js.map +1 -1
  30. package/dist/{openai-tools-CA2N3-Ak.d.ts → openai-tools-DPx9Gzvn.d.ts} +1 -1
  31. package/dist/profiles.d.ts +94 -6
  32. package/dist/profiles.js +320 -9
  33. package/dist/profiles.js.map +1 -1
  34. package/dist/{router-client-30Y_pca8.d.ts → router-client-C7kp_ECN.d.ts} +37 -1
  35. package/dist/{substrate-CUgk7F7s.d.ts → substrate-BoRXgvka.d.ts} +52 -1
  36. package/dist/{types-p8dWBIXL.d.ts → types-BC3bZpH0.d.ts} +1 -1
  37. package/dist/{types-Crxftafi.d.ts → types-BYa2ZOAx.d.ts} +83 -2
  38. package/dist/{worktree-fanout-DUiKPApb.d.ts → worktree-fanout-gNfl0Byj.d.ts} +9 -37
  39. package/package.json +17 -37
  40. package/dist/audit.d.ts +0 -93
  41. package/dist/audit.js +0 -312
  42. package/dist/audit.js.map +0 -1
  43. package/dist/chunk-4B6U4CVQ.js +0 -15
  44. package/dist/chunk-4B6U4CVQ.js.map +0 -1
  45. package/dist/chunk-NLRA6434.js.map +0 -1
  46. package/dist/chunk-O2UPHN7X.js +0 -114
  47. package/dist/chunk-O2UPHN7X.js.map +0 -1
  48. package/dist/chunk-RTDI2DHD.js.map +0 -1
  49. package/dist/coder-2leJPOvC.d.ts +0 -52
  50. package/dist/improvement.d.ts +0 -208
  51. package/dist/improvement.js +0 -343
  52. package/dist/improvement.js.map +0 -1
  53. package/dist/local-harness-BE_h8szs.d.ts +0 -93
  54. package/dist/run-loop-D3PwlG7J.d.ts +0 -112
  55. package/dist/runtime-hooks-C7JwKb9E.d.ts +0 -70
  56. package/dist/runtime.d.ts +0 -3120
  57. package/dist/runtime.js +0 -263
  58. package/dist/runtime.js.map +0 -1
  59. package/dist/topology.d.ts +0 -126
  60. package/dist/topology.js +0 -333
  61. package/dist/topology.js.map +0 -1
  62. package/dist/workflow.d.ts +0 -551
  63. package/dist/workflow.js +0 -1781
  64. package/dist/workflow.js.map +0 -1
  65. /package/dist/{chunk-K4FQSEXQ.js.map → chunk-BGOLR66M.js.map} +0 -0
  66. /package/dist/{chunk-G6U3GVK2.js.map → chunk-CRAH5EY2.js.map} +0 -0
  67. /package/dist/{chunk-QZ6FA5LM.js.map → chunk-LJZ5GC6C.js.map} +0 -0
@@ -1,343 +0,0 @@
1
- import {
2
- runLocalHarness
3
- } from "./chunk-O2UPHN7X.js";
4
- import "./chunk-DGUM43GV.js";
5
-
6
- // src/improvement/agentic-generator.ts
7
- import { spawnSync } from "child_process";
8
- function agenticGenerator(opts = {}) {
9
- const harness = opts.harness ?? "claude";
10
- const buildPrompt = opts.buildPrompt ?? defaultBuildPrompt;
11
- const run = opts.runHarness ?? runLocalHarness;
12
- const dirty = opts.isDirty ?? worktreeDirty;
13
- const verify = opts.verify;
14
- return {
15
- kind: `agentic:${harness}`,
16
- async generate({ worktreePath, report, findings, maxShots, signal }) {
17
- const basePrompt = buildPrompt({ report, findings });
18
- const shots = Math.max(1, maxShots);
19
- let attemptNote = "";
20
- for (let shot = 0; shot < shots; shot++) {
21
- if (signal.aborted) break;
22
- await run({
23
- harness,
24
- cwd: worktreePath,
25
- taskPrompt: attemptNote ? `${basePrompt}
26
-
27
- ${attemptNote}` : basePrompt,
28
- timeoutMs: opts.timeoutMs,
29
- signal
30
- });
31
- if (!dirty(worktreePath)) {
32
- attemptNote = EMPTY_TREE_NOTE;
33
- continue;
34
- }
35
- if (!verify) {
36
- return { applied: true, summary: summarize(findings) };
37
- }
38
- const result = await verify(worktreePath);
39
- if (result.ok) {
40
- return { applied: true, summary: summarize(findings) };
41
- }
42
- attemptNote = failureNote(result.feedback);
43
- }
44
- return { applied: false, summary: "" };
45
- }
46
- };
47
- }
48
- function defaultBuildPrompt(args) {
49
- const lines = [
50
- "You are improving this codebase based on an evaluation analysis.",
51
- "Make the smallest set of edits that addresses the findings below, then stop.",
52
- "Do not change unrelated code. Do not commit \u2014 leave changes in the working tree.",
53
- "",
54
- "Findings:"
55
- ];
56
- for (const f of args.findings) {
57
- const where = f.subject ? ` [${f.subject}]` : "";
58
- lines.push(`- (${f.severity})${where} ${f.claim}`);
59
- if (f.recommended_action) lines.push(` \u2192 ${f.recommended_action}`);
60
- }
61
- return lines.join("\n");
62
- }
63
- var EMPTY_TREE_NOTE = "NOTE: your previous attempt left the working tree unchanged. Make the concrete file edits now.";
64
- function failureNote(feedback) {
65
- const detail = feedback?.trim();
66
- return [
67
- "NOTE: your edits are in the working tree but verification FAILED.",
68
- "Fix the problem in place \u2014 build on your existing edits, do not revert them.",
69
- detail ? `Verifier output:
70
- ${truncate(detail, 4e3)}` : "No verifier detail was captured."
71
- ].join("\n");
72
- }
73
- function commandVerifier(command, args = [], timeoutMs = 3e5) {
74
- return (worktreePath) => {
75
- const result = spawnSync(command, args, {
76
- cwd: worktreePath,
77
- encoding: "utf-8",
78
- timeout: timeoutMs
79
- });
80
- if (result.signal) {
81
- return {
82
- ok: false,
83
- feedback: `verifier '${command}' killed by ${result.signal} (likely timeout after ${timeoutMs}ms)`
84
- };
85
- }
86
- if (result.error) {
87
- const code = result.error.code;
88
- if (code === "ENOENT") {
89
- throw new Error(
90
- `commandVerifier: '${command}' not found in PATH (setup bug, not a failed candidate)`
91
- );
92
- }
93
- throw new Error(`commandVerifier: '${command}' failed to spawn: ${result.error.message}`);
94
- }
95
- if (result.status === 0) return { ok: true };
96
- const out = `${result.stdout ?? ""}${result.stderr ?? ""}`.trim();
97
- return { ok: false, feedback: out.length > 0 ? out : `exit ${result.status}` };
98
- };
99
- }
100
- function summarize(findings) {
101
- if (findings.length === 0) return "agentic improvement";
102
- if (findings.length === 1) return `agentic: ${truncate(findings[0].claim, 64)}`;
103
- return `agentic: ${findings.length} findings addressed`;
104
- }
105
- function truncate(s, n) {
106
- return s.length <= n ? s : `${s.slice(0, n - 1)}\u2026`;
107
- }
108
- function worktreeDirty(worktreePath) {
109
- const result = spawnSync("git", ["status", "--porcelain"], {
110
- cwd: worktreePath,
111
- encoding: "utf-8"
112
- });
113
- if (result.error) {
114
- throw new Error(
115
- `agenticGenerator: git status failed to spawn in ${worktreePath}: ${result.error.message}`
116
- );
117
- }
118
- if (result.status !== 0) {
119
- throw new Error(
120
- `agenticGenerator: git status exited ${result.status} in ${worktreePath}: ${result.stderr.trim()}`
121
- );
122
- }
123
- return result.stdout.trim().length > 0;
124
- }
125
-
126
- // src/improvement/build-prompts.ts
127
- function findingLines(findings) {
128
- return findings.map((f) => {
129
- const where = f.subject ? ` [${f.subject}]` : "";
130
- const action = f.recommended_action ? ` \u2192 ${f.recommended_action}` : "";
131
- return `- (${f.severity})${where} ${f.claim}${action}`;
132
- });
133
- }
134
- function toolBuildPrompt(args) {
135
- return [
136
- "You are building a new TOOL for this codebase to address the gaps below.",
137
- "Write the tool as a small, self-contained module PLUS tests that exercise it.",
138
- "The tool must compile and its tests must pass \u2014 they will be run automatically;",
139
- "if verification fails you will get the error and another attempt. Do not commit;",
140
- "leave the changes in the working tree.",
141
- "",
142
- "Gaps the tool should close:",
143
- ...findingLines(args.findings)
144
- ].join("\n");
145
- }
146
- function mcpBuildPrompt(args) {
147
- return [
148
- "You are building a new MCP SERVER (Model Context Protocol) that exposes",
149
- "tool(s) addressing the gaps below, so any harness can mount it.",
150
- "Requirements that WILL be checked by booting the server:",
151
- "- it starts over stdio and answers the MCP `initialize` handshake,",
152
- "- `tools/list` returns at least one tool with a valid input schema.",
153
- "Newline-delimited JSON-RPC 2.0, protocol version 2024-11-05. Include a start",
154
- "command (e.g. a package.json `start` script or a clear entrypoint). If the",
155
- "boot-and-probe fails you will get the error and another attempt. Do not",
156
- "commit; leave the changes in the working tree.",
157
- "",
158
- "Capabilities the server should provide:",
159
- ...findingLines(args.findings)
160
- ].join("\n");
161
- }
162
-
163
- // src/improvement/improvement-driver.ts
164
- function improvementDriver(opts) {
165
- const baseRef = opts.baseRef ?? "main";
166
- return {
167
- kind: `improvement:${opts.generator.kind}`,
168
- async propose(ctx) {
169
- const findings = resolveFindings(ctx);
170
- if (findings.length === 0 && ctx.report === void 0) return [];
171
- const surfaces = [];
172
- for (let i = 0; i < ctx.populationSize; i++) {
173
- if (ctx.signal.aborted) break;
174
- const wt = await opts.worktree.create({
175
- baseRef,
176
- label: `${opts.generator.kind}-gen${ctx.generation}-cand${i}`
177
- });
178
- try {
179
- const { applied, summary } = await opts.generator.generate({
180
- worktreePath: wt.path,
181
- report: ctx.report,
182
- findings,
183
- dataset: ctx.dataset,
184
- maxShots: ctx.maxImprovementShots ?? 1,
185
- signal: ctx.signal
186
- });
187
- if (!applied) {
188
- await opts.worktree.discard(wt);
189
- continue;
190
- }
191
- surfaces.push(await opts.worktree.finalize(wt, summary));
192
- } catch (err) {
193
- await opts.worktree.discard(wt).catch(() => {
194
- });
195
- throw err;
196
- }
197
- }
198
- return surfaces;
199
- }
200
- };
201
- }
202
- function resolveFindings(ctx) {
203
- const report = ctx.report;
204
- if (report && typeof report === "object" && "findings" in report) {
205
- const f = report.findings;
206
- if (Array.isArray(f) && f.length > 0) return f;
207
- }
208
- return ctx.findings;
209
- }
210
-
211
- // src/improvement/mcp-serve-verifier.ts
212
- import { spawn } from "child_process";
213
- import { createInterface } from "readline";
214
- var PROTOCOL_VERSION = "2024-11-05";
215
- function mcpServeVerifier(spec) {
216
- const timeoutMs = spec.timeoutMs ?? 3e4;
217
- const minTools = spec.minTools ?? 1;
218
- return (worktreePath) => new Promise((resolve, reject) => {
219
- const child = spawn(spec.command, spec.args ?? [], {
220
- cwd: worktreePath,
221
- stdio: ["pipe", "pipe", "pipe"],
222
- env: { ...process.env, ...spec.env }
223
- });
224
- const stderr = [];
225
- let settled = false;
226
- let nextId = 1;
227
- const initId = nextId++;
228
- let listId = -1;
229
- const settle = (fn) => {
230
- if (settled) return;
231
- settled = true;
232
- clearTimeout(timer);
233
- rl.close();
234
- child.kill("SIGKILL");
235
- fn();
236
- };
237
- const withStderr = (msg) => stderr.length > 0 ? `${msg}
238
- stderr:
239
- ${stderr.join("").slice(-2e3)}` : msg;
240
- const pass = () => settle(() => resolve({ ok: true }));
241
- const failCandidate = (msg) => settle(() => resolve({ ok: false, feedback: withStderr(msg) }));
242
- const setupFault = (err) => settle(() => reject(err));
243
- const send = (msg) => {
244
- try {
245
- child.stdin.write(`${JSON.stringify(msg)}
246
- `);
247
- return true;
248
- } catch (err) {
249
- failCandidate(`writing to MCP server stdin failed: ${err.message}`);
250
- return false;
251
- }
252
- };
253
- child.on("error", (err) => {
254
- const code = err.code;
255
- setupFault(
256
- code === "ENOENT" ? new Error(
257
- `mcpServeVerifier: '${spec.command}' not found in PATH (setup bug, not a failed candidate)`
258
- ) : new Error(`mcpServeVerifier: '${spec.command}' failed to spawn: ${err.message}`)
259
- );
260
- });
261
- child.on("exit", (code, signal) => {
262
- failCandidate(`MCP server exited (code ${code}, signal ${signal}) before serving`);
263
- });
264
- child.stderr.on("data", (d) => stderr.push(String(d)));
265
- const rl = createInterface({ input: child.stdout });
266
- rl.on("line", (line) => {
267
- let msg;
268
- try {
269
- msg = JSON.parse(line);
270
- } catch {
271
- return;
272
- }
273
- if (!msg || typeof msg !== "object") return;
274
- if (msg.id === initId) {
275
- if (msg.error) return failCandidate(`initialize errored: ${JSON.stringify(msg.error)}`);
276
- if (!send({ jsonrpc: "2.0", method: "notifications/initialized" })) return;
277
- listId = nextId++;
278
- send({ jsonrpc: "2.0", id: listId, method: "tools/list" });
279
- return;
280
- }
281
- if (msg.id === listId) {
282
- if (msg.error) return failCandidate(`tools/list errored: ${JSON.stringify(msg.error)}`);
283
- const tools = msg.result?.tools;
284
- if (!Array.isArray(tools)) return failCandidate("tools/list result has no tools array");
285
- if (tools.length < minTools) {
286
- return failCandidate(`tools/list returned ${tools.length} tool(s), need >= ${minTools}`);
287
- }
288
- return pass();
289
- }
290
- });
291
- const timer = setTimeout(
292
- () => failCandidate(`MCP server did not complete the handshake within ${timeoutMs}ms`),
293
- timeoutMs
294
- );
295
- send({
296
- jsonrpc: "2.0",
297
- id: initId,
298
- method: "initialize",
299
- params: {
300
- protocolVersion: PROTOCOL_VERSION,
301
- capabilities: {},
302
- clientInfo: { name: "agent-runtime-mcp-verify", version: "0" }
303
- }
304
- });
305
- });
306
- }
307
-
308
- // src/improvement/reflective-generator.ts
309
- import { spawnSync as spawnSync2 } from "child_process";
310
- function reflectiveGenerator(opts) {
311
- return {
312
- kind: "reflective",
313
- async generate({ worktreePath, findings }) {
314
- const batch = await opts.improvementAdapter.proposeFromFindings(findings);
315
- if (batch.edits.length === 0) return { applied: false, summary: "" };
316
- let applied = 0;
317
- for (const edit of batch.edits) {
318
- if (applyPatch(edit.patch, worktreePath)) applied++;
319
- }
320
- if (applied === 0) return { applied: false, summary: "" };
321
- const summary = batch.edits.length === 1 ? batch.edits[0].summary : `analyst: ${applied} surface edit${applied === 1 ? "" : "s"}`;
322
- return { applied: true, summary };
323
- }
324
- };
325
- }
326
- function applyPatch(patch, cwd) {
327
- const result = spawnSync2("git", ["apply", "--whitespace=fix", "-p0", "-"], {
328
- cwd,
329
- input: patch,
330
- encoding: "utf-8"
331
- });
332
- return result.status === 0;
333
- }
334
- export {
335
- agenticGenerator,
336
- commandVerifier,
337
- improvementDriver,
338
- mcpBuildPrompt,
339
- mcpServeVerifier,
340
- reflectiveGenerator,
341
- toolBuildPrompt
342
- };
343
- //# sourceMappingURL=improvement.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/improvement/agentic-generator.ts","../src/improvement/build-prompts.ts","../src/improvement/improvement-driver.ts","../src/improvement/mcp-serve-verifier.ts","../src/improvement/reflective-generator.ts"],"sourcesContent":["/**\n * @experimental\n *\n * `agenticGenerator` — the full-agentic `CandidateGenerator`: the\n * `shots=N, sandbox=on` setting of the one `improvementDriver`. It runs a real\n * coding harness (claude / codex / opencode) inside the candidate worktree the\n * driver already created, letting the agent read the codebase + the research\n * report and make the change in place. The driver then commits the worktree\n * into a `CodeSurface`.\n *\n * Mechanism: identical to the proven Phase-2.8 in-process executor — spawn the\n * harness as a subprocess with `cwd` = the worktree, on the same filesystem,\n * so edits land in place (no sandbox-mount round-trip). `runLocalHarness` is\n * the verified primitive. The OUTER sandbox is the improvement loop's own\n * execution context; the generator does not nest a second sandbox per\n * candidate (which would reintroduce a host↔sandbox worktree-transport\n * problem that does not need solving here).\n *\n * `maxShots` is the DEPTH dial — a multi-shot verify-in-session loop, NOT the\n * kernel `runLoop`. Each shot runs one full harness session in the (persistent)\n * worktree; between shots the loop refines based on what the last shot produced:\n * - empty tree → \"you changed nothing, make the edits\" → retry\n * - dirty + `verify` fails → feed the verifier's failure into the next shot\n * (the worktree persists, so the harness RESUMES atop its own failing\n * edits with the error in hand — no `--resume` session plumbing needed,\n * and harness-agnostic across claude/codex/opencode)\n * - dirty + `verify` ok (or no verifier configured) → return the candidate\n * A candidate that never verifies within `maxShots` is discarded (`applied:\n * false`), never shipped — if you configured a verifier, a non-passing tree is\n * not a candidate. With no verifier the legacy behavior holds: first dirty shot\n * is the candidate.\n */\n\nimport { spawnSync } from 'node:child_process'\nimport type { AnalystFinding } from '@tangle-network/agent-eval'\nimport { type LocalHarness, runLocalHarness } from '../mcp/local-harness'\nimport type { CandidateGenerator } from './improvement-driver'\n\n/** Outcome of verifying a candidate worktree. `feedback` (compiler errors,\n * failing test output) is fed into the next shot when `ok` is false. */\nexport interface VerifyResult {\n ok: boolean\n feedback?: string\n}\n\n/** Verifies the edited worktree. Sync or async; throws only on a setup fault\n * (a candidate that fails verification returns `{ok:false}`, it does not\n * throw). */\nexport type Verifier = (worktreePath: string) => Promise<VerifyResult> | VerifyResult\n\nexport interface AgenticGeneratorOptions {\n /** Local coding harness to run in the worktree. Default `claude`. */\n harness?: LocalHarness\n /** Per-shot wall-clock timeout (ms). Default = `runLocalHarness` default (5m). */\n timeoutMs?: number\n /** Build the harness task prompt from the report + findings. Override for\n * domain phrasing; the default turns findings into a concrete coder task. */\n buildPrompt?: (args: { report: unknown; findings: AnalystFinding[] }) => string\n /** Verify the worktree after each dirtying shot. When set, a candidate that\n * fails verification is NOT returned — the failure feeds the next shot\n * (verify-in-session), up to `maxShots`; a candidate that never verifies is\n * discarded (`applied:false`), never shipped. Omitted ⇒ legacy behavior:\n * the first dirty shot is the candidate. See `commandVerifier`. */\n verify?: Verifier\n /** Test seam — inject the harness runner (defaults to `runLocalHarness`). */\n runHarness?: typeof runLocalHarness\n /** Test seam — inject the worktree-dirty check (defaults to `git status`). */\n isDirty?: (worktreePath: string) => boolean\n}\n\nexport function agenticGenerator(opts: AgenticGeneratorOptions = {}): CandidateGenerator {\n const harness = opts.harness ?? 'claude'\n const buildPrompt = opts.buildPrompt ?? defaultBuildPrompt\n const run = opts.runHarness ?? runLocalHarness\n const dirty = opts.isDirty ?? worktreeDirty\n const verify = opts.verify\n\n return {\n kind: `agentic:${harness}`,\n async generate({ worktreePath, report, findings, maxShots, signal }) {\n const basePrompt = buildPrompt({ report, findings })\n const shots = Math.max(1, maxShots)\n // Feedback appended to the base prompt for the NEXT shot — empty on shot 0.\n let attemptNote = ''\n\n for (let shot = 0; shot < shots; shot++) {\n if (signal.aborted) break\n await run({\n harness,\n cwd: worktreePath,\n taskPrompt: attemptNote ? `${basePrompt}\\n\\n${attemptNote}` : basePrompt,\n timeoutMs: opts.timeoutMs,\n signal,\n })\n\n // The worktree IS the signal: no edits ⇒ tell the next shot to act.\n if (!dirty(worktreePath)) {\n attemptNote = EMPTY_TREE_NOTE\n continue\n }\n\n // Dirty: with no verifier the diff IS the candidate (we trust the diff,\n // not the harness's stdout). With a verifier the candidate must pass it.\n if (!verify) {\n return { applied: true, summary: summarize(findings) }\n }\n const result = await verify(worktreePath)\n if (result.ok) {\n return { applied: true, summary: summarize(findings) }\n }\n // Dirty but failing — resume next shot atop these edits with the error.\n attemptNote = failureNote(result.feedback)\n }\n\n // Shots exhausted: no verified candidate (or, sans verifier, no edits).\n return { applied: false, summary: '' }\n },\n }\n}\n\n/** Turn the analyst's findings (+ optional report) into a concrete coder task. */\nfunction defaultBuildPrompt(args: { report: unknown; findings: AnalystFinding[] }): string {\n const lines: string[] = [\n 'You are improving this codebase based on an evaluation analysis.',\n 'Make the smallest set of edits that addresses the findings below, then stop.',\n 'Do not change unrelated code. Do not commit — leave changes in the working tree.',\n '',\n 'Findings:',\n ]\n for (const f of args.findings) {\n const where = f.subject ? ` [${f.subject}]` : ''\n lines.push(`- (${f.severity})${where} ${f.claim}`)\n if (f.recommended_action) lines.push(` → ${f.recommended_action}`)\n }\n return lines.join('\\n')\n}\n\nconst EMPTY_TREE_NOTE =\n 'NOTE: your previous attempt left the working tree unchanged. Make the concrete file edits now.'\n\n/** Next-shot feedback when the worktree is dirty but failed verification. The\n * edits persist on disk, so the harness resumes atop them — tell it to fix in\n * place, not start over. Verifier detail is truncated to keep the prompt bounded. */\nfunction failureNote(feedback?: string): string {\n const detail = feedback?.trim()\n return [\n 'NOTE: your edits are in the working tree but verification FAILED.',\n 'Fix the problem in place — build on your existing edits, do not revert them.',\n detail ? `Verifier output:\\n${truncate(detail, 4000)}` : 'No verifier detail was captured.',\n ].join('\\n')\n}\n\n/** A `Verifier` that runs a command in the worktree: exit 0 ⇒ ok, any other\n * exit ⇒ failed with stdout+stderr as feedback. The common case — verify by\n * `tsc --noEmit`, `pnpm build`, or a test command. A timeout is treated as a\n * FAILED candidate (a change that hangs the build is a bad change); a missing\n * binary or spawn fault throws (a setup bug, not a failed candidate — no\n * silent fallback). */\nexport function commandVerifier(\n command: string,\n args: string[] = [],\n timeoutMs = 300_000,\n): Verifier {\n return (worktreePath: string): VerifyResult => {\n const result = spawnSync(command, args, {\n cwd: worktreePath,\n encoding: 'utf-8',\n timeout: timeoutMs,\n })\n if (result.signal) {\n return {\n ok: false,\n feedback: `verifier '${command}' killed by ${result.signal} (likely timeout after ${timeoutMs}ms)`,\n }\n }\n if (result.error) {\n const code = (result.error as NodeJS.ErrnoException).code\n if (code === 'ENOENT') {\n throw new Error(\n `commandVerifier: '${command}' not found in PATH (setup bug, not a failed candidate)`,\n )\n }\n throw new Error(`commandVerifier: '${command}' failed to spawn: ${result.error.message}`)\n }\n if (result.status === 0) return { ok: true }\n const out = `${result.stdout ?? ''}${result.stderr ?? ''}`.trim()\n return { ok: false, feedback: out.length > 0 ? out : `exit ${result.status}` }\n }\n}\n\n/** A one-line summary for the commit message, derived from the findings. */\nfunction summarize(findings: AnalystFinding[]): string {\n if (findings.length === 0) return 'agentic improvement'\n if (findings.length === 1) return `agentic: ${truncate(findings[0]!.claim, 64)}`\n return `agentic: ${findings.length} findings addressed`\n}\n\nfunction truncate(s: string, n: number): string {\n return s.length <= n ? s : `${s.slice(0, n - 1)}…`\n}\n\n/** Non-empty `git status --porcelain` ⇒ the harness changed the worktree.\n * Fails loud: the worktree is a fresh checkout, so a git error here means\n * something is genuinely broken (git missing, corrupt index, killed mid-run).\n * Folding that into `false` would silently discard a candidate and mask the\n * real failure — forbidden by the no-silent-fallbacks doctrine. */\nfunction worktreeDirty(worktreePath: string): boolean {\n const result = spawnSync('git', ['status', '--porcelain'], {\n cwd: worktreePath,\n encoding: 'utf-8',\n })\n if (result.error) {\n throw new Error(\n `agenticGenerator: git status failed to spawn in ${worktreePath}: ${result.error.message}`,\n )\n }\n if (result.status !== 0) {\n throw new Error(\n `agenticGenerator: git status exited ${result.status} in ${worktreePath}: ${result.stderr.trim()}`,\n )\n }\n return result.stdout.trim().length > 0\n}\n","/**\n * Build-prompt starting points for the two buildable artifact types. There is\n * NO `toolGenerator`/`mcpGenerator` wrapper — the factory is `agenticGenerator`\n * + a verifier (docs/artifact-lifecycle-frontier.md), so a tool or an MCP\n * server is built by composing the pieces directly:\n *\n * // a tool:\n * agenticGenerator({ buildPrompt: toolBuildPrompt, verify: commandVerifier('pnpm', ['test']) })\n * // an MCP server:\n * agenticGenerator({ buildPrompt: mcpBuildPrompt, verify: mcpServeVerifier({ command: 'node', args: ['server.mjs'] }) })\n *\n * These are the only type-specific bit (the phrasing that points the agent at a\n * tool vs. an MCP); the worktree, resume-on-failure loop, and improvement-loop\n * wrapper are shared. MCP is the load-bearing target — it is how a harness\n * acquires tools; raw tools matter where we control the loader.\n */\n\nimport type { AnalystFinding } from '@tangle-network/agent-eval'\n\ntype FindingsArg = { report: unknown; findings: AnalystFinding[] }\n\nfunction findingLines(findings: AnalystFinding[]): string[] {\n return findings.map((f) => {\n const where = f.subject ? ` [${f.subject}]` : ''\n const action = f.recommended_action ? ` → ${f.recommended_action}` : ''\n return `- (${f.severity})${where} ${f.claim}${action}`\n })\n}\n\nexport function toolBuildPrompt(args: FindingsArg): string {\n return [\n 'You are building a new TOOL for this codebase to address the gaps below.',\n 'Write the tool as a small, self-contained module PLUS tests that exercise it.',\n 'The tool must compile and its tests must pass — they will be run automatically;',\n 'if verification fails you will get the error and another attempt. Do not commit;',\n 'leave the changes in the working tree.',\n '',\n 'Gaps the tool should close:',\n ...findingLines(args.findings),\n ].join('\\n')\n}\n\nexport function mcpBuildPrompt(args: FindingsArg): string {\n return [\n 'You are building a new MCP SERVER (Model Context Protocol) that exposes',\n 'tool(s) addressing the gaps below, so any harness can mount it.',\n 'Requirements that WILL be checked by booting the server:',\n '- it starts over stdio and answers the MCP `initialize` handshake,',\n '- `tools/list` returns at least one tool with a valid input schema.',\n 'Newline-delimited JSON-RPC 2.0, protocol version 2024-11-05. Include a start',\n 'command (e.g. a package.json `start` script or a clear entrypoint). If the',\n 'boot-and-probe fails you will get the error and another attempt. Do not',\n 'commit; leave the changes in the working tree.',\n '',\n 'Capabilities the server should provide:',\n ...findingLines(args.findings),\n ].join('\\n')\n}\n","/**\n * @experimental\n *\n * `improvementDriver` — the ONE reflective/agentic improvement driver for\n * agent-eval's improvement loop. It implements `ImprovementDriver` and owns\n * the candidate lifecycle (worktree create → generate → finalize/discard,\n * × populationSize); it delegates the only thing that genuinely varies — HOW\n * a candidate change is produced — to a pluggable `CandidateGenerator`.\n *\n * There is no separate \"analyst driver\" vs \"autoresearch driver\": those are\n * the SAME driver at two settings of a dial.\n * - cheap reflective path → `reflectiveGenerator` (shots=1, no sandbox;\n * applies pre-drafted patches)\n * - full agentic path → `agenticGenerator` (shots=N, multi-shot\n * verify-in-session loop; an agent reads code +\n * report, edits, and re-tries on verifier failure)\n * Both emit changes into a worktree the driver finalizes into a\n * `CodeSurface{ worktreeRef }` the loop measures on the holdout. See\n * agent-eval's `docs/design/self-improvement-engine.md`.\n */\n\nimport type { AnalystFinding } from '@tangle-network/agent-eval'\nimport type {\n CodeSurface,\n ImprovementDriver,\n LabeledScenarioStore,\n ProposeContext,\n WorktreeAdapter,\n} from '@tangle-network/agent-eval/campaign'\n\n/** The byte-producing seam — the ONE thing that differs between the cheap\n * reflective path and the full agentic path. A generator makes (uncommitted)\n * changes inside `worktreePath`; the driver commits them via the worktree\n * adapter's `finalize`. */\nexport interface CandidateGenerator {\n kind: string\n generate(args: {\n /** The candidate worktree — a fresh checkout of baseRef. Write changes here. */\n worktreePath: string\n /** Phase-2 research report (analyst findings + diff), opaque. */\n report: unknown\n /** Findings resolved from the report or the loop context. */\n findings: AnalystFinding[]\n /** Handle to all captured data, to ground the change. */\n dataset?: LabeledScenarioStore\n /** DEPTH: max iterations the generator may take (agentic uses this; the\n * reflective generator ignores it). */\n maxShots: number\n signal: AbortSignal\n }): Promise<{ applied: boolean; summary: string }>\n}\n\nexport interface ImprovementDriverOptions {\n worktree: WorktreeAdapter\n generator: CandidateGenerator\n /** Base ref candidate worktrees fork from. Default `main`. */\n baseRef?: string\n}\n\nexport function improvementDriver(\n opts: ImprovementDriverOptions,\n): ImprovementDriver<AnalystFinding> {\n const baseRef = opts.baseRef ?? 'main'\n\n return {\n kind: `improvement:${opts.generator.kind}`,\n async propose(ctx) {\n const findings = resolveFindings(ctx)\n // No signal to act on — propose nothing rather than spin up worktrees.\n if (findings.length === 0 && ctx.report === undefined) return []\n\n const surfaces: CodeSurface[] = []\n for (let i = 0; i < ctx.populationSize; i++) {\n if (ctx.signal.aborted) break\n const wt = await opts.worktree.create({\n baseRef,\n label: `${opts.generator.kind}-gen${ctx.generation}-cand${i}`,\n })\n // Once a worktree exists it MUST be accounted for: finalized into a\n // surface, or discarded. A throw from generate()/finalize() must not\n // leak the worktree + branch — discard best-effort, then rethrow loud.\n try {\n const { applied, summary } = await opts.generator.generate({\n worktreePath: wt.path,\n report: ctx.report,\n findings,\n dataset: ctx.dataset,\n maxShots: ctx.maxImprovementShots ?? 1,\n signal: ctx.signal,\n })\n if (!applied) {\n await opts.worktree.discard(wt)\n continue\n }\n surfaces.push(await opts.worktree.finalize(wt, summary))\n } catch (err) {\n // Best-effort cleanup; never mask the original failure.\n await opts.worktree.discard(wt).catch(() => {})\n throw err\n }\n }\n return surfaces\n },\n }\n}\n\n/** Phase-2 report carries `findings` when present; else fall back to the\n * loop's `ctx.findings`. The report is opaque to the substrate, so probe it\n * structurally. */\nfunction resolveFindings(ctx: ProposeContext<AnalystFinding>): AnalystFinding[] {\n const report = ctx.report\n if (report && typeof report === 'object' && 'findings' in report) {\n const f = (report as { findings: unknown }).findings\n if (Array.isArray(f) && f.length > 0) return f as AnalystFinding[]\n }\n return ctx.findings\n}\n","/**\n * `mcpServeVerifier` — the intrinsic verifier for a built MCP server: the\n * boot-and-probe checker named in docs/artifact-lifecycle-frontier.md. A\n * generated MCP server is only a candidate if it actually *serves* — so this\n * boots it over stdio (the default local MCP transport) and runs the real\n * handshake: `initialize` → `notifications/initialized` → `tools/list`, and\n * asserts the server answers with at least `minTools` tools.\n *\n * Outcomes follow the `Verifier` contract: a server that fails to start, exits\n * early, errors the handshake, times out, or exposes no tools is a FAILED\n * candidate (`{ok:false}`, fed back into the next generation shot); a missing\n * start binary or spawn fault THROWS (a setup bug, never a silent fallback).\n *\n * Protocol matches the runtime's own stdio MCP server (src/mcp/server.ts):\n * newline-delimited JSON-RPC 2.0, protocol version 2024-11-05.\n */\n\nimport { spawn } from 'node:child_process'\nimport { createInterface } from 'node:readline'\nimport type { Verifier, VerifyResult } from './agentic-generator'\n\nconst PROTOCOL_VERSION = '2024-11-05'\n\nexport interface McpServeSpec {\n /** Command that starts the built MCP server in the worktree (stdio transport). */\n command: string\n args?: string[]\n /** Extra env for the server process (merged over `process.env`). */\n env?: Record<string, string>\n /** Handshake timeout (ms). Default 30s. */\n timeoutMs?: number\n /** Minimum tools the server must expose to pass. Default 1. */\n minTools?: number\n}\n\ninterface JsonRpcResponse {\n jsonrpc?: string\n id?: number | string | null\n result?: unknown\n error?: { code: number; message: string }\n}\n\nexport function mcpServeVerifier(spec: McpServeSpec): Verifier {\n const timeoutMs = spec.timeoutMs ?? 30_000\n const minTools = spec.minTools ?? 1\n\n return (worktreePath: string): Promise<VerifyResult> =>\n new Promise<VerifyResult>((resolve, reject) => {\n const child = spawn(spec.command, spec.args ?? [], {\n cwd: worktreePath,\n stdio: ['pipe', 'pipe', 'pipe'],\n env: { ...process.env, ...spec.env },\n })\n\n const stderr: string[] = []\n let settled = false\n let nextId = 1\n const initId = nextId++\n let listId = -1\n\n const settle = (fn: () => void) => {\n if (settled) return\n settled = true\n clearTimeout(timer)\n rl.close()\n child.kill('SIGKILL')\n fn()\n }\n const withStderr = (msg: string) =>\n stderr.length > 0 ? `${msg}\\nstderr:\\n${stderr.join('').slice(-2000)}` : msg\n const pass = () => settle(() => resolve({ ok: true }))\n const failCandidate = (msg: string) =>\n settle(() => resolve({ ok: false, feedback: withStderr(msg) }))\n const setupFault = (err: Error) => settle(() => reject(err))\n\n const send = (msg: Record<string, unknown>): boolean => {\n try {\n child.stdin.write(`${JSON.stringify(msg)}\\n`)\n return true\n } catch (err) {\n // EPIPE: the server died mid-handshake — a failed candidate, not a fault.\n failCandidate(`writing to MCP server stdin failed: ${(err as Error).message}`)\n return false\n }\n }\n\n child.on('error', (err) => {\n const code = (err as NodeJS.ErrnoException).code\n setupFault(\n code === 'ENOENT'\n ? new Error(\n `mcpServeVerifier: '${spec.command}' not found in PATH (setup bug, not a failed candidate)`,\n )\n : new Error(`mcpServeVerifier: '${spec.command}' failed to spawn: ${err.message}`),\n )\n })\n child.on('exit', (code, signal) => {\n // An exit before the handshake completes is a failed candidate (the\n // server crashed on boot); after we settle, our own SIGKILL fires here.\n failCandidate(`MCP server exited (code ${code}, signal ${signal}) before serving`)\n })\n child.stderr.on('data', (d) => stderr.push(String(d)))\n\n const rl = createInterface({ input: child.stdout })\n rl.on('line', (line) => {\n let msg: JsonRpcResponse | undefined\n try {\n msg = JSON.parse(line) as JsonRpcResponse\n } catch {\n return // servers log to stdout too; skip non-JSON lines\n }\n if (!msg || typeof msg !== 'object') return\n\n if (msg.id === initId) {\n if (msg.error) return failCandidate(`initialize errored: ${JSON.stringify(msg.error)}`)\n if (!send({ jsonrpc: '2.0', method: 'notifications/initialized' })) return\n listId = nextId++\n send({ jsonrpc: '2.0', id: listId, method: 'tools/list' })\n return\n }\n if (msg.id === listId) {\n if (msg.error) return failCandidate(`tools/list errored: ${JSON.stringify(msg.error)}`)\n const tools = (msg.result as { tools?: unknown[] } | undefined)?.tools\n if (!Array.isArray(tools)) return failCandidate('tools/list result has no tools array')\n if (tools.length < minTools) {\n return failCandidate(`tools/list returned ${tools.length} tool(s), need >= ${minTools}`)\n }\n return pass()\n }\n })\n\n const timer = setTimeout(\n () => failCandidate(`MCP server did not complete the handshake within ${timeoutMs}ms`),\n timeoutMs,\n )\n\n send({\n jsonrpc: '2.0',\n id: initId,\n method: 'initialize',\n params: {\n protocolVersion: PROTOCOL_VERSION,\n capabilities: {},\n clientInfo: { name: 'agent-runtime-mcp-verify', version: '0' },\n },\n })\n })\n}\n","/**\n * @experimental\n *\n * `reflectiveGenerator` — the cheap, no-sandbox `CandidateGenerator`. It drafts\n * surface edits via the existing improvement adapter (`proposeFromFindings`,\n * one LLM patch per finding) and applies them as ONE coherent improvement into\n * the candidate worktree. `maxShots` is ignored — reflection is single-shot by\n * construction (the patches are already drafted).\n *\n * This is the `shots=1, sandbox=off` setting of the one improvement driver.\n * The `agenticGenerator` (a multi-shot verify-in-session loop) is the\n * `shots=N` setting — both plug into the same `improvementDriver`.\n */\n\nimport { spawnSync } from 'node:child_process'\nimport type { SurfaceImprovementEdit } from '../agent/improvement-adapter'\nimport type { ImprovementAdapter } from '../analyst-loop/types'\nimport type { CandidateGenerator } from './improvement-driver'\n\nexport interface ReflectiveGeneratorOptions {\n improvementAdapter: ImprovementAdapter<SurfaceImprovementEdit>\n}\n\nexport function reflectiveGenerator(opts: ReflectiveGeneratorOptions): CandidateGenerator {\n return {\n kind: 'reflective',\n async generate({ worktreePath, findings }) {\n const batch = await opts.improvementAdapter.proposeFromFindings(findings)\n if (batch.edits.length === 0) return { applied: false, summary: '' }\n\n let applied = 0\n for (const edit of batch.edits) {\n if (applyPatch(edit.patch, worktreePath)) applied++\n }\n if (applied === 0) return { applied: false, summary: '' }\n\n const summary =\n batch.edits.length === 1\n ? batch.edits[0]!.summary\n : `analyst: ${applied} surface edit${applied === 1 ? '' : 's'}`\n return { applied: true, summary }\n },\n }\n}\n\n/** Mirror the improvement adapter's proven apply invocation, run inside the\n * candidate worktree (a fresh checkout of baseRef, so `-p0` paths match). */\nfunction applyPatch(patch: string, cwd: string): boolean {\n const result = spawnSync('git', ['apply', '--whitespace=fix', '-p0', '-'], {\n cwd,\n input: patch,\n encoding: 'utf-8',\n })\n return result.status === 0\n}\n"],"mappings":"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","names":["spawnSync"]}
@@ -1,93 +0,0 @@
1
- import { ChildProcess } from 'node:child_process';
2
-
3
- /**
4
- * @experimental
5
- *
6
- * Subprocess wrappers for the local coding-harness CLIs installed in the
7
- * sandbox image (claude-code, codex, opencode). Used by the in-process
8
- * delegation executor (`createInProcessExecutor`) so a `delegate_code` call
9
- * spawns a real harness on a real git worktree instead of provisioning a
10
- * sibling sandbox.
11
- *
12
- * All harness invocations:
13
- * - run with `cwd` set to the worktree
14
- * - inherit env from the parent (the MCP server inside the sandbox has
15
- * the harness's auth already)
16
- * - capture stdout/stderr
17
- * - support cancellation via AbortSignal
18
- * - enforce a wall-clock timeout
19
- */
20
-
21
- /** Local coding harness available inside the sandbox. */
22
- type LocalHarness = 'claude' | 'codex' | 'opencode';
23
- /** @experimental */
24
- interface RunLocalHarnessOptions {
25
- harness: LocalHarness;
26
- /** Working directory for the subprocess (typically a worktree path). */
27
- cwd: string;
28
- /** Prompt forwarded as the harness CLI's task argument. */
29
- taskPrompt: string;
30
- /**
31
- * Pre-built command + args (e.g. from `harnessInvocation` so the full authored
32
- * `AgentProfile` — systemPrompt + model — reaches the harness). When set it OVERRIDES the
33
- * default prompt-only `buildArgs(taskPrompt)` path; `command` defaults to the harness's
34
- * default binary when only `args` is supplied. When absent the legacy prompt-only shape
35
- * is used unchanged.
36
- */
37
- invocation?: {
38
- command?: string;
39
- args: ReadonlyArray<string>;
40
- };
41
- /** Wall-clock kill deadline (ms). Default 5 min. Subprocess SIGTERMed on expiry. */
42
- timeoutMs?: number;
43
- /** Caller cancellation. SIGTERM is sent on abort. */
44
- signal?: AbortSignal;
45
- /** Override env (defaults to inheriting from the parent). */
46
- env?: NodeJS.ProcessEnv;
47
- /**
48
- * Test seam — inject a custom spawner so unit tests can mock the
49
- * subprocess without touching the OS. Defaults to node's `child_process.spawn`.
50
- */
51
- spawn?: (command: string, args: ReadonlyArray<string>, opts: {
52
- cwd: string;
53
- env: NodeJS.ProcessEnv;
54
- stdio: 'pipe';
55
- }) => ChildProcess;
56
- }
57
- /** @experimental */
58
- interface LocalHarnessResult {
59
- /** OS exit code. `null` when killed before exit. */
60
- exitCode: number | null;
61
- /** Concatenated stdout. */
62
- stdout: string;
63
- /** Concatenated stderr. */
64
- stderr: string;
65
- /** Set when the process exited via signal (timeout / abort). */
66
- killedBySignal: NodeJS.Signals | null;
67
- /** Wall-clock duration ms (spawn → exit). */
68
- durationMs: number;
69
- /** Set when timeoutMs elapsed before exit. */
70
- timedOut: boolean;
71
- }
72
- /**
73
- * Spawn a local coding harness CLI as a subprocess + collect its output.
74
- *
75
- * NOT responsible for parsing the harness's output or extracting a diff —
76
- * the in-process executor's `streamPrompt` orchestrates `git diff` against
77
- * the worktree after this resolves. This function is intentionally narrow:
78
- * spawn, wait, capture, return.
79
- *
80
- * Fails loud — throws when:
81
- * - `cwd` doesn't exist (subprocess emits ENOENT; surfaced as Error)
82
- * - the harness binary is not on PATH (ENOENT)
83
- *
84
- * Does NOT throw when:
85
- * - the subprocess exits non-zero (`result.exitCode` carries the code)
86
- * - the subprocess is aborted / timed out (`result.killedBySignal` /
87
- * `result.timedOut` carries the reason)
88
- *
89
- * @experimental
90
- */
91
- declare function runLocalHarness(options: RunLocalHarnessOptions): Promise<LocalHarnessResult>;
92
-
93
- export { type LocalHarness as L, type RunLocalHarnessOptions as R, type LocalHarnessResult as a, runLocalHarness as r };
@@ -1,112 +0,0 @@
1
- import { SandboxInstance } from '@tangle-network/sandbox';
2
- import { D as Driver, A as AgentRunSpec, O as OutputAdapter, V as Validator, E as ExecCtx, I as Iteration, L as LoopWinner, a as LoopLineageOptions, S as SandboxClient, b as LoopResult } from './types-Crxftafi.js';
3
-
4
- /**
5
- * @experimental
6
- *
7
- * `runLoop` — the topology-agnostic kernel built atop the sandbox SDK.
8
- *
9
- * Each iteration:
10
- * 1. `driver.plan(task, history)` → N tasks (1 = refine, N = fanout, 0 = stop)
11
- * 2. For each task (parallel, bounded by `maxConcurrency`):
12
- * a. round-robin an `AgentRunSpec` from `agentRuns`
13
- * b. `sandboxClient.create({ backend: { profile }, ...overrides })`
14
- * c. emit `loop.iteration.dispatch` with the placement
15
- * (`{ sibling, sandboxId }` or `{ fleet, fleetId, machineId, sandboxId }`)
16
- * d. iterate `box.streamPrompt(taskToPrompt(task))` and collect events
17
- * 3. `output.parse(events)` → typed `Output`
18
- * 4. `validator?.validate(output)` → `DefaultVerdict`
19
- * 5. Append `Iteration` to history; emit `loop.iteration.ended`
20
- * 6. `driver.decide(history)` → if terminal, return result + winner
21
- *
22
- * The kernel owns: iteration accounting, per-iteration timing, error
23
- * capture, abort propagation, concurrency cap, cost aggregation, and trace
24
- * emission. The kernel does NOT own: what the agent runs (sandbox SDK +
25
- * profile), how outputs are decoded (output adapter), how outputs are
26
- * scored (validator), or topology (driver).
27
- */
28
-
29
- /** @experimental */
30
- interface RunLoopOptions<Task, Output, Decision> {
31
- driver: Driver<Task, Output, Decision>;
32
- /**
33
- * Single agent spec — every iteration uses this profile. Mutually
34
- * exclusive with `agentRuns`.
35
- */
36
- agentRun?: AgentRunSpec<Task>;
37
- /**
38
- * Multiple specs for heterogeneous fanout. The kernel round-robins
39
- * through them when the driver plans N tasks. Mutually exclusive with
40
- * `agentRun`.
41
- */
42
- agentRuns?: AgentRunSpec<Task>[];
43
- output: OutputAdapter<Output>;
44
- validator?: Validator<Output>;
45
- task: Task;
46
- ctx: ExecCtx;
47
- /** Default 10. Hard cap on total iterations across all `plan()` rounds. */
48
- maxIterations?: number;
49
- /** Default 4. In-flight worker cap within a single `plan()` batch. */
50
- maxConcurrency?: number;
51
- /**
52
- * Pre-allocated id for trace correlation. Default = `loop-${random}`.
53
- * Surfaces as `runId` on every emitted `LoopTraceEvent`.
54
- */
55
- runId?: string;
56
- /**
57
- * Clock override; default `Date.now`. Deterministic tests pass a
58
- * monotonic counter to stabilize iteration timing fields.
59
- */
60
- now?: () => number;
61
- /**
62
- * Override the default winner selector (highest-valid-score, ties broken
63
- * by earliest iteration).
64
- */
65
- selectWinner?: (iterations: Iteration<Task, Output>[]) => LoopWinner<Task, Output> | undefined;
66
- /**
67
- * Same-sandbox driver mode — a kernel→caller out-channel, not a value handed
68
- * in. When set, the kernel keeps each finished worker box alive across the
69
- * `plan()` boundary and hands it here, so a same-sandbox planner
70
- * (one that reuses the worker's box) can stream its move INTO the
71
- * worker's live box — steering from the worker's real filesystem and state,
72
- * not just a history summary. The kernel owns teardown: every box kept alive
73
- * this way is destroyed at loop end (and the callback is invoked with
74
- * `undefined` then as a teardown sentinel). Without it, worker boxes are torn
75
- * down per-iteration (default) and a same-sandbox planner has nothing to
76
- * reuse. Intended for single-worker (refine) loops: under fanout every box is
77
- * still kept for teardown, but only the last-finishing box is handed here, so
78
- * a planner sees an arbitrary branch's filesystem — pair it with refine.
79
- */
80
- onWorkerBox?: (box: SandboxInstance | undefined) => void;
81
- /**
82
- * Opt-in box-lineage controls. Default OFF — unset means every iteration
83
- * acquires a fresh box, streams once, and tears it down (today's behavior,
84
- * byte-identical). With `sessionContinuity` on, a refine round continues the
85
- * parent iteration's session on its live box; with `forkFanout` on (and a
86
- * fork-capable platform), a fanout round forks the parent's checkpoint so the
87
- * branches share a context prefix. The lineage owns every box it starts or
88
- * forks and tears them all down at loop end — so these paths are mutually
89
- * exclusive with `onWorkerBox`, which claims the same box-ownership channel.
90
- * @experimental
91
- */
92
- lineage?: LoopLineageOptions;
93
- }
94
- /** @experimental */
95
- declare function runLoop<Task, Output, Decision>(options: RunLoopOptions<Task, Output, Decision>): Promise<LoopResult<Task, Output, Decision>>;
96
- /**
97
- * Instantiate a sandbox for an `AgentRunSpec`: sets `backend.profile` to the
98
- * spec's profile (inferring the backend type when the spec doesn't override
99
- * it) and merges `sandboxOverrides`. Shared by the loop kernel and the
100
- * `AgentRuntime.act` sandbox bridge so both boot the sandbox identically.
101
- */
102
- declare function createSandboxForSpec<Task>(client: SandboxClient, spec: AgentRunSpec<Task>, signal: AbortSignal): Promise<SandboxInstance>;
103
- /**
104
- * The kernel's winner argmax — best-valid-score, ties broken by earliest index,
105
- * falling back to the best-scoring non-errored output when none is valid. Exported
106
- * so the `runProgram` tree executor selects across merged sub-loop iterations with
107
- * the SAME semantics the kernel uses at a single loop's finalize (one selector, not
108
- * a forked copy).
109
- */
110
- declare function defaultSelectWinner<Task, Output>(iterations: Iteration<Task, Output>[]): LoopWinner<Task, Output> | undefined;
111
-
112
- export { type RunLoopOptions as R, createSandboxForSpec as c, defaultSelectWinner as d, runLoop as r };