@tangle-network/agent-runtime 0.109.1 → 0.110.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/dist/{activation-CM-L6TtL.js → activation-CsuHCZVN.js} +3 -3
  2. package/dist/{activation-CM-L6TtL.js.map → activation-CsuHCZVN.js.map} +1 -1
  3. package/dist/agent.d.ts +4 -4
  4. package/dist/agent.js +2 -2
  5. package/dist/agent.js.map +1 -1
  6. package/dist/{analyst-loop-C8cGThTW.js → analyst-loop-BoNIG2hA.js} +30 -9
  7. package/dist/analyst-loop-BoNIG2hA.js.map +1 -0
  8. package/dist/analyst-loop.d.ts +1 -1
  9. package/dist/analyst-loop.js +1 -1
  10. package/dist/candidate-execution/index.js +4 -4
  11. package/dist/{candidate-execution-nYMa-bc-.js → candidate-execution-Co3sRC_7.js} +4 -4
  12. package/dist/{candidate-execution-nYMa-bc-.js.map → candidate-execution-Co3sRC_7.js.map} +1 -1
  13. package/dist/{environment-provider-CfLUmKmf.js → environment-provider-BsHpW4Dp.js} +52 -5
  14. package/dist/environment-provider-BsHpW4Dp.js.map +1 -0
  15. package/dist/{environment-provider-CMqSAp-O.d.ts → environment-provider-CTEMEP9u.d.ts} +9 -1
  16. package/dist/environment-provider.d.ts +1 -1
  17. package/dist/environment-provider.js +1 -1
  18. package/dist/{improvement-adapter-BaAdfJKT.d.ts → improvement-adapter-D5gwwoXQ.d.ts} +2 -2
  19. package/dist/{improvement-cycle-9O4iVFOA.js → improvement-cycle-ryAyCLKN.js} +5 -5
  20. package/dist/{improvement-cycle-9O4iVFOA.js.map → improvement-cycle-ryAyCLKN.js.map} +1 -1
  21. package/dist/{index-Cn5TtHUG.d.ts → index-C-Zn0VrN.d.ts} +3 -3
  22. package/dist/{index-bXiMVrUv.d.ts → index-D_OdNLe0.d.ts} +290 -96
  23. package/dist/{index-Bur6uUF4.d.ts → index-WODlt7iz.d.ts} +6 -6
  24. package/dist/index.d.ts +5 -5
  25. package/dist/index.js +11 -11
  26. package/dist/intelligence.d.ts +2 -2
  27. package/dist/intelligence.js +39 -9
  28. package/dist/intelligence.js.map +1 -1
  29. package/dist/kernel.d.ts +3 -3
  30. package/dist/kernel.js +7 -7
  31. package/dist/{knowledge-1a38bcUT.js → knowledge-DBNAteaC.js} +5 -5
  32. package/dist/{knowledge-1a38bcUT.js.map → knowledge-DBNAteaC.js.map} +1 -1
  33. package/dist/knowledge.d.ts +1 -1
  34. package/dist/knowledge.js +1 -1
  35. package/dist/{loop-runner-bin-CSzrWlgE.d.ts → loop-runner-bin-BUm83y1g.d.ts} +4 -4
  36. package/dist/{loop-runner-bin-V4EN9aNT.js → loop-runner-bin-zE7DyGop.js} +4 -4
  37. package/dist/{loop-runner-bin-V4EN9aNT.js.map → loop-runner-bin-zE7DyGop.js.map} +1 -1
  38. package/dist/loop-runner-bin.d.ts +1 -1
  39. package/dist/loop-runner-bin.js +1 -1
  40. package/dist/mcp/bin.js +1 -1
  41. package/dist/mcp/index.d.ts +1 -1
  42. package/dist/mcp/index.js +5 -5
  43. package/dist/{openai-tools-DT9FH2_t.js → openai-tools-st-hERvA.js} +2 -2
  44. package/dist/{openai-tools-DT9FH2_t.js.map → openai-tools-st-hERvA.js.map} +1 -1
  45. package/dist/{prepare-Pr19X93k.js → prepare-BKVdOn0w.js} +15 -14
  46. package/dist/prepare-BKVdOn0w.js.map +1 -0
  47. package/dist/primeintellect/index.d.ts +1 -1
  48. package/dist/{protected-model-port-uthtDNqu.js → protected-model-port-BtldAE9j.js} +2 -2
  49. package/dist/{protected-model-port-uthtDNqu.js.map → protected-model-port-BtldAE9j.js.map} +1 -1
  50. package/dist/{runtime-BVMyqgct.js → runtime-DSkMJb_X.js} +415 -27
  51. package/dist/runtime-DSkMJb_X.js.map +1 -0
  52. package/dist/{spawn-journal-CwPvKUTa.js → spawn-journal-DLhnom3e.js} +2 -2
  53. package/dist/{spawn-journal-CwPvKUTa.js.map → spawn-journal-DLhnom3e.js.map} +1 -1
  54. package/dist/{structural-rollout-ASQLr4-v.js → structural-rollout-CgnNy7_4.js} +3 -3
  55. package/dist/{structural-rollout-ASQLr4-v.js.map → structural-rollout-CgnNy7_4.js.map} +1 -1
  56. package/dist/{supervise-DyPmmhJ6.js → supervise-CeZtA1wu.js} +223 -107
  57. package/dist/supervise-CeZtA1wu.js.map +1 -0
  58. package/dist/{supervisor-sTJC9psT.js → supervisor-ByCPHcp9.js} +82 -24
  59. package/dist/supervisor-ByCPHcp9.js.map +1 -0
  60. package/dist/testing.js +9 -9
  61. package/dist/{types-CfGKhIuj.d.ts → types-zWfqDjeL.d.ts} +10 -1
  62. package/dist/{util-MVgdwuIS.js → util-Cc9g9Y-o.js} +2 -2
  63. package/dist/{util-MVgdwuIS.js.map → util-Cc9g9Y-o.js.map} +1 -1
  64. package/dist/{workspace-archive-C9w_rxt6.js → workspace-archive-CYYxZyA7.js} +2 -2
  65. package/dist/{workspace-archive-C9w_rxt6.js.map → workspace-archive-CYYxZyA7.js.map} +1 -1
  66. package/package.json +7 -7
  67. package/dist/analyst-loop-C8cGThTW.js.map +0 -1
  68. package/dist/environment-provider-CfLUmKmf.js.map +0 -1
  69. package/dist/prepare-Pr19X93k.js.map +0 -1
  70. package/dist/runtime-BVMyqgct.js.map +0 -1
  71. package/dist/supervise-DyPmmhJ6.js.map +0 -1
  72. package/dist/supervisor-sTJC9psT.js.map +0 -1
