@tangle-network/agent-runtime 0.126.0 → 0.128.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 (53) hide show
  1. package/README.md +2 -2
  2. package/dist/agent.d.ts +1 -1
  3. package/dist/agent.js +2 -2
  4. package/dist/{environment-provider-PM9PeW_J.d.ts → environment-provider-CUFsyymu.d.ts} +7 -1
  5. package/dist/environment-provider.d.ts +1 -1
  6. package/dist/{index-EdjCQBV9.d.ts → index-BhZhQw77.d.ts} +198 -20
  7. package/dist/{index-DIV33AF5.d.ts → index-BhuzfG2r.d.ts} +3 -3
  8. package/dist/{index-D_M4d1_B.d.ts → index-DLM0W1h1.d.ts} +5 -5
  9. package/dist/index.d.ts +5 -5
  10. package/dist/index.js +5 -5
  11. package/dist/index.js.map +1 -1
  12. package/dist/intelligence.d.ts +1 -1
  13. package/dist/kernel.d.ts +3 -3
  14. package/dist/kernel.js +3 -3
  15. package/dist/{knowledge-EnuEqm_Y.js → knowledge-DF63xPr4.js} +2 -2
  16. package/dist/{knowledge-EnuEqm_Y.js.map → knowledge-DF63xPr4.js.map} +1 -1
  17. package/dist/knowledge.d.ts +1 -1
  18. package/dist/knowledge.js +1 -1
  19. package/dist/{loop-runner-bin-qwT_4F5I.js → loop-runner-bin-CWqOpCEw.js} +3 -3
  20. package/dist/{loop-runner-bin-qwT_4F5I.js.map → loop-runner-bin-CWqOpCEw.js.map} +1 -1
  21. package/dist/{loop-runner-bin-Bo29_fiD.d.ts → loop-runner-bin-Ckp_9tmD.d.ts} +3 -3
  22. package/dist/loop-runner-bin.d.ts +1 -1
  23. package/dist/loop-runner-bin.js +1 -1
  24. package/dist/mcp/bin.js +1 -1
  25. package/dist/mcp/index.d.ts +3 -7
  26. package/dist/mcp/index.js +3 -3
  27. package/dist/{openai-tools-Bp1KSkP6.js → openai-tools-D3XfrrQ6.js} +2 -2
  28. package/dist/{openai-tools-Bp1KSkP6.js.map → openai-tools-D3XfrrQ6.js.map} +1 -1
  29. package/dist/primeintellect/index.d.ts +1 -1
  30. package/dist/{runtime-BzXz7OjS.js → runtime-5uDVVfER.js} +362 -11
  31. package/dist/runtime-5uDVVfER.js.map +1 -0
  32. package/dist/{supervise-Ds8FtyI9.js → supervise-CsTKbH9R.js} +100 -18
  33. package/dist/supervise-CsTKbH9R.js.map +1 -0
  34. package/dist/testing.js +8 -8
  35. package/package.json +1 -1
  36. package/skills/agent-graphs/IMPROVE.md +58 -0
  37. package/skills/agent-graphs/SKILL.md +140 -0
  38. package/skills/agent-graphs/cases/artifact-mission-release-notes.json +10 -0
  39. package/skills/agent-graphs/cases/audited-single-writer.json +9 -0
  40. package/skills/agent-graphs/cases/cap-as-stop-mistake.json +8 -0
  41. package/skills/agent-graphs/cases/floor-trap-pi.json +11 -0
  42. package/skills/agent-graphs/cases/mission-in-deliverable.json +8 -0
  43. package/skills/agent-graphs/cases/review-pipeline.json +14 -0
  44. package/skills/agent-graphs/cases/runtime-discovered-fanout.json +8 -0
  45. package/skills/agent-graphs/cases/single-agent-suffices.json +7 -0
  46. package/skills/agent-graphs/cases/steer-heavy-drafting.json +9 -0
  47. package/skills/agent-graphs/cases/unmeasured-harness.json +9 -0
  48. package/skills/agent-graphs/generations/gen1-baseline.json +248 -0
  49. package/skills/agent-graphs/generations/gen2.json +375 -0
  50. package/skills/agent-graphs/generations/gen3.json +702 -0
  51. package/skills/build-with-agent-runtime/SKILL.md +1 -0
  52. package/dist/runtime-BzXz7OjS.js.map +0 -1
  53. package/dist/supervise-Ds8FtyI9.js.map +0 -1
@@ -1,16 +1,17 @@
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 { i as InMemorySpawnJournal, r as InMemoryResultBlobStore, v as isTraceAnalysisStore } from "./spawn-journal-DsZKDqeh.js";
3
+ import { i as InMemorySpawnJournal, r as InMemoryResultBlobStore, v as isTraceAnalysisStore, x as contentAddress } from "./spawn-journal-DsZKDqeh.js";
4
4
  import { a as randomSuffix, c as stringifySafe, f as zeroTokenUsage, r as isAbortError, s as sleep, t as addTokenUsage } from "./util-MVgdwuIS.js";
5
5
  import { i as redactProtectedValue, r as redactProtectedReason } from "./protected-redaction--F3v1oo8.js";
