@tangle-network/agent-runtime 0.281.0 → 0.282.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 (34) hide show
  1. package/dist/{activation-C1ZAyQrQ.js → activation-Bi_oOB1-.js} +2 -2
  2. package/dist/{activation-C1ZAyQrQ.js.map → activation-Bi_oOB1-.js.map} +1 -1
  3. package/dist/agent.d.ts +1 -1
  4. package/dist/agent.js +1 -1
  5. package/dist/durable.d.ts +1 -1
  6. package/dist/durable.js +71 -45
  7. package/dist/durable.js.map +1 -1
  8. package/dist/{improvement-cycle-DCTCTmNl.js → improvement-cycle-8MUf5Xfp.js} +8 -1772
  9. package/dist/improvement-cycle-8MUf5Xfp.js.map +1 -0
  10. package/dist/{index-BSSGMvUd.d.ts → index-CSyzK6Kd.d.ts} +131 -260
  11. package/dist/index.d.ts +2 -2
  12. package/dist/index.js +5 -5
  13. package/dist/intelligence.js +3 -2
  14. package/dist/intelligence.js.map +1 -1
  15. package/dist/kernel.d.ts +2 -2
  16. package/dist/kernel.js +3 -3
  17. package/dist/{loop-runner-bin-Co2eBFbb.js → loop-runner-bin-Cg78CKmf.js} +2 -2
  18. package/dist/{loop-runner-bin-Co2eBFbb.js.map → loop-runner-bin-Cg78CKmf.js.map} +1 -1
  19. package/dist/{loop-runner-bin-DgeZHpWJ.d.ts → loop-runner-bin-Dtt8FdYO.d.ts} +2 -2
  20. package/dist/loop-runner-bin.d.ts +1 -1
  21. package/dist/loop-runner-bin.js +1 -1
  22. package/dist/mcp/index.d.ts +1 -1
  23. package/dist/mcp/index.js +1 -1
  24. package/dist/{runtime-B_yRPBjj.js → runtime-Bid-kBes.js} +676 -675
  25. package/dist/runtime-Bid-kBes.js.map +1 -0
  26. package/dist/{shared-box-CZFdugL1.js → search-method-CbUyhdz5.js} +1799 -16
  27. package/dist/search-method-CbUyhdz5.js.map +1 -0
  28. package/dist/testing.d.ts +1 -1
  29. package/dist/testing.js +9 -9
  30. package/dist/tui/index.d.ts +1 -1
  31. package/package.json +1 -1
  32. package/dist/improvement-cycle-DCTCTmNl.js.map +0 -1
  33. package/dist/runtime-B_yRPBjj.js.map +0 -1
  34. package/dist/shared-box-CZFdugL1.js.map +0 -1
@@ -1,12 +1,19 @@
1
- import { Ba as promptOptionsFromAgentTurnInput, Ht as InMemorySpawnJournal, Ia as armDeadlineTimer, Ji as unknownExecutionBindingReceipt, Ki as runtimeOwnedPendingExecutorMaterialization, Li as knownExecutionBindingReceipt, M as withDriverExecutor, Mt as createExecutorRegistry, Ot as captureReusableExecutorConfig, Pa as awaitAbortable, Pi as authoredProfileDigest, Qn as observedModelMatchesDeclared, Ri as knownMaterializationReceipt, Sa as sleep, Ui as runtimeOwnedExecutorExecutionBinding, Va as providerMessageText, Vt as InMemoryResultBlobStore, Wi as runtimeOwnedExecutorMaterialization, Xi as executableAgentProfileSnapshot, Yi as unknownMaterializationReceipt, aa as createSandboxUsageLedger, ar as sandboxClientAsProvider, ca as mapSandboxEvent, ea as projectSandboxOutcome, er as LEAF_CONTINUATION_TASK, ia as createSandboxToolPartState, jt as createExecutor, la as mapSandboxToolEvent, oi as harnessInvocation, or as unavailablePauseMs, r as createSupervisor, ra as canonicalStreamEventFromSandboxEvent, sa as isSandboxTerminalEvent, sr as unavailableSignalOfFailure, ta as readSandboxOutcome, za as promptFromAgentTurnInput } from "./supervisor-UXgaPisu.js";
2
- import { m as ValidationError, p as SessionMismatchError, r as BackendTransportError } from "./errors-DodWX-cb.js";
1
+ import { Ba as promptOptionsFromAgentTurnInput, Br as createOpenInferenceFileExporter, Gr as padSpanId, Ht as InMemorySpawnJournal, Ia as armDeadlineTimer, Ji as unknownExecutionBindingReceipt, K as openSlotGroup, Ki as runtimeOwnedPendingExecutorMaterialization, Kr as padTraceId, Li as knownExecutionBindingReceipt, M as withDriverExecutor, Mt as createExecutorRegistry, Ot as captureReusableExecutorConfig, Pa as awaitAbortable, Pi as authoredProfileDigest, Qn as observedModelMatchesDeclared, Ri as knownMaterializationReceipt, Sa as sleep, Ui as runtimeOwnedExecutorExecutionBinding, Ur as generateSpanId, Va as providerMessageText, Vr as createOtelExporter, Vt as InMemoryResultBlobStore, Wi as runtimeOwnedExecutorMaterialization, Xi as executableAgentProfileSnapshot, Yi as unknownMaterializationReceipt, aa as createSandboxUsageLedger, ar as sandboxClientAsProvider, ca as mapSandboxEvent, ea as projectSandboxOutcome, er as LEAF_CONTINUATION_TASK, ia as createSandboxToolPartState, jt as createExecutor, la as mapSandboxToolEvent, oi as harnessInvocation, or as unavailablePauseMs, qr as toOtelAttributes, r as createSupervisor, ra as canonicalStreamEventFromSandboxEvent, sa as isSandboxTerminalEvent, sr as unavailableSignalOfFailure, ta as readSandboxOutcome, za as promptFromAgentTurnInput } from "./supervisor-UXgaPisu.js";
2
+ import { i as ConfigError, m as ValidationError, p as SessionMismatchError, r as BackendTransportError } from "./errors-DodWX-cb.js";
3
3
  import { a as concreteProfileModel, c as profileModelExecutionSettings, i as concreteModelId, l as profileProviderModel, o as enforceTokenLimits, s as profileBridgeWireModel, t as assertExecutableAgentProfile } from "./model-policy-BbSCSak0.js";
4
- import { agentProfileSchema, canonicalAgentProfileDigest, canonicalCandidateDigest, renderInputPartsAsText } from "@tangle-network/agent-interface";
5
- import { costForTokenPricing, makeProposalFinding, scoreKnowledgeReadiness } from "@tangle-network/agent-eval";
4
+ import { C as canonicalCandidateDigest$1, D as immutableCandidateValue } from "./workspace-archive-C9lgf77y.js";
5
+ import { agentProfileSchema, applyAgentProfileDiff, canonicalAgentProfileDigest, canonicalCandidateDigest, diffAgentProfiles, renderInputPartsAsText, sha256DigestSchema } from "@tangle-network/agent-interface";
6
+ import { CostAccountingIncompleteError, CostCeilingReachedError, canonicalJson, costForTokenPricing, costForUsage, makeProposalFinding, scoreKnowledgeReadiness } from "@tangle-network/agent-eval";
6
7
  import { createAgentRunOutcomeTracker } from "@tangle-network/sandbox/runtime";
7
8
  import { randomBytes, randomUUID } from "node:crypto";
9
+ import { mkdirSync, renameSync, writeFileSync } from "node:fs";
10
+ import { dirname, join } from "node:path";
8
11
  import { materializeProfile } from "@tangle-network/agent-profile-materialize";
12
+ import { ATTR, branchSpan } from "@tangle-network/agent-trace-contract";
13
+ import { redact } from "@tangle-network/agent-eval/traces";
9
14
  import { assertProposalFindings } from "@tangle-network/agent-eval/analyst";
15
+ import { SearchRecorder, aide, asha, campaignCellSearchResult, campaignScenarioIdentity, campaignSplitDigestFromIdentities, createRunCostLedger, fsCampaignStorage, isProposedCandidate, openSearchLedger, renderSearchSummary, resolveRunDir, runCampaign, runSearch, searchClaimReserveUsd, searchNodeId, searchProposalExecution, searchProposerView, searchReceiptAccounting } from "@tangle-network/agent-eval/campaign";
16
+ import { defineEvaluationClaim, summarizeEvaluationUnits } from "@tangle-network/agent-eval/experiment";
10
17
  import { harnessSystemPromptIntents as harnessSystemPromptIntents$1 } from "@tangle-network/agent-interface/harness-capabilities";
11
18
  //#region src/sessions.ts
12
19
  /**
@@ -1181,6 +1188,15 @@ const strategyAuthorMethod = [
1181
1188
  " comment at the top of the module — the holdout verdict will be read against it."
1182
1189
  ].join("\n");
1183
1190
  //#endregion
1191
+ //#region src/improvement/improve-result.ts
1192
+ function copyImproveCost(cost) {
1193
+ return {
1194
+ totalCostUsd: cost.totalCostUsd,
1195
+ accountingComplete: cost.accountingComplete,
1196
+ incompleteReasons: [...cost.incompleteReasons]
1197
+ };
1198
+ }
1199
+ //#endregion
1184
1200
  //#region src/runtime/profile-chat-client.ts
1185
1201
  /** Profile-exact adapter for packages that consume agent-eval's ChatClient contract.
1186
1202
  * Every call still enters Runtime through createExecutor -> streamAgentTurn, and every
@@ -1552,7 +1568,7 @@ var ObservationError = class extends Error {
1552
1568
  }
1553
1569
  };
1554
1570
  function validateUsage(usage) {
1555
- if (!Number.isSafeInteger(usage.input) || usage.input < 0 || !Number.isSafeInteger(usage.output) || usage.output < 0 || typeof usage.known !== "boolean") throw new TypeError("observation usage requires nonnegative safe integer subtotals and explicit known status");
1571
+ if (!Number.isSafeInteger(usage.input) || usage.input < 0 || !Number.isSafeInteger(usage.output) || usage.output < 0 || typeof usage.known !== "boolean" || usage.costUsd !== void 0 && !(Number.isFinite(usage.costUsd) && usage.costUsd >= 0)) throw new TypeError("observation usage requires nonnegative safe integer subtotals, explicit known status, and a finite nonnegative costUsd when present");
1556
1572
  }
1557
1573
  /** Compact the trace into the lines the observer reasons over — tool calls,
1558
1574
  * errors, and statuses, in order. Keeps the model call bounded + grounded. */
@@ -1672,7 +1688,8 @@ async function analyzeWithProfile(input, opts) {
1672
1688
  const usage = {
1673
1689
  input: inputTokens ?? 0,
1674
1690
  output: outputTokens ?? 0,
1675
- known: res.usage?.captured !== false && typeof inputTokens === "number" && typeof outputTokens === "number"
1691
+ known: res.usage?.captured !== false && typeof inputTokens === "number" && typeof outputTokens === "number",
1692
+ ...typeof res.costUsd === "number" ? { costUsd: res.costUsd } : {}
1676
1693
  };
1677
1694
  validateUsage(usage);
1678
1695
  try {
@@ -1839,7 +1856,18 @@ async function runShot(surface, _task, handle, tools, messages, opts, profileOve
1839
1856
  input: turn.usage.input,
1840
1857
  output: turn.usage.output
1841
1858
  },
1842
- ...turn.usage.tokensKnown === false ? { tokensKnown: false } : {}
1859
+ ...turn.usage.tokensKnown === false ? { tokensKnown: false } : {},
1860
+ ...billedSpend(turn.usage.usdKnown === false ? void 0 : turn.usage.costUsd)
1861
+ };
1862
+ }
1863
+ /** Provider-billed dollars of one call, or unknown when it billed none: never a fabricated 0. */
1864
+ function billedSpend(costUsd) {
1865
+ return typeof costUsd === "number" && Number.isFinite(costUsd) && costUsd >= 0 ? {
1866
+ usd: costUsd,
1867
+ usdKnown: true
1868
+ } : {
1869
+ usd: 0,
1870
+ usdKnown: false
1843
1871
  };
1844
1872
  }