@@ -1,20 +1,21 @@
1
1
  import { n as AnalystError, r as BackendTransportError, s as PlannerError, u as ValidationError } from "./errors-DEAvWQPy.js";
2
2
  import { i as normalizeBackendStreamEvent, o as newRuntimeSession, s as nowIso } from "./backends-CiOCyRHb.js";
3
- import { a as randomSuffix, c as stringifySafe, f as zeroTokenUsage, r as isAbortError, s as sleep, t as addTokenUsage } from "./util-MVgdwuIS.js";
4
- import { i as InMemorySpawnJournal, r as InMemoryResultBlobStore } from "./spawn-journal-CwPvKUTa.js";
3
+ import { c as sleep, i as isAbortError, l as stringifySafe, n as addTokenUsage, o as randomSuffix, p as zeroTokenUsage } from "./util-Cc9g9Y-o.js";
4
+ import { i as InMemorySpawnJournal, r as InMemoryResultBlobStore } from "./spawn-journal-DLhnom3e.js";
5
5
  import { i as redactProtectedValue, r as redactProtectedReason } from "./protected-redaction--F3v1oo8.js";
6
- import { C as routerChatWithUsage, T as runBrainLoop, d as settledToIteration, l as withDriverExecutor, t as createSupervisor, x as routerBrain } from "./supervisor-sTJC9psT.js";
7
- import { C as observe, O as strategyAuthorMethod, b as sample, v as refine, x as sampleThenRefine, y as runAgentic } from "./structural-rollout-ASQLr4-v.js";
6
+ import { C as routerChatWithUsage, T as runBrainLoop, d as settledToIteration, l as withDriverExecutor, t as createSupervisor, x as routerBrain } from "./supervisor-ByCPHcp9.js";
7
+ import { C as observe, O as strategyAuthorMethod, b as sample, v as refine, x as sampleThenRefine, y as runAgentic } from "./structural-rollout-CgnNy7_4.js";
8
8
  import { i as notifyRuntimeHookEvent } from "./runtime-hooks-C7iJOWm3.js";
9
9
  import { a as notifySandboxEventObserver, i as mapSandboxToolEvent, r as mapSandboxEvent, t as createSandboxToolPartState } from "./sandbox-events-DeI5xX8P.js";
10
- import { Bt as runAgentRounds, Dt as createExecutorRegistry, Et as createExecutor, Ht as createSandboxLineage, Ot as createWorktreeCliExecutor, Ut as probeSandboxCapabilities, bt as rollingDispatch, qt as gateOnDeliverable, t as supervise, zt as defaultSelectWinner } from "./supervise-DyPmmhJ6.js";
10
+ import { Bt as runAgentRounds, Dt as createExecutorRegistry, Et as createExecutor, Ht as createSandboxLineage, Ot as createWorktreeCliExecutor, Ut as probeSandboxCapabilities, bt as rollingDispatch, qt as gateOnDeliverable, t as supervise, zt as defaultSelectWinner } from "./supervise-CeZtA1wu.js";
11
11
  import { CODING_HARNESSES, InMemoryTraceStore, benjaminiHochberg, buildTrajectory, computeFindingId as computeFindingId$1, confidenceInterval, expandProfileAxes, harnessAxisOf, makeFinding as makeFinding$1, pairedBootstrap, paretoFrontier, scoreKnowledgeReadiness, wilcoxonSignedRank, wilson } from "@tangle-network/agent-eval";
12
12
  import { heldoutSignificance, runProfileMatrix } from "@tangle-network/agent-eval/campaign";
13
13
  import { canonicalCandidateDigest, validateAgentProfileSecurity } from "@tangle-network/agent-interface";
14
+ import { randomUUID } from "node:crypto";
14
15
  import { mkdir, readFile, writeFile } from "node:fs/promises";
15
- import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
16
- import { dirname, join } from "node:path";
17
- import { execFileSync, spawn } from "node:child_process";
16
+ import { appendFileSync, chmodSync, constants, copyFileSync, existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, readlinkSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
17
+ import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
18
+ import { execFileSync, spawn, spawnSync } from "node:child_process";
18
19
  import { tmpdir } from "node:os";
19
20
  import { createInterface } from "node:readline";
20
21
  import { collectAgentResponseText } from "@tangle-network/sandbox";
@@ -62,6 +63,52 @@ async function resolveSecretEnv(secretEnv, keys, label) {
62
63
  }
63
64
  return resolved;
64
65
  }
