@tangle-network/agent-knowledge 1.11.1 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,15 +7,16 @@ This package turns raw sources and generated markdown knowledge into a versionab
7
7
  ## Contents
8
8
 
9
9
  - [Install](#install)
10
- - [Start here](#start-here) pick CLI vs programmatic
11
- - [CLI](#cli) `init` `source-add` `index` `search` `lint`
12
- - [Design](#design) the invariants (immutable sources, cited claims, deterministic graph)
13
- - [Benchmark harness](#benchmark-harness) BEIR/MTEB/qrels, RAG answer, hallucination, KB-improvement cases
14
- - [Agent-Eval integration](#agent-eval-integration) retrieval eval + readiness bundles + release reports
15
- - [Memory adapters](#memory-adapters) generic memory contract + Neo4j Agent Memory bridge
16
- - [Research loop](#research-loop) `runKnowledgeResearchLoop` + control-loop adapter
17
- - [Runtime integration](#runtime-integration) how agent runners plug into the pure KB loop
18
- - [Pluggable knowledge sources](#pluggable-knowledge-sources) live authorities eval re-runs
10
+ - [Start here](#start-here): pick CLI vs programmatic
11
+ - [Common uses](#common-uses): wiki, RAG, memory, new KBs, existing KBs, and parallel agents
12
+ - [CLI](#cli): `init` `source-add` `index` `search` `lint`
13
+ - [Design](#design): the invariants, including immutable sources, cited claims, and deterministic graph output
14
+ - [Benchmark harness](#benchmark-harness): BEIR/MTEB/qrels, RAG answer, hallucination, KB-improvement cases
15
+ - [Agent-Eval integration](#agent-eval-integration): retrieval eval, readiness bundles, and release reports
16
+ - [Memory adapters](#memory-adapters): generic memory contract plus Neo4j Agent Memory bridge
17
+ - [Research loop](#research-loop): `runKnowledgeResearchLoop` plus the control-loop adapter
18
+ - [Runtime integration](#runtime-integration): how agent runners plug into the pure KB loop
19
+ - [Pluggable knowledge sources](#pluggable-knowledge-sources): live authorities → eval re-runs
19
20
 
20
21
  ## Install
21
22
 
@@ -44,6 +45,18 @@ Two ways in, depending on what you're doing:
44
45
 
45
46
  Storage stays consumer-owned via `KbStore` (`MemoryKbStore`, `FileSystemKbStore`, or your own D1/Postgres). Every primitive below is source-grounded: claims cite immutable source records, and lint fails on un-grounded citations.
46
47
 
48
+ ## Common Uses
49
+
50
+ | Use case | What this package owns | Front door |
51
+ |---|---|---|
52
+ | LLM wiki or docs KB | Source records, cited markdown pages, lint, readiness scoring, candidate promotion | `improveKnowledgeBase` or `runKnowledgeResearchLoop` |
53
+ | RAG | Retrieval eval, source-span labels, answer quality checks, missing/stale/noisy-source diagnosis | `runRagKnowledgeImprovementLoop` |
54
+ | Memory DB | Adapter contract that turns memory hits into source-like evidence and benchmark rows | `/memory` plus `runMemoryAdapterBenchmark` |
55
+ | From scratch | Empty KB layout, source ingestion, write-block application, indexing, readiness checks | CLI `init` or `runKnowledgeResearchLoop` |
56
+ | Existing KB | Candidate workspace, resume state, base-hash conflict check, promotion only after evals pass | `improveKnowledgeBase` |
57
+ | Parallel agents | Per-run locks, isolated candidates, `promote: false` handoff, retry with the same `runId` | `improveKnowledgeBase` with runtime workers |
58
+ | One-call agent job | Runtime supervisor plus all KB mechanics above | `runKnowledgeImprovementJob` from `@tangle-network/agent-runtime/knowledge` |
59
+
47
60
  ## CLI
48
61
 
49
62
  ```bash
@@ -122,7 +135,7 @@ from `@tangle-network/agent-knowledge`.
122
135
  `rrfScore` are the raw reciprocal-rank-fusion value (typically 0.01–0.05);
123
136
  use them when intent matters or when fusing across queries.
124
137
  `normalizedScore` is the same value scaled into [0, 1] relative to the top
125
- hit *in this result set* (top hit = 1, others = score / topScore) use it
138
+ hit *in this result set* (top hit = 1, others = score / topScore). Use it
126
139
  when comparing against natural confidence thresholds. The normalization is
127
140
  within-set ranking, not a cross-query absolute confidence.
128
141
  - Release confidence uses `@tangle-network/agent-eval` release gates (`evaluateReleaseConfidence`) instead of reimplementing them.
@@ -229,7 +242,7 @@ This is the path for Neo4j Agent Memory, Mem0, Zep, Letta, Graphiti, a vector st
229
242
 
230
243
  ## Agent-Eval Integration
231
244
 
232
- Use `ragAnswerQualityJudge` or `createRagAnswerQualityHook` when the product already has answer traces and needs SOTA-style RAG scoring without rebuilding metrics.
245
+ Use `ragAnswerQualityJudge` or `createRagAnswerQualityHook` when the product already has answer traces and needs RAG answer scoring without rebuilding metrics.
233
246
  The built-in checks are deterministic and general; pass external scores from Ragas, DeepEval, TruLens, RAGChecker, or a custom evaluator when you want model-based judging.
234
247
 
235
248
  ```ts
@@ -500,13 +513,13 @@ with a differentiated worker/driver split over ONE knowledge base: the `worker`
500
513
  does primary research (discovers sources, proposes pages for the open gaps); the
501
514
  `driver` verifies each candidate source before it commits, optionally gap-fills
502
515
  with its own pass (`driverResearches: true`), and gates on the readiness check.
503
- Both are yours (no creds) the loop owns the deterministic mechanics (indexing,
516
+ Both are yours (no creds). The loop owns the deterministic mechanics (indexing,
504
517
  applying write blocks, scoring readiness) and stops once no blocking gap remains.
505
518
 
506
519
  Does the verifying driver actually earn its keep? See
507
520
  [docs/two-agent-research-ab.md](docs/two-agent-research-ab.md) for an equal-compute
508
521
  A/B (9 ML topics, `glm-5.2`): the two-agent loop admits ~2.33 fewer sources per topic
509
- at identical coverage though most of that win is de-duplication, not relevance
522
+ at identical coverage, though most of that win is de-duplication, not relevance
510
523
  filtering. Honest caveats and how to reproduce included.
511
524
 
512
525
  ```ts
@@ -544,7 +557,22 @@ await runTwoAgentResearchLoop({
544
557
 
545
558
  `agent-knowledge` owns knowledge state and measurement.
546
559
  It deliberately does not own an agent runner.
547
- Live agent orchestration belongs in `@tangle-network/agent-runtime`, which can call `improveKnowledgeBase` by passing an `updateKnowledge` callback:
560
+ Live agent orchestration belongs in `@tangle-network/agent-runtime`.
561
+ Use the one-call runtime job when you want agents, candidate workspaces, readiness checks, promotion, and spend measurement wired together:
562
+
563
+ ```ts
564
+ import { runKnowledgeImprovementJob } from '@tangle-network/agent-runtime/knowledge'
565
+
566
+ await runKnowledgeImprovementJob({
567
+ root: './kb',
568
+ goal: 'Build a grounded onboarding wiki for billing support',
569
+ readinessSpecs,
570
+ budget: { maxIterations: 8, maxTokens: 120_000, maxUsd: 10 },
571
+ backend,
572
+ })
573
+ ```
574
+
575
+ Use `improveKnowledgeBase` directly when your product already owns the agent runner and only needs the pure KB mechanics:
548
576
 
549
577
  ```ts
550
578
  import { improveKnowledgeBase } from '@tangle-network/agent-knowledge'
@@ -574,26 +602,26 @@ score = 0.4 · citation_density
574
602
  + 0.2 · gap_coverage
575
603
  ```
576
604
 
577
- The output preserves agent intelligence `items`, `citations`,
605
+ The output preserves agent intelligence: `items`, `citations`,
578
606
  `proposedWrites` are typed; `gaps`, `notes`, and any extras the agent
579
607
  emitted land in `raw` rather than getting dropped.
580
608
 
581
609
  ## Pluggable Knowledge Sources
582
610
 
583
611
  Static knowledge rots. Authorities like Cornell LII, the IRS, and state
584
- Secretaries of State change without warning a ruling vacates an FTC
612
+ Secretaries of State change without warning. A ruling vacates an FTC
585
613
  non-compete rule, a CFR section renumbers, a state replaces Beverly-Killea
586
614
  with RULLCA. The `@tangle-network/agent-knowledge/sources` subpath ships
587
615
  three primitives that bridge "live authority" → "eval re-runs":
588
616
 
589
- - `KnowledgeSource` pluggable contract (`fetch(opts) → KnowledgeFragment[]`).
617
+ - `KnowledgeSource`: pluggable contract (`fetch(opts) → KnowledgeFragment[]`).
590
618
  Every fragment carries `provenance` (URL, source-attested timestamp,
591
619
  jurisdiction, `verifiable` flag) and `dimensionHints` (which eval
592
620
  dimensions a change in this fragment should re-score).
593
- - `KnowledgeFreshnessStore` per-`(workspaceId, sourceId)` last-refresh
621
+ - `KnowledgeFreshnessStore`: per-`(workspaceId, sourceId)` last-refresh
594
622
  tracker. Filesystem adapter ships in-package; D1 / Postgres adapter
595
623
  scaffold is shipped as `createD1FreshnessStoreStub(adapter)`.
596
- - `detectChanges(prev, next)` diffs two fragment snapshots, emits
624
+ - `detectChanges(prev, next)`: diffs two fragment snapshots, emits
597
625
  `KnowledgeChange[]` tagged with the affected eval dimensions so a cron
598
626
  scheduler knows exactly which campaigns to re-run.
599
627
 
@@ -623,7 +651,7 @@ const sources = [
623
651
  publications: ['p15', 'p17', 'p463'],
624
652
  revenueProcedures: [],
625
653
  }),
626
- // Generic state SOS adapter one config per state you need tracked.
654
+ // Generic state SOS adapter: one config per state you need tracked.
627
655
  createStateSosSource({
628
656
  state: 'CA',
629
657
  baseUrl: 'https://www.sos.ca.gov',
package/dist/index.d.ts CHANGED
@@ -937,6 +937,42 @@ interface KnowledgeDiscoveryDispatcher {
937
937
  signal?: AbortSignal;
938
938
  }): Promise<DiscoveryResult[]>;
939
939
  }
940
+ type DiscoveryLoopStopReason = 'complete' | 'max-rounds' | 'max-tasks' | 'aborted';
941
+ interface DiscoveryLoopRound {
942
+ round: number;
943
+ tasks: DiscoveryTask[];
944
+ results: DiscoveryResult[];
945
+ queuedFollowUps: DiscoveryTask[];
946
+ }
947
+ interface DiscoveryLoopResult {
948
+ stopReason: DiscoveryLoopStopReason;
949
+ tasksDispatched: number;
950
+ results: DiscoveryResult[];
951
+ rounds: DiscoveryLoopRound[];
952
+ /** Tasks retained, not dropped, when a configured limit stops the loop. */
953
+ pendingTasks: DiscoveryTask[];
954
+ /** Structurally identical task identities ignored to prevent cycles. */
955
+ duplicateTaskIds: string[];
956
+ }
957
+ interface RunDiscoveryLoopOptions {
958
+ dispatcher: KnowledgeDiscoveryDispatcher;
959
+ initialTasks: readonly DiscoveryTask[];
960
+ /** Maximum follow-up depth including the initial dispatch. Default 3. */
961
+ maxRounds?: number;
962
+ /** Maximum tasks dispatched across all rounds. Default 24. */
963
+ maxTasks?: number;
964
+ /** Forwarded to the dispatcher. Default 4. */
965
+ concurrency?: number;
966
+ signal?: AbortSignal;
967
+ onRound?: (round: DiscoveryLoopRound) => Promise<void> | void;
968
+ }
969
+ /**
970
+ * Dispatch discovery tasks and recursively pursue worker-proposed follow-ups.
971
+ *
972
+ * The runner owns only bounded scheduling and accounting. Workers own search,
973
+ * source verification, and domain-specific candidate shapes.
974
+ */
975
+ declare function runDiscoveryLoop(options: RunDiscoveryLoopOptions): Promise<DiscoveryLoopResult>;
940
976
  declare function createLocalDiscoveryDispatcher(worker: KnowledgeDiscoveryWorker): KnowledgeDiscoveryDispatcher;
941
977
 
942
978
  interface KnowledgeEventQuery {
@@ -2480,4 +2516,4 @@ declare function normalizeLinkTarget(target: string): string;
2480
2516
  declare function isSafeKnowledgePath(path: string, allowedPrefixes?: string[]): boolean;
2481
2517
  declare function parseKnowledgeWriteBlocks(text: string, allowedPrefixes?: string[]): KnowledgeWriteParseResult;
2482
2518
 
2483
- 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 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 KnowledgeImprovementEvaluationInput, type KnowledgeImprovementEvaluator, type KnowledgeImprovementLifecycleRecord, type KnowledgeImprovementMetric, type KnowledgeImprovementOptions, type KnowledgeImprovementResult, type KnowledgeImprovementRetrievalOptions, type KnowledgeImprovementRunState, 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 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 RejectedSource, type ResearchContribution, type ResearchDriver, type ResearchDrivingDriver, type ResearchDrivingDriverOptions, type ResearchDrivingState, type ResearchDrivingSteer, type ResearchSourceProposal, type ResearchWorker, RetrievalConfig, type RouterClient, RouterError, type RouterUsage, 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 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, gradeCompanyAgainstText, gradeFactAgainstText, groundClaimInText, hashKnowledgeBase, improveKnowledgeBase, initKnowledgeBase, inspectKnowledgeIndex, investmentThesisSet, isSafeKnowledgePath, isScaffoldPath, kbIndexToText, knowledgeImprovementRunDir, knowledgeImprovementRunId, knowledgeReleaseReport, layoutFor, lensDistribution, lintKnowledgeIndex, loadKnowledgeImprovementState, loadKnowledgePages, loadSourceRegistry, materialFactsSurfaced, materialFactsSurfacedInText, mediaTypeFor, normalizeExternalRagScores, normalizeLinkTarget, parseFrontmatter, parseKnowledgeWriteBlocks, proposeFromFinding, proposeFromFindings, ragAnswerQualityJudge, reciprocalRankFusion, runInvestmentThesisTask, runKnowledgeResearchLoop, runRagKnowledgeImprovementLoop, runTwoAgentResearchLoop, runVerifiedResearchLoop, scoreKnowledgeBaseIndex, scoreRagAnswerArtifact, searchKnowledge, sha256, slugify, sourceMatchesGaps, sourceRegistryPath, stableId, stripFrontmatter, textSourceAdapter, thesisReadinessSpecs, toDeepEvalTestCases, toRagCheckerRecords, toRagasEvaluationRows, toTruLensRecords, tokenizeQuery, totalMaterialFacts, triageSource, validateKnowledgeIndex, withCitedClaim, writeJson, writeKnowledgeIndex, writeSourceRegistry };
2519
+ 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 KnowledgeImprovementEvaluationInput, type KnowledgeImprovementEvaluator, type KnowledgeImprovementLifecycleRecord, type KnowledgeImprovementMetric, type KnowledgeImprovementOptions, type KnowledgeImprovementResult, type KnowledgeImprovementRetrievalOptions, type KnowledgeImprovementRunState, 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 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 RejectedSource, type ResearchContribution, type ResearchDriver, type ResearchDrivingDriver, type ResearchDrivingDriverOptions, type ResearchDrivingState, type ResearchDrivingSteer, type ResearchSourceProposal, type ResearchWorker, RetrievalConfig, 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 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, gradeCompanyAgainstText, gradeFactAgainstText, groundClaimInText, hashKnowledgeBase, improveKnowledgeBase, initKnowledgeBase, inspectKnowledgeIndex, investmentThesisSet, isSafeKnowledgePath, isScaffoldPath, kbIndexToText, knowledgeImprovementRunDir, knowledgeImprovementRunId, knowledgeReleaseReport, layoutFor, lensDistribution, lintKnowledgeIndex, loadKnowledgeImprovementState, loadKnowledgePages, loadSourceRegistry, materialFactsSurfaced, materialFactsSurfacedInText, mediaTypeFor, normalizeExternalRagScores, normalizeLinkTarget, parseFrontmatter, parseKnowledgeWriteBlocks, proposeFromFinding, proposeFromFindings, ragAnswerQualityJudge, reciprocalRankFusion, runDiscoveryLoop, runInvestmentThesisTask, runKnowledgeResearchLoop, runRagKnowledgeImprovementLoop, runTwoAgentResearchLoop, runVerifiedResearchLoop, scoreKnowledgeBaseIndex, scoreRagAnswerArtifact, searchKnowledge, sha256, slugify, sourceMatchesGaps, sourceRegistryPath, stableId, stripFrontmatter, textSourceAdapter, thesisReadinessSpecs, toDeepEvalTestCases, toRagCheckerRecords, toRagasEvaluationRows, toTruLensRecords, tokenizeQuery, totalMaterialFacts, triageSource, validateKnowledgeIndex, withCitedClaim, writeJson, writeKnowledgeIndex, writeSourceRegistry };
package/dist/index.js CHANGED
@@ -1006,6 +1006,71 @@ function createCollectionResearchDriver() {
1006
1006
  }
1007
1007
 
1008
1008
  // src/discovery.ts
1009
+ import { isDeepStrictEqual } from "util";
1010
+ async function runDiscoveryLoop(options) {
1011
+ const maxRounds = positiveInteger(options.maxRounds ?? 3, "maxRounds");
1012
+ const maxTasks = positiveInteger(options.maxTasks ?? 24, "maxTasks");
1013
+ const concurrency = positiveInteger(options.concurrency ?? 4, "concurrency");
1014
+ const known = /* @__PURE__ */ new Map();
1015
+ const pending = [];
1016
+ const duplicateTaskIds = /* @__PURE__ */ new Set();
1017
+ enqueueTasks(options.initialTasks, known, pending, duplicateTaskIds);
1018
+ const rounds = [];
1019
+ const results = [];
1020
+ let tasksDispatched = 0;
1021
+ let aborted = false;
1022
+ while (pending.length > 0 && rounds.length < maxRounds && tasksDispatched < maxTasks) {
1023
+ if (options.signal?.aborted) {
1024
+ aborted = true;
1025
+ break;
1026
+ }
1027
+ const capacity = maxTasks - tasksDispatched;
1028
+ const tasks = pending.splice(0, capacity);
1029
+ let dispatched;
1030
+ try {
1031
+ dispatched = orderCompleteDispatch(
1032
+ tasks,
1033
+ await options.dispatcher.dispatch(tasks, {
1034
+ concurrency,
1035
+ signal: options.signal
1036
+ })
1037
+ );
1038
+ } catch (cause) {
1039
+ if (!options.signal?.aborted) throw cause;
1040
+ pending.unshift(...tasks);
1041
+ aborted = true;
1042
+ break;
1043
+ }
1044
+ tasksDispatched += tasks.length;
1045
+ results.push(...dispatched);
1046
+ const queuedFollowUps = [];
1047
+ for (const result of dispatched) {
1048
+ enqueueTasks(result.followUpTasks ?? [], known, queuedFollowUps, duplicateTaskIds);
1049
+ }
1050
+ pending.push(...queuedFollowUps);
1051
+ const round2 = {
1052
+ round: rounds.length + 1,
1053
+ tasks,
1054
+ results: dispatched,
1055
+ queuedFollowUps
1056
+ };
1057
+ rounds.push(round2);
1058
+ await options.onRound?.(round2);
1059
+ if (options.signal?.aborted) {
1060
+ aborted = true;
1061
+ break;
1062
+ }
1063
+ }
1064
+ const stopReason = aborted ? "aborted" : pending.length === 0 ? "complete" : tasksDispatched >= maxTasks ? "max-tasks" : "max-rounds";
1065
+ return {
1066
+ stopReason,
1067
+ tasksDispatched,
1068
+ results,
1069
+ rounds,
1070
+ pendingTasks: pending,
1071
+ duplicateTaskIds: [...duplicateTaskIds]
1072
+ };
1073
+ }
1009
1074
  function createLocalDiscoveryDispatcher(worker) {
1010
1075
  return {
1011
1076
  async dispatch(tasks, options = {}) {
@@ -1020,12 +1085,55 @@ function createLocalDiscoveryDispatcher(worker) {
1020
1085
  }
1021
1086
  }
1022
1087
  await Promise.all(Array.from({ length: Math.min(concurrency, tasks.length) }, runNext));
1023
- return results.sort(
1024
- (a, b) => tasks.findIndex((task) => task.id === a.taskId) - tasks.findIndex((task) => task.id === b.taskId)
1025
- );
1088
+ return orderCompleteDispatch(tasks, results);
1026
1089
  }
1027
1090
  };
1028
1091
  }
1092
+ function enqueueTasks(tasks, known, destination, duplicateTaskIds) {
1093
+ for (const task of tasks) {
1094
+ assertTask(task);
1095
+ const prior = known.get(task.id);
1096
+ if (!prior) {
1097
+ known.set(task.id, task);
1098
+ destination.push(task);
1099
+ continue;
1100
+ }
1101
+ if (!isDeepStrictEqual(prior, task)) {
1102
+ throw new Error(`Discovery task id '${task.id}' refers to conflicting tasks`);
1103
+ }
1104
+ duplicateTaskIds.add(task.id);
1105
+ }
1106
+ }
1107
+ function assertTask(task) {
1108
+ if (!task.id.trim()) throw new Error("Discovery task id must not be empty");
1109
+ if (!task.goal.trim()) throw new Error(`Discovery task '${task.id}' goal must not be empty`);
1110
+ }
1111
+ function orderCompleteDispatch(tasks, results) {
1112
+ const order = new Map(tasks.map((task, index) => [task.id, index]));
1113
+ const received = /* @__PURE__ */ new Set();
1114
+ for (const result of results) {
1115
+ if (!order.has(result.taskId)) {
1116
+ throw new Error(`Discovery dispatcher returned unknown task '${result.taskId}'`);
1117
+ }
1118
+ if (received.has(result.taskId)) {
1119
+ throw new Error(`Discovery dispatcher returned task '${result.taskId}' more than once`);
1120
+ }
1121
+ received.add(result.taskId);
1122
+ }
1123
+ const missing = tasks.filter((task) => !received.has(task.id)).map((task) => task.id);
1124
+ if (missing.length > 0) {
1125
+ throw new Error(`Discovery dispatcher omitted tasks: ${missing.join(", ")}`);
1126
+ }
1127
+ return [...results].sort(
1128
+ (a, b) => order.get(a.taskId) - order.get(b.taskId)
1129
+ );
1130
+ }
1131
+ function positiveInteger(value, name) {
1132
+ if (!Number.isInteger(value) || value < 1) {
1133
+ throw new Error(`Discovery loop ${name} must be a positive integer`);
1134
+ }
1135
+ return value;
1136
+ }
1029
1137
 
1030
1138
  // src/eval-readiness.ts
1031
1139
  import {
@@ -4794,6 +4902,7 @@ export {
4794
4902
  retrievalHoldoutConfigHash,
4795
4903
  retrievalParameterSweepProposer,
4796
4904
  retrievalRecallJudge,
4905
+ runDiscoveryLoop,
4797
4906
  runInvestmentThesisTask,
4798
4907
  runKnowledgeBenchmarkSuite,
4799
4908
  runKnowledgeResearchLoop,