1845
1873
  /** The firewall's input shape: the trajectory as compacted text — calls, results,
@@ -1896,7 +1924,8 @@ async function consultAnalyst(task, messages, instruction, opts) {
1896
1924
  input: input ?? 0,
1897
1925
  output: output ?? 0
1898
1926
  },
1899
- ...tokensKnown ? {} : { tokensKnown: false }
1927
+ ...tokensKnown ? {} : { tokensKnown: false },
1928
+ ...billedSpend(res.costUsd)
1900
1929
  };
1901
1930
  }
1902
1931
  async function analyze(task, messages, opts) {
@@ -1927,7 +1956,8 @@ async function analyze(task, messages, opts) {
1927
1956
  input: obs.usage.input,
1928
1957
  output: obs.usage.output
1929
1958
  },
1930
- ...obs.usage.known ? {} : { tokensKnown: false }
1959
+ ...obs.usage.known ? {} : { tokensKnown: false },
1960
+ ...billedSpend(obs.usage.costUsd)
1931
1961
  };
1932
1962
  }
1933
1963
  async function renderCorpusReadback(opts) {
@@ -2007,8 +2037,8 @@ function shotExecutor(surface, opts) {
2007
2037
  iterations: shot.completions,
2008
2038
  tokens: shot.tokens,
2009
2039
  ...shot.tokensKnown === false ? { tokensKnown: false } : {},
2010
- usd: 0,
2011
- usdKnown: false,
2040
+ usd: shot.usd,
2041
+ usdKnown: shot.usdKnown,
2012
2042
  ms: 0
2013
2043
  }
2014
2044
  };
@@ -2030,7 +2060,7 @@ function analystExecutor(opts) {
2030
2060
  runtime: "agentic-analyst",
2031
2061
  async execute(task) {
2032
2062
  const t = task;
2033
- const { steer, tokens, tokensKnown } = t.rawInstruction ? await consultAnalyst(t.task, t.messages, t.rawInstruction, opts) : await analyze(t.task, t.messages, opts);
2063
+ const { steer, tokens, tokensKnown, usd, usdKnown } = t.rawInstruction ? await consultAnalyst(t.task, t.messages, t.rawInstruction, opts) : await analyze(t.task, t.messages, opts);
2034
2064
  artifact = {
2035
2065
  outRef: `analyst:${steer.length}`,
2036
2066
  out: steer,
@@ -2038,8 +2068,8 @@ function analystExecutor(opts) {
2038
2068
  iterations: 1,
2039
2069
  tokens,
2040
2070
  ...tokensKnown === false ? { tokensKnown: false } : {},
2041
- usd: 0,
2042
- usdKnown: false,
2071
+ usd,
2072
+ usdKnown,
2043
2073
  ms: 0
2044
2074
  }
2045
2075
  };
@@ -2870,6 +2900,561 @@ function structuralRollout(config = {}) {
2870
2900
  });
2871
2901
  }
2872
2902
  //#endregion
2903
+ //#region src/improvement/rollout-policy.ts
2904
+ /** The profile extensions namespace the policy persists under. */
2905
+ const ROLLOUT_POLICY_EXTENSION = "structural-rollout";
2906
+ const isBoundedInt = (v, min) => typeof v === "number" && Number.isInteger(v) && v >= min;
2907
+ /** Parse a serialized policy surface. Returns `undefined` for non-strings,
2908
+ * malformed JSON, or values outside the policy invariants. Unknown fields are
2909
+ * dropped; supported optional fields are preserved. */
2910
+ function parseRolloutPolicy(surface) {
2911
+ if (typeof surface !== "string" || surface.trim().length === 0) return void 0;
2912
+ let raw;
2913
+ try {
2914
+ raw = JSON.parse(surface);
2915
+ } catch {
2916
+ return;
2917
+ }
2918
+ return normalizeRolloutPolicy(raw);
2919
+ }
2920
+ /** Normalize an untyped policy bag (a parsed surface or a profile extension) into
2921
+ * a full `StructuralRolloutPolicy`, defaults merged. Returns `undefined` when any
2922
+ * present dial violates the policy invariants (mirrors `resolvePolicy`: integer
2923
+ * k ≥ 1, repairRounds ≥ 0, testgen ≥ 0) — a corrupt config must read as "not
2924
+ * configured", never as a fabricated recipe. */
2925
+ function normalizeRolloutPolicy(raw) {
2926
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return void 0;
2927
+ const bag = raw;
2928
+ const k = bag.k ?? defaultStructuralRolloutPolicy.k;
2929
+ const repairRounds = bag.repairRounds ?? defaultStructuralRolloutPolicy.repairRounds;
2930
+ const testgen = bag.testgen ?? defaultStructuralRolloutPolicy.testgen;
2931
+ if (!isBoundedInt(k, 1) || !isBoundedInt(repairRounds, 0) || !isBoundedInt(testgen, 0)) return;
2932
+ return {
2933
+ k,
2934
+ repairRounds,
2935
+ testgen,
2936
+ ...typeof bag.diverse === "boolean" ? { diverse: bag.diverse } : {}
2937
+ };
2938
+ }
2939
+ /** Stable serialization with fixed field order. */
2940
+ function serializeRolloutPolicy(policy) {
2941
+ return JSON.stringify({
2942
+ k: policy.k,
2943
+ repairRounds: policy.repairRounds,
2944
+ testgen: policy.testgen,
2945
+ ...policy.diverse !== void 0 ? { diverse: policy.diverse } : {}
2946
+ });
2947
+ }
2948
+ /** Read the persisted policy off the profile. `undefined` when the profile does
2949
+ * not opt into structural rollout. */
2950
+ function structuralRolloutPolicyFromProfile(profile) {
2951
+ const bag = profile.extensions?.[ROLLOUT_POLICY_EXTENSION];
2952
+ if (bag === void 0) return void 0;
2953
+ return normalizeRolloutPolicy(bag);
2954
+ }
2955
+ /** Persist a detached policy under the profile extension without mutating the input. */
2956
+ function applyRolloutPolicyToProfile(profile, policy) {
2957
+ const candidate = structuredClone(profile);
2958
+ const bag = {
2959
+ k: policy.k,
2960
+ repairRounds: policy.repairRounds,
2961
+ testgen: policy.testgen,
2962
+ ...policy.diverse !== void 0 ? { diverse: policy.diverse } : {}
2963
+ };
2964
+ return {
2965
+ ...candidate,
2966
+ extensions: {
2967
+ ...candidate.extensions,
2968
+ [ROLLOUT_POLICY_EXTENSION]: bag
2969
+ }
2970
+ };
2971
+ }
2972
+ //#endregion
2973
+ //#region src/improvement/profile-surface.ts
2974
+ /** Extract the baseline optimized by a method and retain its structured value
2975
+ * so external optimizers can inspect it for private fields before serialization. */
2976
+ function prepareProfileSurface(profile, surface, skills, profileComponents) {
2977
+ switch (surface) {
2978
+ case "prompt": return {
2979
+ surface: profile.prompt?.systemPrompt ?? "",
2980
+ value: profile.prompt?.systemPrompt ?? ""
2981
+ };
2982
+ case "skills": {
2983
+ const value = inlineSkill(profile, skills).content;
2984
+ return {
2985
+ surface: value,
2986
+ value
2987
+ };
2988
+ }
2989
+ case "tools": {
2990
+ const value = profile.tools ?? {};
2991
+ return {
2992
+ surface: canonicalJson(value),
2993
+ value
2994
+ };
2995
+ }
2996
+ case "mcp": {
2997
+ const value = profile.mcp ?? {};
2998
+ return {
2999
+ surface: canonicalJson(value),
3000
+ value
3001
+ };
3002
+ }
3003
+ case "hooks": {
3004
+ const value = profile.hooks ?? {};
3005
+ return {
3006
+ surface: canonicalJson(value),
3007
+ value
3008
+ };
3009
+ }
3010
+ case "subagents": {
3011
+ const value = profile.subagents ?? {};
3012
+ return {
3013
+ surface: canonicalJson(value),
3014
+ value
3015
+ };
3016
+ }
3017
+ case "agent-profile":
3018
+ if (profileComponents) {
3019
+ if (profileComponents.encoding !== void 0 && profileComponents.encoding !== "components" && profileComponents.encoding !== "json") throw new ConfigError("improve(): profileComponents.encoding must be components or json");
3020
+ const value = profileComponents.read(profile);
3021
+ const components = componentSurface(value, "profileComponents.read");
3022
+ return {
3023
+ surface: profileComponents.encoding === "json" ? canonicalJson(components.components) : components,
3024
+ value
3025
+ };
3026
+ }
3027
+ return {
3028
+ surface: canonicalJson(profile),
3029
+ value: profile
3030
+ };
3031
+ case "memory": {
3032
+ const value = profileInstructions(profile);
3033
+ return {
3034
+ surface: value,
3035
+ value
3036
+ };
3037
+ }
3038
+ case "rollout-policy": {
3039
+ const policy = structuralRolloutPolicyFromProfile(profile);
3040
+ return {
3041
+ surface: policy ? serializeRolloutPolicy(policy) : "",
3042
+ value: policy ?? null
3043
+ };
3044
+ }
3045
+ case "code": throw new ConfigError("improve(): code requires the isolated baseline created from opts.code.repoRoot");
3046
+ }
3047
+ }
3048
+ function isCodeSurface(surface) {
3049
+ return typeof surface === "object" && surface !== null && surface.kind === "code";
3050
+ }
3051
+ function isComponentSurface(surface) {
3052
+ return typeof surface === "object" && surface !== null && surface.kind === "components";
3053
+ }
3054
+ function componentSurface(components, source) {
3055
+ const entries = validateComponents(components, source);
3056
+ return immutableCandidateValue({
3057
+ kind: "components",
3058
+ components: Object.fromEntries(entries)
3059
+ });
3060
+ }
3061
+ function validateComponents(components, source) {
3062
+ if (typeof components !== "object" || components === null || Array.isArray(components)) throw new ConfigError(`improve(): ${source} must return a component record`);
3063
+ const entries = Object.entries(components);
3064
+ if (entries.length === 0) throw new ConfigError(`improve(): ${source} must return at least one component`);
3065
+ for (const [name, value] of entries) if (!name || name.trim() !== name || typeof value !== "string") throw new ConfigError(`improve(): ${source} must return trimmed component names with string values`);
3066
+ return entries;
3067
+ }
3068
+ /** Parse a JSON winner surface with a typed, contextual error. */
3069
+ function parseWinnerJson(winner, surface) {
3070
+ try {
3071
+ return JSON.parse(winner);
3072
+ } catch (cause) {
3073
+ throw new ConfigError(`improve(): the '${surface}' candidate is not valid JSON, so it cannot form a profile candidate: ${cause.message}`);
3074
+ }
3075
+ }
3076
+ function assertCandidateSurfaceKind(surface, baseline, winner) {
3077
+ if (surface === "code") {
3078
+ if (isCodeSurface(winner)) return;
3079
+ throw new ConfigError(`improve(): the '${surface}' candidate returned an incompatible surface value`);
3080
+ }
3081
+ if (typeof baseline === "string") {
3082
+ if (typeof winner === "string") return;
3083
+ throw new ConfigError(`improve(): the '${surface}' candidate changed from a text surface to an incompatible surface value`);
3084
+ }
3085
+ if (!isComponentSurface(baseline) || !isComponentSurface(winner)) throw new ConfigError(`improve(): the '${surface}' candidate returned an incompatible surface value`);
3086
+ validateComponents(winner.components, `the '${surface}' candidate`);
3087
+ const baselineNames = Object.keys(baseline.components).sort();
3088
+ const winnerNames = Object.keys(winner.components).sort();
3089
+ if (baselineNames.length !== winnerNames.length || baselineNames.some((name, index) => name !== winnerNames[index])) throw new ConfigError(`improve(): the '${surface}' candidate must preserve the exact component names`);
3090
+ }
3091
+ /** Materialize a detached profile candidate without changing the baseline. */
3092
+ function materializeImprovementProfileCandidate(profile, surface, winner, skills, profileComponents) {
3093
+ let candidate;
3094
+ if (isComponentSurface(winner)) {
3095
+ if (surface !== "agent-profile" || !profileComponents) throw new ConfigError(`improve(): the '${surface}' candidate has no profile component mapping`);
3096
+ const winnerComponents = immutableCandidateValue({ ...winner.components });
3097
+ const validated = parseMaterializedProfile(profileComponents.apply(profile, winnerComponents), surface);
3098
+ const materializedComponents = Object.fromEntries(validateComponents(profileComponents.read(validated), "profileComponents.read after apply"));
3099
+ const names = Object.keys(winnerComponents);
3100
+ if (names.length !== Object.keys(materializedComponents).length || names.some((name) => materializedComponents[name] !== winnerComponents[name])) throw new ConfigError("improve(): profileComponents.apply must round-trip every winning component exactly");
3101
+ return validated;
3102
+ }
3103
+ if (typeof winner !== "string") throw new ConfigError(`improve(): the '${surface}' candidate cannot form an AgentProfile`);
3104
+ switch (surface) {
3105
+ case "prompt":
3106
+ candidate = {
3107
+ ...profile,
3108
+ prompt: {
3109
+ ...profile.prompt,
3110
+ systemPrompt: winner
3111
+ }
3112
+ };
3113
+ break;
3114
+ case "skills": {
3115
+ const selectedSkill = inlineSkill(profile, skills);
3116
+ candidate = {
3117
+ ...profile,
3118
+ resources: {
3119
+ ...profile.resources,
3120
+ skills: profile.resources?.skills?.map((resource) => resource === selectedSkill ? {
3121
+ ...resource,
3122
+ content: winner
3123
+ } : resource)
3124
+ }
3125
+ };
3126
+ break;
3127
+ }
3128
+ case "tools":
3129
+ candidate = {
3130
+ ...profile,
3131
+ tools: parseWinnerJson(winner, surface)
3132
+ };
3133
+ break;
3134
+ case "mcp":
3135
+ candidate = {
3136
+ ...profile,
3137
+ mcp: parseWinnerJson(winner, surface)
3138
+ };
3139
+ break;
3140
+ case "hooks":
3141
+ candidate = {
3142
+ ...profile,
3143
+ hooks: parseWinnerJson(winner, surface)
3144
+ };
3145
+ break;
3146
+ case "subagents":
3147
+ candidate = {
3148
+ ...profile,
3149
+ subagents: parseWinnerJson(winner, surface)
3150
+ };
3151
+ break;
3152
+ case "agent-profile":
3153
+ candidate = parseWinnerJson(winner, surface);
3154
+ break;
3155
+ case "memory":
3156
+ candidate = {
3157
+ ...profile,
3158
+ resources: {
3159
+ ...profile.resources,
3160
+ instructions: replaceProfileInstructions(profile, winner)
3161
+ }
3162
+ };
3163
+ break;
3164
+ case "rollout-policy": {
3165
+ const policy = normalizeRolloutPolicy(parseWinnerJson(winner, surface));
3166
+ if (!policy) throw new ConfigError(`improve(): the shipped 'rollout-policy' winner is not a valid StructuralRolloutPolicy (integer k >= 1, repairRounds >= 0, testgen >= 0), so it cannot be applied: ${winner}`);
3167
+ candidate = applyRolloutPolicyToProfile(profile, policy);
3168
+ break;
3169
+ }
3170
+ }
3171
+ return parseMaterializedProfile(candidate, surface);
3172
+ }
3173
+ function parseMaterializedProfile(candidate, surface) {
3174
+ const parsed = agentProfileSchema.safeParse(candidate);
3175
+ if (!parsed.success) throw new ConfigError(`improve(): the '${surface}' candidate does not produce a valid AgentProfile: ${parsed.error.message}`);
3176
+ return immutableCandidateValue(parsed.data);
3177
+ }
3178
+ function createProfileCandidateMaterializer(profile, surface, baselineSurface, skills, profileComponents) {
3179
+ const decode = (candidate) => {
3180
+ if (profileComponents?.encoding !== "json") return candidate;
3181
+ if (typeof candidate !== "string") throw new ConfigError("improve(): JSON profile components require a text surface");
3182
+ return componentSurface(parseWinnerJson(candidate, surface), "JSON profile components");
3183
+ };
3184
+ const decodedBaseline = decode(baselineSurface);
3185
+ const baselineDigest = canonicalCandidateDigest$1(baselineSurface);
3186
+ if (profileComponents) {
3187
+ if (canonicalAgentProfileDigest(materializeImprovementProfileCandidate(profile, surface, decodedBaseline, skills, profileComponents)) !== canonicalAgentProfileDigest(profile)) throw new ConfigError("improve(): profileComponents.apply(profile, profileComponents.read(profile)) must reproduce the complete baseline profile exactly");
3188
+ }
3189
+ const candidates = /* @__PURE__ */ new Map([[baselineDigest, profile]]);
3190
+ return (candidateSurface) => {
3191
+ assertCandidateSurfaceKind(surface, baselineSurface, candidateSurface);
3192
+ const decodedCandidate = decode(candidateSurface);
3193
+ assertCandidateSurfaceKind(surface, decodedBaseline, decodedCandidate);
3194
+ const digest = canonicalCandidateDigest$1(candidateSurface);
3195
+ const existing = candidates.get(digest);
3196
+ if (existing) return existing;
3197
+ const candidate = materializeImprovementProfileCandidate(profile, surface, immutableCandidateValue(decodedCandidate), skills, profileComponents);
3198
+ candidates.set(digest, candidate);
3199
+ return candidate;
3200
+ };
3201
+ }
3202
+ function inlineSkill(profile, options) {
3203
+ const resourceName = options?.resourceName.trim();
3204
+ if (!resourceName) throw new ConfigError("improve(): surface 'skills' requires opts.skills.resourceName for one inline profile skill");
3205
+ assertFailClosedResources(profile, "skills");
3206
+ const matches = (profile.resources?.skills ?? []).filter((resource) => resource.name === resourceName);
3207
+ if (matches.length !== 1 || matches[0]?.kind !== "inline") throw new ConfigError(`improve(): skill '${resourceName}' must identify exactly one inline profile resource`);
3208
+ return matches[0];
3209
+ }
3210
+ function profileInstructions(profile) {
3211
+ assertFailClosedResources(profile, "memory");
3212
+ const instructions = profile.resources?.instructions;
3213
+ if (instructions === void 0) return "";
3214
+ if (typeof instructions === "string") return instructions;
3215
+ if (instructions.kind === "inline") return instructions.content;
3216
+ throw new ConfigError("improve(): surface 'memory' requires inline profile instructions so candidate bytes are exact");
3217
+ }
3218
+ function replaceProfileInstructions(profile, content) {
3219
+ const instructions = profile.resources?.instructions;
3220
+ if (typeof instructions !== "object") return content;
3221
+ if (instructions.kind !== "inline") throw new ConfigError("improve(): surface 'memory' requires inline profile instructions so candidate bytes are exact");
3222
+ return {
3223
+ ...instructions,
3224
+ content
3225
+ };
3226
+ }
3227
+ function assertFailClosedResources(profile, surface) {
3228
+ if (profile.resources?.failOnError !== true) throw new ConfigError(`improve(): surface '${surface}' requires profile.resources.failOnError: true`);
3229
+ }
3230
+ //#endregion
3231
+ //#region src/improvement/candidate-validation.ts
3232
+ /** One spelling of the execution-identity rule for optimization, training, and the harness. */
3233
+ function parseExecutionRef(value, label) {
3234
+ const parsed = sha256DigestSchema.safeParse(value);
3235
+ if (!parsed.success) throw new ConfigError(`${label}: executionRef must be a lowercase sha256:<64 hex> digest`);
3236
+ return parsed.data;
3237
+ }
3238
+ /** Validate the callback itself before any optimizer, trainer, or candidate work starts. */
3239
+ function assertCandidateValidator(validator) {
3240
+ if (validator !== void 0 && typeof validator !== "function") throw new ConfigError("validateCandidate must be a function when present");
3241
+ }
3242
+ /** A validator accepts synchronously by returning void, or rejects by throwing. */
3243
+ function validateProfileCandidate(validator, input) {
3244
+ assertCandidateValidator(validator);
3245
+ const result = validator?.(Object.freeze(input));
3246
+ if (result !== void 0) {
3247
+ Promise.resolve(result).catch(() => {});
3248
+ throw new ConfigError("candidate validators must return void synchronously or throw");
3249
+ }
3250
+ }
3251
+ /**
3252
+ * Refuse exact held-out content digests already declared in this profile's training lineage.
3253
+ * Both training and trainer-visible validation rows are exposure. This is an exact
3254
+ * provenance check, not fuzzy decontamination or proof that undeclared training was fresh.
3255
+ */
3256
+ function assertProfileTrainingIsHeldOut(profile, heldOutDigests) {
3257
+ const training = profile.metadata?.training;
3258
+ if (!training) return;
3259
+ for (const receipt of [training.receipt, ...training.ancestors]) if (receipt.dataset.tasks.some((task) => heldOutDigests.has(task.contentDigest))) throw new ConfigError("known training exposure overlaps held-out evaluation");
3260
+ }
3261
+ /**
3262
+ * JSON paths of credential and private values in candidate content, found by
3263
+ * the redaction core, which names each value it would change. A candidate that
3264
+ * leaves Runtime (an external optimizer, a search ledger) is refused on any.
3265
+ */
3266
+ function privateValuePaths(values) {
3267
+ return [...new Set(values.flatMap((value) => redact(value).report.findings.map((finding) => jsonPathOf(finding.path))))];
3268
+ }
3269
+ /** `/remote/url` or `/tools/0/env` as `$.remote.url` or `$.tools[0].env`. */
3270
+ function jsonPathOf(pointer) {
3271
+ return pointer.split("/").slice(1).map((segment) => segment.replaceAll("~1", "/").replaceAll("~0", "~")).reduce((path, segment) => /^\d+$/.test(segment) ? `${path}[${segment}]` : `${path}.${segment}`, "$");
3272
+ }
3273
+ //#endregion
3274
+ //#region src/improvement/method-identity.ts
3275
+ function buildMethodEvaluationIdentity(input) {
3276
+ const optimizationReps = input.optimizationRunOptions?.reps ?? 1;
3277
+ const finalTestReps = input.reps ?? 1;
3278
+ const scenarioPartitions = immutableCandidateValue({
3279
+ train: input.trainScenarios.map(campaignScenarioIdentity),
3280
+ selection: input.selectionScenarios.map(campaignScenarioIdentity),
3281
+ finalTest: input.testScenarios.map(campaignScenarioIdentity),
3282
+ optimizationReps,
3283
+ finalTestReps
3284
+ });
3285
+ const developmentSplitDigest = canonicalCandidateDigest$1({
3286
+ train: campaignSplitDigestFromIdentities(scenarioPartitions.train, optimizationReps),
3287
+ selection: campaignSplitDigestFromIdentities(scenarioPartitions.selection, optimizationReps)
3288
+ });
3289
+ const finalTestSplitDigest = campaignSplitDigestFromIdentities(scenarioPartitions.finalTest, finalTestReps);
3290
+ const judgeDescriptors = input.judges.map(judgeDescriptor);
3291
+ return {
3292
+ evaluationRef: canonicalCandidateDigest$1({
3293
+ executionRef: input.executionRef,
3294
+ baselineProfileDigest: input.baselineProfileDigest,
3295
+ coordinate: profileCoordinate(input.surface, input.baselineSurface, input.skills),
3296
+ candidateValidation: input.validateCandidate ? Function.prototype.toString.call(input.validateCandidate) : null,
3297
+ developmentSplitDigest,
3298
+ finalTestSplitDigest,
3299
+ findings: input.findings,
3300
+ judges: judgeDescriptors,
3301
+ run: {
3302
+ seed: input.seed ?? 42,
3303
+ finalReps: input.reps ?? 1,
3304
+ optimizationReps,
3305
+ costCeiling: input.costCeiling ?? null,
3306
+ resumable: input.optimizationRunOptions?.resumable ?? true,
3307
+ maxConcurrency: input.optimizationRunOptions?.maxConcurrency ?? 2,
3308
+ abortOnCellError: input.optimizationRunOptions?.abortOnCellError ?? false,
3309
+ dispatchTimeoutMs: input.optimizationRunOptions?.dispatchTimeoutMs ?? null,
3310
+ dispatchShutdownTimeoutMs: input.optimizationRunOptions?.dispatchShutdownTimeoutMs ?? 5e3,
3311
+ tracing: input.optimizationRunOptions?.tracing ?? "on",
3312
+ expectUsage: input.optimizationRunOptions?.expectUsage ?? "warn",
3313
+ captureSource: input.optimizationRunOptions?.captureSource ?? null,
3314
+ captureSourceVersionHash: input.optimizationRunOptions?.captureSourceVersionHash ?? null
3315
+ }
3316
+ }),
3317
+ developmentSplitDigest,
3318
+ finalTestSplitDigest,
3319
+ scenarioPartitions,
3320
+ judgeDescriptors
3321
+ };
3322
+ }
3323
+ function profileCoordinate(surface, baselineSurface, skills) {
3324
+ return {
3325
+ surface,
3326
+ resourceName: surface === "skills" ? skills?.resourceName.trim() ?? null : null,
3327
+ componentNames: typeof baselineSurface === "object" && baselineSurface !== null && baselineSurface.kind === "components" ? Object.keys(baselineSurface.components).sort() : []
3328
+ };
3329
+ }
3330
+ function judgeDescriptor(judge) {
3331
+ return {
3332
+ name: judge.name,
3333
+ dimensions: judge.dimensions.map((dimension) => ({ ...dimension })),
3334
+ declaredVersion: judge.judgeVersion ?? null,
3335
+ scoreImplementation: Function.prototype.toString.call(judge.score),
3336
+ appliesToImplementation: judge.appliesTo ? Function.prototype.toString.call(judge.appliesTo) : null
3337
+ };
3338
+ }
3339
+ //#endregion
3340
+ //#region src/improvement/profile-improvement.ts
3341
+ /**
3342
+ * What every profile improvement prepares before any optimizer or search runs:
3343
+ * the exact surface and its baseline, the evaluation identity, identified
3344
+ * judges, the identities a search ledger records, and one materializer that
3345
+ * admits a candidate only after the held-out and caller checks. `improve()`
3346
+ * with an external method and with `searchMethod` share it, so a candidate is
3347
+ * materialized and admitted the same way on both paths.
3348
+ */
3349
+ function prepareProfileImprovement(profile, input) {
3350
+ const { surface = "prompt", validateCandidate, skills, profileComponents, minimumLift = 0 } = input;
3351
+ assertCandidateValidator(validateCandidate);
3352
+ if (!Number.isFinite(minimumLift) || minimumLift < 0) throw new ConfigError("improve(): minimumLift must be a finite number greater than or equal to 0");
3353
+ if (profileComponents && surface !== "agent-profile") throw new ConfigError("improve(): profileComponents is valid only with surface 'agent-profile'");
3354
+ if (input.subject !== void 0 && (typeof input.subject !== "string" || !input.subject.trim() || input.subject !== input.subject.trim())) throw new ConfigError("improve(): subject must be a trimmed non-empty string");
3355
+ const executionRef = parseExecutionRef(input.executionRef, "improve()");
3356
+ const findings = immutableCandidateValue([...assertProposalFindings(input.findings ?? [], "improve() method findings")]);
3357
+ const preparedSurface = prepareProfileSurface(profile, surface, skills, profileComponents);
3358
+ const baselineSurface = preparedSurface.surface;
3359
+ const baselineValue = immutableCandidateValue(preparedSurface.value);
3360
+ const baselineProfileDigest = canonicalAgentProfileDigest(profile);
3361
+ const identity = buildMethodEvaluationIdentity({
3362
+ executionRef,
3363
+ baselineProfileDigest,
3364
+ baselineSurface,
3365
+ surface,
3366
+ skills,
3367
+ validateCandidate,
3368
+ findings,
3369
+ trainScenarios: input.trainScenarios,
3370
+ selectionScenarios: input.selectionScenarios,
3371
+ testScenarios: input.testScenarios,
3372
+ judges: input.judges,
3373
+ seed: input.seed,
3374
+ reps: input.reps,
3375
+ costCeiling: input.costCeiling,
3376
+ optimizationRunOptions: input.optimizationRunOptions
3377
+ });
3378
+ const judges = input.judges.map((judge, index) => Object.freeze({
3379
+ ...judge,
3380
+ judgeVersion: canonicalCandidateDigest$1({
3381
+ evaluationRef: identity.evaluationRef,
3382
+ descriptor: identity.judgeDescriptors[index]
3383
+ })
3384
+ }));
3385
+ const rawMaterializeProfile = createProfileCandidateMaterializer(profile, surface, baselineSurface, skills, profileComponents);
3386
+ const baselineSurfaceDigest = canonicalCandidateDigest$1(baselineSurface);
3387
+ const heldOutDigests = new Set(identity.scenarioPartitions.finalTest.map((task) => task.scenarioDigest));
3388
+ const validatedCandidates = /* @__PURE__ */ new Set();
3389
+ const validateMaterialized = (validator, candidate, candidateSurface, isBaseline) => {
3390
+ const prepared = prepareProfileSurface(candidate, surface, skills, profileComponents);
3391
+ validateProfileCandidate(validator, {
3392
+ profile: candidate,
3393
+ surface,
3394
+ candidateSurface,
3395
+ value: immutableCandidateValue(prepared.value),
3396
+ isBaseline
3397
+ });
3398
+ };
3399
+ const admitCandidate = (candidate, candidateSurface) => {
3400
+ const candidateDigest = canonicalCandidateDigest$1(candidateSurface);
3401
+ if (validatedCandidates.has(candidateDigest)) return;
3402
+ assertProfileTrainingIsHeldOut(candidate, heldOutDigests);
3403
+ validateMaterialized(validateCandidate, candidate, immutableCandidateValue(candidateSurface), candidateDigest === baselineSurfaceDigest);
3404
+ validatedCandidates.add(candidateDigest);
3405
+ };
3406
+ const materializeProfile = (candidateSurface) => {
3407
+ const candidate = rawMaterializeProfile(candidateSurface);
3408
+ admitCandidate(candidate, candidateSurface);
3409
+ return candidate;
3410
+ };
3411
+ materializeProfile(baselineSurface);
3412
+ return {
3413
+ profile,
3414
+ surface,
3415
+ executionRef,
3416
+ findings,
3417
+ minimumLift,
3418
+ baselineSurface,
3419
+ baselineValue,
3420
+ baselineProfileDigest,
3421
+ identity,
3422
+ invocationId: `runtime-optimization:${randomUUID()}`,
3423
+ judges,
3424
+ searchIdentity: Object.freeze({
3425
+ subject: input.subject ?? profile.name ?? "agent-profile",
3426
+ agent: {
3427
+ uri: "agent-runtime:improve-execution-ref",
3428
+ revision: executionRef
3429
+ },
3430
+ judge: {
3431
+ uri: "agent-runtime:improve-judges",
3432
+ revision: canonicalCandidateDigest$1(identity.judgeDescriptors)
3433
+ },
3434
+ model: profileModel(profile)
3435
+ }),
3436
+ surfaceOf: (candidate) => prepareProfileSurface(candidate, surface, skills, profileComponents).surface,
3437
+ materializeCandidate: rawMaterializeProfile,
3438
+ admitCandidate,
3439
+ materializeProfile,
3440
+ validateMaterialized
3441
+ };
3442
+ }
3443
+ /** The profile's model hint as a moving alias; each cell records what it resolved. */
3444
+ function profileModel(profile) {
3445
+ const hint = profile.model?.default;
3446
+ if (!hint) return {
3447
+ provider: "unspecified",
3448
+ alias: "unspecified",
3449
+ unknown: "the profile names no model; each cell records the model it resolved"
3450
+ };
3451
+ return {
3452
+ provider: profile.model?.provider ?? "unspecified",
3453
+ alias: hint,
3454
+ unknown: "the profile names a model hint, not a snapshot; each cell records the model it resolved"
3455
+ };
3456
+ }
3457
+ //#endregion
2873
3458
  //#region src/runtime/shared-box.ts