66
+ /** Apply a secret-ref's declared decoration to its resolved raw value. */
67
+ function formatSecretValue(value, format) {
68
+ return format === "bearer" ? `Bearer ${value}` : value;
69
+ }
70
+ /**
71
+ * Resolve a profile MCP server's `args`/`env` config values (interface ≥0.40
72
+ * `AgentProfileConfigValue`) plus the legacy `metadata.secretEnv` channel into
73
+ * the plain strings a spawn needs.
74
+ *
75
+ * Rules, all fail-closed:
76
+ * - `args` must be public values. A secret-ref in argv is refused: argv is
77
+ * readable by every host process (/proc/PID/cmdline) and outside the
78
+ * protected-value redaction channel, so a secret there cannot be contained.
79
+ * - `env` secret-refs resolve through the KeyProvider (missing provider or key
80
+ * throws, naming the KEY NAME only) and land in `protectedEnv`.
81
+ * - An env var declared secret on BOTH channels (env secret-ref and
82
+ * metadata.secretEnv) is ambiguous configuration and throws.
83
+ * - A public `env` entry shadowed by a legacy metadata secret keeps the
84
+ * pre-0.40 spawn precedence: the secret value wins in the child env.
85
+ */
86
+ async function resolveMcpServerLaunch(server, keys, label) {
87
+ const args = server.args?.map((value, index) => {
88
+ if (value.kind !== "public") throw new ValidationError(`${label}.args[${index}] is a secret-ref ('${value.key}') — argv is readable by every host process and exempt from redaction; declare the secret in env instead`);
89
+ return value.value;
90
+ });
91
+ const publicEnv = {};
92
+ const envSecretRefs = {};
93
+ const envSecretFormats = {};
94
+ for (const [envName, value] of Object.entries(server.env ?? {})) if (value.kind === "public") publicEnv[envName] = value.value;
95
+ else {
96
+ envSecretRefs[envName] = value.key;
97
+ envSecretFormats[envName] = value.format;
98
+ }
99
+ const legacySecretEnv = secretEnvOfMcpServer(server);
100
+ for (const envName of Object.keys(legacySecretEnv ?? {})) if (envName in envSecretRefs) throw new ValidationError(`${label}: env ${envName} is declared secret twice — once as an env secret-ref and once in metadata.${mcpSecretEnvMetadataKey}; keep exactly one declaration`);
101
+ const resolvedRefs = await resolveSecretEnv(envSecretRefs, keys, label);
102
+ const protectedEnv = {
103
+ ...legacySecretEnv ? await resolveSecretEnv(legacySecretEnv, keys, label) : {},
104
+ ...Object.fromEntries(Object.entries(resolvedRefs).map(([envName, raw]) => [envName, formatSecretValue(raw, envSecretFormats[envName])]))
105
+ };
106
+ return {
107
+ ...args ? { args } : {},
108
+ ...server.env ? { env: publicEnv } : {},
109
+ ...Object.keys(protectedEnv).length > 0 ? { protectedEnv } : {}
110
+ };
111
+ }
65
112
  //#endregion
66
113
  //#region src/runtime/mcp-environment.ts
67
114
  /** POST JSON-RPC and parse a JSON body OR the last `data:` line of an SSE stream.
@@ -385,14 +432,13 @@ async function materializeLocalMcp(profile, opts = {}) {
385
432
  const transport = server.transport ?? "stdio";
386
433
  if (transport !== "stdio") throw new ValidationError(`materializeLocalMcp: profile.mcp['${key}'] has transport '${transport}' — the same-host client only spawns stdio servers; a remote (http/sse) server needs an http MCP client (not yet built here) or the sandbox backend. Failing loud: scoring this profile without its declared server would fake the with/without ablation`);
387
434
  if (!server.command || server.command.trim().length === 0) throw new ValidationError(`materializeLocalMcp: profile.mcp['${key}'] declares a stdio server with no command`);
388
- const secretRefs = secretEnvOfMcpServer(server);
389
- const provisioned = secretRefs ? await resolveSecretEnv(secretRefs, opts.keys, `materializeLocalMcp: profile.mcp['${key}']`) : void 0;
435
+ const launch = await resolveMcpServerLaunch(server, opts.keys, `materializeLocalMcp: profile.mcp['${key}']`);
390
436
  const conn = await connectStdioMcp({
391
437
  command: server.command,
392
- ...server.args ? { args: server.args } : {},
438
+ ...launch.args ? { args: launch.args } : {},
393
439
  ...server.cwd ? { cwd: server.cwd } : {},
394
- ...server.env ? { env: server.env } : {},
395
- ...provisioned ? { protectedEnv: provisioned } : {},
440
+ ...launch.env ? { env: launch.env } : {},
441
+ ...launch.protectedEnv ? { protectedEnv: launch.protectedEnv } : {},
396
442
  ...opts.timeoutMs !== void 0 ? { timeoutMs: opts.timeoutMs } : {}
397
443
  });
398
444
  connections.push(conn);
@@ -3096,13 +3142,12 @@ function requireSpend(rolled, id, root) {
3096
3142
  /**
3097
3143
  * promotionGate — the statistical promotion decision over a holdout benchmark: does the
3098
3144
  * candidate strategy beat the incumbent on held-out tasks by a margin the task noise
3099
- * cannot fake? The statistics are the substrate's (`heldoutSignificance`): a SEEDED
3100
- * paired bootstrap over per-task (candidate incumbent) deltas deterministic verdict,
3101
- * a minimum-evidence floor, and the CI lower bound must clear `deltaThreshold`. A raw
3102
- * h1>h0 point comparison on m≈8 holdout tasks certifies false champions at near
3103
- * coin-flip rates; this gate is the instrument-grade replacement.
3145
+ * cannot fake? The statistics come from `heldoutSignificance`, which chooses the
3146
+ * decision interval that matches the outcome shape, applies a minimum-evidence floor,
3147
+ * and requires the interval's lower bound to clear `deltaThreshold`. A raw h1>h0 point
3148
+ * comparison on m≈8 holdout tasks certifies false champions at near coin-flip rates.
3104
3149
  */
