@tangle-network/agent-runtime 0.301.0 → 0.306.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{activation-V6aaOlZV.js → activation-C5wesfzd.js} +3 -3
- package/dist/{activation-V6aaOlZV.js.map → activation-C5wesfzd.js.map} +1 -1
- package/dist/{activation-CRgEJutr.d.ts → activation-wZ-8vOjV.d.ts} +88 -13
- package/dist/agent.d.ts +2 -2
- package/dist/agent.js +2 -2
- package/dist/{bundle-C9v5TH_H.js → bundle-C8EO05u3.js} +2 -2
- package/dist/{bundle-C9v5TH_H.js.map → bundle-C8EO05u3.js.map} +1 -1
- package/dist/candidate-execution/index.d.ts +3 -26
- package/dist/candidate-execution/index.js +6 -6
- package/dist/{coordination-driver-vNrdQBSH.js → coordination-driver-yj9HPXef.js} +9 -16
- package/dist/coordination-driver-yj9HPXef.js.map +1 -0
- package/dist/{delegate-B-jFJcbW.js → delegate-KtrL9HWq.js} +2 -2
- package/dist/{delegate-B-jFJcbW.js.map → delegate-KtrL9HWq.js.map} +1 -1
- package/dist/durable.d.ts +3 -15
- package/dist/durable.js +158 -124
- package/dist/durable.js.map +1 -1
- package/dist/{graph-Dwv_hQB_.js → graph-DcdyHbgf.js} +4 -5
- package/dist/graph-DcdyHbgf.js.map +1 -0
- package/dist/{improvement-cycle-Cf37Kexd.js → improvement-cycle-DsN-TVXR.js} +1129 -10
- package/dist/improvement-cycle-DsN-TVXR.js.map +1 -0
- package/dist/{index-CxBVmgqL.d.ts → index-DflDZq_I.d.ts} +50 -688
- package/dist/index.d.ts +378 -12
- package/dist/index.js +223 -320
- package/dist/index.js.map +1 -1
- package/dist/intelligence.d.ts +5 -5
- package/dist/intelligence.js +7 -8
- package/dist/intelligence.js.map +1 -1
- package/dist/kernel.d.ts +4 -4
- package/dist/kernel.js +9 -9
- package/dist/{loop-runner-bin-DiTNiJNs.d.ts → loop-runner-bin-DZfRUVWy.d.ts} +3 -3
- package/dist/{loop-runner-bin-C8MI8N1A.js → loop-runner-bin-rVrSX5l1.js} +3 -3
- package/dist/{loop-runner-bin-C8MI8N1A.js.map → loop-runner-bin-rVrSX5l1.js.map} +1 -1
- package/dist/loop-runner-bin.d.ts +1 -1
- package/dist/loop-runner-bin.js +1 -1
- package/dist/mcp/bin.js +3 -3
- package/dist/mcp/index.d.ts +6 -35
- package/dist/mcp/index.js +311 -364
- package/dist/mcp/index.js.map +1 -1
- package/dist/model-policy-DydyWTQg.js.map +1 -1
- package/dist/{openai-tools-BeogJ6V8.d.ts → openai-tools-YO30D2s3.d.ts} +2 -2
- package/dist/{prepare-CGVNMb1o.js → prepare--nWcazPr.js} +7 -13
- package/dist/prepare--nWcazPr.js.map +1 -0
- package/dist/{profile-BetOB4_Q.js → profile-h04LDjV6.js} +2 -2
- package/dist/{profile-BetOB4_Q.js.map → profile-h04LDjV6.js.map} +1 -1
- package/dist/profiles.d.ts +2 -94
- package/dist/profiles.js +2 -451
- package/dist/profiles.js.map +1 -1
- package/dist/{protected-model-port-CAa0t1MT.d.ts → protected-model-port-C9QtEf3y.d.ts} +2 -2
- package/dist/{protected-model-port-CuVHkhti.js → protected-model-port-wwalbyXM.js} +4 -4
- package/dist/{protected-model-port-CuVHkhti.js.map → protected-model-port-wwalbyXM.js.map} +1 -1
- package/dist/{provision-supervisor-CS0fBIhp.js → provision-supervisor-WxFEFQeJ.js} +4 -3
- package/dist/{provision-supervisor-CS0fBIhp.js.map → provision-supervisor-WxFEFQeJ.js.map} +1 -1
- package/dist/{runtime-6VPSJVeg.js → runtime-B9eBIyws.js} +67 -469
- package/dist/runtime-B9eBIyws.js.map +1 -0
- package/dist/{search-method-wTTS7mGG.js → search-executor-2tWr38Qw.js} +239 -1132
- package/dist/search-executor-2tWr38Qw.js.map +1 -0
- package/dist/{server-BfHD5iLD.js → server-CpKcrOPj.js} +5 -12
- package/dist/server-CpKcrOPj.js.map +1 -0
- package/dist/{stream-agent-turn-B1ipFtOc.d.ts → stream-agent-turn-B1giFgOg.d.ts} +2 -2
- package/dist/{substrate-DKBMd0Dl.d.ts → substrate-L_sC7jCD.d.ts} +2 -2
- package/dist/{supervise-BJrEC2Mh.js → supervise-DllOHM4M.js} +14 -24
- package/dist/supervise-DllOHM4M.js.map +1 -0
- package/dist/{supervisor-DA_nvF-h.js → supervisor-gCfG6K1-.js} +488 -1407
- package/dist/supervisor-gCfG6K1-.js.map +1 -0
- package/dist/testing.d.ts +2 -2
- package/dist/testing.js +14 -14
- package/dist/tui/index.d.ts +1 -1
- package/dist/tui/index.js +1 -1
- package/dist/{types-jD9mNnJM.d.ts → types-DeuEkBhI.d.ts} +114 -258
- package/dist/{workspace-archive-pz8YJ1fr.d.ts → workspace-streams-CpSmt3zx.d.ts} +67 -3
- package/dist/{workspace-streams-D5gHJdTb.js → workspace-streams-ILw0eWZ0.js} +694 -2
- package/dist/workspace-streams-ILw0eWZ0.js.map +1 -0
- package/package.json +8 -8
- package/skills/generate-eval/SKILL.md +1 -1
- package/skills/profile-authoring/SKILL.md +2 -2
- package/dist/coordination-driver-vNrdQBSH.js.map +0 -1
- package/dist/graph-Dwv_hQB_.js.map +0 -1
- package/dist/improvement-cycle-Cf37Kexd.js.map +0 -1
- package/dist/prepare-CGVNMb1o.js.map +0 -1
- package/dist/runtime-6VPSJVeg.js.map +0 -1
- package/dist/search-method-wTTS7mGG.js.map +0 -1
- package/dist/server-BfHD5iLD.js.map +0 -1
- package/dist/supervise-BJrEC2Mh.js.map +0 -1
- package/dist/supervisor-DA_nvF-h.js.map +0 -1
- package/dist/workspace-streams-D5gHJdTb.js.map +0 -1
|
@@ -1,23 +1,25 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Bi as detachedSnapshot, Wr as runSettledCommand, fr as linkAbort, ni as terminateProcessTreeAndConfirm, pr as runAbortable, xt as createExecutor } from "./supervisor-gCfG6K1-.js";
|
|
2
2
|
import { i as ConfigError } from "./errors-DodWX-cb.js";
|
|
3
|
-
import {
|
|
3
|
+
import { E as defaultStructuralRolloutPolicy, Q as streamAgentTurn, Y as optimizerMethod, Z as collectAgentTurn, a as reconcileInterruptedSearchCalls, b as improveSearchCost, c as searchExecutor, d as taggedLedger, i as isSearchEnvironmentFault, n as assertSearchLanes, s as searchCallTags, v as decideClosedSearch } from "./search-executor-2tWr38Qw.js";
|
|
4
|
+
import { A as canonicalCandidateBytes$1, F as immutableCandidateValue, I as omitTopLevelDigest, L as sha256Bytes$1, M as canonicalCandidateDocument, R as verifyCanonicalCandidateDocument, _t as armDeadlineTimer, j as canonicalCandidateDigest$1 } from "./workspace-streams-ILw0eWZ0.js";
|
|
4
5
|
import { a as concreteProfileModel, t as assertExecutableAgentProfile } from "./model-policy-DydyWTQg.js";
|
|
5
|
-
import { A as canonicalCandidateDocument, F as sha256Bytes$1, I as verifyCanonicalCandidateDocument, N as immutableCandidateValue, O as canonicalCandidateBytes$1, P as omitTopLevelDigest, k as canonicalCandidateDigest$1 } from "./workspace-streams-D5gHJdTb.js";
|
|
6
6
|
import { i as syncDurableDirectory, r as publishExclusiveDurableFile } from "./durable-file-DWQA4ooo.js";
|
|
7
7
|
import { t as runAnalystLoop } from "./analyst-loop-DZw5QWT9.js";
|
|
8
|
-
import { c as executePreparedAgentCandidate, o as verifiedResourceTextByDigest, s as verifyAgentCandidateBundle, t as prepareAgentCandidateExecution } from "./prepare
|
|
9
|
-
import { a as assertCandidateProfileBinding, c as createAgentCandidateProfileActivation, d as omitUndefinedObjectFields, f as parseAgentCandidateProfileActivation, i as applyExactAgentProfileDiff, p as parseExactAgentProfile, r as agentCandidateProfileAsAgentProfile, u as materializeAgentCandidateProfilePlan } from "./profile-
|
|
10
|
-
import { AGENT_IMPROVEMENT_SOURCE_METADATA_KEY, agentCandidateMaterializationReceiptSchema, agentCandidateRunReceiptSchema, agentImprovementActivationSchema, agentImprovementProposalSchema, agentImprovementReviewSchema, agentImprovementSourceMetadata, agentImprovementSourceSchema, agentProfileDiffSchema, agentProfileEnvironmentSchema, agentProfileImprovementArmSchema, agentProfileImprovementExecutionRefSchema, agentProfileModelHintsSchema, agentProfileSchema, agentProfileTrainingSchema, agentTrainingDatasetIdentitySchema, agentTrainingParametersSchema, agentTrainingReceiptSchema, agentTrainingTaskKey, agentTrainingTaskSchema, candidateExecutionEvidenceSchema, canonicalAgentProfileDigest, canonicalCandidateBytes, changedProfileImprovementSurfaces, defineAgentProfileDiff, numbersApproximatelyEqual, sha256DigestSchema, snapshotAgentProfile, trainedModelIdForArtifact } from "@tangle-network/agent-interface";
|
|
11
|
-
import { CostLedger, makeProposalFinding } from "@tangle-network/agent-eval";
|
|
8
|
+
import { c as executePreparedAgentCandidate, o as verifiedResourceTextByDigest, s as verifyAgentCandidateBundle, t as prepareAgentCandidateExecution } from "./prepare--nWcazPr.js";
|
|
9
|
+
import { a as assertCandidateProfileBinding, c as createAgentCandidateProfileActivation, d as omitUndefinedObjectFields, f as parseAgentCandidateProfileActivation, i as applyExactAgentProfileDiff, p as parseExactAgentProfile, r as agentCandidateProfileAsAgentProfile, u as materializeAgentCandidateProfilePlan } from "./profile-h04LDjV6.js";
|
|
10
|
+
import { AGENT_IMPROVEMENT_SOURCE_METADATA_KEY, agentCandidateMaterializationReceiptSchema, agentCandidateRunReceiptSchema, agentImprovementActivationSchema, agentImprovementProposalSchema, agentImprovementReviewSchema, agentImprovementSourceMetadata, agentImprovementSourceSchema, agentProfileDiffSchema, agentProfileEnvironmentSchema, agentProfileImprovementArmSchema, agentProfileImprovementExecutionRefSchema, agentProfileModelHintsSchema, agentProfileSchema, agentProfileTrainingSchema, agentTrainingDatasetIdentitySchema, agentTrainingParametersSchema, agentTrainingReceiptSchema, agentTrainingTaskKey, agentTrainingTaskSchema, applyAgentProfileDiff, candidateExecutionEvidenceSchema, canonicalAgentProfileDigest, canonicalCandidateBytes, changedProfileImprovementSurfaces, defineAgentProfileDiff, diffAgentProfiles, numbersApproximatelyEqual, sha256DigestSchema, snapshotAgentProfile, trainedModelIdForArtifact } from "@tangle-network/agent-interface";
|
|
11
|
+
import { CostLedger, canonicalJson, makeProposalFinding } from "@tangle-network/agent-eval";
|
|
12
12
|
import { createHash, randomUUID } from "node:crypto";
|
|
13
13
|
import { spawn, spawnSync } from "node:child_process";
|
|
14
14
|
import { constants, existsSync, mkdtempSync, readFileSync, readdirSync, realpathSync, rmSync } from "node:fs";
|
|
15
15
|
import { basename, dirname, isAbsolute, join, resolve } from "node:path";
|
|
16
16
|
import { chmod, mkdir, mkdtemp, open, realpath, rm, writeFile } from "node:fs/promises";
|
|
17
17
|
import { tmpdir } from "node:os";
|
|
18
|
+
import { redact } from "@tangle-network/agent-eval/traces";
|
|
18
19
|
import { assertProposalFindings } from "@tangle-network/agent-eval/analyst";
|
|
19
|
-
import { campaignSplitDigestFromIdentities, compareOptimizationMethods, fsCampaignStorage, gitWorktreeAdapter, verifyCodeSurface, verifySearchHistoryArtifact } from "@tangle-network/agent-eval/campaign";
|
|
20
|
+
import { SearchRecorder, aide, asha, campaignCellSearchResult, campaignScenarioIdentity, campaignSplitDigestFromIdentities, compareOptimizationMethods, createRunCostLedger, fsCampaignStorage, gitWorktreeAdapter, isProposedCandidate, openSearchLedger, renderSearchSummary, resolveRunDir, runCampaign, runSearch, searchClaimReserveUsd, searchNodeId, searchProposalExecution, searchProposerView, searchReceiptAccounting, verifyCodeSurface, verifySearchHistoryArtifact } from "@tangle-network/agent-eval/campaign";
|
|
20
21
|
import { measuredComparisonFromAgentProfileImprovementExperiment, measuredComparisonFromCandidateExperiment, runAgentProfileImprovementExperiment, runCandidateExperiment, sealAgentProfileImprovementExperiment, sealAgentProfileImprovementSuite, sealAgentProfileImprovementTask, sealCandidateExperiment, selfImprove, verifyAgentProfileImprovementExperimentComparison, verifyCandidateExperiment, verifyCandidateExperimentComparison } from "@tangle-network/agent-eval/contract";
|
|
22
|
+
import { defineEvaluationClaim, summarizeEvaluationUnits } from "@tangle-network/agent-eval/experiment";
|
|
21
23
|
//#region src/improvement/worktree-tree.ts
|
|
22
24
|
/**
|
|
23
25
|
* The exact content of a candidate worktree, as a Git tree object.
|
|
@@ -686,6 +688,15 @@ async function rethrowAfterCleanup(cause, cleanup, context) {
|
|
|
686
688
|
throw new AggregateError([cause, ...cleanupErrors], `${context}; cleanup failed`);
|
|
687
689
|
}
|
|
688
690
|
//#endregion
|
|
691
|
+
//#region src/improvement/improve-result.ts
|
|
692
|
+
function copyImproveCost(cost) {
|
|
693
|
+
return {
|
|
694
|
+
totalCostUsd: cost.totalCostUsd,
|
|
695
|
+
accountingComplete: cost.accountingComplete,
|
|
696
|
+
incompleteReasons: [...cost.incompleteReasons]
|
|
697
|
+
};
|
|
698
|
+
}
|
|
699
|
+
//#endregion
|
|
689
700
|
//#region src/improvement/improvement-driver.ts
|
|
690
701
|
/**
|
|
691
702
|
* Code-only candidate driver for Runtime-owned git worktrees.
|
|
@@ -798,6 +809,334 @@ function advanceToIncumbent(worktree, incumbent) {
|
|
|
798
809
|
if (head.error || head.status !== 0 || head.stdout.trim() !== incumbent.candidateCommit) throw new Error("improvementDriver: candidate worktree did not reach the incumbent commit");
|
|
799
810
|
}
|
|
800
811
|
//#endregion
|
|
812
|
+
//#region src/improvement/rollout-policy.ts
|
|
813
|
+
/** The profile extensions namespace the policy persists under. */
|
|
814
|
+
const ROLLOUT_POLICY_EXTENSION = "structural-rollout";
|
|
815
|
+
const isBoundedInt = (v, min) => typeof v === "number" && Number.isInteger(v) && v >= min;
|
|
816
|
+
/** Parse a serialized policy surface. Returns `undefined` for non-strings,
|
|
817
|
+
* malformed JSON, or values outside the policy invariants. Unknown fields are
|
|
818
|
+
* dropped; supported optional fields are preserved. */
|
|
819
|
+
function parseRolloutPolicy(surface) {
|
|
820
|
+
if (typeof surface !== "string" || surface.trim().length === 0) return void 0;
|
|
821
|
+
let raw;
|
|
822
|
+
try {
|
|
823
|
+
raw = JSON.parse(surface);
|
|
824
|
+
} catch {
|
|
825
|
+
return;
|
|
826
|
+
}
|
|
827
|
+
return normalizeRolloutPolicy(raw);
|
|
828
|
+
}
|
|
829
|
+
/** Normalize an untyped policy bag (a parsed surface or a profile extension) into
|
|
830
|
+
* a full `StructuralRolloutPolicy`, defaults merged. Returns `undefined` when any
|
|
831
|
+
* present dial violates the policy invariants (mirrors `resolvePolicy`: integer
|
|
832
|
+
* k ≥ 1, repairRounds ≥ 0, testgen ≥ 0) — a corrupt config must read as "not
|
|
833
|
+
* configured", never as a fabricated recipe. */
|
|
834
|
+
function normalizeRolloutPolicy(raw) {
|
|
835
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return void 0;
|
|
836
|
+
const bag = raw;
|
|
837
|
+
const k = bag.k ?? defaultStructuralRolloutPolicy.k;
|
|
838
|
+
const repairRounds = bag.repairRounds ?? defaultStructuralRolloutPolicy.repairRounds;
|
|
839
|
+
const testgen = bag.testgen ?? defaultStructuralRolloutPolicy.testgen;
|
|
840
|
+
if (!isBoundedInt(k, 1) || !isBoundedInt(repairRounds, 0) || !isBoundedInt(testgen, 0)) return;
|
|
841
|
+
return {
|
|
842
|
+
k,
|
|
843
|
+
repairRounds,
|
|
844
|
+
testgen,
|
|
845
|
+
...typeof bag.diverse === "boolean" ? { diverse: bag.diverse } : {}
|
|
846
|
+
};
|
|
847
|
+
}
|
|
848
|
+
/** Stable serialization with fixed field order. */
|
|
849
|
+
function serializeRolloutPolicy(policy) {
|
|
850
|
+
return JSON.stringify({
|
|
851
|
+
k: policy.k,
|
|
852
|
+
repairRounds: policy.repairRounds,
|
|
853
|
+
testgen: policy.testgen,
|
|
854
|
+
...policy.diverse !== void 0 ? { diverse: policy.diverse } : {}
|
|
855
|
+
});
|
|
856
|
+
}
|
|
857
|
+
/** Read the persisted policy off the profile. `undefined` when the profile does
|
|
858
|
+
* not opt into structural rollout. */
|
|
859
|
+
function structuralRolloutPolicyFromProfile(profile) {
|
|
860
|
+
const bag = profile.extensions?.[ROLLOUT_POLICY_EXTENSION];
|
|
861
|
+
if (bag === void 0) return void 0;
|
|
862
|
+
return normalizeRolloutPolicy(bag);
|
|
863
|
+
}
|
|
864
|
+
/** Persist a detached policy under the profile extension without mutating the input. */
|
|
865
|
+
function applyRolloutPolicyToProfile(profile, policy) {
|
|
866
|
+
const candidate = structuredClone(profile);
|
|
867
|
+
const bag = {
|
|
868
|
+
k: policy.k,
|
|
869
|
+
repairRounds: policy.repairRounds,
|
|
870
|
+
testgen: policy.testgen,
|
|
871
|
+
...policy.diverse !== void 0 ? { diverse: policy.diverse } : {}
|
|
872
|
+
};
|
|
873
|
+
return {
|
|
874
|
+
...candidate,
|
|
875
|
+
extensions: {
|
|
876
|
+
...candidate.extensions,
|
|
877
|
+
[ROLLOUT_POLICY_EXTENSION]: bag
|
|
878
|
+
}
|
|
879
|
+
};
|
|
880
|
+
}
|
|
881
|
+
//#endregion
|
|
882
|
+
//#region src/improvement/profile-surface.ts
|
|
883
|
+
/** Extract the baseline optimized by a method and retain its structured value
|
|
884
|
+
* so external optimizers can inspect it for private fields before serialization. */
|
|
885
|
+
function prepareProfileSurface(profile, surface, skills, profileComponents) {
|
|
886
|
+
switch (surface) {
|
|
887
|
+
case "prompt": return {
|
|
888
|
+
surface: profile.prompt?.systemPrompt ?? "",
|
|
889
|
+
value: profile.prompt?.systemPrompt ?? ""
|
|
890
|
+
};
|
|
891
|
+
case "skills": {
|
|
892
|
+
const value = inlineSkill(profile, skills).content;
|
|
893
|
+
return {
|
|
894
|
+
surface: value,
|
|
895
|
+
value
|
|
896
|
+
};
|
|
897
|
+
}
|
|
898
|
+
case "tools": {
|
|
899
|
+
const value = profile.tools ?? {};
|
|
900
|
+
return {
|
|
901
|
+
surface: canonicalJson(value),
|
|
902
|
+
value
|
|
903
|
+
};
|
|
904
|
+
}
|
|
905
|
+
case "mcp": {
|
|
906
|
+
const value = profile.mcp ?? {};
|
|
907
|
+
return {
|
|
908
|
+
surface: canonicalJson(value),
|
|
909
|
+
value
|
|
910
|
+
};
|
|
911
|
+
}
|
|
912
|
+
case "hooks": {
|
|
913
|
+
const value = profile.hooks ?? {};
|
|
914
|
+
return {
|
|
915
|
+
surface: canonicalJson(value),
|
|
916
|
+
value
|
|
917
|
+
};
|
|
918
|
+
}
|
|
919
|
+
case "subagents": {
|
|
920
|
+
const value = profile.subagents ?? {};
|
|
921
|
+
return {
|
|
922
|
+
surface: canonicalJson(value),
|
|
923
|
+
value
|
|
924
|
+
};
|
|
925
|
+
}
|
|
926
|
+
case "agent-profile":
|
|
927
|
+
if (profileComponents) {
|
|
928
|
+
if (profileComponents.encoding !== void 0 && profileComponents.encoding !== "components" && profileComponents.encoding !== "json") throw new ConfigError("improve(): profileComponents.encoding must be components or json");
|
|
929
|
+
const value = profileComponents.read(profile);
|
|
930
|
+
const components = componentSurface(value, "profileComponents.read");
|
|
931
|
+
return {
|
|
932
|
+
surface: profileComponents.encoding === "json" ? canonicalJson(components.components) : components,
|
|
933
|
+
value
|
|
934
|
+
};
|
|
935
|
+
}
|
|
936
|
+
return {
|
|
937
|
+
surface: canonicalJson(profile),
|
|
938
|
+
value: profile
|
|
939
|
+
};
|
|
940
|
+
case "memory": {
|
|
941
|
+
const value = profileInstructions(profile);
|
|
942
|
+
return {
|
|
943
|
+
surface: value,
|
|
944
|
+
value
|
|
945
|
+
};
|
|
946
|
+
}
|
|
947
|
+
case "rollout-policy": {
|
|
948
|
+
const policy = structuralRolloutPolicyFromProfile(profile);
|
|
949
|
+
return {
|
|
950
|
+
surface: policy ? serializeRolloutPolicy(policy) : "",
|
|
951
|
+
value: policy ?? null
|
|
952
|
+
};
|
|
953
|
+
}
|
|
954
|
+
case "code": throw new ConfigError("improve(): code requires the isolated baseline created from opts.code.repoRoot");
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
function isCodeSurface(surface) {
|
|
958
|
+
return typeof surface === "object" && surface !== null && surface.kind === "code";
|
|
959
|
+
}
|
|
960
|
+
function isComponentSurface(surface) {
|
|
961
|
+
return typeof surface === "object" && surface !== null && surface.kind === "components";
|
|
962
|
+
}
|
|
963
|
+
function componentSurface(components, source) {
|
|
964
|
+
const entries = validateComponents(components, source);
|
|
965
|
+
return immutableCandidateValue({
|
|
966
|
+
kind: "components",
|
|
967
|
+
components: Object.fromEntries(entries)
|
|
968
|
+
});
|
|
969
|
+
}
|
|
970
|
+
function validateComponents(components, source) {
|
|
971
|
+
if (typeof components !== "object" || components === null || Array.isArray(components)) throw new ConfigError(`improve(): ${source} must return a component record`);
|
|
972
|
+
const entries = Object.entries(components);
|
|
973
|
+
if (entries.length === 0) throw new ConfigError(`improve(): ${source} must return at least one component`);
|
|
974
|
+
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`);
|
|
975
|
+
return entries;
|
|
976
|
+
}
|
|
977
|
+
/** Parse a JSON winner surface with a typed, contextual error. */
|
|
978
|
+
function parseWinnerJson(winner, surface) {
|
|
979
|
+
try {
|
|
980
|
+
return JSON.parse(winner);
|
|
981
|
+
} catch (cause) {
|
|
982
|
+
throw new ConfigError(`improve(): the '${surface}' candidate is not valid JSON, so it cannot form a profile candidate: ${cause.message}`);
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
function assertCandidateSurfaceKind(surface, baseline, winner) {
|
|
986
|
+
if (surface === "code") {
|
|
987
|
+
if (isCodeSurface(winner)) return;
|
|
988
|
+
throw new ConfigError(`improve(): the '${surface}' candidate returned an incompatible surface value`);
|
|
989
|
+
}
|
|
990
|
+
if (typeof baseline === "string") {
|
|
991
|
+
if (typeof winner === "string") return;
|
|
992
|
+
throw new ConfigError(`improve(): the '${surface}' candidate changed from a text surface to an incompatible surface value`);
|
|
993
|
+
}
|
|
994
|
+
if (!isComponentSurface(baseline) || !isComponentSurface(winner)) throw new ConfigError(`improve(): the '${surface}' candidate returned an incompatible surface value`);
|
|
995
|
+
validateComponents(winner.components, `the '${surface}' candidate`);
|
|
996
|
+
const baselineNames = Object.keys(baseline.components).sort();
|
|
997
|
+
const winnerNames = Object.keys(winner.components).sort();
|
|
998
|
+
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`);
|
|
999
|
+
}
|
|
1000
|
+
/** Materialize a detached profile candidate without changing the baseline. */
|
|
1001
|
+
function materializeImprovementProfileCandidate(profile, surface, winner, skills, profileComponents) {
|
|
1002
|
+
let candidate;
|
|
1003
|
+
if (isComponentSurface(winner)) {
|
|
1004
|
+
if (surface !== "agent-profile" || !profileComponents) throw new ConfigError(`improve(): the '${surface}' candidate has no profile component mapping`);
|
|
1005
|
+
const winnerComponents = immutableCandidateValue({ ...winner.components });
|
|
1006
|
+
const validated = parseMaterializedProfile(profileComponents.apply(profile, winnerComponents), surface);
|
|
1007
|
+
const materializedComponents = Object.fromEntries(validateComponents(profileComponents.read(validated), "profileComponents.read after apply"));
|
|
1008
|
+
const names = Object.keys(winnerComponents);
|
|
1009
|
+
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");
|
|
1010
|
+
return validated;
|
|
1011
|
+
}
|
|
1012
|
+
if (typeof winner !== "string") throw new ConfigError(`improve(): the '${surface}' candidate cannot form an AgentProfile`);
|
|
1013
|
+
switch (surface) {
|
|
1014
|
+
case "prompt":
|
|
1015
|
+
candidate = {
|
|
1016
|
+
...profile,
|
|
1017
|
+
prompt: {
|
|
1018
|
+
...profile.prompt,
|
|
1019
|
+
systemPrompt: winner
|
|
1020
|
+
}
|
|
1021
|
+
};
|
|
1022
|
+
break;
|
|
1023
|
+
case "skills": {
|
|
1024
|
+
const selectedSkill = inlineSkill(profile, skills);
|
|
1025
|
+
candidate = {
|
|
1026
|
+
...profile,
|
|
1027
|
+
resources: {
|
|
1028
|
+
...profile.resources,
|
|
1029
|
+
skills: profile.resources?.skills?.map((resource) => resource === selectedSkill ? {
|
|
1030
|
+
...resource,
|
|
1031
|
+
content: winner
|
|
1032
|
+
} : resource)
|
|
1033
|
+
}
|
|
1034
|
+
};
|
|
1035
|
+
break;
|
|
1036
|
+
}
|
|
1037
|
+
case "tools":
|
|
1038
|
+
candidate = {
|
|
1039
|
+
...profile,
|
|
1040
|
+
tools: parseWinnerJson(winner, surface)
|
|
1041
|
+
};
|
|
1042
|
+
break;
|
|
1043
|
+
case "mcp":
|
|
1044
|
+
candidate = {
|
|
1045
|
+
...profile,
|
|
1046
|
+
mcp: parseWinnerJson(winner, surface)
|
|
1047
|
+
};
|
|
1048
|
+
break;
|
|
1049
|
+
case "hooks":
|
|
1050
|
+
candidate = {
|
|
1051
|
+
...profile,
|
|
1052
|
+
hooks: parseWinnerJson(winner, surface)
|
|
1053
|
+
};
|
|
1054
|
+
break;
|
|
1055
|
+
case "subagents":
|
|
1056
|
+
candidate = {
|
|
1057
|
+
...profile,
|
|
1058
|
+
subagents: parseWinnerJson(winner, surface)
|
|
1059
|
+
};
|
|
1060
|
+
break;
|
|
1061
|
+
case "agent-profile":
|
|
1062
|
+
candidate = parseWinnerJson(winner, surface);
|
|
1063
|
+
break;
|
|
1064
|
+
case "memory":
|
|
1065
|
+
candidate = {
|
|
1066
|
+
...profile,
|
|
1067
|
+
resources: {
|
|
1068
|
+
...profile.resources,
|
|
1069
|
+
instructions: replaceProfileInstructions(profile, winner)
|
|
1070
|
+
}
|
|
1071
|
+
};
|
|
1072
|
+
break;
|
|
1073
|
+
case "rollout-policy": {
|
|
1074
|
+
const policy = normalizeRolloutPolicy(parseWinnerJson(winner, surface));
|
|
1075
|
+
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}`);
|
|
1076
|
+
candidate = applyRolloutPolicyToProfile(profile, policy);
|
|
1077
|
+
break;
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
return parseMaterializedProfile(candidate, surface);
|
|
1081
|
+
}
|
|
1082
|
+
function parseMaterializedProfile(candidate, surface) {
|
|
1083
|
+
const parsed = agentProfileSchema.safeParse(candidate);
|
|
1084
|
+
if (!parsed.success) throw new ConfigError(`improve(): the '${surface}' candidate does not produce a valid AgentProfile: ${parsed.error.message}`);
|
|
1085
|
+
return immutableCandidateValue(parsed.data);
|
|
1086
|
+
}
|
|
1087
|
+
function createProfileCandidateMaterializer(profile, surface, baselineSurface, skills, profileComponents) {
|
|
1088
|
+
const decode = (candidate) => {
|
|
1089
|
+
if (profileComponents?.encoding !== "json") return candidate;
|
|
1090
|
+
if (typeof candidate !== "string") throw new ConfigError("improve(): JSON profile components require a text surface");
|
|
1091
|
+
return componentSurface(parseWinnerJson(candidate, surface), "JSON profile components");
|
|
1092
|
+
};
|
|
1093
|
+
const decodedBaseline = decode(baselineSurface);
|
|
1094
|
+
const baselineDigest = canonicalCandidateDigest$1(baselineSurface);
|
|
1095
|
+
if (profileComponents) {
|
|
1096
|
+
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");
|
|
1097
|
+
}
|
|
1098
|
+
const candidates = /* @__PURE__ */ new Map([[baselineDigest, profile]]);
|
|
1099
|
+
return (candidateSurface) => {
|
|
1100
|
+
assertCandidateSurfaceKind(surface, baselineSurface, candidateSurface);
|
|
1101
|
+
const decodedCandidate = decode(candidateSurface);
|
|
1102
|
+
assertCandidateSurfaceKind(surface, decodedBaseline, decodedCandidate);
|
|
1103
|
+
const digest = canonicalCandidateDigest$1(candidateSurface);
|
|
1104
|
+
const existing = candidates.get(digest);
|
|
1105
|
+
if (existing) return existing;
|
|
1106
|
+
const candidate = materializeImprovementProfileCandidate(profile, surface, immutableCandidateValue(decodedCandidate), skills, profileComponents);
|
|
1107
|
+
candidates.set(digest, candidate);
|
|
1108
|
+
return candidate;
|
|
1109
|
+
};
|
|
1110
|
+
}
|
|
1111
|
+
function inlineSkill(profile, options) {
|
|
1112
|
+
const resourceName = options?.resourceName.trim();
|
|
1113
|
+
if (!resourceName) throw new ConfigError("improve(): surface 'skills' requires opts.skills.resourceName for one inline profile skill");
|
|
1114
|
+
assertFailClosedResources(profile, "skills");
|
|
1115
|
+
const matches = (profile.resources?.skills ?? []).filter((resource) => resource.name === resourceName);
|
|
1116
|
+
if (matches.length !== 1 || matches[0]?.kind !== "inline") throw new ConfigError(`improve(): skill '${resourceName}' must identify exactly one inline profile resource`);
|
|
1117
|
+
return matches[0];
|
|
1118
|
+
}
|
|
1119
|
+
function profileInstructions(profile) {
|
|
1120
|
+
assertFailClosedResources(profile, "memory");
|
|
1121
|
+
const instructions = profile.resources?.instructions;
|
|
1122
|
+
if (instructions === void 0) return "";
|
|
1123
|
+
if (typeof instructions === "string") return instructions;
|
|
1124
|
+
if (instructions.kind === "inline") return instructions.content;
|
|
1125
|
+
throw new ConfigError("improve(): surface 'memory' requires inline profile instructions so candidate bytes are exact");
|
|
1126
|
+
}
|
|
1127
|
+
function replaceProfileInstructions(profile, content) {
|
|
1128
|
+
const instructions = profile.resources?.instructions;
|
|
1129
|
+
if (typeof instructions !== "object") return content;
|
|
1130
|
+
if (instructions.kind !== "inline") throw new ConfigError("improve(): surface 'memory' requires inline profile instructions so candidate bytes are exact");
|
|
1131
|
+
return {
|
|
1132
|
+
...instructions,
|
|
1133
|
+
content
|
|
1134
|
+
};
|
|
1135
|
+
}
|
|
1136
|
+
function assertFailClosedResources(profile, surface) {
|
|
1137
|
+
if (profile.resources?.failOnError !== true) throw new ConfigError(`improve(): surface '${surface}' requires profile.resources.failOnError: true`);
|
|
1138
|
+
}
|
|
1139
|
+
//#endregion
|
|
801
1140
|
//#region src/improvement/raw-trace-distiller.ts
|
|
802
1141
|
/**
|
|
803
1142
|
*
|
|
@@ -1342,6 +1681,233 @@ function methodHistoricalReceipts(ledger, optimizerRun, invocationId) {
|
|
|
1342
1681
|
return ledger.list({ tags: { optimizerRun } }).filter((receipt) => receipt.tags?.[INVOCATION_TAG] !== invocationId);
|
|
1343
1682
|
}
|
|
1344
1683
|
//#endregion
|
|
1684
|
+
//#region src/improvement/candidate-validation.ts
|
|
1685
|
+
/** One spelling of the execution-identity rule for optimization, training, and the harness. */
|
|
1686
|
+
function parseExecutionRef(value, label) {
|
|
1687
|
+
const parsed = sha256DigestSchema.safeParse(value);
|
|
1688
|
+
if (!parsed.success) throw new ConfigError(`${label}: executionRef must be a lowercase sha256:<64 hex> digest`);
|
|
1689
|
+
return parsed.data;
|
|
1690
|
+
}
|
|
1691
|
+
/** Validate the callback itself before any optimizer, trainer, or candidate work starts. */
|
|
1692
|
+
function assertCandidateValidator(validator) {
|
|
1693
|
+
if (validator !== void 0 && typeof validator !== "function") throw new ConfigError("validateCandidate must be a function when present");
|
|
1694
|
+
}
|
|
1695
|
+
/** A validator accepts synchronously by returning void, or rejects by throwing. */
|
|
1696
|
+
function validateProfileCandidate(validator, input) {
|
|
1697
|
+
assertCandidateValidator(validator);
|
|
1698
|
+
const result = validator?.(Object.freeze(input));
|
|
1699
|
+
if (result !== void 0) {
|
|
1700
|
+
Promise.resolve(result).catch(() => {});
|
|
1701
|
+
throw new ConfigError("candidate validators must return void synchronously or throw");
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
/**
|
|
1705
|
+
* Refuse exact held-out content digests already declared in this profile's training lineage.
|
|
1706
|
+
* Both training and trainer-visible validation rows are exposure. This is an exact
|
|
1707
|
+
* provenance check, not fuzzy decontamination or proof that undeclared training was fresh.
|
|
1708
|
+
*/
|
|
1709
|
+
function assertProfileTrainingIsHeldOut(profile, heldOutDigests) {
|
|
1710
|
+
const training = profile.metadata?.training;
|
|
1711
|
+
if (!training) return;
|
|
1712
|
+
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");
|
|
1713
|
+
}
|
|
1714
|
+
/**
|
|
1715
|
+
* JSON paths of credential and private values in candidate content, found by
|
|
1716
|
+
* the redaction core, which names each value it would change. A candidate that
|
|
1717
|
+
* leaves Runtime (an external optimizer, a search ledger) is refused on any.
|
|
1718
|
+
*/
|
|
1719
|
+
function privateValuePaths(values) {
|
|
1720
|
+
return [...new Set(values.flatMap((value) => redact(value).report.findings.map((finding) => jsonPathOf(finding.path))))];
|
|
1721
|
+
}
|
|
1722
|
+
/** `/remote/url` or `/tools/0/env` as `$.remote.url` or `$.tools[0].env`. */
|
|
1723
|
+
function jsonPathOf(pointer) {
|
|
1724
|
+
return pointer.split("/").slice(1).map((segment) => segment.replaceAll("~1", "/").replaceAll("~0", "~")).reduce((path, segment) => /^\d+$/.test(segment) ? `${path}[${segment}]` : `${path}.${segment}`, "$");
|
|
1725
|
+
}
|
|
1726
|
+
//#endregion
|
|
1727
|
+
//#region src/improvement/method-identity.ts
|
|
1728
|
+
function buildMethodEvaluationIdentity(input) {
|
|
1729
|
+
const optimizationReps = input.optimizationRunOptions?.reps ?? 1;
|
|
1730
|
+
const finalTestReps = input.reps ?? 1;
|
|
1731
|
+
const scenarioPartitions = immutableCandidateValue({
|
|
1732
|
+
train: input.trainScenarios.map(campaignScenarioIdentity),
|
|
1733
|
+
selection: input.selectionScenarios.map(campaignScenarioIdentity),
|
|
1734
|
+
finalTest: input.testScenarios.map(campaignScenarioIdentity),
|
|
1735
|
+
optimizationReps,
|
|
1736
|
+
finalTestReps
|
|
1737
|
+
});
|
|
1738
|
+
const developmentSplitDigest = canonicalCandidateDigest$1({
|
|
1739
|
+
train: campaignSplitDigestFromIdentities(scenarioPartitions.train, optimizationReps),
|
|
1740
|
+
selection: campaignSplitDigestFromIdentities(scenarioPartitions.selection, optimizationReps)
|
|
1741
|
+
});
|
|
1742
|
+
const finalTestSplitDigest = campaignSplitDigestFromIdentities(scenarioPartitions.finalTest, finalTestReps);
|
|
1743
|
+
const judgeDescriptors = input.judges.map(judgeDescriptor);
|
|
1744
|
+
return {
|
|
1745
|
+
evaluationRef: canonicalCandidateDigest$1({
|
|
1746
|
+
executionRef: input.executionRef,
|
|
1747
|
+
baselineProfileDigest: input.baselineProfileDigest,
|
|
1748
|
+
coordinate: profileCoordinate(input.surface, input.baselineSurface, input.skills),
|
|
1749
|
+
candidateValidation: input.validateCandidate ? Function.prototype.toString.call(input.validateCandidate) : null,
|
|
1750
|
+
developmentSplitDigest,
|
|
1751
|
+
finalTestSplitDigest,
|
|
1752
|
+
findings: input.findings,
|
|
1753
|
+
judges: judgeDescriptors,
|
|
1754
|
+
run: {
|
|
1755
|
+
seed: input.seed ?? 42,
|
|
1756
|
+
finalReps: input.reps ?? 1,
|
|
1757
|
+
optimizationReps,
|
|
1758
|
+
costCeiling: input.costCeiling ?? null,
|
|
1759
|
+
resumable: input.optimizationRunOptions?.resumable ?? true,
|
|
1760
|
+
maxConcurrency: input.optimizationRunOptions?.maxConcurrency ?? 2,
|
|
1761
|
+
abortOnCellError: input.optimizationRunOptions?.abortOnCellError ?? false,
|
|
1762
|
+
dispatchTimeoutMs: input.optimizationRunOptions?.dispatchTimeoutMs ?? null,
|
|
1763
|
+
dispatchShutdownTimeoutMs: input.optimizationRunOptions?.dispatchShutdownTimeoutMs ?? 5e3,
|
|
1764
|
+
tracing: input.optimizationRunOptions?.tracing ?? "on",
|
|
1765
|
+
expectUsage: input.optimizationRunOptions?.expectUsage ?? "warn",
|
|
1766
|
+
captureSource: input.optimizationRunOptions?.captureSource ?? null,
|
|
1767
|
+
captureSourceVersionHash: input.optimizationRunOptions?.captureSourceVersionHash ?? null
|
|
1768
|
+
}
|
|
1769
|
+
}),
|
|
1770
|
+
developmentSplitDigest,
|
|
1771
|
+
finalTestSplitDigest,
|
|
1772
|
+
scenarioPartitions,
|
|
1773
|
+
judgeDescriptors
|
|
1774
|
+
};
|
|
1775
|
+
}
|
|
1776
|
+
function profileCoordinate(surface, baselineSurface, skills) {
|
|
1777
|
+
return {
|
|
1778
|
+
surface,
|
|
1779
|
+
resourceName: surface === "skills" ? skills?.resourceName.trim() ?? null : null,
|
|
1780
|
+
componentNames: typeof baselineSurface === "object" && baselineSurface !== null && baselineSurface.kind === "components" ? Object.keys(baselineSurface.components).sort() : []
|
|
1781
|
+
};
|
|
1782
|
+
}
|
|
1783
|
+
function judgeDescriptor(judge) {
|
|
1784
|
+
return {
|
|
1785
|
+
name: judge.name,
|
|
1786
|
+
dimensions: judge.dimensions.map((dimension) => ({ ...dimension })),
|
|
1787
|
+
declaredVersion: judge.judgeVersion ?? null,
|
|
1788
|
+
scoreImplementation: Function.prototype.toString.call(judge.score),
|
|
1789
|
+
appliesToImplementation: judge.appliesTo ? Function.prototype.toString.call(judge.appliesTo) : null
|
|
1790
|
+
};
|
|
1791
|
+
}
|
|
1792
|
+
//#endregion
|
|
1793
|
+
//#region src/improvement/profile-improvement.ts
|
|
1794
|
+
/**
|
|
1795
|
+
* What every profile improvement prepares before any optimizer or search runs:
|
|
1796
|
+
* the exact surface and its baseline, the evaluation identity, identified
|
|
1797
|
+
* judges, the identities a search ledger records, and one materializer that
|
|
1798
|
+
* admits a candidate only after the held-out and caller checks. `improve()`
|
|
1799
|
+
* with an external method and with `searchMethod` share it, so a candidate is
|
|
1800
|
+
* materialized and admitted the same way on both paths.
|
|
1801
|
+
*/
|
|
1802
|
+
function prepareProfileImprovement(profile, input) {
|
|
1803
|
+
const { surface = "prompt", validateCandidate, skills, profileComponents, minimumLift = 0 } = input;
|
|
1804
|
+
assertCandidateValidator(validateCandidate);
|
|
1805
|
+
if (!Number.isFinite(minimumLift) || minimumLift < 0) throw new ConfigError("improve(): minimumLift must be a finite number greater than or equal to 0");
|
|
1806
|
+
if (profileComponents && surface !== "agent-profile") throw new ConfigError("improve(): profileComponents is valid only with surface 'agent-profile'");
|
|
1807
|
+
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");
|
|
1808
|
+
const executionRef = parseExecutionRef(input.executionRef, "improve()");
|
|
1809
|
+
const findings = immutableCandidateValue([...assertProposalFindings(input.findings ?? [], "improve() method findings")]);
|
|
1810
|
+
const preparedSurface = prepareProfileSurface(profile, surface, skills, profileComponents);
|
|
1811
|
+
const baselineSurface = preparedSurface.surface;
|
|
1812
|
+
const baselineValue = immutableCandidateValue(preparedSurface.value);
|
|
1813
|
+
const baselineProfileDigest = canonicalAgentProfileDigest(profile);
|
|
1814
|
+
const identity = buildMethodEvaluationIdentity({
|
|
1815
|
+
executionRef,
|
|
1816
|
+
baselineProfileDigest,
|
|
1817
|
+
baselineSurface,
|
|
1818
|
+
surface,
|
|
1819
|
+
skills,
|
|
1820
|
+
validateCandidate,
|
|
1821
|
+
findings,
|
|
1822
|
+
trainScenarios: input.trainScenarios,
|
|
1823
|
+
selectionScenarios: input.selectionScenarios,
|
|
1824
|
+
testScenarios: input.testScenarios,
|
|
1825
|
+
judges: input.judges,
|
|
1826
|
+
seed: input.seed,
|
|
1827
|
+
reps: input.reps,
|
|
1828
|
+
costCeiling: input.costCeiling,
|
|
1829
|
+
optimizationRunOptions: input.optimizationRunOptions
|
|
1830
|
+
});
|
|
1831
|
+
const judges = input.judges.map((judge, index) => Object.freeze({
|
|
1832
|
+
...judge,
|
|
1833
|
+
judgeVersion: canonicalCandidateDigest$1({
|
|
1834
|
+
evaluationRef: identity.evaluationRef,
|
|
1835
|
+
descriptor: identity.judgeDescriptors[index]
|
|
1836
|
+
})
|
|
1837
|
+
}));
|
|
1838
|
+
const rawMaterializeProfile = createProfileCandidateMaterializer(profile, surface, baselineSurface, skills, profileComponents);
|
|
1839
|
+
const baselineSurfaceDigest = canonicalCandidateDigest$1(baselineSurface);
|
|
1840
|
+
const heldOutDigests = new Set(identity.scenarioPartitions.finalTest.map((task) => task.scenarioDigest));
|
|
1841
|
+
const validatedCandidates = /* @__PURE__ */ new Set();
|
|
1842
|
+
const validateMaterialized = (validator, candidate, candidateSurface, isBaseline) => {
|
|
1843
|
+
const prepared = prepareProfileSurface(candidate, surface, skills, profileComponents);
|
|
1844
|
+
validateProfileCandidate(validator, {
|
|
1845
|
+
profile: candidate,
|
|
1846
|
+
surface,
|
|
1847
|
+
candidateSurface,
|
|
1848
|
+
value: immutableCandidateValue(prepared.value),
|
|
1849
|
+
isBaseline
|
|
1850
|
+
});
|
|
1851
|
+
};
|
|
1852
|
+
const admitCandidate = (candidate, candidateSurface) => {
|
|
1853
|
+
const candidateDigest = canonicalCandidateDigest$1(candidateSurface);
|
|
1854
|
+
if (validatedCandidates.has(candidateDigest)) return;
|
|
1855
|
+
assertProfileTrainingIsHeldOut(candidate, heldOutDigests);
|
|
1856
|
+
validateMaterialized(validateCandidate, candidate, immutableCandidateValue(candidateSurface), candidateDigest === baselineSurfaceDigest);
|
|
1857
|
+
validatedCandidates.add(candidateDigest);
|
|
1858
|
+
};
|
|
1859
|
+
const materializeProfile = (candidateSurface) => {
|
|
1860
|
+
const candidate = rawMaterializeProfile(candidateSurface);
|
|
1861
|
+
admitCandidate(candidate, candidateSurface);
|
|
1862
|
+
return candidate;
|
|
1863
|
+
};
|
|
1864
|
+
materializeProfile(baselineSurface);
|
|
1865
|
+
return {
|
|
1866
|
+
profile,
|
|
1867
|
+
surface,
|
|
1868
|
+
executionRef,
|
|
1869
|
+
findings,
|
|
1870
|
+
minimumLift,
|
|
1871
|
+
baselineSurface,
|
|
1872
|
+
baselineValue,
|
|
1873
|
+
baselineProfileDigest,
|
|
1874
|
+
identity,
|
|
1875
|
+
invocationId: `runtime-optimization:${randomUUID()}`,
|
|
1876
|
+
judges,
|
|
1877
|
+
searchIdentity: Object.freeze({
|
|
1878
|
+
subject: input.subject ?? profile.name ?? "agent-profile",
|
|
1879
|
+
agent: {
|
|
1880
|
+
uri: "agent-runtime:improve-execution-ref",
|
|
1881
|
+
revision: executionRef
|
|
1882
|
+
},
|
|
1883
|
+
judge: {
|
|
1884
|
+
uri: "agent-runtime:improve-judges",
|
|
1885
|
+
revision: canonicalCandidateDigest$1(identity.judgeDescriptors)
|
|
1886
|
+
},
|
|
1887
|
+
model: profileModel(profile)
|
|
1888
|
+
}),
|
|
1889
|
+
surfaceOf: (candidate) => prepareProfileSurface(candidate, surface, skills, profileComponents).surface,
|
|
1890
|
+
materializeCandidate: rawMaterializeProfile,
|
|
1891
|
+
admitCandidate,
|
|
1892
|
+
materializeProfile,
|
|
1893
|
+
validateMaterialized
|
|
1894
|
+
};
|
|
1895
|
+
}
|
|
1896
|
+
/** The profile's model hint as a moving alias; each cell records what it resolved. */
|
|
1897
|
+
function profileModel(profile) {
|
|
1898
|
+
const hint = profile.model?.default;
|
|
1899
|
+
if (!hint) return {
|
|
1900
|
+
provider: "unspecified",
|
|
1901
|
+
alias: "unspecified",
|
|
1902
|
+
unknown: "the profile names no model; each cell records the model it resolved"
|
|
1903
|
+
};
|
|
1904
|
+
return {
|
|
1905
|
+
provider: profile.model?.provider ?? "unspecified",
|
|
1906
|
+
alias: hint,
|
|
1907
|
+
unknown: "the profile names a model hint, not a snapshot; each cell records the model it resolved"
|
|
1908
|
+
};
|
|
1909
|
+
}
|
|
1910
|
+
//#endregion
|
|
1345
1911
|
//#region src/improvement/method-execution.ts
|
|
1346
1912
|
function resolveOptimizationMethod(source, context) {
|
|
1347
1913
|
const method = typeof source === "function" ? source(context) : source;
|
|
@@ -1478,6 +2044,559 @@ async function runMethodImprovement(profile, opts) {
|
|
|
1478
2044
|
};
|
|
1479
2045
|
}
|
|
1480
2046
|
//#endregion
|
|
2047
|
+
//#region src/improvement/search-method.ts
|
|
2048
|
+
/** Build Runtime's native search for `improve(profile, { method })`. */
|
|
2049
|
+
function searchMethod(options) {
|
|
2050
|
+
if (!options || typeof options !== "object") throw new ConfigError("searchMethod(): options are required");
|
|
2051
|
+
const { proposer } = options;
|
|
2052
|
+
if (!proposer || typeof proposer.kind !== "string" || typeof proposer.propose !== "function") throw new ConfigError("searchMethod(): proposer must be a SurfaceProposer");
|
|
2053
|
+
const count = (name, value, fallback, min) => {
|
|
2054
|
+
const resolved = value ?? fallback;
|
|
2055
|
+
if (!Number.isSafeInteger(resolved) || resolved < min) throw new ConfigError(`searchMethod(): ${name} must be an integer of at least ${min}`);
|
|
2056
|
+
return resolved;
|
|
2057
|
+
};
|
|
2058
|
+
const dollars = (name, value) => {
|
|
2059
|
+
if (value === void 0) return null;
|
|
2060
|
+
if (!Number.isFinite(value) || value < 0) throw new ConfigError(`searchMethod(): ${name} must be a finite non-negative number`);
|
|
2061
|
+
return value;
|
|
2062
|
+
};
|
|
2063
|
+
if (options.deadline !== void 0 && !Number.isFinite(Date.parse(options.deadline))) throw new ConfigError("searchMethod(): deadline must be an ISO time");
|
|
2064
|
+
const name = options.name ?? "search";
|
|
2065
|
+
if (!name.trim() || name.trim() !== name) throw new ConfigError("searchMethod(): name must be a trimmed non-empty string");
|
|
2066
|
+
assertSearchLanes(options.lanes, "searchMethod()");
|
|
2067
|
+
return Object.freeze({
|
|
2068
|
+
kind: "search",
|
|
2069
|
+
name,
|
|
2070
|
+
policy: options.policy ?? aide(),
|
|
2071
|
+
allocation: options.allocation ?? asha(),
|
|
2072
|
+
proposer,
|
|
2073
|
+
maxExpansions: count("maxExpansions", options.maxExpansions, NaN, 0),
|
|
2074
|
+
childrenPerProposal: count("childrenPerProposal", options.childrenPerProposal, 1, 1),
|
|
2075
|
+
lanes: Object.freeze([...options.lanes]),
|
|
2076
|
+
claimReserveUsd: dollars("claimReserveUsd", options.claimReserveUsd),
|
|
2077
|
+
deadline: options.deadline === void 0 ? null : new Date(options.deadline).toISOString(),
|
|
2078
|
+
maxAttempts: count("maxAttempts", options.maxAttempts, 3, 1)
|
|
2079
|
+
});
|
|
2080
|
+
}
|
|
2081
|
+
function isImproveSearchMethod(value) {
|
|
2082
|
+
return typeof value === "object" && value !== null && value.kind === "search";
|
|
2083
|
+
}
|
|
2084
|
+
const SEARCH_METHOD_SOURCE = {
|
|
2085
|
+
uri: "npm:@tangle-network/agent-runtime#searchMethod",
|
|
2086
|
+
revision: canonicalCandidateDigest$1({
|
|
2087
|
+
name: "agent-runtime.search-method.2026-09",
|
|
2088
|
+
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",
|
|
2089
|
+
edge: "the Interface diffs from the parent profile to the child, stored when they reproduce the child digest",
|
|
2090
|
+
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",
|
|
2091
|
+
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",
|
|
2092
|
+
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",
|
|
2093
|
+
proposer: "a SurfaceProposer reads the parents, the train view and the train summary; paid calls it makes are its operation accounting"
|
|
2094
|
+
})
|
|
2095
|
+
};
|
|
2096
|
+
async function runSearchImprovement(profile, opts) {
|
|
2097
|
+
const { method, claim: inputClaim, agent, executionRunId, recordCell, 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;
|
|
2098
|
+
if (!isImproveSearchMethod(method)) throw new ConfigError("improve(): a search needs method: searchMethod(...)");
|
|
2099
|
+
const claim = defineEvaluationClaim(inputClaim);
|
|
2100
|
+
if (claim.minimumEffect === void 0) throw new ConfigError("improve(): a search claim needs minimumEffect for its power check");
|
|
2101
|
+
for (const [name, split] of [
|
|
2102
|
+
["trainScenarios", trainScenarios],
|
|
2103
|
+
["selectionScenarios", selectionScenarios],
|
|
2104
|
+
["testScenarios", testScenarios]
|
|
2105
|
+
]) if (!Array.isArray(split) || split.length === 0) throw new ConfigError(`improve(): a search needs at least one of ${name}`);
|
|
2106
|
+
const { allocation, policy, lanes } = method;
|
|
2107
|
+
const reps = allocation.reps;
|
|
2108
|
+
const concurrency = lanes.reduce((total, lane) => total + lane.capacity, 0);
|
|
2109
|
+
const prepared = prepareProfileImprovement(profile, {
|
|
2110
|
+
...opts,
|
|
2111
|
+
seed,
|
|
2112
|
+
reps,
|
|
2113
|
+
optimizationRunOptions: {
|
|
2114
|
+
reps,
|
|
2115
|
+
maxConcurrency: concurrency
|
|
2116
|
+
}
|
|
2117
|
+
});
|
|
2118
|
+
const { evaluationRef } = prepared.identity;
|
|
2119
|
+
const storage = campaignOptions.storage ?? fsCampaignStorage();
|
|
2120
|
+
const runDir = resolveRunDir(campaignOptions.runDir, campaignOptions.repo);
|
|
2121
|
+
const searchId = `improve-${canonicalCandidateDigest$1({
|
|
2122
|
+
evaluationRef,
|
|
2123
|
+
process: SEARCH_METHOD_SOURCE,
|
|
2124
|
+
method: searchMethodDescriptor(method)
|
|
2125
|
+
}).slice(7, 31)}`;
|
|
2126
|
+
const searchDir = `${runDir}/search/${searchId}`;
|
|
2127
|
+
const costLedger = inputCostLedger ?? createRunCostLedger({
|
|
2128
|
+
storage,
|
|
2129
|
+
runDir: searchDir,
|
|
2130
|
+
costCeilingUsd: costCeiling
|
|
2131
|
+
});
|
|
2132
|
+
const unitOf = (scenario) => summarizeEvaluationUnits(claim, [scenario]).units[0].id;
|
|
2133
|
+
const tasks = (scenarios) => scenarios.map((scenario) => ({
|
|
2134
|
+
taskId: scenario.id,
|
|
2135
|
+
unitId: unitOf(scenario),
|
|
2136
|
+
source: {
|
|
2137
|
+
uri: `scenario://${scenario.id}`,
|
|
2138
|
+
revision: canonicalCandidateDigest$1(scenario)
|
|
2139
|
+
}
|
|
2140
|
+
}));
|
|
2141
|
+
const splits = {
|
|
2142
|
+
train: tasks(trainScenarios),
|
|
2143
|
+
selection: tasks(selectionScenarios),
|
|
2144
|
+
test: tasks(testScenarios)
|
|
2145
|
+
};
|
|
2146
|
+
const developmentUnits = new Set([...splits.train, ...splits.selection].map((task) => task.unitId));
|
|
2147
|
+
const execution = {
|
|
2148
|
+
model: prepared.searchIdentity.model,
|
|
2149
|
+
agent: prepared.searchIdentity.agent,
|
|
2150
|
+
benchmark: {
|
|
2151
|
+
uri: "agent-runtime:improve-splits",
|
|
2152
|
+
revision: canonicalCandidateDigest$1({
|
|
2153
|
+
development: prepared.identity.developmentSplitDigest,
|
|
2154
|
+
test: prepared.identity.finalTestSplitDigest
|
|
2155
|
+
})
|
|
2156
|
+
}
|
|
2157
|
+
};
|
|
2158
|
+
const reservedClaimUsd = Math.max(method.claimReserveUsd ?? 0, searchClaimReserveUsd({
|
|
2159
|
+
testTasks: splits.test.length,
|
|
2160
|
+
reps,
|
|
2161
|
+
cellUsd: Math.max(...lanes.map((lane) => lane.cellUsd))
|
|
2162
|
+
}));
|
|
2163
|
+
const recorder = await SearchRecorder.open({
|
|
2164
|
+
ledger: storage.kind === "filesystem" ? openSearchLedger({
|
|
2165
|
+
path: `${searchDir}/ledger.jsonl`,
|
|
2166
|
+
searchId
|
|
2167
|
+
}) : openSearchLedger({
|
|
2168
|
+
path: `${searchDir}/ledger.jsonl`,
|
|
2169
|
+
searchId,
|
|
2170
|
+
store: storage
|
|
2171
|
+
}),
|
|
2172
|
+
storage
|
|
2173
|
+
}, {
|
|
2174
|
+
subject: prepared.searchIdentity.subject,
|
|
2175
|
+
process: {
|
|
2176
|
+
name: method.name,
|
|
2177
|
+
executionRef: SEARCH_METHOD_SOURCE
|
|
2178
|
+
},
|
|
2179
|
+
artifactKind: "agent-profile",
|
|
2180
|
+
objective: {
|
|
2181
|
+
metric: "composite",
|
|
2182
|
+
direction: "maximize",
|
|
2183
|
+
judge: prepared.searchIdentity.judge,
|
|
2184
|
+
claim
|
|
2185
|
+
},
|
|
2186
|
+
splits: {
|
|
2187
|
+
...splits,
|
|
2188
|
+
heldOutUnits: splits.test.every((task) => !developmentUnits.has(task.unitId))
|
|
2189
|
+
},
|
|
2190
|
+
policy: {
|
|
2191
|
+
expansion: policy.name,
|
|
2192
|
+
allocation: allocation.name,
|
|
2193
|
+
seed
|
|
2194
|
+
},
|
|
2195
|
+
budget: {
|
|
2196
|
+
maxUsd: costCeiling ?? null,
|
|
2197
|
+
maxCells: null,
|
|
2198
|
+
maxNodes: 1 + method.maxExpansions * method.childrenPerProposal,
|
|
2199
|
+
deadline: method.deadline,
|
|
2200
|
+
maxConcurrency: concurrency,
|
|
2201
|
+
reservedClaimUsd: costCeiling === void 0 ? 0 : reservedClaimUsd
|
|
2202
|
+
},
|
|
2203
|
+
containment: null,
|
|
2204
|
+
derivedFrom: null,
|
|
2205
|
+
identity: execution
|
|
2206
|
+
});
|
|
2207
|
+
const nodeOf = (candidateSurface) => {
|
|
2208
|
+
const surface = immutableCandidateValue(candidateSurface);
|
|
2209
|
+
try {
|
|
2210
|
+
return {
|
|
2211
|
+
surface,
|
|
2212
|
+
profile: prepared.materializeCandidate(surface),
|
|
2213
|
+
refusal: null
|
|
2214
|
+
};
|
|
2215
|
+
} catch (error) {
|
|
2216
|
+
return {
|
|
2217
|
+
surface,
|
|
2218
|
+
profile: null,
|
|
2219
|
+
refusal: refusalText(error)
|
|
2220
|
+
};
|
|
2221
|
+
}
|
|
2222
|
+
};
|
|
2223
|
+
const profiles = /* @__PURE__ */ new Map();
|
|
2224
|
+
const profiled = profileCodec(prepared);
|
|
2225
|
+
const codec = {
|
|
2226
|
+
node(recorder, node) {
|
|
2227
|
+
const registered = profiled.node(recorder, node);
|
|
2228
|
+
profiles.set(searchNodeId(searchId, registered.artifactDigest), node.profile);
|
|
2229
|
+
return registered;
|
|
2230
|
+
},
|
|
2231
|
+
diff: profiled.diff,
|
|
2232
|
+
load(recorder, node) {
|
|
2233
|
+
const loaded = profiled.load(recorder, node);
|
|
2234
|
+
profiles.set(node.nodeId, loaded.profile);
|
|
2235
|
+
return loaded;
|
|
2236
|
+
}
|
|
2237
|
+
};
|
|
2238
|
+
for (const node of (await recorder.state()).nodes()) codec.load(recorder, node);
|
|
2239
|
+
await reconcileInterruptedSearchCalls(costLedger, searchId, lanes);
|
|
2240
|
+
const laneRefusal = (nodeProfile) => {
|
|
2241
|
+
const refusals = lanes.map((lane) => `${lane.name}: ${lane.refusal(nodeProfile)}`);
|
|
2242
|
+
return lanes.some((lane) => lane.refusal(nodeProfile) === void 0) ? null : `no lane can run the profile (${refusals.join("; ")})`;
|
|
2243
|
+
};
|
|
2244
|
+
const root = nodeOf(prepared.baselineSurface);
|
|
2245
|
+
if (root.profile) {
|
|
2246
|
+
const refused = laneRefusal(root.profile);
|
|
2247
|
+
if (refused) throw new ConfigError(`improve(): the baseline profile cannot run: ${refused}`);
|
|
2248
|
+
}
|
|
2249
|
+
const scenarios = [
|
|
2250
|
+
...trainScenarios,
|
|
2251
|
+
...selectionScenarios,
|
|
2252
|
+
...testScenarios
|
|
2253
|
+
];
|
|
2254
|
+
const scenarioIds = /* @__PURE__ */ new Set();
|
|
2255
|
+
for (const scenario of scenarios) {
|
|
2256
|
+
if (scenarioIds.has(scenario.id)) throw new ConfigError(`improve(): scenario '${scenario.id}' appears in more than one split`);
|
|
2257
|
+
scenarioIds.add(scenario.id);
|
|
2258
|
+
}
|
|
2259
|
+
const executor = searchExecutor({
|
|
2260
|
+
lanes,
|
|
2261
|
+
profileOf(nodeId) {
|
|
2262
|
+
const known = profiles.get(nodeId);
|
|
2263
|
+
if (known === void 0) throw new Error(`improve(): node ${nodeId} was placed unregistered`);
|
|
2264
|
+
return known;
|
|
2265
|
+
},
|
|
2266
|
+
costLedger,
|
|
2267
|
+
identity: execution,
|
|
2268
|
+
storage,
|
|
2269
|
+
dir: searchDir,
|
|
2270
|
+
...workerSlots ? { workerSlots } : {},
|
|
2271
|
+
...budgetPool ? { budgetPool } : {},
|
|
2272
|
+
...trace ? { trace } : {},
|
|
2273
|
+
async runAttempt({ work, lane, context, costLedger: cellLedger, span }) {
|
|
2274
|
+
const nodeProfile = work.artifact.profile;
|
|
2275
|
+
if (!nodeProfile) throw new Error(`improve(): refused node ${work.nodeId} was given a cell`);
|
|
2276
|
+
const profileDigest = canonicalAgentProfileDigest(nodeProfile);
|
|
2277
|
+
let fault;
|
|
2278
|
+
const cell = (await runCampaign({
|
|
2279
|
+
...campaignOptions,
|
|
2280
|
+
...lane.kind === "subscription" && campaignOptions.expectUsage === void 0 ? { expectUsage: "off" } : {},
|
|
2281
|
+
scenarios,
|
|
2282
|
+
judges: prepared.judges.map((judge) => ({
|
|
2283
|
+
...judge,
|
|
2284
|
+
async score(input) {
|
|
2285
|
+
try {
|
|
2286
|
+
return await judge.score(input);
|
|
2287
|
+
} catch (error) {
|
|
2288
|
+
if (isSearchEnvironmentFault(error)) fault = error;
|
|
2289
|
+
throw error;
|
|
2290
|
+
}
|
|
2291
|
+
}
|
|
2292
|
+
})),
|
|
2293
|
+
seed,
|
|
2294
|
+
reps,
|
|
2295
|
+
storage,
|
|
2296
|
+
runDir: `${searchDir}/nodes/${profileDigest.slice(7)}`,
|
|
2297
|
+
dispatchRef: `improve:${evaluationRef}:${profileDigest}`,
|
|
2298
|
+
async dispatch(scenario, ctx) {
|
|
2299
|
+
try {
|
|
2300
|
+
return await agent(nodeProfile, scenario, {
|
|
2301
|
+
...ctx,
|
|
2302
|
+
search: context
|
|
2303
|
+
});
|
|
2304
|
+
} catch (error) {
|
|
2305
|
+
if (isSearchEnvironmentFault(error)) fault = error;
|
|
2306
|
+
throw error;
|
|
2307
|
+
}
|
|
2308
|
+
},
|
|
2309
|
+
cellFilter: ({ scenario, rep }) => scenario.id === work.taskId && rep === work.rep,
|
|
2310
|
+
resumable: true,
|
|
2311
|
+
maxConcurrency: 1,
|
|
2312
|
+
costLedger: cellLedger,
|
|
2313
|
+
costPhase: `search.${work.stage}`,
|
|
2314
|
+
buildTraceWriter: () => ({
|
|
2315
|
+
span,
|
|
2316
|
+
flush: async () => {}
|
|
2317
|
+
}),
|
|
2318
|
+
signal: work.signal
|
|
2319
|
+
})).cells[0];
|
|
2320
|
+
if (!cell) throw new Error(`improve(): cell ${work.cellId} produced no campaign cell`);
|
|
2321
|
+
const result = campaignCellSearchResult(cell, {
|
|
2322
|
+
execution,
|
|
2323
|
+
lane: lane.name
|
|
2324
|
+
});
|
|
2325
|
+
const execRunId = cell.error ? null : executionRunId?.(cell.artifact) ?? null;
|
|
2326
|
+
const settled = faultResult(execRunId && context.trace ? {
|
|
2327
|
+
...result,
|
|
2328
|
+
traceRef: {
|
|
2329
|
+
traceId: context.trace.traceId,
|
|
2330
|
+
execRunId,
|
|
2331
|
+
spansWritten: null,
|
|
2332
|
+
spansDropped: null
|
|
2333
|
+
}
|
|
2334
|
+
} : result, fault);
|
|
2335
|
+
return recordCell && settled.outcome.status !== "errored" ? {
|
|
2336
|
+
...settled,
|
|
2337
|
+
recordCell: (finalResult) => recordCell({
|
|
2338
|
+
cell,
|
|
2339
|
+
search: context,
|
|
2340
|
+
result: finalResult
|
|
2341
|
+
})
|
|
2342
|
+
} : settled;
|
|
2343
|
+
}
|
|
2344
|
+
});
|
|
2345
|
+
const { proposer } = method;
|
|
2346
|
+
const proposerSource = {
|
|
2347
|
+
uri: `proposer:${proposer.kind}`,
|
|
2348
|
+
revision: canonicalCandidateDigest$1({
|
|
2349
|
+
kind: proposer.kind,
|
|
2350
|
+
propose: Function.prototype.toString.call(proposer.propose),
|
|
2351
|
+
decide: proposer.decide ? Function.prototype.toString.call(proposer.decide) : null
|
|
2352
|
+
})
|
|
2353
|
+
};
|
|
2354
|
+
const proposalPhase = "search.proposal";
|
|
2355
|
+
const port = {
|
|
2356
|
+
name: proposer.kind,
|
|
2357
|
+
kind: "optimizer",
|
|
2358
|
+
source: proposerSource,
|
|
2359
|
+
execution: {
|
|
2360
|
+
kind: "deterministic",
|
|
2361
|
+
source: proposerSource
|
|
2362
|
+
},
|
|
2363
|
+
childrenPerProposal: method.childrenPerProposal,
|
|
2364
|
+
async propose(request) {
|
|
2365
|
+
const tags = searchCallTags(searchId, { operation: request.operationId });
|
|
2366
|
+
const state = await recorder.state();
|
|
2367
|
+
const parents = request.parents.map(({ nodeId, artifact }) => ({
|
|
2368
|
+
nodeId,
|
|
2369
|
+
artifact: artifact.surface
|
|
2370
|
+
}));
|
|
2371
|
+
const context = Object.freeze({
|
|
2372
|
+
currentSurface: parents[0]?.artifact ?? prepared.baselineSurface,
|
|
2373
|
+
operator: request.operator,
|
|
2374
|
+
parents,
|
|
2375
|
+
train: searchProposerView(state),
|
|
2376
|
+
summary: renderSearchSummary(state, { split: "train" }),
|
|
2377
|
+
history: [],
|
|
2378
|
+
findings: prepared.findings,
|
|
2379
|
+
populationSize: method.childrenPerProposal,
|
|
2380
|
+
generation: request.expansion,
|
|
2381
|
+
signal: request.signal,
|
|
2382
|
+
costLedger: taggedLedger(costLedger, tags),
|
|
2383
|
+
costPhase: proposalPhase
|
|
2384
|
+
});
|
|
2385
|
+
const decision = proposer.decide?.({ history: [] });
|
|
2386
|
+
const proposed = decision?.stop ? [] : await proposer.propose(context);
|
|
2387
|
+
if (!Array.isArray(proposed)) throw new ConfigError("improve(): the search proposer must return an array");
|
|
2388
|
+
const fresh = costLedger.list({
|
|
2389
|
+
phase: proposalPhase,
|
|
2390
|
+
tags
|
|
2391
|
+
});
|
|
2392
|
+
return {
|
|
2393
|
+
children: proposed.slice(0, method.childrenPerProposal).map((child) => isProposedCandidate(child) ? {
|
|
2394
|
+
artifact: nodeOf(child.surface),
|
|
2395
|
+
label: child.label,
|
|
2396
|
+
rationale: child.rationale,
|
|
2397
|
+
...child.attribution ? { attribution: child.attribution } : {}
|
|
2398
|
+
} : {
|
|
2399
|
+
artifact: nodeOf(child),
|
|
2400
|
+
label: "",
|
|
2401
|
+
rationale: ""
|
|
2402
|
+
}),
|
|
2403
|
+
...decision?.stop ? { stop: decision.reason ?? "the proposer decided to stop" } : {},
|
|
2404
|
+
accounting: searchReceiptAccounting(fresh),
|
|
2405
|
+
execution: searchProposalExecution(fresh, prepared.searchIdentity.model.provider, proposerSource)
|
|
2406
|
+
};
|
|
2407
|
+
}
|
|
2408
|
+
};
|
|
2409
|
+
const admit = (node) => {
|
|
2410
|
+
if (node.refusal !== null || node.profile === null) return node.refusal;
|
|
2411
|
+
try {
|
|
2412
|
+
prepared.admitCandidate(node.profile, node.surface);
|
|
2413
|
+
} catch (error) {
|
|
2414
|
+
return refusalText(error);
|
|
2415
|
+
}
|
|
2416
|
+
const paths = privateValuePaths([node.surface]);
|
|
2417
|
+
if (paths.length > 0) return `the surface carries a credential or private value at ${paths.slice(0, 8).join(", ")}`;
|
|
2418
|
+
return laneRefusal(node.profile);
|
|
2419
|
+
};
|
|
2420
|
+
const startedAt = Date.now();
|
|
2421
|
+
const result = await runSearch({
|
|
2422
|
+
recorder,
|
|
2423
|
+
root,
|
|
2424
|
+
codec,
|
|
2425
|
+
policy,
|
|
2426
|
+
allocation,
|
|
2427
|
+
proposer: port,
|
|
2428
|
+
executor,
|
|
2429
|
+
admit,
|
|
2430
|
+
maxExpansions: method.maxExpansions,
|
|
2431
|
+
maxAttempts: method.maxAttempts,
|
|
2432
|
+
...signal ? { signal } : {}
|
|
2433
|
+
});
|
|
2434
|
+
const { state } = result;
|
|
2435
|
+
const claimResult = result.claim;
|
|
2436
|
+
if (!claimResult || !result.claimVerification) throw new Error(`improve(): search ${searchId} closed without a claim`);
|
|
2437
|
+
const kept = codec.load(recorder, state.node(result.leader));
|
|
2438
|
+
if (!kept.profile) throw new Error(`improve(): search ${searchId} kept a refused node`);
|
|
2439
|
+
const candidate = Object.freeze({
|
|
2440
|
+
surface: prepared.surface,
|
|
2441
|
+
value: kept.surface,
|
|
2442
|
+
profile: kept.profile
|
|
2443
|
+
});
|
|
2444
|
+
const cost = improveSearchCost(costLedger);
|
|
2445
|
+
const decided = await decideClosedSearch({
|
|
2446
|
+
state,
|
|
2447
|
+
claim: claimResult,
|
|
2448
|
+
claimVerification: result.claimVerification,
|
|
2449
|
+
cost,
|
|
2450
|
+
costCeiling,
|
|
2451
|
+
minimumLift: prepared.minimumLift,
|
|
2452
|
+
profileOf(nodeId) {
|
|
2453
|
+
const node = state.node(nodeId);
|
|
2454
|
+
const loaded = node ? codec.load(recorder, node) : null;
|
|
2455
|
+
if (!loaded?.profile) throw new Error(`improve(): search ${searchId} node ${nodeId} holds no profile`);
|
|
2456
|
+
return loaded.profile;
|
|
2457
|
+
}
|
|
2458
|
+
});
|
|
2459
|
+
return {
|
|
2460
|
+
mode: "search",
|
|
2461
|
+
method: method.name,
|
|
2462
|
+
candidate,
|
|
2463
|
+
...decided,
|
|
2464
|
+
claim: claimResult,
|
|
2465
|
+
claimVerification: result.claimVerification,
|
|
2466
|
+
searchHistory: recorder.receipt({
|
|
2467
|
+
producerId: method.name,
|
|
2468
|
+
runId: searchId
|
|
2469
|
+
}),
|
|
2470
|
+
cost,
|
|
2471
|
+
durationMs: Date.now() - startedAt,
|
|
2472
|
+
lineage: Object.freeze({
|
|
2473
|
+
invocationId: prepared.invocationId,
|
|
2474
|
+
runId: searchId,
|
|
2475
|
+
developmentSplitDigest: prepared.identity.developmentSplitDigest,
|
|
2476
|
+
finalTestSplitDigest: prepared.identity.finalTestSplitDigest,
|
|
2477
|
+
scenarioPartitions: prepared.identity.scenarioPartitions,
|
|
2478
|
+
executionRef: prepared.executionRef,
|
|
2479
|
+
baselineProfileDigest: prepared.baselineProfileDigest
|
|
2480
|
+
}),
|
|
2481
|
+
async dispose() {}
|
|
2482
|
+
};
|
|
2483
|
+
}
|
|
2484
|
+
/** Profiles as search artifacts: nodes by profile digest, edges by profile diffs. */
|
|
2485
|
+
function profileCodec(prepared) {
|
|
2486
|
+
const surfaceId = prepared.surface;
|
|
2487
|
+
return {
|
|
2488
|
+
node(recorder, node) {
|
|
2489
|
+
if (node.profile) {
|
|
2490
|
+
const artifact = recorder.blob("agent-profile", {
|
|
2491
|
+
kind: "agent-profile",
|
|
2492
|
+
profile: node.profile
|
|
2493
|
+
});
|
|
2494
|
+
return {
|
|
2495
|
+
artifactDigest: canonicalAgentProfileDigest(node.profile),
|
|
2496
|
+
artifact,
|
|
2497
|
+
surfaces: [{
|
|
2498
|
+
surfaceId,
|
|
2499
|
+
kind: "agent-profile",
|
|
2500
|
+
artifact
|
|
2501
|
+
}]
|
|
2502
|
+
};
|
|
2503
|
+
}
|
|
2504
|
+
const artifact = recorder.blob("surface", {
|
|
2505
|
+
kind: "unmaterialized-surface",
|
|
2506
|
+
surface: node.surface,
|
|
2507
|
+
refusal: node.refusal
|
|
2508
|
+
});
|
|
2509
|
+
return {
|
|
2510
|
+
artifactDigest: canonicalCandidateDigest$1({
|
|
2511
|
+
kind: "unmaterialized-surface",
|
|
2512
|
+
surface: node.surface
|
|
2513
|
+
}),
|
|
2514
|
+
artifact,
|
|
2515
|
+
surfaces: [{
|
|
2516
|
+
surfaceId,
|
|
2517
|
+
kind: "agent-profile",
|
|
2518
|
+
artifact
|
|
2519
|
+
}]
|
|
2520
|
+
};
|
|
2521
|
+
},
|
|
2522
|
+
diff(recorder, parent, child) {
|
|
2523
|
+
if (!parent.profile || !child.profile) return { unknown: "a surface that does not materialize has no profile to diff" };
|
|
2524
|
+
const diffs = diffAgentProfiles(parent.profile, child.profile);
|
|
2525
|
+
const to = canonicalAgentProfileDigest(child.profile);
|
|
2526
|
+
if (canonicalAgentProfileDigest(diffs.reduce(applyAgentProfileDiff, parent.profile)) !== to) return { unknown: "the Interface profile diffs do not reproduce the child profile" };
|
|
2527
|
+
return recorder.blob("diff", {
|
|
2528
|
+
kind: "agent-profile-diff",
|
|
2529
|
+
from: canonicalAgentProfileDigest(parent.profile),
|
|
2530
|
+
to,
|
|
2531
|
+
diffs
|
|
2532
|
+
});
|
|
2533
|
+
},
|
|
2534
|
+
load(recorder, node) {
|
|
2535
|
+
const stored = recorder.readBlob(node.artifact);
|
|
2536
|
+
if (stored.kind === "agent-profile") {
|
|
2537
|
+
const parsed = agentProfileSchema.safeParse(stored.profile);
|
|
2538
|
+
if (!parsed.success) throw new Error(`improve(): node ${node.nodeId} holds an invalid AgentProfile`);
|
|
2539
|
+
const loaded = immutableCandidateValue(parsed.data);
|
|
2540
|
+
return {
|
|
2541
|
+
surface: prepared.surfaceOf(loaded),
|
|
2542
|
+
profile: loaded,
|
|
2543
|
+
refusal: null
|
|
2544
|
+
};
|
|
2545
|
+
}
|
|
2546
|
+
if (stored.kind === "unmaterialized-surface" && stored.surface !== void 0) return {
|
|
2547
|
+
surface: stored.surface,
|
|
2548
|
+
profile: null,
|
|
2549
|
+
refusal: stored.refusal ?? null
|
|
2550
|
+
};
|
|
2551
|
+
throw new Error(`improve(): node ${node.nodeId} holds no profile search artifact`);
|
|
2552
|
+
}
|
|
2553
|
+
};
|
|
2554
|
+
}
|
|
2555
|
+
/** Everything that decides which search a call continues. */
|
|
2556
|
+
function searchMethodDescriptor(method) {
|
|
2557
|
+
return {
|
|
2558
|
+
name: method.name,
|
|
2559
|
+
policy: method.policy.name,
|
|
2560
|
+
allocation: method.allocation.name,
|
|
2561
|
+
reps: method.allocation.reps,
|
|
2562
|
+
proposer: method.proposer.kind,
|
|
2563
|
+
maxExpansions: method.maxExpansions,
|
|
2564
|
+
childrenPerProposal: method.childrenPerProposal,
|
|
2565
|
+
lanes: method.lanes.map(({ name, kind, capacity, costCap, cellUsd }) => ({
|
|
2566
|
+
name,
|
|
2567
|
+
kind,
|
|
2568
|
+
capacity,
|
|
2569
|
+
costCap,
|
|
2570
|
+
cellUsd
|
|
2571
|
+
})),
|
|
2572
|
+
claimReserveUsd: method.claimReserveUsd,
|
|
2573
|
+
deadline: method.deadline,
|
|
2574
|
+
maxAttempts: method.maxAttempts
|
|
2575
|
+
};
|
|
2576
|
+
}
|
|
2577
|
+
/**
|
|
2578
|
+
* An environment fault the agent raised settles retryable. The campaign reports every error as
|
|
2579
|
+
* final because it applies its own retry policy; here the kernel owns retries.
|
|
2580
|
+
*/
|
|
2581
|
+
function faultResult(result, fault) {
|
|
2582
|
+
if (fault === void 0 || result.outcome.status !== "errored") return result;
|
|
2583
|
+
return {
|
|
2584
|
+
...result,
|
|
2585
|
+
outcome: {
|
|
2586
|
+
...result.outcome,
|
|
2587
|
+
error: {
|
|
2588
|
+
code: "environment-fault",
|
|
2589
|
+
message: refusalText(fault),
|
|
2590
|
+
retryable: true
|
|
2591
|
+
}
|
|
2592
|
+
}
|
|
2593
|
+
};
|
|
2594
|
+
}
|
|
2595
|
+
/** A refusal as the ledger stores it: redacted with the share profile. */
|
|
2596
|
+
function refusalText(error) {
|
|
2597
|
+
return redact(error instanceof Error ? error.message : String(error), { profile: "share" }).value;
|
|
2598
|
+
}
|
|
2599
|
+
//#endregion
|
|
1481
2600
|
//#region src/improvement/training.ts
|
|
1482
2601
|
function positiveLimit(value, label) {
|
|
1483
2602
|
if (!Number.isSafeInteger(value) || value <= 0) throw new Error(`invalid ${label}`);
|
|
@@ -3096,6 +4215,6 @@ function sameOrderedValues(left, right) {
|
|
|
3096
4215
|
return left.length === right.length && left.every((value, index) => value === right[index]);
|
|
3097
4216
|
}
|
|
3098
4217
|
//#endregion
|
|
3099
|
-
export { agentImprovementTargetInput as A,
|
|
4218
|
+
export { commandVerifier as $, agentImprovementTargetInput as A, assertCandidateValidator as B, optimizationActivationReceiptFromMetadata as C, agentImprovementProfileSurfaceDigest as D, agentImprovementProfileDiffs as E, isAgentImprovementProfileSurface as F, rawTraceDistiller as G, parseExecutionRef as H, isAgentProfileMeasuredSurface as I, normalizeRolloutPolicy as J, ROLLOUT_POLICY_EXTENSION as K, improve as L, agentProfileImprovementStateDigest as M, assertProfileImprovementTargetsShareIdentity as N, agentImprovementProfileSurfaceInput as O, buildAgentImprovementActivationTargets as P, agenticGenerator as Q, createCommandProfileTrainer as R, createOptimizationActivationReceipt as S, AGENT_PROFILE_MEASURED_SURFACES as T, privateValuePaths as U, assertProfileTrainingIsHeldOut as V, withMethodRuntimeControls as W, serializeRolloutPolicy as X, parseRolloutPolicy as Y, structuralRolloutPolicyFromProfile as Z, profilePolicyWithBudget as _, executeAgentCandidateExperimentCell as a, profileTaskScenarioIdentity as b, requireSealedCandidateExperiment as c, verifyAgentImprovementActivation as d, defaultBuildPrompt as et, verifyAgentImprovementProposal as f, profileImprovementMetadata as g, createProfileImprovementCostLedger as h, createAgentImprovementProposal as i, agentImprovementTargetProfileDiffs as j, agentImprovementTargetDigest as k, reviewAgentImprovementProposal as l, verifyCandidateExecutionEvidence as m, createAgentImprovementActivation as n, proposeAgentImprovement as o, verifyAgentImprovementReview as p, applyRolloutPolicyToProfile as q, createAgentImprovementMeasuredComparison as r, proposeAgentProfileImprovement as s, AgentCandidateExperimentCellExecutionError as t, runAgentCandidateExperiment as u, profilePreparationAccounting as v, AGENT_IMPROVEMENT_PROFILE_SURFACES as w, sealProfileImprovementBenchmark as x, profileStateDigest as y, searchMethod as z };
|
|
3100
4219
|
|
|
3101
|
-
//# sourceMappingURL=improvement-cycle-
|
|
4220
|
+
//# sourceMappingURL=improvement-cycle-DsN-TVXR.js.map
|