@tangle-network/agent-knowledge 4.1.0 → 5.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +3 -1
- package/CHANGELOG.md +34 -0
- package/README.md +220 -955
- package/dist/benchmarks/index.d.ts +3 -2
- package/dist/benchmarks/index.js +1 -1
- package/dist/{chunk-BBCIB4UL.js → chunk-EYIA5PLQ.js} +27 -195
- package/dist/chunk-EYIA5PLQ.js.map +1 -0
- package/dist/{chunk-CPMLJYA3.js → chunk-LMR53POQ.js} +1227 -574
- package/dist/chunk-LMR53POQ.js.map +1 -0
- package/dist/index-Cf7txrYP.d.ts +790 -0
- package/dist/index.d.ts +208 -24
- package/dist/index.js +632 -80
- package/dist/index.js.map +1 -1
- package/dist/memory/index.d.ts +8 -706
- package/dist/memory/index.js +2 -2
- package/dist/{types-DP38encz.d.ts → types-BY-xLVw-.d.ts} +16 -59
- package/docs/eval/rag-eval-roadmap.md +15 -12
- package/package.json +8 -5
- package/skills/build-with-agent-knowledge/SKILL.md +97 -0
- package/dist/chunk-BBCIB4UL.js.map +0 -1
- package/dist/chunk-CPMLJYA3.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -64,6 +64,7 @@ import {
|
|
|
64
64
|
agentMemorySequenceJudge,
|
|
65
65
|
applyRetrievalHoldout,
|
|
66
66
|
applySessionStickyRetrievalHoldout,
|
|
67
|
+
assertImmutableRef,
|
|
67
68
|
buildAgentMemorySequenceScenarios,
|
|
68
69
|
buildAgentMemorySequencesFromBenchmarkCases,
|
|
69
70
|
createAgentMemoryBranch,
|
|
@@ -75,14 +76,18 @@ import {
|
|
|
75
76
|
emitRetrievalHoldoutBypass,
|
|
76
77
|
forkAgentMemoryBranchSnapshot,
|
|
77
78
|
graphitiMemoryAdapterIdentity,
|
|
79
|
+
jsonCandidateCodec,
|
|
80
|
+
jsonObjectCandidateCodec,
|
|
78
81
|
mem0MemoryAdapterIdentity,
|
|
79
82
|
renderMemoryContext,
|
|
80
83
|
resetRetrievalHoldoutRegistry,
|
|
81
84
|
retrievalHoldoutConfigHash,
|
|
82
85
|
runAgentMemoryExperiment,
|
|
83
86
|
runAgentMemoryImprovement,
|
|
87
|
+
runSerializedKnowledgeOptimization,
|
|
88
|
+
scenarioContentFingerprint,
|
|
84
89
|
toOffPolicyTrajectory
|
|
85
|
-
} from "./chunk-
|
|
90
|
+
} from "./chunk-LMR53POQ.js";
|
|
86
91
|
import {
|
|
87
92
|
IRS_DIMENSION_HINTS,
|
|
88
93
|
MAX_RESPONSE_BYTES,
|
|
@@ -112,7 +117,6 @@ import {
|
|
|
112
117
|
buildKnowledgeBenchmarkScenarios,
|
|
113
118
|
buildRetrievalBenchmarkCasesFromQrels,
|
|
114
119
|
buildRetrievalEvalDispatch,
|
|
115
|
-
buildRetrievalParameterCandidates,
|
|
116
120
|
createInMemoryBenchmarkAdapter,
|
|
117
121
|
createMemoryExecutionPool,
|
|
118
122
|
createNoopMemoryBenchmarkAdapter,
|
|
@@ -123,24 +127,23 @@ import {
|
|
|
123
127
|
memoryWriteResultToSourceRecord,
|
|
124
128
|
parseKnowledgeBenchmarkJsonl,
|
|
125
129
|
parseKnowledgeBenchmarkQrels,
|
|
130
|
+
partitionRetrievalScenarios,
|
|
126
131
|
renderKnowledgeBenchmarkReportMarkdown,
|
|
127
132
|
resolveMemoryCleanupTimeoutMs,
|
|
128
133
|
respondToIndustryMemoryBenchmarkSmokeCase,
|
|
129
134
|
respondToIndustryRagBenchmarkSmokeCase,
|
|
130
135
|
retrievalConfigFromSurface,
|
|
131
136
|
retrievalConfigSurface,
|
|
132
|
-
retrievalParameterSweepProposer,
|
|
133
137
|
retrievalRecallJudge,
|
|
134
138
|
runBoundedMemoryLifecycle,
|
|
135
139
|
runKnowledgeBenchmarkSuite,
|
|
136
140
|
runMemoryAdapterBenchmark,
|
|
137
|
-
runRetrievalImprovementLoop,
|
|
138
141
|
scoreKnowledgeBenchmarkArtifact,
|
|
139
142
|
scoreMemoryBenchmarkArtifact,
|
|
140
143
|
scoreRetrievalArtifact,
|
|
141
144
|
sleepForMemoryRecovery,
|
|
142
145
|
summarizeKnowledgeBenchmarkCampaign
|
|
143
|
-
} from "./chunk-
|
|
146
|
+
} from "./chunk-EYIA5PLQ.js";
|
|
144
147
|
import {
|
|
145
148
|
reciprocalRankFusion,
|
|
146
149
|
searchKnowledge,
|
|
@@ -691,6 +694,7 @@ import {
|
|
|
691
694
|
} from "@tangle-network/agent-interface";
|
|
692
695
|
import { z } from "zod";
|
|
693
696
|
var digestSchema = z.string().regex(/^[a-f0-9]{64}$/);
|
|
697
|
+
var immutableRefSchema = z.string().regex(/^(?:sha256:[a-f0-9]{64}|git:[a-f0-9]{40})$/);
|
|
694
698
|
var runIdSchema = z.string().min(1).max(2048);
|
|
695
699
|
var safePathSegmentSchema = z.string().min(1).max(128).regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/);
|
|
696
700
|
var knowledgeImprovementMutationReceiptSchema = z.object({
|
|
@@ -770,6 +774,7 @@ var candidateRecordSchema = z.object({
|
|
|
770
774
|
candidateHash: digestSchema.optional(),
|
|
771
775
|
evidenceHash: digestSchema.optional(),
|
|
772
776
|
promotionPlanHash: digestSchema.optional(),
|
|
777
|
+
finalEvaluationStartedAt: z.iso.datetime().optional(),
|
|
773
778
|
status: improvementStatusSchema,
|
|
774
779
|
createdAt: z.iso.datetime(),
|
|
775
780
|
updatedAt: z.iso.datetime()
|
|
@@ -778,6 +783,7 @@ var KnowledgeImprovementRunStateSchema = z.object({
|
|
|
778
783
|
runId: runIdSchema,
|
|
779
784
|
root: z.string().min(1),
|
|
780
785
|
goal: z.string().min(1),
|
|
786
|
+
implementationRef: immutableRefSchema,
|
|
781
787
|
status: improvementStatusSchema,
|
|
782
788
|
baseHash: digestSchema,
|
|
783
789
|
createdAt: z.iso.datetime(),
|
|
@@ -874,6 +880,7 @@ var KnowledgeImprovementEvidenceSchema = z.object({
|
|
|
874
880
|
candidateId: safePathSegmentSchema,
|
|
875
881
|
iteration: z.number().int().positive(),
|
|
876
882
|
goalHash: digestSchema,
|
|
883
|
+
implementationRef: immutableRefSchema,
|
|
877
884
|
baseHash: digestSchema,
|
|
878
885
|
candidateHash: digestSchema,
|
|
879
886
|
promotionPlanHash: digestSchema,
|
|
@@ -899,6 +906,7 @@ var UPDATE_PHASES = [
|
|
|
899
906
|
"knowledge-update"
|
|
900
907
|
];
|
|
901
908
|
var EVALUATION_PHASES = [
|
|
909
|
+
"rag-optimization",
|
|
902
910
|
"retrieval-tuning",
|
|
903
911
|
"gap-diagnosis",
|
|
904
912
|
"answer-quality",
|
|
@@ -1279,7 +1287,60 @@ function immutableJsonValue(value) {
|
|
|
1279
1287
|
|
|
1280
1288
|
// src/kb-improvement/evaluation.ts
|
|
1281
1289
|
import { join as join3 } from "path";
|
|
1282
|
-
import { contentHash as
|
|
1290
|
+
import { contentHash as contentHash6 } from "@tangle-network/agent-eval";
|
|
1291
|
+
|
|
1292
|
+
// src/rag-answer-evidence.ts
|
|
1293
|
+
function assertRagAnswerEvidence(result) {
|
|
1294
|
+
if (!result || typeof result !== "object") {
|
|
1295
|
+
throw new Error("answer-quality evidence must be an object");
|
|
1296
|
+
}
|
|
1297
|
+
if (typeof result.passed !== "boolean") {
|
|
1298
|
+
throw new Error("answer-quality evidence requires a boolean passed verdict");
|
|
1299
|
+
}
|
|
1300
|
+
assertImmutableRef(result.datasetRef, "answer-quality datasetRef");
|
|
1301
|
+
assertImmutableRef(result.evaluatorRef, "answer-quality evaluatorRef");
|
|
1302
|
+
if (!Array.isArray(result.finalScenarioIds) || result.finalScenarioIds.length < 2 || new Set(result.finalScenarioIds).size !== result.finalScenarioIds.length || result.finalScenarioIds.some((id) => typeof id !== "string" || id.trim().length === 0)) {
|
|
1303
|
+
throw new Error("answer-quality evidence requires at least 2 unique final scenario IDs");
|
|
1304
|
+
}
|
|
1305
|
+
if (!result.metrics || typeof result.metrics !== "object" || Array.isArray(result.metrics)) {
|
|
1306
|
+
throw new Error("answer-quality evidence requires non-empty finite metrics");
|
|
1307
|
+
}
|
|
1308
|
+
const metrics = Object.entries(result.metrics);
|
|
1309
|
+
if (metrics.length === 0 || metrics.some(([key, value]) => key.trim().length === 0 || !Number.isFinite(value))) {
|
|
1310
|
+
throw new Error("answer-quality evidence requires non-empty finite metrics");
|
|
1311
|
+
}
|
|
1312
|
+
if (!result.cost || typeof result.cost !== "object") {
|
|
1313
|
+
throw new Error("answer-quality evidence requires cost accounting");
|
|
1314
|
+
}
|
|
1315
|
+
if (!Number.isFinite(result.cost.totalCostUsd) || result.cost.totalCostUsd < 0 || typeof result.cost.accountingComplete !== "boolean" || !Array.isArray(result.cost.incompleteReasons) || result.cost.incompleteReasons.some((reason) => typeof reason !== "string" || !reason.trim())) {
|
|
1316
|
+
throw new Error("answer-quality evidence has invalid cost accounting");
|
|
1317
|
+
}
|
|
1318
|
+
if (result.cost.accountingComplete && result.cost.incompleteReasons.length > 0) {
|
|
1319
|
+
throw new Error("complete answer-quality cost accounting cannot include incomplete reasons");
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
function ragAnswerEvidenceRejectionReasons(evidence, costCeiling) {
|
|
1323
|
+
const reasons = [];
|
|
1324
|
+
if (!evidence.passed) reasons.push("answer-quality evaluation failed");
|
|
1325
|
+
if (!evidence.cost.accountingComplete) {
|
|
1326
|
+
reasons.push("answer-quality final comparison has incomplete cost accounting");
|
|
1327
|
+
}
|
|
1328
|
+
if (costCeiling === void 0) {
|
|
1329
|
+
reasons.push("answer-quality promotion requires answerQualityCostCeiling");
|
|
1330
|
+
} else if (exceedsCostCeiling(evidence.cost.totalCostUsd, costCeiling)) {
|
|
1331
|
+
reasons.push(
|
|
1332
|
+
`answer-quality final comparison cost ${evidence.cost.totalCostUsd} exceeds ${costCeiling}`
|
|
1333
|
+
);
|
|
1334
|
+
}
|
|
1335
|
+
return reasons;
|
|
1336
|
+
}
|
|
1337
|
+
function exceedsCostCeiling(totalCostUsd, costCeiling) {
|
|
1338
|
+
const tolerance = Number.EPSILON * Math.max(1, Math.abs(totalCostUsd), Math.abs(costCeiling)) * 8;
|
|
1339
|
+
return totalCostUsd - costCeiling > tolerance;
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
// src/rag-eval/calibration.ts
|
|
1343
|
+
import { contentHash as contentHash3 } from "@tangle-network/agent-eval";
|
|
1283
1344
|
|
|
1284
1345
|
// src/claim-grounding.ts
|
|
1285
1346
|
var citedClaimKey = "citedClaim";
|
|
@@ -1911,6 +1972,12 @@ function below(metric, threshold) {
|
|
|
1911
1972
|
|
|
1912
1973
|
// src/rag-eval/calibration.ts
|
|
1913
1974
|
function createRagAnswerQualityHook(options) {
|
|
1975
|
+
assertImmutableRef(options.evaluatorRef, "RAG answer evaluatorRef");
|
|
1976
|
+
const finalScenarioIds = options.scenarios.map((scenario) => scenario.id);
|
|
1977
|
+
if (finalScenarioIds.length < 2 || new Set(finalScenarioIds).size !== finalScenarioIds.length || finalScenarioIds.some((id) => !id.trim())) {
|
|
1978
|
+
throw new Error("RAG answer quality requires at least 2 unique final scenarios");
|
|
1979
|
+
}
|
|
1980
|
+
const datasetRef = `sha256:${contentHash3(options.scenarios)}`;
|
|
1914
1981
|
return async () => {
|
|
1915
1982
|
const summaries = [];
|
|
1916
1983
|
const findings = [];
|
|
@@ -1932,9 +1999,14 @@ function createRagAnswerQualityHook(options) {
|
|
|
1932
1999
|
findings.push(...summary.findings);
|
|
1933
2000
|
}
|
|
1934
2001
|
const metrics = aggregateRagAnswerMetrics(summaries);
|
|
2002
|
+
const cost = typeof options.cost === "function" ? await options.cost() : structuredClone(options.cost);
|
|
1935
2003
|
return {
|
|
1936
2004
|
passed: findings.length === 0,
|
|
1937
2005
|
metrics,
|
|
2006
|
+
finalScenarioIds,
|
|
2007
|
+
datasetRef,
|
|
2008
|
+
evaluatorRef: options.evaluatorRef,
|
|
2009
|
+
cost,
|
|
1938
2010
|
findings,
|
|
1939
2011
|
metadata: { scenarioCount: options.scenarios.length }
|
|
1940
2012
|
};
|
|
@@ -2034,6 +2106,46 @@ function sourceRefs(text) {
|
|
|
2034
2106
|
return refs;
|
|
2035
2107
|
}
|
|
2036
2108
|
|
|
2109
|
+
// src/rag-optimization.ts
|
|
2110
|
+
async function runRagOptimization(options) {
|
|
2111
|
+
const {
|
|
2112
|
+
baseline,
|
|
2113
|
+
method,
|
|
2114
|
+
trainScenarios,
|
|
2115
|
+
selectionScenarios,
|
|
2116
|
+
finalScenarios,
|
|
2117
|
+
run,
|
|
2118
|
+
judges,
|
|
2119
|
+
...runOptions
|
|
2120
|
+
} = options;
|
|
2121
|
+
const result = await runSerializedKnowledgeOptimization({
|
|
2122
|
+
...runOptions,
|
|
2123
|
+
baseline,
|
|
2124
|
+
method,
|
|
2125
|
+
trainScenarios,
|
|
2126
|
+
selectionScenarios,
|
|
2127
|
+
finalScenarios,
|
|
2128
|
+
codec: jsonObjectCandidateCodec(),
|
|
2129
|
+
judges: [...judges ?? [ragAnswerQualityJudge()]],
|
|
2130
|
+
scenarioFingerprint: scenarioContentFingerprint,
|
|
2131
|
+
dispatchCandidate: ({ candidate, candidateSurface, candidateSurfaceHash, scenario, context }) => run({
|
|
2132
|
+
config: candidate,
|
|
2133
|
+
configSurface: candidateSurface,
|
|
2134
|
+
configSurfaceHash: candidateSurfaceHash,
|
|
2135
|
+
scenario,
|
|
2136
|
+
context
|
|
2137
|
+
})
|
|
2138
|
+
});
|
|
2139
|
+
return {
|
|
2140
|
+
...result,
|
|
2141
|
+
baselineConfig: result.baseline.value,
|
|
2142
|
+
winnerConfig: result.winner.value,
|
|
2143
|
+
trainScenarios: [...trainScenarios],
|
|
2144
|
+
selectionScenarios: [...selectionScenarios],
|
|
2145
|
+
finalScenarios: [...finalScenarios]
|
|
2146
|
+
};
|
|
2147
|
+
}
|
|
2148
|
+
|
|
2037
2149
|
// src/research-loop.ts
|
|
2038
2150
|
import {
|
|
2039
2151
|
blockingKnowledgeEval,
|
|
@@ -2347,33 +2459,74 @@ async function applyKnowledgeResearchDecision(options, decision, iteration = 1)
|
|
|
2347
2459
|
};
|
|
2348
2460
|
}
|
|
2349
2461
|
|
|
2462
|
+
// src/retrieval-optimization.ts
|
|
2463
|
+
import { canonicalJson as canonicalJson3 } from "@tangle-network/agent-eval";
|
|
2464
|
+
import {
|
|
2465
|
+
surfaceHash
|
|
2466
|
+
} from "@tangle-network/agent-eval/campaign";
|
|
2467
|
+
async function runRetrievalImprovementLoop(options) {
|
|
2468
|
+
const dispatch = buildRetrievalEvalDispatch({
|
|
2469
|
+
index: options.index,
|
|
2470
|
+
defaultK: options.defaultK,
|
|
2471
|
+
retrieve: options.retrieve
|
|
2472
|
+
});
|
|
2473
|
+
const {
|
|
2474
|
+
baseline,
|
|
2475
|
+
trainScenarios,
|
|
2476
|
+
selectionScenarios,
|
|
2477
|
+
finalScenarios,
|
|
2478
|
+
method,
|
|
2479
|
+
index: _index,
|
|
2480
|
+
defaultK: _defaultK,
|
|
2481
|
+
retrieve: _retrieve,
|
|
2482
|
+
judges,
|
|
2483
|
+
metricWeights,
|
|
2484
|
+
...runOptions
|
|
2485
|
+
} = options;
|
|
2486
|
+
const result = await runSerializedKnowledgeOptimization({
|
|
2487
|
+
...runOptions,
|
|
2488
|
+
baseline,
|
|
2489
|
+
method,
|
|
2490
|
+
trainScenarios,
|
|
2491
|
+
selectionScenarios,
|
|
2492
|
+
finalScenarios,
|
|
2493
|
+
codec: jsonObjectCandidateCodec(),
|
|
2494
|
+
judges: [...judges ?? [retrievalRecallJudge({ weights: metricWeights })]],
|
|
2495
|
+
scenarioFingerprint: retrievalScenarioFingerprint,
|
|
2496
|
+
dispatchCandidate: ({ candidateSurface, scenario, context }) => dispatch(candidateSurface, scenario, context)
|
|
2497
|
+
});
|
|
2498
|
+
return {
|
|
2499
|
+
...result,
|
|
2500
|
+
baselineConfig: result.baseline.value,
|
|
2501
|
+
winnerConfig: result.winner.value,
|
|
2502
|
+
trainScenarios: [...trainScenarios],
|
|
2503
|
+
selectionScenarios: [...selectionScenarios],
|
|
2504
|
+
finalScenarios: [...finalScenarios]
|
|
2505
|
+
};
|
|
2506
|
+
}
|
|
2507
|
+
function retrievalScenarioFingerprint(scenario) {
|
|
2508
|
+
return surfaceHash(
|
|
2509
|
+
canonicalJson3({
|
|
2510
|
+
query: scenario.query,
|
|
2511
|
+
expected: scenario.expected,
|
|
2512
|
+
k: scenario.k ?? null
|
|
2513
|
+
})
|
|
2514
|
+
);
|
|
2515
|
+
}
|
|
2516
|
+
|
|
2350
2517
|
// src/rag-improvement-loop.ts
|
|
2351
2518
|
async function runRagKnowledgeImprovementLoop(options) {
|
|
2352
2519
|
assertConfiguredRequiredPhases(options);
|
|
2520
|
+
assertOptionalCostCeiling(options.answerQualityCostCeiling, "answerQualityCostCeiling");
|
|
2353
2521
|
const now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
2354
2522
|
const phases = [];
|
|
2523
|
+
let optimization;
|
|
2355
2524
|
let retrieval;
|
|
2356
2525
|
let findings = [];
|
|
2357
2526
|
let acquisition;
|
|
2358
2527
|
let knowledgeUpdate;
|
|
2359
2528
|
let answerQuality;
|
|
2360
2529
|
let promotion;
|
|
2361
|
-
if (phaseEnabled(options, "retrieval-tuning")) {
|
|
2362
|
-
if (options.retrieval) {
|
|
2363
|
-
retrieval = await runPhase(
|
|
2364
|
-
phases,
|
|
2365
|
-
now,
|
|
2366
|
-
"retrieval-tuning",
|
|
2367
|
-
async () => {
|
|
2368
|
-
assertNotAborted(options.signal);
|
|
2369
|
-
return runRetrievalImprovementLoop(options.retrieval);
|
|
2370
|
-
},
|
|
2371
|
-
summarizeRetrievalResult
|
|
2372
|
-
);
|
|
2373
|
-
} else {
|
|
2374
|
-
skipPhase(phases, now, "retrieval-tuning", "no retrieval options provided");
|
|
2375
|
-
}
|
|
2376
|
-
}
|
|
2377
2530
|
if (phaseEnabled(options, "gap-diagnosis")) {
|
|
2378
2531
|
if (options.diagnose) {
|
|
2379
2532
|
findings = [
|
|
@@ -2386,8 +2539,9 @@ async function runRagKnowledgeImprovementLoop(options) {
|
|
|
2386
2539
|
return options.diagnose({
|
|
2387
2540
|
goal: options.goal,
|
|
2388
2541
|
phases,
|
|
2542
|
+
optimization: selectRagOptimization(optimization),
|
|
2389
2543
|
signal: options.signal,
|
|
2390
|
-
retrieval
|
|
2544
|
+
retrieval: selectRetrievalOptimization(retrieval)
|
|
2391
2545
|
});
|
|
2392
2546
|
},
|
|
2393
2547
|
(diagnosed) => `${diagnosed.length} finding(s)`
|
|
@@ -2408,8 +2562,9 @@ async function runRagKnowledgeImprovementLoop(options) {
|
|
|
2408
2562
|
return options.acquireKnowledge({
|
|
2409
2563
|
goal: options.goal,
|
|
2410
2564
|
phases,
|
|
2565
|
+
optimization: selectRagOptimization(optimization),
|
|
2411
2566
|
signal: options.signal,
|
|
2412
|
-
retrieval,
|
|
2567
|
+
retrieval: selectRetrievalOptimization(retrieval),
|
|
2413
2568
|
findings
|
|
2414
2569
|
});
|
|
2415
2570
|
},
|
|
@@ -2430,8 +2585,9 @@ async function runRagKnowledgeImprovementLoop(options) {
|
|
|
2430
2585
|
return options.updateKnowledge({
|
|
2431
2586
|
goal: options.goal,
|
|
2432
2587
|
phases,
|
|
2588
|
+
optimization: selectRagOptimization(optimization),
|
|
2433
2589
|
signal: options.signal,
|
|
2434
|
-
retrieval,
|
|
2590
|
+
retrieval: selectRetrievalOptimization(retrieval),
|
|
2435
2591
|
findings,
|
|
2436
2592
|
acquisition
|
|
2437
2593
|
});
|
|
@@ -2453,6 +2609,38 @@ async function runRagKnowledgeImprovementLoop(options) {
|
|
|
2453
2609
|
skipPhase(phases, now, "knowledge-update", "no update hook or research loop provided");
|
|
2454
2610
|
}
|
|
2455
2611
|
}
|
|
2612
|
+
if (phaseEnabled(options, "rag-optimization") && (options.optimization || options.enabledPhases?.includes("rag-optimization") || options.requiredPhases?.includes("rag-optimization"))) {
|
|
2613
|
+
if (options.optimization) {
|
|
2614
|
+
optimization = await runPhase(
|
|
2615
|
+
phases,
|
|
2616
|
+
now,
|
|
2617
|
+
"rag-optimization",
|
|
2618
|
+
async () => {
|
|
2619
|
+
assertNotAborted(options.signal);
|
|
2620
|
+
return runRagOptimization(options.optimization);
|
|
2621
|
+
},
|
|
2622
|
+
summarizeRagOptimization
|
|
2623
|
+
);
|
|
2624
|
+
} else {
|
|
2625
|
+
skipPhase(phases, now, "rag-optimization", "no full RAG optimization options provided");
|
|
2626
|
+
}
|
|
2627
|
+
}
|
|
2628
|
+
if (phaseEnabled(options, "retrieval-tuning")) {
|
|
2629
|
+
if (options.retrieval) {
|
|
2630
|
+
retrieval = await runPhase(
|
|
2631
|
+
phases,
|
|
2632
|
+
now,
|
|
2633
|
+
"retrieval-tuning",
|
|
2634
|
+
async () => {
|
|
2635
|
+
assertNotAborted(options.signal);
|
|
2636
|
+
return runRetrievalImprovementLoop(options.retrieval);
|
|
2637
|
+
},
|
|
2638
|
+
summarizeRetrievalResult
|
|
2639
|
+
);
|
|
2640
|
+
} else {
|
|
2641
|
+
skipPhase(phases, now, "retrieval-tuning", "no retrieval options provided");
|
|
2642
|
+
}
|
|
2643
|
+
}
|
|
2456
2644
|
if (phaseEnabled(options, "answer-quality")) {
|
|
2457
2645
|
if (options.evaluateAnswers) {
|
|
2458
2646
|
answerQuality = await runPhase(
|
|
@@ -2461,15 +2649,18 @@ async function runRagKnowledgeImprovementLoop(options) {
|
|
|
2461
2649
|
"answer-quality",
|
|
2462
2650
|
async () => {
|
|
2463
2651
|
assertNotAborted(options.signal);
|
|
2464
|
-
|
|
2652
|
+
const result = await options.evaluateAnswers({
|
|
2465
2653
|
goal: options.goal,
|
|
2466
2654
|
phases,
|
|
2655
|
+
optimization: selectRagOptimization(optimization),
|
|
2467
2656
|
signal: options.signal,
|
|
2468
|
-
retrieval,
|
|
2657
|
+
retrieval: selectRetrievalOptimization(retrieval),
|
|
2469
2658
|
findings,
|
|
2470
2659
|
acquisition,
|
|
2471
2660
|
knowledgeUpdate
|
|
2472
2661
|
});
|
|
2662
|
+
assertRagAnswerEvidence(result);
|
|
2663
|
+
return result;
|
|
2473
2664
|
},
|
|
2474
2665
|
summarizeAnswerQuality
|
|
2475
2666
|
);
|
|
@@ -2479,18 +2670,30 @@ async function runRagKnowledgeImprovementLoop(options) {
|
|
|
2479
2670
|
}
|
|
2480
2671
|
}
|
|
2481
2672
|
if (phaseEnabled(options, "promotion")) {
|
|
2482
|
-
if (options.
|
|
2673
|
+
if (options.decidePromotion) {
|
|
2483
2674
|
promotion = await runPhase(
|
|
2484
2675
|
phases,
|
|
2485
2676
|
now,
|
|
2486
2677
|
"promotion",
|
|
2487
2678
|
async () => {
|
|
2488
2679
|
assertNotAborted(options.signal);
|
|
2489
|
-
|
|
2680
|
+
const evidenceRejection = rejectUnsafePromotionEvidence({
|
|
2681
|
+
optimization: optimization?.comparison,
|
|
2682
|
+
optimizationCostCeiling: options.optimization?.costCeiling,
|
|
2683
|
+
retrieval: retrieval?.comparison,
|
|
2684
|
+
retrievalCostCeiling: options.retrieval?.costCeiling,
|
|
2685
|
+
answerQuality,
|
|
2686
|
+
answerQualityCostCeiling: options.answerQualityCostCeiling
|
|
2687
|
+
});
|
|
2688
|
+
if (evidenceRejection) return evidenceRejection;
|
|
2689
|
+
return options.decidePromotion({
|
|
2490
2690
|
goal: options.goal,
|
|
2491
2691
|
phases,
|
|
2692
|
+
optimization: selectRagOptimization(optimization),
|
|
2693
|
+
optimizationComparison: optimization?.comparison,
|
|
2492
2694
|
signal: options.signal,
|
|
2493
|
-
retrieval,
|
|
2695
|
+
retrieval: selectRetrievalOptimization(retrieval),
|
|
2696
|
+
retrievalComparison: retrieval?.comparison,
|
|
2494
2697
|
findings,
|
|
2495
2698
|
acquisition,
|
|
2496
2699
|
knowledgeUpdate,
|
|
@@ -2500,12 +2703,13 @@ async function runRagKnowledgeImprovementLoop(options) {
|
|
|
2500
2703
|
(result) => `${result.promoted ? "promoted" : "held"}: ${result.reason}`
|
|
2501
2704
|
);
|
|
2502
2705
|
} else {
|
|
2503
|
-
skipPhase(phases, now, "promotion", "no promotion hook provided");
|
|
2706
|
+
skipPhase(phases, now, "promotion", "no promotion decision hook provided");
|
|
2504
2707
|
}
|
|
2505
2708
|
}
|
|
2506
2709
|
return {
|
|
2507
2710
|
goal: options.goal,
|
|
2508
2711
|
phases,
|
|
2712
|
+
optimization,
|
|
2509
2713
|
retrieval,
|
|
2510
2714
|
findings,
|
|
2511
2715
|
acquisition,
|
|
@@ -2514,6 +2718,58 @@ async function runRagKnowledgeImprovementLoop(options) {
|
|
|
2514
2718
|
promotion
|
|
2515
2719
|
};
|
|
2516
2720
|
}
|
|
2721
|
+
function rejectUnsafePromotionEvidence(evidence) {
|
|
2722
|
+
const reasons = [];
|
|
2723
|
+
if (!evidence.optimization && !evidence.retrieval && !evidence.answerQuality) {
|
|
2724
|
+
reasons.push("promotion requires final RAG, retrieval, or answer-quality evidence");
|
|
2725
|
+
}
|
|
2726
|
+
for (const [label, comparison, costCeiling] of [
|
|
2727
|
+
["RAG", evidence.optimization, evidence.optimizationCostCeiling],
|
|
2728
|
+
["retrieval", evidence.retrieval, evidence.retrievalCostCeiling]
|
|
2729
|
+
]) {
|
|
2730
|
+
if (!comparison) continue;
|
|
2731
|
+
if (!comparison.totalCost.accountingComplete) {
|
|
2732
|
+
reasons.push(`${label} final comparison has incomplete cost accounting`);
|
|
2733
|
+
}
|
|
2734
|
+
const optimizerSource = comparison.best.provenance?.source;
|
|
2735
|
+
if (optimizerSource && optimizerSource.evidence !== "observed") {
|
|
2736
|
+
reasons.push(`${label} optimizer package identity was not observed`);
|
|
2737
|
+
}
|
|
2738
|
+
if (comparison.best.liftCi.low < 0) {
|
|
2739
|
+
reasons.push(`${label} final comparison does not rule out a regression`);
|
|
2740
|
+
}
|
|
2741
|
+
if (costCeiling !== void 0 && exceedsCostCeiling2(comparison.totalCost.totalCostUsd, costCeiling)) {
|
|
2742
|
+
reasons.push(
|
|
2743
|
+
`${label} final comparison cost ${comparison.totalCost.totalCostUsd} exceeds ${costCeiling}`
|
|
2744
|
+
);
|
|
2745
|
+
}
|
|
2746
|
+
}
|
|
2747
|
+
if (evidence.answerQuality) {
|
|
2748
|
+
reasons.push(
|
|
2749
|
+
...ragAnswerEvidenceRejectionReasons(
|
|
2750
|
+
evidence.answerQuality,
|
|
2751
|
+
evidence.answerQualityCostCeiling
|
|
2752
|
+
)
|
|
2753
|
+
);
|
|
2754
|
+
}
|
|
2755
|
+
if (reasons.length === 0) return void 0;
|
|
2756
|
+
return {
|
|
2757
|
+
promoted: false,
|
|
2758
|
+
reason: reasons.join("; ")
|
|
2759
|
+
};
|
|
2760
|
+
}
|
|
2761
|
+
function assertOptionalCostCeiling(value, label) {
|
|
2762
|
+
if (value !== void 0 && (!Number.isFinite(value) || value < 0)) {
|
|
2763
|
+
throw new Error(`${label} must be a non-negative finite number`);
|
|
2764
|
+
}
|
|
2765
|
+
}
|
|
2766
|
+
function exceedsCostCeiling2(totalCostUsd, costCeiling) {
|
|
2767
|
+
const tolerance = Number.EPSILON * Math.max(1, Math.abs(totalCostUsd), Math.abs(costCeiling)) * 8;
|
|
2768
|
+
return totalCostUsd - costCeiling > tolerance;
|
|
2769
|
+
}
|
|
2770
|
+
function summarizeRagOptimization(result) {
|
|
2771
|
+
return `${result.methodName}; winner=${result.winner.surfaceHash}`;
|
|
2772
|
+
}
|
|
2517
2773
|
async function runKnowledgeResearchUpdate(options, acquisition) {
|
|
2518
2774
|
const research = options.knowledgeResearch;
|
|
2519
2775
|
if (!research) {
|
|
@@ -2573,7 +2829,27 @@ function skipPhase(phases, now, phase, summary) {
|
|
|
2573
2829
|
phases.push({ phase, status: "skipped", summary, startedAt: timestamp, finishedAt: timestamp });
|
|
2574
2830
|
}
|
|
2575
2831
|
function summarizeRetrievalResult(result) {
|
|
2576
|
-
return `${result.
|
|
2832
|
+
return `${result.methodName}; winner=${result.winner.surfaceHash}`;
|
|
2833
|
+
}
|
|
2834
|
+
function selectRagOptimization(result) {
|
|
2835
|
+
if (!result) return void 0;
|
|
2836
|
+
return {
|
|
2837
|
+
methodName: result.methodName,
|
|
2838
|
+
baseline: structuredClone(result.baseline),
|
|
2839
|
+
winner: structuredClone(result.winner),
|
|
2840
|
+
baselineConfig: structuredClone(result.baselineConfig),
|
|
2841
|
+
winnerConfig: structuredClone(result.winnerConfig)
|
|
2842
|
+
};
|
|
2843
|
+
}
|
|
2844
|
+
function selectRetrievalOptimization(result) {
|
|
2845
|
+
if (!result) return void 0;
|
|
2846
|
+
return {
|
|
2847
|
+
methodName: result.methodName,
|
|
2848
|
+
baseline: structuredClone(result.baseline),
|
|
2849
|
+
winner: structuredClone(result.winner),
|
|
2850
|
+
baselineConfig: structuredClone(result.baselineConfig),
|
|
2851
|
+
winnerConfig: structuredClone(result.winnerConfig)
|
|
2852
|
+
};
|
|
2577
2853
|
}
|
|
2578
2854
|
function summarizeAcquisitionDecision(decision) {
|
|
2579
2855
|
const sourcePathCount = decision.sourcePaths?.length ?? 0;
|
|
@@ -2603,6 +2879,8 @@ function assertConfiguredRequiredPhases(options) {
|
|
|
2603
2879
|
}
|
|
2604
2880
|
function phaseConfigured(options, phase) {
|
|
2605
2881
|
switch (phase) {
|
|
2882
|
+
case "rag-optimization":
|
|
2883
|
+
return Boolean(options.optimization);
|
|
2606
2884
|
case "retrieval-tuning":
|
|
2607
2885
|
return Boolean(options.retrieval);
|
|
2608
2886
|
case "gap-diagnosis":
|
|
@@ -2614,11 +2892,13 @@ function phaseConfigured(options, phase) {
|
|
|
2614
2892
|
case "answer-quality":
|
|
2615
2893
|
return Boolean(options.evaluateAnswers);
|
|
2616
2894
|
case "promotion":
|
|
2617
|
-
return Boolean(options.
|
|
2895
|
+
return Boolean(options.decidePromotion);
|
|
2618
2896
|
}
|
|
2619
2897
|
}
|
|
2620
2898
|
function requiredPhaseMessage(phase) {
|
|
2621
2899
|
switch (phase) {
|
|
2900
|
+
case "rag-optimization":
|
|
2901
|
+
return "required phase rag-optimization requires optimization options";
|
|
2622
2902
|
case "retrieval-tuning":
|
|
2623
2903
|
return "required phase retrieval-tuning requires retrieval options";
|
|
2624
2904
|
case "gap-diagnosis":
|
|
@@ -2630,7 +2910,7 @@ function requiredPhaseMessage(phase) {
|
|
|
2630
2910
|
case "answer-quality":
|
|
2631
2911
|
return "required phase answer-quality requires an evaluateAnswers hook";
|
|
2632
2912
|
case "promotion":
|
|
2633
|
-
return "required phase promotion requires a
|
|
2913
|
+
return "required phase promotion requires a decidePromotion hook";
|
|
2634
2914
|
}
|
|
2635
2915
|
}
|
|
2636
2916
|
function assertNotAborted(signal) {
|
|
@@ -2641,14 +2921,14 @@ function assertNotAborted(signal) {
|
|
|
2641
2921
|
|
|
2642
2922
|
// src/kb-improvement/transition.ts
|
|
2643
2923
|
import { createHash as createHash2 } from "crypto";
|
|
2644
|
-
import { canonicalJson as
|
|
2924
|
+
import { canonicalJson as canonicalJson5, contentHash as contentHash5 } from "@tangle-network/agent-eval";
|
|
2645
2925
|
|
|
2646
2926
|
// src/kb-improvement/workspace.ts
|
|
2647
2927
|
import { createHash } from "crypto";
|
|
2648
2928
|
import { cp, lstat, mkdir, mkdtemp, rm } from "fs/promises";
|
|
2649
2929
|
import { tmpdir } from "os";
|
|
2650
2930
|
import { dirname, join as join2, relative as relative2, resolve as resolve2 } from "path";
|
|
2651
|
-
import { canonicalJson as
|
|
2931
|
+
import { canonicalJson as canonicalJson4, contentHash as contentHash4 } from "@tangle-network/agent-eval";
|
|
2652
2932
|
function knowledgeImprovementCandidateRef(result) {
|
|
2653
2933
|
if (!result.candidate) throw new Error("knowledge improvement result has no candidate");
|
|
2654
2934
|
return candidateRefFor(result.runId, result.state, result.candidate);
|
|
@@ -2753,10 +3033,10 @@ async function withMeasuredCandidateSnapshot(liveRoot, runDir, state, candidateR
|
|
|
2753
3033
|
throw new Error(`knowledge candidate '${candidateRef.candidateId}' does not exist`);
|
|
2754
3034
|
}
|
|
2755
3035
|
const expectedRef = candidateRefFor(candidateRef.runId, state, candidate);
|
|
2756
|
-
if (
|
|
3036
|
+
if (canonicalJson4(expectedRef) !== canonicalJson4(candidateRef)) {
|
|
2757
3037
|
throw new Error("knowledge candidate approval does not match the measured candidate");
|
|
2758
3038
|
}
|
|
2759
|
-
const evidence = await assertCandidateEvidence(runDir, candidateRef);
|
|
3039
|
+
const evidence = await assertCandidateEvidence(runDir, candidateRef, state.implementationRef);
|
|
2760
3040
|
const relativePath = join2(
|
|
2761
3041
|
"candidates",
|
|
2762
3042
|
candidate.candidateId,
|
|
@@ -2791,7 +3071,7 @@ async function withIsolatedKnowledgeCopy(sourceRoot, expectedHash, target, use)
|
|
|
2791
3071
|
await rm(isolationRoot, { recursive: true, force: true });
|
|
2792
3072
|
}
|
|
2793
3073
|
}
|
|
2794
|
-
async function assertCandidateEvidence(runDir, candidate) {
|
|
3074
|
+
async function assertCandidateEvidence(runDir, candidate, expectedImplementationRef) {
|
|
2795
3075
|
const evidence = KnowledgeImprovementEvidenceSchema.parse(
|
|
2796
3076
|
JSON.parse(
|
|
2797
3077
|
(await readRegularFileWithinRoot(
|
|
@@ -2800,13 +3080,13 @@ async function assertCandidateEvidence(runDir, candidate) {
|
|
|
2800
3080
|
)).bytes.toString("utf8")
|
|
2801
3081
|
)
|
|
2802
3082
|
);
|
|
2803
|
-
const actualHash =
|
|
3083
|
+
const actualHash = contentHash4(evidence);
|
|
2804
3084
|
if (actualHash !== candidate.evidenceHash) {
|
|
2805
3085
|
throw new Error(
|
|
2806
3086
|
`knowledge candidate evidence changed after approval: expected ${candidate.evidenceHash}, got ${actualHash}`
|
|
2807
3087
|
);
|
|
2808
3088
|
}
|
|
2809
|
-
if (evidence.runId !== candidate.runId || evidence.candidateId !== candidate.candidateId || evidence.goalHash !== candidate.goalHash || evidence.baseHash !== candidate.baseHash || evidence.candidateHash !== candidate.candidateHash || evidence.promotionPlanHash !== candidate.promotionPlanHash || evidence.evaluation.passed !== true) {
|
|
3089
|
+
if (evidence.runId !== candidate.runId || evidence.candidateId !== candidate.candidateId || evidence.goalHash !== candidate.goalHash || evidence.implementationRef !== expectedImplementationRef || evidence.baseHash !== candidate.baseHash || evidence.candidateHash !== candidate.candidateHash || evidence.promotionPlanHash !== candidate.promotionPlanHash || evidence.evaluation.passed !== true) {
|
|
2810
3090
|
throw new Error("knowledge candidate evidence does not match the approved candidate");
|
|
2811
3091
|
}
|
|
2812
3092
|
return evidence;
|
|
@@ -3048,12 +3328,12 @@ async function applyKnowledgeCandidateTarget(input, target) {
|
|
|
3048
3328
|
const { candidateRef, runDir, state } = input;
|
|
3049
3329
|
assertStateIdentity(input.root, candidateRef, state);
|
|
3050
3330
|
const candidate = state.candidates.find((entry) => entry.candidateId === candidateRef.candidateId);
|
|
3051
|
-
if (!candidate ||
|
|
3331
|
+
if (!candidate || canonicalJson5(candidateIdentityFor(candidateRef.runId, state, candidate)) !== canonicalJson5(candidateRef)) {
|
|
3052
3332
|
throw new Error("knowledge candidate approval does not match the measured candidate");
|
|
3053
3333
|
}
|
|
3054
3334
|
const action = target === "candidate" ? "promotion" : "restore";
|
|
3055
3335
|
const desiredHash = target === "candidate" ? candidateRef.candidateHash : candidateRef.baseHash;
|
|
3056
|
-
const purpose = knowledgeCandidateTransitionPurpose(candidateRef, target);
|
|
3336
|
+
const purpose = knowledgeCandidateTransitionPurpose(candidateRef, state.implementationRef, target);
|
|
3057
3337
|
const recoveryOwner = input.activation ? `knowledge-improvement-activation:${input.activation.activation.digest}` : "knowledge-improvement-candidate-transition";
|
|
3058
3338
|
return withKnowledgeMutation(
|
|
3059
3339
|
input.root,
|
|
@@ -3065,6 +3345,9 @@ async function applyKnowledgeCandidateTarget(input, target) {
|
|
|
3065
3345
|
assertOwned();
|
|
3066
3346
|
const transactionRoot = mutationLock.transactionRoot;
|
|
3067
3347
|
const recovery = mutationLock.recovery?.purpose === purpose ? mutationLock.recovery : void 0;
|
|
3348
|
+
if (!recovery) {
|
|
3349
|
+
await assertCandidateEvidence(runDir, candidateRef, state.implementationRef);
|
|
3350
|
+
}
|
|
3068
3351
|
const existingActivation = input.activation ? await loadKnowledgeActivationRecord(
|
|
3069
3352
|
runDir,
|
|
3070
3353
|
candidateRef,
|
|
@@ -3366,9 +3649,9 @@ function candidateTransitionResult(input, candidate, promoted, blocked, mutation
|
|
|
3366
3649
|
blocked
|
|
3367
3650
|
};
|
|
3368
3651
|
}
|
|
3369
|
-
function knowledgeCandidateTransitionPurpose(candidate, target) {
|
|
3652
|
+
function knowledgeCandidateTransitionPurpose(candidate, implementationRef, target) {
|
|
3370
3653
|
const action = target === "candidate" ? "promotion" : "restore";
|
|
3371
|
-
return `knowledge-${action}:${
|
|
3654
|
+
return `knowledge-${action}:${contentHash5({ candidate, implementationRef })}`;
|
|
3372
3655
|
}
|
|
3373
3656
|
async function knowledgeFilePlanEntries(sourceRoot, targetRoot) {
|
|
3374
3657
|
const [before, after] = await Promise.all([
|
|
@@ -3453,6 +3736,24 @@ async function hasCandidateTransitionEvent(runDir, candidateRef, target) {
|
|
|
3453
3736
|
|
|
3454
3737
|
// src/kb-improvement/evaluation.ts
|
|
3455
3738
|
function assertKnowledgeImprovementOptions(options) {
|
|
3739
|
+
assertImmutableRef(options.implementationRef, "knowledge improvement implementationRef");
|
|
3740
|
+
if (options.answerQualityCostCeiling !== void 0 && (!Number.isFinite(options.answerQualityCostCeiling) || options.answerQualityCostCeiling < 0)) {
|
|
3741
|
+
throw new Error(
|
|
3742
|
+
"knowledge improvement answerQualityCostCeiling must be a non-negative finite number"
|
|
3743
|
+
);
|
|
3744
|
+
}
|
|
3745
|
+
if (options.ragOptimization) {
|
|
3746
|
+
assertImmutableRef(
|
|
3747
|
+
options.ragOptimization.executionRef,
|
|
3748
|
+
"knowledge improvement RAG executionRef"
|
|
3749
|
+
);
|
|
3750
|
+
}
|
|
3751
|
+
if (options.retrieval) {
|
|
3752
|
+
assertImmutableRef(
|
|
3753
|
+
options.retrieval.executionRef,
|
|
3754
|
+
"knowledge improvement retrieval executionRef"
|
|
3755
|
+
);
|
|
3756
|
+
}
|
|
3456
3757
|
if (options.step && options.knowledgeResearch?.step) {
|
|
3457
3758
|
throw new Error("improveKnowledgeBase accepts either step or knowledgeResearch.step, not both");
|
|
3458
3759
|
}
|
|
@@ -3472,9 +3773,15 @@ async function measureCandidate(runId, runDir, state, candidate, options, now) {
|
|
|
3472
3773
|
if (candidate.status === "candidate-ready" && candidate.candidateHash === currentCandidateHash && candidate.evidenceHash !== void 0 && candidate.promotionPlanHash !== void 0) {
|
|
3473
3774
|
const evidence = await assertCandidateEvidence(
|
|
3474
3775
|
runDir,
|
|
3475
|
-
candidateRefFor(runId, state, candidate)
|
|
3776
|
+
candidateRefFor(runId, state, candidate),
|
|
3777
|
+
state.implementationRef
|
|
3476
3778
|
);
|
|
3477
|
-
return {
|
|
3779
|
+
return {
|
|
3780
|
+
candidate,
|
|
3781
|
+
evaluation: evidence.evaluation,
|
|
3782
|
+
...evidence.lifecycle === null ? {} : { lifecycle: evidence.lifecycle },
|
|
3783
|
+
finalEvaluated: shouldRunEvaluationStage(options)
|
|
3784
|
+
};
|
|
3478
3785
|
}
|
|
3479
3786
|
clearCandidateMeasurement(candidate);
|
|
3480
3787
|
const lifecycles = [];
|
|
@@ -3489,15 +3796,44 @@ async function measureCandidate(runId, runDir, state, candidate, options, now) {
|
|
|
3489
3796
|
if (updateLifecycle) lifecycles.push(updateLifecycle);
|
|
3490
3797
|
}
|
|
3491
3798
|
return withFrozenCandidateWorkspace(runDir, candidate, candidateRoot, async (snapshot) => {
|
|
3799
|
+
let lifecycle = mergeLifecycleResults(options.goal, lifecycles);
|
|
3800
|
+
const development = await evaluateCandidate(
|
|
3801
|
+
runDir,
|
|
3802
|
+
state,
|
|
3803
|
+
candidate,
|
|
3804
|
+
snapshot,
|
|
3805
|
+
lifecycle,
|
|
3806
|
+
options,
|
|
3807
|
+
now,
|
|
3808
|
+
false
|
|
3809
|
+
);
|
|
3810
|
+
if (!development.evaluation.passed || !shouldRunEvaluationStage(options)) {
|
|
3811
|
+
return {
|
|
3812
|
+
...development,
|
|
3813
|
+
...lifecycle ? { lifecycle } : {},
|
|
3814
|
+
finalEvaluated: false
|
|
3815
|
+
};
|
|
3816
|
+
}
|
|
3817
|
+
candidate.finalEvaluationStartedAt = now().toISOString();
|
|
3818
|
+
candidate.updatedAt = candidate.finalEvaluationStartedAt;
|
|
3819
|
+
state.updatedAt = candidate.finalEvaluationStartedAt;
|
|
3820
|
+
await saveState(runDir, state, options.onState);
|
|
3821
|
+
await appendLedger(runDir, {
|
|
3822
|
+
type: "candidate.final-evaluation-started",
|
|
3823
|
+
runId: state.runId,
|
|
3824
|
+
candidateId: candidate.candidateId
|
|
3825
|
+
});
|
|
3492
3826
|
const evaluationLifecycle = await runCandidateEvaluationLifecycle(
|
|
3827
|
+
runId,
|
|
3493
3828
|
runDir,
|
|
3494
3829
|
candidate,
|
|
3495
3830
|
snapshot.root,
|
|
3831
|
+
snapshot.hash,
|
|
3496
3832
|
options,
|
|
3497
3833
|
now
|
|
3498
3834
|
);
|
|
3499
3835
|
if (evaluationLifecycle) lifecycles.push(evaluationLifecycle);
|
|
3500
|
-
|
|
3836
|
+
lifecycle = mergeLifecycleResults(options.goal, lifecycles);
|
|
3501
3837
|
const measured = await evaluateCandidate(
|
|
3502
3838
|
runDir,
|
|
3503
3839
|
state,
|
|
@@ -3505,9 +3841,14 @@ async function measureCandidate(runId, runDir, state, candidate, options, now) {
|
|
|
3505
3841
|
snapshot,
|
|
3506
3842
|
lifecycle,
|
|
3507
3843
|
options,
|
|
3508
|
-
now
|
|
3844
|
+
now,
|
|
3845
|
+
true
|
|
3509
3846
|
);
|
|
3510
|
-
return {
|
|
3847
|
+
return {
|
|
3848
|
+
...measured,
|
|
3849
|
+
...lifecycle ? { lifecycle } : {},
|
|
3850
|
+
finalEvaluated: true
|
|
3851
|
+
};
|
|
3511
3852
|
});
|
|
3512
3853
|
});
|
|
3513
3854
|
}
|
|
@@ -3525,25 +3866,53 @@ async function runCandidateUpdateLifecycle(runId, candidate, candidateRoot, opti
|
|
|
3525
3866
|
});
|
|
3526
3867
|
return lifecycle;
|
|
3527
3868
|
}
|
|
3528
|
-
async function runCandidateEvaluationLifecycle(runDir, candidate, candidateRoot, options, now) {
|
|
3869
|
+
async function runCandidateEvaluationLifecycle(runId, runDir, candidate, candidateRoot, candidateHash, options, now) {
|
|
3529
3870
|
if (!shouldRunEvaluationStage(options)) return void 0;
|
|
3530
3871
|
const candidateIndex = await buildKnowledgeIndex(candidateRoot);
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3872
|
+
return withBaselineSnapshot(
|
|
3873
|
+
runDir,
|
|
3874
|
+
candidate.baseHash,
|
|
3875
|
+
(baselineRoot) => runRagKnowledgeImprovementLoop({
|
|
3876
|
+
goal: options.goal,
|
|
3877
|
+
optimization: options.ragOptimization ? {
|
|
3878
|
+
...options.ragOptimization,
|
|
3879
|
+
executionRef: candidateExecutionRef(
|
|
3880
|
+
options.ragOptimization.executionRef,
|
|
3881
|
+
candidateHash
|
|
3882
|
+
),
|
|
3883
|
+
runDir: options.ragOptimization.runDir ?? join3(runDir, "rag-optimization", candidate.candidateId),
|
|
3884
|
+
run: (input) => options.ragOptimization.run({
|
|
3885
|
+
...input,
|
|
3886
|
+
runId,
|
|
3887
|
+
iteration: candidate.iteration,
|
|
3888
|
+
candidateId: candidate.candidateId,
|
|
3889
|
+
root: candidateRoot,
|
|
3890
|
+
baselineRoot,
|
|
3891
|
+
candidateRoot,
|
|
3892
|
+
candidateIndex,
|
|
3893
|
+
baseHash: candidate.baseHash
|
|
3894
|
+
})
|
|
3895
|
+
} : void 0,
|
|
3896
|
+
retrieval: options.retrieval ? {
|
|
3897
|
+
...options.retrieval,
|
|
3898
|
+
executionRef: candidateExecutionRef(options.retrieval.executionRef, candidateHash),
|
|
3899
|
+
index: candidateIndex,
|
|
3900
|
+
runDir: options.retrieval.runDir ?? join3(runDir, "retrieval", candidate.candidateId)
|
|
3901
|
+
} : void 0,
|
|
3902
|
+
diagnose: options.diagnose,
|
|
3903
|
+
evaluateAnswers: options.evaluateAnswers,
|
|
3904
|
+
answerQualityCostCeiling: options.answerQualityCostCeiling,
|
|
3905
|
+
decidePromotion: options.decidePromotion,
|
|
3906
|
+
enabledPhases: selectedStagePhases(options, EVALUATION_PHASES),
|
|
3907
|
+
requiredPhases: selectedStageRequiredPhases(options, EVALUATION_PHASES),
|
|
3908
|
+
signal: options.signal,
|
|
3909
|
+
now
|
|
3910
|
+
})
|
|
3911
|
+
);
|
|
3912
|
+
}
|
|
3913
|
+
function candidateExecutionRef(executionRef, candidateHash) {
|
|
3914
|
+
return `sha256:${sha256(`${executionRef}
|
|
3915
|
+
${candidateHash}`)}`;
|
|
3547
3916
|
}
|
|
3548
3917
|
function candidateKnowledgeResearchOptions(candidateRoot, options) {
|
|
3549
3918
|
if (!options.step && !options.knowledgeResearch) return void 0;
|
|
@@ -3584,7 +3953,7 @@ function shouldRunEvaluationStage(options) {
|
|
|
3584
3953
|
const phases = selectedStagePhases(options, EVALUATION_PHASES);
|
|
3585
3954
|
if (phases.length === 0) return false;
|
|
3586
3955
|
return Boolean(
|
|
3587
|
-
options.retrieval || options.diagnose || options.evaluateAnswers || options.decidePromotion || selectedStageRequiredPhases(options, EVALUATION_PHASES).length > 0
|
|
3956
|
+
options.ragOptimization || options.retrieval || options.diagnose || options.evaluateAnswers || options.decidePromotion || options.evaluate || selectedStageRequiredPhases(options, EVALUATION_PHASES).length > 0
|
|
3588
3957
|
);
|
|
3589
3958
|
}
|
|
3590
3959
|
function selectedStagePhases(options, stagePhases) {
|
|
@@ -3599,6 +3968,7 @@ function mergeLifecycleResults(goal, lifecycles) {
|
|
|
3599
3968
|
return {
|
|
3600
3969
|
goal,
|
|
3601
3970
|
phases: lifecycles.flatMap((lifecycle) => lifecycle.phases),
|
|
3971
|
+
optimization: lastDefined(lifecycles.map((lifecycle) => lifecycle.optimization)),
|
|
3602
3972
|
retrieval: lastDefined(lifecycles.map((lifecycle) => lifecycle.retrieval)),
|
|
3603
3973
|
findings: lifecycles.flatMap((lifecycle) => lifecycle.findings),
|
|
3604
3974
|
acquisition: lastDefined(lifecycles.map((lifecycle) => lifecycle.acquisition)),
|
|
@@ -3613,7 +3983,7 @@ function lastDefined(values) {
|
|
|
3613
3983
|
}
|
|
3614
3984
|
return void 0;
|
|
3615
3985
|
}
|
|
3616
|
-
async function evaluateCandidate(runDir, state, candidate, snapshot, lifecycle, options, now) {
|
|
3986
|
+
async function evaluateCandidate(runDir, state, candidate, snapshot, lifecycle, options, now, useConfiguredEvaluator) {
|
|
3617
3987
|
return withBaselineSnapshot(runDir, state.baseHash, async (baselineRoot) => {
|
|
3618
3988
|
const [baselineIndex, candidateIndex] = await Promise.all([
|
|
3619
3989
|
buildKnowledgeIndex(baselineRoot),
|
|
@@ -3626,7 +3996,8 @@ async function evaluateCandidate(runDir, state, candidate, snapshot, lifecycle,
|
|
|
3626
3996
|
...options.kbQuality
|
|
3627
3997
|
});
|
|
3628
3998
|
const candidateHash = snapshot.hash;
|
|
3629
|
-
const
|
|
3999
|
+
const evaluator = useConfiguredEvaluator ? options.evaluate : options.evaluateDevelopment;
|
|
4000
|
+
const configuredMetric = evaluator ? evaluator({
|
|
3630
4001
|
runId: state.runId,
|
|
3631
4002
|
iteration: candidate.iteration,
|
|
3632
4003
|
root: options.root,
|
|
@@ -3641,14 +4012,19 @@ async function evaluateCandidate(runDir, state, candidate, snapshot, lifecycle,
|
|
|
3641
4012
|
kbQuality,
|
|
3642
4013
|
lifecycle,
|
|
3643
4014
|
signal: options.signal
|
|
3644
|
-
})
|
|
4015
|
+
}) : void 0;
|
|
4016
|
+
const metric = configuredMetric ?? defaultKnowledgeImprovementMetric(
|
|
3645
4017
|
validation,
|
|
3646
4018
|
readiness,
|
|
3647
4019
|
options.readinessSpecs,
|
|
3648
4020
|
kbQuality,
|
|
3649
4021
|
lifecycle
|
|
3650
4022
|
);
|
|
3651
|
-
const evaluation = applyLifecycleFailures(
|
|
4023
|
+
const evaluation = applyLifecycleFailures(
|
|
4024
|
+
normalizeMetric(await metric),
|
|
4025
|
+
lifecycle,
|
|
4026
|
+
options.answerQualityCostCeiling
|
|
4027
|
+
);
|
|
3652
4028
|
const measuredHash = await hashKnowledgeBase(snapshot.root);
|
|
3653
4029
|
if (measuredHash !== candidateHash) {
|
|
3654
4030
|
throw new Error(
|
|
@@ -3667,6 +4043,7 @@ async function evaluateCandidate(runDir, state, candidate, snapshot, lifecycle,
|
|
|
3667
4043
|
candidateId: candidate.candidateId,
|
|
3668
4044
|
iteration: candidate.iteration,
|
|
3669
4045
|
goalHash: sha256(state.goal),
|
|
4046
|
+
implementationRef: state.implementationRef,
|
|
3670
4047
|
baseHash: candidate.baseHash,
|
|
3671
4048
|
candidateHash,
|
|
3672
4049
|
promotionPlanHash: candidate.promotionPlanHash,
|
|
@@ -3678,7 +4055,7 @@ async function evaluateCandidate(runDir, state, candidate, snapshot, lifecycle,
|
|
|
3678
4055
|
})
|
|
3679
4056
|
)
|
|
3680
4057
|
);
|
|
3681
|
-
candidate.evidenceHash =
|
|
4058
|
+
candidate.evidenceHash = contentHash6(evidence);
|
|
3682
4059
|
candidate.updatedAt = now().toISOString();
|
|
3683
4060
|
await writeJsonDurableWithinRoot(
|
|
3684
4061
|
runDir,
|
|
@@ -3725,13 +4102,14 @@ function defaultKnowledgeImprovementMetric(validation, readiness, readinessSpecs
|
|
|
3725
4102
|
}
|
|
3726
4103
|
};
|
|
3727
4104
|
}
|
|
3728
|
-
function applyLifecycleFailures(metric, lifecycle) {
|
|
4105
|
+
function applyLifecycleFailures(metric, lifecycle, answerQualityCostCeiling) {
|
|
4106
|
+
const answerQualityFailures = lifecycle?.answerQuality ? ragAnswerEvidenceRejectionReasons(lifecycle.answerQuality, answerQualityCostCeiling) : [];
|
|
3729
4107
|
const reasons = [
|
|
3730
4108
|
metric.notes,
|
|
3731
|
-
|
|
4109
|
+
...answerQualityFailures,
|
|
3732
4110
|
lifecycle?.promotion && !lifecycle.promotion.promoted ? `promotion decision held: ${lifecycle.promotion.reason}` : void 0
|
|
3733
4111
|
].filter((reason) => Boolean(reason));
|
|
3734
|
-
const forcedFailure =
|
|
4112
|
+
const forcedFailure = answerQualityFailures.length > 0 || Boolean(lifecycle?.promotion && !lifecycle.promotion.promoted);
|
|
3735
4113
|
return {
|
|
3736
4114
|
...metric,
|
|
3737
4115
|
passed: metric.passed && !forcedFailure,
|
|
@@ -3780,6 +4158,7 @@ async function improveKnowledgeBaseInRun(options, runId, runDir, now) {
|
|
|
3780
4158
|
runId,
|
|
3781
4159
|
root: options.root,
|
|
3782
4160
|
goal: options.goal,
|
|
4161
|
+
implementationRef: options.implementationRef,
|
|
3783
4162
|
status: "running",
|
|
3784
4163
|
baseHash,
|
|
3785
4164
|
createdAt: now().toISOString(),
|
|
@@ -3793,6 +4172,9 @@ async function improveKnowledgeBaseInRun(options, runId, runDir, now) {
|
|
|
3793
4172
|
if (state.goal !== options.goal) {
|
|
3794
4173
|
throw new Error("knowledge improvement state does not match the requested goal");
|
|
3795
4174
|
}
|
|
4175
|
+
if (state.implementationRef !== options.implementationRef) {
|
|
4176
|
+
throw new Error("knowledge improvement state does not match the requested implementationRef");
|
|
4177
|
+
}
|
|
3796
4178
|
const promotedCandidateId = state.promotedCandidateId;
|
|
3797
4179
|
const promotedCandidate = state.status === "promoted" ? state.candidates.find((candidate2) => candidate2.candidateId === promotedCandidateId) : void 0;
|
|
3798
4180
|
if (state.status === "promoted" && !promotedCandidate) {
|
|
@@ -3810,7 +4192,8 @@ async function improveKnowledgeBaseInRun(options, runId, runDir, now) {
|
|
|
3810
4192
|
}
|
|
3811
4193
|
const evidence2 = await assertCandidateEvidence(
|
|
3812
4194
|
runDir,
|
|
3813
|
-
candidateRefFor(runId, promotedState, promoted)
|
|
4195
|
+
candidateRefFor(runId, promotedState, promoted),
|
|
4196
|
+
promotedState.implementationRef
|
|
3814
4197
|
);
|
|
3815
4198
|
return {
|
|
3816
4199
|
runId,
|
|
@@ -3833,6 +4216,22 @@ async function improveKnowledgeBaseInRun(options, runId, runDir, now) {
|
|
|
3833
4216
|
let lastRejectedEvaluation;
|
|
3834
4217
|
let lifecycle;
|
|
3835
4218
|
while (candidate || state.candidates.length < maxCandidates) {
|
|
4219
|
+
if (candidate?.status === "running" && candidate.finalEvaluationStartedAt) {
|
|
4220
|
+
state = await blockRun(
|
|
4221
|
+
runDir,
|
|
4222
|
+
state,
|
|
4223
|
+
`candidate '${candidate.candidateId}' was interrupted after final evaluation started; refusing to reuse final cases`,
|
|
4224
|
+
options.onState,
|
|
4225
|
+
now
|
|
4226
|
+
);
|
|
4227
|
+
return {
|
|
4228
|
+
runId,
|
|
4229
|
+
state,
|
|
4230
|
+
candidate,
|
|
4231
|
+
promoted: false,
|
|
4232
|
+
blocked: true
|
|
4233
|
+
};
|
|
4234
|
+
}
|
|
3836
4235
|
if (!candidate) {
|
|
3837
4236
|
const currentHash = await hashKnowledgeBase(options.root);
|
|
3838
4237
|
if (currentHash !== state.baseHash) {
|
|
@@ -3891,6 +4290,7 @@ async function improveKnowledgeBaseInRun(options, runId, runDir, now) {
|
|
|
3891
4290
|
lastRejectedCandidate = candidate;
|
|
3892
4291
|
lastRejectedEvaluation = evaluation;
|
|
3893
4292
|
candidate = void 0;
|
|
4293
|
+
if (measured.finalEvaluated) break;
|
|
3894
4294
|
}
|
|
3895
4295
|
if (!candidate) {
|
|
3896
4296
|
state.status = "rejected";
|
|
@@ -3906,7 +4306,11 @@ async function improveKnowledgeBaseInRun(options, runId, runDir, now) {
|
|
|
3906
4306
|
blocked: false
|
|
3907
4307
|
};
|
|
3908
4308
|
}
|
|
3909
|
-
const evidence = await assertCandidateEvidence(
|
|
4309
|
+
const evidence = await assertCandidateEvidence(
|
|
4310
|
+
runDir,
|
|
4311
|
+
candidateRefFor(runId, state, candidate),
|
|
4312
|
+
state.implementationRef
|
|
4313
|
+
);
|
|
3910
4314
|
return {
|
|
3911
4315
|
runId,
|
|
3912
4316
|
state,
|
|
@@ -3921,6 +4325,93 @@ async function improveKnowledgeBaseInRun(options, runId, runDir, now) {
|
|
|
3921
4325
|
}
|
|
3922
4326
|
}
|
|
3923
4327
|
|
|
4328
|
+
// src/kb-improvement/optimization.ts
|
|
4329
|
+
async function optimizeKnowledgeBasePolicy(options) {
|
|
4330
|
+
const {
|
|
4331
|
+
root,
|
|
4332
|
+
goal,
|
|
4333
|
+
baselinePolicy,
|
|
4334
|
+
method,
|
|
4335
|
+
trainScenarios,
|
|
4336
|
+
selectionScenarios,
|
|
4337
|
+
finalScenarios,
|
|
4338
|
+
policyApplicationRef,
|
|
4339
|
+
candidateRunLabel,
|
|
4340
|
+
candidate,
|
|
4341
|
+
applyPolicy,
|
|
4342
|
+
...optimizationOptions
|
|
4343
|
+
} = options;
|
|
4344
|
+
if (typeof root !== "string" || !root.trim()) {
|
|
4345
|
+
throw new Error("optimizeKnowledgeBasePolicy root must be non-empty");
|
|
4346
|
+
}
|
|
4347
|
+
if (typeof goal !== "string" || !goal.trim()) {
|
|
4348
|
+
throw new Error("optimizeKnowledgeBasePolicy goal must be non-empty");
|
|
4349
|
+
}
|
|
4350
|
+
assertImmutableRef(policyApplicationRef, "optimizeKnowledgeBasePolicy policyApplicationRef");
|
|
4351
|
+
if (candidateRunLabel !== void 0 && (typeof candidateRunLabel !== "string" || !candidateRunLabel.trim())) {
|
|
4352
|
+
throw new Error("optimizeKnowledgeBasePolicy candidateRunLabel must be non-empty");
|
|
4353
|
+
}
|
|
4354
|
+
const baseHash = await hashKnowledgeBase(root);
|
|
4355
|
+
const optimization = await runSerializedKnowledgeOptimization({
|
|
4356
|
+
...optimizationOptions,
|
|
4357
|
+
executionRef: policyApplicationRef,
|
|
4358
|
+
baseline: baselinePolicy,
|
|
4359
|
+
method,
|
|
4360
|
+
trainScenarios,
|
|
4361
|
+
selectionScenarios,
|
|
4362
|
+
finalScenarios
|
|
4363
|
+
});
|
|
4364
|
+
const winner = optimization.winner;
|
|
4365
|
+
const currentBaseHash = await hashKnowledgeBase(root);
|
|
4366
|
+
if (currentBaseHash !== baseHash) {
|
|
4367
|
+
throw new Error(
|
|
4368
|
+
`knowledge base changed during policy optimization: expected ${baseHash}, got ${currentBaseHash}`
|
|
4369
|
+
);
|
|
4370
|
+
}
|
|
4371
|
+
const runId = stableId(
|
|
4372
|
+
"kbpolicy",
|
|
4373
|
+
`${candidateRunLabel ?? "default"}:${goal}:${optimization.methodName}:${winner.surfaceHash}:${policyApplicationRef}:${baseHash}`
|
|
4374
|
+
);
|
|
4375
|
+
const improvement = await improveKnowledgeBase({
|
|
4376
|
+
...candidate ?? {},
|
|
4377
|
+
root,
|
|
4378
|
+
goal,
|
|
4379
|
+
implementationRef: `sha256:${sha256(
|
|
4380
|
+
`${policyApplicationRef}
|
|
4381
|
+
${winner.surfaceHash}
|
|
4382
|
+
${optimization.methodName}`
|
|
4383
|
+
)}`,
|
|
4384
|
+
runId,
|
|
4385
|
+
maxCandidates: 1,
|
|
4386
|
+
updateKnowledge: async (input) => {
|
|
4387
|
+
if (input.baseHash !== baseHash) {
|
|
4388
|
+
throw new Error(
|
|
4389
|
+
`knowledge base changed before policy materialization: expected ${baseHash}, got ${input.baseHash}`
|
|
4390
|
+
);
|
|
4391
|
+
}
|
|
4392
|
+
const result = await applyPolicy({
|
|
4393
|
+
...input,
|
|
4394
|
+
policy: structuredClone(winner.value),
|
|
4395
|
+
policySurface: winner.surface,
|
|
4396
|
+
policySurfaceHash: winner.surfaceHash,
|
|
4397
|
+
optimizationMethod: optimization.methodName
|
|
4398
|
+
});
|
|
4399
|
+
return {
|
|
4400
|
+
...result,
|
|
4401
|
+
metadata: {
|
|
4402
|
+
...result.metadata ?? {},
|
|
4403
|
+
optimization: {
|
|
4404
|
+
method: optimization.methodName,
|
|
4405
|
+
policySurfaceHash: winner.surfaceHash,
|
|
4406
|
+
policyApplicationRef
|
|
4407
|
+
}
|
|
4408
|
+
}
|
|
4409
|
+
};
|
|
4410
|
+
}
|
|
4411
|
+
});
|
|
4412
|
+
return { optimization, improvement };
|
|
4413
|
+
}
|
|
4414
|
+
|
|
3924
4415
|
// src/agent-candidate.ts
|
|
3925
4416
|
function toAgentCandidateKnowledgeRef(candidate) {
|
|
3926
4417
|
const parsed = KnowledgeImprovementCandidateRefSchema.parse(candidate);
|
|
@@ -4302,6 +4793,60 @@ function positiveInteger(value, name) {
|
|
|
4302
4793
|
return value;
|
|
4303
4794
|
}
|
|
4304
4795
|
|
|
4796
|
+
// src/filesystem-search-provider.ts
|
|
4797
|
+
var FileSystemSearchProvider = class {
|
|
4798
|
+
root;
|
|
4799
|
+
index;
|
|
4800
|
+
defaultLimit;
|
|
4801
|
+
refreshMode;
|
|
4802
|
+
constructor(options) {
|
|
4803
|
+
this.root = options.root;
|
|
4804
|
+
this.index = options.index;
|
|
4805
|
+
this.defaultLimit = options.defaultLimit ?? 10;
|
|
4806
|
+
this.refreshMode = options.refresh ?? "manual";
|
|
4807
|
+
}
|
|
4808
|
+
async getIndex(options = {}) {
|
|
4809
|
+
if (this.refreshMode === "always" || options.refresh || !this.index) {
|
|
4810
|
+
this.index = await buildKnowledgeIndex(this.root);
|
|
4811
|
+
}
|
|
4812
|
+
return this.index;
|
|
4813
|
+
}
|
|
4814
|
+
async search(query, options = {}) {
|
|
4815
|
+
const index = await this.getIndex(options);
|
|
4816
|
+
return searchKnowledge(index, query, options.limit ?? this.defaultLimit);
|
|
4817
|
+
}
|
|
4818
|
+
async retrieve(query, options = {}) {
|
|
4819
|
+
const hits = await this.search(query, options);
|
|
4820
|
+
return hits.map(hitFromSearchResult);
|
|
4821
|
+
}
|
|
4822
|
+
asRetrievalEvalRetriever() {
|
|
4823
|
+
return async ({ config, scenario, k }) => ({
|
|
4824
|
+
hits: await this.retrieve(scenario.query, {
|
|
4825
|
+
limit: k,
|
|
4826
|
+
refresh: config.refresh === true
|
|
4827
|
+
})
|
|
4828
|
+
});
|
|
4829
|
+
}
|
|
4830
|
+
invalidate() {
|
|
4831
|
+
this.index = void 0;
|
|
4832
|
+
}
|
|
4833
|
+
};
|
|
4834
|
+
function createFileSystemSearchProvider(options) {
|
|
4835
|
+
return new FileSystemSearchProvider(options);
|
|
4836
|
+
}
|
|
4837
|
+
function hitFromSearchResult(result) {
|
|
4838
|
+
return {
|
|
4839
|
+
pageId: result.page.id,
|
|
4840
|
+
path: result.page.path,
|
|
4841
|
+
title: result.page.title,
|
|
4842
|
+
rank: result.rank,
|
|
4843
|
+
score: result.score,
|
|
4844
|
+
normalizedScore: result.normalizedScore,
|
|
4845
|
+
sourceIds: result.page.sourceIds,
|
|
4846
|
+
snippet: result.snippet
|
|
4847
|
+
};
|
|
4848
|
+
}
|
|
4849
|
+
|
|
4305
4850
|
// src/freshness.ts
|
|
4306
4851
|
import { readFile } from "fs/promises";
|
|
4307
4852
|
import { join as join4 } from "path";
|
|
@@ -6275,6 +6820,7 @@ export {
|
|
|
6275
6820
|
AgentMemoryWriteInputSchema,
|
|
6276
6821
|
DEFAULT_MEMORY_CLEANUP_TIMEOUT_MS,
|
|
6277
6822
|
FileSystemKbStore,
|
|
6823
|
+
FileSystemSearchProvider,
|
|
6278
6824
|
INDUSTRY_MEMORY_BENCHMARKS,
|
|
6279
6825
|
INDUSTRY_RAG_BENCHMARKS,
|
|
6280
6826
|
IRS_DIMENSION_HINTS,
|
|
@@ -6318,7 +6864,6 @@ export {
|
|
|
6318
6864
|
buildKnowledgeIndex,
|
|
6319
6865
|
buildRetrievalBenchmarkCasesFromQrels,
|
|
6320
6866
|
buildRetrievalEvalDispatch,
|
|
6321
|
-
buildRetrievalParameterCandidates,
|
|
6322
6867
|
calibrateRagAnswerJudge,
|
|
6323
6868
|
canonicalizeUrl,
|
|
6324
6869
|
chunkMarkdown,
|
|
@@ -6333,6 +6878,7 @@ export {
|
|
|
6333
6878
|
createCornellLiiSource,
|
|
6334
6879
|
createD1FreshnessStoreStub,
|
|
6335
6880
|
createFileSystemFreshnessStore,
|
|
6881
|
+
createFileSystemSearchProvider,
|
|
6336
6882
|
createGraphitiMemoryAdapter,
|
|
6337
6883
|
createInMemoryBenchmarkAdapter,
|
|
6338
6884
|
createIrsPublicationsSource,
|
|
@@ -6378,6 +6924,8 @@ export {
|
|
|
6378
6924
|
isKnowledgeMemoryBenchmarkCase,
|
|
6379
6925
|
isSafeKnowledgePath,
|
|
6380
6926
|
isScaffoldPath,
|
|
6927
|
+
jsonCandidateCodec,
|
|
6928
|
+
jsonObjectCandidateCodec,
|
|
6381
6929
|
kbIndexToText,
|
|
6382
6930
|
knowledgeBenchmarkJudge,
|
|
6383
6931
|
knowledgeImprovementCandidateRef,
|
|
@@ -6402,10 +6950,12 @@ export {
|
|
|
6402
6950
|
memoryWriteResultToSourceRecord,
|
|
6403
6951
|
normalizeExternalRagScores,
|
|
6404
6952
|
normalizeLinkTarget,
|
|
6953
|
+
optimizeKnowledgeBasePolicy,
|
|
6405
6954
|
parseFrontmatter,
|
|
6406
6955
|
parseKnowledgeBenchmarkJsonl,
|
|
6407
6956
|
parseKnowledgeBenchmarkQrels,
|
|
6408
6957
|
parseKnowledgeWriteBlocks,
|
|
6958
|
+
partitionRetrievalScenarios,
|
|
6409
6959
|
politeFetch,
|
|
6410
6960
|
promoteKnowledgeCandidate,
|
|
6411
6961
|
proposeFromFinding,
|
|
@@ -6423,7 +6973,6 @@ export {
|
|
|
6423
6973
|
retrievalConfigFromSurface,
|
|
6424
6974
|
retrievalConfigSurface,
|
|
6425
6975
|
retrievalHoldoutConfigHash,
|
|
6426
|
-
retrievalParameterSweepProposer,
|
|
6427
6976
|
retrievalRecallJudge,
|
|
6428
6977
|
runAgentMemoryExperiment,
|
|
6429
6978
|
runAgentMemoryImprovement,
|
|
@@ -6434,9 +6983,12 @@ export {
|
|
|
6434
6983
|
runKnowledgeResearchLoop,
|
|
6435
6984
|
runMemoryAdapterBenchmark,
|
|
6436
6985
|
runRagKnowledgeImprovementLoop,
|
|
6986
|
+
runRagOptimization,
|
|
6437
6987
|
runRetrievalImprovementLoop,
|
|
6988
|
+
runSerializedKnowledgeOptimization,
|
|
6438
6989
|
runTwoAgentResearchLoop,
|
|
6439
6990
|
runVerifiedResearchLoop,
|
|
6991
|
+
scenarioContentFingerprint,
|
|
6440
6992
|
scoreKnowledgeBaseIndex,
|
|
6441
6993
|
scoreKnowledgeBenchmarkArtifact,
|
|
6442
6994
|
scoreMemoryBenchmarkArtifact,
|