3105
- /** Statistical promotion decision over a holdout benchmark: a seeded paired bootstrap (`heldoutSignificance`) whose CI lower bound must clear `deltaThreshold`. */
3150
+ /** Statistical promotion decision over a holdout benchmark using the outcome-appropriate interval selected by `heldoutSignificance`. */
3106
3151
  function promotionGate(opts) {
3107
3152
  const mode = opts.mode ?? "superiority";
3108
3153
  if (opts.candidate === opts.incumbent) return {
@@ -3151,8 +3196,8 @@ function promotionGate(opts) {
3151
3196
  const lift = {
3152
3197
  mean: sig.bootstrap.mean,
3153
3198
  median: sig.bootstrap.median,
3154
- low: sig.bootstrap.low,
3155
- high: sig.bootstrap.high
3199
+ low: sig.decision.low,
3200
+ high: sig.decision.high
3156
3201
  };
3157
3202
  const latSig = heldoutSignificance({
3158
3203
  before: incMs,
@@ -3168,8 +3213,8 @@ function promotionGate(opts) {
3168
3213
  const latency = {
3169
3214
  mean: latSig.bootstrap.mean,
3170
3215
  median: latSig.bootstrap.median,
3171
- low: latSig.bootstrap.low,
3172
- high: latSig.bootstrap.high
3216
+ low: latSig.decision.low,
3217
+ high: latSig.decision.high
3173
3218
  };
3174
3219
  if (mode === "superiority") {
3175
3220
  if (sig.fewRuns) return {
@@ -3222,8 +3267,8 @@ function promotionGate(opts) {
3222
3267
  const costSavings = {
3223
3268
  mean: costSig.bootstrap.mean,
3224
3269
  median: costSig.bootstrap.median,
3225
- low: costSig.bootstrap.low,
3226
- high: costSig.bootstrap.high
3270
+ low: costSig.decision.low,
3271
+ high: costSig.decision.high
3227
3272
  };
3228
3273
  if (scoreSig.fewRuns) return {
3229
3274
  promoted: false,
@@ -4727,6 +4772,123 @@ function signalPass(value, required) {
4727
4772
  return !required;
4728
4773
  }
4729
4774
  //#endregion
4775
+ //#region src/runtime/supervise/run-layout.ts
4776
+ /**
4777
+ * The on-disk supervisor-run layout: `<root>/.loops/supervisor/<id>`.
4778
+ *
4779
+ * This is the durable, cross-process face of a supervisor run — the counterpart to the in-process
4780
+ * `Inbox` seam in `./inbox`. A run persists its state under one directory so that any OTHER process
4781
+ * can find it after the fact: `@tangle-network/traces` reads exactly this layout
4782
+ * (`traces analyze --supervisor-run-dir` expects `<runDir>/ws/.loops/supervisor/<id>`), a restarted
4783
+ * host can rehydrate a run it no longer holds handles to, and a human can steer a live worker by
4784
+ * appending one NDJSON line. Until now the layout was defined only in the unpublished `loops` repo
4785
+ * (`src/supervisor-control.ts`) — a published reader depending on an unpublished writer's
4786
+ * convention — so the contract is promoted here, names preserved.
4787
+ *
4788
+ * Layout, relative to `supervisorRunDir(root, id)`:
4789
+ *
4790
+ * workers/<label>.inbox.ndjson down-leg steer/answer requests for one worker (durable inbox);
4791
+ * each line is a {@link WorkerSteerRequest}
4792
+ * workers/<label>.ndjson best-effort per-worker control-event log (delivery bookkeeping)
4793
+ *
4794
+ * Reads are tolerant by contract: a partial trailing line (a writer mid-append) or a corrupt line
4795
+ * never poisons the rest of the file — later valid lines still matter.
4796
+ *
4797
+ * Promoted from `loops/src/supervisor-control.ts`. The one deliberate difference: the loops version
4798
+ * resolved a worker id to its label through the run journal before writing a steer; that resolution
4799
+ * stays with the caller (it is journal-format-specific), so `writeWorkerSteer` here takes the worker
4800
+ * LABEL directly.
4801
+ *
4802
+ * @experimental
4803
+ */
4804
+ /** The run directory every artifact of one supervisor run lives under. */
4805
+ function supervisorRunDir(rootDir, id) {
4806
+ return join(resolve(rootDir), ".loops", "supervisor", id);
4807
+ }
4808
+ /** A worker label reduced to a safe filename stem. Empty labels get a stable fallback. */
4809
+ function safeWorkerFile(label) {
4810
+ const safe = label.replace(/[^A-Za-z0-9._-]/g, "_");
4811
+ return safe.length > 0 ? safe : "worker";
4812
+ }
4813
+ /** The durable inbox file for one worker of one run. */
4814
+ function workerInboxFile(rootDir, supervisorId, worker) {
4815
+ return workerInboxFileFromEventDir(supervisorRunDir(rootDir, supervisorId), worker);
4816
+ }
4817
+ /** Same, addressed from an already-known run directory (the reader's usual entry point). */
4818
+ function workerInboxFileFromEventDir(eventDir, worker) {
4819
+ return join(eventDir, "workers", `${safeWorkerFile(worker)}.inbox.ndjson`);
4820
+ }
4821
+ /**
4822
+ * Durably append one steer request to a worker's inbox and log the delivery attempt.
4823
+ *
4824
+ * The inbox append is the durable act; the control-event log is best-effort bookkeeping and may
4825
+ * silently fail without voiding the steer.
4826
+ */
4827
+ function writeWorkerSteer(rootDir, supervisorId, worker, message, source = "human") {
4828
+ const trimmed = message.trim();
4829
+ if (!trimmed) throw new Error("steer message is empty");
4830
+ const dir = supervisorRunDir(rootDir, supervisorId);
4831
+ mkdirSync(join(dir, "workers"), { recursive: true });
4832
+ const request = {
4833
+ id: randomUUID(),
4834
+ at: (/* @__PURE__ */ new Date()).toISOString(),
4835
+ source,
4836
+ worker,
4837
+ message: trimmed
4838
+ };
4839
+ const file = workerInboxFile(rootDir, supervisorId, worker);
4840
+ appendFileSync(file, `${JSON.stringify(request)}\n`, "utf8");
4841
+ appendWorkerControlEvent(dir, worker, {
4842
+ kind: "message",
4843
+ direction: "down",
4844
+ source,
4845
+ requestId: request.id,
4846
+ message: trimmed,
4847
+ queued: true,
4848
+ delivered: false
4849
+ });
4850
+ return {
4851
+ worker,
4852
+ file,
4853
+ request
4854
+ };
4855
+ }
4856
+ /** Read every valid steer request in a worker's inbox. Corrupt or partial lines are skipped. */
4857
+ function readWorkerSteerRequests(eventDir, worker) {
4858
+ const file = workerInboxFileFromEventDir(eventDir, worker);
4859
+ if (!existsSync(file)) return [];
4860
+ const out = [];
4861
+ let raw = "";
4862
+ try {
4863
+ raw = readFileSync(file, "utf8");
4864
+ } catch {
4865
+ return out;
4866
+ }
4867
+ for (const line of raw.split("\n")) {
4868
+ const trimmed = line.trim();
4869
+ if (!trimmed) continue;
4870
+ try {
4871
+ const parsed = JSON.parse(trimmed);
4872
+ if (isWorkerSteerRequest(parsed)) out.push(parsed);
4873
+ } catch {}
4874
+ }
4875
+ return out;
4876
+ }
4877
+ function appendWorkerControlEvent(eventDir, label, event) {
4878
+ try {
4879
+ const workersDir = join(eventDir, "workers");
4880
+ mkdirSync(workersDir, { recursive: true });
4881
+ appendFileSync(join(workersDir, `${safeWorkerFile(label)}.ndjson`), `${JSON.stringify({
4882
+ at: (/* @__PURE__ */ new Date()).toISOString(),
4883
+ label,
4884
+ ...event
4885
+ })}\n`, "utf8");
4886
+ } catch {}
4887
+ }
4888
+ function isWorkerSteerRequest(value) {
4889
+ return typeof value.id === "string" && typeof value.at === "string" && typeof value.source === "string" && typeof value.worker === "string" && typeof value.message === "string" && value.message.trim().length > 0;
4890
+ }
4891
+ //#endregion
4730
4892
  //#region src/runtime/supervise/trajectory-recorder.ts
4731
4893
  /**
4732
4894
  *
@@ -4789,6 +4951,232 @@ async function analyzeTrace(source, runId = "worker") {
4789
4951
  };
4790
4952
  }
4791
4953
  //#endregion
4954
+ //#region src/runtime/supervise/untracked-clone.ts
4955
+ /**
4956
+ * Worker-clone preparation: make each worker's fresh clone a FAITHFUL copy of the
4957
+ * shared workspace's working tree, not just of its git history.
4958
+ *
4959
+ * `runInWorkspace` materializes a worker dir via `git clone`, which carries only
4960
+ * COMMITTED files. Real workspaces (SWE-bench instance images: astropy,
4961
+ * matplotlib) hold compiled extension modules (.so/.pyd) as UNTRACKED build
4962
+ * artifacts — inside a bare clone `import astropy` dies with "cannot import name
4963
+ * '_compiler'" before the worker's first edit, so its verify gate is physically
4964
+ * unpassable regardless of patch quality (observed: 7/7 astropy and 6/6
4965
+ * matplotlib workers failed exactly this way while the shared workspace verified
4966
+ * fine). The fix copies the source tree's untracked files — including git-ignored
4967
+ * build outputs — into the clone right after materialize and before the worker
4968
+ * starts.
4969
+ *
4970
+ * Isolation is preserved: artifacts are COPIED (copy-on-write via FICLONE where
4971
+ * the filesystem supports it — never hardlinked, a worker rebuild opening an
4972
+ * artifact with O_TRUNC on a shared inode would corrupt the source workspace for
4973
+ * every sibling), and an absolute symlink pointing inside the source tree is
4974
+ * rewritten to the clone-local path so no worker holds a live handle back into
4975
+ * shared mutable state.
4976
+ *
4977
+ * Fidelity stops at git history: every copied path is appended to the clone's
4978
+ * `.git/info/exclude`, so the clone-side `git add -A` (both the local delegate's
4979
+ * diff capture and `gitWorkspace.commit`) can never stage pre-existing build
4980
+ * artifacts into the shared ref — in the source they are untracked, and a
4981
+ * delivery must not silently start tracking them.
4982
+ *
4983
+ * Promoted verbatim from `loops/src/worker-clone.ts` (see agent-dev-container#4519): any harness
4984
+ * that materializes workers via `git clone` needs the working tree, not just the history.
4985
+ *
4986
+ * @experimental
4987
+ */
4988
+ /** Loop-infra dirs living inside a workspace; orchestration state, never build inputs. */
4989
+ const SKIPPED_TOP_LEVEL = /* @__PURE__ */ new Set([
4990
+ ".loops",
4991
+ ".evolve",
4992
+ ".agent-worktrees",
4993
+ ".claude"
4994
+ ]);
4995
+ /** Warn (and copy anyway) past this untracked payload size. */
4996
+ const DEFAULT_WARN_BYTES = 2 * 1024 * 1024 * 1024;
4997
+ /**
4998
+ * Copy every untracked file of `sourceDir`'s working tree — including git-ignored
4999
+ * build outputs (`git ls-files --others` with NO exclude flags lists both) — into
5000
+ * `cloneDir`, then shield the copied paths from the clone's `git add -A` via
5001
+ * `.git/info/exclude`. Nested git repos (listed as bare `dir/` entries), any path
5002
+ * containing a `.git` segment, and loop-infra dirs are skipped.
5003
+ */
5004
+ function copyUntrackedIntoClone(sourceDir, cloneDir, opts = {}) {
5005
+ const warnBytes = opts.warnBytes ?? DEFAULT_WARN_BYTES;
5006
+ const log = opts.log ?? ((message) => console.warn(message));
5007
+ const src = resolve(sourceDir);
5008
+ const dst = resolve(cloneDir);
5009
+ const ls = spawnSync("git", [
5010
+ "-C",
5011
+ src,
5012
+ "ls-files",
5013
+ "--others",
5014
+ "-z"
5015
+ ], {
5016
+ encoding: "utf8",
5017
+ maxBuffer: 256 * 1024 * 1024
5018
+ });
5019
+ if (ls.status !== 0) throw new Error(`git ls-files --others failed in ${src}: ${(ls.stderr ?? "").trim() || `exit ${ls.status}`}`);
5020
+ const plan = [];
5021
+ for (const rel of (ls.stdout ?? "").split("\0")) {
5022
+ if (!rel || rel.endsWith("/")) continue;
5023
+ const segments = rel.split("/");
5024
+ if (segments.includes(".git")) continue;
5025
+ if (SKIPPED_TOP_LEVEL.has(segments[0] ?? "")) continue;
5026
+ let stat;
5027
+ try {
5028
+ stat = lstatSync(join(src, rel));
5029
+ } catch {
5030
+ continue;
5031
+ }
5032
+ if (stat.isSymbolicLink()) plan.push({
5033
+ rel,
5034
+ kind: "symlink",
5035
+ size: 0,
5036
+ mode: stat.mode
5037
+ });
5038
+ else if (stat.isFile()) plan.push({
5039
+ rel,
5040
+ kind: "file",
5041
+ size: stat.size,
5042
+ mode: stat.mode
5043
+ });
5044
+ }
5045
+ const bytes = plan.reduce((sum, entry) => sum + entry.size, 0);
5046
+ if (bytes > warnBytes) log(`worker clone: untracked payload in ${src} is ${(bytes / 1024 / 1024).toFixed(0)}MB (> ${(warnBytes / 1024 / 1024).toFixed(0)}MB) — copying anyway so the clone stays runnable`);
5047
+ let copied = 0;
5048
+ const excludeLines = [];
5049
+ for (const entry of plan) {
5050
+ const from = join(src, entry.rel);
5051
+ const to = join(dst, entry.rel);
5052
+ try {
5053
+ mkdirSync(dirname(to), { recursive: true });
5054
+ if (entry.kind === "symlink") {
5055
+ let target = readlinkSync(from);
5056
+ if (isAbsolute(target)) {
5057
+ const resolved = resolve(target);
5058
+ if (resolved === src || resolved.startsWith(src + sep)) target = join(dst, relative(src, resolved));
5059
+ }
5060
+ rmSync(to, { force: true });
5061
+ symlinkSync(target, to);
5062
+ } else {
5063
+ copyFileSync(from, to, constants.COPYFILE_FICLONE);
5064
+ chmodSync(to, entry.mode & 4095);
5065
+ }
5066
+ copied += 1;
5067
+ excludeLines.push(toExcludePattern(entry.rel));
5068
+ } catch (err) {
5069
+ log(`worker clone: failed to copy untracked ${entry.rel}: ${err instanceof Error ? err.message : String(err)}`);
5070
+ }
5071
+ }
5072
+ if (excludeLines.length > 0) {
5073
+ const infoDir = join(dst, ".git", "info");
5074
+ mkdirSync(infoDir, { recursive: true });
5075
+ appendFileSync(join(infoDir, "exclude"), `# untracked artifacts copied from the shared workspace — never commit them back\n${excludeLines.join("\n")}\n`, "utf8");
5076
+ }
5077
+ return {
5078
+ copied,
5079
+ bytes
5080
+ };
5081
+ }
5082
+ /** Root-anchored literal exclude pattern: glob metachars and trailing spaces escaped. */
5083
+ function toExcludePattern(rel) {
5084
+ return `/${rel.replace(/([\\*?[\]])/g, "\\$1").replace(/ +$/, (spaces) => "\\ ".repeat(spaces.length))}`;
5085
+ }
5086
+ /**
5087
+ * Wrap a `Workspace` so every `materialize` (the per-worker `git clone` inside
5088
+ * `runInWorkspace`) is followed by the untracked-artifact copy above — the clone
5089
+ * the worker starts in matches the source WORKING TREE, not just its history.
5090
+ * `commit`/`head` pass through untouched, so delivery semantics are unchanged.
5091
+ */
5092
+ function withUntrackedArtifacts(ws, sourceDir, log) {
5093
+ return {
5094
+ ref: ws.ref,
5095
+ materialize: async (dir) => {
5096
+ await ws.materialize(dir);
5097
+ copyUntrackedIntoClone(sourceDir, dir, log ? { log } : {});
5098
+ },
5099
+ commit: (dir, message) => ws.commit(dir, message),
5100
+ head: () => ws.head()
5101
+ };
5102
+ }
5103
+ //#endregion
5104
+ //#region src/runtime/supervise/worker-evidence.ts
5105
+ /**
5106
+ * Evidence-rich worker settlement.
5107
+ *
5108
+ * The supervisor BRAIN decides respawn/steer/stop from what a settled worker
5109
+ * shows it. A bare `finished passed=false patchBytes=6138` starves that
5110
+ * decision: the brain cannot quote the failing assertion, so its next worker
5111
+ * goal is authored blind. This module composes the bounded evidence block a
5112
+ * settling worker appends to its event stream and — on failure — returns as
5113
+ * its output artifact, so `observe_agent` hands the brain the failing verify
5114
+ * tail, a diff summary, and the worker's final note instead of counters.
5115
+ */
5116
+ /** Hard cap on one worker's evidence block so the brain's context cannot blow up. */
5117
+ const EVIDENCE_MAX_CHARS = 3e3;
5118
+ /** Tail of the verify output — the failing assertion lives at the END of a test log. */
5119
+ const VERIFY_TAIL_CHARS = 1200;
5120
+ const PATCH_HEAD_LINES = 40;
5121
+ const PATCH_LINE_MAX_CHARS = 200;
5122
+ /** Cap on the worker's closing note inside the evidence block. */
5123
+ const NOTE_MAX_CHARS = 300;
5124
+ /**
5125
+ * Compose the settle evidence block. Section order is priority order under the
5126
+ * hard cap: the verify tail (what failed) survives before the diff head (what
5127
+ * was tried) and the worker note — a truncated diff is recoverable from the
5128
+ * persisted patch file, a truncated failing assertion is not recoverable at all.
5129
+ */
5130
+ function composeWorkerEvidence(input) {
5131
+ const sections = [];
5132
+ const failures = [...input.testPassed ? [] : ["tests failed"], ...input.typecheckPassed ? [] : ["typecheck failed"]];
5133
+ sections.push(input.passed ? "verify PASSED" : `verify FAILED (${failures.join(", ") || "gate not passed"})`);
5134
+ const testTail = input.testOutput.trim().slice(-1200);
5135
+ if (testTail) sections.push(`--- verify output (tail) ---\n${testTail}`);
5136
+ if (!input.typecheckPassed) {
5137
+ const typecheckTail = input.typecheckOutput.trim().slice(-400);
5138
+ if (typecheckTail) sections.push(`--- typecheck output (tail) ---\n${typecheckTail}`);
5139
+ }
5140
+ sections.push(diffSummary(input.patch));
5141
+ const note = input.reviewerNotes?.trim();
5142
+ if (note) sections.push(`--- worker note ---\n${note.slice(0, 300)}`);
5143
+ return sections.join("\n").slice(0, EVIDENCE_MAX_CHARS);
5144
+ }
5145
+ /**
5146
+ * What a settled worker exposes as its output artifact (the blob the brain's
5147
+ * `observe_agent` reads). A passing worker's output is its patch — the
5148
+ * deliverable. A failing worker's output is its evidence block. A passing
5149
+ * worker with NO edits — the post-delivery read-only reviewer: the workspace
5150
+ * already holds a delivered fix, so the gate stays green under an empty diff —
5151
+ * would otherwise settle with an EMPTY output and its review would be lost, so
5152
+ * it exposes its evidence block instead (the worker note carries the review).
5153
+ */
5154
+ function settledWorkerOut(input) {
5155
+ if (input.evidence.length === 0) return input.patch;
5156
+ if (!input.passed) return input.evidence;
5157
+ return input.patch.trim().length > 0 ? input.patch : input.evidence;
5158
+ }
5159
+ /**
5160
+ * The worker's closing commentary off a local harness run: the TAIL of its
5161
+ * stdout (falling back to stderr), bounded to the note cap so a reviewer's
5162
+ * final verdict line — written last — survives into the evidence block
5163
+ * (`composeWorkerEvidence` keeps the note's FIRST `NOTE_MAX_CHARS` chars).
5164
+ */
5165
+ function closingWorkerNote(stdout, stderr) {
5166
+ const source = stdout.trim() || stderr.trim();
5167
+ if (!source) return void 0;
5168
+ return source.slice(-300);
5169
+ }
5170
+ function diffSummary(patch) {
5171
+ const trimmed = patch.trim();
5172
+ if (!trimmed) return "--- diff: EMPTY (the worker produced no edits) ---";
5173
+ const lines = trimmed.split("\n");
5174
+ const filesChanged = lines.filter((line) => line.startsWith("diff --git ")).length;
5175
+ const head = lines.slice(0, PATCH_HEAD_LINES).map((line) => line.length > PATCH_LINE_MAX_CHARS ? `${line.slice(0, PATCH_LINE_MAX_CHARS)}~` : line);
5176
+ const omitted = lines.length - head.length;
5177
+ return `${`--- diff: ${filesChanged} file(s) changed, ${Buffer.byteLength(patch)} bytes; first ${head.length} line(s) ---`}\n${head.join("\n")}${omitted > 0 ? `\n... (${omitted} more patch lines; full patch persisted per worker)` : ""}`;
5178
+ }
5179
+ //#endregion
4792
5180
  //#region src/runtime/supervise/worktree-fanout.ts
4793
5181
  /**
4794
5182
  * Build the worktree fanout combinator. Run it with `runPersonified({ persona, shape, task, budget })`
@@ -5411,6 +5799,6 @@ function tail(s) {
5411
5799
  return s.slice(-400);
5412
5800
  }
5413
5801
  //#endregion
5414
- export { defineLeaderboard as $, trajectoryReport as A, flatWidenGate as B, strategyAuthorContract as C, sanitizeMcpToolSchema as Ct, runBenchmark as D, secretEnvOfMcpServer as Dt, printBenchmarkReport as E, resolveSecretEnv as Et, registerShape as F, verify as G, panel as H, FileCorpus as I, buildSteerContext as J, widen as K, InMemoryCorpus as L, runPersonified as M, builtinShapes as N, promotionGate as O, createShapeRegistry as P, harvestCorpus as Q, renderCorpusToInstructions as R, authorStrategy as S, createMcpEnvironment as St, openSandboxRun as T, mcpSecretEnvMetadataKey as Tt, pipeline as U, loopUntil as V, selectValidWinner as W, registryScopeAnalyst as X, createScopeAnalyst as Y, inProcessSandboxClient as Z, discriminatingMeans as _, auditIntent as _t, localShell as a, loopCampaignDispatch as at, selectChampion as b, connectStdioMcp as bt, createVerifierEnvironment as c, deterministicCompletion as ct, worktreeFanout as d, leaderboard as dt, dumbDriver as et, analyzeTrace as f, pairwiseSignificance as ft, streamAgentTurn as g, renderPairwiseMarkdown as gt, collectAgentTurn as h, renderLeaderboardSvg as ht, jjWorkspace as i, inlineSandboxClient as it, definePersona as j, equalKOnCost as k, failuresAnalyst as l, sentinelCompletion as lt, runCoderChecks as m, renderLeaderboardMarkdown as mt, makeFinding$1 as n, resolveSandboxClient as nt, runInWorkspace as o, loopDispatch as ot, patchDelivered as p, renderLeaderboardHtml as pt, assertTraceDerivedFindings as q, gitWorkspace as r, localSandboxClient as rt, createWaterfallCollector as s, completionAuthorizes as st, computeFindingId$1 as t, naiveDriver as tt, superviseSurface as u, stopSentinel as ut, pickChampion as v, defaultAuditorInstruction as vt, SandboxRunAbortError as w, envKeyProvider as wt, assertStrategyContract as x, materializeLocalMcp as xt, runStrategyEvolution as y, McpSpawnFault as yt, fanout as z };
5802
+ export { fanout as $, streamAgentTurn as A, renderPairwiseMarkdown as At, printBenchmarkReport as B, resolveMcpServerLaunch as Bt, supervisorRunDir as C, sentinelCompletion as Ct, patchDelivered as D, renderLeaderboardHtml as Dt, writeWorkerSteer as E, pairwiseSignificance as Et, assertStrategyContract as F, materializeLocalMcp as Ft, definePersona as G, promotionGate as H, secretEnvOfMcpServer as Ht, authorStrategy as I, createMcpEnvironment as It, createShapeRegistry as J, runPersonified as K, strategyAuthorContract as L, sanitizeMcpToolSchema as Lt, pickChampion as M, defaultAuditorInstruction as Mt, runStrategyEvolution as N, McpSpawnFault as Nt, runCoderChecks as O, renderLeaderboardMarkdown as Ot, selectChampion as P, connectStdioMcp as Pt, renderCorpusToInstructions as Q, SandboxRunAbortError as R, envKeyProvider as Rt, safeWorkerFile as S, deterministicCompletion as St, workerInboxFileFromEventDir as T, leaderboard as Tt, equalKOnCost as U, runBenchmark as V, resolveSecretEnv as Vt, trajectoryReport as W, FileCorpus as X, registerShape as Y, InMemoryCorpus as Z, settledWorkerOut as _, localSandboxClient as _t, localShell as a, verify as at, analyzeTrace as b, loopDispatch as bt, createVerifierEnvironment as c, buildSteerContext as ct, worktreeFanout as d, inProcessSandboxClient as dt, flatWidenGate as et, EVIDENCE_MAX_CHARS as f, harvestCorpus as ft, composeWorkerEvidence as g, resolveSandboxClient as gt, closingWorkerNote as h, naiveDriver as ht, jjWorkspace as i, selectValidWinner as it, discriminatingMeans as j, auditIntent as jt, collectAgentTurn as k, renderLeaderboardSvg as kt, failuresAnalyst as l, createScopeAnalyst as lt, VERIFY_TAIL_CHARS as m, dumbDriver as mt, makeFinding$1 as n, panel as nt, runInWorkspace as o, widen as ot, NOTE_MAX_CHARS as p, defineLeaderboard as pt, builtinShapes as q, gitWorkspace as r, pipeline as rt, createWaterfallCollector as s, assertTraceDerivedFindings as st, computeFindingId$1 as t, loopUntil as tt, superviseSurface as u, registryScopeAnalyst as ut, copyUntrackedIntoClone as v, inlineSandboxClient as vt, workerInboxFile as w, stopSentinel as wt, readWorkerSteerRequests as x, completionAuthorizes as xt, withUntrackedArtifacts as y, loopCampaignDispatch as yt, openSandboxRun as z, mcpSecretEnvMetadataKey as zt };
5415
5803
 
5416
- //# sourceMappingURL=runtime-BVMyqgct.js.map
5804
+ //# sourceMappingURL=runtime-DSkMJb_X.js.map