6
- import { _t as routerChatWithUsage, bt as runBrainLoop, en as isHarnessNativeModel, et as rollingDispatch, ht as routerBrain, l as withDriverExecutor, m as settledToIteration, n as createSupervisor } from "./supervisor-DpjO0Gmy.js";
6
+ import { $t as concreteProfileModel, Qt as concreteModelId, _t as routerChatWithUsage, bt as runBrainLoop, ct as attestRuntimeOwnedExecutor, dt as newExecutionAttemptId, en as isHarnessNativeModel, et as rollingDispatch, ht as routerBrain, l as withDriverExecutor, m as settledToIteration, n as createSupervisor } from "./supervisor-DpjO0Gmy.js";
7
7
  import { C as observe, O as strategyAuthorMethod, b as sample, v as refine, x as sampleThenRefine, y as runAgentic } from "./structural-rollout-zY0oqQzO.js";
8
8
  import { i as notifyRuntimeHookEvent, t as composeRuntimeHooks } from "./runtime-hooks-C7iJOWm3.js";
9
9
  import { a as notifySandboxEventObserver, i as mapSandboxToolEvent, r as mapSandboxEvent, t as createSandboxToolPartState } from "./sandbox-events-Yhd1GYWl.js";
10
- import { Ct as createWorktreeCliExecutor, Et as createPushTraceSource, Ft as probeSandboxCapabilities, Mt as runAgentRounds, Pt as createSandboxLineage, Qt as kernelPromptRegistry, St as createExecutorRegistry, Zt as formatPromptHandle, jt as defaultSelectWinner, n as supervise, nn as gateOnDeliverable, r as workerFromBackend, xt as createExecutor } from "./supervise-Ds8FtyI9.js";
10
+ import { $t as kernelPromptRegistry, Ct as mergeAbortSignals, Ft as createSandboxLineage, It as probeSandboxCapabilities, Nt as defaultSelectWinner, Ot as createPushTraceSource, Pt as runAgentRounds, Qt as formatPromptHandle, St as createExecutorRegistry, Tt as createWorktreeCliExecutor, Ut as canonicalizeAuthoredProfile, n as supervise, r as workerFromBackend, rn as gateOnDeliverable, wt as taskToPrompt, xt as createExecutor } from "./supervise-CsTKbH9R.js";
11
11
  import { CODING_HARNESSES, InMemoryTraceStore, OUTPUT_VALUE, 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 { agentProfileSchema, canonicalCandidateDigest, validateAgentProfileSecurity } from "@tangle-network/agent-interface";
14
+ import { randomUUID } from "node:crypto";
14
15
  import { mkdir, readFile, writeFile } from "node:fs/promises";
15
16
  import { appendFileSync, chmodSync, constants, copyFileSync, existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, readlinkSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
16
17
  import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
@@ -4593,6 +4594,333 @@ function deriveTurnSignal(callerSignal, timeoutMs) {
4593
4594
  };
4594
4595
  }
4595
4596
  //#endregion
4597
+ //#region src/runtime/supervise/chat-transport-executor.ts
4598
+ /**
4599
+ * The chat-transport leaf executor: a worker whose runtime is a plain OpenAI-compatible
4600
+ * `/v1/chat/completions` transport — the worker IS a model conversation, not a sandboxed process
4601
+ * (#721). Tool calls are optional (none, or a caller-provided tool table executed on this host).
4602
+ * A chat worker gets everything real workers get through the open `Executor` port: node pinning,
4603
+ * conserved spend, settle/verdict, journal + edge ledger.
4604
+ *
4605
+ * Module home: a standalone leaf-executor module beside `worktree-cli-executor.ts` — a direct
4606
+ * `(options) → Executor` constructor, NOT a `createExecutor` backend variant. The reason is
4607
+ * continuity: `workerFromBackend` (the backend-as-data path every `ExecutorConfig` rides) creates
4608
+ * a fresh executor per spawn with no session re-attachment and deliberately FAILS LOUD on a
4609
+ * `continuity: 'resume'` spawn; the documented resume consumer is a session-owning
4610
+ * `makeWorkerAgent` seam. {@link chatWorkerSeam} is that seam, and this module ships both halves
4611
+ * together so no caller re-derives the resume wiring.
4612
+ *
4613
+ * Transport shape: NON-streaming, one buffered POST per turn — the simplest honest choice.
4614
+ * A streaming executor cannot mark an unmetered turn today (`UsageEvent`'s `tokens` variant has
4615
+ * no `tokensKnown: false` twin — see the documented limitation in `./types`), while the one-shot
4616
+ * path returns a whole `Spend` that carries both markers. Honesty wins over liveness here.
4617
+ *
4618
+ * Metering: tokens come from the transport's `usage` fields; a turn without usage marks
4619
+ * `tokensKnown: false`. Dollars come ONLY from the response's own cost fields (`usage.cost` /
4620
+ * `usage.cost_usd`, the cli-bridge and OpenRouter conventions); a turn without one marks
4621
+ * `usdKnown: false`. NEVER estimated from a local price table — this executor speaks to arbitrary
4622
+ * OpenAI-compatible endpoints whose models a local table cannot price, and a silent estimate is a
4623
+ * fabricated measurement.
4624
+ *
4625
+ * @experimental
4626
+ */
4627
+ /** The default transport: POST `${url}/chat/completions` with an optional bearer. Fail-loud on
4628
+ * any non-2xx — the status and body head become the settle reason. */
4629
+ function chatCompletionsTransport(opts) {
4630
+ if (typeof opts.url !== "string" || opts.url.length === 0) throw new ValidationError("chatCompletionsTransport: url required");
4631
+ const endpoint = `${opts.url.replace(/\/$/, "")}/chat/completions`;
4632
+ return async (body, signal) => {
4633
+ const res = await fetch(endpoint, {
4634
+ method: "POST",
4635
+ headers: {
4636
+ "content-type": "application/json",
4637
+ ...opts.bearer ? { authorization: `Bearer ${opts.bearer}` } : {}
4638
+ },
4639
+ body: JSON.stringify(body),
4640
+ ...signal ? { signal } : {}
4641
+ });
4642
+ if (!res.ok) throw new ValidationError(`chat transport ${res.status}: ${(await res.text()).slice(0, 200)}`);
4643
+ return res.json();
4644
+ };
4645
+ }
4646
+ /** In-memory `ChatSessionStore`. Entries are detached copies — a caller mutating a saved array
4647
+ * cannot corrupt a recorded session. */
4648
+ function createChatSessionStore() {
4649
+ const sessions = /* @__PURE__ */ new Map();
4650
+ return {
4651
+ load: (workerId) => sessions.get(workerId),
4652
+ save: (workerId, messages) => {
4653
+ sessions.set(workerId, structuredClone(messages));
4654
+ }
4655
+ };
4656
+ }
4657
+ const CHAT_TRANSPORT_RUNTIME = "chat-transport";
4658
+ /**
4659
+ * Build the chat-transport `Executor`: one `execute` = one conversation SHOT — seed (fresh system
4660
+ * prompt, or the resumed session's recorded history) + the task as the next user message, then
4661
+ * loop completion → host tool calls → tool messages until the model answers without a tool call
4662
+ * (or the turn cap). Settles with the final assistant text as `out`.
4663
+ *
4664
+ * Fail-loud contract: transport failures (non-2xx, network faults, malformed completions) throw
4665
+ * `ValidationError`, which the scope settles as an INFRA failure (`Settled.down.infra`) — never a
4666
+ * fake success. The accumulated conversation is still recorded before the throw when a store is
4667
+ * configured, because the inference HAPPENED and a resume may continue a failed session (the
4668
+ * kernel deliberately allows resume-after-failure; the seam decides).
4669
+ */
4670
+ function chatTransportExecutor(opts) {
4671
+ const model = concreteModelId(opts.model);
4672
+ if (!model) throw new ValidationError("chatTransportExecutor: model required");
4673
+ if (!opts.complete && (typeof opts.url !== "string" || opts.url.length === 0)) throw new ValidationError("chatTransportExecutor: url required (or inject `complete`)");
4674
+ for (const tool of opts.tools ?? []) if (typeof tool.spec?.function?.name !== "string" || typeof tool.execute !== "function") throw new ValidationError("chatTransportExecutor: every tools entry needs spec.function.name + execute");
4675
+ const maxTurns = opts.maxTurnsPerShot ?? 200;
4676
+ if (!Number.isInteger(maxTurns) || maxTurns < 1) throw new ValidationError("chatTransportExecutor: maxTurnsPerShot must be a positive integer");
4677
+ if (opts.maxTokens !== void 0 && (!Number.isInteger(opts.maxTokens) || opts.maxTokens < 1)) throw new ValidationError("chatTransportExecutor: maxTokens must be a positive integer");
4678
+ let seed;
4679
+ if (opts.resume) {
4680
+ if (!opts.sessions) throw new ValidationError("chatTransportExecutor: a 'resume' spawn needs `sessions` — the store holding the conversation this shot continues");
4681
+ const prior = opts.sessions.load(opts.resume.ofWorker);
4682
+ if (prior === void 0) throw new ValidationError(`chatTransportExecutor: no recorded conversation for worker '${opts.resume.ofWorker}' — the session store holds only conversations recorded by this process (the kernel’s process-local resume boundary)`);
4683
+ seed = structuredClone(prior);
4684
+ } else seed = opts.system !== void 0 && opts.system.length > 0 ? [{
4685
+ role: "system",
4686
+ content: opts.system
4687
+ }] : [];
4688
+ const transport = opts.complete ?? chatCompletionsTransport({
4689
+ url: opts.url,
4690
+ ...opts.bearer ? { bearer: opts.bearer } : {}
4691
+ });
4692
+ const toolSpecs = (opts.tools ?? []).map((tool) => tool.spec);
4693
+ const toolByName = new Map((opts.tools ?? []).map((tool) => [tool.spec.function.name, tool]));
4694
+ const controller = new AbortController();
4695
+ let artifact;
4696
+ let executed = false;
4697
+ const executionId = opts.sessionKey ?? `chat-session-${randomUUID()}`;
4698
+ const attemptId = opts.attemptId ?? newExecutionAttemptId(executionId);
4699
+ const executor = {
4700
+ runtime: CHAT_TRANSPORT_RUNTIME,
4701
+ async execute(task, signal) {
4702
+ if (executed) throw new ValidationError("chatTransportExecutor: execute() called twice on one instance");
4703
+ executed = true;
4704
+ const started = Date.now();
4705
+ const messages = seed;
4706
+ messages.push({
4707
+ role: "user",
4708
+ content: taskToPrompt(task)
4709
+ });
4710
+ const linked = mergeAbortSignals(signal, controller.signal);
4711
+ const tokens = zeroTokenUsage();
4712
+ let tokensKnown = true;
4713
+ let usd = 0;
4714
+ let usdKnown = true;
4715
+ let turns = 0;
4716
+ let lastText = "";
4717
+ try {
4718
+ for (let t = 0; t < maxTurns; t += 1) {
4719
+ const body = {
4720
+ model,
4721
+ messages,
4722
+ ...toolSpecs.length > 0 ? {
4723
+ tools: toolSpecs,
4724
+ tool_choice: "auto"
4725
+ } : {},
4726
+ ...opts.temperature !== void 0 ? { temperature: opts.temperature } : {},
4727
+ ...opts.maxTokens !== void 0 ? { max_tokens: opts.maxTokens } : {}
4728
+ };
4729
+ let raw;
4730
+ try {
4731
+ raw = await transport(body, linked);
4732
+ } catch (cause) {
4733
+ if (cause instanceof Error && cause.name === "AbortError") throw cause;
4734
+ if (cause instanceof ValidationError) throw cause;
4735
+ throw new ValidationError(`chatTransportExecutor: transport failed: ${cause instanceof Error ? cause.message : String(cause)}`);
4736
+ }
4737
+ turns += 1;
4738
+ const data = raw;
4739
+ const usage = data?.usage;
4740
+ if (usage && typeof usage.prompt_tokens === "number" && typeof usage.completion_tokens === "number") {
4741
+ tokens.input += usage.prompt_tokens;
4742
+ tokens.output += usage.completion_tokens;
4743
+ } else tokensKnown = false;
4744
+ const turnCost = typeof usage?.cost === "number" ? usage.cost : typeof usage?.cost_usd === "number" ? usage.cost_usd : void 0;
4745
+ if (turnCost !== void 0) usd += turnCost;
4746
+ else usdKnown = false;
4747
+ const msg = data?.choices?.[0]?.message;
4748
+ if (msg === void 0) throw new ValidationError("chatTransportExecutor: transport returned no choices[0].message");
4749
+ if (typeof msg.content === "string" && msg.content.length > 0) lastText = msg.content;
4750
+ const toolCalls = msg.tool_calls ?? [];
4751
+ if (toolCalls.length === 0 || toolSpecs.length === 0) {
4752
+ messages.push({
4753
+ role: "assistant",
4754
+ content: msg.content ?? ""
4755
+ });
4756
+ break;
4757
+ }
4758
+ messages.push({
4759
+ role: "assistant",
4760
+ content: msg.content ?? "",
4761
+ tool_calls: toolCalls.map((tc, i) => ({
4762
+ id: tc.id ?? `call_${i}`,
4763
+ type: "function",
4764
+ function: {
4765
+ name: tc.function?.name ?? "",
4766
+ arguments: tc.function?.arguments ?? "{}"
4767
+ }
4768
+ }))
4769
+ });
4770
+ for (let i = 0; i < toolCalls.length; i += 1) {
4771
+ const tc = toolCalls[i];
4772
+ const id = tc?.id ?? `call_${i}`;
4773
+ const name = tc?.function?.name ?? "";
4774
+ const tool = toolByName.get(name);
4775
+ if (!tool) {
4776
+ messages.push({
4777
+ role: "tool",
4778
+ tool_call_id: id,
4779
+ content: `error: unknown tool '${name}'`
4780
+ });
4781
+ continue;
4782
+ }
4783
+ let args;
4784
+ try {
4785
+ args = JSON.parse(tc?.function?.arguments ?? "{}");
4786
+ } catch {
4787
+ messages.push({
4788
+ role: "tool",
4789
+ tool_call_id: id,
4790
+ content: "error: tool arguments were not valid JSON"
4791
+ });
4792
+ continue;
4793
+ }
4794
+ let result;
4795
+ try {
4796
+ result = await tool.execute(args, task);
4797
+ } catch (cause) {
4798
+ result = `error: ${cause instanceof Error ? cause.message : String(cause)}`;
4799
+ }
4800
+ messages.push({
4801
+ role: "tool",
4802
+ tool_call_id: id,
4803
+ content: result
4804
+ });
4805
+ }
4806
+ }
4807
+ } finally {
4808
+ if (opts.sessions && opts.sessionKey !== void 0) opts.sessions.save(opts.sessionKey, messages);
4809
+ }
4810
+ const spent = {
4811
+ iterations: turns,
4812
+ tokens,
4813
+ ...tokensKnown ? {} : { tokensKnown: false },
4814
+ usd,
4815
+ ...usdKnown ? {} : { usdKnown: false },
4816
+ ms: Date.now() - started
4817
+ };
4818
+ artifact = {
4819
+ outRef: contentAddress({
4820
+ kind: "chat-transport",
4821
+ model,
4822
+ content: lastText,
4823
+ turns
4824
+ }),
4825
+ out: lastText,
4826
+ spent
4827
+ };
4828
+ return artifact;
4829
+ },
4830
+ teardown(_grace) {
4831
+ controller.abort();
4832
+ return Promise.resolve({ destroyed: true });
4833
+ },
4834
+ resultArtifact() {
4835
+ if (!artifact) throw new ValidationError("chatTransportExecutor: resultArtifact() read before execute()");
4836
+ return {
4837
+ ...artifact,
4838
+ spent: artifact.spent
4839
+ };
4840
+ }
4841
+ };
4842
+ if (opts.profile === void 0) return executor;
4843
+ return attestRuntimeOwnedExecutor(executor, {
4844
+ effectiveProfile: opts.profile,
4845
+ backend: "chat-transport",
4846
+ model: {
4847
+ status: "known",
4848
+ id: model
4849
+ },
4850
+ execution: {
4851
+ kind: "session",
4852
+ id: executionId
4853
+ },
4854
+ materializer: "chat-transport-conversation",
4855
+ plan: {
4856
+ kind: "openai-chat-conversation",
4857
+ model,
4858
+ maxTurnsPerShot: maxTurns,
4859
+ tools: toolSpecs,
4860
+ resumeOf: opts.resume?.ofWorker ?? null
4861
+ }
4862
+ }, {
4863
+ attemptId,
4864
+ binding: {
4865
+ endpoint: opts.complete ? "injected-transport" : opts.url,
4866
+ model,
4867
+ sessionKey: opts.sessionKey ?? null
4868
+ },
4869
+ descriptor: {
4870
+ kind: "chat-transport-session",
4871
+ transport: opts.complete ? "injected" : "http",
4872
+ backend: "chat-transport"
4873
+ }
4874
+ });
4875
+ }
4876
+ /**
4877
+ * The `makeWorkerAgent` seam over {@link chatTransportExecutor} — the continuity consumer
4878
+ * `workerFromBackend` refuses to be. Every spawn becomes one conversation shot: the spawned
4879
+ * profile's system prompt + instructions (which is where a graph's delegates directive lands)
4880
+ * seed a fresh session, and a `'resume'` spawn re-attaches by loading `resume.ofWorker`'s
4881
+ * recorded message list from the seam's session store. Conversations are recorded under the
4882
+ * kernel node id, which is exactly what a later `resume.ofWorker` names.
4883
+ */
4884
+ function chatWorkerSeam(opts) {
4885
+ if (!opts.complete && (typeof opts.url !== "string" || opts.url.length === 0)) throw new ValidationError("chatWorkerSeam: url required (or inject `complete`)");
4886
+ const sessions = opts.sessions ?? createChatSessionStore();
4887
+ return (rawProfile, spawnContext) => {
4888
+ const parsed = agentProfileSchema.safeParse(canonicalizeAuthoredProfile(rawProfile));
4889
+ if (!parsed.success) throw new ValidationError(`chatWorkerSeam: invalid AgentProfile: ${parsed.error.message}`);
4890
+ const profile = parsed.data;
4891
+ const model = concreteProfileModel(profile) ?? concreteModelId(opts.model);
4892
+ if (!model) throw new ValidationError("chatWorkerSeam: no model — set ChatWorkerSeamOptions.model or AgentProfile.model.default");
4893
+ const system = [profile.prompt?.systemPrompt, ...profile.prompt?.instructions ?? []].filter((line) => typeof line === "string" && line.trim().length > 0).join("\n");
4894
+ return {
4895
+ name: profile.name ?? "chat-worker",
4896
+ act: async () => void 0,
4897
+ executorSpec: {
4898
+ profile,
4899
+ harness: null,
4900
+ executorFactory: (executorSpec, ctx) => {
4901
+ const executor = chatTransportExecutor({
4902
+ url: opts.url,
4903
+ ...opts.bearer !== void 0 ? { bearer: opts.bearer } : {},
4904
+ model,
4905
+ ...system.length > 0 ? { system } : {},
4906
+ ...opts.tools !== void 0 ? { tools: opts.tools } : {},
4907
+ ...opts.temperature !== void 0 ? { temperature: opts.temperature } : {},
4908
+ ...opts.maxTokens !== void 0 ? { maxTokens: opts.maxTokens } : {},
4909
+ ...opts.maxTurnsPerShot !== void 0 ? { maxTurnsPerShot: opts.maxTurnsPerShot } : {},
4910
+ ...opts.complete !== void 0 ? { complete: opts.complete } : {},
4911
+ sessions,
4912
+ ...ctx.node?.nodeId !== void 0 ? { sessionKey: ctx.node.nodeId } : {},
4913
+ ...spawnContext?.resume !== void 0 ? { resume: spawnContext.resume } : {},
4914
+ profile: executorSpec.profile,
4915
+ ...ctx.node?.attemptId !== void 0 ? { attemptId: ctx.node.attemptId } : {}
4916
+ });
4917
+ return opts.deliverable ? gateOnDeliverable(executor, opts.deliverable) : executor;
4918
+ }
4919
+ }
4920
+ };
4921
+ };
4922
+ }
4923
+ //#endregion
4596
4924
  //#region src/runtime/supervise/graph.ts
4597
4925
  /**
4598
4926
  *
@@ -4607,8 +4935,8 @@ function deriveTurnSignal(callerSignal, timeoutMs) {
4607
4935
  * NOT A SECOND SCHEDULER. `runGraph` is an interpretation layer over what already runs:
4608
4936
  * `supervise()` is the execution core — the same `supervisorAgent`/`driverAgent` machinery,
4609
4937
  * `makeWorkerAgent` seam, conserved-pool budget, and deliverable-gated settlement every
4610
- * supervised run uses. (`runLoop` is a deprecated alias of `runAgentRounds` and is deliberately
4611
- * NOT the substrate here.) What the graph layer ADDS is exactly what a bespoke driver loop never
4938
+ * supervised run uses. (`runAgentRounds` is deliberately NOT the substrate here.) What the graph
4939
+ * layer ADDS is exactly what a bespoke driver loop never
4612
4940
  * had:
4613
4941
  *
4614
4942
  * 1. **Node pinning** — a spawn names a node (`profile.name` = node id) and the node's canonical
@@ -4623,6 +4951,12 @@ function deriveTurnSignal(callerSignal, timeoutMs) {
4623
4951
  * edge is a versioned optimization target, never prose hardcoded in a builder function.
4624
4952
  * 4. **Per-edge traversal caps** — the cyclic-graph backstop. A delegates edge whose cap is
4625
4953
  * exhausted REFUSES further traversals (fail loud), so a cycle cannot spin the pool dry.
4954
+ * 5. **Continuity as data** — a delegates edge may declare `continuity: 'resume'`, so each spawn
4955
+ * after the node's first re-attaches to its latest SETTLED session (the spawn context hands
4956
+ * the executor seam `resume: { ofWorker, sequence }`; the kernel keeps identity, ordering,
4957
+ * ledger truth, and the one conserved pool). Every ledger row states how its hop continued:
4958
+ * `'fresh' | 'resume'` for spawns, `'steer'` for mid-run deliveries — fresh respawns, session
4959
+ * resumes, and live steers are all plain data, each a ledgered fact.
4626
4960
  *
4627
4961
  * ORACLES ARE ENVIRONMENT, NEVER WORKERS. Graders/verifiers must not be spawnable in the graph —
4628
4962
  * a delegates edge to them leaks the rubric. An `analyzes` edge names its analyst in one of two
@@ -4682,6 +5016,7 @@ function validateGraph(graph, registry, analysts) {
4682
5016
  requireNode(edge.from, edgeId(edge));
4683
5017
  requireNode(edge.to, edgeId(edge));
4684
5018
  if (edge.from === edge.to) throw new ValidationError(`runGraph: ${edgeId(edge)} delegates to itself — the driver↔worker cycle is the settle-return loop, not a self-edge`);
5019
+ if (edge.continuity !== void 0 && edge.continuity !== "fresh" && edge.continuity !== "resume") throw new ValidationError(`runGraph: ${edgeId(edge)} has invalid continuity ${JSON.stringify(edge.continuity)} — a delegates edge's continuity is 'fresh' or 'resume'`);
4685
5020
  }
4686
5021
  const delegatedTo = new Set(delegates.map((edge) => edge.to));
4687
5022
  const roots = [...new Set(delegates.map((edge) => edge.from))].filter((id) => !delegatedTo.has(id));
@@ -4691,6 +5026,7 @@ function validateGraph(graph, registry, analysts) {
4691
5026
  const analystIds = /* @__PURE__ */ new Set();
4692
5027
  const analystNodes = /* @__PURE__ */ new Map();
4693
5028
  for (const edge of analyzes) {
5029
+ if (edge.continuity !== void 0) throw new ValidationError(`runGraph: ${edgeId(edge)} carries continuity — analysts are spawned by the analyst machinery (every analyst run is a fresh session over settled evidence), so continuity is a delegates-edge axis only`);
4694
5030
  if (analystIds.has(edge.analyst)) throw new ValidationError(`runGraph: two analyzes edges share analyst '${edge.analyst}' — one analyzes edge per analyst lens (traversals are ledgered by analyst id; a second edge would silently absorb the first's). Register the lens under a second id for a second edge.`);
4695
5031
  analystIds.add(edge.analyst);
4696
5032
  const analystNode = byId.get(edge.analyst);
@@ -4703,7 +5039,10 @@ function validateGraph(graph, registry, analysts) {
4703
5039
  } else if (!analysts) throw new ValidationError(`runGraph: ${edgeId(edge)} analyst '${edge.analyst}' is not a graph node, and no RunGraphOptions.analysts registry was provided to resolve it as a lens`);
4704
5040
  else if (!inRegistry) throw new ValidationError(`runGraph: ${edgeId(edge)} analyst '${edge.analyst}' is neither a graph node nor in the analysts registry (known lenses: ${analysts.kinds.map((kind) => kind.id).join(", ") || "none"})`);
4705
5041
  if (edge.over.length === 0) throw new ValidationError(`runGraph: ${edgeId(edge)} must analyze at least one node`);
4706
- for (const over of edge.over) requireNode(over, edgeId(edge));
5042
+ for (const over of edge.over) {
5043
+ requireNode(over, edgeId(edge));
5044
+ if (over === root.id) throw new ValidationError(`runGraph: ${edgeId(edge)} analyzes the ROOT — analysts observe settled workers, and the root never settles as one, so this edge would silently never fire; list delegates-target nodes only`);
5045
+ }
4707
5046
  requireNode(edge.to, edgeId(edge));
4708
5047
  }
4709
5048
  for (const edge of analyzes) for (const over of edge.over) if (analystNodes.has(over)) throw new ValidationError(`runGraph: ${edgeId(edge)} analyzes '${over}', which is an analyst node — an analyst run settles as a finding, never as a worker, so this edge would silently never fire; analyst nodes are not analyzable`);
@@ -4769,6 +5108,7 @@ function runGraph(graph, opts) {
4769
5108
  },
4770
5109
  traversal: entry.traversal,
4771
5110
  outcome: entry.outcome,
5111
+ continuity: entry.continuity,
4772
5112
  bytes: entry.bytes,
4773
5113
  ...entry.reason !== void 0 ? { reason: entry.reason } : {},
4774
5114
  seq: ledgerSeq++,
@@ -4803,7 +5143,9 @@ function runGraph(graph, opts) {
4803
5143
  const edge = delegatesByWorker.get(node.id);
4804
5144
  const id = edgeId(edge);
4805
5145
  const cap = edge.maxTraversals ?? 32;
4806
- if ((traversalCounts.get(id) ?? 0) >= cap) {
5146
+ const used = traversalCounts.get(id) ?? 0;
5147
+ const spawnContinuity = spawnContext?.continuity ?? "fresh";
5148
+ if (used >= cap) {
4807
5149
  exhausted.add(id);
4808
5150
  exhaustedDelegates.add(id);
4809
5151
  record({
@@ -4813,6 +5155,7 @@ function runGraph(graph, opts) {
4813
5155
  to: edge.to,
4814
5156
  directive: formatPromptHandle(edge.directive),
4815
5157
  outcome: "unpropagated",
5158
+ continuity: spawnContinuity,
4816
5159
  bytes: 0,
4817
5160
  reason: `traversal-cap-exhausted (max ${cap})`
4818
5161
  }, true);
@@ -4828,6 +5171,7 @@ function runGraph(graph, opts) {
4828
5171
  to: edge.to,
4829
5172
  directive: formatPromptHandle(edge.directive),
4830
5173
  outcome: bytes === 0 ? "empty" : "delivered",
5174
+ continuity: spawnContinuity,
4831
5175
  bytes,
4832
5176
  ...bytes === 0 ? { reason: "no directive text and no task payload" } : {}
4833
5177
  }, false);
@@ -4862,14 +5206,18 @@ function runGraph(graph, opts) {
4862
5206
  };
4863
5207
  });
4864
5208
  const driverAnalyzesBriefs = analyzes.filter((edge) => edge.to === root.id).map((edge) => analystNodes.has(edge.analyst) ? `Findings from analyst '${edge.analyst}' (a tool-equipped analyst agent node, over: ${edge.over.join(", ")}) will arrive as finding events.` : `Findings from analyst '${edge.analyst}' (over: ${edge.over.join(", ")}) will arrive as finding events.\n${registry.resolve(edge.directive).text}`);
5209
+ const continuityByProfile = {};
5210
+ for (const [nodeId, edge] of delegatesByWorker) if (edge.continuity !== void 0) continuityByProfile[nodeId] = edge.continuity;
4865
5211
  const graphBrief = [
4866
5212
  "AGENT GRAPH: you are the driver node of a fixed topology. You may spawn ONLY these worker",
4867
5213
  "nodes, by EXACT name (spawn_agent with profile: { name: '<node id>' }; the node's full",
4868
5214
  "profile is pinned by the graph — any other profile fields you author are ignored):",
4869
5215
  ...[...workers.values()].map((node) => {
4870
- const cap = delegatesByWorker.get(node.id).maxTraversals ?? 32;
5216
+ const edge = delegatesByWorker.get(node.id);
5217
+ const cap = edge.maxTraversals ?? 32;
4871
5218
  const description = typeof node.profile.description === "string" && node.profile.description.length > 0 ? ` — ${node.profile.description}` : "";
4872
- return `- '${node.id}'${description} (delegation cap: ${cap} traversals)`;
5219
+ const continuityNote = edge.continuity === "resume" ? "; continuity: resume — each spawn after the first re-attaches to this node's latest settled session (spawn again to continue it; steer while it is live)" : "";
5220
+ return `- '${node.id}'${description} (delegation cap: ${cap} traversals${continuityNote})`;
4873
5221
  }),
4874
5222
  ...driverAnalyzesBriefs.length > 0 ? ["", ...driverAnalyzesBriefs] : []
4875
5223
  ].join("\n");
@@ -4904,6 +5252,7 @@ function runGraph(graph, opts) {
4904
5252
  to: edge.to,
4905
5253
  directive: formatPromptHandle(edge.directive),
4906
5254
  outcome: capped ? "unpropagated" : outcome,
5255
+ continuity: "steer",
4907
5256
  bytes,
4908
5257
  ...capped ? { reason: `traversal-cap-exhausted (max ${edge.maxTraversals ?? 32})` } : reason !== void 0 ? { reason } : {},
4909
5258
  ...workerId !== void 0 ? { workerId } : {}
@@ -4942,6 +5291,7 @@ function runGraph(graph, opts) {
4942
5291
  to: edge.to,
4943
5292
  directive: formatPromptHandle(edge.directive),
4944
5293
  outcome: !down.delivered ? "unpropagated" : stripped ? "stripped" : "delivered",
5294
+ continuity: "steer",
4945
5295
  bytes: byteLength(down.instruction),
4946
5296
  ...!down.delivered ? { reason: down.outcome } : stripped ? { reason: `authorization narrowed ${stripped.composedBytes} composed bytes` } : {},
4947
5297
  workerId: down.toWorker
@@ -4977,6 +5327,7 @@ function runGraph(graph, opts) {
4977
5327
  analyzeOnSettle: routes,
4978
5328
  ...opts.analysts ? { analysts: opts.analysts } : {}
4979
5329
  } : {},
5330
+ ...Object.keys(continuityByProfile).length > 0 ? { continuityByProfile } : {},
4980
5331
  ...opts.watchWorkers ? { watchWorkers: opts.watchWorkers } : {},
4981
5332
  ...opts.router ? { router: opts.router } : {},
4982
5333
  ...opts.brain ? { brain: opts.brain } : {},
@@ -6150,6 +6501,6 @@ function tail(s) {
6150
6501
  return s.slice(-400);
6151
6502
  }
6152
6503
  //#endregion
6153
- export { panel as $, runStrategyEvolution as A, materializeLocalMcp as At, equalKOnCost as B, GraphEdgeCapError as C, renderLeaderboardMarkdown as Ct, streamAgentTurn as D, defaultAuditorInstruction as Dt, collectAgentTurn as E, auditIntent as Et, SandboxRunAbortError as F, resolveMcpServerLaunch as Ft, createShapeRegistry as G, definePersona as H, openSandboxRun as I, resolveSecretEnv as It, InMemoryCorpus as J, registerShape as K, printBenchmarkReport as L, secretEnvOfMcpServer as Lt, assertStrategyContract as M, sanitizeMcpToolSchema as Mt, authorStrategy as N, envKeyProvider as Nt, discriminatingMeans as O, McpSpawnFault as Ot, strategyAuthorContract as P, mcpSecretEnvMetadataKey as Pt, loopUntil as Q, runBenchmark as R, runCoderChecks as S, renderLeaderboardHtml as St, runGraph as T, renderPairwiseMarkdown as Tt, runPersonified as U, trajectoryReport as V, builtinShapes as W, fanout as X, renderCorpusToInstructions as Y, flatWidenGate as Z, settledWorkerOut as _, deterministicCompletion as _t, localShell as a, buildSteerContext as at, analyzeTrace as b, leaderboard as bt, createVerifierEnvironment as c, inProcessSandboxClient as ct, worktreeFanout as d, resolveSandboxClient as dt, pipeline as et, EVIDENCE_MAX_CHARS as f, localSandboxClient as ft, composeWorkerEvidence as g, completionAuthorizes as gt, closingWorkerNote as h, loopDispatch as ht, jjWorkspace as i, assertTraceDerivedFindings as it, selectChampion as j, createMcpEnvironment as jt, pickChampion as k, connectStdioMcp as kt, failuresAnalyst as l, harvestCorpus as lt, VERIFY_TAIL_CHARS as m, loopCampaignDispatch as mt, makeFinding$1 as n, verify as nt, runInWorkspace as o, createScopeAnalyst as ot, NOTE_MAX_CHARS as p, inlineSandboxClient as pt, FileCorpus as q, gitWorkspace as r, widen as rt, createWaterfallCollector as s, registryScopeAnalyst as st, computeFindingId$1 as t, selectValidWinner as tt, superviseSurface as u, defineLeaderboard as ut, copyUntrackedIntoClone as v, sentinelCompletion as vt, defaultEdgeTraversalCap as w, renderLeaderboardSvg as wt, patchDelivered as x, pairwiseSignificance as xt, withUntrackedArtifacts as y, stopSentinel as yt, promotionGate as z };
6504
+ export { renderCorpusToInstructions as $, collectAgentTurn as A, auditIntent as At, openSandboxRun as B, resolveSecretEnv as Bt, GraphEdgeCapError as C, stopSentinel as Ct, chatTransportExecutor as D, renderLeaderboardMarkdown as Dt, chatCompletionsTransport as E, renderLeaderboardHtml as Et, selectChampion as F, createMcpEnvironment as Ft, trajectoryReport as G, runBenchmark as H, assertStrategyContract as I, sanitizeMcpToolSchema as It, builtinShapes as J, definePersona as K, authorStrategy as L, envKeyProvider as Lt, discriminatingMeans as M, McpSpawnFault as Mt, pickChampion as N, connectStdioMcp as Nt, chatWorkerSeam as O, renderLeaderboardSvg as Ot, runStrategyEvolution as P, materializeLocalMcp as Pt, InMemoryCorpus as Q, strategyAuthorContract as R, mcpSecretEnvMetadataKey as Rt, runCoderChecks as S, sentinelCompletion as St, runGraph as T, pairwiseSignificance as Tt, promotionGate as U, printBenchmarkReport as V, secretEnvOfMcpServer as Vt, equalKOnCost as W, registerShape as X, createShapeRegistry as Y, FileCorpus as Z, settledWorkerOut as _, inlineSandboxClient as _t, localShell as a, selectValidWinner as at, analyzeTrace as b, completionAuthorizes as bt, createVerifierEnvironment as c, assertTraceDerivedFindings as ct, worktreeFanout as d, registryScopeAnalyst as dt, fanout as et, EVIDENCE_MAX_CHARS as f, inProcessSandboxClient as ft, composeWorkerEvidence as g, localSandboxClient as gt, closingWorkerNote as h, resolveSandboxClient as ht, jjWorkspace as i, pipeline as it, streamAgentTurn as j, defaultAuditorInstruction as jt, createChatSessionStore as k, renderPairwiseMarkdown as kt, failuresAnalyst as l, buildSteerContext as lt, VERIFY_TAIL_CHARS as m, defineLeaderboard as mt, makeFinding$1 as n, loopUntil as nt, runInWorkspace as o, verify as ot, NOTE_MAX_CHARS as p, harvestCorpus as pt, runPersonified as q, gitWorkspace as r, panel as rt, createWaterfallCollector as s, widen as st, computeFindingId$1 as t, flatWidenGate as tt, superviseSurface as u, createScopeAnalyst as ut, copyUntrackedIntoClone as v, loopCampaignDispatch as vt, defaultEdgeTraversalCap as w, leaderboard as wt, patchDelivered as x, deterministicCompletion as xt, withUntrackedArtifacts as y, loopDispatch as yt, SandboxRunAbortError as z, resolveMcpServerLaunch as zt };
6154
6505
 
6155
- //# sourceMappingURL=runtime-BzXz7OjS.js.map
6506
+ //# sourceMappingURL=runtime-5uDVVfER.js.map