2874
3459
  /**
2875
3460
  * Shared-box placement: many harness workers in one Sandbox box, each as its own process.
@@ -3818,6 +4403,1204 @@ function errorMessage(error) {
3818
4403
  return "opencode reported an error";
3819
4404
  }
3820
4405
  //#endregion
3821
- export { defaultAnalystInstruction as A, createSandboxPromptBackend as B, defineStrategy as C, sample as D, runAgentic as E, optimizerMethod as F, startOrResumeRuntimeSession as G, InMemoryRuntimeSessionStore as H, strategyAuthorMethod as I, touchSession as K, collectAgentTurn as L, renderReport as M, profileChatClient as N, sampleThenRefine as O, profileOptimizerModelCall as P, streamAgentTurn as R, breadthStrategy as S, refine as T, newRuntimeSession as U, normalizeBackendStreamEvent as V, nowIso as W, sandboxCheckRunner as _, sharedBoxPlacement as a, visibleCheckScore as b, canDisplace as c, defaultExtractCandidate as d, defaultStructuralRolloutPolicy as f, resolveEntrySymbol as g, officialChecksFromMeta as h, isTransientSandboxFailure as i, observe as j, ObservationError as k, compareCheckOutcomes as l, modelAuthoredChecks as m, DEFAULT_SHARED_BOX_WORKERS as n, sharedBoxRefusal as o, filterAuthoredAsserts as p, ROUTER_CLIENT_HEADER as r, sharedWorkerClientName as s, DEFAULT_SHARED_BOX_RESOURCES as t, composeCheckSources as u, selectBestIndex as v, depthStrategy as w, adaptiveRefine as x, structuralRollout as y, createIterableBackend as z };
4406
+ //#region src/improvement/search-executor.ts
4407
+ /**
4408
+ * The search kernel's executor port for cells Runtime runs.
4409
+ *
4410
+ * A lane is a pool of execution slots with one cost rule: a shared box, dedicated
4411
+ * environments, subscription seats, or the router. The kernel places each cell on a lane and
4412
+ * bounds each lane's running cells by its capacity. This executor adds what one search cannot
4413
+ * see or enforce on its own:
4414
+ *
4415
+ * - Fleet slots. A `WorkerSlots` allocator shared by concurrent searches bounds working cells
4416
+ * across all of them. A cell waits for a slot, and the wait is its `queueMs`.
4417
+ * - Fleet dollars. On a hard lane a cell holds its enforced maximum as a `BudgetPool` ticket
4418
+ * before it starts, waits while open tickets could return enough, and settles the ticket
4419
+ * with its measured spend. Estimate lanes take no ticket: they cannot bound a cell, and an
4420
+ * unknown cost would close a capped pool for every search that shares it.
4421
+ * - Hard caps. On a hard lane every paid call of the cell, the agent's and the judges', holds
4422
+ * its maximum against the lane's `cellUsd` and is refused when it would pass it, so the
4423
+ * kernel's hard reservation is a bound and not a hope.
4424
+ * - Adoption. A finished attempt is written under its run id before the kernel sees it, so a
4425
+ * kernel that restarts adopts the attempt instead of running it again. The run id is stable
4426
+ * across restarts; an agent that runs remote work keys it by `ctx.search.runId`, so a lost
4427
+ * response is fetched again rather than executed again.
4428
+ * - Accounting. Every paid call is tagged with its search and attempt, and an attempt's cost is
4429
+ * every call tagged with its run id, including calls a process that ended made for it. A
4430
+ * reopened search settles those interrupted calls first: from the provider through the lane's
4431
+ * `recoverReceipt`, else with an unknown cost, never as free.
4432
+ * - Environment faults. A `SearchEnvironmentFault`, or a platform failure a repeated request
4433
+ * can change, settles `errored` and retryable, and the kernel runs a fresh attempt.
4434
+ * - Traces. Each attempt is one trace whose root span carries `agent.branch.id` = the node id.
4435
+ * The spans the attempt's exporter wrote and dropped go into the cell's `traceRef`.
4436
+ */
4437
+ function laneReceipts(options) {
4438
+ return options.recoverReceipt ? { recoverReceipt: options.recoverReceipt } : {};
4439
+ }
4440
+ const acceptEveryProfile = () => void 0;
4441
+ function laneName(name, fallback) {
4442
+ const resolved = name ?? fallback;
4443
+ if (!/^[A-Za-z0-9._-]{1,64}$/u.test(resolved)) throw new ConfigError(`search lane name '${resolved}' must be 1-64 of [A-Za-z0-9._-]`);
4444
+ return resolved;
4445
+ }
4446
+ function positiveInteger(value, name) {
4447
+ if (!Number.isSafeInteger(value) || value < 1) throw new ConfigError(`${name} must be a positive integer`);
4448
+ return value;
4449
+ }
4450
+ function dollars(value, name) {
4451
+ if (!Number.isFinite(value) || value < 0) throw new ConfigError(`${name} must be a finite non-negative number of dollars`);
4452
+ return value;
4453
+ }
4454
+ /**
4455
+ * Cells as workers packed into shared Sandbox boxes, `workersPerBox` to a box.
4456
+ *
4457
+ * Capacity is `boxes × workersPerBox`. The workers of one box share its router key, which caps
4458
+ * no single worker, so the lane holds an estimate (`cellUsd` is the prior until 20 cells settle).
4459
+ * A profile the placement refuses (a repository writer, a replaced system prompt, MCP servers,
4460
+ * hooks, subagents, tool grants) needs another lane. The agent reaches the box through
4461
+ * `lane.placement.providerFor({ nodeId: ctx.search.runId })`, which names the attempt to the
4462
+ * router on every call.
4463
+ */
4464
+ function sharedBoxLane(options) {
4465
+ const { name, boxes, cellUsd, recoverReceipt, ...placementOptions } = options;
4466
+ const placement = sharedBoxPlacement(placementOptions);
4467
+ const workersPerBox = placementOptions.workersPerBox ?? 8;
4468
+ return Object.freeze({
4469
+ name: laneName(name, "shared-box"),
4470
+ kind: "shared-box",
4471
+ capacity: positiveInteger(boxes, "sharedBoxLane(): boxes") * workersPerBox,
4472
+ costCap: "estimate",
4473
+ cellUsd: dollars(cellUsd, "sharedBoxLane(): cellUsd"),
4474
+ refusal: (profile) => placement.refusal(profile),
4475
+ ...laneReceipts({ recoverReceipt }),
4476
+ placement
4477
+ });
4478
+ }
4479
+ /**
4480
+ * Cells that each run in their own environment, `capacity` at once. The lane cannot bound a
4481
+ * cell's dollars, so it holds an estimate: `cellUsd` until 20 cells settle, then 1.5 × the p99
4482
+ * of its settled cells.
4483
+ */
4484
+ function dedicatedLane(options) {
4485
+ return Object.freeze({
4486
+ name: laneName(options.name, "dedicated"),
4487
+ kind: "dedicated",
4488
+ capacity: positiveInteger(options.capacity, "dedicatedLane(): capacity"),
4489
+ costCap: "estimate",
4490
+ cellUsd: dollars(options.cellUsd, "dedicatedLane(): cellUsd"),
4491
+ refusal: acceptEveryProfile,
4492
+ ...laneReceipts(options)
4493
+ });
4494
+ }
4495
+ /**
4496
+ * Cells on subscription seats, one cell a seat. A seat charges no dollar per call, so its own
4497
+ * work costs $0 and reports no tokens. `cellUsd` bounds the cell's priced calls, such as its
4498
+ * judges; every one of them must declare a maximum, and the lane refuses a call past it.
4499
+ */
4500
+ function subscriptionLane(options) {
4501
+ return Object.freeze({
4502
+ name: laneName(options.name, "subscription"),
4503
+ kind: "subscription",
4504
+ capacity: positiveInteger(options.seats, "subscriptionLane(): seats"),
4505
+ costCap: "hard",
4506
+ cellUsd: dollars(options.cellUsd ?? 0, "subscriptionLane(): cellUsd"),
4507
+ refusal: acceptEveryProfile,
4508
+ ...laneReceipts(options)
4509
+ });
4510
+ }
4511
+ /**
4512
+ * Cells whose model calls are priced router calls, `capacity` at once. Every paid call of a
4513
+ * cell must declare its maximum charge, and the lane refuses a call that would take the cell
4514
+ * past `cellUsd`, so `cellUsd` is each cell's hard maximum.
4515
+ */
4516
+ function routerLane(options) {
4517
+ return Object.freeze({
4518
+ name: laneName(options.name, "router"),
4519
+ kind: "router",
4520
+ capacity: positiveInteger(options.capacity, "routerLane(): capacity"),
4521
+ costCap: "hard",
4522
+ cellUsd: dollars(options.cellUsd, "routerLane(): cellUsd"),
4523
+ refusal: acceptEveryProfile,
4524
+ ...laneReceipts(options)
4525
+ });
4526
+ }
4527
+ /** Check a lane list: at least one lane, unique names, a hard lane's cap known. */
4528
+ function assertSearchLanes(lanes, context) {
4529
+ if (!Array.isArray(lanes) || lanes.length === 0) throw new ConfigError(`${context}: lanes needs at least one lane`);
4530
+ const names = /* @__PURE__ */ new Set();
4531
+ for (const lane of lanes) {
4532
+ if (!lane || typeof lane.refusal !== "function" || typeof lane.kind !== "string") throw new ConfigError(`${context}: every lane comes from sharedBoxLane, dedicatedLane, subscriptionLane or routerLane`);
4533
+ if (names.has(lane.name)) throw new ConfigError(`${context}: lane '${lane.name}' appears twice`);
4534
+ names.add(lane.name);
4535
+ }
4536
+ }
4537
+ /**
4538
+ * The environment, not the candidate, ended the attempt: a box that died, a platform that
4539
+ * refused the run, a quota. The attempt settles `errored` and retryable, and the kernel runs a
4540
+ * fresh attempt up to its `maxAttempts`. Throw anything else for the agent's own failure.
4541
+ */
4542
+ var SearchEnvironmentFault = class extends Error {
4543
+ constructor(message, options) {
4544
+ super(message, options);
4545
+ this.name = "SearchEnvironmentFault";
4546
+ }
4547
+ };
4548
+ /** Whether an attempt's error is the environment's: a `SearchEnvironmentFault`, or a platform,
4549
+ * gateway or network failure that a repeated request can change. */
4550
+ function isSearchEnvironmentFault(error) {
4551
+ return error instanceof SearchEnvironmentFault || isTransientSandboxFailure(error);
4552
+ }
4553
+ const USD_TOLERANCE = 1e-9;
4554
+ /** The kernel's executor port over Runtime lanes. */
4555
+ function searchExecutor(options) {
4556
+ assertSearchLanes(options.lanes, "searchExecutor()");
4557
+ const lanes = new Map(options.lanes.map((lane) => [lane.name, lane]));
4558
+ const placed = new Map(options.lanes.map((lane) => [lane.name, 0]));
4559
+ const slots = options.workerSlots ? openSlotGroup(options.workerSlots) : null;
4560
+ const attempts = attemptStore(options.storage, join(options.dir, "attempts"));
4561
+ const tracing = searchTracing(options);
4562
+ const laneOf = (work) => {
4563
+ const lane = lanes.get(work.lane);
4564
+ if (!lane) throw new Error(`search cell ${work.cellId} was placed on unknown lane '${work.lane}'`);
4565
+ return lane;
4566
+ };
4567
+ return {
4568
+ lanes: () => options.lanes,
4569
+ place(cell) {
4570
+ const profile = options.profileOf(cell.nodeId);
4571
+ let chosen;
4572
+ for (const lane of options.lanes) {
4573
+ if (profile && lane.refusal(profile) !== void 0) continue;
4574
+ if (chosen === void 0 || placed.get(lane.name) / lane.capacity < placed.get(chosen.name) / chosen.capacity) chosen = lane;
4575
+ }
4576
+ if (!chosen) throw new Error(`no search lane can run node ${cell.nodeId}; admission should have refused it`);
4577
+ placed.set(chosen.name, placed.get(chosen.name) + 1);
4578
+ return chosen.name;
4579
+ },
4580
+ async adopt(work) {
4581
+ return attempts.read(work.runId);
4582
+ },
4583
+ async run(work) {
4584
+ const lane = laneOf(work);
4585
+ const queuedAt = Date.now();
4586
+ let hold;
4587
+ try {
4588
+ hold = await holdFleet(lane, work, options.budgetPool, slots);
4589
+ } catch (error) {
4590
+ if (work.signal.aborted) return interrupted(work, lane, options.identity, error);
4591
+ throw error;
4592
+ }
4593
+ const queueMs = Date.now() - queuedAt;
4594
+ const trace = tracing.open(work, lane);
4595
+ let result;
4596
+ try {
4597
+ const context = Object.freeze({
4598
+ searchId: work.searchId,
4599
+ cellId: work.cellId,
4600
+ nodeId: work.nodeId,
4601
+ taskId: work.taskId,
4602
+ split: work.split,
4603
+ stage: work.stage,
4604
+ attempt: work.attempt,
4605
+ runId: work.runId,
4606
+ lane,
4607
+ trace: trace.ids
4608
+ });
4609
+ const tags = searchCallTags(work.searchId, {
4610
+ run: work.runId,
4611
+ lane: lane.name
4612
+ });
4613
+ const measured = await options.runAttempt({
4614
+ work,
4615
+ lane,
4616
+ context,
4617
+ costLedger: attemptLedger(options.costLedger, lane, tags),
4618
+ span: trace.span
4619
+ });
4620
+ result = {
4621
+ ...measured,
4622
+ accounting: attemptAccounting(options.costLedger, lane, tags),
4623
+ queueMs,
4624
+ placement: {
4625
+ lane: lane.name,
4626
+ boxId: measured.placement?.boxId ?? null
4627
+ },
4628
+ traceRef: await trace.finish(measured)
4629
+ };
4630
+ } finally {
4631
+ hold.release(result);
4632
+ }
4633
+ if (!work.signal.aborted) attempts.write(work.runId, result);
4634
+ return result;
4635
+ }
4636
+ };
4637
+ }
4638
+ function interrupted(work, lane, identity, error) {
4639
+ return {
4640
+ outcome: {
4641
+ status: "errored",
4642
+ metrics: {},
4643
+ error: {
4644
+ code: "interrupted",
4645
+ message: `search cell ${work.runId} was interrupted before it ran: ${error instanceof Error ? error.message : String(error)}`,
4646
+ retryable: true
4647
+ }
4648
+ },
4649
+ accounting: {
4650
+ tokens: {
4651
+ status: "known",
4652
+ inputTokens: 0,
4653
+ outputTokens: 0,
4654
+ cachedTokens: 0
4655
+ },
4656
+ cost: {
4657
+ status: "known",
4658
+ usd: 0,
4659
+ source: "free"
4660
+ }
4661
+ },
4662
+ identity,
4663
+ placement: {
4664
+ lane: lane.name,
4665
+ boxId: null
4666
+ },
4667
+ traceRef: { unknown: "the attempt never started" }
4668
+ };
4669
+ }
4670
+ /** Take the attempt's fleet dollars, then its fleet slot. A cell waiting for budget holds no
4671
+ * slot, so it cannot hold a slot the cells it waits on need. */
4672
+ async function holdFleet(lane, work, pool, slots) {
4673
+ let ticket;
4674
+ if (pool && lane.costCap === "hard" && lane.cellUsd > 0) {
4675
+ const reserved = pool.reserve({
4676
+ maxUsd: lane.cellUsd,
4677
+ maxTokens: 0,
4678
+ maxIterations: 0
4679
+ }, {
4680
+ label: work.runId,
4681
+ stage: "admitted"
4682
+ }, { wait: true });
4683
+ if (!reserved.ok) throw new Error(`the fleet budget pool refused search cell ${work.runId} on lane ${lane.name}: ${reserved.reason}`);
4684
+ ticket = reserved.ticket;
4685
+ if (reserved.granted) try {
4686
+ await abortable(reserved.granted, work.signal);
4687
+ } catch (error) {
4688
+ pool.reconcile(ticket, noSpend());
4689
+ throw error;
4690
+ }
4691
+ pool.attribute(ticket, {
4692
+ label: work.runId,
4693
+ stage: "executing"
4694
+ });
4695
+ }
4696
+ const permit = slots?.acquire(0);
4697
+ if (permit) try {
4698
+ await abortable(permit.ready, work.signal);
4699
+ } catch (error) {
4700
+ permit.release();
4701
+ if (ticket) pool.reconcile(ticket, noSpend());
4702
+ throw error;
4703
+ }
4704
+ return { release(result) {
4705
+ permit?.release();
4706
+ if (!ticket) return;
4707
+ try {
4708
+ pool.reconcile(ticket, result ? spendOf(result) : unknownSpend());
4709
+ } catch {}
4710
+ } };
4711
+ }
4712
+ function abortable(promise, signal) {
4713
+ if (signal.aborted) return Promise.reject(signal.reason ?? /* @__PURE__ */ new Error("search cell aborted"));
4714
+ return new Promise((resolve, reject) => {
4715
+ const onAbort = () => reject(signal.reason ?? /* @__PURE__ */ new Error("search cell aborted"));
4716
+ signal.addEventListener("abort", onAbort, { once: true });
4717
+ promise.then((value) => {
4718
+ signal.removeEventListener("abort", onAbort);
4719
+ resolve(value);
4720
+ }, (error) => {
4721
+ signal.removeEventListener("abort", onAbort);
4722
+ reject(error);
4723
+ });
4724
+ });
4725
+ }
4726
+ function noSpend() {
4727
+ return {
4728
+ iterations: 0,
4729
+ tokens: {
4730
+ input: 0,
4731
+ output: 0
4732
+ },
4733
+ usd: 0,
4734
+ ms: 0
4735
+ };
4736
+ }
4737
+ function unknownSpend() {
4738
+ return {
4739
+ ...noSpend(),
4740
+ usdKnown: false,
4741
+ tokensKnown: false
4742
+ };
4743
+ }
4744
+ /** The attempt's spend as the budget pool reads it. Unknown dollars carry their proven floor. */
4745
+ function spendOf(result) {
4746
+ const { cost, tokens } = result.accounting;
4747
+ return {
4748
+ iterations: 0,
4749
+ tokens: tokens.status === "known" ? {
4750
+ input: tokens.inputTokens,
4751
+ output: tokens.outputTokens
4752
+ } : {
4753
+ input: 0,
4754
+ output: 0
4755
+ },
4756
+ ...tokens.status === "known" ? {} : { tokensKnown: false },
4757
+ usd: cost.status === "known" ? cost.usd : cost.knownLowerBoundUsd,
4758
+ ...cost.status === "known" ? {} : { usdKnown: false },
4759
+ ms: result.wallMs ?? 0
4760
+ };
4761
+ }
4762
+ /** The dollar maximum a paid call declares, or null when it declares no priced one. */
4763
+ function chargeMaximumUsd(maximum) {
4764
+ if (!maximum) return null;
4765
+ if ("externallyEnforcedMaximumUsd" in maximum) return maximum.externallyEnforcedMaximumUsd;
4766
+ if ("customTokenPricing" in maximum) return costForTokenPricing(maximum.customTokenPricing, maximum);
4767
+ const priced = costForUsage(maximum.model, maximum);
4768
+ return priced.costUnknown ? null : priced.costUsd;
4769
+ }
4770
+ const TAG_SEARCH = "searchId";
4771
+ const TAG_RUN = "searchRunId";
4772
+ const TAG_LANE = "searchLane";
4773
+ const TAG_OPERATION = "searchOperation";
4774
+ /** The cost-ledger tags of one search's calls: a cell attempt's, or a proposal operation's. */
4775
+ function searchCallTags(searchId, of) {
4776
+ return "run" in of ? {
4777
+ [TAG_SEARCH]: searchId,
4778
+ [TAG_RUN]: of.run,
4779
+ [TAG_LANE]: of.lane
4780
+ } : {
4781
+ [TAG_SEARCH]: searchId,
4782
+ [TAG_OPERATION]: of.operation
4783
+ };
4784
+ }
4785
+ /** The search ledger with `tags` added to every paid call. */
4786
+ function taggedLedger(ledger, tags) {
4787
+ return ledgerView(ledger, (input) => ledger.runPaidCall({
4788
+ ...input,
4789
+ tags: {
4790
+ ...input.tags,
4791
+ ...tags
4792
+ }
4793
+ }));
4794
+ }
4795
+ function ledgerView(ledger, runPaidCall) {
4796
+ return new Proxy(ledger, { get(target, property) {
4797
+ if (property === "runPaidCall") return runPaidCall;
4798
+ const value = Reflect.get(target, property, target);
4799
+ return typeof value === "function" ? value.bind(target) : value;
4800
+ } });
4801
+ }
4802
+ /**
4803
+ * The search ledger seen by one attempt: every paid call carries the attempt's tags. On a hard
4804
+ * lane every call also holds its declared maximum against the lane's `cellUsd` until its
4805
+ * receipt replaces the hold with the charge, and a call that would pass the cap, or declares no
4806
+ * priced maximum, is refused. A charge the provider left unknown keeps its maximum held.
4807
+ */
4808
+ function attemptLedger(ledger, lane, tags) {
4809
+ const tagged = taggedLedger(ledger, tags);
4810
+ if (lane.costCap !== "hard") return tagged;
4811
+ let heldUsd = 0;
4812
+ const runPaidCall = async (input) => {
4813
+ const maximumUsd = chargeMaximumUsd(input.maximumCharge);
4814
+ if (maximumUsd === null) return {
4815
+ succeeded: false,
4816
+ error: new CostAccountingIncompleteError(`lane ${lane.name} caps each cell at $${lane.cellUsd}, so paid call '${input.actor}' during '${input.phase}' needs a priced maximumCharge`)
4817
+ };
4818
+ if (heldUsd + maximumUsd > lane.cellUsd + USD_TOLERANCE) return {
4819
+ succeeded: false,
4820
+ error: new CostCeilingReachedError(lane.cellUsd, heldUsd, maximumUsd, input.phase, input.actor)
4821
+ };
4822
+ heldUsd += maximumUsd;
4823
+ const result = await tagged.runPaidCall(input);
4824
+ const { receipt } = result;
4825
+ if (receipt && !receipt.costUnknown) heldUsd += receipt.costUsd - maximumUsd;
4826
+ return result;
4827
+ };
4828
+ return ledgerView(tagged, runPaidCall);
4829
+ }
4830
+ /**
4831
+ * An attempt's cost is every call tagged with its run id, a call a process that ended made for
4832
+ * it included; a call still pending makes the cost unknown with the settled calls as its floor.
4833
+ * A subscription seat reports no tokens, and its own work charges no dollar.
4834
+ */
4835
+ function attemptAccounting(ledger, lane, tags) {
4836
+ const receipts = ledger.list({ tags });
4837
+ const accounting = searchReceiptAccounting(receipts);
4838
+ const pending = ledger.listPending?.({ tags }) ?? [];
4839
+ const floorUsd = accounting.cost.status === "known" ? accounting.cost.usd : accounting.cost.knownLowerBoundUsd;
4840
+ const cost = pending.length > 0 ? {
4841
+ status: "unknown",
4842
+ knownLowerBoundUsd: floorUsd,
4843
+ reason: `${pending.length} paid call(s) of the attempt had no receipt when it ended`
4844
+ } : accounting.cost.status === "known" && accounting.cost.usd > 0 && receipts.some((receipt) => receipt.actualCostUsd === void 0) ? {
4845
+ ...accounting.cost,
4846
+ source: "pricing-table"
4847
+ } : accounting.cost;
4848
+ return {
4849
+ tokens: lane.kind === "subscription" ? {
4850
+ status: "unknown",
4851
+ reason: "a subscription seat reports no token usage"
4852
+ } : accounting.tokens,
4853
+ cost
4854
+ };
4855
+ }
4856
+ /**
4857
+ * Settle every paid call of `searchId` that a process which ended left pending, before the
4858
+ * reopened search makes a new one: a capped ledger refuses new paid work while one is
4859
+ * unresolved. A cell's call is asked of its lane's provider through `recoverReceipt`; any other
4860
+ * call, or one the provider cannot answer, settles failed with an unknown cost.
4861
+ */
4862
+ async function reconcileInterruptedSearchCalls(ledger, searchId, lanes) {
4863
+ const interrupted = (ledger.listPending?.({ tags: { [TAG_SEARCH]: searchId } }) ?? []).filter((call) => call.state === "interrupted");
4864
+ let recovered = 0;
4865
+ for (const call of interrupted) {
4866
+ const receipt = await lanes.find((candidate) => candidate.name === call.tags?.[TAG_LANE])?.recoverReceipt?.(call) ?? null;
4867
+ if (receipt) {
4868
+ ledger.reconcile(call.callId, receipt);
4869
+ recovered += 1;
4870
+ } else ledger.reconcile(call.callId, {
4871
+ model: call.model,
4872
+ inputTokens: 0,
4873
+ outputTokens: 0,
4874
+ costUnknown: true,
4875
+ usageUnknown: true
4876
+ }, { error: "the process that made this call ended before its receipt" });
4877
+ }
4878
+ return {
4879
+ recovered,
4880
+ unknown: interrupted.length - recovered
4881
+ };
4882
+ }
4883
+ /** Finished attempts by run id: the record a restarted kernel adopts. */
4884
+ function attemptStore(storage, dir) {
4885
+ const pathOf = (runId) => join(dir, `${runId.replace(/[^A-Za-z0-9_-]/gu, ".")}.json`);
4886
+ storage.ensureDir(dir);
4887
+ return {
4888
+ read(runId) {
4889
+ const text = storage.read(pathOf(runId));
4890
+ if (text === void 0) return null;
4891
+ const record = JSON.parse(text);
4892
+ if (record.runId !== runId || !record.result) throw new Error(`attempt record ${pathOf(runId)} does not hold run ${runId}`);
4893
+ return record.result;
4894
+ },
4895
+ write(runId, result) {
4896
+ const text = `${JSON.stringify({
4897
+ runId,
4898
+ result
4899
+ })}\n`;
4900
+ const path = pathOf(runId);
4901
+ if (storage.kind !== "filesystem") {
4902
+ storage.write(path, text);
4903
+ return;
4904
+ }
4905
+ mkdirSync(dirname(path), { recursive: true });
4906
+ const temporary = `${path}.${process.pid}.tmp`;
4907
+ writeFileSync(temporary, text);
4908
+ renameSync(temporary, path);
4909
+ }
4910
+ };
4911
+ }
4912
+ const STATUS_OK = 1;
4913
+ const STATUS_ERROR = 2;
4914
+ const MAX_ATTRIBUTE_CHARS = 256;
4915
+ function searchTracing(options) {
4916
+ const mode = options.trace;
4917
+ const fileExporter = mode === void 0 && options.storage.kind === "filesystem" ? createOpenInferenceFileExporter(join(options.dir, "spans.otlp.jsonl")) : void 0;
4918
+ const off = (reason) => ({
4919
+ ids: null,
4920
+ span: () => ({
4921
+ setAttribute() {},
4922
+ end() {}
4923
+ }),
4924
+ finish: async () => ({ unknown: reason })
4925
+ });
4926
+ return { open(work, lane) {
4927
+ if (mode === "off") return off("tracing is off for this search");
4928
+ const exporter = mode === void 0 ? fileExporter : createOtelExporter(mode.otlp);
4929
+ if (!exporter) return off(mode === void 0 ? "the search storage is not the filesystem and no OTLP exporter was configured" : "the OTLP exporter has no endpoint");
4930
+ return attemptTrace(work, lane, exporter, mode !== void 0);
4931
+ } };
4932
+ }
4933
+ /**
4934
+ * One attempt's trace. Its ids derive from the run id, so an attempt run again after a restart
4935
+ * writes into the same trace. A shared file exporter writes each span synchronously, so the
4936
+ * attempt's written and dropped counts are the change in the exporter's own counts across each
4937
+ * of its spans; an attempt's own OTLP exporter is shut down at the end and read whole.
4938
+ */
4939
+ function attemptTrace(work, lane, exporter, ownsExporter) {
4940
+ const traceId = padTraceId(`search-cell:${work.runId}`);
4941
+ const rootSpanId = padSpanId(`search-cell:${work.runId}`);
4942
+ const startMs = Date.now();
4943
+ let written = 0;
4944
+ let dropped = 0;
4945
+ const exportCounted = (span) => {
4946
+ if (ownsExporter) {
4947
+ exporter.exportSpan(span);
4948
+ return;
4949
+ }
4950
+ const before = exporter.stats();
4951
+ exporter.exportSpan(span);
4952
+ const after = exporter.stats();
4953
+ written += after.written - before.written;
4954
+ dropped += after.dropped - before.dropped;
4955
+ };
4956
+ return {
4957
+ ids: {
4958
+ traceId,
4959
+ spanId: rootSpanId
4960
+ },
4961
+ span(name, attributes = {}) {
4962
+ const opened = Date.now();
4963
+ const record = { ...attributes };
4964
+ let ended = false;
4965
+ return {
4966
+ setAttribute(key, value) {
4967
+ record[key] = value;
4968
+ },
4969
+ end(endAttributes = {}) {
4970
+ if (ended) return;
4971
+ ended = true;
4972
+ exportCounted(otelSpan({
4973
+ traceId,
4974
+ spanId: generateSpanId(),
4975
+ parentSpanId: rootSpanId,
4976
+ name,
4977
+ startMs: opened,
4978
+ endMs: Date.now(),
4979
+ attributes: {
4980
+ ...record,
4981
+ ...endAttributes
4982
+ },
4983
+ status: STATUS_OK
4984
+ }));
4985
+ }
4986
+ };
4987
+ },
4988
+ async finish(result) {
4989
+ const root = branchSpan({
4990
+ traceId,
4991
+ spanId: rootSpanId,
4992
+ name: "search.cell",
4993
+ startTime: new Date(startMs).toISOString(),
4994
+ branchId: work.nodeId,
4995
+ arm: lane.name,
4996
+ attributes: {
4997
+ "tangle.search.id": work.searchId,
4998
+ "tangle.search.cell_id": work.cellId,
4999
+ "tangle.search.run_id": work.runId,
5000
+ "tangle.search.task_id": work.taskId,
5001
+ "tangle.search.split": work.split,
5002
+ "tangle.search.stage": work.stage,
5003
+ "tangle.search.attempt": work.attempt,
5004
+ "tangle.search.lane": lane.name,
5005
+ "tangle.search.lane_kind": lane.kind,
5006
+ "tangle.search.outcome": result.outcome.status,
5007
+ ..."score" in result.outcome ? { [ATTR.score]: result.outcome.score } : {}
5008
+ }
5009
+ });
5010
+ exportCounted(otelSpan({
5011
+ traceId,
5012
+ spanId: rootSpanId,
5013
+ name: root.name,
5014
+ startMs,
5015
+ endMs: Date.now(),
5016
+ attributes: root.attributes,
5017
+ status: result.outcome.status === "errored" ? STATUS_ERROR : STATUS_OK
5018
+ }));
5019
+ if (ownsExporter) {
5020
+ await exporter.shutdown();
5021
+ const stats = exporter.stats();
5022
+ written = stats.written;
5023
+ dropped = stats.dropped;
5024
+ }
5025
+ return {
5026
+ traceId,
5027
+ execRunId: null,
5028
+ spansWritten: written,
5029
+ spansDropped: dropped
5030
+ };
5031
+ }
5032
+ };
5033
+ }
5034
+ function otelSpan(input) {
5035
+ const attributes = {};
5036
+ for (const [key, value] of Object.entries(input.attributes)) if (typeof value === "number" || typeof value === "boolean") attributes[key] = value;
5037
+ else if (typeof value === "string") attributes[key] = value.slice(0, MAX_ATTRIBUTE_CHARS);
5038
+ return {
5039
+ traceId: input.traceId,
5040
+ spanId: input.spanId,
5041
+ ...input.parentSpanId ? { parentSpanId: input.parentSpanId } : {},
5042
+ name: input.name,
5043
+ kind: 1,
5044
+ startTimeUnixNano: (BigInt(Math.floor(input.startMs)) * 1000000n).toString(),
5045
+ endTimeUnixNano: (BigInt(Math.floor(Math.max(input.startMs, input.endMs))) * 1000000n).toString(),
5046
+ attributes: toOtelAttributes(attributes),
5047
+ status: { code: input.status }
5048
+ };
5049
+ }
5050
+ //#endregion
5051
+ //#region src/improvement/search-method.ts
5052
+ /** Build Runtime's native search for `improve(profile, { method })`. */
5053
+ function searchMethod(options) {
5054
+ if (!options || typeof options !== "object") throw new ConfigError("searchMethod(): options are required");
5055
+ const { proposer } = options;
5056
+ if (!proposer || typeof proposer.kind !== "string" || typeof proposer.propose !== "function") throw new ConfigError("searchMethod(): proposer must be a SurfaceProposer");
5057
+ const count = (name, value, fallback, min) => {
5058
+ const resolved = value ?? fallback;
5059
+ if (!Number.isSafeInteger(resolved) || resolved < min) throw new ConfigError(`searchMethod(): ${name} must be an integer of at least ${min}`);
5060
+ return resolved;
5061
+ };
5062
+ const dollars = (name, value) => {
5063
+ if (value === void 0) return null;
5064
+ if (!Number.isFinite(value) || value < 0) throw new ConfigError(`searchMethod(): ${name} must be a finite non-negative number`);
5065
+ return value;
5066
+ };
5067
+ if (options.deadline !== void 0 && !Number.isFinite(Date.parse(options.deadline))) throw new ConfigError("searchMethod(): deadline must be an ISO time");
5068
+ const name = options.name ?? "search";
5069
+ if (!name.trim() || name.trim() !== name) throw new ConfigError("searchMethod(): name must be a trimmed non-empty string");
5070
+ assertSearchLanes(options.lanes, "searchMethod()");
5071
+ return Object.freeze({
5072
+ kind: "search",
5073
+ name,
5074
+ policy: options.policy ?? aide(),
5075
+ allocation: options.allocation ?? asha(),
5076
+ proposer,
5077
+ maxExpansions: count("maxExpansions", options.maxExpansions, NaN, 0),
5078
+ childrenPerProposal: count("childrenPerProposal", options.childrenPerProposal, 1, 1),
5079
+ lanes: Object.freeze([...options.lanes]),
5080
+ claimReserveUsd: dollars("claimReserveUsd", options.claimReserveUsd),
5081
+ deadline: options.deadline === void 0 ? null : new Date(options.deadline).toISOString(),
5082
+ maxAttempts: count("maxAttempts", options.maxAttempts, 3, 1)
5083
+ });
5084
+ }
5085
+ function isImproveSearchMethod(value) {
5086
+ return typeof value === "object" && value !== null && value.kind === "search";
5087
+ }
5088
+ const SEARCH_METHOD_SOURCE = {
5089
+ uri: "npm:@tangle-network/agent-runtime#searchMethod",
5090
+ revision: canonicalCandidateDigest$1({
5091
+ name: "agent-runtime.search-method.2026-09",
5092
+ node: "an exact AgentProfile materialized from the baseline and one surface, content-addressed by canonicalAgentProfileDigest; a surface that does not materialize is a node addressed by its surface and refused",
5093
+ edge: "the Interface diffs from the parent profile to the child, stored when they reproduce the child digest",
5094
+ admission: "a candidate is refused when it does not materialize, declares training on a test task, fails the caller validator, carries a credential or private value, or no lane can run its profile",
5095
+ cell: "a one-cell runCampaign of the materialized profile in a directory addressed by its digest, on a lane that accepts the profile; a cached cell is read back, not run again; a finished attempt is recorded by run id before it settles and adopted after a restart",
5096
+ lanes: "a hard lane refuses a paid call that declares no priced maximum or would take the cell past its cellUsd; an environment fault settles errored and retryable; a subscription seat reports no tokens and charges no dollars",
5097
+ proposer: "a SurfaceProposer reads the parents, the train view and the train summary; paid calls it makes are its operation accounting",
5098
+ ship: "the claim shipped, re-derives from the ledger, cost accounting is complete, and the shipped finalist test lower bound exceeds minimumLift"
5099
+ })
5100
+ };
5101
+ async function runSearchImprovement(profile, opts) {
5102
+ const { method, claim: inputClaim, agent, trainScenarios, selectionScenarios, testScenarios, judges: _judges, surface: _surface, executionRef: _executionRef, validateCandidate: _validateCandidate, findings: _findings, skills: _skills, profileComponents: _profileComponents, minimumLift: _minimumLift, subject: _subject, costCeiling, costLedger: inputCostLedger, seed = 42, signal, workerSlots, budgetPool, trace, ...campaignOptions } = opts;
5103
+ if (!isImproveSearchMethod(method)) throw new ConfigError("improve(): a search needs method: searchMethod(...)");
5104
+ const claim = defineEvaluationClaim(inputClaim);
5105
+ if (claim.minimumEffect === void 0) throw new ConfigError("improve(): a search claim needs minimumEffect for its power check");
5106
+ for (const [name, split] of [
5107
+ ["trainScenarios", trainScenarios],
5108
+ ["selectionScenarios", selectionScenarios],
5109
+ ["testScenarios", testScenarios]
5110
+ ]) if (!Array.isArray(split) || split.length === 0) throw new ConfigError(`improve(): a search needs at least one of ${name}`);
5111
+ const { allocation, policy, lanes } = method;
5112
+ const reps = allocation.reps;
5113
+ const concurrency = lanes.reduce((total, lane) => total + lane.capacity, 0);
5114
+ const prepared = prepareProfileImprovement(profile, {
5115
+ ...opts,
5116
+ seed,
5117
+ reps,
5118
+ optimizationRunOptions: {
5119
+ reps,
5120
+ maxConcurrency: concurrency
5121
+ }
5122
+ });
5123
+ const { evaluationRef } = prepared.identity;
5124
+ const storage = campaignOptions.storage ?? fsCampaignStorage();
5125
+ const runDir = resolveRunDir(campaignOptions.runDir, campaignOptions.repo);
5126
+ const searchId = `improve-${canonicalCandidateDigest$1({
5127
+ evaluationRef,
5128
+ process: SEARCH_METHOD_SOURCE,
5129
+ method: searchMethodDescriptor(method)
5130
+ }).slice(7, 31)}`;
5131
+ const searchDir = `${runDir}/search/${searchId}`;
5132
+ const costLedger = inputCostLedger ?? createRunCostLedger({
5133
+ storage,
5134
+ runDir: searchDir,
5135
+ costCeilingUsd: costCeiling
5136
+ });
5137
+ const unitOf = (scenario) => summarizeEvaluationUnits(claim, [scenario]).units[0].id;
5138
+ const tasks = (scenarios) => scenarios.map((scenario) => ({
5139
+ taskId: scenario.id,
5140
+ unitId: unitOf(scenario),
5141
+ source: {
5142
+ uri: `scenario://${scenario.id}`,
5143
+ revision: canonicalCandidateDigest$1(scenario)
5144
+ }
5145
+ }));
5146
+ const splits = {
5147
+ train: tasks(trainScenarios),
5148
+ selection: tasks(selectionScenarios),
5149
+ test: tasks(testScenarios)
5150
+ };
5151
+ const developmentUnits = new Set([...splits.train, ...splits.selection].map((task) => task.unitId));
5152
+ const execution = {
5153
+ model: prepared.searchIdentity.model,
5154
+ agent: prepared.searchIdentity.agent,
5155
+ benchmark: {
5156
+ uri: "agent-runtime:improve-splits",
5157
+ revision: canonicalCandidateDigest$1({
5158
+ development: prepared.identity.developmentSplitDigest,
5159
+ test: prepared.identity.finalTestSplitDigest
5160
+ })
5161
+ }
5162
+ };
5163
+ const reservedClaimUsd = Math.max(method.claimReserveUsd ?? 0, searchClaimReserveUsd({
5164
+ testTasks: splits.test.length,
5165
+ reps,
5166
+ cellUsd: Math.max(...lanes.map((lane) => lane.cellUsd))
5167
+ }));
5168
+ const recorder = await SearchRecorder.open({
5169
+ ledger: storage.kind === "filesystem" ? openSearchLedger({
5170
+ path: `${searchDir}/ledger.jsonl`,
5171
+ searchId
5172
+ }) : openSearchLedger({
5173
+ path: `${searchDir}/ledger.jsonl`,
5174
+ searchId,
5175
+ store: storage
5176
+ }),
5177
+ storage
5178
+ }, {
5179
+ subject: prepared.searchIdentity.subject,
5180
+ process: {
5181
+ name: method.name,
5182
+ executionRef: SEARCH_METHOD_SOURCE
5183
+ },
5184
+ artifactKind: "agent-profile",
5185
+ objective: {
5186
+ metric: "composite",
5187
+ direction: "maximize",
5188
+ judge: prepared.searchIdentity.judge,
5189
+ claim
5190
+ },
5191
+ splits: {
5192
+ ...splits,
5193
+ heldOutUnits: splits.test.every((task) => !developmentUnits.has(task.unitId))
5194
+ },
5195
+ policy: {
5196
+ expansion: policy.name,
5197
+ allocation: allocation.name,
5198
+ seed
5199
+ },
5200
+ budget: {
5201
+ maxUsd: costCeiling ?? null,
5202
+ maxCells: null,
5203
+ maxNodes: 1 + method.maxExpansions * method.childrenPerProposal,
5204
+ deadline: method.deadline,
5205
+ maxConcurrency: concurrency,
5206
+ reservedClaimUsd: costCeiling === void 0 ? 0 : reservedClaimUsd
5207
+ },
5208
+ containment: null,
5209
+ derivedFrom: null,
5210
+ identity: execution
5211
+ });
5212
+ const nodeOf = (candidateSurface) => {
5213
+ const surface = immutableCandidateValue(candidateSurface);
5214
+ try {
5215
+ return {
5216
+ surface,
5217
+ profile: prepared.materializeCandidate(surface),
5218
+ refusal: null
5219
+ };
5220
+ } catch (error) {
5221
+ return {
5222
+ surface,
5223
+ profile: null,
5224
+ refusal: refusalText(error)
5225
+ };
5226
+ }
5227
+ };
5228
+ const profiles = /* @__PURE__ */ new Map();
5229
+ const profiled = profileCodec(prepared);
5230
+ const codec = {
5231
+ node(recorder, node) {
5232
+ const registered = profiled.node(recorder, node);
5233
+ profiles.set(searchNodeId(searchId, registered.artifactDigest), node.profile);
5234
+ return registered;
5235
+ },
5236
+ diff: profiled.diff,
5237
+ load(recorder, node) {
5238
+ const loaded = profiled.load(recorder, node);
5239
+ profiles.set(node.nodeId, loaded.profile);
5240
+ return loaded;
5241
+ }
5242
+ };
5243
+ for (const node of (await recorder.state()).nodes()) codec.load(recorder, node);
5244
+ await reconcileInterruptedSearchCalls(costLedger, searchId, lanes);
5245
+ const laneRefusal = (nodeProfile) => {
5246
+ const refusals = lanes.map((lane) => `${lane.name}: ${lane.refusal(nodeProfile)}`);
5247
+ return lanes.some((lane) => lane.refusal(nodeProfile) === void 0) ? null : `no lane can run the profile (${refusals.join("; ")})`;
5248
+ };
5249
+ const root = nodeOf(prepared.baselineSurface);
5250
+ if (root.profile) {
5251
+ const refused = laneRefusal(root.profile);
5252
+ if (refused) throw new ConfigError(`improve(): the baseline profile cannot run: ${refused}`);
5253
+ }
5254
+ const scenarios = [
5255
+ ...trainScenarios,
5256
+ ...selectionScenarios,
5257
+ ...testScenarios
5258
+ ];
5259
+ const scenarioIds = /* @__PURE__ */ new Set();
5260
+ for (const scenario of scenarios) {
5261
+ if (scenarioIds.has(scenario.id)) throw new ConfigError(`improve(): scenario '${scenario.id}' appears in more than one split`);
5262
+ scenarioIds.add(scenario.id);
5263
+ }
5264
+ const executor = searchExecutor({
5265
+ lanes,
5266
+ profileOf(nodeId) {
5267
+ const known = profiles.get(nodeId);
5268
+ if (known === void 0) throw new Error(`improve(): node ${nodeId} was placed unregistered`);
5269
+ return known;
5270
+ },
5271
+ costLedger,
5272
+ identity: execution,
5273
+ storage,
5274
+ dir: searchDir,
5275
+ ...workerSlots ? { workerSlots } : {},
5276
+ ...budgetPool ? { budgetPool } : {},
5277
+ ...trace ? { trace } : {},
5278
+ async runAttempt({ work, lane, context, costLedger: cellLedger, span }) {
5279
+ const nodeProfile = work.artifact.profile;
5280
+ if (!nodeProfile) throw new Error(`improve(): refused node ${work.nodeId} was given a cell`);
5281
+ const profileDigest = canonicalAgentProfileDigest(nodeProfile);
5282
+ let fault;
5283
+ const cell = (await runCampaign({
5284
+ ...campaignOptions,
5285
+ ...lane.kind === "subscription" && campaignOptions.expectUsage === void 0 ? { expectUsage: "off" } : {},
5286
+ scenarios,
5287
+ judges: prepared.judges,
5288
+ seed,
5289
+ reps,
5290
+ storage,
5291
+ runDir: `${searchDir}/nodes/${profileDigest.slice(7)}`,
5292
+ dispatchRef: `improve:${evaluationRef}:${profileDigest}`,
5293
+ async dispatch(scenario, ctx) {
5294
+ try {
5295
+ return await agent(nodeProfile, scenario, {
5296
+ ...ctx,
5297
+ search: context
5298
+ });
5299
+ } catch (error) {
5300
+ if (isSearchEnvironmentFault(error)) fault = error;
5301
+ throw error;
5302
+ }
5303
+ },
5304
+ cellFilter: ({ scenario, rep }) => scenario.id === work.taskId && rep === work.rep,
5305
+ resumable: true,
5306
+ maxConcurrency: 1,
5307
+ costLedger: cellLedger,
5308
+ costPhase: `search.${work.stage}`,
5309
+ buildTraceWriter: () => ({
5310
+ span,
5311
+ flush: async () => {}
5312
+ }),
5313
+ signal: work.signal
5314
+ })).cells[0];
5315
+ if (!cell) throw new Error(`improve(): cell ${work.cellId} produced no campaign cell`);
5316
+ return faultResult(campaignCellSearchResult(cell, {
5317
+ execution,
5318
+ lane: lane.name
5319
+ }), cell.errorStage === "dispatch" ? fault : void 0);
5320
+ }
5321
+ });
5322
+ const { proposer } = method;
5323
+ const proposerSource = {
5324
+ uri: `proposer:${proposer.kind}`,
5325
+ revision: canonicalCandidateDigest$1({
5326
+ kind: proposer.kind,
5327
+ propose: Function.prototype.toString.call(proposer.propose),
5328
+ decide: proposer.decide ? Function.prototype.toString.call(proposer.decide) : null
5329
+ })
5330
+ };
5331
+ const proposalPhase = "search.proposal";
5332
+ const port = {
5333
+ name: proposer.kind,
5334
+ kind: "optimizer",
5335
+ source: proposerSource,
5336
+ execution: {
5337
+ kind: "deterministic",
5338
+ source: proposerSource
5339
+ },
5340
+ childrenPerProposal: method.childrenPerProposal,
5341
+ async propose(request) {
5342
+ const tags = searchCallTags(searchId, { operation: request.operationId });
5343
+ const state = await recorder.state();
5344
+ const parents = request.parents.map(({ nodeId, artifact }) => ({
5345
+ nodeId,
5346
+ artifact: artifact.surface
5347
+ }));
5348
+ const context = Object.freeze({
5349
+ currentSurface: parents[0]?.artifact ?? prepared.baselineSurface,
5350
+ operator: request.operator,
5351
+ parents,
5352
+ train: searchProposerView(state),
5353
+ summary: renderSearchSummary(state, { split: "train" }),
5354
+ history: [],
5355
+ findings: prepared.findings,
5356
+ populationSize: method.childrenPerProposal,
5357
+ generation: request.expansion,
5358
+ signal: request.signal,
5359
+ costLedger: taggedLedger(costLedger, tags),
5360
+ costPhase: proposalPhase
5361
+ });
5362
+ const decision = proposer.decide?.({ history: [] });
5363
+ const proposed = decision?.stop ? [] : await proposer.propose(context);
5364
+ if (!Array.isArray(proposed)) throw new ConfigError("improve(): the search proposer must return an array");
5365
+ const fresh = costLedger.list({
5366
+ phase: proposalPhase,
5367
+ tags
5368
+ });
5369
+ return {
5370
+ children: proposed.slice(0, method.childrenPerProposal).map((child) => isProposedCandidate(child) ? {
5371
+ artifact: nodeOf(child.surface),
5372
+ label: child.label,
5373
+ rationale: child.rationale,
5374
+ ...child.attribution ? { attribution: child.attribution } : {}
5375
+ } : {
5376
+ artifact: nodeOf(child),
5377
+ label: "",
5378
+ rationale: ""
5379
+ }),
5380
+ ...decision?.stop ? { stop: decision.reason ?? "the proposer decided to stop" } : {},
5381
+ accounting: searchReceiptAccounting(fresh),
5382
+ execution: searchProposalExecution(fresh, prepared.searchIdentity.model.provider, proposerSource)
5383
+ };
5384
+ }
5385
+ };
5386
+ const admit = (node) => {
5387
+ if (node.refusal !== null || node.profile === null) return node.refusal;
5388
+ try {
5389
+ prepared.admitCandidate(node.profile, node.surface);
5390
+ } catch (error) {
5391
+ return refusalText(error);
5392
+ }
5393
+ const paths = privateValuePaths([node.surface]);
5394
+ if (paths.length > 0) return `the surface carries a credential or private value at ${paths.slice(0, 8).join(", ")}`;
5395
+ return laneRefusal(node.profile);
5396
+ };
5397
+ const startedAt = Date.now();
5398
+ const result = await runSearch({
5399
+ recorder,
5400
+ root,
5401
+ codec,
5402
+ policy,
5403
+ allocation,
5404
+ proposer: port,
5405
+ executor,
5406
+ admit,
5407
+ maxExpansions: method.maxExpansions,
5408
+ maxAttempts: method.maxAttempts,
5409
+ ...signal ? { signal } : {}
5410
+ });
5411
+ const { state } = result;
5412
+ const claimResult = result.claim;
5413
+ if (!claimResult || !result.claimVerification) throw new Error(`improve(): search ${searchId} closed without a claim`);
5414
+ const kept = codec.load(recorder, state.node(result.leader));
5415
+ if (!kept.profile) throw new Error(`improve(): search ${searchId} kept a refused node`);
5416
+ const candidate = Object.freeze({
5417
+ surface: prepared.surface,
5418
+ value: kept.surface,
5419
+ profile: kept.profile
5420
+ });
5421
+ const cost = copyImproveCost(costLedger.summary());
5422
+ const shipped = claimResult.finalists.find((finalist) => finalist.nodeId === claimResult.selected && finalist.test !== null);
5423
+ const { decision, reason } = runtimeShipDecision({
5424
+ claim: claimResult,
5425
+ verified: result.claimVerification.status === "verified",
5426
+ accountingComplete: cost.accountingComplete,
5427
+ lowerBound: shipped?.test?.interval[0] ?? null,
5428
+ minimumLift: prepared.minimumLift
5429
+ });
5430
+ return {
5431
+ mode: "search",
5432
+ method: method.name,
5433
+ candidate,
5434
+ decision,
5435
+ reason,
5436
+ claim: claimResult,
5437
+ claimVerification: result.claimVerification,
5438
+ ...shipped?.test ? {
5439
+ lift: shipped.test.delta,
5440
+ liftInterval: {
5441
+ low: shipped.test.interval[0],
5442
+ high: shipped.test.interval[1]
5443
+ }
5444
+ } : {},
5445
+ searchHistory: recorder.receipt({
5446
+ producerId: method.name,
5447
+ runId: searchId
5448
+ }),
5449
+ cost,
5450
+ durationMs: Date.now() - startedAt,
5451
+ lineage: Object.freeze({
5452
+ invocationId: prepared.invocationId,
5453
+ runId: searchId,
5454
+ developmentSplitDigest: prepared.identity.developmentSplitDigest,
5455
+ finalTestSplitDigest: prepared.identity.finalTestSplitDigest,
5456
+ scenarioPartitions: prepared.identity.scenarioPartitions,
5457
+ executionRef: prepared.executionRef,
5458
+ baselineProfileDigest: prepared.baselineProfileDigest
5459
+ }),
5460
+ async dispose() {}
5461
+ };
5462
+ }
5463
+ /** Runtime's ship rule over the kernel's statistical claim (design §6.5 step 5), shared by
5464
+ * `searchMethod` and `runStrategyEvolution`. */
5465
+ function runtimeShipDecision(input) {
5466
+ const { claim } = input;
5467
+ if (claim.decision !== "ship") return {
5468
+ decision: "hold",
5469
+ reason: claim.reason
5470
+ };
5471
+ if (!input.verified) return {
5472
+ decision: "hold",
5473
+ reason: "the claim shipped, but it does not re-derive from the ledger under this rule revision"
5474
+ };
5475
+ if (!input.accountingComplete) return {
5476
+ decision: "hold",
5477
+ reason: "the claim shipped, but the search cost accounting is incomplete"
5478
+ };
5479
+ if (input.lowerBound === null || !(input.lowerBound > input.minimumLift)) return {
5480
+ decision: "hold",
5481
+ reason: `the claim shipped, but its test lower bound ${input.lowerBound} does not exceed minimumLift ${input.minimumLift}`
5482
+ };
5483
+ return {
5484
+ decision: "ship",
5485
+ reason: claim.reason
5486
+ };
5487
+ }
5488
+ /** Profiles as search artifacts: nodes by profile digest, edges by profile diffs. */
5489
+ function profileCodec(prepared) {
5490
+ const surfaceId = prepared.surface;
5491
+ return {
5492
+ node(recorder, node) {
5493
+ if (node.profile) {
5494
+ const artifact = recorder.blob("agent-profile", {
5495
+ kind: "agent-profile",
5496
+ profile: node.profile
5497
+ });
5498
+ return {
5499
+ artifactDigest: canonicalAgentProfileDigest(node.profile),
5500
+ artifact,
5501
+ surfaces: [{
5502
+ surfaceId,
5503
+ kind: "agent-profile",
5504
+ artifact
5505
+ }]
5506
+ };
5507
+ }
5508
+ const artifact = recorder.blob("surface", {
5509
+ kind: "unmaterialized-surface",
5510
+ surface: node.surface,
5511
+ refusal: node.refusal
5512
+ });
5513
+ return {
5514
+ artifactDigest: canonicalCandidateDigest$1({
5515
+ kind: "unmaterialized-surface",
5516
+ surface: node.surface
5517
+ }),
5518
+ artifact,
5519
+ surfaces: [{
5520
+ surfaceId,
5521
+ kind: "agent-profile",
5522
+ artifact
5523
+ }]
5524
+ };
5525
+ },
5526
+ diff(recorder, parent, child) {
5527
+ if (!parent.profile || !child.profile) return { unknown: "a surface that does not materialize has no profile to diff" };
5528
+ const diffs = diffAgentProfiles(parent.profile, child.profile);
5529
+ const to = canonicalAgentProfileDigest(child.profile);
5530
+ if (canonicalAgentProfileDigest(diffs.reduce(applyAgentProfileDiff, parent.profile)) !== to) return { unknown: "the Interface profile diffs do not reproduce the child profile" };
5531
+ return recorder.blob("diff", {
5532
+ kind: "agent-profile-diff",
5533
+ from: canonicalAgentProfileDigest(parent.profile),
5534
+ to,
5535
+ diffs
5536
+ });
5537
+ },
5538
+ load(recorder, node) {
5539
+ const stored = recorder.readBlob(node.artifact);
5540
+ if (stored.kind === "agent-profile") {
5541
+ const parsed = agentProfileSchema.safeParse(stored.profile);
5542
+ if (!parsed.success) throw new Error(`improve(): node ${node.nodeId} holds an invalid AgentProfile`);
5543
+ const loaded = immutableCandidateValue(parsed.data);
5544
+ return {
5545
+ surface: prepared.surfaceOf(loaded),
5546
+ profile: loaded,
5547
+ refusal: null
5548
+ };
5549
+ }
5550
+ if (stored.kind === "unmaterialized-surface" && stored.surface !== void 0) return {
5551
+ surface: stored.surface,
5552
+ profile: null,
5553
+ refusal: stored.refusal ?? null
5554
+ };
5555
+ throw new Error(`improve(): node ${node.nodeId} holds no profile search artifact`);
5556
+ }
5557
+ };
5558
+ }
5559
+ /** Everything that decides which search a call continues. */
5560
+ function searchMethodDescriptor(method) {
5561
+ return {
5562
+ name: method.name,
5563
+ policy: method.policy.name,
5564
+ allocation: method.allocation.name,
5565
+ reps: method.allocation.reps,
5566
+ proposer: method.proposer.kind,
5567
+ maxExpansions: method.maxExpansions,
5568
+ childrenPerProposal: method.childrenPerProposal,
5569
+ lanes: method.lanes.map(({ name, kind, capacity, costCap, cellUsd }) => ({
5570
+ name,
5571
+ kind,
5572
+ capacity,
5573
+ costCap,
5574
+ cellUsd
5575
+ })),
5576
+ claimReserveUsd: method.claimReserveUsd,
5577
+ deadline: method.deadline,
5578
+ maxAttempts: method.maxAttempts
5579
+ };
5580
+ }
5581
+ /**
5582
+ * An environment fault the agent raised settles retryable. The campaign reports every error as
5583
+ * final because it applies its own retry policy; here the kernel owns retries.
5584
+ */
5585
+ function faultResult(result, fault) {
5586
+ if (fault === void 0 || result.outcome.status !== "errored") return result;
5587
+ return {
5588
+ ...result,
5589
+ outcome: {
5590
+ ...result.outcome,
5591
+ error: {
5592
+ code: "environment-fault",
5593
+ message: refusalText(fault),
5594
+ retryable: true
5595
+ }
5596
+ }
5597
+ };
5598
+ }
5599
+ /** A refusal as the ledger stores it: redacted with the share profile. */
5600
+ function refusalText(error) {
5601
+ return redact(error instanceof Error ? error.message : String(error), { profile: "share" }).value;
5602
+ }
5603
+ //#endregion
5604
+ export { sampleThenRefine as $, parseRolloutPolicy as A, officialChecksFromMeta as B, privateValuePaths as C, ROLLOUT_POLICY_EXTENSION as D, isCodeSurface as E, composeCheckSources as F, visibleCheckScore as G, sandboxCheckRunner as H, defaultExtractCandidate as I, defineStrategy as J, adaptiveRefine as K, defaultStructuralRolloutPolicy as L, structuralRolloutPolicyFromProfile as M, canDisplace as N, applyRolloutPolicyToProfile as O, compareCheckOutcomes as P, sample as Q, filterAuthoredAsserts as R, parseExecutionRef as S, assertCandidateSurfaceKind as T, selectBestIndex as U, resolveEntrySymbol as V, structuralRollout as W, refine as X, depthStrategy as Y, runAgentic as Z, sharedBoxRefusal as _, startOrResumeRuntimeSession as _t, SearchEnvironmentFault as a, profileOptimizerModelCall as at, assertCandidateValidator as b, reconcileInterruptedSearchCalls as c, strategyAuthorMethod as ct, sharedBoxLane as d, createIterableBackend as dt, ObservationError as et, subscriptionLane as f, createSandboxPromptBackend as ft, sharedBoxPlacement as g, nowIso as gt, ROUTER_CLIENT_HEADER as h, newRuntimeSession as ht, searchMethod as i, profileChatClient as it, serializeRolloutPolicy as j, normalizeRolloutPolicy as k, routerLane as l, collectAgentTurn as lt, DEFAULT_SHARED_BOX_WORKERS as m, InMemoryRuntimeSessionStore as mt, runSearchImprovement as n, observe as nt, dedicatedLane as o, copyImproveCost as ot, DEFAULT_SHARED_BOX_RESOURCES as p, normalizeBackendStreamEvent as pt, breadthStrategy as q, runtimeShipDecision as r, renderReport as rt, isSearchEnvironmentFault as s, optimizerMethod as st, isImproveSearchMethod as t, defaultAnalystInstruction as tt, searchExecutor as u, streamAgentTurn as ut, sharedWorkerClientName as v, touchSession as vt, validateProfileCandidate as w, assertProfileTrainingIsHeldOut as x, prepareProfileImprovement as y, modelAuthoredChecks as z };
3822
5605
 
3823
- //# sourceMappingURL=shared-box-CZFdugL1.js.map
5606
+ //# sourceMappingURL=search-method-CbUyhdz5.js.map