@tangle-network/agent-knowledge 3.0.0 → 3.1.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/dist/index.d.ts CHANGED
@@ -1186,6 +1186,7 @@ interface PromoteKnowledgeCandidateOptions {
1186
1186
  now?: () => Date;
1187
1187
  onState?: (state: KnowledgeImprovementRunState) => Promise<void> | void;
1188
1188
  }
1189
+ type RestoreKnowledgeCandidateBaselineOptions = PromoteKnowledgeCandidateOptions;
1189
1190
  interface UseKnowledgeImprovementCandidateOptions {
1190
1191
  root: string;
1191
1192
  candidate: KnowledgeImprovementCandidateRef;
@@ -1246,6 +1247,8 @@ declare function knowledgeImprovementCandidateRef(result: Pick<KnowledgeImprovem
1246
1247
  declare function withKnowledgeImprovementCandidate<T>(options: UseKnowledgeImprovementCandidateOptions, use: (candidate: ResolvedKnowledgeImprovementCandidate) => Promise<T> | T): Promise<T>;
1247
1248
  /** Promote one previously measured candidate without rerunning research or evaluation. */
1248
1249
  declare function promoteKnowledgeCandidate(options: PromoteKnowledgeCandidateOptions): Promise<KnowledgeImprovementResult>;
1250
+ /** Restore the frozen baseline paired with one previously measured candidate. */
1251
+ declare function restoreKnowledgeCandidateBaseline(options: RestoreKnowledgeCandidateBaselineOptions): Promise<KnowledgeImprovementResult>;
1249
1252
  declare function improveKnowledgeBase(options: KnowledgeImprovementOptions): Promise<KnowledgeImprovementResult>;
1250
1253
  interface KnowledgeImprovementEvent extends Record<string, unknown> {
1251
1254
  at: string;
@@ -2664,4 +2667,4 @@ declare function normalizeLinkTarget(target: string): string;
2664
2667
  declare function isSafeKnowledgePath(path: string, allowedPrefixes?: string[]): boolean;
2665
2668
  declare function parseKnowledgeWriteBlocks(text: string, allowedPrefixes?: string[]): KnowledgeWriteParseResult;
2666
2669
 
2667
- export { type AdaptiveDecision, type AdaptiveDriverOptions, type AdaptiveResearchDriver, type AdaptiveStats, type AddSourceOptions, type AddSourceTextInput, type ApplyWriteBlocksResult, type BuildEvalKnowledgeBundleOptions, type ChunkingOptions, type ClaimGroundingDriverOptions, type CompanyEvalCase, type D1Adapter, type DedupReason, type DeepQuestion, type DeepQuestionKind, type DefineReadinessSpecInput, type DetectChangesOptions, type DetectChangesResult, type DiscoveryLoopResult, type DiscoveryLoopRound, type DiscoveryLoopStopReason, type DiscoveryResult, type DiscoveryTask, type DriverResearchContext, type EvalKnowledgeBundleBuildResult, type EvaluateKnowledgeBaseReadinessOptions, type ExpectedGroup, type ExternalRagEvalScore, type FactResult, type FileSystemFreshnessStoreOptions, FileSystemKbStore, type FreshnessKey, type FreshnessMark, type FreshnessRecord, type FreshnessTtl, type GroundClaimOptions, type GroundingResult, type KbStore, KnowledgeBaseCandidateSchema, type KnowledgeBaseQualityOptions, type KnowledgeBaseQualityReport, type KnowledgeBaseReadinessEvaluation, type KnowledgeChange, type KnowledgeChangeKind, type KnowledgeChunk, KnowledgeClaim, type KnowledgeControlLoopAction, type KnowledgeControlLoopActionResult, type KnowledgeControlLoopAdapter, type KnowledgeControlLoopAdapterOptions, type KnowledgeControlLoopState, type KnowledgeDiscoveryDispatcher, type KnowledgeDiscoveryWorker, KnowledgeEvent, type KnowledgeEventQuery, KnowledgeEventSchema, KnowledgeEventType, type KnowledgeExplanation, KnowledgeFragment, type KnowledgeFreshnessStore, type KnowledgeGap, KnowledgeGraph, KnowledgeGraphEdgeSchema, KnowledgeGraphNodeSchema, type KnowledgeImprovementCandidateRecord, type KnowledgeImprovementCandidateRef, KnowledgeImprovementCandidateRefSchema, type KnowledgeImprovementEvaluationInput, type KnowledgeImprovementEvaluator, type KnowledgeImprovementEvent, type KnowledgeImprovementEvidence, KnowledgeImprovementEvidenceSchema, type KnowledgeImprovementMetric, type KnowledgeImprovementMetricProvenance, type KnowledgeImprovementOptions, type KnowledgeImprovementResult, type KnowledgeImprovementRetrievalOptions, type KnowledgeImprovementRunState, KnowledgeImprovementRunStateSchema, type KnowledgeImprovementStatus, type KnowledgeImprovementUpdate, type KnowledgeImprovementUpdateInput, KnowledgeIndex, KnowledgeIndexSchema, type KnowledgeInspection, type KnowledgeLayout, KnowledgeLintFinding, KnowledgePage, KnowledgePageSchema, type KnowledgeProposal, KnowledgeProposalParseError, type KnowledgeReadinessSpec, KnowledgeRelease, type KnowledgeReleaseInput, type KnowledgeReleaseReport, type KnowledgeResearchLoopContext, type KnowledgeResearchLoopDecision, type KnowledgeResearchLoopResult, type KnowledgeResearchLoopStep, KnowledgeSearchResult, KnowledgeWriteBlock, KnowledgeWriteParseResult, type MaterialFact, type MaterialFactLens, type MaterialFactsResult, MemoryKbStore, type ParsedFrontmatter, type PendingKnowledgeMutation, type PromoteKnowledgeCandidateOptions, type ProposeFromFindingsResult, READINESS_SPEC_DEFAULTS, type RagAnswerEvalArtifact, type RagAnswerEvalCase, type RagAnswerEvalScenario, type RagAnswerMetricSummary, type RagAnswerQualityHookOptions, type RagAnswerQualityInput, type RagAnswerQualityJudgeOptions, type RagAnswerQualityResult, type RagCalibrationOptions, type RagCalibrationResult, type RagDiagnosisInput, type RagEvalCitation, type RagEvalClaim, type RagEvalContext, type RagEvalMetricKey, type RagEvalProvider, type RagEvalSlice, type RagGapFinding, type RagGapKind, type RagGapSeverity, type RagKnowledgeAcquisitionInput, type RagKnowledgeImprovementPhase, type RagKnowledgeImprovementPhaseResult, type RagKnowledgeImprovementPhaseStatus, type RagKnowledgeResearchOptions, type RagKnowledgeUpdateInput, type RagKnowledgeUpdateResult, type RagPhaseInputBase, type RagPromotionInput, type RagPromotionResult, type RagRequiredContext, type RecoverPendingKnowledgeMutationOptions, type RejectedSource, type ResearchContribution, type ResearchDriver, type ResearchDrivingDriver, type ResearchDrivingDriverOptions, type ResearchDrivingState, type ResearchDrivingSteer, type ResearchSourceProposal, type ResearchWorker, type ResolvedKnowledgeImprovementCandidate, type RouterClient, RouterError, type RouterUsage, type RunDiscoveryLoopOptions, type RunKnowledgeResearchLoopOptions, type RunRagKnowledgeImprovementLoopOptions, type RunRagKnowledgeImprovementLoopResult, RunRetrievalImprovementLoopOptions, RunRetrievalImprovementLoopResult, SCAFFOLD_PAGE_BASENAMES, type SourceAdapter, type SourceAdapterInput, type SourceAdapterOutput, SourceAnchorSchema, type SourceFreshnessInspection, SourceRecord, SourceRecordSchema, SourceRegistry, type SourceVerdict, type SourceVerificationContext, type TangleRouterOptions, type ThesisRunOptions, type ThesisRunResult, type ThesisTaskInput, type TrackedClaim, type TriageClass, type TwoAgentResearchLoopOptions, type TwoAgentResearchLoopResult, type TwoAgentResearchRound, type UseKnowledgeImprovementCandidateOptions, type ValidateKnowledgeOptions, type ValidateKnowledgeResult, type VerifiedResearchLoopOptions, type VerifiedResearchLoopResult, type VerifiedResearchRound, type VerifyingDriverOptions, WIKILINK_REGEX, type WebResearchWorkerOptions, type WebSearchHit, type WorkerClaimDecorationOptions, type WorkerResearchContext, addSourcePath, addSourceText, applyKnowledgeWriteBlocks, applyKnowledgeWriteBlocksFile, buildEvalKnowledgeBundle, buildKnowledgeGraph, buildKnowledgeIndex, calibrateRagAnswerJudge, canonicalizeUrl, chunkMarkdown, citedClaimKey, citedClaimOf, contentKey, createAdaptiveResearchDriver, createClaimDecorator, createClaimGroundingVerifier, createCollectionResearchDriver, createD1FreshnessStoreStub, createFileSystemFreshnessStore, createKnowledgeControlLoopAdapter, createKnowledgeEvent, createLocalDiscoveryDispatcher, createRagAnswerQualityHook, createResearchDrivingDriver, createTangleRouterClient, createVerifyingResearchDriver, createWebResearchWorker, defineReadinessSpec, detectChanges, diagnoseRagAnswerFailure, evaluateKnowledgeBaseReadiness, explainKnowledgeTarget, extractWikilinks, formatFrontmatter, fromAgentCandidateKnowledgeRef, gradeCompanyAgainstText, gradeFactAgainstText, groundClaimInText, hashKnowledgeBase, improveKnowledgeBase, initKnowledgeBase, inspectKnowledgeIndex, inspectPendingKnowledgeMutation, investmentThesisSet, isSafeKnowledgePath, isScaffoldPath, kbIndexToText, knowledgeImprovementCandidateRef, knowledgeImprovementRunDir, knowledgeImprovementRunId, knowledgeReleaseReport, layoutFor, lensDistribution, lintKnowledgeIndex, loadKnowledgeImprovementEvents, loadKnowledgeImprovementState, loadKnowledgePages, loadSourceRegistry, materialFactsSurfaced, materialFactsSurfacedInText, mediaTypeFor, normalizeExternalRagScores, normalizeLinkTarget, parseFrontmatter, parseKnowledgeWriteBlocks, promoteKnowledgeCandidate, proposeFromFinding, proposeFromFindings, ragAnswerQualityJudge, reciprocalRankFusion, recoverPendingKnowledgeMutation, runDiscoveryLoop, runInvestmentThesisTask, runKnowledgeResearchLoop, runRagKnowledgeImprovementLoop, runTwoAgentResearchLoop, runVerifiedResearchLoop, scoreKnowledgeBaseIndex, scoreRagAnswerArtifact, searchKnowledge, sha256, slugify, sourceMatchesGaps, sourceRegistryPath, stableId, stripFrontmatter, textSourceAdapter, thesisReadinessSpecs, toAgentCandidateKnowledgeRef, toDeepEvalTestCases, toRagCheckerRecords, toRagasEvaluationRows, toTruLensRecords, tokenizeQuery, totalMaterialFacts, triageSource, validateKnowledgeIndex, withCitedClaim, withKnowledgeImprovementCandidate, writeJson, writeKnowledgeIndex, writeSourceRegistry };
2670
+ export { type AdaptiveDecision, type AdaptiveDriverOptions, type AdaptiveResearchDriver, type AdaptiveStats, type AddSourceOptions, type AddSourceTextInput, type ApplyWriteBlocksResult, type BuildEvalKnowledgeBundleOptions, type ChunkingOptions, type ClaimGroundingDriverOptions, type CompanyEvalCase, type D1Adapter, type DedupReason, type DeepQuestion, type DeepQuestionKind, type DefineReadinessSpecInput, type DetectChangesOptions, type DetectChangesResult, type DiscoveryLoopResult, type DiscoveryLoopRound, type DiscoveryLoopStopReason, type DiscoveryResult, type DiscoveryTask, type DriverResearchContext, type EvalKnowledgeBundleBuildResult, type EvaluateKnowledgeBaseReadinessOptions, type ExpectedGroup, type ExternalRagEvalScore, type FactResult, type FileSystemFreshnessStoreOptions, FileSystemKbStore, type FreshnessKey, type FreshnessMark, type FreshnessRecord, type FreshnessTtl, type GroundClaimOptions, type GroundingResult, type KbStore, KnowledgeBaseCandidateSchema, type KnowledgeBaseQualityOptions, type KnowledgeBaseQualityReport, type KnowledgeBaseReadinessEvaluation, type KnowledgeChange, type KnowledgeChangeKind, type KnowledgeChunk, KnowledgeClaim, type KnowledgeControlLoopAction, type KnowledgeControlLoopActionResult, type KnowledgeControlLoopAdapter, type KnowledgeControlLoopAdapterOptions, type KnowledgeControlLoopState, type KnowledgeDiscoveryDispatcher, type KnowledgeDiscoveryWorker, KnowledgeEvent, type KnowledgeEventQuery, KnowledgeEventSchema, KnowledgeEventType, type KnowledgeExplanation, KnowledgeFragment, type KnowledgeFreshnessStore, type KnowledgeGap, KnowledgeGraph, KnowledgeGraphEdgeSchema, KnowledgeGraphNodeSchema, type KnowledgeImprovementCandidateRecord, type KnowledgeImprovementCandidateRef, KnowledgeImprovementCandidateRefSchema, type KnowledgeImprovementEvaluationInput, type KnowledgeImprovementEvaluator, type KnowledgeImprovementEvent, type KnowledgeImprovementEvidence, KnowledgeImprovementEvidenceSchema, type KnowledgeImprovementMetric, type KnowledgeImprovementMetricProvenance, type KnowledgeImprovementOptions, type KnowledgeImprovementResult, type KnowledgeImprovementRetrievalOptions, type KnowledgeImprovementRunState, KnowledgeImprovementRunStateSchema, type KnowledgeImprovementStatus, type KnowledgeImprovementUpdate, type KnowledgeImprovementUpdateInput, KnowledgeIndex, KnowledgeIndexSchema, type KnowledgeInspection, type KnowledgeLayout, KnowledgeLintFinding, KnowledgePage, KnowledgePageSchema, type KnowledgeProposal, KnowledgeProposalParseError, type KnowledgeReadinessSpec, KnowledgeRelease, type KnowledgeReleaseInput, type KnowledgeReleaseReport, type KnowledgeResearchLoopContext, type KnowledgeResearchLoopDecision, type KnowledgeResearchLoopResult, type KnowledgeResearchLoopStep, KnowledgeSearchResult, KnowledgeWriteBlock, KnowledgeWriteParseResult, type MaterialFact, type MaterialFactLens, type MaterialFactsResult, MemoryKbStore, type ParsedFrontmatter, type PendingKnowledgeMutation, type PromoteKnowledgeCandidateOptions, type ProposeFromFindingsResult, READINESS_SPEC_DEFAULTS, type RagAnswerEvalArtifact, type RagAnswerEvalCase, type RagAnswerEvalScenario, type RagAnswerMetricSummary, type RagAnswerQualityHookOptions, type RagAnswerQualityInput, type RagAnswerQualityJudgeOptions, type RagAnswerQualityResult, type RagCalibrationOptions, type RagCalibrationResult, type RagDiagnosisInput, type RagEvalCitation, type RagEvalClaim, type RagEvalContext, type RagEvalMetricKey, type RagEvalProvider, type RagEvalSlice, type RagGapFinding, type RagGapKind, type RagGapSeverity, type RagKnowledgeAcquisitionInput, type RagKnowledgeImprovementPhase, type RagKnowledgeImprovementPhaseResult, type RagKnowledgeImprovementPhaseStatus, type RagKnowledgeResearchOptions, type RagKnowledgeUpdateInput, type RagKnowledgeUpdateResult, type RagPhaseInputBase, type RagPromotionInput, type RagPromotionResult, type RagRequiredContext, type RecoverPendingKnowledgeMutationOptions, type RejectedSource, type ResearchContribution, type ResearchDriver, type ResearchDrivingDriver, type ResearchDrivingDriverOptions, type ResearchDrivingState, type ResearchDrivingSteer, type ResearchSourceProposal, type ResearchWorker, type ResolvedKnowledgeImprovementCandidate, type RestoreKnowledgeCandidateBaselineOptions, type RouterClient, RouterError, type RouterUsage, type RunDiscoveryLoopOptions, type RunKnowledgeResearchLoopOptions, type RunRagKnowledgeImprovementLoopOptions, type RunRagKnowledgeImprovementLoopResult, RunRetrievalImprovementLoopOptions, RunRetrievalImprovementLoopResult, SCAFFOLD_PAGE_BASENAMES, type SourceAdapter, type SourceAdapterInput, type SourceAdapterOutput, SourceAnchorSchema, type SourceFreshnessInspection, SourceRecord, SourceRecordSchema, SourceRegistry, type SourceVerdict, type SourceVerificationContext, type TangleRouterOptions, type ThesisRunOptions, type ThesisRunResult, type ThesisTaskInput, type TrackedClaim, type TriageClass, type TwoAgentResearchLoopOptions, type TwoAgentResearchLoopResult, type TwoAgentResearchRound, type UseKnowledgeImprovementCandidateOptions, type ValidateKnowledgeOptions, type ValidateKnowledgeResult, type VerifiedResearchLoopOptions, type VerifiedResearchLoopResult, type VerifiedResearchRound, type VerifyingDriverOptions, WIKILINK_REGEX, type WebResearchWorkerOptions, type WebSearchHit, type WorkerClaimDecorationOptions, type WorkerResearchContext, addSourcePath, addSourceText, applyKnowledgeWriteBlocks, applyKnowledgeWriteBlocksFile, buildEvalKnowledgeBundle, buildKnowledgeGraph, buildKnowledgeIndex, calibrateRagAnswerJudge, canonicalizeUrl, chunkMarkdown, citedClaimKey, citedClaimOf, contentKey, createAdaptiveResearchDriver, createClaimDecorator, createClaimGroundingVerifier, createCollectionResearchDriver, createD1FreshnessStoreStub, createFileSystemFreshnessStore, createKnowledgeControlLoopAdapter, createKnowledgeEvent, createLocalDiscoveryDispatcher, createRagAnswerQualityHook, createResearchDrivingDriver, createTangleRouterClient, createVerifyingResearchDriver, createWebResearchWorker, defineReadinessSpec, detectChanges, diagnoseRagAnswerFailure, evaluateKnowledgeBaseReadiness, explainKnowledgeTarget, extractWikilinks, formatFrontmatter, fromAgentCandidateKnowledgeRef, gradeCompanyAgainstText, gradeFactAgainstText, groundClaimInText, hashKnowledgeBase, improveKnowledgeBase, initKnowledgeBase, inspectKnowledgeIndex, inspectPendingKnowledgeMutation, investmentThesisSet, isSafeKnowledgePath, isScaffoldPath, kbIndexToText, knowledgeImprovementCandidateRef, knowledgeImprovementRunDir, knowledgeImprovementRunId, knowledgeReleaseReport, layoutFor, lensDistribution, lintKnowledgeIndex, loadKnowledgeImprovementEvents, loadKnowledgeImprovementState, loadKnowledgePages, loadSourceRegistry, materialFactsSurfaced, materialFactsSurfacedInText, mediaTypeFor, normalizeExternalRagScores, normalizeLinkTarget, parseFrontmatter, parseKnowledgeWriteBlocks, promoteKnowledgeCandidate, proposeFromFinding, proposeFromFindings, ragAnswerQualityJudge, reciprocalRankFusion, recoverPendingKnowledgeMutation, restoreKnowledgeCandidateBaseline, runDiscoveryLoop, runInvestmentThesisTask, runKnowledgeResearchLoop, runRagKnowledgeImprovementLoop, runTwoAgentResearchLoop, runVerifiedResearchLoop, scoreKnowledgeBaseIndex, scoreRagAnswerArtifact, searchKnowledge, sha256, slugify, sourceMatchesGaps, sourceRegistryPath, stableId, stripFrontmatter, textSourceAdapter, thesisReadinessSpecs, toAgentCandidateKnowledgeRef, toDeepEvalTestCases, toRagCheckerRecords, toRagasEvaluationRows, toTruLensRecords, tokenizeQuery, totalMaterialFacts, triageSource, validateKnowledgeIndex, withCitedClaim, withKnowledgeImprovementCandidate, writeJson, writeKnowledgeIndex, writeSourceRegistry };
package/dist/index.js CHANGED
@@ -2314,6 +2314,12 @@ async function withKnowledgeImprovementCandidate(options, use) {
2314
2314
  });
2315
2315
  }
2316
2316
  async function promoteKnowledgeCandidate(options) {
2317
+ return transitionKnowledgeCandidate(options, "candidate");
2318
+ }
2319
+ async function restoreKnowledgeCandidateBaseline(options) {
2320
+ return transitionKnowledgeCandidate(options, "baseline");
2321
+ }
2322
+ async function transitionKnowledgeCandidate(options, target) {
2317
2323
  assertExactCandidatePlatform();
2318
2324
  const candidateRef = Object.freeze(
2319
2325
  KnowledgeImprovementCandidateRefSchema.parse(options.candidate)
@@ -2331,16 +2337,19 @@ async function promoteKnowledgeCandidate(options) {
2331
2337
  candidateRef.runId,
2332
2338
  runDir
2333
2339
  );
2334
- return await promoteReadyCandidate({
2335
- root: options.root,
2336
- runDir,
2337
- state,
2338
- candidateRef,
2339
- leaseTtlMs: options.leaseTtlMs ?? DEFAULT_LEASE_TTL_MS,
2340
- assertRunOwned: lease.assertOwned,
2341
- now,
2342
- onState: options.onState
2343
- });
2340
+ return await applyKnowledgeCandidateTarget(
2341
+ {
2342
+ root: options.root,
2343
+ runDir,
2344
+ state,
2345
+ candidateRef,
2346
+ leaseTtlMs: options.leaseTtlMs ?? DEFAULT_LEASE_TTL_MS,
2347
+ assertRunOwned: lease.assertOwned,
2348
+ now,
2349
+ onState: options.onState
2350
+ },
2351
+ target
2352
+ );
2344
2353
  } finally {
2345
2354
  await lease.release();
2346
2355
  }
@@ -2402,23 +2411,26 @@ async function improveKnowledgeBaseInRun(options, runId, runDir, now) {
2402
2411
  const resumableCandidateRef = resumablePromotion ? candidateRefFor(runId, state, resumablePromotion) : void 0;
2403
2412
  await withKnowledgeMutation(options.root, () => void 0, {
2404
2413
  resumeTransaction: resumableCandidateRef ? {
2405
- purpose: promotionTransactionPurpose(resumableCandidateRef),
2406
- validate: (transaction) => assertPromotionTransaction(transaction, resumableCandidateRef)
2414
+ purpose: knowledgeCandidateTransitionPurpose(resumableCandidateRef, "candidate"),
2415
+ validate: (transaction) => assertCandidateTransitionTransaction(transaction, resumableCandidateRef, "candidate")
2407
2416
  } : void 0
2408
2417
  });
2409
2418
  await ensureBaselineSnapshot(runDir, options.root, state.baseHash);
2410
2419
  if (state.status === "promoted") {
2411
2420
  const promoted = promotedCandidate;
2412
- return await promoteReadyCandidate({
2413
- root: options.root,
2414
- runDir,
2415
- state,
2416
- candidateRef: candidateRefFor(runId, state, promoted),
2417
- leaseTtlMs: options.leaseTtlMs ?? DEFAULT_LEASE_TTL_MS,
2418
- assertRunOwned: lease.assertOwned,
2419
- now,
2420
- onState: options.onState
2421
- });
2421
+ return await applyKnowledgeCandidateTarget(
2422
+ {
2423
+ root: options.root,
2424
+ runDir,
2425
+ state,
2426
+ candidateRef: candidateRefFor(runId, state, promoted),
2427
+ leaseTtlMs: options.leaseTtlMs ?? DEFAULT_LEASE_TTL_MS,
2428
+ assertRunOwned: lease.assertOwned,
2429
+ now,
2430
+ onState: options.onState
2431
+ },
2432
+ "candidate"
2433
+ );
2422
2434
  }
2423
2435
  if (state.status === "blocked") {
2424
2436
  return { runId, state, promoted: false, blocked: true };
@@ -2516,14 +2528,16 @@ async function improveKnowledgeBaseInRun(options, runId, runDir, now) {
2516
2528
  await lease.release();
2517
2529
  }
2518
2530
  }
2519
- async function promoteReadyCandidate(input) {
2531
+ async function applyKnowledgeCandidateTarget(input, target) {
2520
2532
  const { candidateRef, runDir, state } = input;
2521
2533
  assertStateIdentity(input.root, candidateRef, state);
2522
2534
  const candidate = state.candidates.find((entry) => entry.candidateId === candidateRef.candidateId);
2523
2535
  if (!candidate || canonicalJson(candidateRefFor(candidateRef.runId, state, candidate)) !== canonicalJson(candidateRef)) {
2524
2536
  throw new Error("knowledge candidate approval does not match the measured candidate");
2525
2537
  }
2526
- const purpose = promotionTransactionPurpose(candidateRef);
2538
+ const action = target === "candidate" ? "promotion" : "restore";
2539
+ const desiredHash = target === "candidate" ? candidateRef.candidateHash : candidateRef.baseHash;
2540
+ const purpose = knowledgeCandidateTransitionPurpose(candidateRef, target);
2527
2541
  return withKnowledgeMutation(
2528
2542
  input.root,
2529
2543
  async (mutationLock) => {
@@ -2536,49 +2550,46 @@ async function promoteReadyCandidate(input) {
2536
2550
  `knowledge run already promoted '${state.promotedCandidateId ?? "unknown"}'`
2537
2551
  );
2538
2552
  }
2539
- if (state.status === "promoted" && currentHash !== candidateRef.candidateHash) {
2553
+ if (target === "candidate" && state.status === "promoted" && currentHash !== candidateRef.candidateHash) {
2540
2554
  throw new Error(
2541
2555
  `promoted knowledge base changed: expected ${candidateRef.candidateHash}, got ${currentHash}`
2542
2556
  );
2543
2557
  }
2544
2558
  if (state.status !== "promoted" && state.status !== "candidate-ready") {
2545
2559
  throw new Error(
2546
- `knowledge candidate is not ready for promotion: run=${state.status}, candidate=${candidate.status}`
2560
+ `knowledge candidate is not ready for ${action}: run=${state.status}, candidate=${candidate.status}`
2547
2561
  );
2548
2562
  }
2549
2563
  if (currentHash !== state.baseHash && currentHash !== candidateRef.candidateHash) {
2550
- return await blockPromotion(
2551
- input,
2552
- candidate,
2553
- `base changed before promotion: expected ${state.baseHash}, got ${currentHash}`
2554
- );
2564
+ const reason = target === "candidate" ? `base changed before promotion: expected ${state.baseHash}, got ${currentHash}` : `knowledge changed before restore: expected ${candidateRef.candidateHash}, got ${currentHash}`;
2565
+ return await blockCandidateTransition(input, candidate, target, reason);
2555
2566
  }
2556
- if (currentHash !== candidateRef.candidateHash) {
2567
+ if (currentHash !== desiredHash) {
2557
2568
  pending = await withMeasuredCandidateSnapshot(
2558
2569
  input.root,
2559
2570
  runDir,
2560
2571
  state,
2561
2572
  candidateRef,
2562
2573
  (resolved) => withBaselineSnapshot(runDir, state.baseHash, async (baselineRoot) => {
2563
- const plan = await promotionPlanEntries(baselineRoot, resolved.root);
2564
- if (knowledgeFileTransactionPlanHash(plan) !== candidateRef.promotionPlanHash) {
2565
- throw new Error("knowledge candidate promotion plan changed after approval");
2566
- }
2574
+ const sourceRoot = target === "candidate" ? baselineRoot : resolved.root;
2575
+ const targetRoot = target === "candidate" ? resolved.root : baselineRoot;
2576
+ const plan = await knowledgeFilePlanEntries(sourceRoot, targetRoot);
2577
+ assertCandidateTransitionPlan(plan, candidateRef, target);
2567
2578
  return prepareKnowledgeFileTransaction({
2568
2579
  root: input.root,
2569
2580
  transactionRoot,
2570
2581
  purpose,
2571
- mutations: await promotionMutations(resolved.root, plan),
2582
+ mutations: await knowledgePlanMutations(targetRoot, plan),
2572
2583
  includeUnchanged: true,
2573
2584
  now: input.now
2574
2585
  });
2575
2586
  })
2576
2587
  );
2577
2588
  if (!pending) {
2578
- throw new Error("knowledge promotion plan unexpectedly contained no file changes");
2589
+ throw new Error(`knowledge ${action} plan unexpectedly contained no file changes`);
2579
2590
  }
2580
2591
  try {
2581
- assertPromotionTransaction(pending, candidateRef);
2592
+ assertCandidateTransitionTransaction(pending, candidateRef, target);
2582
2593
  } catch (error) {
2583
2594
  try {
2584
2595
  await rollbackKnowledgeFileTransaction({
@@ -2602,7 +2613,7 @@ async function promoteReadyCandidate(input) {
2602
2613
  } catch (cleanupError) {
2603
2614
  throw new AggregateError(
2604
2615
  [error, cleanupError],
2605
- "invalid knowledge promotion transaction could not be removed"
2616
+ `invalid knowledge ${action} transaction could not be removed`
2606
2617
  );
2607
2618
  }
2608
2619
  throw error;
@@ -2622,8 +2633,8 @@ async function promoteReadyCandidate(input) {
2622
2633
  }
2623
2634
  mutationLock.assertOwned();
2624
2635
  input.assertRunOwned();
2625
- if (await hashKnowledgeBase(input.root) !== candidateRef.candidateHash) {
2626
- throw new Error("promoted knowledge content does not match the approved candidate");
2636
+ if (await hashKnowledgeBase(input.root) !== desiredHash) {
2637
+ throw new Error(`knowledge ${action} content does not match the approved target`);
2627
2638
  }
2628
2639
  await writeKnowledgeIndex(input.root);
2629
2640
  } catch (error) {
@@ -2634,7 +2645,7 @@ async function promoteReadyCandidate(input) {
2634
2645
  } catch (ownershipError) {
2635
2646
  throw new AggregateError(
2636
2647
  [error, ownershipError],
2637
- "knowledge promotion lost its lock and left the transaction pending"
2648
+ `knowledge ${action} lost its lock and left the transaction pending`
2638
2649
  );
2639
2650
  }
2640
2651
  try {
@@ -2660,18 +2671,20 @@ async function promoteReadyCandidate(input) {
2660
2671
  } catch (rollbackError) {
2661
2672
  throw new AggregateError(
2662
2673
  [error, rollbackError],
2663
- "knowledge promotion failed and could not restore the previous files"
2674
+ `knowledge ${action} failed and could not restore the previous files`
2664
2675
  );
2665
2676
  }
2666
2677
  throw error;
2667
2678
  }
2668
- candidate.status = "promoted";
2679
+ candidate.status = target === "candidate" ? "promoted" : "candidate-ready";
2669
2680
  candidate.updatedAt = input.now().toISOString();
2670
- state.status = "promoted";
2671
- state.promotedCandidateId = candidate.candidateId;
2681
+ state.status = candidate.status;
2682
+ if (target === "candidate") state.promotedCandidateId = candidate.candidateId;
2683
+ else delete state.promotedCandidateId;
2684
+ delete state.blockedReason;
2672
2685
  state.updatedAt = input.now().toISOString();
2673
2686
  await saveState(runDir, state, input.onState);
2674
- await ensurePromotionEvent(runDir, candidateRef);
2687
+ await ensureCandidateTransitionEvent(runDir, candidateRef, target);
2675
2688
  if (pending) {
2676
2689
  await finishKnowledgeFileTransaction({
2677
2690
  root: input.root,
@@ -2683,28 +2696,33 @@ async function promoteReadyCandidate(input) {
2683
2696
  }
2684
2697
  });
2685
2698
  }
2686
- return promotionResult(input, candidate, true, false);
2699
+ return candidateTransitionResult(input, candidate, target === "candidate", false);
2687
2700
  },
2688
2701
  {
2689
2702
  staleMs: input.leaseTtlMs,
2690
2703
  resumeTransaction: {
2691
2704
  purpose,
2692
- validate: (transaction) => assertPromotionTransaction(transaction, candidateRef)
2705
+ validate: (transaction) => assertCandidateTransitionTransaction(transaction, candidateRef, target)
2693
2706
  }
2694
2707
  }
2695
2708
  );
2696
2709
  }
2697
- async function blockPromotion(input, candidate, reason) {
2710
+ async function blockCandidateTransition(input, candidate, target, reason) {
2711
+ if (input.state.status === "promoted") {
2712
+ candidate.status = "blocked";
2713
+ candidate.updatedAt = input.now().toISOString();
2714
+ delete input.state.promotedCandidateId;
2715
+ }
2698
2716
  await blockRun(input.runDir, input.state, reason, input.onState, input.now);
2699
2717
  await appendLedger(input.runDir, {
2700
- type: "promotion.blocked",
2718
+ type: target === "candidate" ? "promotion.blocked" : "restore.blocked",
2701
2719
  runId: input.candidateRef.runId,
2702
2720
  candidateId: candidate.candidateId,
2703
2721
  reason
2704
2722
  });
2705
- return promotionResult(input, candidate, false, true);
2723
+ return candidateTransitionResult(input, candidate, false, true);
2706
2724
  }
2707
- function promotionResult(input, candidate, promoted, blocked) {
2725
+ function candidateTransitionResult(input, candidate, promoted, blocked) {
2708
2726
  return {
2709
2727
  runId: input.candidateRef.runId,
2710
2728
  state: input.state,
@@ -3033,7 +3051,7 @@ async function evaluateCandidate(runDir, state, candidate, snapshot, lifecycle,
3033
3051
  }
3034
3052
  candidate.candidateHash = candidateHash;
3035
3053
  candidate.promotionPlanHash = knowledgeFileTransactionPlanHash(
3036
- await promotionPlanEntries(baselineRoot, snapshot.root)
3054
+ await knowledgeFilePlanEntries(baselineRoot, snapshot.root)
3037
3055
  );
3038
3056
  const evidence = KnowledgeImprovementEvidenceSchema.parse(
3039
3057
  JSON.parse(
@@ -3243,13 +3261,14 @@ async function copyKnowledgeWorkspace(sourceRoot, targetRoot) {
3243
3261
  );
3244
3262
  await writeKnowledgeIndex(targetRoot);
3245
3263
  }
3246
- function promotionTransactionPurpose(candidate) {
3247
- return `knowledge-promotion:${contentHash(candidate)}`;
3264
+ function knowledgeCandidateTransitionPurpose(candidate, target) {
3265
+ const action = target === "candidate" ? "promotion" : "restore";
3266
+ return `knowledge-${action}:${contentHash(candidate)}`;
3248
3267
  }
3249
- async function promotionPlanEntries(baselineRoot, candidateRoot) {
3268
+ async function knowledgeFilePlanEntries(sourceRoot, targetRoot) {
3250
3269
  const [before, after] = await Promise.all([
3251
- knowledgeHashEntries(baselineRoot),
3252
- knowledgeHashEntries(candidateRoot)
3270
+ knowledgeHashEntries(sourceRoot),
3271
+ knowledgeHashEntries(targetRoot)
3253
3272
  ]);
3254
3273
  const beforeByPath = new Map(before.map((entry) => [entry.path, entry]));
3255
3274
  const afterByPath = new Map(after.map((entry) => [entry.path, entry]));
@@ -3269,31 +3288,44 @@ async function promotionPlanEntries(baselineRoot, candidateRoot) {
3269
3288
  };
3270
3289
  });
3271
3290
  }
3272
- async function promotionMutations(candidateRoot, plan) {
3291
+ async function knowledgePlanMutations(targetRoot, plan) {
3273
3292
  return Promise.all(
3274
3293
  plan.map(async (entry) => {
3275
3294
  if (entry.afterHash === null) return { path: entry.path, content: null };
3276
- const file = await readRegularFileWithinRoot(candidateRoot, entry.path);
3295
+ const file = await readRegularFileWithinRoot(targetRoot, entry.path);
3277
3296
  const actualHash = createHash("sha256").update(file.bytes).digest("hex");
3278
3297
  if (actualHash !== entry.afterHash || file.mode !== entry.afterMode) {
3279
- throw new Error(`knowledge candidate file changed before promotion: ${entry.path}`);
3298
+ throw new Error(`knowledge target file changed before activation: ${entry.path}`);
3280
3299
  }
3281
3300
  return { path: entry.path, content: file.bytes, mode: file.mode };
3282
3301
  })
3283
3302
  );
3284
3303
  }
3285
- function assertPromotionTransaction(transaction, candidate) {
3286
- const actualPlanHash = knowledgeFileTransactionPlanHash(transaction.entries);
3304
+ function assertCandidateTransitionPlan(plan, candidate, target) {
3305
+ const approvedDirection = target === "candidate" ? plan : reverseKnowledgeFilePlan(plan);
3306
+ const actualPlanHash = knowledgeFileTransactionPlanHash(approvedDirection);
3287
3307
  if (actualPlanHash !== candidate.promotionPlanHash) {
3288
3308
  throw new Error(
3289
- `knowledge promotion plan changed after approval: expected ${candidate.promotionPlanHash}, got ${actualPlanHash}`
3309
+ `knowledge candidate plan changed after approval: expected ${candidate.promotionPlanHash}, got ${actualPlanHash}`
3290
3310
  );
3291
3311
  }
3292
3312
  }
3293
- async function ensurePromotionEvent(runDir, candidateRef) {
3294
- if (await hasPromotionEvent(runDir, candidateRef)) return;
3313
+ function assertCandidateTransitionTransaction(transaction, candidate, target) {
3314
+ assertCandidateTransitionPlan(transaction.entries, candidate, target);
3315
+ }
3316
+ function reverseKnowledgeFilePlan(plan) {
3317
+ return plan.map((entry) => ({
3318
+ path: entry.path,
3319
+ beforeHash: entry.afterHash,
3320
+ afterHash: entry.beforeHash,
3321
+ ...entry.afterMode === void 0 ? {} : { beforeMode: entry.afterMode },
3322
+ ...entry.beforeMode === void 0 ? {} : { afterMode: entry.beforeMode }
3323
+ }));
3324
+ }
3325
+ async function ensureCandidateTransitionEvent(runDir, candidateRef, target) {
3326
+ if (await hasCandidateTransitionEvent(runDir, candidateRef, target)) return;
3295
3327
  await appendLedger(runDir, {
3296
- type: "candidate.promoted",
3328
+ type: target === "candidate" ? "candidate.promoted" : "candidate.restored",
3297
3329
  runId: candidateRef.runId,
3298
3330
  candidateId: candidateRef.candidateId,
3299
3331
  candidateHash: candidateRef.candidateHash,
@@ -3301,12 +3333,13 @@ async function ensurePromotionEvent(runDir, candidateRef) {
3301
3333
  promotionPlanHash: candidateRef.promotionPlanHash
3302
3334
  });
3303
3335
  }
3304
- async function hasPromotionEvent(runDir, candidateRef) {
3336
+ async function hasCandidateTransitionEvent(runDir, candidateRef, target) {
3337
+ const eventType = target === "candidate" ? "candidate.promoted" : "candidate.restored";
3305
3338
  let matched = false;
3306
3339
  for (const row of await loadKnowledgeImprovementEventsFromRun(runDir)) {
3307
- if (row.type !== "candidate.promoted" || row.candidateId !== candidateRef.candidateId) continue;
3340
+ if (row.type !== eventType || row.candidateId !== candidateRef.candidateId) continue;
3308
3341
  if (row.runId !== candidateRef.runId || row.candidateHash !== candidateRef.candidateHash || row.evidenceHash !== candidateRef.evidenceHash || row.promotionPlanHash !== candidateRef.promotionPlanHash) {
3309
- throw new Error("persisted knowledge promotion event conflicts with the approved candidate");
3342
+ throw new Error("persisted knowledge activation event conflicts with the approved candidate");
3310
3343
  }
3311
3344
  matched = true;
3312
3345
  }
@@ -5961,6 +5994,7 @@ export {
5961
5994
  resetRetrievalHoldoutRegistry,
5962
5995
  respondToIndustryMemoryBenchmarkSmokeCase,
5963
5996
  respondToIndustryRagBenchmarkSmokeCase,
5997
+ restoreKnowledgeCandidateBaseline,
5964
5998
  retrievalConfigFromSurface,
5965
5999
  retrievalConfigSurface,
5966
6000
  retrievalHoldoutConfigHash,