@tangle-network/agent-runtime 0.104.0 → 0.105.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.
- package/README.md +176 -42
- package/dist/agent.js +4 -4
- package/dist/candidate-execution/index.d.ts +2 -2
- package/dist/candidate-execution/index.js +4 -4
- package/dist/{chunk-2QJSNOGK.js → chunk-C5RTIBNZ.js} +2 -2
- package/dist/{chunk-SNSMRT6H.js → chunk-CTRA64LY.js} +3 -3
- package/dist/{chunk-ZXICDSAK.js → chunk-H5QPIZNX.js} +2 -2
- package/dist/{chunk-2X65HYMI.js → chunk-HLKC4UYB.js} +1 -13
- package/dist/chunk-HLKC4UYB.js.map +1 -0
- package/dist/{chunk-3PPVCS75.js → chunk-HNP72PNU.js} +3 -10
- package/dist/chunk-HNP72PNU.js.map +1 -0
- package/dist/chunk-OPVWXJ2H.js +75 -0
- package/dist/chunk-OPVWXJ2H.js.map +1 -0
- package/dist/{chunk-B7K7V22Y.js → chunk-RDOAVVHY.js} +2 -2
- package/dist/{chunk-L5DST3QC.js → chunk-SMQXZGLZ.js} +1 -1
- package/dist/chunk-SMQXZGLZ.js.map +1 -0
- package/dist/{chunk-FJI3EXU3.js → chunk-UHEZW5BU.js} +1104 -588
- package/dist/chunk-UHEZW5BU.js.map +1 -0
- package/dist/{chunk-HAO4CXHP.js → chunk-VISA6CI3.js} +3 -3
- package/dist/{chunk-2UABGGUB.js → chunk-WMTCUOQL.js} +5 -5
- package/dist/{chunk-ATDFUJYI.js → chunk-WRTOVNN4.js} +4 -4
- package/dist/{chunk-ATDFUJYI.js.map → chunk-WRTOVNN4.js.map} +1 -1
- package/dist/{chunk-SBTWKPVR.js → chunk-WSTRQZYQ.js} +1 -1
- package/dist/chunk-WSTRQZYQ.js.map +1 -0
- package/dist/{chunk-5HNDYWUT.js → chunk-XBG2W2VW.js} +13 -3
- package/dist/chunk-XBG2W2VW.js.map +1 -0
- package/dist/{chunk-STJEHM5F.js → chunk-YJZA2BIK.js} +2 -2
- package/dist/{chunk-STJEHM5F.js.map → chunk-YJZA2BIK.js.map} +1 -1
- package/dist/{completion-gate-Bv47cOnn.d.ts → completion-gate-BMy5LGoP.d.ts} +1 -1
- package/dist/{coordination-CxtzMxSM.d.ts → coordination-BZZSVYpZ.d.ts} +2 -2
- package/dist/index.d.ts +101 -177
- package/dist/index.js +373 -235
- package/dist/index.js.map +1 -1
- package/dist/intelligence.d.ts +49 -40
- package/dist/intelligence.js +14 -57
- package/dist/intelligence.js.map +1 -1
- package/dist/knowledge.d.ts +4 -4
- package/dist/knowledge.js +8 -8
- package/dist/{local-harness-CtK9dSny.d.ts → local-harness-BDNcl6jI.d.ts} +1 -1
- package/dist/{loop-runner-bin-DUOGtvOl.d.ts → loop-runner-bin-68aoM9-7.d.ts} +3 -11
- package/dist/loop-runner-bin.d.ts +4 -6
- package/dist/loop-runner-bin.js +5 -5
- package/dist/loops.d.ts +11 -11
- package/dist/loops.js +5 -5
- package/dist/mcp/bin.js +2 -2
- package/dist/mcp/index.d.ts +7 -8
- package/dist/mcp/index.js +6 -6
- package/dist/mcp/memory-bin.js +1 -1
- package/dist/primeintellect/index.d.ts +2 -3
- package/dist/primeintellect/index.js +5 -6
- package/dist/primeintellect/index.js.map +1 -1
- package/dist/{protected-model-port-DzkUY3HQ.d.ts → protected-model-port-B4t-OQjL.d.ts} +1 -1
- package/dist/{improve--2A0gK1-.d.ts → redact-BuFjxBUJ.d.ts} +201 -160
- package/dist/{structural-rollout-C4mabf87.d.ts → structural-rollout-DEh6CEsa.d.ts} +2 -2
- package/dist/{supervise-7q9F5brx.d.ts → supervise-4_48wwvy.d.ts} +2 -2
- package/dist/testing.js +9 -9
- package/dist/testing.js.map +1 -1
- package/dist/{worktree-fanout-WsOzt8qu.d.ts → worktree-fanout-DxhAWr5Z.d.ts} +2 -2
- package/package.json +6 -5
- package/skills/build-with-agent-runtime/SKILL.md +15 -9
- package/skills/loop-writer/SKILL.md +1 -1
- package/dist/chunk-2X65HYMI.js.map +0 -1
- package/dist/chunk-3PPVCS75.js.map +0 -1
- package/dist/chunk-5HNDYWUT.js.map +0 -1
- package/dist/chunk-FJI3EXU3.js.map +0 -1
- package/dist/chunk-L5DST3QC.js.map +0 -1
- package/dist/chunk-SBTWKPVR.js.map +0 -1
- /package/dist/{chunk-2QJSNOGK.js.map → chunk-C5RTIBNZ.js.map} +0 -0
- /package/dist/{chunk-SNSMRT6H.js.map → chunk-CTRA64LY.js.map} +0 -0
- /package/dist/{chunk-ZXICDSAK.js.map → chunk-H5QPIZNX.js.map} +0 -0
- /package/dist/{chunk-B7K7V22Y.js.map → chunk-RDOAVVHY.js.map} +0 -0
- /package/dist/{chunk-HAO4CXHP.js.map → chunk-VISA6CI3.js.map} +0 -0
- /package/dist/{chunk-2UABGGUB.js.map → chunk-WMTCUOQL.js.map} +0 -0
|
@@ -16,17 +16,16 @@ import {
|
|
|
16
16
|
verifiedResourceTextByDigest,
|
|
17
17
|
verifyAgentCandidateBundle,
|
|
18
18
|
verifyCanonicalCandidateDocument
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-WSTRQZYQ.js";
|
|
20
20
|
import {
|
|
21
21
|
defaultStructuralRolloutPolicy,
|
|
22
22
|
optimizerMethod
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-YJZA2BIK.js";
|
|
24
24
|
import {
|
|
25
|
-
assertModelAllowed,
|
|
26
25
|
harnessInvocation,
|
|
27
26
|
runLocalHarness,
|
|
28
27
|
runSettledCommand
|
|
29
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-HLKC4UYB.js";
|
|
30
29
|
import {
|
|
31
30
|
runAnalystLoop
|
|
32
31
|
} from "./chunk-FD2MBMOH.js";
|
|
@@ -70,7 +69,7 @@ function agenticGenerator(opts = {}) {
|
|
|
70
69
|
kind: `agentic:${harness}`,
|
|
71
70
|
// The seed repo + (in rawTraceContext mode) the raw-trace filesystem context
|
|
72
71
|
// are the change signal — an agentic coder proposes from them even when the
|
|
73
|
-
// distiller yielded zero findings. Without this, the
|
|
72
|
+
// distiller yielded zero findings. Without this, the code candidate driver's
|
|
74
73
|
// empty-findings guard short-circuits and generates ZERO candidates on the
|
|
75
74
|
// first (and, for a single-generation run, only) proposal round.
|
|
76
75
|
proposesWithoutFindings: true,
|
|
@@ -758,148 +757,63 @@ function toAnalystFindings(findings, opts = {}) {
|
|
|
758
757
|
return out;
|
|
759
758
|
}
|
|
760
759
|
|
|
761
|
-
// src/improvement/
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
try {
|
|
772
|
-
await cleanup();
|
|
773
|
-
} catch (cleanupCause) {
|
|
774
|
-
cleanupErrors.push(cleanupCause);
|
|
775
|
-
continue;
|
|
776
|
-
}
|
|
777
|
-
if (cleanupErrors.length === 0) throw cause;
|
|
778
|
-
throw new AggregateError([cause, ...cleanupErrors], `${context}; cleanup retry succeeded`);
|
|
760
|
+
// src/improvement/rollout-policy.ts
|
|
761
|
+
var ROLLOUT_POLICY_EXTENSION = "structural-rollout";
|
|
762
|
+
var isBoundedInt = (v, min) => typeof v === "number" && Number.isInteger(v) && v >= min;
|
|
763
|
+
function parseRolloutPolicy(surface) {
|
|
764
|
+
if (typeof surface !== "string" || surface.trim().length === 0) return void 0;
|
|
765
|
+
let raw;
|
|
766
|
+
try {
|
|
767
|
+
raw = JSON.parse(surface);
|
|
768
|
+
} catch {
|
|
769
|
+
return void 0;
|
|
779
770
|
}
|
|
780
|
-
|
|
771
|
+
return normalizeRolloutPolicy(raw);
|
|
781
772
|
}
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
const
|
|
786
|
-
const
|
|
773
|
+
function normalizeRolloutPolicy(raw) {
|
|
774
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return void 0;
|
|
775
|
+
const bag = raw;
|
|
776
|
+
const k = bag.k ?? defaultStructuralRolloutPolicy.k;
|
|
777
|
+
const repairRounds = bag.repairRounds ?? defaultStructuralRolloutPolicy.repairRounds;
|
|
778
|
+
const testgen = bag.testgen ?? defaultStructuralRolloutPolicy.testgen;
|
|
779
|
+
if (!isBoundedInt(k, 1) || !isBoundedInt(repairRounds, 0) || !isBoundedInt(testgen, 0)) {
|
|
780
|
+
return void 0;
|
|
781
|
+
}
|
|
787
782
|
return {
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
}
|
|
794
|
-
const surfaces = [];
|
|
795
|
-
const incumbent = verifiedCodeIncumbent(ctx.currentSurface);
|
|
796
|
-
const proposalBaseRef = incumbent?.baseCommit ?? baseRef;
|
|
797
|
-
for (let i = 0; i < ctx.populationSize; i++) {
|
|
798
|
-
if (ctx.signal.aborted) break;
|
|
799
|
-
const wt = await opts.worktree.create({
|
|
800
|
-
baseRef: proposalBaseRef,
|
|
801
|
-
label: `${opts.generator.kind}-gen${ctx.generation}-cand${i}`
|
|
802
|
-
});
|
|
803
|
-
owned.set(wt.path, wt);
|
|
804
|
-
try {
|
|
805
|
-
if (incumbent) advanceToIncumbent(wt, incumbent);
|
|
806
|
-
const { applied, summary, label, rationale } = await opts.generator.generate({
|
|
807
|
-
worktreePath: wt.path,
|
|
808
|
-
report: ctx.report,
|
|
809
|
-
findings,
|
|
810
|
-
dataset: ctx.dataset,
|
|
811
|
-
maxShots: ctx.maxImprovementShots ?? 1,
|
|
812
|
-
signal: ctx.signal,
|
|
813
|
-
generation: ctx.generation,
|
|
814
|
-
candidateIndex: i,
|
|
815
|
-
...ctx.costLedger ? { costLedger: ctx.costLedger } : {},
|
|
816
|
-
...ctx.costPhase ? { costPhase: ctx.costPhase } : {}
|
|
817
|
-
});
|
|
818
|
-
if (!applied) {
|
|
819
|
-
await opts.worktree.discard(wt);
|
|
820
|
-
owned.delete(wt.path);
|
|
821
|
-
continue;
|
|
822
|
-
}
|
|
823
|
-
const surface = await opts.worktree.finalize(wt, summary);
|
|
824
|
-
surfaces.push(
|
|
825
|
-
label || rationale ? { surface, label: label ?? "", rationale: rationale ?? "" } : surface
|
|
826
|
-
);
|
|
827
|
-
owned.delete(wt.path);
|
|
828
|
-
owned.set(surface.worktreeRef, wt);
|
|
829
|
-
} catch (err) {
|
|
830
|
-
const failure = err instanceof Error ? err.message : String(err);
|
|
831
|
-
return rethrowAfterCleanup(
|
|
832
|
-
err,
|
|
833
|
-
async () => {
|
|
834
|
-
await opts.worktree.discard(wt);
|
|
835
|
-
owned.delete(wt.path);
|
|
836
|
-
},
|
|
837
|
-
`improvementDriver: ${failure}`
|
|
838
|
-
);
|
|
839
|
-
}
|
|
840
|
-
}
|
|
841
|
-
return surfaces;
|
|
842
|
-
},
|
|
843
|
-
async cleanup(retainWorktreeRefs = []) {
|
|
844
|
-
const retained = new Set(retainWorktreeRefs);
|
|
845
|
-
const errors = [];
|
|
846
|
-
for (const [worktreeRef, worktree] of owned) {
|
|
847
|
-
if (retained.has(worktreeRef)) continue;
|
|
848
|
-
try {
|
|
849
|
-
await opts.worktree.discard(worktree);
|
|
850
|
-
owned.delete(worktreeRef);
|
|
851
|
-
} catch (cause) {
|
|
852
|
-
errors.push(cause);
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
if (errors.length > 0) {
|
|
856
|
-
throw new AggregateError(errors, "improvementDriver: failed to discard candidate worktrees");
|
|
857
|
-
}
|
|
858
|
-
}
|
|
783
|
+
k,
|
|
784
|
+
repairRounds,
|
|
785
|
+
testgen,
|
|
786
|
+
...typeof bag.diverse === "boolean" ? { diverse: bag.diverse } : {},
|
|
787
|
+
...typeof bag.temperature === "number" ? { temperature: bag.temperature } : {}
|
|
859
788
|
};
|
|
860
789
|
}
|
|
861
|
-
function
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
throw new Error("improvementDriver: candidate worktree does not match incumbent base identity");
|
|
869
|
-
}
|
|
870
|
-
if (worktree.baseCommit === incumbent.candidateCommit) return;
|
|
871
|
-
const merge = spawnSync2("git", ["merge", "--ff-only", incumbent.candidateCommit], {
|
|
872
|
-
cwd: worktree.path,
|
|
873
|
-
encoding: "utf8"
|
|
874
|
-
});
|
|
875
|
-
if (merge.error) {
|
|
876
|
-
throw new Error(
|
|
877
|
-
`improvementDriver: failed to start candidate from incumbent: ${merge.error.message}`
|
|
878
|
-
);
|
|
879
|
-
}
|
|
880
|
-
if (merge.status !== 0) {
|
|
881
|
-
throw new Error(
|
|
882
|
-
`improvementDriver: could not fast-forward candidate to incumbent ${incumbent.candidateCommit}: ${merge.stderr.trim()}`
|
|
883
|
-
);
|
|
884
|
-
}
|
|
885
|
-
const head = spawnSync2("git", ["rev-parse", "--verify", "HEAD"], {
|
|
886
|
-
cwd: worktree.path,
|
|
887
|
-
encoding: "utf8"
|
|
790
|
+
function serializeRolloutPolicy(policy) {
|
|
791
|
+
return JSON.stringify({
|
|
792
|
+
k: policy.k,
|
|
793
|
+
repairRounds: policy.repairRounds,
|
|
794
|
+
testgen: policy.testgen,
|
|
795
|
+
...policy.diverse !== void 0 ? { diverse: policy.diverse } : {},
|
|
796
|
+
...policy.temperature !== void 0 ? { temperature: policy.temperature } : {}
|
|
888
797
|
});
|
|
889
|
-
if (head.error || head.status !== 0 || head.stdout.trim() !== incumbent.candidateCommit) {
|
|
890
|
-
throw new Error("improvementDriver: candidate worktree did not reach the incumbent commit");
|
|
891
|
-
}
|
|
892
798
|
}
|
|
893
|
-
function
|
|
894
|
-
const
|
|
895
|
-
if (
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
799
|
+
function structuralRolloutPolicyFromProfile(profile) {
|
|
800
|
+
const bag = profile.extensions?.[ROLLOUT_POLICY_EXTENSION];
|
|
801
|
+
if (bag === void 0) return void 0;
|
|
802
|
+
return normalizeRolloutPolicy(bag);
|
|
803
|
+
}
|
|
804
|
+
function applyRolloutPolicyToProfile(profile, policy) {
|
|
805
|
+
const candidate = structuredClone(profile);
|
|
806
|
+
const bag = {
|
|
807
|
+
k: policy.k,
|
|
808
|
+
repairRounds: policy.repairRounds,
|
|
809
|
+
testgen: policy.testgen,
|
|
810
|
+
...policy.diverse !== void 0 ? { diverse: policy.diverse } : {},
|
|
811
|
+
...policy.temperature !== void 0 ? { temperature: policy.temperature } : {}
|
|
812
|
+
};
|
|
813
|
+
return {
|
|
814
|
+
...candidate,
|
|
815
|
+
extensions: { ...candidate.extensions, [ROLLOUT_POLICY_EXTENSION]: bag }
|
|
816
|
+
};
|
|
903
817
|
}
|
|
904
818
|
|
|
905
819
|
// src/improvement/raw-trace-distiller.ts
|
|
@@ -1074,184 +988,464 @@ function truncate2(s, n) {
|
|
|
1074
988
|
return s.length <= n ? s : `${s.slice(0, n - 1)}\u2026`;
|
|
1075
989
|
}
|
|
1076
990
|
|
|
1077
|
-
// src/improvement/rollout-policy.ts
|
|
1078
|
-
var ROLLOUT_POLICY_EXTENSION = "structural-rollout";
|
|
1079
|
-
var ROLLOUT_POLICY_BOUNDS = {
|
|
1080
|
-
k: { min: 1, max: 10, step: 2 },
|
|
1081
|
-
repairRounds: { min: 0, max: 3, step: 1 },
|
|
1082
|
-
testgen: { min: 0, max: 10, step: 3 }
|
|
1083
|
-
};
|
|
1084
|
-
var MAX_CANDIDATES_PER_GENERATION = 4;
|
|
1085
|
-
var clamp = (v, min, max) => Math.min(max, Math.max(min, v));
|
|
1086
|
-
var isBoundedInt = (v, min) => typeof v === "number" && Number.isInteger(v) && v >= min;
|
|
1087
|
-
function parseRolloutPolicy(surface) {
|
|
1088
|
-
if (typeof surface !== "string" || surface.trim().length === 0) return void 0;
|
|
1089
|
-
let raw;
|
|
1090
|
-
try {
|
|
1091
|
-
raw = JSON.parse(surface);
|
|
1092
|
-
} catch {
|
|
1093
|
-
return void 0;
|
|
1094
|
-
}
|
|
1095
|
-
return normalizeRolloutPolicy(raw);
|
|
1096
|
-
}
|
|
1097
|
-
function normalizeRolloutPolicy(raw) {
|
|
1098
|
-
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return void 0;
|
|
1099
|
-
const bag = raw;
|
|
1100
|
-
const k = bag.k ?? defaultStructuralRolloutPolicy.k;
|
|
1101
|
-
const repairRounds = bag.repairRounds ?? defaultStructuralRolloutPolicy.repairRounds;
|
|
1102
|
-
const testgen = bag.testgen ?? defaultStructuralRolloutPolicy.testgen;
|
|
1103
|
-
if (!isBoundedInt(k, 1) || !isBoundedInt(repairRounds, 0) || !isBoundedInt(testgen, 0)) {
|
|
1104
|
-
return void 0;
|
|
1105
|
-
}
|
|
1106
|
-
return {
|
|
1107
|
-
k,
|
|
1108
|
-
repairRounds,
|
|
1109
|
-
testgen,
|
|
1110
|
-
...typeof bag.diverse === "boolean" ? { diverse: bag.diverse } : {},
|
|
1111
|
-
...typeof bag.temperature === "number" ? { temperature: bag.temperature } : {}
|
|
1112
|
-
};
|
|
1113
|
-
}
|
|
1114
|
-
function serializeRolloutPolicy(policy) {
|
|
1115
|
-
return JSON.stringify({
|
|
1116
|
-
k: policy.k,
|
|
1117
|
-
repairRounds: policy.repairRounds,
|
|
1118
|
-
testgen: policy.testgen,
|
|
1119
|
-
...policy.diverse !== void 0 ? { diverse: policy.diverse } : {},
|
|
1120
|
-
...policy.temperature !== void 0 ? { temperature: policy.temperature } : {}
|
|
1121
|
-
});
|
|
1122
|
-
}
|
|
1123
|
-
function structuralRolloutPolicyFromProfile(profile) {
|
|
1124
|
-
const bag = profile.extensions?.[ROLLOUT_POLICY_EXTENSION];
|
|
1125
|
-
if (bag === void 0) return void 0;
|
|
1126
|
-
return normalizeRolloutPolicy(bag);
|
|
1127
|
-
}
|
|
1128
|
-
function applyRolloutPolicyToProfile(profile, policy) {
|
|
1129
|
-
const bag = {
|
|
1130
|
-
k: policy.k,
|
|
1131
|
-
repairRounds: policy.repairRounds,
|
|
1132
|
-
testgen: policy.testgen,
|
|
1133
|
-
...policy.diverse !== void 0 ? { diverse: policy.diverse } : {},
|
|
1134
|
-
...policy.temperature !== void 0 ? { temperature: policy.temperature } : {}
|
|
1135
|
-
};
|
|
1136
|
-
return {
|
|
1137
|
-
...profile,
|
|
1138
|
-
extensions: { ...profile.extensions, [ROLLOUT_POLICY_EXTENSION]: bag }
|
|
1139
|
-
};
|
|
1140
|
-
}
|
|
1141
|
-
function enumerateNeighborPolicies(policy) {
|
|
1142
|
-
const moves = [
|
|
1143
|
-
{ dial: "k", delta: 1 },
|
|
1144
|
-
{ dial: "k", delta: -1 },
|
|
1145
|
-
{ dial: "repairRounds", delta: 1 },
|
|
1146
|
-
{ dial: "repairRounds", delta: -1 },
|
|
1147
|
-
{ dial: "testgen", delta: 1 },
|
|
1148
|
-
{ dial: "testgen", delta: -1 }
|
|
1149
|
-
];
|
|
1150
|
-
const seen = /* @__PURE__ */ new Set([serializeRolloutPolicy(policy)]);
|
|
1151
|
-
const neighbors = [];
|
|
1152
|
-
for (const move of moves) {
|
|
1153
|
-
const bounds = ROLLOUT_POLICY_BOUNDS[move.dial];
|
|
1154
|
-
const next = clamp(policy[move.dial] + move.delta * bounds.step, bounds.min, bounds.max);
|
|
1155
|
-
const candidate = { ...policy, [move.dial]: next };
|
|
1156
|
-
const key = serializeRolloutPolicy(candidate);
|
|
1157
|
-
if (seen.has(key)) continue;
|
|
1158
|
-
seen.add(key);
|
|
1159
|
-
neighbors.push(candidate);
|
|
1160
|
-
}
|
|
1161
|
-
return neighbors;
|
|
1162
|
-
}
|
|
1163
|
-
function candidateLabel(base, next) {
|
|
1164
|
-
for (const dial of ["k", "repairRounds", "testgen"]) {
|
|
1165
|
-
if (next[dial] !== base[dial]) return `${dial} ${base[dial]}\u2192${next[dial]}`;
|
|
1166
|
-
}
|
|
1167
|
-
return "unchanged";
|
|
1168
|
-
}
|
|
1169
|
-
function rolloutPolicyProposer() {
|
|
1170
|
-
return {
|
|
1171
|
-
kind: "rollout-policy",
|
|
1172
|
-
async propose(ctx) {
|
|
1173
|
-
const policy = parseRolloutPolicy(ctx.currentSurface);
|
|
1174
|
-
if (!policy) return [];
|
|
1175
|
-
const neighbors = enumerateNeighborPolicies(policy);
|
|
1176
|
-
if (neighbors.length === 0) return [];
|
|
1177
|
-
const cap = Math.max(1, Math.min(ctx.populationSize, MAX_CANDIDATES_PER_GENERATION));
|
|
1178
|
-
const start = ctx.generation * cap % neighbors.length;
|
|
1179
|
-
const window = [];
|
|
1180
|
-
for (let i = 0; i < Math.min(cap, neighbors.length); i += 1) {
|
|
1181
|
-
window.push(neighbors[(start + i) % neighbors.length]);
|
|
1182
|
-
}
|
|
1183
|
-
return window.map((candidate) => ({
|
|
1184
|
-
surface: serializeRolloutPolicy(candidate),
|
|
1185
|
-
label: candidateLabel(policy, candidate),
|
|
1186
|
-
rationale: "bounded single-dial neighbor of the current structuralRollout policy; the held-out gate decides (deterministic enumeration \u2014 the dial space is tiny and prompt-style reflective proposals are a measured zero here)"
|
|
1187
|
-
}));
|
|
1188
|
-
}
|
|
1189
|
-
};
|
|
1190
|
-
}
|
|
1191
|
-
|
|
1192
991
|
// src/improvement/improve.ts
|
|
1193
|
-
import {
|
|
992
|
+
import { agentProfileSchema as agentProfileSchema2 } from "@tangle-network/agent-interface";
|
|
993
|
+
|
|
994
|
+
// src/improvement/code-execution.ts
|
|
995
|
+
import { makeFinding as makeFinding3 } from "@tangle-network/agent-eval";
|
|
1194
996
|
import {
|
|
1195
|
-
|
|
1196
|
-
gitWorktreeAdapter,
|
|
1197
|
-
memoryCurationProposer,
|
|
1198
|
-
skillOptProposer
|
|
997
|
+
gitWorktreeAdapter
|
|
1199
998
|
} from "@tangle-network/agent-eval/campaign";
|
|
1200
999
|
import {
|
|
1201
1000
|
selfImprove
|
|
1202
1001
|
} from "@tangle-network/agent-eval/contract";
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1002
|
+
|
|
1003
|
+
// src/improvement/cleanup.ts
|
|
1004
|
+
async function rethrowAfterCleanup(cause, cleanup, context) {
|
|
1005
|
+
const cleanupErrors = [];
|
|
1006
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
1007
|
+
try {
|
|
1008
|
+
await cleanup();
|
|
1009
|
+
} catch (cleanupCause) {
|
|
1010
|
+
cleanupErrors.push(cleanupCause);
|
|
1011
|
+
continue;
|
|
1012
|
+
}
|
|
1013
|
+
if (cleanupErrors.length === 0) throw cause;
|
|
1014
|
+
throw new AggregateError([cause, ...cleanupErrors], `${context}; cleanup retry succeeded`);
|
|
1015
|
+
}
|
|
1016
|
+
throw new AggregateError([cause, ...cleanupErrors], `${context}; cleanup failed`);
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
// src/improvement/improve-result.ts
|
|
1020
|
+
function copyImproveCost(cost) {
|
|
1021
|
+
return {
|
|
1022
|
+
totalCostUsd: cost.totalCostUsd,
|
|
1023
|
+
accountingComplete: cost.accountingComplete,
|
|
1024
|
+
incompleteReasons: [...cost.incompleteReasons]
|
|
1025
|
+
};
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
// src/improvement/improvement-driver.ts
|
|
1029
|
+
import { spawnSync as spawnSync2 } from "child_process";
|
|
1030
|
+
import {
|
|
1031
|
+
verifyCodeSurface
|
|
1032
|
+
} from "@tangle-network/agent-eval/campaign";
|
|
1033
|
+
function improvementDriver(opts) {
|
|
1034
|
+
const baseRef = opts.baseRef ?? "main";
|
|
1035
|
+
const owned = /* @__PURE__ */ new Map();
|
|
1036
|
+
return {
|
|
1037
|
+
kind: `improvement:${opts.generator.kind}`,
|
|
1038
|
+
async propose(ctx) {
|
|
1039
|
+
const findings = resolveFindings(ctx);
|
|
1040
|
+
if (findings.length === 0 && ctx.report === void 0 && !opts.generator.proposesWithoutFindings) {
|
|
1041
|
+
return [];
|
|
1042
|
+
}
|
|
1043
|
+
const surfaces = [];
|
|
1044
|
+
const incumbent = verifiedCodeIncumbent(ctx.currentSurface);
|
|
1045
|
+
const proposalBaseRef = incumbent?.baseCommit ?? baseRef;
|
|
1046
|
+
for (let i = 0; i < ctx.populationSize; i++) {
|
|
1047
|
+
if (ctx.signal.aborted) break;
|
|
1048
|
+
const wt = await opts.worktree.create({
|
|
1049
|
+
baseRef: proposalBaseRef,
|
|
1050
|
+
label: `${opts.generator.kind}-gen${ctx.generation}-cand${i}`
|
|
1051
|
+
});
|
|
1052
|
+
owned.set(wt.path, wt);
|
|
1053
|
+
try {
|
|
1054
|
+
if (incumbent) advanceToIncumbent(wt, incumbent);
|
|
1055
|
+
const { applied, summary, label, rationale } = await opts.generator.generate({
|
|
1056
|
+
worktreePath: wt.path,
|
|
1057
|
+
report: ctx.report,
|
|
1058
|
+
findings,
|
|
1059
|
+
dataset: ctx.dataset,
|
|
1060
|
+
maxShots: ctx.maxImprovementShots ?? 1,
|
|
1061
|
+
signal: ctx.signal,
|
|
1062
|
+
generation: ctx.generation,
|
|
1063
|
+
candidateIndex: i,
|
|
1064
|
+
...ctx.costLedger ? { costLedger: ctx.costLedger } : {},
|
|
1065
|
+
...ctx.costPhase ? { costPhase: ctx.costPhase } : {}
|
|
1066
|
+
});
|
|
1067
|
+
if (!applied) {
|
|
1068
|
+
await opts.worktree.discard(wt);
|
|
1069
|
+
owned.delete(wt.path);
|
|
1070
|
+
continue;
|
|
1071
|
+
}
|
|
1072
|
+
const surface = await opts.worktree.finalize(wt, summary);
|
|
1073
|
+
surfaces.push(
|
|
1074
|
+
label || rationale ? { surface, label: label ?? "", rationale: rationale ?? "" } : surface
|
|
1075
|
+
);
|
|
1076
|
+
owned.delete(wt.path);
|
|
1077
|
+
owned.set(surface.worktreeRef, wt);
|
|
1078
|
+
} catch (err) {
|
|
1079
|
+
const failure = err instanceof Error ? err.message : String(err);
|
|
1080
|
+
return rethrowAfterCleanup(
|
|
1081
|
+
err,
|
|
1082
|
+
async () => {
|
|
1083
|
+
await opts.worktree.discard(wt);
|
|
1084
|
+
owned.delete(wt.path);
|
|
1085
|
+
},
|
|
1086
|
+
`improvementDriver: ${failure}`
|
|
1087
|
+
);
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
return surfaces;
|
|
1091
|
+
},
|
|
1092
|
+
async cleanup(retainWorktreeRefs = []) {
|
|
1093
|
+
const retained = new Set(retainWorktreeRefs);
|
|
1094
|
+
const errors = [];
|
|
1095
|
+
for (const [worktreeRef, worktree] of owned) {
|
|
1096
|
+
if (retained.has(worktreeRef)) continue;
|
|
1097
|
+
try {
|
|
1098
|
+
await opts.worktree.discard(worktree);
|
|
1099
|
+
owned.delete(worktreeRef);
|
|
1100
|
+
} catch (cause) {
|
|
1101
|
+
errors.push(cause);
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
if (errors.length > 0) {
|
|
1105
|
+
throw new AggregateError(errors, "improvementDriver: failed to discard candidate worktrees");
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
};
|
|
1109
|
+
}
|
|
1110
|
+
function verifiedCodeIncumbent(surface) {
|
|
1111
|
+
if (typeof surface !== "object" || surface.kind !== "code") return void 0;
|
|
1112
|
+
verifyCodeSurface(surface);
|
|
1113
|
+
return surface;
|
|
1224
1114
|
}
|
|
1225
|
-
function
|
|
1115
|
+
function advanceToIncumbent(worktree, incumbent) {
|
|
1116
|
+
if (worktree.baseCommit !== incumbent.baseCommit || worktree.baseTree !== incumbent.baseTree) {
|
|
1117
|
+
throw new Error("improvementDriver: candidate worktree does not match incumbent base identity");
|
|
1118
|
+
}
|
|
1119
|
+
if (worktree.baseCommit === incumbent.candidateCommit) return;
|
|
1120
|
+
const merge = spawnSync2("git", ["merge", "--ff-only", incumbent.candidateCommit], {
|
|
1121
|
+
cwd: worktree.path,
|
|
1122
|
+
encoding: "utf8"
|
|
1123
|
+
});
|
|
1124
|
+
if (merge.error) {
|
|
1125
|
+
throw new Error(
|
|
1126
|
+
`improvementDriver: failed to start candidate from incumbent: ${merge.error.message}`
|
|
1127
|
+
);
|
|
1128
|
+
}
|
|
1129
|
+
if (merge.status !== 0) {
|
|
1130
|
+
throw new Error(
|
|
1131
|
+
`improvementDriver: could not fast-forward candidate to incumbent ${incumbent.candidateCommit}: ${merge.stderr.trim()}`
|
|
1132
|
+
);
|
|
1133
|
+
}
|
|
1134
|
+
const head = spawnSync2("git", ["rev-parse", "--verify", "HEAD"], {
|
|
1135
|
+
cwd: worktree.path,
|
|
1136
|
+
encoding: "utf8"
|
|
1137
|
+
});
|
|
1138
|
+
if (head.error || head.status !== 0 || head.stdout.trim() !== incumbent.candidateCommit) {
|
|
1139
|
+
throw new Error("improvementDriver: candidate worktree did not reach the incumbent commit");
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
function resolveFindings(ctx) {
|
|
1143
|
+
const report = ctx.report;
|
|
1144
|
+
if (report && typeof report === "object" && "findings" in report) {
|
|
1145
|
+
const f = report.findings;
|
|
1146
|
+
if (Array.isArray(f) && f.length > 0) {
|
|
1147
|
+
const lifted = toAnalystFindings(f, { analystId: "report-findings", area: "report" });
|
|
1148
|
+
if (lifted.length > 0) return lifted;
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
return toAnalystFindings(ctx.findings ?? [], { analystId: "loop-context", area: "seed" });
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
// src/improvement/profile-surface.ts
|
|
1155
|
+
import { canonicalJson } from "@tangle-network/agent-eval";
|
|
1156
|
+
import {
|
|
1157
|
+
agentProfileSchema
|
|
1158
|
+
} from "@tangle-network/agent-interface";
|
|
1159
|
+
function prepareProfileSurface(profile, surface, skills, profileComponents) {
|
|
1226
1160
|
switch (surface) {
|
|
1227
1161
|
case "prompt":
|
|
1228
|
-
return
|
|
1229
|
-
|
|
1230
|
-
|
|
1162
|
+
return {
|
|
1163
|
+
surface: profile.prompt?.systemPrompt ?? "",
|
|
1164
|
+
value: profile.prompt?.systemPrompt ?? ""
|
|
1165
|
+
};
|
|
1166
|
+
case "skills": {
|
|
1167
|
+
const value = inlineSkill(profile, skills).content;
|
|
1168
|
+
return { surface: value, value };
|
|
1169
|
+
}
|
|
1170
|
+
case "tools": {
|
|
1171
|
+
const value = profile.tools ?? {};
|
|
1172
|
+
return { surface: canonicalJson(value), value };
|
|
1173
|
+
}
|
|
1174
|
+
case "mcp": {
|
|
1175
|
+
const value = profile.mcp ?? {};
|
|
1176
|
+
return { surface: canonicalJson(value), value };
|
|
1177
|
+
}
|
|
1178
|
+
case "hooks": {
|
|
1179
|
+
const value = profile.hooks ?? {};
|
|
1180
|
+
return { surface: canonicalJson(value), value };
|
|
1181
|
+
}
|
|
1182
|
+
case "subagents": {
|
|
1183
|
+
const value = profile.subagents ?? {};
|
|
1184
|
+
return { surface: canonicalJson(value), value };
|
|
1185
|
+
}
|
|
1186
|
+
case "agent-profile": {
|
|
1187
|
+
if (profileComponents) {
|
|
1188
|
+
const value = profileComponents.read(profile);
|
|
1189
|
+
return {
|
|
1190
|
+
surface: componentSurface(value, "profileComponents.read"),
|
|
1191
|
+
value
|
|
1192
|
+
};
|
|
1193
|
+
}
|
|
1194
|
+
return { surface: canonicalJson(profile), value: profile };
|
|
1195
|
+
}
|
|
1196
|
+
case "memory": {
|
|
1197
|
+
const value = profileInstructions(profile);
|
|
1198
|
+
return { surface: value, value };
|
|
1199
|
+
}
|
|
1200
|
+
case "rollout-policy": {
|
|
1201
|
+
const policy = structuralRolloutPolicyFromProfile(profile);
|
|
1202
|
+
return {
|
|
1203
|
+
surface: policy ? serializeRolloutPolicy(policy) : "",
|
|
1204
|
+
value: policy ?? null
|
|
1205
|
+
};
|
|
1206
|
+
}
|
|
1207
|
+
case "code":
|
|
1208
|
+
throw new ConfigError(
|
|
1209
|
+
"improve(): code requires the isolated baseline created from opts.code.repoRoot"
|
|
1210
|
+
);
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
function isCodeSurface(surface) {
|
|
1214
|
+
return typeof surface === "object" && surface !== null && surface.kind === "code";
|
|
1215
|
+
}
|
|
1216
|
+
function isComponentSurface(surface) {
|
|
1217
|
+
return typeof surface === "object" && surface !== null && surface.kind === "components";
|
|
1218
|
+
}
|
|
1219
|
+
function componentSurface(components, source) {
|
|
1220
|
+
const entries = validateComponents(components, source);
|
|
1221
|
+
return immutableCandidateValue({
|
|
1222
|
+
kind: "components",
|
|
1223
|
+
components: Object.fromEntries(entries)
|
|
1224
|
+
});
|
|
1225
|
+
}
|
|
1226
|
+
function validateComponents(components, source) {
|
|
1227
|
+
if (typeof components !== "object" || components === null || Array.isArray(components)) {
|
|
1228
|
+
throw new ConfigError(`improve(): ${source} must return a component record`);
|
|
1229
|
+
}
|
|
1230
|
+
const entries = Object.entries(components);
|
|
1231
|
+
if (entries.length === 0) {
|
|
1232
|
+
throw new ConfigError(`improve(): ${source} must return at least one component`);
|
|
1233
|
+
}
|
|
1234
|
+
for (const [name, value] of entries) {
|
|
1235
|
+
if (!name || name.trim() !== name || typeof value !== "string") {
|
|
1236
|
+
throw new ConfigError(
|
|
1237
|
+
`improve(): ${source} must return trimmed component names with string values`
|
|
1238
|
+
);
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
return entries;
|
|
1242
|
+
}
|
|
1243
|
+
function parseWinnerJson(winner, surface) {
|
|
1244
|
+
try {
|
|
1245
|
+
return JSON.parse(winner);
|
|
1246
|
+
} catch (cause) {
|
|
1247
|
+
throw new ConfigError(
|
|
1248
|
+
`improve(): the '${surface}' candidate is not valid JSON, so it cannot form a profile candidate: ${cause.message}`
|
|
1249
|
+
);
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
function assertCandidateSurfaceKind(surface, baseline, winner) {
|
|
1253
|
+
if (surface === "code") {
|
|
1254
|
+
if (isCodeSurface(winner)) return;
|
|
1255
|
+
throw new ConfigError(
|
|
1256
|
+
`improve(): the '${surface}' candidate returned an incompatible surface value`
|
|
1257
|
+
);
|
|
1258
|
+
}
|
|
1259
|
+
if (typeof baseline === "string") {
|
|
1260
|
+
if (typeof winner === "string") return;
|
|
1261
|
+
throw new ConfigError(
|
|
1262
|
+
`improve(): the '${surface}' candidate changed from a text surface to an incompatible surface value`
|
|
1263
|
+
);
|
|
1264
|
+
}
|
|
1265
|
+
if (!isComponentSurface(baseline) || !isComponentSurface(winner)) {
|
|
1266
|
+
throw new ConfigError(
|
|
1267
|
+
`improve(): the '${surface}' candidate returned an incompatible surface value`
|
|
1268
|
+
);
|
|
1269
|
+
}
|
|
1270
|
+
validateComponents(winner.components, `the '${surface}' candidate`);
|
|
1271
|
+
const baselineNames = Object.keys(baseline.components).sort();
|
|
1272
|
+
const winnerNames = Object.keys(winner.components).sort();
|
|
1273
|
+
if (baselineNames.length !== winnerNames.length || baselineNames.some((name, index) => name !== winnerNames[index])) {
|
|
1274
|
+
throw new ConfigError(
|
|
1275
|
+
`improve(): the '${surface}' candidate must preserve the exact component names`
|
|
1276
|
+
);
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
function materializeImprovementProfileCandidate(profile, surface, winner, skills, profileComponents) {
|
|
1280
|
+
let candidate;
|
|
1281
|
+
if (isComponentSurface(winner)) {
|
|
1282
|
+
if (surface !== "agent-profile" || !profileComponents) {
|
|
1283
|
+
throw new ConfigError(
|
|
1284
|
+
`improve(): the '${surface}' candidate has no profile component mapping`
|
|
1285
|
+
);
|
|
1286
|
+
}
|
|
1287
|
+
const winnerComponents = immutableCandidateValue({ ...winner.components });
|
|
1288
|
+
const applied = profileComponents.apply(profile, winnerComponents);
|
|
1289
|
+
const validated = validateProfileCandidate(applied, surface);
|
|
1290
|
+
const materializedComponents = Object.fromEntries(
|
|
1291
|
+
validateComponents(profileComponents.read(validated), "profileComponents.read after apply")
|
|
1292
|
+
);
|
|
1293
|
+
const names = Object.keys(winnerComponents);
|
|
1294
|
+
if (names.length !== Object.keys(materializedComponents).length || names.some((name) => materializedComponents[name] !== winnerComponents[name])) {
|
|
1295
|
+
throw new ConfigError(
|
|
1296
|
+
"improve(): profileComponents.apply must round-trip every winning component exactly"
|
|
1297
|
+
);
|
|
1298
|
+
}
|
|
1299
|
+
return validated;
|
|
1300
|
+
}
|
|
1301
|
+
if (typeof winner !== "string") {
|
|
1302
|
+
throw new ConfigError(`improve(): the '${surface}' candidate cannot form an AgentProfile`);
|
|
1303
|
+
}
|
|
1304
|
+
switch (surface) {
|
|
1305
|
+
case "prompt":
|
|
1306
|
+
candidate = { ...profile, prompt: { ...profile.prompt, systemPrompt: winner } };
|
|
1307
|
+
break;
|
|
1308
|
+
case "skills": {
|
|
1309
|
+
const selectedSkill = inlineSkill(profile, skills);
|
|
1310
|
+
candidate = {
|
|
1311
|
+
...profile,
|
|
1312
|
+
resources: {
|
|
1313
|
+
...profile.resources,
|
|
1314
|
+
skills: profile.resources?.skills?.map(
|
|
1315
|
+
(resource) => resource === selectedSkill ? { ...resource, content: winner } : resource
|
|
1316
|
+
)
|
|
1317
|
+
}
|
|
1318
|
+
};
|
|
1319
|
+
break;
|
|
1320
|
+
}
|
|
1231
1321
|
case "tools":
|
|
1232
|
-
|
|
1322
|
+
candidate = { ...profile, tools: parseWinnerJson(winner, surface) };
|
|
1323
|
+
break;
|
|
1233
1324
|
case "mcp":
|
|
1234
|
-
|
|
1325
|
+
candidate = { ...profile, mcp: parseWinnerJson(winner, surface) };
|
|
1326
|
+
break;
|
|
1235
1327
|
case "hooks":
|
|
1236
|
-
|
|
1328
|
+
candidate = { ...profile, hooks: parseWinnerJson(winner, surface) };
|
|
1329
|
+
break;
|
|
1237
1330
|
case "subagents":
|
|
1238
|
-
|
|
1331
|
+
candidate = { ...profile, subagents: parseWinnerJson(winner, surface) };
|
|
1332
|
+
break;
|
|
1239
1333
|
case "agent-profile":
|
|
1240
|
-
|
|
1334
|
+
candidate = parseWinnerJson(winner, surface);
|
|
1335
|
+
break;
|
|
1241
1336
|
case "memory":
|
|
1242
|
-
|
|
1337
|
+
candidate = {
|
|
1338
|
+
...profile,
|
|
1339
|
+
resources: {
|
|
1340
|
+
...profile.resources,
|
|
1341
|
+
instructions: replaceProfileInstructions(profile, winner)
|
|
1342
|
+
}
|
|
1343
|
+
};
|
|
1344
|
+
break;
|
|
1243
1345
|
case "rollout-policy": {
|
|
1244
|
-
const policy =
|
|
1245
|
-
|
|
1346
|
+
const policy = normalizeRolloutPolicy(parseWinnerJson(winner, surface));
|
|
1347
|
+
if (!policy) {
|
|
1348
|
+
throw new ConfigError(
|
|
1349
|
+
`improve(): the shipped 'rollout-policy' winner is not a valid StructuralRolloutPolicy (integer k >= 1, repairRounds >= 0, testgen >= 0), so it cannot be applied: ${winner}`
|
|
1350
|
+
);
|
|
1351
|
+
}
|
|
1352
|
+
candidate = applyRolloutPolicyToProfile(profile, policy);
|
|
1353
|
+
break;
|
|
1246
1354
|
}
|
|
1247
|
-
|
|
1355
|
+
}
|
|
1356
|
+
return validateProfileCandidate(candidate, surface);
|
|
1357
|
+
}
|
|
1358
|
+
function validateProfileCandidate(candidate, surface) {
|
|
1359
|
+
const parsed = agentProfileSchema.safeParse(candidate);
|
|
1360
|
+
if (!parsed.success) {
|
|
1361
|
+
throw new ConfigError(
|
|
1362
|
+
`improve(): the '${surface}' candidate does not produce a valid AgentProfile: ${parsed.error.message}`
|
|
1363
|
+
);
|
|
1364
|
+
}
|
|
1365
|
+
return immutableCandidateValue(parsed.data);
|
|
1366
|
+
}
|
|
1367
|
+
function createProfileCandidateMaterializer(profile, surface, baselineSurface, skills, profileComponents) {
|
|
1368
|
+
const baselineDigest = canonicalCandidateDigest(baselineSurface);
|
|
1369
|
+
if (profileComponents) {
|
|
1370
|
+
const reappliedBaseline = materializeImprovementProfileCandidate(
|
|
1371
|
+
profile,
|
|
1372
|
+
surface,
|
|
1373
|
+
baselineSurface,
|
|
1374
|
+
skills,
|
|
1375
|
+
profileComponents
|
|
1376
|
+
);
|
|
1377
|
+
if (canonicalCandidateDigest(reappliedBaseline) !== canonicalCandidateDigest(profile)) {
|
|
1248
1378
|
throw new ConfigError(
|
|
1249
|
-
"improve():
|
|
1379
|
+
"improve(): profileComponents.apply(profile, profileComponents.read(profile)) must reproduce the complete baseline profile exactly"
|
|
1250
1380
|
);
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
const candidates = /* @__PURE__ */ new Map([[baselineDigest, profile]]);
|
|
1384
|
+
return (candidateSurface) => {
|
|
1385
|
+
assertCandidateSurfaceKind(surface, baselineSurface, candidateSurface);
|
|
1386
|
+
const digest = canonicalCandidateDigest(candidateSurface);
|
|
1387
|
+
const existing = candidates.get(digest);
|
|
1388
|
+
if (existing) return existing;
|
|
1389
|
+
const candidate = materializeImprovementProfileCandidate(
|
|
1390
|
+
profile,
|
|
1391
|
+
surface,
|
|
1392
|
+
immutableCandidateValue(candidateSurface),
|
|
1393
|
+
skills,
|
|
1394
|
+
profileComponents
|
|
1395
|
+
);
|
|
1396
|
+
candidates.set(digest, candidate);
|
|
1397
|
+
return candidate;
|
|
1398
|
+
};
|
|
1399
|
+
}
|
|
1400
|
+
function inlineSkill(profile, options) {
|
|
1401
|
+
const resourceName = options?.resourceName.trim();
|
|
1402
|
+
if (!resourceName) {
|
|
1403
|
+
throw new ConfigError(
|
|
1404
|
+
"improve(): surface 'skills' requires opts.skills.resourceName for one inline profile skill"
|
|
1405
|
+
);
|
|
1406
|
+
}
|
|
1407
|
+
assertFailClosedResources(profile, "skills");
|
|
1408
|
+
const matches = (profile.resources?.skills ?? []).filter(
|
|
1409
|
+
(resource) => resource.name === resourceName
|
|
1410
|
+
);
|
|
1411
|
+
if (matches.length !== 1 || matches[0]?.kind !== "inline") {
|
|
1412
|
+
throw new ConfigError(
|
|
1413
|
+
`improve(): skill '${resourceName}' must identify exactly one inline profile resource`
|
|
1414
|
+
);
|
|
1415
|
+
}
|
|
1416
|
+
return matches[0];
|
|
1417
|
+
}
|
|
1418
|
+
function profileInstructions(profile) {
|
|
1419
|
+
assertFailClosedResources(profile, "memory");
|
|
1420
|
+
const instructions = profile.resources?.instructions;
|
|
1421
|
+
if (instructions === void 0) return "";
|
|
1422
|
+
if (typeof instructions === "string") return instructions;
|
|
1423
|
+
if (instructions.kind === "inline") return instructions.content;
|
|
1424
|
+
throw new ConfigError(
|
|
1425
|
+
"improve(): surface 'memory' requires inline profile instructions so candidate bytes are exact"
|
|
1426
|
+
);
|
|
1427
|
+
}
|
|
1428
|
+
function replaceProfileInstructions(profile, content) {
|
|
1429
|
+
const instructions = profile.resources?.instructions;
|
|
1430
|
+
if (typeof instructions !== "object") return content;
|
|
1431
|
+
if (instructions.kind !== "inline") {
|
|
1432
|
+
throw new ConfigError(
|
|
1433
|
+
"improve(): surface 'memory' requires inline profile instructions so candidate bytes are exact"
|
|
1434
|
+
);
|
|
1435
|
+
}
|
|
1436
|
+
return { ...instructions, content };
|
|
1437
|
+
}
|
|
1438
|
+
function assertFailClosedResources(profile, surface) {
|
|
1439
|
+
if (profile.resources?.failOnError !== true) {
|
|
1440
|
+
throw new ConfigError(
|
|
1441
|
+
`improve(): surface '${surface}' requires profile.resources.failOnError: true`
|
|
1442
|
+
);
|
|
1251
1443
|
}
|
|
1252
1444
|
}
|
|
1253
|
-
|
|
1254
|
-
|
|
1445
|
+
|
|
1446
|
+
// src/improvement/code-execution.ts
|
|
1447
|
+
var distilledNotesMaxChars = 1500;
|
|
1448
|
+
var distilledErrorMaxChars = 500;
|
|
1255
1449
|
function generationFailureDistiller(staticFindings) {
|
|
1256
1450
|
const CAP = 12;
|
|
1257
1451
|
return async (input) => {
|
|
@@ -1264,53 +1458,44 @@ function generationFailureDistiller(staticFindings) {
|
|
|
1264
1458
|
const judgeScores = cell.judgeScores && typeof cell.judgeScores === "object" ? Object.values(
|
|
1265
1459
|
cell.judgeScores
|
|
1266
1460
|
) : [];
|
|
1267
|
-
const composite = judgeScores.length === 0 ? 0 : judgeScores.reduce((sum,
|
|
1461
|
+
const composite = judgeScores.length === 0 ? 0 : judgeScores.reduce((sum, judge) => sum + (judge.composite ?? 0), 0) / judgeScores.length;
|
|
1268
1462
|
if (!error && composite >= 0.999) continue;
|
|
1269
|
-
const notes = judgeScores.map((
|
|
1270
|
-
const claim = notes || (error ? `Scenario ${scenario} failed: ${error.slice(0,
|
|
1463
|
+
const notes = judgeScores.map((judge) => judge.notes).filter((note) => typeof note === "string" && note.length > 0).join("; ").slice(0, distilledNotesMaxChars);
|
|
1464
|
+
const claim = notes || (error ? `Scenario ${scenario} failed: ${error.slice(0, distilledErrorMaxChars)}` : "");
|
|
1271
1465
|
failures.push({
|
|
1272
1466
|
scenario,
|
|
1273
1467
|
composite: Number(composite.toFixed(3)),
|
|
1274
1468
|
notes,
|
|
1275
1469
|
...claim ? { claim } : {},
|
|
1276
|
-
...error ? { error: error.slice(0,
|
|
1470
|
+
...error ? { error: error.slice(0, distilledErrorMaxChars) } : {}
|
|
1277
1471
|
});
|
|
1278
1472
|
}
|
|
1279
1473
|
}
|
|
1280
1474
|
if (failures.length === 0) return staticFindings;
|
|
1281
|
-
failures.sort((
|
|
1475
|
+
failures.sort((left, right) => left.composite - right.composite);
|
|
1282
1476
|
return failures.slice(0, CAP).map(
|
|
1283
|
-
(
|
|
1477
|
+
(failure) => makeFinding3({
|
|
1284
1478
|
analyst_id: "generation-failure-distiller",
|
|
1285
|
-
severity:
|
|
1479
|
+
severity: failure.error !== void 0 || failure.composite < 0.5 ? "high" : "medium",
|
|
1286
1480
|
area: "generation-failure",
|
|
1287
1481
|
confidence: 1,
|
|
1288
|
-
subject:
|
|
1289
|
-
claim: `Scenario ${
|
|
1482
|
+
subject: failure.scenario,
|
|
1483
|
+
claim: `Scenario ${failure.scenario} scored composite ${failure.composite}${failure.notes ? `: ${failure.notes}` : ""}${failure.error ? ` (error: ${failure.error})` : ""}`,
|
|
1290
1484
|
evidence_refs: [],
|
|
1291
1485
|
metadata: {
|
|
1292
|
-
scenario:
|
|
1293
|
-
composite:
|
|
1294
|
-
...
|
|
1295
|
-
...
|
|
1486
|
+
scenario: failure.scenario,
|
|
1487
|
+
composite: failure.composite,
|
|
1488
|
+
...failure.notes ? { notes: failure.notes } : {},
|
|
1489
|
+
...failure.error !== void 0 ? { error: failure.error } : {}
|
|
1296
1490
|
}
|
|
1297
1491
|
})
|
|
1298
1492
|
);
|
|
1299
1493
|
};
|
|
1300
1494
|
}
|
|
1301
|
-
function memoryGenerationDistiller(staticFindings) {
|
|
1302
|
-
const distillFailures = generationFailureDistiller(staticFindings);
|
|
1303
|
-
return async (input) => {
|
|
1304
|
-
const fresh = await distillFailures(input);
|
|
1305
|
-
return fresh === staticFindings ? staticFindings : [...staticFindings, ...fresh];
|
|
1306
|
-
};
|
|
1307
|
-
}
|
|
1308
1495
|
function defaultDistillerFor(opts, findings) {
|
|
1309
|
-
const surface = opts.surface ?? "prompt";
|
|
1310
1496
|
const durableRun = opts.runDir !== void 0 && !opts.runDir.startsWith("mem://");
|
|
1311
|
-
const useRawTraces = opts.rawTraceContext ??
|
|
1497
|
+
const useRawTraces = opts.rawTraceContext ?? durableRun;
|
|
1312
1498
|
if (useRawTraces) return rawTraceDistiller({ fallbackFindings: findings });
|
|
1313
|
-
if (surface === "memory") return memoryGenerationDistiller(findings);
|
|
1314
1499
|
return generationFailureDistiller(findings);
|
|
1315
1500
|
}
|
|
1316
1501
|
async function discardPreparedBaseline(worktree, baselineWorktree, cause) {
|
|
@@ -1320,9 +1505,6 @@ async function discardPreparedBaseline(worktree, baselineWorktree, cause) {
|
|
|
1320
1505
|
"improve(): code preparation failed"
|
|
1321
1506
|
);
|
|
1322
1507
|
}
|
|
1323
|
-
function isCodeSurface(surface) {
|
|
1324
|
-
return typeof surface === "object" && surface !== null && surface.kind === "code";
|
|
1325
|
-
}
|
|
1326
1508
|
async function prepareCodeRun(code) {
|
|
1327
1509
|
const baseRef = code.baseRef ?? "main";
|
|
1328
1510
|
const worktree = code.worktree ?? gitWorktreeAdapter({
|
|
@@ -1363,245 +1545,47 @@ async function prepareCodeRun(code) {
|
|
|
1363
1545
|
}
|
|
1364
1546
|
}
|
|
1365
1547
|
};
|
|
1366
|
-
} catch (cause) {
|
|
1367
|
-
return discardPreparedBaseline(worktree, baselineWorktree, cause);
|
|
1368
|
-
}
|
|
1369
|
-
}
|
|
1370
|
-
function idempotentDispose(dispose) {
|
|
1371
|
-
let disposed = false;
|
|
1372
|
-
let inFlight;
|
|
1373
|
-
return async () => {
|
|
1374
|
-
if (disposed) return;
|
|
1375
|
-
if (inFlight) return inFlight;
|
|
1376
|
-
inFlight = (async () => {
|
|
1377
|
-
await dispose();
|
|
1378
|
-
disposed = true;
|
|
1379
|
-
})();
|
|
1380
|
-
try {
|
|
1381
|
-
await inFlight;
|
|
1382
|
-
} finally {
|
|
1383
|
-
inFlight = void 0;
|
|
1384
|
-
}
|
|
1385
|
-
};
|
|
1386
|
-
}
|
|
1387
|
-
function parseWinnerJson(winner, surface) {
|
|
1388
|
-
try {
|
|
1389
|
-
return JSON.parse(winner);
|
|
1390
|
-
} catch (cause) {
|
|
1391
|
-
throw new ConfigError(
|
|
1392
|
-
`improve(): the '${surface}' candidate is not valid JSON, so it cannot form a profile candidate: ${cause.message}`
|
|
1393
|
-
);
|
|
1394
|
-
}
|
|
1395
|
-
}
|
|
1396
|
-
function assertCandidateSurfaceKind(surface, winner) {
|
|
1397
|
-
if (surface === "code" ? typeof winner === "string" : typeof winner !== "string") {
|
|
1398
|
-
throw new ConfigError(
|
|
1399
|
-
`improve(): the '${surface}' candidate returned an incompatible surface value`
|
|
1400
|
-
);
|
|
1401
|
-
}
|
|
1402
|
-
}
|
|
1403
|
-
function materializeImprovementProfileCandidate(profile, surface, winner, skills) {
|
|
1404
|
-
if (typeof winner !== "string") return void 0;
|
|
1405
|
-
let candidate;
|
|
1406
|
-
switch (surface) {
|
|
1407
|
-
case "prompt":
|
|
1408
|
-
candidate = { ...profile, prompt: { ...profile.prompt, systemPrompt: winner } };
|
|
1409
|
-
break;
|
|
1410
|
-
case "skills": {
|
|
1411
|
-
const selectedSkill = inlineSkill(profile, skills);
|
|
1412
|
-
candidate = {
|
|
1413
|
-
...profile,
|
|
1414
|
-
resources: {
|
|
1415
|
-
...profile.resources,
|
|
1416
|
-
skills: profile.resources?.skills?.map(
|
|
1417
|
-
(resource) => resource === selectedSkill ? { ...resource, content: winner } : resource
|
|
1418
|
-
)
|
|
1419
|
-
}
|
|
1420
|
-
};
|
|
1421
|
-
break;
|
|
1422
|
-
}
|
|
1423
|
-
case "tools":
|
|
1424
|
-
candidate = { ...profile, tools: parseWinnerJson(winner, surface) };
|
|
1425
|
-
break;
|
|
1426
|
-
case "mcp":
|
|
1427
|
-
candidate = { ...profile, mcp: parseWinnerJson(winner, surface) };
|
|
1428
|
-
break;
|
|
1429
|
-
case "hooks":
|
|
1430
|
-
candidate = { ...profile, hooks: parseWinnerJson(winner, surface) };
|
|
1431
|
-
break;
|
|
1432
|
-
case "subagents":
|
|
1433
|
-
candidate = { ...profile, subagents: parseWinnerJson(winner, surface) };
|
|
1434
|
-
break;
|
|
1435
|
-
case "agent-profile":
|
|
1436
|
-
candidate = parseWinnerJson(winner, surface);
|
|
1437
|
-
break;
|
|
1438
|
-
case "memory":
|
|
1439
|
-
candidate = {
|
|
1440
|
-
...profile,
|
|
1441
|
-
resources: {
|
|
1442
|
-
...profile.resources,
|
|
1443
|
-
instructions: replaceProfileInstructions(profile, winner)
|
|
1444
|
-
}
|
|
1445
|
-
};
|
|
1446
|
-
break;
|
|
1447
|
-
case "rollout-policy": {
|
|
1448
|
-
if (winner === "") return void 0;
|
|
1449
|
-
const policy = normalizeRolloutPolicy(parseWinnerJson(winner, surface));
|
|
1450
|
-
if (!policy) {
|
|
1451
|
-
throw new ConfigError(
|
|
1452
|
-
`improve(): the shipped 'rollout-policy' winner is not a valid StructuralRolloutPolicy (integer k >= 1, repairRounds >= 0, testgen >= 0), so it cannot be applied: ${winner}`
|
|
1453
|
-
);
|
|
1454
|
-
}
|
|
1455
|
-
candidate = applyRolloutPolicyToProfile(profile, policy);
|
|
1456
|
-
break;
|
|
1457
|
-
}
|
|
1458
|
-
case "code":
|
|
1459
|
-
return void 0;
|
|
1460
|
-
}
|
|
1461
|
-
const parsed = agentProfileSchema.safeParse(candidate);
|
|
1462
|
-
if (!parsed.success) {
|
|
1463
|
-
throw new ConfigError(
|
|
1464
|
-
`improve(): the '${surface}' candidate does not produce a valid AgentProfile: ${parsed.error.message}`
|
|
1465
|
-
);
|
|
1548
|
+
} catch (cause) {
|
|
1549
|
+
return discardPreparedBaseline(worktree, baselineWorktree, cause);
|
|
1466
1550
|
}
|
|
1467
|
-
return immutableCandidateValue(parsed.data);
|
|
1468
1551
|
}
|
|
1469
|
-
function
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1552
|
+
function idempotentDispose(dispose) {
|
|
1553
|
+
let disposed = false;
|
|
1554
|
+
let inFlight;
|
|
1555
|
+
return async () => {
|
|
1556
|
+
if (disposed) return;
|
|
1557
|
+
if (inFlight) return inFlight;
|
|
1558
|
+
inFlight = (async () => {
|
|
1559
|
+
await dispose();
|
|
1560
|
+
disposed = true;
|
|
1561
|
+
})();
|
|
1562
|
+
try {
|
|
1563
|
+
await inFlight;
|
|
1564
|
+
} finally {
|
|
1565
|
+
inFlight = void 0;
|
|
1482
1566
|
}
|
|
1483
|
-
return input.dispatch(dispatchedProfile, scenario, ctx);
|
|
1484
1567
|
};
|
|
1485
1568
|
}
|
|
1486
|
-
function
|
|
1487
|
-
const resourceName = options?.resourceName.trim();
|
|
1488
|
-
if (!resourceName) {
|
|
1489
|
-
throw new ConfigError(
|
|
1490
|
-
"improve(): surface 'skills' requires opts.skills.resourceName for one inline profile skill"
|
|
1491
|
-
);
|
|
1492
|
-
}
|
|
1493
|
-
assertFailClosedResources(profile, "skills");
|
|
1494
|
-
const matches = (profile.resources?.skills ?? []).filter(
|
|
1495
|
-
(resource) => resource.name === resourceName
|
|
1496
|
-
);
|
|
1497
|
-
if (matches.length !== 1 || matches[0]?.kind !== "inline") {
|
|
1498
|
-
throw new ConfigError(
|
|
1499
|
-
`improve(): skill '${resourceName}' must identify exactly one inline profile resource`
|
|
1500
|
-
);
|
|
1501
|
-
}
|
|
1502
|
-
return matches[0];
|
|
1503
|
-
}
|
|
1504
|
-
function profileInstructions(profile) {
|
|
1505
|
-
assertFailClosedResources(profile, "memory");
|
|
1506
|
-
const instructions = profile.resources?.instructions;
|
|
1507
|
-
if (instructions === void 0) return "";
|
|
1508
|
-
if (typeof instructions === "string") return instructions;
|
|
1509
|
-
if (instructions.kind === "inline") return instructions.content;
|
|
1510
|
-
throw new ConfigError(
|
|
1511
|
-
"improve(): surface 'memory' requires inline profile instructions so candidate bytes are exact"
|
|
1512
|
-
);
|
|
1513
|
-
}
|
|
1514
|
-
function replaceProfileInstructions(profile, content) {
|
|
1515
|
-
const instructions = profile.resources?.instructions;
|
|
1516
|
-
if (typeof instructions !== "object") return content;
|
|
1517
|
-
if (instructions.kind !== "inline") {
|
|
1518
|
-
throw new ConfigError(
|
|
1519
|
-
"improve(): surface 'memory' requires inline profile instructions so candidate bytes are exact"
|
|
1520
|
-
);
|
|
1521
|
-
}
|
|
1522
|
-
return { ...instructions, content };
|
|
1523
|
-
}
|
|
1524
|
-
function assertFailClosedResources(profile, surface) {
|
|
1525
|
-
if (profile.resources?.failOnError !== true) {
|
|
1526
|
-
throw new ConfigError(
|
|
1527
|
-
`improve(): surface '${surface}' requires profile.resources.failOnError: true`
|
|
1528
|
-
);
|
|
1529
|
-
}
|
|
1530
|
-
}
|
|
1531
|
-
async function improve(profile, findings, opts) {
|
|
1569
|
+
async function runCodeImprovement(opts) {
|
|
1532
1570
|
const {
|
|
1533
|
-
surface = "prompt",
|
|
1534
1571
|
gate = "holdout",
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
generator,
|
|
1538
|
-
allowedModels,
|
|
1539
|
-
rawTraceContext,
|
|
1572
|
+
findings: inputFindings = [],
|
|
1573
|
+
rawTraceContext: _rawTraceContext,
|
|
1540
1574
|
code,
|
|
1541
|
-
skills,
|
|
1542
1575
|
promotionGate,
|
|
1543
1576
|
analyzeGeneration,
|
|
1577
|
+
surface: _surface,
|
|
1544
1578
|
...sharedOptions
|
|
1545
1579
|
} = opts;
|
|
1546
|
-
const
|
|
1547
|
-
|
|
1548
|
-
throw new ConfigError(
|
|
1549
|
-
`improve(): input is not a valid AgentProfile: ${parsedProfile.error.message}`
|
|
1550
|
-
);
|
|
1551
|
-
}
|
|
1552
|
-
if (agent !== void 0 && profileDispatch !== void 0) {
|
|
1553
|
-
throw new ConfigError("improve(): provide exactly one of opts.agent or opts.profileDispatch");
|
|
1554
|
-
}
|
|
1555
|
-
if (agent === void 0 && profileDispatch === void 0) {
|
|
1556
|
-
throw new ConfigError("improve(): provide exactly one of opts.agent or opts.profileDispatch");
|
|
1557
|
-
}
|
|
1558
|
-
const baselineProfile = immutableCandidateValue(parsedProfile.data);
|
|
1559
|
-
if (profileDispatch && surface === "code") {
|
|
1560
|
-
throw new ConfigError(
|
|
1561
|
-
"improve(): surface 'code' cannot use profileDispatch because code candidates require isolated worktree execution; use opts.agent"
|
|
1562
|
-
);
|
|
1563
|
-
}
|
|
1564
|
-
if (surface === "code" && generator) {
|
|
1565
|
-
throw new ConfigError(
|
|
1566
|
-
"improve(): surface 'code' forbids opts.generator because an external SurfaceProposer cannot transfer checkout ownership; pass opts.code.generator instead"
|
|
1567
|
-
);
|
|
1568
|
-
}
|
|
1569
|
-
const usesReflectionModel = !generator && (surface === "prompt" || surface === "skills");
|
|
1570
|
-
if (usesReflectionModel) {
|
|
1571
|
-
assertModelAllowed(sharedOptions.llm?.model ?? defaultReflectionModel, allowedModels);
|
|
1572
|
-
}
|
|
1573
|
-
let preparedCode;
|
|
1574
|
-
if (surface === "code") {
|
|
1575
|
-
if (!code) {
|
|
1576
|
-
throw new ConfigError(
|
|
1577
|
-
"improve(): surface 'code' requires opts.code.repoRoot so the incumbent can run from an isolated checkout"
|
|
1578
|
-
);
|
|
1579
|
-
}
|
|
1580
|
-
preparedCode = await prepareCodeRun(code);
|
|
1581
|
-
}
|
|
1582
|
-
const proposer = preparedCode?.proposer ?? generator ?? defaultGeneratorFor(surface, sharedOptions.llm);
|
|
1583
|
-
if (!proposer) {
|
|
1584
|
-
throw new ConfigError(
|
|
1585
|
-
`improve(): surface '${surface}' has no default generator \u2014 pass opts.generator (a SurfaceProposer) explicitly`
|
|
1586
|
-
);
|
|
1587
|
-
}
|
|
1580
|
+
const findings = [...inputFindings];
|
|
1581
|
+
const preparedCode = await prepareCodeRun(code);
|
|
1588
1582
|
const budget = gate === "none" ? { ...sharedOptions.budget, generations: 0 } : { ...sharedOptions.budget };
|
|
1589
|
-
const effectiveAgent = profileDispatch === void 0 ? agent : profileImprovementAgent({
|
|
1590
|
-
baselineProfile,
|
|
1591
|
-
surface,
|
|
1592
|
-
...skills === void 0 ? {} : { skills },
|
|
1593
|
-
dispatch: profileDispatch
|
|
1594
|
-
});
|
|
1595
|
-
if (!effectiveAgent) {
|
|
1596
|
-
throw new ConfigError("improve(): provide exactly one of opts.agent or opts.profileDispatch");
|
|
1597
|
-
}
|
|
1598
1583
|
let raw;
|
|
1599
1584
|
try {
|
|
1600
1585
|
raw = await selfImprove({
|
|
1601
1586
|
...sharedOptions,
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
proposer,
|
|
1587
|
+
baselineSurface: preparedCode.baseline,
|
|
1588
|
+
proposer: preparedCode.proposer,
|
|
1605
1589
|
budget,
|
|
1606
1590
|
findings,
|
|
1607
1591
|
...promotionGate !== void 0 ? { gate: promotionGate } : {},
|
|
@@ -1610,7 +1594,6 @@ async function improve(profile, findings, opts) {
|
|
|
1610
1594
|
}
|
|
1611
1595
|
});
|
|
1612
1596
|
} catch (cause) {
|
|
1613
|
-
if (!preparedCode) throw cause;
|
|
1614
1597
|
return rethrowAfterCleanup(
|
|
1615
1598
|
cause,
|
|
1616
1599
|
() => preparedCode.cleanup(),
|
|
@@ -1618,50 +1601,423 @@ async function improve(profile, findings, opts) {
|
|
|
1618
1601
|
);
|
|
1619
1602
|
}
|
|
1620
1603
|
const winnerSurface = raw.winner.surface;
|
|
1621
|
-
assertCandidateSurfaceKind(
|
|
1622
|
-
|
|
1604
|
+
assertCandidateSurfaceKind("code", preparedCode.baseline, winnerSurface);
|
|
1605
|
+
try {
|
|
1606
|
+
await preparedCode.cleanup(winnerSurface);
|
|
1607
|
+
} catch (cleanupCause) {
|
|
1623
1608
|
try {
|
|
1624
|
-
await preparedCode.cleanup(
|
|
1625
|
-
} catch (
|
|
1626
|
-
try {
|
|
1627
|
-
await preparedCode.cleanup();
|
|
1628
|
-
} catch (finalCleanupCause) {
|
|
1629
|
-
throw new AggregateError(
|
|
1630
|
-
[cleanupCause, finalCleanupCause],
|
|
1631
|
-
"improve(): code result cleanup failed, including the final all-worktree retry"
|
|
1632
|
-
);
|
|
1633
|
-
}
|
|
1609
|
+
await preparedCode.cleanup();
|
|
1610
|
+
} catch (finalCleanupCause) {
|
|
1634
1611
|
throw new AggregateError(
|
|
1635
|
-
[cleanupCause],
|
|
1636
|
-
"improve(): code result cleanup failed
|
|
1612
|
+
[cleanupCause, finalCleanupCause],
|
|
1613
|
+
"improve(): code result cleanup failed, including the final all-worktree retry"
|
|
1637
1614
|
);
|
|
1638
1615
|
}
|
|
1616
|
+
throw new AggregateError(
|
|
1617
|
+
[cleanupCause],
|
|
1618
|
+
"improve(): code result cleanup failed; the final all-worktree retry succeeded"
|
|
1619
|
+
);
|
|
1639
1620
|
}
|
|
1640
|
-
const dispose = idempotentDispose(async () => preparedCode
|
|
1641
|
-
const candidateProfile = materializeImprovementProfileCandidate(
|
|
1642
|
-
baselineProfile,
|
|
1643
|
-
surface,
|
|
1644
|
-
winnerSurface,
|
|
1645
|
-
skills
|
|
1646
|
-
);
|
|
1621
|
+
const dispose = idempotentDispose(async () => preparedCode.cleanup());
|
|
1647
1622
|
const candidate = immutableCandidateValue({
|
|
1648
|
-
surface,
|
|
1649
|
-
value: winnerSurface
|
|
1650
|
-
...candidateProfile ? { profile: candidateProfile } : {}
|
|
1623
|
+
surface: "code",
|
|
1624
|
+
value: winnerSurface
|
|
1651
1625
|
});
|
|
1652
1626
|
return {
|
|
1627
|
+
mode: "code",
|
|
1653
1628
|
candidate,
|
|
1654
1629
|
decision: raw.gateDecision,
|
|
1655
1630
|
...raw.lift !== void 0 ? { lift: raw.lift } : {},
|
|
1631
|
+
cost: copyImproveCost(raw.cost),
|
|
1632
|
+
durationMs: raw.durationMs,
|
|
1633
|
+
lineage: Object.freeze({
|
|
1634
|
+
invocationId: raw.provenance.runId,
|
|
1635
|
+
runId: raw.provenance.runId,
|
|
1636
|
+
developmentSplitDigest: raw.provenance.evidence.search.splitDigest
|
|
1637
|
+
}),
|
|
1638
|
+
generationsExplored: raw.generationsExplored,
|
|
1656
1639
|
raw,
|
|
1657
1640
|
dispose
|
|
1658
1641
|
};
|
|
1659
1642
|
}
|
|
1660
1643
|
|
|
1644
|
+
// src/improvement/method-execution.ts
|
|
1645
|
+
import { randomUUID } from "crypto";
|
|
1646
|
+
import {
|
|
1647
|
+
compareOptimizationMethods
|
|
1648
|
+
} from "@tangle-network/agent-eval/campaign";
|
|
1649
|
+
import {
|
|
1650
|
+
sha256DigestSchema
|
|
1651
|
+
} from "@tangle-network/agent-interface";
|
|
1652
|
+
|
|
1653
|
+
// src/improvement/method-controls.ts
|
|
1654
|
+
var methodRuntimeControls = /* @__PURE__ */ Symbol("agent-runtime.improvement.method-runtime-controls");
|
|
1655
|
+
function withMethodRuntimeControls(method, controls) {
|
|
1656
|
+
return Object.freeze({
|
|
1657
|
+
...method,
|
|
1658
|
+
[methodRuntimeControls]: Object.freeze({ ...controls })
|
|
1659
|
+
});
|
|
1660
|
+
}
|
|
1661
|
+
function methodRuntimeControlsOf(method) {
|
|
1662
|
+
return method[methodRuntimeControls];
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1665
|
+
// src/improvement/method-cost.ts
|
|
1666
|
+
var EVALUATION_TAG = "runtimeEvaluationRef";
|
|
1667
|
+
var INVOCATION_TAG = "runtimeInvocationId";
|
|
1668
|
+
function methodInputWithScopedCost(input, scope, costAttribution = "invocation") {
|
|
1669
|
+
return Object.freeze({
|
|
1670
|
+
...input,
|
|
1671
|
+
costLedger: scopedCostLedger(input.costLedger, scope, costAttribution)
|
|
1672
|
+
});
|
|
1673
|
+
}
|
|
1674
|
+
function methodInvocationCostLedger(ledger, scope) {
|
|
1675
|
+
return scopedCostLedger(ledger, scope, "invocation");
|
|
1676
|
+
}
|
|
1677
|
+
function assertMethodCostRecorded(methodName, result, compatibleLedger, invocationLedger, costCeiling, costAttribution = "invocation") {
|
|
1678
|
+
const { cost } = result;
|
|
1679
|
+
const observed = costAttribution === "optimizer-run" && result.provenance?.runId ? compatibleLedger.summary({ tags: { optimizerRun: result.provenance.runId } }) : invocationLedger.summary();
|
|
1680
|
+
if (costCeiling !== void 0 && !cost.accountingComplete) {
|
|
1681
|
+
throw new ConfigError(
|
|
1682
|
+
`improve(): method '${methodName}' returned incomplete cost accounting under costCeiling; refusing final scoring`
|
|
1683
|
+
);
|
|
1684
|
+
}
|
|
1685
|
+
if (costCeiling !== void 0 && exceeds(cost.totalCostUsd, costCeiling)) {
|
|
1686
|
+
throw new ConfigError(
|
|
1687
|
+
`improve(): method '${methodName}' reported cost $${cost.totalCostUsd} above costCeiling $${costCeiling}; refusing final scoring`
|
|
1688
|
+
);
|
|
1689
|
+
}
|
|
1690
|
+
if (cost.accountingComplete && !observed.accountingComplete) {
|
|
1691
|
+
throw new ConfigError(
|
|
1692
|
+
`improve(): method '${methodName}' reported complete cost accounting but its shared cost receipts are incomplete`
|
|
1693
|
+
);
|
|
1694
|
+
}
|
|
1695
|
+
if (cost.accountingComplete && !approximatelyEqual(cost.totalCostUsd, observed.totalCostUsd)) {
|
|
1696
|
+
throw new ConfigError(
|
|
1697
|
+
`improve(): method '${methodName}' reported $${cost.totalCostUsd} but recorded $${observed.totalCostUsd} through input.costLedger`
|
|
1698
|
+
);
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
function scopedCostLedger(parent, scope, costAttribution) {
|
|
1702
|
+
const evaluationTags = {
|
|
1703
|
+
[EVALUATION_TAG]: scope.evaluationRef
|
|
1704
|
+
};
|
|
1705
|
+
const invocationTags = {
|
|
1706
|
+
...evaluationTags,
|
|
1707
|
+
[INVOCATION_TAG]: scope.invocationId
|
|
1708
|
+
};
|
|
1709
|
+
const readTags = (filter) => costAttribution === "optimizer-run" && hasOptimizerRunFilter(filter) ? evaluationTags : invocationTags;
|
|
1710
|
+
return {
|
|
1711
|
+
costCeilingUsd: parent.costCeilingUsd,
|
|
1712
|
+
runPaidCall: (input) => parent.runPaidCall({
|
|
1713
|
+
...input,
|
|
1714
|
+
tags: { ...input.tags ?? {}, ...invocationTags }
|
|
1715
|
+
}),
|
|
1716
|
+
reconcile: (...args) => parent.reconcile(...args),
|
|
1717
|
+
list: (filter) => parent.list(withTags(filter, readTags(filter))),
|
|
1718
|
+
listPending: (filter) => parent.listPending?.(withTags(filter, readTags(filter))) ?? [],
|
|
1719
|
+
summary: (filter) => parent.summary(withTags(filter, readTags(filter))),
|
|
1720
|
+
waitForIdle: (options = {}) => parent.waitForIdle?.({
|
|
1721
|
+
...options,
|
|
1722
|
+
filter: withTags(options.filter, readTags(options.filter))
|
|
1723
|
+
}) ?? Promise.resolve(
|
|
1724
|
+
parent.summary(withTags(options.filter, readTags(options.filter))).pendingCalls === 0
|
|
1725
|
+
),
|
|
1726
|
+
markCompleted: (count) => parent.markCompleted(count),
|
|
1727
|
+
costPerCompletedTask: () => parent.costPerCompletedTask()
|
|
1728
|
+
};
|
|
1729
|
+
}
|
|
1730
|
+
function hasOptimizerRunFilter(filter) {
|
|
1731
|
+
return typeof filter?.tags?.optimizerRun === "string" && filter.tags.optimizerRun.length > 0;
|
|
1732
|
+
}
|
|
1733
|
+
function withTags(filter, tags) {
|
|
1734
|
+
return {
|
|
1735
|
+
...filter ?? {},
|
|
1736
|
+
tags: { ...filter?.tags ?? {}, ...tags }
|
|
1737
|
+
};
|
|
1738
|
+
}
|
|
1739
|
+
function approximatelyEqual(left, right) {
|
|
1740
|
+
const tolerance = Number.EPSILON * Math.max(1, Math.abs(left), Math.abs(right)) * 8;
|
|
1741
|
+
return Math.abs(left - right) <= tolerance;
|
|
1742
|
+
}
|
|
1743
|
+
function exceeds(value, limit) {
|
|
1744
|
+
const tolerance = Number.EPSILON * Math.max(1, Math.abs(value), Math.abs(limit)) * 8;
|
|
1745
|
+
return value - limit > tolerance;
|
|
1746
|
+
}
|
|
1747
|
+
|
|
1748
|
+
// src/improvement/method-identity.ts
|
|
1749
|
+
import {
|
|
1750
|
+
campaignSplitDigest
|
|
1751
|
+
} from "@tangle-network/agent-eval/campaign";
|
|
1752
|
+
function buildMethodEvaluationIdentity(input) {
|
|
1753
|
+
const optimizationReps = input.optimizationRunOptions?.reps ?? 1;
|
|
1754
|
+
const developmentSplitDigest = canonicalCandidateDigest({
|
|
1755
|
+
train: campaignSplitDigest(input.trainScenarios, optimizationReps),
|
|
1756
|
+
selection: campaignSplitDigest(input.selectionScenarios, optimizationReps)
|
|
1757
|
+
});
|
|
1758
|
+
const judgeDescriptors = input.judges.map(judgeDescriptor);
|
|
1759
|
+
const evaluationRef = canonicalCandidateDigest({
|
|
1760
|
+
executionRef: input.executionRef,
|
|
1761
|
+
baselineProfileDigest: input.baselineProfileDigest,
|
|
1762
|
+
coordinate: profileCoordinate(input.surface, input.baselineSurface, input.skills),
|
|
1763
|
+
candidateValidation: input.validateCandidate ? Function.prototype.toString.call(input.validateCandidate) : null,
|
|
1764
|
+
developmentSplitDigest,
|
|
1765
|
+
findings: input.findings,
|
|
1766
|
+
judges: judgeDescriptors,
|
|
1767
|
+
run: {
|
|
1768
|
+
seed: input.seed ?? 42,
|
|
1769
|
+
finalReps: input.reps ?? 1,
|
|
1770
|
+
optimizationReps,
|
|
1771
|
+
costCeiling: input.costCeiling ?? null,
|
|
1772
|
+
resumable: input.optimizationRunOptions?.resumable ?? true,
|
|
1773
|
+
maxConcurrency: input.optimizationRunOptions?.maxConcurrency ?? 2,
|
|
1774
|
+
abortOnCellError: input.optimizationRunOptions?.abortOnCellError ?? false,
|
|
1775
|
+
dispatchTimeoutMs: input.optimizationRunOptions?.dispatchTimeoutMs ?? null,
|
|
1776
|
+
dispatchShutdownTimeoutMs: input.optimizationRunOptions?.dispatchShutdownTimeoutMs ?? 5e3,
|
|
1777
|
+
tracing: input.optimizationRunOptions?.tracing ?? "on",
|
|
1778
|
+
expectUsage: input.optimizationRunOptions?.expectUsage ?? "warn",
|
|
1779
|
+
captureSource: input.optimizationRunOptions?.captureSource ?? null,
|
|
1780
|
+
captureSourceVersionHash: input.optimizationRunOptions?.captureSourceVersionHash ?? null
|
|
1781
|
+
}
|
|
1782
|
+
});
|
|
1783
|
+
return {
|
|
1784
|
+
evaluationRef,
|
|
1785
|
+
developmentSplitDigest,
|
|
1786
|
+
judgeDescriptors
|
|
1787
|
+
};
|
|
1788
|
+
}
|
|
1789
|
+
function profileCoordinate(surface, baselineSurface, skills) {
|
|
1790
|
+
return {
|
|
1791
|
+
surface,
|
|
1792
|
+
resourceName: surface === "skills" ? skills?.resourceName.trim() ?? null : null,
|
|
1793
|
+
componentNames: typeof baselineSurface === "object" && baselineSurface !== null && baselineSurface.kind === "components" ? Object.keys(baselineSurface.components).sort() : []
|
|
1794
|
+
};
|
|
1795
|
+
}
|
|
1796
|
+
function judgeDescriptor(judge) {
|
|
1797
|
+
return {
|
|
1798
|
+
name: judge.name,
|
|
1799
|
+
dimensions: judge.dimensions.map((dimension) => ({ ...dimension })),
|
|
1800
|
+
declaredVersion: judge.judgeVersion ?? null,
|
|
1801
|
+
scoreImplementation: Function.prototype.toString.call(judge.score),
|
|
1802
|
+
appliesToImplementation: judge.appliesTo ? Function.prototype.toString.call(judge.appliesTo) : null
|
|
1803
|
+
};
|
|
1804
|
+
}
|
|
1805
|
+
|
|
1806
|
+
// src/improvement/method-execution.ts
|
|
1807
|
+
function resolveOptimizationMethod(source, context) {
|
|
1808
|
+
const method = typeof source === "function" ? source(context) : source;
|
|
1809
|
+
if (!method || typeof method !== "object" || typeof method.name !== "string" || method.name.trim() !== method.name || method.name.length === 0 || typeof method.optimize !== "function") {
|
|
1810
|
+
throw new ConfigError(
|
|
1811
|
+
"improve(): method must be a complete OptimizationMethod with a trimmed name and optimize(input)"
|
|
1812
|
+
);
|
|
1813
|
+
}
|
|
1814
|
+
return method;
|
|
1815
|
+
}
|
|
1816
|
+
function copyProvenance(provenance) {
|
|
1817
|
+
return immutableCandidateValue(provenance);
|
|
1818
|
+
}
|
|
1819
|
+
function validateExecutionRef(value) {
|
|
1820
|
+
const parsed = sha256DigestSchema.safeParse(value);
|
|
1821
|
+
if (!parsed.success) {
|
|
1822
|
+
throw new ConfigError("improve(): executionRef must be a lowercase sha256:<64 hex> digest");
|
|
1823
|
+
}
|
|
1824
|
+
return parsed.data;
|
|
1825
|
+
}
|
|
1826
|
+
async function runMethodImprovement(profile, opts) {
|
|
1827
|
+
const {
|
|
1828
|
+
surface = "prompt",
|
|
1829
|
+
executionRef: inputExecutionRef,
|
|
1830
|
+
method: methodSource,
|
|
1831
|
+
agent,
|
|
1832
|
+
validateCandidate,
|
|
1833
|
+
findings: inputFindings = [],
|
|
1834
|
+
skills,
|
|
1835
|
+
profileComponents,
|
|
1836
|
+
optimizationRunOptions,
|
|
1837
|
+
minimumLift = 0,
|
|
1838
|
+
...comparisonOptions
|
|
1839
|
+
} = opts;
|
|
1840
|
+
if (!Number.isFinite(minimumLift) || minimumLift < 0) {
|
|
1841
|
+
throw new ConfigError(
|
|
1842
|
+
"improve(): minimumLift must be a finite number greater than or equal to 0"
|
|
1843
|
+
);
|
|
1844
|
+
}
|
|
1845
|
+
if (profileComponents && surface !== "agent-profile") {
|
|
1846
|
+
throw new ConfigError("improve(): profileComponents is valid only with surface 'agent-profile'");
|
|
1847
|
+
}
|
|
1848
|
+
const executionRef = validateExecutionRef(inputExecutionRef);
|
|
1849
|
+
const findings = [...inputFindings];
|
|
1850
|
+
const preparedSurface = prepareProfileSurface(profile, surface, skills, profileComponents);
|
|
1851
|
+
const baselineSurface = preparedSurface.surface;
|
|
1852
|
+
const baselineValue = immutableCandidateValue(preparedSurface.value);
|
|
1853
|
+
const baselineProfileDigest = canonicalCandidateDigest(profile);
|
|
1854
|
+
const identity = buildMethodEvaluationIdentity({
|
|
1855
|
+
executionRef,
|
|
1856
|
+
baselineProfileDigest,
|
|
1857
|
+
baselineSurface,
|
|
1858
|
+
surface,
|
|
1859
|
+
skills,
|
|
1860
|
+
validateCandidate,
|
|
1861
|
+
findings,
|
|
1862
|
+
trainScenarios: comparisonOptions.trainScenarios,
|
|
1863
|
+
selectionScenarios: comparisonOptions.selectionScenarios,
|
|
1864
|
+
judges: comparisonOptions.judges,
|
|
1865
|
+
seed: comparisonOptions.seed,
|
|
1866
|
+
reps: comparisonOptions.reps,
|
|
1867
|
+
costCeiling: comparisonOptions.costCeiling,
|
|
1868
|
+
optimizationRunOptions
|
|
1869
|
+
});
|
|
1870
|
+
const { evaluationRef, developmentSplitDigest } = identity;
|
|
1871
|
+
const dispatchRef = `improve:${evaluationRef}`;
|
|
1872
|
+
const identifiedJudges = comparisonOptions.judges.map(
|
|
1873
|
+
(judge, index) => Object.freeze({
|
|
1874
|
+
...judge,
|
|
1875
|
+
judgeVersion: canonicalCandidateDigest({
|
|
1876
|
+
evaluationRef,
|
|
1877
|
+
descriptor: identity.judgeDescriptors[index]
|
|
1878
|
+
})
|
|
1879
|
+
})
|
|
1880
|
+
);
|
|
1881
|
+
const rawMaterializeProfile = createProfileCandidateMaterializer(
|
|
1882
|
+
profile,
|
|
1883
|
+
surface,
|
|
1884
|
+
baselineSurface,
|
|
1885
|
+
skills,
|
|
1886
|
+
profileComponents
|
|
1887
|
+
);
|
|
1888
|
+
const runtimeInvocationId = `runtime-optimization:${randomUUID()}`;
|
|
1889
|
+
const method = resolveOptimizationMethod(methodSource, {
|
|
1890
|
+
profile,
|
|
1891
|
+
evaluationRef,
|
|
1892
|
+
surface,
|
|
1893
|
+
baselineSurface,
|
|
1894
|
+
baselineValue,
|
|
1895
|
+
findings
|
|
1896
|
+
});
|
|
1897
|
+
const methodControls = methodRuntimeControlsOf(method);
|
|
1898
|
+
const baselineSurfaceDigest = canonicalCandidateDigest(baselineSurface);
|
|
1899
|
+
const validatedCandidates = /* @__PURE__ */ new Set();
|
|
1900
|
+
const materializeProfile2 = (candidateSurface) => {
|
|
1901
|
+
const candidate2 = rawMaterializeProfile(candidateSurface);
|
|
1902
|
+
const candidateDigest = canonicalCandidateDigest(candidateSurface);
|
|
1903
|
+
if (!validatedCandidates.has(candidateDigest)) {
|
|
1904
|
+
const prepared = prepareProfileSurface(candidate2, surface, skills, profileComponents);
|
|
1905
|
+
const validationInput = Object.freeze({
|
|
1906
|
+
profile: candidate2,
|
|
1907
|
+
surface,
|
|
1908
|
+
candidateSurface: immutableCandidateValue(candidateSurface),
|
|
1909
|
+
value: immutableCandidateValue(prepared.value),
|
|
1910
|
+
isBaseline: candidateDigest === baselineSurfaceDigest
|
|
1911
|
+
});
|
|
1912
|
+
methodControls?.validateCandidate(validationInput);
|
|
1913
|
+
validateCandidate?.(validationInput);
|
|
1914
|
+
validatedCandidates.add(candidateDigest);
|
|
1915
|
+
}
|
|
1916
|
+
return candidate2;
|
|
1917
|
+
};
|
|
1918
|
+
materializeProfile2(baselineSurface);
|
|
1919
|
+
const measuredMethod = {
|
|
1920
|
+
...method,
|
|
1921
|
+
async optimize(input) {
|
|
1922
|
+
const costScope = {
|
|
1923
|
+
evaluationRef,
|
|
1924
|
+
invocationId: runtimeInvocationId
|
|
1925
|
+
};
|
|
1926
|
+
const scopedInput = methodInputWithScopedCost(
|
|
1927
|
+
input,
|
|
1928
|
+
costScope,
|
|
1929
|
+
methodControls?.costAttribution
|
|
1930
|
+
);
|
|
1931
|
+
const invocationLedger = methodInvocationCostLedger(input.costLedger, costScope);
|
|
1932
|
+
const result = await method.optimize(scopedInput);
|
|
1933
|
+
assertMethodCostRecorded(
|
|
1934
|
+
method.name,
|
|
1935
|
+
result,
|
|
1936
|
+
scopedInput.costLedger,
|
|
1937
|
+
invocationLedger,
|
|
1938
|
+
comparisonOptions.costCeiling,
|
|
1939
|
+
methodControls?.costAttribution
|
|
1940
|
+
);
|
|
1941
|
+
materializeProfile2(result.winnerSurface);
|
|
1942
|
+
return result;
|
|
1943
|
+
}
|
|
1944
|
+
};
|
|
1945
|
+
const startedAt = Date.now();
|
|
1946
|
+
const raw = await compareOptimizationMethods({
|
|
1947
|
+
...comparisonOptions,
|
|
1948
|
+
judges: identifiedJudges,
|
|
1949
|
+
dispatchRef,
|
|
1950
|
+
optimizationRunOptions: {
|
|
1951
|
+
...optimizationRunOptions ?? {},
|
|
1952
|
+
dispatchRef
|
|
1953
|
+
},
|
|
1954
|
+
methods: [measuredMethod],
|
|
1955
|
+
baselineSurface,
|
|
1956
|
+
dispatchWithSurface: (candidateSurface, scenario, ctx) => agent(materializeProfile2(candidateSurface), scenario, ctx)
|
|
1957
|
+
});
|
|
1958
|
+
if (comparisonOptions.costCeiling !== void 0 && raw.totalCost.totalCostUsd > comparisonOptions.costCeiling) {
|
|
1959
|
+
throw new ConfigError(
|
|
1960
|
+
`improve(): reported total cost $${raw.totalCost.totalCostUsd} exceeds costCeiling $${comparisonOptions.costCeiling}`
|
|
1961
|
+
);
|
|
1962
|
+
}
|
|
1963
|
+
const score = raw.best;
|
|
1964
|
+
const winnerSurface = immutableCandidateValue(score.winnerSurface);
|
|
1965
|
+
assertCandidateSurfaceKind(surface, baselineSurface, winnerSurface);
|
|
1966
|
+
const candidateProfile = materializeProfile2(winnerSurface);
|
|
1967
|
+
const candidate = Object.freeze({
|
|
1968
|
+
surface,
|
|
1969
|
+
value: winnerSurface,
|
|
1970
|
+
profile: candidateProfile
|
|
1971
|
+
});
|
|
1972
|
+
const cost = copyImproveCost(raw.totalCost);
|
|
1973
|
+
return {
|
|
1974
|
+
mode: "method",
|
|
1975
|
+
method: method.name,
|
|
1976
|
+
...score.provenance ? { provenance: copyProvenance(score.provenance) } : {},
|
|
1977
|
+
candidate,
|
|
1978
|
+
decision: cost.accountingComplete && score.liftCi.low > minimumLift ? "ship" : "hold",
|
|
1979
|
+
lift: score.lift,
|
|
1980
|
+
liftInterval: { ...score.liftCi },
|
|
1981
|
+
cost,
|
|
1982
|
+
durationMs: Date.now() - startedAt,
|
|
1983
|
+
lineage: Object.freeze({
|
|
1984
|
+
invocationId: runtimeInvocationId,
|
|
1985
|
+
runId: score.provenance?.runId ?? runtimeInvocationId,
|
|
1986
|
+
developmentSplitDigest,
|
|
1987
|
+
executionRef,
|
|
1988
|
+
baselineProfileDigest
|
|
1989
|
+
}),
|
|
1990
|
+
raw,
|
|
1991
|
+
async dispose() {
|
|
1992
|
+
}
|
|
1993
|
+
};
|
|
1994
|
+
}
|
|
1995
|
+
|
|
1996
|
+
// src/improvement/improve.ts
|
|
1997
|
+
async function improve(profileOrCode, opts) {
|
|
1998
|
+
if (opts === void 0) {
|
|
1999
|
+
const code = profileOrCode;
|
|
2000
|
+
if (!code || code.surface !== "code") {
|
|
2001
|
+
throw new ConfigError("improve(): the one-argument form requires { surface: 'code', ... }");
|
|
2002
|
+
}
|
|
2003
|
+
return runCodeImprovement(code);
|
|
2004
|
+
}
|
|
2005
|
+
if (opts.surface === "code") {
|
|
2006
|
+
throw new ConfigError("improve(): code takes one argument: improve({ surface: 'code', ... })");
|
|
2007
|
+
}
|
|
2008
|
+
const parsedProfile = agentProfileSchema2.safeParse(profileOrCode);
|
|
2009
|
+
if (!parsedProfile.success) {
|
|
2010
|
+
throw new ConfigError(
|
|
2011
|
+
`improve(): input is not a valid AgentProfile: ${parsedProfile.error.message}`
|
|
2012
|
+
);
|
|
2013
|
+
}
|
|
2014
|
+
return runMethodImprovement(immutableCandidateValue(parsedProfile.data), opts);
|
|
2015
|
+
}
|
|
2016
|
+
|
|
1661
2017
|
// src/intelligence/improvement-surfaces.ts
|
|
1662
2018
|
import {
|
|
1663
2019
|
agentProfileDiffSchema,
|
|
1664
|
-
agentProfileSchema as
|
|
2020
|
+
agentProfileSchema as agentProfileSchema3,
|
|
1665
2021
|
defineAgentProfileDiff
|
|
1666
2022
|
} from "@tangle-network/agent-interface";
|
|
1667
2023
|
var changedSurfaceOrder = [
|
|
@@ -1864,7 +2220,7 @@ function exactObject(value, keys, label) {
|
|
|
1864
2220
|
return record;
|
|
1865
2221
|
}
|
|
1866
2222
|
function parseProfileSet(value) {
|
|
1867
|
-
return
|
|
2223
|
+
return agentProfileSchema3.parse(value);
|
|
1868
2224
|
}
|
|
1869
2225
|
function assertKnowledgeCandidatePair(baselineBundle, candidateBundle) {
|
|
1870
2226
|
const baseline = baselineBundle.knowledge;
|
|
@@ -1934,6 +2290,160 @@ function opaqueProfileSlice(profile) {
|
|
|
1934
2290
|
};
|
|
1935
2291
|
}
|
|
1936
2292
|
|
|
2293
|
+
// src/intelligence/optimization-receipt.ts
|
|
2294
|
+
import {
|
|
2295
|
+
agentProfileModelHintsSchema
|
|
2296
|
+
} from "@tangle-network/agent-interface";
|
|
2297
|
+
var optimizationReceiptMetadataKey = "optimizationReceipt";
|
|
2298
|
+
function createOptimizationActivationReceipt(improvement) {
|
|
2299
|
+
const provenance = improvement.provenance;
|
|
2300
|
+
if (!provenance) return void 0;
|
|
2301
|
+
const optimizerModel = provenance.optimizerModel;
|
|
2302
|
+
const candidateModel = improvement.candidate.profile.model;
|
|
2303
|
+
return canonicalCandidateDocument({
|
|
2304
|
+
kind: "optimization-activation-receipt",
|
|
2305
|
+
method: improvement.method,
|
|
2306
|
+
source: provenance.source,
|
|
2307
|
+
...provenance.bridge ? { bridge: provenance.bridge } : {},
|
|
2308
|
+
...provenance.modules ? { modules: provenance.modules } : {},
|
|
2309
|
+
...provenance.python ? { python: provenance.python } : {},
|
|
2310
|
+
...candidateModel || optimizerModel ? {
|
|
2311
|
+
models: {
|
|
2312
|
+
...candidateModel ? { candidate: candidateModel } : {},
|
|
2313
|
+
...optimizerModel ? { optimizer: optimizerModel } : {}
|
|
2314
|
+
}
|
|
2315
|
+
} : {},
|
|
2316
|
+
usage: {
|
|
2317
|
+
optimizerEvaluations: provenance.evaluationCount,
|
|
2318
|
+
...provenance.tokenUsage ? { optimizerTokens: provenance.tokenUsage } : {}
|
|
2319
|
+
},
|
|
2320
|
+
cost: {
|
|
2321
|
+
optimization: receiptCost(improvement.raw.optimizationCost),
|
|
2322
|
+
finalTest: receiptCost(improvement.raw.testCost),
|
|
2323
|
+
total: receiptCost(improvement.raw.totalCost)
|
|
2324
|
+
},
|
|
2325
|
+
invocation: {
|
|
2326
|
+
runtimeInvocationId: improvement.lineage.invocationId,
|
|
2327
|
+
optimizerRunId: provenance.runId,
|
|
2328
|
+
...provenance.compatibleRunId ? { compatibleOptimizerRunId: provenance.compatibleRunId } : {},
|
|
2329
|
+
resumed: provenance.resumed,
|
|
2330
|
+
artifactDir: provenance.artifactDir
|
|
2331
|
+
},
|
|
2332
|
+
developmentDataDigest: improvement.lineage.developmentSplitDigest
|
|
2333
|
+
}).value;
|
|
2334
|
+
}
|
|
2335
|
+
function attachOptimizationActivationReceipt(metadata, receipt) {
|
|
2336
|
+
assertNoCallerOptimizationReceipt(metadata);
|
|
2337
|
+
return immutableCandidateValue({
|
|
2338
|
+
...metadata ?? {},
|
|
2339
|
+
[optimizationReceiptMetadataKey]: receipt
|
|
2340
|
+
});
|
|
2341
|
+
}
|
|
2342
|
+
function assertNoCallerOptimizationReceipt(metadata) {
|
|
2343
|
+
if (metadata && Object.hasOwn(metadata, optimizationReceiptMetadataKey)) {
|
|
2344
|
+
throw new Error(`candidate metadata reserves '${optimizationReceiptMetadataKey}' for Runtime`);
|
|
2345
|
+
}
|
|
2346
|
+
}
|
|
2347
|
+
function optimizationActivationReceiptFromMetadata(metadata) {
|
|
2348
|
+
const value = metadata?.[optimizationReceiptMetadataKey];
|
|
2349
|
+
if (value === void 0) return void 0;
|
|
2350
|
+
return immutableCandidateValue(parseOptimizationActivationReceipt(value));
|
|
2351
|
+
}
|
|
2352
|
+
function parseOptimizationActivationReceipt(value) {
|
|
2353
|
+
if (!isRecord(value) || value.kind !== "optimization-activation-receipt") {
|
|
2354
|
+
throw new Error("optimization receipt must be an optimization-activation-receipt");
|
|
2355
|
+
}
|
|
2356
|
+
if (!isNonEmptyString(value.method) || !isPackageSource(value.source) || value.bridge !== void 0 && !isPackageSource(value.bridge) || !isModules(value.modules) || !isPythonRuntime(value.python) || !isModels(value.models) || !isUsage(value.usage) || !isCost(value.cost) || !isInvocation(value.invocation) || !isSha256Digest(value.developmentDataDigest) || !isSha256Digest(value.digest)) {
|
|
2357
|
+
throw new Error("optimization receipt contains invalid evidence");
|
|
2358
|
+
}
|
|
2359
|
+
const receipt = value;
|
|
2360
|
+
if (canonicalCandidateDigest(omitTopLevelDigest(receipt)) !== receipt.digest) {
|
|
2361
|
+
throw new Error("optimization receipt digest does not match its evidence");
|
|
2362
|
+
}
|
|
2363
|
+
return receipt;
|
|
2364
|
+
}
|
|
2365
|
+
function isPackageSource(value) {
|
|
2366
|
+
if (!isRecord(value) || value.kind !== "package" || value.evidence !== "observed" && value.evidence !== "declared" || !isNonEmptyString(value.package) || !isNonEmptyString(value.version)) {
|
|
2367
|
+
return false;
|
|
2368
|
+
}
|
|
2369
|
+
return isOptionalNonEmptyString(value.sourceUrl) && isOptionalNonEmptyString(value.revision) && (value.sourceSha256 === void 0 || typeof value.sourceSha256 === "string" && /^[0-9a-f]{64}$/.test(value.sourceSha256));
|
|
2370
|
+
}
|
|
2371
|
+
function isModules(value) {
|
|
2372
|
+
return value === void 0 || Array.isArray(value) && value.every(
|
|
2373
|
+
(module) => isRecord(module) && isNonEmptyString(module.module) && typeof module.sourceSha256 === "string" && /^[0-9a-f]{64}$/.test(module.sourceSha256)
|
|
2374
|
+
);
|
|
2375
|
+
}
|
|
2376
|
+
function isPythonRuntime(value) {
|
|
2377
|
+
return value === void 0 || isRecord(value) && isNonEmptyString(value.implementation) && isNonEmptyString(value.version);
|
|
2378
|
+
}
|
|
2379
|
+
function isModels(value) {
|
|
2380
|
+
return value === void 0 || isRecord(value) && (value.candidate === void 0 || agentProfileModelHintsSchema.safeParse(value.candidate).success) && isOptionalNonEmptyString(value.optimizer) && (value.candidate !== void 0 || value.optimizer !== void 0);
|
|
2381
|
+
}
|
|
2382
|
+
function isUsage(value) {
|
|
2383
|
+
if (!isRecord(value) || !isNonNegativeInteger(value.optimizerEvaluations)) return false;
|
|
2384
|
+
if (value.optimizerTokens === void 0) return true;
|
|
2385
|
+
const tokens = value.optimizerTokens;
|
|
2386
|
+
if (!isRecord(tokens)) return false;
|
|
2387
|
+
const inputTokens = tokens.inputTokens;
|
|
2388
|
+
const outputTokens = tokens.outputTokens;
|
|
2389
|
+
const totalTokens = tokens.totalTokens;
|
|
2390
|
+
const calls = tokens.calls;
|
|
2391
|
+
if (!isNonNegativeInteger(inputTokens) || !isNonNegativeInteger(outputTokens) || !isNonNegativeInteger(totalTokens) || !isNonNegativeInteger(calls)) {
|
|
2392
|
+
return false;
|
|
2393
|
+
}
|
|
2394
|
+
if (!isOptionalNonNegativeInteger(tokens.cachedInputTokens) || !isOptionalNonNegativeInteger(tokens.cacheWriteInputTokens) || !isOptionalNonNegativeInteger(tokens.reasoningTokens)) {
|
|
2395
|
+
return false;
|
|
2396
|
+
}
|
|
2397
|
+
const cachedInputTokens = typeof tokens.cachedInputTokens === "number" ? tokens.cachedInputTokens : 0;
|
|
2398
|
+
const cacheWriteInputTokens = typeof tokens.cacheWriteInputTokens === "number" ? tokens.cacheWriteInputTokens : 0;
|
|
2399
|
+
const reasoningTokens = typeof tokens.reasoningTokens === "number" ? tokens.reasoningTokens : 0;
|
|
2400
|
+
return totalTokens === inputTokens + outputTokens && cachedInputTokens + cacheWriteInputTokens <= inputTokens && reasoningTokens <= outputTokens && (totalTokens === 0 || calls > 0);
|
|
2401
|
+
}
|
|
2402
|
+
function isCost(value) {
|
|
2403
|
+
if (!isRecord(value) || !isCostPart(value.optimization) || !isCostPart(value.finalTest) || !isCostPart(value.total)) {
|
|
2404
|
+
return false;
|
|
2405
|
+
}
|
|
2406
|
+
const optimization = value.optimization;
|
|
2407
|
+
const finalTest = value.finalTest;
|
|
2408
|
+
const total = value.total;
|
|
2409
|
+
return approximatelyEqual2(total.totalUsd, optimization.totalUsd + finalTest.totalUsd) && total.accountingComplete === (optimization.accountingComplete && finalTest.accountingComplete);
|
|
2410
|
+
}
|
|
2411
|
+
function isCostPart(value) {
|
|
2412
|
+
return isRecord(value) && typeof value.totalUsd === "number" && Number.isFinite(value.totalUsd) && value.totalUsd >= 0 && typeof value.accountingComplete === "boolean" && Array.isArray(value.incompleteReasons) && value.incompleteReasons.every((reason) => typeof reason === "string");
|
|
2413
|
+
}
|
|
2414
|
+
function receiptCost(value) {
|
|
2415
|
+
return {
|
|
2416
|
+
totalUsd: value.totalCostUsd,
|
|
2417
|
+
accountingComplete: value.accountingComplete,
|
|
2418
|
+
incompleteReasons: [...value.incompleteReasons]
|
|
2419
|
+
};
|
|
2420
|
+
}
|
|
2421
|
+
function approximatelyEqual2(left, right) {
|
|
2422
|
+
const tolerance = Number.EPSILON * Math.max(1, Math.abs(left), Math.abs(right)) * 8;
|
|
2423
|
+
return Math.abs(left - right) <= tolerance;
|
|
2424
|
+
}
|
|
2425
|
+
function isInvocation(value) {
|
|
2426
|
+
return isRecord(value) && isNonEmptyString(value.runtimeInvocationId) && isNonEmptyString(value.optimizerRunId) && isOptionalNonEmptyString(value.compatibleOptimizerRunId) && typeof value.resumed === "boolean" && isNonEmptyString(value.artifactDir);
|
|
2427
|
+
}
|
|
2428
|
+
function isRecord(value) {
|
|
2429
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2430
|
+
}
|
|
2431
|
+
function isNonEmptyString(value) {
|
|
2432
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
2433
|
+
}
|
|
2434
|
+
function isOptionalNonEmptyString(value) {
|
|
2435
|
+
return value === void 0 || isNonEmptyString(value);
|
|
2436
|
+
}
|
|
2437
|
+
function isNonNegativeInteger(value) {
|
|
2438
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
2439
|
+
}
|
|
2440
|
+
function isOptionalNonNegativeInteger(value) {
|
|
2441
|
+
return value === void 0 || isNonNegativeInteger(value);
|
|
2442
|
+
}
|
|
2443
|
+
function isSha256Digest(value) {
|
|
2444
|
+
return typeof value === "string" && /^sha256:[0-9a-f]{64}$/.test(value);
|
|
2445
|
+
}
|
|
2446
|
+
|
|
1937
2447
|
// src/intelligence/improvement-cycle.ts
|
|
1938
2448
|
import { assertNoJudgeVerdict } from "@tangle-network/agent-eval/analyst";
|
|
1939
2449
|
import {
|
|
@@ -1965,8 +2475,8 @@ function sealAgentImprovementExperiment(material, improvement) {
|
|
|
1965
2475
|
const candidateLineage = {
|
|
1966
2476
|
source: "optimizer",
|
|
1967
2477
|
parentDigests: [material.baseline.digest],
|
|
1968
|
-
runIds: [improvement.
|
|
1969
|
-
developmentSplitDigest: improvement.
|
|
2478
|
+
runIds: [improvement.lineage.runId],
|
|
2479
|
+
developmentSplitDigest: improvement.lineage.developmentSplitDigest
|
|
1970
2480
|
};
|
|
1971
2481
|
return sealCandidateExperiment({ ...material, candidateLineage });
|
|
1972
2482
|
}
|
|
@@ -2060,16 +2570,22 @@ function createAgentImprovementMeasuredComparison(options) {
|
|
|
2060
2570
|
return verifyCandidateExperimentComparison(measuredComparisonFromCandidateExperiment(options));
|
|
2061
2571
|
}
|
|
2062
2572
|
async function proposeAgentImprovement(options) {
|
|
2573
|
+
assertNoCallerOptimizationReceipt(options.metadata);
|
|
2063
2574
|
const analysis = await runAnalystLoop({ ...options.analysis, runId: options.runId });
|
|
2064
2575
|
const findings = assertNoJudgeVerdict(
|
|
2065
2576
|
analysis.analystResult.findings,
|
|
2066
2577
|
"proposeAgentImprovement findings"
|
|
2067
2578
|
);
|
|
2068
|
-
const
|
|
2579
|
+
const improvementInput = {
|
|
2580
|
+
...options.improvement,
|
|
2581
|
+
findings: [...options.improvement.findings ?? [], ...findings]
|
|
2582
|
+
};
|
|
2583
|
+
const improvement = improvementInput.surface === "code" ? await improve(improvementInput) : await improve(options.profile, improvementInput);
|
|
2069
2584
|
try {
|
|
2070
2585
|
if (improvement.decision !== "ship") {
|
|
2071
2586
|
throw new Error("agent improvement search did not produce a promotable candidate");
|
|
2072
2587
|
}
|
|
2588
|
+
const optimizationReceipt = improvement.mode === "method" ? createOptimizationActivationReceipt(improvement) : void 0;
|
|
2073
2589
|
const experiment = sealAgentImprovementExperiment(
|
|
2074
2590
|
await options.buildExperiment({ analysis, improvement }),
|
|
2075
2591
|
improvement
|
|
@@ -2083,10 +2599,12 @@ async function proposeAgentImprovement(options) {
|
|
|
2083
2599
|
...options.maxConcurrency === void 0 ? {} : { maxConcurrency: options.maxConcurrency },
|
|
2084
2600
|
...options.signal ? { signal: options.signal } : {},
|
|
2085
2601
|
...options.candidate ? { candidate: options.candidate } : {},
|
|
2086
|
-
...
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2602
|
+
...optimizationReceipt ? {
|
|
2603
|
+
metadata: attachOptimizationActivationReceipt(options.metadata, optimizationReceipt)
|
|
2604
|
+
} : options.metadata ? { metadata: options.metadata } : {},
|
|
2605
|
+
...improvement.generationsExplored === void 0 ? {} : { generationsExplored: improvement.generationsExplored },
|
|
2606
|
+
searchDurationMs: improvement.durationMs,
|
|
2607
|
+
searchCostUsd: improvement.cost.totalCostUsd
|
|
2090
2608
|
});
|
|
2091
2609
|
const proposal = createAgentImprovementProposal({
|
|
2092
2610
|
runId: options.runId,
|
|
@@ -2108,9 +2626,6 @@ async function proposeAgentImprovement(options) {
|
|
|
2108
2626
|
function assertImprovementCandidateBinding(improvement, experiment) {
|
|
2109
2627
|
const candidate = improvement.candidate;
|
|
2110
2628
|
if (candidate.surface !== "code") {
|
|
2111
|
-
if (!candidate.profile) {
|
|
2112
|
-
throw new Error(`improvement surface '${candidate.surface}' did not produce an exact profile`);
|
|
2113
|
-
}
|
|
2114
2629
|
try {
|
|
2115
2630
|
assertCandidateProfileBinding(candidate.profile, experiment.candidate.profile);
|
|
2116
2631
|
} catch (cause) {
|
|
@@ -2133,6 +2648,7 @@ function createAgentImprovementProposal(options) {
|
|
|
2133
2648
|
"createAgentImprovementProposal findings"
|
|
2134
2649
|
);
|
|
2135
2650
|
const evaluation = verifyCandidateExperimentComparison(options.evaluation);
|
|
2651
|
+
optimizationActivationReceiptFromMetadata(evaluation.metadata);
|
|
2136
2652
|
if (evaluation.decision.outcome !== "ship") {
|
|
2137
2653
|
throw new Error("agent improvement proposal requires a passing experiment");
|
|
2138
2654
|
}
|
|
@@ -2219,6 +2735,7 @@ function verifyAgentImprovementProposal(input) {
|
|
|
2219
2735
|
"agent improvement proposal"
|
|
2220
2736
|
);
|
|
2221
2737
|
const evaluation = verifyCandidateExperimentComparison(proposal.evaluation);
|
|
2738
|
+
optimizationActivationReceiptFromMetadata(evaluation.metadata);
|
|
2222
2739
|
if (evaluation.decision.outcome !== "ship") {
|
|
2223
2740
|
throw new Error("agent improvement proposal does not contain a passing experiment");
|
|
2224
2741
|
}
|
|
@@ -2366,17 +2883,14 @@ export {
|
|
|
2366
2883
|
LIFTED_FINDING_ANALYST_ID,
|
|
2367
2884
|
isAnalystFinding,
|
|
2368
2885
|
toAnalystFindings,
|
|
2369
|
-
improvementDriver,
|
|
2370
|
-
rawTraceDistiller,
|
|
2371
2886
|
ROLLOUT_POLICY_EXTENSION,
|
|
2372
|
-
ROLLOUT_POLICY_BOUNDS,
|
|
2373
2887
|
parseRolloutPolicy,
|
|
2374
2888
|
normalizeRolloutPolicy,
|
|
2375
2889
|
serializeRolloutPolicy,
|
|
2376
2890
|
structuralRolloutPolicyFromProfile,
|
|
2377
2891
|
applyRolloutPolicyToProfile,
|
|
2378
|
-
|
|
2379
|
-
|
|
2892
|
+
rawTraceDistiller,
|
|
2893
|
+
withMethodRuntimeControls,
|
|
2380
2894
|
improve,
|
|
2381
2895
|
AGENT_IMPROVEMENT_PROFILE_SURFACES,
|
|
2382
2896
|
buildAgentImprovementActivationTargets,
|
|
@@ -2386,6 +2900,8 @@ export {
|
|
|
2386
2900
|
agentImprovementProfileSurfaceInput,
|
|
2387
2901
|
agentImprovementProfileSurfaceDigest,
|
|
2388
2902
|
agentImprovementTargetProfileDiffs,
|
|
2903
|
+
createOptimizationActivationReceipt,
|
|
2904
|
+
optimizationActivationReceiptFromMetadata,
|
|
2389
2905
|
AgentCandidateExperimentCellExecutionError,
|
|
2390
2906
|
runAgentCandidateExperiment,
|
|
2391
2907
|
executeAgentCandidateExperimentCell,
|
|
@@ -2399,4 +2915,4 @@ export {
|
|
|
2399
2915
|
verifyAgentImprovementActivation,
|
|
2400
2916
|
verifyCandidateExecutionEvidence
|
|
2401
2917
|
};
|
|
2402
|
-
//# sourceMappingURL=chunk-
|
|
2918
|
+
//# sourceMappingURL=chunk-UHEZW5BU.js.map
|