@tangle-network/agent-knowledge 17.1.10 → 19.0.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.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["exceedsCostCeiling","stopwords","contentWords","stopwords","nonEmpty","nonEmpty","hostOf"],"sources":["../src/web-research-worker.ts","../src/adaptive-driver.ts","../src/knowledge-state-scope.ts","../src/kb-improvement/contracts.ts","../src/kb-improvement/state.ts","../src/kb-improvement/activation.ts","../src/rag-answer-evidence.ts","../src/claim-grounding.ts","../src/rag-eval/answer.ts","../src/rag-eval/providers.ts","../src/rag-eval/scoring.ts","../src/rag-eval/calibration.ts","../src/rag-eval/knowledge-base.ts","../src/rag-optimization.ts","../src/events.ts","../src/eval-readiness.ts","../src/readiness-helpers.ts","../src/research-loop.ts","../src/retrieval-optimization.ts","../src/rag-improvement-phases.ts","../src/rag-improvement-loop.ts","../src/kb-improvement/workspace.ts","../src/kb-improvement/transition.ts","../src/kb-improvement/evaluation.ts","../src/kb-improvement/run.ts","../src/kb-improvement/optimization.ts","../src/kb-improvement/selected-candidate.ts","../src/agent-candidate.ts","../src/changes.ts","../src/chunking.ts","../src/citation-lint.ts","../src/collection-research-driver.ts","../src/discovery.ts","../src/filesystem-search-provider.ts","../src/freshness.ts","../src/invalidation-propagation.ts","../src/investment-thesis-set.ts","../src/material-facts-metric.ts","../src/verified-research-loop.ts","../src/investment-thesis-task.ts","../src/knowledge-brief.ts","../src/knowledge-visibility.ts","../src/knowledge-use-receipts.ts","../src/knowledge-tools.ts","../src/promotion.ts","../src/propose-from-finding.ts","../src/readiness-check.ts","../src/relation-graph.ts","../src/release.ts","../src/research-driving-driver.ts"],"sourcesContent":["/**\n * Real web-research worker + verifying driver for `runVerifiedResearchLoop`.\n *\n * This is the GENERAL, any-topic implementation behind the two-agent research\n * loop's live arm. Given the open knowledge gaps the readiness gate surfaces,\n * the worker:\n *\n * 1. asks an LLM (glm-5.2 by default) to turn each gap into focused web\n * search queries,\n * 2. runs a REAL web search over the Tangle router (`POST /v1/search` — the\n * same endpoint `tcloud mcp`'s `web_search` tool forwards to), so there is\n * no hardcoded corpus,\n * 3. fetches the top results with the repo's polite, cached `politeFetch` and\n * reduces each page to text with `htmlToText`,\n * 4. proposes the readable, verifiable pages as `ResearchSourceProposal`s plus\n * a `buildPages` that writes citing `knowledge/*.md` pages from the sources\n * the driver accepts.\n *\n * The verifying DRIVER is the differentiated role from the two-agent loop: a\n * second LLM pass that judges each fetched source's on-topic relevance to the\n * goal + open gaps and rejects off-topic / spam / already-covered material. The\n * worker ADDS; the driver GATES. Together they build a cleaner knowledge base\n * than a single agent at the same compute budget.\n *\n * Dependency-free on purpose: it talks to the router over `fetch` directly with\n * the published OpenAI-compatible chat shape and the `/v1/search` shape, so it\n * works whether or not the `tcloud` CLI is installed. Point it at any router by\n * passing `baseUrl`; supply the key via `apiKey` or `TANGLE_API_KEY`.\n */\n\nimport { htmlToText } from './sources/html'\nimport { politeFetch } from './sources/http'\nimport type { SourceRecord } from './types'\nimport type {\n KnowledgeGap,\n ResearchContribution,\n ResearchDriver,\n ResearchSourceProposal,\n ResearchWorker,\n SourceVerdict,\n SourceVerificationContext,\n WorkerResearchContext,\n} from './verified-research-loop'\n\n/** Default router model. Plain id (no namespace) — see CLAUDE/creds notes. */\nconst DEFAULT_MODEL = 'glm-5.2'\n/** Default router base. */\nconst DEFAULT_BASE_URL = 'https://router.tangle.tools/v1'\n/**\n * glm-5.2 spends its first tokens on hidden `reasoning_content`; below ~1200\n * output tokens it returns EMPTY visible content. Floor every call so a\n * reasoning model never silently yields nothing. (Verified creds note.)\n */\nconst MIN_MAX_TOKENS = 1200\n\n/** One live web result, as the router's `/v1/search` returns it. */\nexport interface WebSearchHit {\n title: string\n url: string\n snippet?: string\n}\n\n/**\n * The two router capabilities the worker/driver need. Injectable so tests can\n * stub the network; the default talks to the live Tangle router over `fetch`.\n */\nexport interface RouterClient {\n /** Live web search — returns title/url/snippet hits. */\n search(query: string, opts?: { maxResults?: number }): Promise<WebSearchHit[]>\n /** Chat completion — returns the assistant message's visible text. */\n chat(\n messages: { role: 'system' | 'user'; content: string }[],\n maxTokens?: number,\n ): Promise<string>\n /** Cumulative cost (chat + search) since this client was created. */\n usage(): RouterUsage\n}\n\n/**\n * Cumulative router cost — the per-arm signal the A/B reports ALONGSIDE quality,\n * so \"2.3 fewer sources\" can be read against the token/$/latency it cost. A\n * two-agent round is one worker pass plus N `verifySource` LLM calls; counting\n * each call here is what surfaces that the two-agent loop spends more inference\n * than its \"equal passes\" budget implies.\n */\nexport interface RouterUsage {\n chatCalls: number\n searchCalls: number\n promptTokens: number\n completionTokens: number\n usd: number\n wallMs: number\n}\n\nexport interface TangleRouterOptions {\n /** Router base URL. Defaults to `https://router.tangle.tools/v1`. */\n baseUrl?: string\n /** Bearer key. Defaults to `process.env.TANGLE_API_KEY`. */\n apiKey?: string\n /** Chat model id. Defaults to `glm-5.2`. */\n model?: string\n /** Optional preferred search provider (exa | you | perplexity | …). */\n searchProvider?: string\n /**\n * Retries on a TRANSIENT upstream status (502/503/504/429) with exponential\n * backoff. Default 4. A 4xx that isn't 429, and a 401, are NOT retried — those\n * are not transient. After the budget is exhausted the call still fails loud\n * with the original `RouterError`, so the fail-closed contract holds; this only\n * stops a single upstream-capacity blip from voiding a whole multi-topic run.\n */\n maxRetries?: number\n /** Base backoff in ms (doubled each retry, ±25% jitter). Default 1500. */\n retryBaseMs?: number\n signal?: AbortSignal\n}\n\n/** Transient upstream statuses worth a retry (capacity / rate-limit / gateway). */\nconst transientStatuses = new Set([429, 502, 503, 504])\n\n/**\n * POST with bounded exponential backoff on transient upstream statuses. Returns\n * the first `res.ok` response, or the LAST response (so the caller throws the\n * real status). A non-transient failure returns immediately — only 502/503/504/\n * 429 are retried. Aborts propagate at once.\n */\nasync function fetchWithRetry(\n url: string,\n init: RequestInit,\n opts: { maxRetries: number; retryBaseMs: number; signal?: AbortSignal },\n): Promise<Response> {\n let lastRes: Response | undefined\n for (let attempt = 0; attempt <= opts.maxRetries; attempt += 1) {\n if (opts.signal?.aborted) throw new RouterError(0, 'aborted')\n const res = await fetch(url, init)\n if (res.ok || !transientStatuses.has(res.status)) return res\n lastRes = res\n if (attempt === opts.maxRetries) break\n // Drain the body so the socket frees before we wait.\n await res.text().catch(() => '')\n const backoff = opts.retryBaseMs * 2 ** attempt\n const jitter = backoff * (0.75 + Math.random() * 0.5)\n await new Promise((resolve) => setTimeout(resolve, jitter))\n }\n // Exhausted: hand back the last transient response so the caller fails loud\n // with its real status.\n if (lastRes) return lastRes\n throw new RouterError(0, 'fetchWithRetry produced no response')\n}\n\n/** A small error so a failed router call fails loud rather than returning junk. */\nexport class RouterError extends Error {\n constructor(\n public readonly status: number,\n message: string,\n ) {\n super(`router ${status}: ${message}`)\n this.name = 'RouterError'\n }\n}\n\n/**\n * Build a dependency-free Tangle router client over `fetch`. This is the same\n * wire surface the `tcloud` SDK + `tcloud mcp` use (`/v1/search` for web search,\n * `/v1/chat/completions` for chat) so it needs no CLI installed.\n */\nexport function createTangleRouterClient(options: TangleRouterOptions = {}): RouterClient {\n const baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, '')\n const apiKey = options.apiKey ?? process.env.TANGLE_API_KEY\n if (!apiKey) {\n throw new RouterError(401, 'no TANGLE_API_KEY (pass apiKey or set the env var)')\n }\n const model = options.model ?? DEFAULT_MODEL\n const maxRetries = Math.max(0, options.maxRetries ?? 4)\n const retryBaseMs = Math.max(1, options.retryBaseMs ?? 1500)\n const headers = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n }\n\n // glm-5.2 pricing (USD per token) + a cumulative accumulator. Read via usage().\n const price = { prompt: 0.95 / 1_000_000, completion: 3.0 / 1_000_000 }\n const acc: RouterUsage = {\n chatCalls: 0,\n searchCalls: 0,\n promptTokens: 0,\n completionTokens: 0,\n usd: 0,\n wallMs: 0,\n }\n\n return {\n async search(query, opts) {\n const t0 = Date.now()\n const res = await fetchWithRetry(\n `${baseUrl}/search`,\n {\n method: 'POST',\n headers,\n signal: options.signal,\n body: JSON.stringify({\n query,\n ...(options.searchProvider ? { provider: options.searchProvider } : {}),\n ...(opts?.maxResults != null ? { maxResults: opts.maxResults } : {}),\n }),\n },\n { maxRetries, retryBaseMs, signal: options.signal },\n )\n acc.searchCalls += 1\n acc.wallMs += Date.now() - t0\n if (!res.ok) {\n throw new RouterError(res.status, await res.text().catch(() => res.statusText))\n }\n const body = (await res.json()) as { data?: WebSearchHit[] }\n return (body.data ?? [])\n .filter((hit) => typeof hit?.url === 'string' && hit.url.length > 0)\n .map((hit) => ({ title: hit.title ?? hit.url, url: hit.url, snippet: hit.snippet }))\n },\n async chat(messages, maxTokens) {\n // Reasoning-model floor: never let glm-5.2 spend the whole budget on\n // hidden reasoning and return empty visible content.\n const max_tokens = Math.max(MIN_MAX_TOKENS, maxTokens ?? MIN_MAX_TOKENS)\n const t0 = Date.now()\n const res = await fetchWithRetry(\n `${baseUrl}/chat/completions`,\n {\n method: 'POST',\n headers,\n signal: options.signal,\n body: JSON.stringify({ model, messages, max_tokens, temperature: 0.2, stream: false }),\n },\n { maxRetries, retryBaseMs, signal: options.signal },\n )\n if (!res.ok) {\n throw new RouterError(res.status, await res.text().catch(() => res.statusText))\n }\n const body = (await res.json()) as {\n choices?: { message?: { content?: string } }[]\n usage?: { prompt_tokens?: number; completion_tokens?: number }\n }\n const promptTokens = body.usage?.prompt_tokens ?? 0\n const completionTokens = body.usage?.completion_tokens ?? 0\n acc.chatCalls += 1\n acc.promptTokens += promptTokens\n acc.completionTokens += completionTokens\n acc.usd += promptTokens * price.prompt + completionTokens * price.completion\n acc.wallMs += Date.now() - t0\n return body.choices?.[0]?.message?.content ?? ''\n },\n usage() {\n return { ...acc }\n },\n }\n}\n\nexport interface WebResearchWorkerOptions {\n /** Router client. Defaults to a live Tangle router client from env creds. */\n router?: RouterClient\n router_options?: TangleRouterOptions\n /** Max search queries the LLM may form per gap. Default 2. */\n queriesPerGap?: number\n /** Max web results fetched per query. Default 3. */\n resultsPerQuery?: number\n /** Hard cap on sources proposed per round (across all gaps). Default 6. */\n maxSourcesPerRound?: number\n /** Disk cache dir for `politeFetch`. Optional; speeds repeat runs. */\n cacheDir?: string\n /** Minimum readable text length to keep a fetched page. Default 200. */\n minTextChars?: number\n /** Max chars of page text stored per source (keeps pages bounded). Default 4000. */\n maxTextChars?: number\n}\n\n/** Resolve the router client lazily so a worker with an injected client never reads env. */\nfunction resolveRouter(opts: {\n router?: RouterClient\n router_options?: TangleRouterOptions\n}): RouterClient {\n return opts.router ?? createTangleRouterClient(opts.router_options)\n}\n\n/**\n * The real web-research worker. Conforms to the loop's `ResearchWorker`\n * contract: given the open gaps, it returns the sources it found plus a\n * `buildPages` that emits citing pages from the sources the driver accepted.\n */\nexport function createWebResearchWorker(options: WebResearchWorkerOptions = {}): ResearchWorker {\n const queriesPerGap = Math.max(1, options.queriesPerGap ?? 2)\n const resultsPerQuery = Math.max(1, options.resultsPerQuery ?? 3)\n const maxSourcesPerRound = Math.max(1, options.maxSourcesPerRound ?? 6)\n const minTextChars = Math.max(1, options.minTextChars ?? 200)\n const maxTextChars = Math.max(minTextChars, options.maxTextChars ?? 4000)\n\n return async (ctx: WorkerResearchContext): Promise<ResearchContribution> => {\n const router = resolveRouter(options)\n // Target the BLOCKING gaps first; fall back to all gaps if none are blocking.\n const targetGaps = ctx.gaps.filter((gap) => gap.blocking)\n const gaps = targetGaps.length > 0 ? targetGaps : ctx.gaps\n if (gaps.length === 0) {\n return { sources: [], notes: 'no open gaps to research' }\n }\n\n const queries = await formSearchQueries(router, ctx, gaps, queriesPerGap)\n const proposals: ResearchSourceProposal[] = []\n const seenUris = new Set<string>()\n\n for (const query of queries) {\n if (proposals.length >= maxSourcesPerRound) break\n if (ctx.signal?.aborted) break\n let hits: WebSearchHit[]\n try {\n hits = await router.search(query, { maxResults: resultsPerQuery })\n } catch (error) {\n // A single failed query must not sink the round — record nothing, move on.\n if ((error as { name?: string }).name === 'AbortError') break\n continue\n }\n for (const hit of hits) {\n if (proposals.length >= maxSourcesPerRound) break\n if (seenUris.has(hit.url)) continue\n const fetched = await politeFetch(hit.url, {\n signal: ctx.signal,\n cacheDir: options.cacheDir,\n })\n if (!fetched.verifiable) continue\n const text = htmlToText(fetched.body).slice(0, maxTextChars)\n if (text.length < minTextChars) continue\n seenUris.add(hit.url)\n proposals.push({\n uri: hit.url,\n title: hit.title || hit.url,\n text,\n // We just fetched + verified this page, so stamp `lastVerifiedAt` with\n // fetch time. Do NOT set `validUntil`: a live page has no inherent\n // future expiry, and the readiness freshness check treats any\n // `validUntil <= now` as EXPIRED (score 0). The page's `Last-Modified`\n // is a PAST date, so writing it here would mark every real source stale\n // and zero out coverage. Record it as provenance metadata instead.\n lastVerifiedAt: fetched.fetchedAt,\n metadata: {\n discoveredVia: query,\n snippet: hit.snippet ?? '',\n goal: ctx.goal,\n sourceUpdatedAt: fetched.sourceUpdatedAt,\n },\n })\n }\n }\n\n return {\n sources: proposals,\n buildPages: buildCitingPages(proposals),\n notes: `web-research worker: ${queries.length} queries → ${proposals.length} fetched sources`,\n }\n }\n}\n\n/**\n * Ask the LLM to turn the open gaps into focused web search queries. Falls back\n * to the gap's own readiness query if the model returns nothing parseable, so a\n * model hiccup degrades to a sane search rather than an empty round.\n */\nasync function formSearchQueries(\n router: RouterClient,\n ctx: WorkerResearchContext,\n gaps: KnowledgeGap[],\n queriesPerGap: number,\n): Promise<string[]> {\n const gapLines = gaps\n .map((gap, i) => `${i + 1}. ${gap.description} (readiness query: \"${gap.query}\")`)\n .join('\\n')\n const want = gaps.length * queriesPerGap\n const system =\n 'You are a research librarian. Turn knowledge gaps into precise web search queries that will ' +\n 'surface authoritative primary sources (papers, docs, standards, official pages). ' +\n 'Return ONLY a JSON array of query strings, no prose.'\n const user = [\n `Research goal: ${ctx.goal}`,\n ctx.steer ? `Steer from the coordinator:\\n${ctx.steer}` : '',\n `Open knowledge gaps:\\n${gapLines}`,\n `Return up to ${want} search query strings as a JSON array (e.g. [\"query one\",\"query two\"]).`,\n ]\n .filter(Boolean)\n .join('\\n\\n')\n\n let raw = ''\n try {\n raw = await router.chat(\n [\n { role: 'system', content: system },\n { role: 'user', content: user },\n ],\n MIN_MAX_TOKENS,\n )\n } catch {\n raw = ''\n }\n const parsed = parseQueryList(raw)\n const fromLlm = parsed.slice(0, want)\n if (fromLlm.length > 0) return dedupeStrings(fromLlm)\n // Degrade to the readiness queries themselves — still a real search.\n return dedupeStrings(gaps.map((gap) => gap.query || gap.description))\n}\n\n/** Parse a JSON array of query strings, tolerant of code fences / surrounding prose. */\nfunction parseQueryList(raw: string): string[] {\n const text = raw.trim()\n if (!text) return []\n const candidates: string[] = []\n // Prefer a fenced or bare JSON array.\n const arrayMatch = text.match(/\\[[\\s\\S]*\\]/)\n if (arrayMatch) {\n try {\n const arr = JSON.parse(arrayMatch[0]) as unknown[]\n for (const item of arr)\n if (typeof item === 'string' && item.trim()) candidates.push(item.trim())\n } catch {\n /* fall through to line parsing */\n }\n }\n if (candidates.length === 0) {\n for (const line of text.split('\\n')) {\n const cleaned = line\n .replace(/^\\s*(?:[-*]|\\d+[.)])\\s*/, '')\n .replace(/^[\"']|[\"']$/g, '')\n .trim()\n if (cleaned && cleaned.length > 2 && !cleaned.startsWith('{')) candidates.push(cleaned)\n }\n }\n return candidates\n}\n\nfunction dedupeStrings(values: string[]): string[] {\n const seen = new Set<string>()\n const out: string[] = []\n for (const value of values) {\n const key = value.toLowerCase().trim()\n if (key && !seen.has(key)) {\n seen.add(key)\n out.push(value.trim())\n }\n }\n return out\n}\n\n/**\n * Build the curated `knowledge/*.md` pages from the sources the driver accepted.\n * Each page cites the registered source by its assigned `record.id` (matched back\n * to the proposal via `metadata.originalUri`, which `addSourceText` stashes).\n */\nfunction buildCitingPages(\n proposals: ResearchSourceProposal[],\n): (acceptedSources: SourceRecord[]) => string | undefined {\n return (acceptedSources) => {\n if (acceptedSources.length === 0) return undefined\n const blocks = acceptedSources.map((record) => {\n const proposal = proposals.find((p) => p.uri === record.metadata?.originalUri)\n const uri = proposal?.uri ?? record.id\n const slug =\n uri\n .replace(/^https?:\\/\\//, '')\n .replace(/[^a-z0-9]+/gi, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 120) || record.id\n const title = proposal?.title ?? record.id\n const body = proposal?.text ?? ''\n return [\n `---FILE: knowledge/${slug}.md---`,\n '---',\n `title: ${escapeYaml(title)}`,\n `sources: [\"${record.id}\"]`,\n `source_url: ${uri}`,\n '---',\n `# ${title}`,\n '',\n body,\n '',\n `Source: ${uri}`,\n '---END FILE---',\n ].join('\\n')\n })\n return blocks.join('\\n')\n }\n}\n\nfunction escapeYaml(value: string): string {\n // Keep the frontmatter line single-valued and safe: collapse newlines, strip\n // quotes that would break the scalar.\n return value\n .replace(/[\\r\\n]+/g, ' ')\n .replace(/\"/g, \"'\")\n .trim()\n}\n\nexport interface VerifyingDriverOptions {\n router?: RouterClient\n router_options?: TangleRouterOptions\n /**\n * When the LLM verdict can't be parsed, default to REJECT (fail-closed) so a\n * model hiccup never poisons the KB with an unverified source. Set `true` to\n * accept-on-parse-failure only if you have a reason to. Default false.\n */\n acceptOnParseFailure?: boolean\n}\n\n/**\n * The verifying driver: a real LLM pass that judges each candidate source's\n * on-topic relevance to the goal + open gaps and whether it duplicates material\n * already accepted this round. This is the differentiated coordinator role — it\n * GATES the worker's additions; it adds nothing itself.\n *\n * The loop already dedups exact-uri duplicates and only calls this on genuinely\n * new candidates, so the verifier focuses on relevance + near-duplicate\n * judgement, not bookkeeping.\n */\nexport function createVerifyingResearchDriver(\n options: VerifyingDriverOptions = {},\n): ResearchDriver {\n const acceptOnParseFailure = options.acceptOnParseFailure ?? false\n return {\n async verifySource(\n source: ResearchSourceProposal,\n ctx: SourceVerificationContext,\n ): Promise<SourceVerdict> {\n const router = resolveRouter(options)\n const gapLines = ctx.gaps\n .map((gap) => `- ${gap.description} (query: \"${gap.query}\")`)\n .join('\\n')\n const acceptedTitles = ctx.acceptedThisRound\n .map((accepted) => `- ${accepted.title ?? accepted.uri}`)\n .join('\\n')\n const excerpt = source.text.slice(0, 1500)\n const system =\n 'You verify whether a fetched web source belongs in a curated knowledge base. ' +\n 'Accept a source ONLY if it is genuinely on-topic for the research goal and helps close ' +\n 'one of the open gaps, AND it is not a near-duplicate of an already-accepted source. ' +\n 'Reject spam, listicles, off-topic pages, marketing, and near-duplicates. ' +\n 'Respond with ONLY a JSON object: {\"accept\": true|false, \"reason\": \"<short reason>\"}.'\n const user = [\n `Research goal: ${ctx.goal}`,\n `Open gaps:\\n${gapLines || '(none specified)'}`,\n acceptedTitles\n ? `Already accepted this round:\\n${acceptedTitles}`\n : 'Nothing accepted yet this round.',\n `Candidate source:\\nURL: ${source.uri}\\nTitle: ${source.title ?? '(none)'}\\nExcerpt:\\n${excerpt}`,\n 'Verdict as JSON {\"accept\": boolean, \"reason\": string}:',\n ].join('\\n\\n')\n\n let raw = ''\n try {\n raw = await router.chat(\n [\n { role: 'system', content: system },\n { role: 'user', content: user },\n ],\n MIN_MAX_TOKENS,\n )\n } catch (error) {\n if ((error as { name?: string }).name === 'AbortError') throw error\n // Router failure: fail-closed (reject) so an unverified source can't slip in.\n return acceptOnParseFailure\n ? { accept: true }\n : { accept: false, reason: `verifier unavailable: ${(error as Error).message}` }\n }\n\n const verdict = parseVerdict(raw)\n if (verdict) return verdict\n return acceptOnParseFailure\n ? { accept: true }\n : { accept: false, reason: 'verifier returned an unparseable verdict' }\n },\n }\n}\n\n/** Parse the verifier's `{accept, reason}` JSON, tolerant of fences / prose. */\nfunction parseVerdict(raw: string): SourceVerdict | null {\n const text = raw.trim()\n if (!text) return null\n const objMatch = text.match(/\\{[\\s\\S]*\\}/)\n if (!objMatch) return null\n try {\n const parsed = JSON.parse(objMatch[0]) as { accept?: unknown; reason?: unknown }\n if (typeof parsed.accept !== 'boolean') return null\n if (parsed.accept) return { accept: true }\n return {\n accept: false,\n reason:\n typeof parsed.reason === 'string' && parsed.reason.trim()\n ? parsed.reason.trim()\n : 'rejected by verifier',\n }\n } catch {\n return null\n }\n}\n","/**\n * Adaptive verifier mode for `runVerifiedResearchLoop`.\n *\n * The cost/quality A/B (`docs/results/cost-quality.md`) found the LLM relevance\n * verifier's cleanliness win is dominated by DE-DUPLICATION — which a\n * deterministic content-hash / canonical-URL check captures at ~none of the LLM\n * premium — and that an LLM check only earns its dollar on the off-scope tail.\n * The honest production move it names is: do the cheap deterministic work first,\n * spend the LLM only where it pays. This module is that driver.\n *\n * Per candidate source the adaptive driver runs THREE stages, cheapest first,\n * and stops at the first that decides:\n *\n * 1. DEDUP ($0, no LLM). Reject a source whose CONTENT (normalized-text hash)\n * or whose CANONICAL URL matches one already accepted this round or already\n * in the knowledge base. This is the de-dup the relevance judge was being\n * paid to do; doing it deterministically is free and exact.\n *\n * 2. HEURISTIC TRIAGE ($0, no LLM). For a unique survivor, a cheap host /\n * title / length signal classifies it as clearly-keep, clearly-drop, or\n * AMBIGUOUS. Clear cases are resolved without a model: an authoritative host\n * (arxiv, *.edu, *.gov, official docs) with a substantial readable body is\n * kept; an obvious spam/listicle/marketing title or a too-thin body is\n * dropped. Only genuinely ambiguous survivors fall through.\n *\n * 3. LLM ESCALATION ($, one call). ONLY the ambiguous survivors reach the LLM\n * `verifySource` — the shipped `createVerifyingResearchDriver` relevance\n * judge. This is where the verifier earns its premium: the off-scope tail a\n * cheap rule can't adjudicate.\n *\n * The result is the cost/quality frontier point the doc predicted: most of the\n * cleanliness (dedup + clear drops) at a fraction of the LLM $/calls (only the\n * ambiguous tail pays). It is a real `ResearchDriver` — same contract the\n * two-agent loop already gates on — and reuses `sha256`, the relevance verifier,\n * and the index; it reinvents none of them.\n */\n\nimport { sha256 } from './ids'\nimport type {\n ResearchSourceProposal,\n SourceVerdict,\n SourceVerificationContext,\n} from './verified-research-loop'\nimport {\n createVerifyingResearchDriver,\n type RouterClient,\n type TangleRouterOptions,\n type VerifyingDriverOptions,\n} from './web-research-worker'\n\n/**\n * Canonicalize a URL for duplicate detection: lowercase host, strip a leading\n * `www.`, drop the scheme, the fragment, a trailing slash, and tracking query\n * params (`utm_*`, `ref`, `fbclid`, `gclid`, …). Two URLs that differ only by\n * those decorations canonicalize to the same key, so the dedup stage treats them\n * as the same source. Falls back to the lowercased raw string when the input is\n * not a parseable absolute URL (so non-http identifiers still dedup by equality).\n */\nexport function canonicalizeUrl(uri: string): string {\n const trimmed = uri.trim()\n try {\n const url = new URL(trimmed)\n const host = url.hostname.toLowerCase().replace(/^www\\./, '')\n // Keep only non-tracking query params, sorted for stable ordering.\n const kept: [string, string][] = []\n for (const [key, value] of url.searchParams) {\n const lower = key.toLowerCase()\n if (lower.startsWith('utm_')) continue\n if (trackingParams.has(lower)) continue\n kept.push([key, value])\n }\n kept.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n const query = kept.map(([k, v]) => `${k}=${v}`).join('&')\n const path = url.pathname.replace(/\\/+$/, '') || '/'\n return `${host}${path}${query ? `?${query}` : ''}`\n } catch {\n return trimmed.toLowerCase()\n }\n}\n\n/** Tracking / referrer query params dropped during URL canonicalization. */\nconst trackingParams = new Set([\n 'ref',\n 'ref_src',\n 'source',\n 'fbclid',\n 'gclid',\n 'mc_cid',\n 'mc_eid',\n 'igshid',\n 'spm',\n '_hsenc',\n '_hsmi',\n])\n\n/**\n * A stable content key for a fetched page: the sha256 of its normalized text\n * (lowercased, punctuation/whitespace collapsed). Two pages whose readable body\n * is the same modulo formatting collide here, so the dedup stage rejects a\n * mirror/syndication of an already-accepted source even when the URL differs.\n */\nexport function contentKey(text: string): string {\n const normalized = text\n .toLowerCase()\n .replace(/[^\\p{L}\\p{N}\\s]+/gu, ' ')\n .replace(/\\s+/g, ' ')\n .trim()\n return sha256(normalized)\n}\n\n/** Why the deterministic dedup stage rejected a candidate (for audit/notes). */\nexport type DedupReason = 'duplicate-url' | 'duplicate-content'\n\n/** The cheap-triage classification of a unique survivor. */\nexport type TriageClass = 'keep' | 'drop' | 'ambiguous'\n\n/** One source's adaptive routing decision, for instrumentation and the doc. */\nexport interface AdaptiveDecision {\n uri: string\n /** The stage that decided this source: dedup | heuristic | llm. */\n stage: 'dedup' | 'heuristic' | 'llm'\n accepted: boolean\n /** The triage class assigned (set once past dedup). */\n triage?: TriageClass\n reason?: string\n}\n\n/** Running tally of where the adaptive driver spent its decisions. */\nexport interface AdaptiveStats {\n total: number\n /** Rejected by deterministic dedup (URL or content). $0. */\n dedupRejected: number\n /** Kept by the cheap heuristic without an LLM call. $0. */\n heuristicKept: number\n /** Dropped by the cheap heuristic without an LLM call. $0. */\n heuristicDropped: number\n /** Escalated to the LLM relevance verifier ($ — the only paid stage). */\n llmCalls: number\n /** Of the escalations, how many the LLM accepted. */\n llmAccepted: number\n decisions: AdaptiveDecision[]\n}\n\nexport interface AdaptiveDriverOptions {\n /** Router client for the LLM escalation. Defaults to a live client from env. */\n router?: RouterClient\n router_options?: TangleRouterOptions\n /** Passed through to the escalation relevance verifier. */\n verifying?: Pick<VerifyingDriverOptions, 'acceptOnParseFailure'>\n /**\n * Hosts an authoritative source lives on. A unique survivor on one of these,\n * with a substantial body, is KEPT deterministically (no LLM). Suffix-matched\n * against the canonical host, so `arxiv.org` matches `export.arxiv.org`. The\n * defaults cover papers, official docs, and standards bodies.\n */\n authoritativeHosts?: string[]\n /**\n * Title/snippet patterns that mark obvious spam / listicle / marketing — a\n * unique survivor matching one is DROPPED deterministically (no LLM).\n */\n spamPatterns?: RegExp[]\n /**\n * Below this many readable chars a survivor is too thin to be a real reference\n * and is dropped deterministically. Default 400.\n */\n minBodyChars?: number\n /**\n * A survivor whose body is at or above this many chars AND on an authoritative\n * host is kept without an LLM call. Default 600.\n */\n substantialBodyChars?: number\n /** Receives each routing decision as it is made (for live instrumentation). */\n onDecision?: (decision: AdaptiveDecision) => void\n}\n\n/** Default authoritative host suffixes — papers, official docs, standards. */\nconst defaultAuthoritativeHosts = [\n 'arxiv.org',\n 'aclanthology.org',\n 'openreview.net',\n 'dl.acm.org',\n 'ieeexplore.ieee.org',\n 'nature.com',\n 'science.org',\n 'pubmed.ncbi.nlm.nih.gov',\n 'ncbi.nlm.nih.gov',\n '.edu',\n '.gov',\n 'docs.python.org',\n 'pytorch.org',\n 'tensorflow.org',\n 'huggingface.co',\n 'github.com',\n 'developer.mozilla.org',\n 'wikipedia.org',\n 'w3.org',\n 'ietf.org',\n 'rfc-editor.org',\n]\n\n/** Default spam/listicle/marketing title patterns. */\nconst defaultSpamPatterns = [\n /\\bbuy\\b.*\\b(cheap|now|deal|sale|discount)\\b/i,\n /\\b\\d+\\s+(things|ways|reasons|tips|tricks|secrets|hacks)\\b.*\\b(you|that|will)\\b/i,\n /\\bshock(ing|ed)?\\b/i,\n /\\bclickbait\\b/i,\n /!!!|\\$\\$\\$/,\n /\\b(coupon|promo code|affiliate|sponsored)\\b/i,\n /\\bbest .* (of \\d{4}|in \\d{4})\\b/i,\n]\n\n/**\n * Classify a UNIQUE survivor (already past dedup) with cheap host/title/length\n * signals only — no LLM. Returns `keep`, `drop`, or `ambiguous`. `ambiguous` is\n * the residue the LLM is reserved for: on-topic-looking pages on unknown hosts\n * with a plausible body, which a host/title rule cannot adjudicate.\n */\nexport function triageSource(\n source: ResearchSourceProposal,\n options: {\n authoritativeHosts: string[]\n spamPatterns: RegExp[]\n minBodyChars: number\n substantialBodyChars: number\n },\n): { triage: TriageClass; reason: string } {\n const titleAndSnippet = `${source.title ?? ''} ${\n typeof source.metadata?.snippet === 'string' ? source.metadata.snippet : ''\n }`.trim()\n const bodyLen = source.text.trim().length\n\n // Clear DROP: obvious spam/listicle/marketing title, OR a too-thin body that\n // can't be a real reference.\n for (const pattern of options.spamPatterns) {\n if (pattern.test(titleAndSnippet)) {\n return { triage: 'drop', reason: `spam/listicle title (${pattern.source})` }\n }\n }\n if (bodyLen < options.minBodyChars) {\n return { triage: 'drop', reason: `thin body (${bodyLen} < ${options.minBodyChars} chars)` }\n }\n\n // Clear KEEP: an authoritative host with a substantial readable body. The host\n // is a strong prior for a real reference; the length rules out a stub page.\n const host = hostOf(source.uri)\n const authoritative =\n host.length > 0 && options.authoritativeHosts.some((suffix) => hostMatches(host, suffix))\n if (authoritative && bodyLen >= options.substantialBodyChars) {\n return { triage: 'keep', reason: `authoritative host ${host} + substantial body (${bodyLen})` }\n }\n\n // Everything else is AMBIGUOUS — an unknown host with a plausible body. This\n // is exactly the off-scope tail the LLM relevance judge is reserved for.\n return { triage: 'ambiguous', reason: `unknown host ${host || '(none)'}, body ${bodyLen} chars` }\n}\n\nfunction hostOf(uri: string): string {\n try {\n return new URL(uri.trim()).hostname.toLowerCase().replace(/^www\\./, '')\n } catch {\n return ''\n }\n}\n\n/** Suffix host match: `.edu` matches `mit.edu`; `arxiv.org` matches `export.arxiv.org`. */\nfunction hostMatches(host: string, suffix: string): boolean {\n if (suffix.startsWith('.')) return host.endsWith(suffix) || host === suffix.slice(1)\n return host === suffix || host.endsWith(`.${suffix}`)\n}\n\nexport interface AdaptiveResearchDriver {\n verifySource(\n source: ResearchSourceProposal,\n ctx: SourceVerificationContext,\n ): Promise<SourceVerdict>\n /** Live tally of where decisions were spent — the cost/quality instrumentation. */\n stats(): AdaptiveStats\n}\n\n/**\n * Build the adaptive verifier. The deterministic stages (dedup + heuristic\n * triage) cost $0; only AMBIGUOUS survivors escalate to the LLM relevance\n * verifier. `stats()` exposes where every decision was spent so the A/B can read\n * the LLM $/calls the adaptive driver saved against the cleanliness it kept.\n *\n * Dedup state is kept on the driver instance: it tracks the canonical URLs and\n * content hashes it has ACCEPTED, plus those it sees in the verification\n * context's `acceptedThisRound` and the KB index. Use one driver per loop run.\n */\nexport function createAdaptiveResearchDriver(\n options: AdaptiveDriverOptions = {},\n): AdaptiveResearchDriver {\n const authoritativeHosts = options.authoritativeHosts ?? defaultAuthoritativeHosts\n const spamPatterns = options.spamPatterns ?? defaultSpamPatterns\n const minBodyChars = Math.max(1, options.minBodyChars ?? 400)\n const substantialBodyChars = Math.max(minBodyChars, options.substantialBodyChars ?? 600)\n\n // The shipped LLM relevance verifier — the ONLY paid stage, reused, not rebuilt.\n const relevance = createVerifyingResearchDriver({\n router: options.router,\n router_options: options.router_options,\n acceptOnParseFailure: options.verifying?.acceptOnParseFailure,\n })\n\n // Dedup memory across the run: every URL/content key this driver ACCEPTED.\n const acceptedUrlKeys = new Set<string>()\n const acceptedContentKeys = new Set<string>()\n\n const stats: AdaptiveStats = {\n total: 0,\n dedupRejected: 0,\n heuristicKept: 0,\n heuristicDropped: 0,\n llmCalls: 0,\n llmAccepted: 0,\n decisions: [],\n }\n\n function record(decision: AdaptiveDecision): void {\n stats.decisions.push(decision)\n options.onDecision?.(decision)\n }\n\n return {\n async verifySource(source, ctx): Promise<SourceVerdict> {\n stats.total += 1\n const urlKey = canonicalizeUrl(source.uri)\n const cKey = contentKey(source.text)\n\n // ---- STAGE 1: DETERMINISTIC DEDUP ($0) ----------------------------------\n // Seed the dup sets from what the loop already accepted this round AND from\n // the KB index, so a duplicate of an existing source is caught even if this\n // driver instance hasn't seen it yet.\n const roundUrlKeys = new Set(\n ctx.acceptedThisRound.map((accepted) => canonicalizeUrl(accepted.uri)),\n )\n const roundContentKeys = new Set(\n ctx.acceptedThisRound.map((accepted) => contentKey(accepted.text)),\n )\n const indexUrlKeys = new Set(\n ctx.index.sources.flatMap((indexed) =>\n typeof indexed.metadata?.originalUri === 'string'\n ? [canonicalizeUrl(indexed.metadata.originalUri)]\n : [],\n ),\n )\n const dupUrl =\n acceptedUrlKeys.has(urlKey) || roundUrlKeys.has(urlKey) || indexUrlKeys.has(urlKey)\n const dupContent = acceptedContentKeys.has(cKey) || roundContentKeys.has(cKey)\n if (dupUrl || dupContent) {\n stats.dedupRejected += 1\n const reason: DedupReason = dupUrl ? 'duplicate-url' : 'duplicate-content'\n record({ uri: source.uri, stage: 'dedup', accepted: false, reason })\n return { accept: false, reason: `dedup: ${reason}` }\n }\n\n // ---- STAGE 2: CHEAP HEURISTIC TRIAGE ($0) -------------------------------\n const { triage, reason } = triageSource(source, {\n authoritativeHosts,\n spamPatterns,\n minBodyChars,\n substantialBodyChars,\n })\n if (triage === 'keep') {\n stats.heuristicKept += 1\n acceptedUrlKeys.add(urlKey)\n acceptedContentKeys.add(cKey)\n record({ uri: source.uri, stage: 'heuristic', accepted: true, triage, reason })\n return { accept: true }\n }\n if (triage === 'drop') {\n stats.heuristicDropped += 1\n record({ uri: source.uri, stage: 'heuristic', accepted: false, triage, reason })\n return { accept: false, reason: `heuristic drop: ${reason}` }\n }\n\n // ---- STAGE 3: LLM ESCALATION ($ — ambiguous tail only) ------------------\n stats.llmCalls += 1\n const verdict = await relevance.verifySource(source, ctx)\n if (verdict.accept) {\n stats.llmAccepted += 1\n acceptedUrlKeys.add(urlKey)\n acceptedContentKeys.add(cKey)\n }\n record({\n uri: source.uri,\n stage: 'llm',\n accepted: verdict.accept,\n triage,\n reason: verdict.accept ? 'llm accepted' : verdict.reason,\n })\n return verdict\n },\n stats(): AdaptiveStats {\n return {\n ...stats,\n decisions: [...stats.decisions],\n }\n },\n }\n}\n","import { z } from 'zod'\nimport { normalizePagesDirectory } from './pages-directory'\n\n/** Authoritative local state included in a KB improvement candidate. */\nexport interface KnowledgeStateScope {\n /** Root-relative Markdown pages directory. Defaults to `knowledge`. */\n pagesDirectory?: string\n /** Include claim ledgers and research events. Excludes indexes, locks, and receipt artifacts. */\n researchState?: boolean\n}\n\nexport const knowledgeStateScopeSchema = z\n .object({\n pagesDirectory: z\n .string()\n .transform((value) => normalizePagesDirectory(value))\n .optional(),\n researchState: z.boolean().optional(),\n })\n .strict()\n\nexport function normalizeKnowledgeStateScope(scope: KnowledgeStateScope = {}) {\n const parsed = knowledgeStateScopeSchema.parse(scope)\n return {\n pagesDirectory: normalizePagesDirectory(parsed.pagesDirectory),\n researchState: parsed.researchState ?? false,\n }\n}\n\nexport const KNOWLEDGE_RESEARCH_STATE_PATHS = [\n '.agent-knowledge/claim-ledgers',\n '.agent-knowledge/events.json',\n] as const\n","import { contentHash, type RunRecord, validateRunRecord } from '@tangle-network/agent-eval'\nimport {\n type AgentImprovementActivation,\n type AgentImprovementActivationResult,\n agentImprovementActivationResultSchema,\n} from '@tangle-network/agent-interface'\nimport { z } from 'zod'\nimport type {\n BuildEvalKnowledgeBundleOptions,\n EvalKnowledgeBundleBuildResult,\n KnowledgeReadinessSpec,\n} from '../eval-readiness'\nimport { type KnowledgeStateScope, knowledgeStateScopeSchema } from '../knowledge-state-scope'\nimport { DEFAULT_PAGES_DIRECTORY } from '../pages-directory'\nimport type {\n KnowledgeBaseQualityOptions,\n KnowledgeBaseQualityReport,\n RagAnswerEvalArtifact,\n} from '../rag-eval'\nimport type {\n RagKnowledgeImprovementPhase,\n RagKnowledgeResearchOptions,\n RagKnowledgeUpdateInput,\n RagKnowledgeUpdateResult,\n RunRagKnowledgeImprovementLoopOptions,\n RunRagKnowledgeImprovementLoopResult,\n} from '../rag-improvement-loop'\nimport type { RunRagOptimizationOptions } from '../rag-optimization'\nimport type { RunKnowledgeResearchLoopOptions } from '../research-loop'\nimport type { RunRetrievalImprovementLoopOptions } from '../retrieval-optimization'\nimport type { KnowledgeIndex } from '../types'\nimport type { ValidateKnowledgeOptions, ValidateKnowledgeResult } from '../validate'\n\nexport type KnowledgeImprovementStatus =\n | 'running'\n | 'candidate-ready'\n | 'promoted'\n | 'rejected'\n | 'blocked'\n\ninterface KnowledgeImprovementMetricProvenanceBase {\n evaluator: string\n version: string\n}\n\nexport type KnowledgeImprovementMetricProvenance =\n | (KnowledgeImprovementMetricProvenanceBase & {\n method: 'deterministic'\n })\n | (KnowledgeImprovementMetricProvenanceBase & {\n method: 'sampled' | 'composite'\n corpusHash: string\n runRecords: RunRecord[]\n })\n | (KnowledgeImprovementMetricProvenanceBase & {\n method: 'model'\n model: string\n corpusHash: string\n runRecords: RunRecord[]\n })\n\nexport interface KnowledgeImprovementMetric {\n score: number\n passed: boolean\n dimensions?: Record<string, number>\n notes?: string\n provenance: KnowledgeImprovementMetricProvenance\n}\n\nexport interface KnowledgeImprovementEvaluationInput {\n runId: string\n iteration: number\n root: string\n baselineRoot: string\n candidateRoot: string\n baselineIndex: KnowledgeIndex\n candidateIndex: KnowledgeIndex\n baseHash: string\n candidateHash: string\n validation: ValidateKnowledgeResult\n readiness?: EvalKnowledgeBundleBuildResult\n kbQuality: KnowledgeBaseQualityReport\n lifecycle?: RunRagKnowledgeImprovementLoopResult\n signal?: AbortSignal\n}\n\nexport type KnowledgeImprovementEvaluator = (\n input: KnowledgeImprovementEvaluationInput,\n) => Promise<KnowledgeImprovementMetric> | KnowledgeImprovementMetric\n\nexport interface KnowledgeImprovementCandidateRecord {\n iteration: number\n candidateId: string\n baseHash: string\n candidateHash?: string\n evidenceHash?: string\n promotionPlanHash?: string\n /** Durable one-way boundary preventing final-case reuse after interruption. */\n finalEvaluationStartedAt?: string\n status: KnowledgeImprovementStatus\n createdAt: string\n updatedAt: string\n}\n\nexport interface KnowledgeImprovementRunState {\n stateScope?: KnowledgeStateScope\n runId: string\n root: string\n goal: string\n implementationRef: string\n status: KnowledgeImprovementStatus\n baseHash: string\n createdAt: string\n updatedAt: string\n ownerId?: string\n candidates: KnowledgeImprovementCandidateRecord[]\n promotedCandidateId?: string\n blockedReason?: string\n}\n\nexport interface KnowledgeImprovementResult {\n runId: string\n state: KnowledgeImprovementRunState\n candidate?: KnowledgeImprovementCandidateRecord\n evaluation?: KnowledgeImprovementMetric\n lifecycle?: RunRagKnowledgeImprovementLoopResult\n promoted: boolean\n blocked: boolean\n}\n\nexport type KnowledgeImprovementTarget = 'candidate' | 'baseline'\n\nexport interface KnowledgeImprovementMutationReceipt {\n target: KnowledgeImprovementTarget\n beforeHash: string\n afterHash: string\n changed: boolean\n transactionId: string | null\n recovered: boolean\n}\n\nexport interface KnowledgeImprovementMutationResult extends KnowledgeImprovementResult {\n candidate: KnowledgeImprovementCandidateRecord\n mutation: KnowledgeImprovementMutationReceipt\n activationResult?: AgentImprovementActivationResult\n}\n\nexport interface KnowledgeImprovementActivationPersistence {\n activation: AgentImprovementActivation\n attemptedAt: string\n identity: string\n /** May run again after interruption; keep this deterministic and free of external side effects. */\n createResult(\n mutation: KnowledgeImprovementMutationReceipt,\n ): Promise<AgentImprovementActivationResult> | AgentImprovementActivationResult\n}\n\nexport const digestSchema = z.string().regex(/^[a-f0-9]{64}$/)\nexport const immutableRefSchema = z.string().regex(/^(?:sha256:[a-f0-9]{64}|git:[a-f0-9]{40})$/)\n\nexport const runIdSchema = z.string().min(1).max(2_048)\n\nexport const safePathSegmentSchema = z\n .string()\n .min(1)\n .max(128)\n .regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/)\n\nexport const knowledgeImprovementMutationReceiptSchema = z\n .object({\n target: z.enum(['candidate', 'baseline']),\n beforeHash: digestSchema,\n afterHash: digestSchema,\n changed: z.boolean(),\n transactionId: z.string().uuid().nullable(),\n recovered: z.boolean(),\n })\n .strict()\n\nexport interface KnowledgeImprovementActivationRecord {\n kind: 'knowledge-improvement-activation-result'\n candidateId: string\n mutation: KnowledgeImprovementMutationReceipt\n result: AgentImprovementActivationResult\n}\n\nexport const knowledgeImprovementActivationRecordSchema: z.ZodType<KnowledgeImprovementActivationRecord> =\n z\n .object({\n kind: z.literal('knowledge-improvement-activation-result'),\n candidateId: safePathSegmentSchema,\n mutation: knowledgeImprovementMutationReceiptSchema,\n result: agentImprovementActivationResultSchema,\n })\n .strict()\n\nconst improvementStatusSchema = z.enum([\n 'running',\n 'candidate-ready',\n 'promoted',\n 'rejected',\n 'blocked',\n])\n\nconst runRecordSchema = z.custom<RunRecord>((value) => {\n try {\n validateRunRecord(value)\n return true\n } catch {\n return false\n }\n}, 'invalid agent-eval RunRecord')\n\nconst deterministicMetricProvenanceSchema = z\n .object({\n evaluator: z.string().min(1),\n version: z.string().min(1),\n method: z.literal('deterministic'),\n })\n .strict()\n\nconst measuredMetricProvenanceSchema = z\n .object({\n evaluator: z.string().min(1),\n version: z.string().min(1),\n method: z.enum(['sampled', 'composite']),\n corpusHash: digestSchema,\n runRecords: z.array(runRecordSchema).min(1),\n })\n .strict()\n\nconst modelMetricProvenanceSchema = z\n .object({\n evaluator: z.string().min(1),\n version: z.string().min(1),\n method: z.literal('model'),\n model: z.string().min(1),\n corpusHash: digestSchema,\n runRecords: z.array(runRecordSchema).min(1),\n })\n .strict()\n\nexport const improvementMetricSchema = z\n .object({\n score: z.number().finite().min(0).max(1),\n passed: z.boolean(),\n dimensions: z.record(z.string(), z.number().finite()).optional(),\n notes: z.string().optional(),\n provenance: z.discriminatedUnion('method', [\n deterministicMetricProvenanceSchema,\n measuredMetricProvenanceSchema,\n modelMetricProvenanceSchema,\n ]),\n })\n .strict()\n .superRefine((metric, context) => {\n if (metric.provenance.method === 'deterministic') return\n const actualCorpusHash = contentHash(metric.provenance.runRecords)\n if (actualCorpusHash !== metric.provenance.corpusHash) {\n context.addIssue({\n code: 'custom',\n path: ['provenance', 'corpusHash'],\n message: 'metric corpus hash must bind the complete RunRecord array',\n })\n }\n })\n\nconst candidateRecordSchema = z\n .object({\n iteration: z.number().int().positive(),\n candidateId: safePathSegmentSchema,\n baseHash: digestSchema,\n candidateHash: digestSchema.optional(),\n evidenceHash: digestSchema.optional(),\n promotionPlanHash: digestSchema.optional(),\n finalEvaluationStartedAt: z.iso.datetime().optional(),\n status: improvementStatusSchema,\n createdAt: z.iso.datetime(),\n updatedAt: z.iso.datetime(),\n })\n .strict()\n\nexport const KnowledgeImprovementRunStateSchema = z\n .object({\n stateScope: knowledgeStateScopeSchema.optional(),\n runId: runIdSchema,\n root: z.string().min(1),\n goal: z.string().min(1),\n implementationRef: immutableRefSchema,\n status: improvementStatusSchema,\n baseHash: digestSchema,\n createdAt: z.iso.datetime(),\n updatedAt: z.iso.datetime(),\n ownerId: z.string().min(1).optional(),\n candidates: z.array(candidateRecordSchema),\n promotedCandidateId: safePathSegmentSchema.optional(),\n blockedReason: z.string().min(1).optional(),\n })\n .strict()\n .superRefine((state, context) => {\n const candidateIds = new Set<string>()\n for (const [index, candidate] of state.candidates.entries()) {\n if (candidateIds.has(candidate.candidateId)) {\n context.addIssue({\n code: 'custom',\n path: ['candidates', index, 'candidateId'],\n message: 'candidate ids must be unique within an improvement run',\n })\n }\n candidateIds.add(candidate.candidateId)\n if (candidate.baseHash !== state.baseHash) {\n context.addIssue({\n code: 'custom',\n path: ['candidates', index, 'baseHash'],\n message: 'candidate base hash must match its improvement run',\n })\n }\n if (candidate.status === 'candidate-ready') {\n if (!candidate.candidateHash || !candidate.evidenceHash || !candidate.promotionPlanHash) {\n context.addIssue({\n code: 'custom',\n path: ['candidates', index],\n message: 'ready candidates require content, evidence, and promotion-plan identities',\n })\n }\n }\n if (\n candidate.status === 'promoted' &&\n (!candidate.candidateHash || !candidate.evidenceHash || !candidate.promotionPlanHash)\n ) {\n context.addIssue({\n code: 'custom',\n path: ['candidates', index],\n message: 'promoted candidates require content, evidence, and promotion-plan identities',\n })\n }\n if (\n candidate.status === 'promoted' &&\n Boolean(candidate.evidenceHash) !== Boolean(candidate.promotionPlanHash)\n ) {\n context.addIssue({\n code: 'custom',\n path: ['candidates', index],\n message: 'promoted candidate evidence and promotion-plan identities must appear together',\n })\n }\n if (candidate.status === 'promoted' && state.status !== 'promoted') {\n context.addIssue({\n code: 'custom',\n path: ['candidates', index, 'status'],\n message: 'only a promoted run may contain a promoted candidate',\n })\n }\n }\n if (state.status === 'promoted') {\n const promoted = state.candidates.filter(\n (candidate) => candidate.candidateId === state.promotedCandidateId,\n )\n if (promoted.length !== 1 || promoted[0]?.status !== 'promoted') {\n context.addIssue({\n code: 'custom',\n path: ['promotedCandidateId'],\n message: 'promoted state must identify exactly one promoted candidate',\n })\n }\n } else if (state.promotedCandidateId !== undefined) {\n context.addIssue({\n code: 'custom',\n path: ['promotedCandidateId'],\n message: 'only a promoted run may identify a promoted candidate',\n })\n }\n if (\n state.status === 'candidate-ready' &&\n state.candidates.filter((candidate) => candidate.status === 'candidate-ready').length !== 1\n ) {\n context.addIssue({\n code: 'custom',\n path: ['status'],\n message: 'candidate-ready state must contain exactly one ready candidate',\n })\n }\n if (state.status === 'blocked' && state.blockedReason === undefined) {\n context.addIssue({\n code: 'custom',\n path: ['blockedReason'],\n message: 'blocked state must include a reason',\n })\n }\n })\n\nexport const KnowledgeImprovementEvidenceSchema = z\n .object({\n kind: z.literal('knowledge-improvement-evidence'),\n runId: runIdSchema,\n candidateId: safePathSegmentSchema,\n iteration: z.number().int().positive(),\n goalHash: digestSchema,\n implementationRef: immutableRefSchema,\n baseHash: digestSchema,\n candidateHash: digestSchema,\n promotionPlanHash: digestSchema,\n validation: z.unknown(),\n readiness: z.unknown().nullable(),\n kbQuality: z.unknown(),\n evaluation: improvementMetricSchema,\n lifecycle: z.unknown().nullable(),\n })\n .strict()\n\nexport type KnowledgeImprovementEvidence = z.infer<typeof KnowledgeImprovementEvidenceSchema>\n\n/** Portable identity of one measured candidate. Paths and mutable run state are deliberately excluded. */\nexport const KnowledgeImprovementCandidateRefSchema = z\n .object({\n kind: z.literal('knowledge-improvement-candidate'),\n runId: runIdSchema,\n candidateId: safePathSegmentSchema,\n goalHash: digestSchema,\n baseHash: digestSchema,\n candidateHash: digestSchema,\n evidenceHash: digestSchema,\n promotionPlanHash: digestSchema,\n })\n .strict()\n\nexport type KnowledgeImprovementCandidateRef = z.infer<\n typeof KnowledgeImprovementCandidateRefSchema\n>\n\nexport interface PromoteKnowledgeCandidateOptions {\n root: string\n candidate: KnowledgeImprovementCandidateRef\n activation?: KnowledgeImprovementActivationPersistence\n ownerId?: string\n leaseTtlMs?: number\n now?: () => Date\n onState?: (state: KnowledgeImprovementRunState) => Promise<void> | void\n}\n\nexport type RestoreKnowledgeCandidateBaselineOptions = PromoteKnowledgeCandidateOptions\n\nexport interface LoadKnowledgeImprovementActivationResultOptions {\n root: string\n candidate: KnowledgeImprovementCandidateRef\n activation: AgentImprovementActivation\n identity: string\n}\n\nexport interface UseKnowledgeImprovementCandidateOptions {\n root: string\n candidate: KnowledgeImprovementCandidateRef\n}\n\nexport interface ResolvedKnowledgeImprovementComparisonSnapshot {\n root: string\n hash: string\n}\n\nexport interface ResolvedKnowledgeImprovementComparison {\n stateScope?: KnowledgeStateScope\n reference: KnowledgeImprovementCandidateRef\n evaluation: KnowledgeImprovementMetric\n baseline: ResolvedKnowledgeImprovementComparisonSnapshot\n candidate: ResolvedKnowledgeImprovementComparisonSnapshot\n}\n\nexport interface ResolvedKnowledgeImprovementCandidate {\n stateScope?: KnowledgeStateScope\n root: string\n candidate: KnowledgeImprovementCandidateRef\n evaluation: KnowledgeImprovementMetric\n}\n\nexport interface KnowledgeImprovementRetrievalOptions\n extends Omit<RunRetrievalImprovementLoopOptions, 'index' | 'runDir'> {\n runDir?: RunRetrievalImprovementLoopOptions['runDir']\n}\n\nexport type KnowledgeImprovementRagOptimizationRunInput = Parameters<\n RunRagOptimizationOptions['run']\n>[0] & {\n runId: string\n iteration: number\n candidateId: string\n root: string\n baselineRoot: string\n candidateRoot: string\n candidateIndex: KnowledgeIndex\n baseHash: string\n}\n\nexport interface KnowledgeImprovementRagOptimizationOptions\n extends Omit<RunRagOptimizationOptions, 'run' | 'runDir'> {\n runDir?: RunRagOptimizationOptions['runDir']\n run(input: KnowledgeImprovementRagOptimizationRunInput): Promise<RagAnswerEvalArtifact>\n}\n\nexport interface KnowledgeImprovementUpdateInput extends RagKnowledgeUpdateInput {\n runId: string\n iteration: number\n candidateId: string\n root: string\n baselineRoot: string\n candidateRoot: string\n baseHash: string\n}\n\nexport type KnowledgeImprovementUpdate = (\n input: KnowledgeImprovementUpdateInput,\n) => Promise<RagKnowledgeUpdateResult> | RagKnowledgeUpdateResult\n\nexport interface KnowledgeImprovementOptions {\n /** Declared authoritative local state, frozen and restored with each candidate. */\n stateScope?: KnowledgeStateScope\n root: string\n goal: string\n /**\n * Immutable identity covering callbacks, evaluation policy, models, indexes,\n * external services, and all other behavior that can affect this run.\n */\n implementationRef: string\n runId?: string\n ownerId?: string\n leaseTtlMs?: number\n resume?: boolean\n maxCandidates?: number\n candidateResearchIterations?: number\n strict?: ValidateKnowledgeOptions['strict']\n readinessSpecs?: KnowledgeReadinessSpec[]\n readinessTaskId?: string\n readiness?: Omit<BuildEvalKnowledgeBundleOptions, 'taskId' | 'index' | 'specs'>\n kbQuality?: KnowledgeBaseQualityOptions\n step?: RunKnowledgeResearchLoopOptions['step']\n knowledgeResearch?: Omit<RagKnowledgeResearchOptions, 'root'>\n ragOptimization?: KnowledgeImprovementRagOptimizationOptions\n retrieval?: KnowledgeImprovementRetrievalOptions\n diagnose?: NonNullable<RunRagKnowledgeImprovementLoopOptions['diagnose']>\n acquireKnowledge?: NonNullable<RunRagKnowledgeImprovementLoopOptions['acquireKnowledge']>\n updateKnowledge?: KnowledgeImprovementUpdate\n evaluateAnswers?: NonNullable<RunRagKnowledgeImprovementLoopOptions['evaluateAnswers']>\n answerQualityCostCeiling?: RunRagKnowledgeImprovementLoopOptions['answerQualityCostCeiling']\n decidePromotion?: NonNullable<RunRagKnowledgeImprovementLoopOptions['decidePromotion']>\n enabledPhases?: readonly RagKnowledgeImprovementPhase[]\n requiredPhases?: readonly RagKnowledgeImprovementPhase[]\n /** Repeatable candidate screening that must not use final cases. */\n evaluateDevelopment?: KnowledgeImprovementEvaluator\n /** Single-use final evaluator. A failure ends the run. */\n evaluate?: KnowledgeImprovementEvaluator\n signal?: AbortSignal\n now?: () => Date\n onState?: (state: KnowledgeImprovementRunState) => Promise<void> | void\n}\n\nexport interface LeaseHandle {\n ownerId: string\n assertOwned(): void\n release(): Promise<void>\n}\n\nexport const DEFAULT_LEASE_TTL_MS = 15 * 60 * 1000\n\nexport const UPDATE_PHASES: readonly RagKnowledgeImprovementPhase[] = [\n 'gap-diagnosis',\n 'knowledge-acquisition',\n 'knowledge-update',\n]\n\nexport const EVALUATION_PHASES: readonly RagKnowledgeImprovementPhase[] = [\n 'rag-optimization',\n 'retrieval-tuning',\n 'answer-quality',\n 'promotion',\n]\n\n/**\n * The pages directory every knowledge-improvement path reads and writes.\n *\n * This subsystem has no option for a caller-chosen pages directory: the\n * workspace it snapshots, the plan it hashes, and the transaction it applies\n * all address the default tree. Naming it once means the write allowlist, the\n * plan hash, and the generated-page set cannot disagree about which tree they\n * are talking about, and threading a real choice through later changes one\n * constant instead of hunting call sites.\n */\nexport const KB_IMPROVEMENT_PAGES_DIRECTORY = DEFAULT_PAGES_DIRECTORY\n","import { stat } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { canonicalJson, contentHash } from '@tangle-network/agent-eval'\nimport {\n canonicalPathsEqual,\n isMissingFile,\n listRegularFilesWithinRoot,\n readRegularFileWithinRoot,\n relativeWithinRoot,\n withSafeDirectory,\n writeJsonDurableWithinRoot,\n} from '../durable-fs'\nimport { sha256, slugify, stableId } from '../ids'\nimport { acquireDurableFileLock } from '../mutation-lock'\nimport { layoutFor } from '../store'\nimport type {\n KnowledgeImprovementCandidateRecord,\n KnowledgeImprovementOptions,\n KnowledgeImprovementRunState,\n LeaseHandle,\n} from './contracts'\nimport { KnowledgeImprovementRunStateSchema, runIdSchema, safePathSegmentSchema } from './contracts'\n\nexport function knowledgeImprovementRunId(root: string, goal: string): string {\n return stableId('kimpr', `${root}:${goal}`)\n}\n\nexport function knowledgeImprovementRunDir(root: string, runId: string): string {\n const parsedRunId = runIdSchema.parse(runId)\n const safeRunId = safePathSegmentSchema.safeParse(parsedRunId)\n const runSegment = safeRunId.success\n ? safeRunId.data\n : `${slugify(parsedRunId).slice(0, 72)}-${sha256(parsedRunId).slice(0, 16)}`\n const improvementsDir = join(layoutFor(root).cacheDir, 'improvements')\n const runDir = join(improvementsDir, runSegment)\n if (relativeWithinRoot(improvementsDir, runDir) === undefined) {\n throw new Error('knowledge improvement run directory escaped its root')\n }\n return runDir\n}\n\nexport async function withKnowledgeImprovementRun<T>(\n root: string,\n runId: string,\n create: boolean,\n use: (runDir: string) => Promise<T> | T,\n): Promise<T> {\n const runDir = knowledgeImprovementRunDir(root, runId)\n const relativePath = relativeWithinRoot(root, runDir)\n if (!relativePath) throw new Error('knowledge improvement run directory escaped its root')\n return withSafeDirectory(root, relativePath, create, async (openedRunDir) => {\n const result = await use(openedRunDir)\n const openedIdentity = await stat(openedRunDir)\n const currentIdentity = await withSafeDirectory(root, relativePath, false, (currentRunDir) =>\n stat(currentRunDir),\n )\n if (openedIdentity.dev !== currentIdentity.dev || openedIdentity.ino !== currentIdentity.ino) {\n throw new Error('knowledge improvement run directory changed during use')\n }\n return result\n })\n}\n\nexport async function loadKnowledgeImprovementState(\n root: string,\n runId: string,\n): Promise<KnowledgeImprovementRunState | null> {\n const expectedRunId = runIdSchema.parse(runId)\n try {\n return await withKnowledgeImprovementRun(root, expectedRunId, false, (runDir) =>\n loadKnowledgeImprovementStateFromRun(root, expectedRunId, runDir),\n )\n } catch (error) {\n if (isMissingFile(error)) return null\n throw error\n }\n}\n\nexport async function loadKnowledgeImprovementStateFromRun(\n root: string,\n runId: string,\n runDir: string,\n): Promise<KnowledgeImprovementRunState> {\n const stateFile = await readRegularFileWithinRoot(runDir, 'state.json')\n const raw = JSON.parse(stateFile.bytes.toString('utf8')) as unknown\n const state = KnowledgeImprovementRunStateSchema.parse(raw) as KnowledgeImprovementRunState\n if (state.runId !== runId) {\n throw new Error('knowledge improvement state does not match the requested run')\n }\n if (!(await canonicalPathsEqual(state.root, root))) {\n throw new Error('knowledge improvement state does not match the requested root')\n }\n for (const candidate of state.candidates) {\n if (candidate.status === 'running') await assertCandidateWorkspace(runDir, candidate)\n }\n return state\n}\n\nasync function assertCandidateWorkspace(\n runDir: string,\n candidate: Pick<KnowledgeImprovementCandidateRecord, 'candidateId'>,\n): Promise<void> {\n await withCandidateWorkspace(runDir, candidate, () => undefined)\n}\n\nexport async function withCandidateWorkspace<T>(\n runDir: string,\n candidate: Pick<KnowledgeImprovementCandidateRecord, 'candidateId'>,\n use: (candidateRoot: string) => Promise<T> | T,\n): Promise<T> {\n return withSafeDirectory(\n runDir,\n join('candidates', safePathSegmentSchema.parse(candidate.candidateId), 'workspace'),\n false,\n use,\n )\n}\n\nexport function findActiveCandidate(\n state: KnowledgeImprovementRunState,\n): KnowledgeImprovementCandidateRecord | undefined {\n return [...state.candidates]\n .reverse()\n .find((candidate) => candidate.status === 'candidate-ready' || candidate.status === 'running')\n}\n\nexport interface KnowledgeImprovementEvent extends Record<string, unknown> {\n at: string\n type: string\n}\n\nexport async function loadKnowledgeImprovementEvents(\n root: string,\n runId: string,\n): Promise<KnowledgeImprovementEvent[]> {\n const parsedRunId = runIdSchema.parse(runId)\n try {\n return await withKnowledgeImprovementRun(root, parsedRunId, false, (runDir) =>\n loadKnowledgeImprovementEventsFromRun(runDir),\n )\n } catch (error) {\n if (isMissingFile(error)) return []\n throw error\n }\n}\n\nexport async function loadKnowledgeImprovementEventsFromRun(\n runDir: string,\n): Promise<KnowledgeImprovementEvent[]> {\n const events: KnowledgeImprovementEvent[] = []\n try {\n for (const file of await listRegularFilesWithinRoot(runDir, 'events')) {\n const name = file.path.slice('events/'.length)\n if (name.includes('/') || !name.endsWith('.json')) {\n throw new Error(`knowledge event store contains an unsupported entry: ${name}`)\n }\n events.push(parseKnowledgeImprovementEvent(JSON.parse(file.bytes.toString('utf8'))))\n }\n } catch (error) {\n if (!isMissingFile(error)) throw error\n }\n\n const unique = new Map<string, KnowledgeImprovementEvent>()\n for (const event of events) {\n const { at: _at, ...semantic } = event\n unique.set(contentHash(semantic), event)\n }\n return [...unique.values()].sort((left, right) => left.at.localeCompare(right.at))\n}\n\nfunction parseKnowledgeImprovementEvent(value: unknown): KnowledgeImprovementEvent {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('knowledge improvement event is not an object')\n }\n const event = value as Record<string, unknown>\n if (typeof event.at !== 'string' || typeof event.type !== 'string') {\n throw new Error('knowledge improvement event is missing at or type')\n }\n return event as KnowledgeImprovementEvent\n}\n\nexport async function acquireRunLease(\n runDir: string,\n options: { ownerId: string; ttlMs: number },\n): Promise<LeaseHandle> {\n const path = join(runDir, 'run.lock.durable')\n const acquired = await acquireDurableFileLock(runDir, {\n lockfilePath: path,\n staleMs: options.ttlMs,\n })\n return {\n ownerId: options.ownerId,\n assertOwned: acquired.assertOwned,\n release: acquired.release,\n }\n}\n\nexport async function blockRun(\n runDir: string,\n state: KnowledgeImprovementRunState,\n reason: string,\n onState: KnowledgeImprovementOptions['onState'],\n now: () => Date,\n): Promise<KnowledgeImprovementRunState> {\n state.status = 'blocked'\n state.blockedReason = reason\n state.updatedAt = now().toISOString()\n await saveState(runDir, state, onState)\n return state\n}\n\nexport async function saveState(\n runDir: string,\n state: KnowledgeImprovementRunState,\n onState?: KnowledgeImprovementOptions['onState'],\n): Promise<void> {\n await writeJsonDurableWithinRoot(\n runDir,\n 'state.json',\n KnowledgeImprovementRunStateSchema.parse(state),\n )\n await onState?.(state)\n}\n\nexport async function appendLedger(runDir: string, value: Record<string, unknown>): Promise<void> {\n const type = value.type\n if (typeof type !== 'string' || type.length === 0) {\n throw new Error('knowledge improvement event requires a type')\n }\n const relativePath = join('events', `${contentHash(value)}.json`).replace(/\\\\/g, '/')\n try {\n const file = await readRegularFileWithinRoot(runDir, relativePath)\n const existing = parseKnowledgeImprovementEvent(JSON.parse(file.bytes.toString('utf8')))\n const { at: _at, ...semantic } = existing\n if (canonicalJson(semantic) !== canonicalJson(value)) {\n throw new Error('knowledge improvement event identity conflicts with durable content')\n }\n return\n } catch (error) {\n if (!isMissingFile(error)) throw error\n }\n await writeJsonDurableWithinRoot(runDir, relativePath, {\n at: new Date().toISOString(),\n ...value,\n })\n}\n\nexport function candidateEvidenceRelativePath(candidateId: string): string {\n return join('candidates', safePathSegmentSchema.parse(candidateId), 'evidence.json').replace(\n /\\\\/g,\n '/',\n )\n}\n\nexport function assertExactCandidatePlatform(): void {\n if (process.platform !== 'linux') {\n throw new Error('exact knowledge candidate workflows require Linux directory descriptors')\n }\n}\n","import { canonicalJson } from '@tangle-network/agent-eval'\nimport {\n type AgentImprovementActivation,\n type AgentImprovementActivationResult,\n agentImprovementActivationResultSchema,\n agentImprovementActivationSchema,\n canonicalCandidateDigest,\n omitTopLevelDigest,\n type Sha256Digest,\n sha256DigestSchema,\n} from '@tangle-network/agent-interface'\nimport { z } from 'zod'\nimport { isMissingFile, readRegularFileWithinRoot, writeJsonDurableWithinRoot } from '../durable-fs'\nimport type {\n KnowledgeImprovementActivationPersistence,\n KnowledgeImprovementActivationRecord,\n KnowledgeImprovementCandidateRef,\n KnowledgeImprovementMutationReceipt,\n KnowledgeImprovementTarget,\n LoadKnowledgeImprovementActivationResultOptions,\n} from './contracts'\nimport {\n digestSchema,\n KnowledgeImprovementCandidateRefSchema,\n knowledgeImprovementActivationRecordSchema,\n knowledgeImprovementMutationReceiptSchema,\n} from './contracts'\nimport { assertExactCandidatePlatform, withKnowledgeImprovementRun } from './state'\n\n/** Load the durable result for one exact activation without changing knowledge or run state. */\nexport async function loadKnowledgeImprovementActivationResult(\n options: LoadKnowledgeImprovementActivationResultOptions,\n): Promise<AgentImprovementActivationResult | null> {\n assertExactCandidatePlatform()\n const candidate = Object.freeze(KnowledgeImprovementCandidateRefSchema.parse(options.candidate))\n const activation = verifyCanonicalKnowledgeActivation(options.activation)\n const target = targetForKnowledgeActivation(activation)\n assertKnowledgeActivationAuthority(activation, candidate, target, options.identity)\n return withKnowledgeImprovementRun(options.root, candidate.runId, false, async (runDir) => {\n const record = await loadKnowledgeActivationRecord(\n runDir,\n candidate,\n activation,\n target,\n options.identity,\n )\n return record?.result ?? null\n })\n}\n\nexport interface ResolvedKnowledgeImprovementActivationPersistence\n extends KnowledgeImprovementActivationPersistence {\n activation: AgentImprovementActivation\n}\n\nexport function sourceKnowledgeHash(\n candidate: KnowledgeImprovementCandidateRef,\n target: KnowledgeImprovementTarget,\n): string {\n return target === 'candidate' ? candidate.baseHash : candidate.candidateHash\n}\n\nfunction targetForKnowledgeActivation(\n activation: AgentImprovementActivation,\n): KnowledgeImprovementTarget {\n return activation.intent === 'activate-candidate' ? 'candidate' : 'baseline'\n}\n\nexport function resolveKnowledgeActivationPersistence(\n input: KnowledgeImprovementActivationPersistence,\n candidate: KnowledgeImprovementCandidateRef,\n target: KnowledgeImprovementTarget,\n): ResolvedKnowledgeImprovementActivationPersistence {\n const activation = verifyCanonicalKnowledgeActivation(input.activation)\n assertKnowledgeActivationAuthority(activation, candidate, target, input.identity)\n const attemptedAt = z.iso.datetime().parse(input.attemptedAt)\n if (\n Date.parse(attemptedAt) < Date.parse(activation.authorizedAt) ||\n Date.parse(attemptedAt) >= Date.parse(activation.expiresAt)\n ) {\n throw new Error('knowledge activation attempt is outside its authorization window')\n }\n return Object.freeze({\n activation,\n attemptedAt,\n identity: input.identity,\n createResult: input.createResult,\n })\n}\n\nfunction assertKnowledgeActivationAuthority(\n activation: AgentImprovementActivation,\n candidate: KnowledgeImprovementCandidateRef,\n target: KnowledgeImprovementTarget,\n identity: string,\n): void {\n if (!identity.trim()) throw new Error('knowledge activation identity is required')\n if (targetForKnowledgeActivation(activation) !== target) {\n throw new Error('knowledge activation intent does not match the requested transition')\n }\n if (activation.targets.length !== 1) {\n throw new Error('knowledge activation requires exactly one target')\n }\n const authorizedTarget = activation.targets[0]\n if (authorizedTarget.surface !== 'knowledge' || authorizedTarget.identity !== identity) {\n throw new Error('knowledge activation target does not match this knowledge base')\n }\n if (\n authorizedTarget.expectedBaseDigest !==\n prefixedKnowledgeDigest(sourceKnowledgeHash(candidate, target))\n ) {\n throw new Error('knowledge activation does not authorize the measured source state')\n }\n}\n\nfunction verifyCanonicalKnowledgeActivation(\n value: AgentImprovementActivation,\n): AgentImprovementActivation {\n const activation = agentImprovementActivationSchema.parse(value)\n if (canonicalCandidateDigest(omitTopLevelDigest(activation)) !== activation.digest) {\n throw new Error('knowledge activation digest does not match its canonical content')\n }\n return immutableJsonValue(structuredClone(activation))\n}\n\nfunction verifyCanonicalKnowledgeActivationResult(\n value: AgentImprovementActivationResult,\n): AgentImprovementActivationResult {\n const result = agentImprovementActivationResultSchema.parse(value)\n if (canonicalCandidateDigest(omitTopLevelDigest(result)) !== result.digest) {\n throw new Error('knowledge activation result digest does not match its canonical content')\n }\n return immutableJsonValue(structuredClone(result))\n}\n\nexport async function persistKnowledgeActivationResult(\n runDir: string,\n candidate: KnowledgeImprovementCandidateRef,\n persistence: ResolvedKnowledgeImprovementActivationPersistence,\n target: KnowledgeImprovementTarget,\n mutation: KnowledgeImprovementMutationReceipt,\n): Promise<AgentImprovementActivationResult> {\n const result = assertKnowledgeActivationResult(\n persistence.activation,\n candidate,\n target,\n persistence.identity,\n mutation,\n await persistence.createResult(Object.freeze({ ...mutation })),\n persistence.attemptedAt,\n )\n const record = knowledgeImprovementActivationRecordSchema.parse({\n kind: 'knowledge-improvement-activation-result',\n candidateId: candidate.candidateId,\n mutation,\n result,\n })\n const existing = await loadKnowledgeActivationRecord(\n runDir,\n candidate,\n persistence.activation,\n target,\n persistence.identity,\n )\n if (existing) {\n if (canonicalJson(existing) !== canonicalJson(record)) {\n throw new Error('knowledge activation result identity conflicts with durable content')\n }\n return existing.result\n }\n await writeJsonDurableWithinRoot(\n runDir,\n knowledgeActivationResultPath(persistence.activation.digest),\n record,\n )\n const stored = await loadKnowledgeActivationRecord(\n runDir,\n candidate,\n persistence.activation,\n target,\n persistence.identity,\n )\n if (!stored || canonicalJson(stored) !== canonicalJson(record)) {\n throw new Error('knowledge activation result was not durably persisted')\n }\n return stored.result\n}\n\nexport async function loadKnowledgeActivationRecord(\n runDir: string,\n candidate: KnowledgeImprovementCandidateRef,\n activation: AgentImprovementActivation,\n target: KnowledgeImprovementTarget,\n identity: string,\n): Promise<KnowledgeImprovementActivationRecord | null> {\n let raw: unknown\n try {\n const file = await readRegularFileWithinRoot(\n runDir,\n knowledgeActivationResultPath(activation.digest),\n )\n raw = JSON.parse(file.bytes.toString('utf8')) as unknown\n } catch (error) {\n if (isMissingFile(error)) return null\n throw error\n }\n const record = knowledgeImprovementActivationRecordSchema.parse(raw)\n if (record.candidateId !== candidate.candidateId) {\n throw new Error('knowledge activation result belongs to another candidate')\n }\n const result = assertKnowledgeActivationResult(\n activation,\n candidate,\n target,\n identity,\n record.mutation,\n record.result,\n )\n return immutableJsonValue({ ...record, result })\n}\n\nfunction assertKnowledgeActivationResult(\n activation: AgentImprovementActivation,\n candidate: KnowledgeImprovementCandidateRef,\n target: KnowledgeImprovementTarget,\n identity: string,\n mutationInput: KnowledgeImprovementMutationReceipt,\n resultInput: AgentImprovementActivationResult,\n attemptedAt?: string,\n): AgentImprovementActivationResult {\n assertKnowledgeActivationAuthority(activation, candidate, target, identity)\n const mutation = knowledgeImprovementMutationReceiptSchema.parse(mutationInput)\n const result = verifyCanonicalKnowledgeActivationResult(resultInput)\n if (\n result.idempotencyKey !== activation.digest ||\n (attemptedAt !== undefined && result.attemptedAt !== attemptedAt) ||\n Date.parse(result.attemptedAt) < Date.parse(activation.authorizedAt) ||\n Date.parse(result.attemptedAt) >= Date.parse(activation.expiresAt) ||\n mutation.target !== target ||\n mutation.changed !== (mutation.beforeHash !== mutation.afterHash) ||\n (!mutation.changed && (mutation.transactionId !== null || mutation.recovered))\n ) {\n throw new Error('knowledge activation result does not bind its authorized mutation')\n }\n\n const sourceDigest = prefixedKnowledgeDigest(sourceKnowledgeHash(candidate, target))\n const desiredDigest = prefixedKnowledgeDigest(\n target === 'candidate' ? candidate.candidateHash : candidate.baseHash,\n )\n const beforeDigest = prefixedKnowledgeDigest(mutation.beforeHash)\n const afterDigest = prefixedKnowledgeDigest(mutation.afterHash)\n const outcome = result.outcome\n if (mutation.changed) {\n if (\n mutation.transactionId === null ||\n beforeDigest !== sourceDigest ||\n afterDigest !== desiredDigest ||\n outcome.status !== 'applied' ||\n outcome.transactionId !== mutation.transactionId ||\n outcome.targets.length !== 1 ||\n outcome.targets[0]?.surface !== 'knowledge' ||\n outcome.targets[0]?.identity !== identity ||\n outcome.targets[0]?.beforeDigest !== beforeDigest ||\n outcome.targets[0]?.afterDigest !== afterDigest\n ) {\n throw new Error('knowledge activation result does not prove the applied transaction')\n }\n return result\n }\n\n const expectedStatus = afterDigest === desiredDigest ? 'already-applied' : 'conflict'\n if (\n afterDigest === sourceDigest ||\n outcome.status !== expectedStatus ||\n outcome.targets.length !== 1 ||\n outcome.targets[0]?.surface !== 'knowledge' ||\n outcome.targets[0]?.identity !== identity ||\n outcome.targets[0]?.currentDigest !== afterDigest\n ) {\n throw new Error('knowledge activation result does not prove the observed target state')\n }\n return result\n}\n\nfunction knowledgeActivationResultPath(digest: Sha256Digest): string {\n const parsed = sha256DigestSchema.parse(digest)\n return `activation-results/${parsed.slice('sha256:'.length)}.json`\n}\n\nfunction prefixedKnowledgeDigest(hash: string): Sha256Digest {\n return sha256DigestSchema.parse(`sha256:${digestSchema.parse(hash)}`)\n}\n\nexport function immutableJsonValue<T>(value: T): T {\n if (value === null || typeof value !== 'object') return value\n for (const child of Object.values(value)) immutableJsonValue(child)\n return Object.freeze(value)\n}\n","import type { ComparisonCost } from '@tangle-network/agent-eval/campaign'\nimport { assertImmutableRef } from './immutable-ref'\n\ninterface RagAnswerEvidence {\n passed: boolean\n metrics: Record<string, number>\n finalScenarioIds: readonly string[]\n datasetRef: string\n evaluatorRef: string\n cost: ComparisonCost\n}\n\nexport function assertRagAnswerEvidence(result: RagAnswerEvidence): void {\n if (!result || typeof result !== 'object') {\n throw new Error('answer-quality evidence must be an object')\n }\n if (typeof result.passed !== 'boolean') {\n throw new Error('answer-quality evidence requires a boolean passed verdict')\n }\n assertImmutableRef(result.datasetRef, 'answer-quality datasetRef')\n assertImmutableRef(result.evaluatorRef, 'answer-quality evaluatorRef')\n if (\n !Array.isArray(result.finalScenarioIds) ||\n result.finalScenarioIds.length < 2 ||\n new Set(result.finalScenarioIds).size !== result.finalScenarioIds.length ||\n result.finalScenarioIds.some((id) => typeof id !== 'string' || id.trim().length === 0)\n ) {\n throw new Error('answer-quality evidence requires at least 2 unique final scenario IDs')\n }\n if (!result.metrics || typeof result.metrics !== 'object' || Array.isArray(result.metrics)) {\n throw new Error('answer-quality evidence requires non-empty finite metrics')\n }\n const metrics = Object.entries(result.metrics)\n if (\n metrics.length === 0 ||\n metrics.some(([key, value]) => key.trim().length === 0 || !Number.isFinite(value))\n ) {\n throw new Error('answer-quality evidence requires non-empty finite metrics')\n }\n if (!result.cost || typeof result.cost !== 'object') {\n throw new Error('answer-quality evidence requires cost accounting')\n }\n if (\n !Number.isFinite(result.cost.totalCostUsd) ||\n result.cost.totalCostUsd < 0 ||\n typeof result.cost.accountingComplete !== 'boolean' ||\n !Array.isArray(result.cost.incompleteReasons) ||\n result.cost.incompleteReasons.some((reason) => typeof reason !== 'string' || !reason.trim())\n ) {\n throw new Error('answer-quality evidence has invalid cost accounting')\n }\n if (result.cost.accountingComplete && result.cost.incompleteReasons.length > 0) {\n throw new Error('complete answer-quality cost accounting cannot include incomplete reasons')\n }\n}\n\nexport function ragAnswerEvidenceRejectionReasons(\n evidence: RagAnswerEvidence,\n costCeiling: number | undefined,\n): string[] {\n const reasons: string[] = []\n if (!evidence.passed) reasons.push('answer-quality evaluation failed')\n if (!evidence.cost.accountingComplete) {\n reasons.push('answer-quality final comparison has incomplete cost accounting')\n }\n if (costCeiling === undefined) {\n reasons.push('answer-quality promotion requires answerQualityCostCeiling')\n } else if (exceedsCostCeiling(evidence.cost.totalCostUsd, costCeiling)) {\n reasons.push(\n `answer-quality final comparison cost ${evidence.cost.totalCostUsd} exceeds ${costCeiling}`,\n )\n }\n return reasons\n}\n\nfunction exceedsCostCeiling(totalCostUsd: number, costCeiling: number): boolean {\n const tolerance = Number.EPSILON * Math.max(1, Math.abs(totalCostUsd), Math.abs(costCeiling)) * 8\n return totalCostUsd - costCeiling > tolerance\n}\n","/**\n * Claim-grounding mode for `runVerifiedResearchLoop`.\n *\n * The two-agent loop's existing verifier judges a source's on-topic RELEVANCE\n * (is this page about the goal?). On the topic sets we have measured, its\n * cleanliness win is dominated by DE-DUPLICATION — which a deterministic\n * content-hash / canonical-URL check captures at ~none of the LLM premium (see\n * `docs/results/cost-quality.md`). That makes the LLM verifier look expensive\n * for what a cheap rule already does.\n *\n * Claim-grounding targets a DIFFERENT, harder error band: a citation that is\n * relevant and unique but **misattributed** — the page is on-topic, the URL is\n * real, yet the specific CLAIM the source is cited for does NOT actually appear\n * in the page. This is the citation-fabrication failure mode of LLM research:\n * the model writes a plausible sentence and hangs a real URL off it that never\n * says any such thing. Neither de-dup nor a relevance judge catches it (both can\n * pass a misattributed-but-on-topic page); only checking the claim against the\n * fetched text does.\n *\n * The check is EXECUTABLE GROUND TRUTH, not another LLM opinion: the worker\n * attaches the specific claim it is citing the source for, and the verifier\n * tests whether that claim is PRESENT (verbatim, normalized, or as a sufficient\n * content-word overlap / close paraphrase) in the `htmlToText` output of the\n * page the worker actually fetched. A claim that is not grounded is rejected as\n * misattributed. Because the oracle is deterministic text presence — not a model\n * call — it is a deployable, non-oracle verifier: it can run in production with\n * zero inference cost, OR be composed with the LLM relevance verifier so the\n * loop rejects BOTH off-topic AND misattributed sources.\n *\n * This module is content-free and any-topic: it adds (1) a way for a proposal to\n * carry the claim it is cited for, (2) the `groundClaimInText` oracle, and (3) a\n * `ResearchDriver` that gates on grounding. It composes the existing\n * `ResearchDriver` / `ResearchSourceProposal` contracts and the shipped\n * `htmlToText`; it reinvents none of them.\n */\n\nimport type {\n ResearchSourceProposal,\n SourceVerdict,\n SourceVerificationContext,\n} from './verified-research-loop'\nimport {\n createTangleRouterClient,\n type RouterClient,\n type TangleRouterOptions,\n} from './web-research-worker'\n\n/**\n * Metadata key under which a proposal carries the specific claim it is cited\n * for. The worker sets `metadata[citedClaimKey] = '<the claim>'`; the\n * claim-grounding driver reads it and checks it against the fetched page text.\n */\nexport const citedClaimKey = 'citedClaim'\n\n/** Read the cited claim a proposal carries, if any. */\nexport function citedClaimOf(source: ResearchSourceProposal): string | undefined {\n const claim = source.metadata?.[citedClaimKey]\n return typeof claim === 'string' && claim.trim() ? claim.trim() : undefined\n}\n\n/** Attach a cited claim to a proposal (immutably returns a new proposal). */\nexport function withCitedClaim(\n source: ResearchSourceProposal,\n claim: string,\n): ResearchSourceProposal {\n return { ...source, metadata: { ...source.metadata, [citedClaimKey]: claim } }\n}\n\nexport interface GroundingResult {\n /** True when the claim is sufficiently present in the page text. */\n grounded: boolean\n /** How the claim matched (or why it didn't). For audit/notes. */\n mode: 'verbatim' | 'normalized' | 'overlap' | 'absent' | 'empty-claim' | 'empty-text'\n /**\n * Fraction of the claim's content words found in the page text. 1 for a\n * verbatim/normalized hit; the measured overlap otherwise.\n */\n overlap: number\n /** Content words present in the claim but NOT in the page text. */\n missingWords: string[]\n}\n\nexport interface GroundClaimOptions {\n /**\n * Minimum fraction of the claim's content words that must appear in the page\n * text to count as a close paraphrase when there is no verbatim/normalized\n * hit. Default 0.7 — a high bar, because a misattribution is exactly a claim\n * whose specific words the page does not contain.\n */\n minOverlap?: number\n /**\n * Content words shorter than this are ignored (drops \"the\", \"of\", \"is\", …)\n * and never count toward overlap. Default 3.\n */\n minWordLength?: number\n}\n\n/**\n * Stopwords stripped before overlap scoring so the bar measures the claim's\n * SUBSTANTIVE words (the numbers, nouns, methods it asserts), not filler a\n * misattributed page would trivially share with the real one.\n */\nconst stopwords = new Set([\n 'the',\n 'a',\n 'an',\n 'and',\n 'or',\n 'but',\n 'of',\n 'to',\n 'in',\n 'on',\n 'for',\n 'with',\n 'as',\n 'by',\n 'at',\n 'from',\n 'that',\n 'this',\n 'these',\n 'those',\n 'it',\n 'its',\n 'is',\n 'are',\n 'was',\n 'were',\n 'be',\n 'been',\n 'being',\n 'has',\n 'have',\n 'had',\n 'can',\n 'will',\n 'would',\n 'should',\n 'may',\n 'might',\n 'not',\n 'no',\n 'than',\n 'then',\n 'over',\n 'under',\n 'about',\n 'into',\n 'their',\n 'they',\n 'them',\n])\n\n/** Normalize for presence checks: lowercase, collapse whitespace + punctuation. */\nfunction normalize(text: string): string {\n return text\n .toLowerCase()\n .replace(/[^\\p{L}\\p{N}\\s]+/gu, ' ')\n .replace(/\\s+/g, ' ')\n .trim()\n}\n\n/** The claim's substantive content words (deduped, stopwords + short words removed). */\nfunction contentWords(claim: string, minWordLength: number): string[] {\n const words = normalize(claim)\n .split(' ')\n .filter((word) => word.length >= minWordLength && !stopwords.has(word))\n return [...new Set(words)]\n}\n\n/**\n * THE ORACLE. Is `claim` grounded in `pageText` (the `htmlToText` output of the\n * page the worker fetched)? Deterministic, no model call:\n *\n * 1. verbatim — the claim string appears as-is (case-insensitive).\n * 2. normalized — the claim appears after collapsing punctuation/whitespace\n * on both sides (so \"5.4x\" vs \"5.4 x\", smart quotes, etc. still match).\n * 3. overlap — a close paraphrase: at least `minOverlap` of the claim's\n * substantive content words appear in the page text. A misattributed page\n * fails here because the SPECIFIC words the claim asserts are absent.\n *\n * Returns the match mode, the measured overlap, and the missing content words —\n * enough for the driver to give a precise rejection reason and for a test/doc to\n * audit WHY a claim grounded or didn't.\n */\nexport function groundClaimInText(\n claim: string,\n pageText: string,\n options: GroundClaimOptions = {},\n): GroundingResult {\n const minOverlap = options.minOverlap ?? 0.7\n const minWordLength = Math.max(1, options.minWordLength ?? 3)\n\n const claimTrimmed = claim.trim()\n if (!claimTrimmed) return { grounded: false, mode: 'empty-claim', overlap: 0, missingWords: [] }\n if (!pageText.trim()) return { grounded: false, mode: 'empty-text', overlap: 0, missingWords: [] }\n\n const haystackLower = pageText.toLowerCase()\n if (haystackLower.includes(claimTrimmed.toLowerCase())) {\n return { grounded: true, mode: 'verbatim', overlap: 1, missingWords: [] }\n }\n\n const haystackNorm = normalize(pageText)\n const claimNorm = normalize(claimTrimmed)\n if (claimNorm && haystackNorm.includes(claimNorm)) {\n return { grounded: true, mode: 'normalized', overlap: 1, missingWords: [] }\n }\n\n const words = contentWords(claimTrimmed, minWordLength)\n if (words.length === 0) {\n // The claim has no substantive content words (all stopwords/short). With no\n // verbatim/normalized hit there is nothing to ground — treat as absent.\n return { grounded: false, mode: 'absent', overlap: 0, missingWords: [] }\n }\n // Word-boundary presence so \"rotary\" does not match inside \"rotaryxyz\".\n const present = words.filter((word) =>\n new RegExp(`\\\\b${word.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}\\\\b`).test(haystackNorm),\n )\n const missingWords = words.filter((word) => !present.includes(word))\n const overlap = present.length / words.length\n const grounded = overlap >= minOverlap\n return { grounded, mode: grounded ? 'overlap' : 'absent', overlap, missingWords }\n}\n\nexport interface ClaimGroundingDriverOptions extends GroundClaimOptions {\n /**\n * Optional second verifier to compose AFTER grounding passes. When set, a\n * source must BOTH ground its claim AND pass this verifier (e.g. the LLM\n * relevance driver's `verifySource`). Lets the loop reject off-topic AND\n * misattributed sources in one driver. Omit for the pure, zero-inference\n * grounding gate.\n */\n relevanceVerifier?: (\n source: ResearchSourceProposal,\n ctx: SourceVerificationContext,\n ) => Promise<SourceVerdict> | SourceVerdict\n /**\n * What to do when a proposal carries NO cited claim. `'reject'` (default) is\n * fail-closed: in claim-grounding mode every source must declare what it is\n * cited for, so an un-annotated source is treated as ungrounded. `'accept'`\n * lets unannotated sources through to the relevance verifier, if present.\n */\n onMissingClaim?: 'reject' | 'accept'\n}\n\n/**\n * A `ResearchDriver`-shaped verifier (just the `verifySource` arm) that gates on\n * CLAIM GROUNDING: it rejects a source whose cited claim is not present in its\n * fetched page text — a misattributed / fabricated citation — and (optionally)\n * composes a relevance verifier after grounding passes.\n *\n * The returned function matches `ResearchDriver['verifySource']`, so it drops\n * straight into `runVerifiedResearchLoop` as `{ verifySource: createClaimGroundingVerifier(...) }`.\n */\nexport function createClaimGroundingVerifier(options: ClaimGroundingDriverOptions = {}) {\n const onMissingClaim = options.onMissingClaim ?? 'reject'\n return async function verifySource(\n source: ResearchSourceProposal,\n ctx: SourceVerificationContext,\n ): Promise<SourceVerdict> {\n const claim = citedClaimOf(source)\n if (!claim) {\n if (onMissingClaim === 'reject') {\n return {\n accept: false,\n reason: 'no cited claim: claim-grounding mode requires every source to declare its claim',\n }\n }\n return options.relevanceVerifier ? options.relevanceVerifier(source, ctx) : { accept: true }\n }\n\n const grounding = groundClaimInText(claim, source.text, options)\n if (!grounding.grounded) {\n const detail =\n grounding.mode === 'empty-text'\n ? 'fetched page has no text'\n : `claim not found in the fetched page (overlap ${(grounding.overlap * 100).toFixed(0)}%${\n grounding.missingWords.length\n ? `, missing: ${grounding.missingWords.slice(0, 6).join(', ')}`\n : ''\n })`\n return {\n accept: false,\n reason: `misattributed citation: ${detail}`,\n }\n }\n\n if (options.relevanceVerifier) return options.relevanceVerifier(source, ctx)\n return { accept: true }\n }\n}\n\nexport interface WorkerClaimDecorationOptions {\n router?: RouterClient\n router_options?: TangleRouterOptions\n /** Max output tokens for the claim-extraction call. Default 1200 (glm floor). */\n maxTokens?: number\n}\n\n/**\n * Ask an LLM to state, for one source, the single specific factual claim a\n * researcher would cite THIS page for toward the goal. Used to DECORATE the\n * sources a relevance-only worker produced with the claim a citation would make,\n * so the claim-grounding verifier has something executable to check. The model\n * is told to ground the claim in the provided excerpt; the verifier then checks\n * it against the FULL page text independently — the model does not get to mark\n * its own homework.\n *\n * Returns the proposal annotated via `withCitedClaim`, or the original proposal\n * unchanged if the model returns nothing parseable (the verifier's\n * `onMissingClaim` policy then decides).\n */\nexport function createClaimDecorator(options: WorkerClaimDecorationOptions = {}) {\n const maxTokens = options.maxTokens ?? 1200\n return async function decorate(\n source: ResearchSourceProposal,\n goal: string,\n ): Promise<ResearchSourceProposal> {\n const router = options.router ?? createTangleRouterClient(options.router_options)\n const excerpt = source.text.slice(0, 1500)\n const system =\n 'You extract the single most important factual claim a researcher would cite a page for. ' +\n \"State ONE concrete, checkable sentence using the page's own key terms and numbers. \" +\n 'Do NOT invent facts not in the excerpt. Respond with ONLY the claim sentence, no prose.'\n const user = [\n `Research goal: ${goal}`,\n `Page title: ${source.title ?? '(none)'}`,\n `Page excerpt:\\n${excerpt}`,\n 'The single claim this page should be cited for:',\n ].join('\\n\\n')\n let raw = ''\n try {\n raw = await router.chat(\n [\n { role: 'system', content: system },\n { role: 'user', content: user },\n ],\n maxTokens,\n )\n } catch {\n return source\n }\n const claim = raw.trim().split('\\n')[0]?.trim()\n if (!claim) return source\n return withCitedClaim(source, claim)\n }\n}\n","import { groundClaimInText } from '../claim-grounding'\nimport { mean } from '../statistics'\nimport type {\n RagAnswerEvalArtifact,\n RagAnswerEvalScenario,\n RagAnswerQualityJudgeOptions,\n RagEvalCitation,\n RagEvalClaim,\n RagEvalContext,\n RagRequiredContext,\n} from './contracts'\n\nexport function requiredContextTargets(scenario: RagAnswerEvalScenario): RagRequiredContext[] {\n if (scenario.requiredContext?.length) return [...scenario.requiredContext]\n return (scenario.expectedClaims ?? []).map((text) => ({ text }))\n}\n\nexport function requiredContextTexts(scenario: RagAnswerEvalScenario): string[] {\n return requiredContextTargets(scenario).flatMap((target) => (target.text ? [target.text] : []))\n}\n\nexport function contextMatchesTarget(context: RagEvalContext, target: RagRequiredContext): boolean {\n if (target.id && context.id === target.id) return true\n if (target.pageId && context.pageId === target.pageId) return true\n if (target.sourceId && context.sourceId === target.sourceId) return true\n if (target.anchorId && context.anchorId === target.anchorId) return true\n if (target.text && textSupportScore(target.text, context.text) >= 0.7) return true\n return false\n}\n\nexport function contextIsRelevant(\n context: RagEvalContext,\n scenario: RagAnswerEvalScenario,\n): boolean {\n return contextRelevanceScore(context, scenario) >= 0.3\n}\n\nexport function contextRelevanceScore(\n context: RagEvalContext,\n scenario: RagAnswerEvalScenario,\n): number {\n const targets = [\n scenario.query,\n scenario.referenceAnswer,\n ...(scenario.expectedClaims ?? []),\n ...requiredContextTexts(scenario),\n ].filter((value): value is string => Boolean(value?.trim()))\n if (targets.length === 0) return 1\n return Math.max(...targets.map((target) => textSupportScore(target, context.text)))\n}\n\nexport function claimSupport(\n claim: string,\n contexts: readonly RagEvalContext[],\n options: Pick<RagAnswerQualityJudgeOptions, 'minClaimSupport'>,\n): boolean {\n if (contexts.length === 0) return false\n const combined = contexts.map((context) => context.text).join('\\n\\n')\n const deterministic = groundClaimInText(claim, combined, {\n minOverlap: options.minClaimSupport ?? 0.7,\n })\n return (\n deterministic.grounded || textSupportScore(claim, combined) >= (options.minClaimSupport ?? 0.7)\n )\n}\n\nexport function scoreCitations(\n claims: readonly RagEvalClaim[],\n artifact: RagAnswerEvalArtifact,\n scenario: RagAnswerEvalScenario,\n options: Pick<RagAnswerQualityJudgeOptions, 'minClaimSupport'>,\n): { support: number; citedClaimCount: number; supportedCitationCount: number } {\n if (claims.length === 0)\n return { support: scenario.unanswerable ? 1 : 0, citedClaimCount: 0, supportedCitationCount: 0 }\n const citations = artifact.citations ?? []\n const citedClaims = claims.filter((claim) => citationsForClaim(claim, citations).length > 0)\n if (citedClaims.length === 0) {\n return {\n support: scenario.requireCitations ? 0 : 1,\n citedClaimCount: 0,\n supportedCitationCount: 0,\n }\n }\n let supportedCitationCount = 0\n for (const claim of citedClaims) {\n const citedContexts = contextsForClaim(claim, citations, artifact.contexts)\n if (claimSupport(claim.text, citedContexts, options)) supportedCitationCount += 1\n }\n return {\n support: supportedCitationCount / citedClaims.length,\n citedClaimCount: citedClaims.length,\n supportedCitationCount,\n }\n}\n\nfunction citationsForClaim(\n claim: RagEvalClaim,\n citations: readonly RagEvalCitation[],\n): RagEvalCitation[] {\n const claimCitationIds = new Set(claim.citationIds ?? [])\n return citations.filter((citation) => {\n return citation.claimId === claim.id || (citation.id && claimCitationIds.has(citation.id))\n })\n}\n\nfunction contextsForClaim(\n claim: RagEvalClaim,\n citations: readonly RagEvalCitation[],\n contexts: readonly RagEvalContext[],\n): readonly RagEvalContext[] {\n const matchedCitations = citationsForClaim(claim, citations)\n const matchedContexts = contexts.filter((context) =>\n matchedCitations.some((citation) => {\n if (citation.contextId && citation.contextId === context.id) return true\n if (citation.pageId && citation.pageId === context.pageId) return true\n if (citation.sourceId && citation.sourceId === context.sourceId) return true\n if (citation.anchorId && citation.anchorId === context.anchorId) return true\n return false\n }),\n )\n return matchedContexts.length > 0 ? matchedContexts : contexts\n}\n\nexport function scoreAnswerRelevance(\n artifact: RagAnswerEvalArtifact,\n scenario: RagAnswerEvalScenario,\n abstained: boolean,\n): number {\n if (scenario.unanswerable) return abstained ? 1 : 0\n if (abstained) return 0\n const targets = [\n scenario.referenceAnswer,\n ...(scenario.expectedClaims ?? []),\n scenario.query,\n ].filter((value): value is string => Boolean(value?.trim()))\n return Math.max(...targets.map((target) => textSupportScore(target, artifact.answer)))\n}\n\nexport function scoreAnswerCorrectness(\n artifact: RagAnswerEvalArtifact,\n scenario: RagAnswerEvalScenario,\n abstained: boolean,\n): number {\n if (scenario.unanswerable) return abstained ? 1 : 0\n const expected = scenario.expectedClaims ?? []\n const forbidden = scenario.forbiddenClaims ?? []\n const expectedScore =\n expected.length === 0\n ? scoreAnswerRelevance(artifact, scenario, abstained)\n : mean(expected.map((claim) => textSupportScore(claim, artifact.answer)))\n const forbiddenPenalty =\n forbidden.length === 0\n ? 0\n : forbidden.filter((claim) => textSupportScore(claim, artifact.answer) >= 0.7).length /\n forbidden.length\n return clamp01(expectedScore * (1 - forbiddenPenalty))\n}\n\nexport function normalizeClaims(artifact: RagAnswerEvalArtifact): RagEvalClaim[] {\n if (artifact.claims?.length) return [...artifact.claims]\n return splitSentences(artifact.answer).map((text, index) => ({ id: `claim-${index + 1}`, text }))\n}\n\nfunction splitSentences(text: string): string[] {\n return text\n .split(/(?<=[.!?])\\s+/)\n .map((sentence) => sentence.trim())\n .filter((sentence) => sentence.length > 0 && !looksLikeAbstention(sentence))\n}\n\nexport function looksLikeAbstention(answer: string): boolean {\n const normalized = answer.toLowerCase()\n return [\n \"i don't know\",\n 'i do not know',\n 'not enough information',\n 'cannot answer',\n \"can't answer\",\n 'insufficient information',\n 'no reliable answer',\n ].some((phrase) => normalized.includes(phrase))\n}\n\nfunction textSupportScore(needle: string, haystack: string): number {\n const needleWords = contentWords(needle)\n if (needleWords.length === 0) return 0\n const haystackWords = new Set(contentWords(haystack))\n const present = needleWords.filter((word) => haystackWords.has(word))\n return present.length / needleWords.length\n}\n\nfunction contentWords(text: string): string[] {\n const normalized = text\n .toLowerCase()\n .replace(/[^\\p{L}\\p{N}\\s]+/gu, ' ')\n .split(/\\s+/)\n .map((word) => stem(word.trim()))\n .filter((word) => (word.length >= 3 || /^\\d+$/.test(word)) && !stopwords.has(word))\n return [...new Set(normalized)]\n}\n\nfunction stem(word: string): string {\n if (word.endsWith('ies') && word.length > 4) return `${word.slice(0, -3)}y`\n if (word.endsWith('ing') && word.length > 5) return word.slice(0, -3)\n if (word.endsWith('ed') && word.length > 4) return word.slice(0, -2)\n if (word.endsWith('s') && word.length > 3) return word.slice(0, -1)\n return word\n}\n\nexport function neutralScore(condition: boolean): number {\n return condition ? 1 : 0\n}\n\nexport function clamp01(value: number): number {\n if (!Number.isFinite(value)) return 0\n return Math.max(0, Math.min(1, value))\n}\n\nconst stopwords = new Set([\n 'the',\n 'a',\n 'an',\n 'and',\n 'or',\n 'but',\n 'of',\n 'to',\n 'in',\n 'on',\n 'for',\n 'with',\n 'as',\n 'by',\n 'at',\n 'from',\n 'that',\n 'this',\n 'these',\n 'those',\n 'it',\n 'its',\n 'is',\n 'are',\n 'was',\n 'were',\n 'be',\n 'been',\n 'being',\n 'has',\n 'have',\n 'had',\n 'can',\n 'will',\n 'would',\n 'should',\n 'may',\n 'might',\n 'not',\n 'no',\n 'than',\n 'then',\n 'over',\n 'under',\n 'about',\n 'into',\n 'their',\n 'they',\n 'them',\n 'what',\n 'when',\n 'where',\n 'who',\n 'why',\n 'how',\n])\n","import { clamp01, normalizeClaims, requiredContextTexts } from './answer'\nimport type { ExternalRagEvalScore, RagAnswerEvalCase, RagEvalMetricKey } from './contracts'\n\nconst metricAliases: Record<string, RagEvalMetricKey> = {\n answer_correctness: 'answer_correctness',\n answer_relevance: 'answer_relevance',\n answer_relevancy: 'answer_relevance',\n answerrelevancy: 'answer_relevance',\n context_precision: 'context_precision',\n context_recall: 'context_recall',\n context_relevance: 'context_relevance',\n context_relevancy: 'context_relevance',\n context_sufficiency: 'context_sufficiency',\n contextual_precision: 'context_precision',\n contextual_recall: 'context_recall',\n contextual_relevancy: 'context_relevance',\n faithfulness: 'faithfulness',\n groundedness: 'groundedness',\n claim_recall: 'context_recall',\n claim_precision: 'faithfulness',\n citation_support: 'citation_support',\n abstention: 'abstention',\n unsupported_answer_rate: 'unsupported_answer_rate',\n}\n\nexport function normalizeExternalRagScores(\n scores: readonly ExternalRagEvalScore[],\n): Record<string, Record<RagEvalMetricKey, number>> {\n const normalized: Record<string, Record<RagEvalMetricKey, number>> = {}\n for (const item of scores) {\n const provider = item.provider || 'custom'\n const providerScores = (normalized[provider] ?? {}) as Record<RagEvalMetricKey, number>\n for (const [key, value] of Object.entries(item.scores)) {\n const canonical = metricAliases[normalizeMetricName(key)]\n if (!canonical) continue\n if (Number.isFinite(value)) providerScores[canonical] = clamp01(value)\n }\n normalized[provider] = providerScores\n }\n return normalized\n}\n\nexport function toRagasEvaluationRows(cases: readonly RagAnswerEvalCase[]) {\n return cases.map(({ scenario, artifact }) => ({\n user_input: scenario.query,\n response: artifact.answer,\n retrieved_contexts: artifact.contexts.map((context) => context.text),\n reference: scenario.referenceAnswer,\n reference_contexts: requiredContextTexts(scenario),\n }))\n}\n\nexport function toDeepEvalTestCases(cases: readonly RagAnswerEvalCase[]) {\n return cases.map(({ scenario, artifact }) => ({\n input: scenario.query,\n actual_output: artifact.answer,\n expected_output: scenario.referenceAnswer,\n retrieval_context: artifact.contexts.map((context) => context.text),\n context: requiredContextTexts(scenario),\n }))\n}\n\nexport function toTruLensRecords(cases: readonly RagAnswerEvalCase[]) {\n return cases.map(({ scenario, artifact }) => ({\n input: scenario.query,\n output: artifact.answer,\n context: artifact.contexts.map((context) => context.text).join('\\n\\n'),\n }))\n}\n\nexport function toRagCheckerRecords(cases: readonly RagAnswerEvalCase[]) {\n return cases.map(({ scenario, artifact }) => ({\n query_id: scenario.id,\n query: scenario.query,\n gt_answer: scenario.referenceAnswer,\n response: artifact.answer,\n retrieved_context: artifact.contexts.map((context) => ({\n doc_id: context.id,\n text: context.text,\n })),\n claims: normalizeClaims(artifact).map((claim) => claim.text),\n }))\n}\n\nfunction normalizeMetricName(metric: string): string {\n return metric\n .trim()\n .toLowerCase()\n .replace(/[@/.-]+/g, '_')\n .replace(/\\s+/g, '_')\n}\n","import type { JudgeConfig } from '@tangle-network/agent-eval/campaign'\nimport type { RagGapFinding } from '../rag-improvement-loop'\nimport { mean } from '../statistics'\nimport {\n claimSupport,\n clamp01,\n contextIsRelevant,\n contextMatchesTarget,\n contextRelevanceScore,\n looksLikeAbstention,\n neutralScore,\n normalizeClaims,\n requiredContextTargets,\n scoreAnswerCorrectness,\n scoreAnswerRelevance,\n scoreCitations,\n} from './answer'\nimport type {\n RagAnswerEvalArtifact,\n RagAnswerEvalScenario,\n RagAnswerMetricSummary,\n RagAnswerQualityJudgeOptions,\n RagEvalMetricKey,\n} from './contracts'\nimport { normalizeExternalRagScores } from './providers'\n\nconst defaultThresholds: Partial<Record<RagEvalMetricKey, number>> = {\n context_precision: 0.5,\n context_recall: 0.8,\n context_relevance: 0.5,\n context_sufficiency: 0.8,\n faithfulness: 0.9,\n answer_relevance: 0.7,\n citation_support: 0.9,\n abstention: 1,\n unsupported_answer_rate: 0,\n}\n\nconst defaultWeights: Partial<Record<RagEvalMetricKey, number>> = {\n context_relevance: 1,\n context_sufficiency: 1,\n faithfulness: 2,\n answer_relevance: 1,\n citation_support: 1,\n abstention: 1,\n}\n\nexport function ragAnswerQualityJudge(\n options: RagAnswerQualityJudgeOptions = {},\n): JudgeConfig<RagAnswerEvalArtifact, RagAnswerEvalScenario> {\n return {\n name: options.name ?? 'rag-answer-quality',\n dimensions: [\n { key: 'context_precision', description: 'share of retrieved context that is useful' },\n { key: 'context_recall', description: 'share of required evidence present in context' },\n { key: 'context_relevance', description: 'context relevance to the query and answer target' },\n { key: 'context_sufficiency', description: 'whether context is enough to answer' },\n { key: 'faithfulness', description: 'share of answer claims supported by retrieved context' },\n { key: 'answer_relevance', description: 'answer addresses the user query' },\n { key: 'answer_correctness', description: 'answer contains expected claims' },\n { key: 'citation_support', description: 'citations support the claims they cite' },\n { key: 'abstention', description: 'answer abstains exactly when the case is unanswerable' },\n ],\n appliesTo: (scenario) => scenario.kind === 'rag-answer-eval',\n async score({ artifact, scenario }) {\n const summary = scoreRagAnswerArtifact(artifact, scenario, options)\n return {\n dimensions: summary.metrics,\n composite: summary.composite,\n notes: summary.findings.map((finding) => finding.message).join('; '),\n }\n },\n }\n}\n\nexport function scoreRagAnswerArtifact(\n artifact: RagAnswerEvalArtifact,\n scenario: RagAnswerEvalScenario,\n options: RagAnswerQualityJudgeOptions = {},\n): RagAnswerMetricSummary {\n const claims = normalizeClaims(artifact)\n const abstained = artifact.abstained ?? looksLikeAbstention(artifact.answer)\n const requiredTargets = requiredContextTargets(scenario)\n const matchedRequiredContextCount = requiredTargets.filter((target) =>\n artifact.contexts.some((context) => contextMatchesTarget(context, target)),\n ).length\n const requiredContextCount = requiredTargets.length\n const contextRecall =\n requiredContextCount === 0\n ? neutralScore(Boolean(scenario.unanswerable) || artifact.contexts.length > 0)\n : matchedRequiredContextCount / requiredContextCount\n const relevantContextCount = artifact.contexts.filter((context) =>\n contextIsRelevant(context, scenario),\n ).length\n const contextPrecision =\n artifact.contexts.length === 0\n ? scenario.unanswerable\n ? 1\n : 0\n : relevantContextCount / artifact.contexts.length\n const contextRelevance =\n artifact.contexts.length === 0\n ? scenario.unanswerable\n ? 1\n : 0\n : mean(artifact.contexts.map((context) => contextRelevanceScore(context, scenario)))\n const contextSufficiency = requiredContextCount === 0 ? contextRelevance : contextRecall\n const support = claims.map((claim) => claimSupport(claim.text, artifact.contexts, options))\n const supportedClaimCount = support.filter(Boolean).length\n const faithfulness =\n claims.length === 0 ? (abstained ? 1 : 0) : supportedClaimCount / Math.max(1, claims.length)\n const citation = scoreCitations(claims, artifact, scenario, options)\n const answerRelevance = scoreAnswerRelevance(artifact, scenario, abstained)\n const answerCorrectness = scoreAnswerCorrectness(artifact, scenario, abstained)\n const abstention = scenario.unanswerable ? (abstained ? 1 : 0) : abstained ? 0 : 1\n const unsupportedAnswerRate =\n claims.length === 0 ? (abstained ? 0 : 1) : 1 - supportedClaimCount / Math.max(1, claims.length)\n\n const deterministicMetrics: Record<RagEvalMetricKey, number> = {\n context_precision: clamp01(contextPrecision),\n context_recall: clamp01(contextRecall),\n context_relevance: clamp01(contextRelevance),\n context_sufficiency: clamp01(contextSufficiency),\n faithfulness: clamp01(faithfulness),\n groundedness: clamp01(faithfulness),\n answer_relevance: clamp01(answerRelevance),\n answer_correctness: clamp01(answerCorrectness),\n citation_support: clamp01(citation.support),\n abstention: clamp01(abstention),\n unsupported_answer_rate: clamp01(unsupportedAnswerRate),\n }\n const providerScores = normalizeExternalRagScores(artifact.externalScores ?? [])\n const metrics = mergeMetrics(deterministicMetrics, providerScores, options.externalScorePolicy)\n const thresholds = { ...defaultThresholds, ...scenario.thresholds, ...options.thresholds }\n const findings = diagnoseRagAnswerFailure(metrics, scenario, thresholds)\n const composite = weightedComposite(metrics, options.weights ?? defaultWeights)\n\n return {\n metrics,\n composite,\n passed: findings.every(\n (finding) => finding.severity !== 'error' && finding.severity !== 'critical',\n ),\n findings,\n claimCount: claims.length,\n supportedClaimCount,\n citedClaimCount: citation.citedClaimCount,\n supportedCitationCount: citation.supportedCitationCount,\n matchedRequiredContextCount,\n requiredContextCount,\n providerScores,\n }\n}\n\nexport function diagnoseRagAnswerFailure(\n metrics: Record<RagEvalMetricKey, number>,\n scenario: RagAnswerEvalScenario,\n thresholds: Partial<Record<RagEvalMetricKey, number>> = defaultThresholds,\n): RagGapFinding[] {\n const findings: RagGapFinding[] = []\n if (below(metrics.context_recall, thresholds.context_recall)) {\n findings.push({\n id: `${scenario.id}:context-recall`,\n kind: scenario.slices?.includes('multi-source')\n ? 'missing-multihop-evidence'\n : 'retrieval-miss',\n severity: 'error',\n scenarioId: scenario.id,\n message: 'Required evidence was not present in retrieved context.',\n evidence: { context_recall: metrics.context_recall },\n })\n }\n if (below(metrics.context_precision, thresholds.context_precision)) {\n findings.push({\n id: `${scenario.id}:context-precision`,\n kind: 'retrieval-noise',\n severity: 'warning',\n scenarioId: scenario.id,\n message: 'Retrieved context contains too much irrelevant material.',\n evidence: { context_precision: metrics.context_precision },\n })\n }\n if (below(metrics.faithfulness, thresholds.faithfulness)) {\n findings.push({\n id: `${scenario.id}:faithfulness`,\n kind: 'generator-unsupported-claim',\n severity: 'error',\n scenarioId: scenario.id,\n message: 'The answer contains claims not supported by retrieved context.',\n evidence: { faithfulness: metrics.faithfulness },\n })\n }\n if (below(metrics.citation_support, thresholds.citation_support)) {\n findings.push({\n id: `${scenario.id}:citation-support`,\n kind: 'citation-mismatch',\n severity: 'error',\n scenarioId: scenario.id,\n message: 'Citations do not support the claims they are attached to.',\n evidence: { citation_support: metrics.citation_support },\n })\n }\n if (below(metrics.abstention, thresholds.abstention)) {\n findings.push({\n id: `${scenario.id}:abstention`,\n kind: 'incorrect-abstention',\n severity: 'error',\n scenarioId: scenario.id,\n message: scenario.unanswerable\n ? 'The system answered a case marked unanswerable.'\n : 'The system abstained from an answerable case.',\n evidence: { abstention: metrics.abstention },\n })\n }\n return findings\n}\n\nfunction mergeMetrics(\n deterministic: Record<RagEvalMetricKey, number>,\n providerScores: Record<string, Record<RagEvalMetricKey, number>>,\n policy: RagAnswerQualityJudgeOptions['externalScorePolicy'] = 'prefer-external',\n): Record<RagEvalMetricKey, number> {\n if (policy === 'deterministic-first') return deterministic\n const merged = { ...deterministic }\n for (const scores of Object.values(providerScores)) {\n for (const [key, value] of Object.entries(scores) as Array<[RagEvalMetricKey, number]>) {\n merged[key] = value\n if (key === 'groundedness') merged.faithfulness = value\n if (key === 'faithfulness') merged.groundedness = value\n }\n }\n return merged\n}\n\nexport function aggregateRagAnswerMetrics(\n summaries: readonly RagAnswerMetricSummary[],\n): Record<string, number> {\n const keys = new Set<RagEvalMetricKey>()\n for (const summary of summaries) {\n for (const key of Object.keys(summary.metrics) as RagEvalMetricKey[]) keys.add(key)\n }\n const out: Record<string, number> = {}\n for (const key of [...keys].sort()) {\n out[key] = mean(summaries.map((summary) => summary.metrics[key]))\n }\n out.composite = mean(summaries.map((summary) => summary.composite))\n return out\n}\n\nfunction weightedComposite(\n metrics: Record<RagEvalMetricKey, number>,\n weights: Partial<Record<RagEvalMetricKey, number>>,\n): number {\n let weighted = 0\n let total = 0\n for (const [key, weight] of Object.entries(weights) as Array<[RagEvalMetricKey, number]>) {\n if (!Number.isFinite(weight) || weight <= 0) continue\n const metric = metrics[key]\n if (!Number.isFinite(metric)) continue\n const value = key === 'unsupported_answer_rate' ? 1 - metric : metric\n weighted += value * weight\n total += weight\n }\n return total === 0 ? 0 : weighted / total\n}\n\nfunction below(metric: number, threshold: number | undefined): boolean {\n return threshold !== undefined && metric < threshold\n}\n","import { contentHash } from '@tangle-network/agent-eval'\nimport { assertImmutableRef } from '../immutable-ref'\nimport type { RagAnswerQualityResult, RagGapFinding } from '../rag-improvement-loop'\nimport type {\n RagAnswerMetricSummary,\n RagAnswerQualityHookOptions,\n RagCalibrationOptions,\n RagCalibrationResult,\n} from './contracts'\nimport { aggregateRagAnswerMetrics, ragAnswerQualityJudge, scoreRagAnswerArtifact } from './scoring'\n\nexport function createRagAnswerQualityHook(\n options: RagAnswerQualityHookOptions,\n): () => Promise<RagAnswerQualityResult> {\n assertImmutableRef(options.evaluatorRef, 'RAG answer evaluatorRef')\n const finalScenarioIds = options.scenarios.map((scenario) => scenario.id)\n if (\n finalScenarioIds.length < 2 ||\n new Set(finalScenarioIds).size !== finalScenarioIds.length ||\n finalScenarioIds.some((id) => !id.trim())\n ) {\n throw new Error('RAG answer quality requires at least 2 unique final scenarios')\n }\n const datasetRef = `sha256:${contentHash(options.scenarios)}`\n return async () => {\n const summaries: RagAnswerMetricSummary[] = []\n const findings: RagGapFinding[] = []\n for (const scenario of options.scenarios) {\n const initialArtifact = await options.run(scenario)\n const external = await options.externalEvaluator?.({ scenario, artifact: initialArtifact })\n const artifact = external\n ? {\n ...initialArtifact,\n externalScores: [\n ...(initialArtifact.externalScores ?? []),\n ...(Array.isArray(external) ? external : [external]),\n ],\n }\n : initialArtifact\n const summary = scoreRagAnswerArtifact(artifact, scenario, {\n thresholds: options.thresholds,\n weights: options.weights,\n })\n summaries.push(summary)\n findings.push(...summary.findings)\n }\n const metrics = aggregateRagAnswerMetrics(summaries)\n const cost =\n typeof options.cost === 'function' ? await options.cost() : structuredClone(options.cost)\n return {\n passed: findings.length === 0,\n metrics,\n finalScenarioIds,\n datasetRef,\n evaluatorRef: options.evaluatorRef,\n cost,\n findings,\n metadata: { scenarioCount: options.scenarios.length },\n }\n }\n}\n\nexport async function calibrateRagAnswerJudge(\n options: RagCalibrationOptions,\n): Promise<RagCalibrationResult> {\n const judge = options.judge ?? ragAnswerQualityJudge()\n const strong = await judge.score({\n artifact: options.strong,\n scenario: options.scenario,\n signal: options.signal ?? new AbortController().signal,\n })\n const weak = await judge.score({\n artifact: options.weak,\n scenario: options.scenario,\n signal: options.signal ?? new AbortController().signal,\n })\n const strongScore = strong.composite\n const weakScore = weak.composite\n const minStrongScore = options.minStrongScore ?? 0.7\n const maxWeakScore = options.maxWeakScore ?? 0.3\n return {\n passed: strongScore >= minStrongScore && weakScore <= maxWeakScore,\n strongScore,\n weakScore,\n gap: strongScore - weakScore,\n }\n}\n","import { lintKnowledgeIndex } from '../lint'\nimport type { RagGapFinding } from '../rag-improvement-loop'\nimport type { KnowledgeIndex } from '../types'\nimport { validateKnowledgeIndex } from '../validate'\nimport type { KnowledgeBaseQualityOptions, KnowledgeBaseQualityReport } from './contracts'\nimport { detectNearDuplicatePages } from './near-duplicates'\n\nexport function scoreKnowledgeBaseIndex(\n index: KnowledgeIndex,\n options: KnowledgeBaseQualityOptions = {},\n): KnowledgeBaseQualityReport {\n const validation = validateKnowledgeIndex(index, { strict: options.strict })\n const lintFindings = lintKnowledgeIndex(index)\n const now = options.now ?? new Date()\n const staleSourceCount = index.sources.filter((source) => {\n return source.validUntil ? Date.parse(source.validUntil) < now.getTime() : false\n }).length\n const sourceHashCounts = new Map<string, number>()\n for (const source of index.sources) {\n sourceHashCounts.set(source.contentHash, (sourceHashCounts.get(source.contentHash) ?? 0) + 1)\n }\n const duplicateSourceHashCount = [...sourceHashCounts.values()].filter(\n (count) => count > 1,\n ).length\n const pagesWithInlineCitations = index.pages.filter(\n (page) => sourceRefs(page.text).length > 0,\n ).length\n const pagesWithSources = index.pages.filter((page) => page.sourceIds.length > 0).length\n const nearDuplicates = detectNearDuplicatePages(index.pages, options.nearDuplicates)\n const maxNearDuplicatePageRate = unitInterval(\n options.maxNearDuplicatePageRate ?? 1,\n 'maxNearDuplicatePageRate',\n )\n const metrics = {\n page_count: index.pages.length,\n source_count: index.sources.length,\n citation_rate: index.pages.length === 0 ? 1 : pagesWithInlineCitations / index.pages.length,\n source_backed_page_rate: index.pages.length === 0 ? 1 : pagesWithSources / index.pages.length,\n stale_source_rate: index.sources.length === 0 ? 0 : staleSourceCount / index.sources.length,\n duplicate_source_hash_rate:\n index.sources.length === 0 ? 0 : duplicateSourceHashCount / index.sources.length,\n lint_error_count: validation.findings.filter((finding) => finding.severity === 'error').length,\n lint_warning_count: lintFindings.filter((finding) => finding.severity === 'warning').length,\n near_duplicate_page_rate: nearDuplicates.duplicatePageRate,\n near_duplicate_page_count: nearDuplicates.duplicatePageCount,\n near_duplicate_pair_count: nearDuplicates.duplicatePairCount,\n }\n const findings: RagGapFinding[] = []\n if (metrics.lint_error_count > 0) {\n findings.push({\n id: 'kb:lint-errors',\n kind: 'unknown',\n severity: 'critical',\n message: `${metrics.lint_error_count} validation error(s) in the knowledge index.`,\n evidence: { lint_error_count: metrics.lint_error_count },\n })\n }\n if (metrics.citation_rate < (options.minCitationRate ?? 0)) {\n findings.push({\n id: 'kb:citation-rate',\n kind: 'missing-source',\n severity: 'error',\n message: 'Inline citation coverage is below the configured minimum.',\n evidence: { citation_rate: metrics.citation_rate },\n })\n }\n if (metrics.stale_source_rate > (options.maxStaleSourceRate ?? 1)) {\n findings.push({\n id: 'kb:stale-source-rate',\n kind: 'stale-source',\n severity: 'error',\n message: 'Stale source rate exceeds the configured maximum.',\n evidence: { stale_source_rate: metrics.stale_source_rate },\n })\n }\n if (nearDuplicates.truncated && maxNearDuplicatePageRate < 1) {\n findings.push({\n id: 'kb:near-duplicate-analysis-truncated',\n kind: 'unknown',\n severity: 'error',\n message:\n 'Near-duplicate analysis reached a configured bound, so the duplicate-page gate cannot be evaluated completely.',\n evidence: {\n candidate_pair_count: nearDuplicates.candidatePairCount,\n compared_pair_count: nearDuplicates.comparedPairCount,\n duplicate_pair_count: nearDuplicates.duplicatePairCount,\n },\n })\n } else if (metrics.near_duplicate_page_rate > maxNearDuplicatePageRate) {\n findings.push({\n id: 'kb:near-duplicate-page-rate',\n kind: 'unknown',\n severity: 'error',\n message: 'Near-duplicate page rate exceeds the configured maximum.',\n evidence: {\n near_duplicate_page_rate: metrics.near_duplicate_page_rate,\n near_duplicate_page_count: metrics.near_duplicate_page_count,\n near_duplicate_pair_count: metrics.near_duplicate_pair_count,\n threshold: nearDuplicates.threshold,\n },\n })\n }\n return { ok: findings.length === 0, metrics, nearDuplicates, findings }\n}\n\nfunction sourceRefs(text: string): string[] {\n const refs: string[] = []\n const regex = /\\[\\^([A-Za-z0-9_-]+)(?:#([A-Za-z0-9_.:-]+))?\\]/g\n let match = regex.exec(text)\n while (match !== null) {\n refs.push(match[0])\n match = regex.exec(text)\n }\n return refs\n}\n\nfunction unitInterval(value: number, name: string): number {\n if (!Number.isFinite(value) || value < 0 || value > 1) {\n throw new Error(`${name} must be a finite number in [0, 1]`)\n }\n return value\n}\n","import type {\n DispatchContext,\n JudgeConfig,\n OptimizationMethod,\n} from '@tangle-network/agent-eval/campaign'\nimport type { AgentCandidateJsonValue as JsonValue } from '@tangle-network/agent-interface'\nimport {\n jsonObjectCandidateCodec,\n type RunSerializedKnowledgeOptimizationOptions,\n type RunSerializedKnowledgeOptimizationResult,\n runSerializedKnowledgeOptimization,\n scenarioContentFingerprint,\n} from './optimization'\nimport type { RagAnswerEvalArtifact, RagAnswerEvalScenario } from './rag-eval'\nimport { ragAnswerQualityJudge } from './rag-eval'\n\nexport type RagOptimizationConfig = Record<string, JsonValue>\n\ntype RagOptimizationBaseOptions = Omit<\n RunSerializedKnowledgeOptimizationOptions<\n RagOptimizationConfig,\n RagAnswerEvalScenario,\n RagAnswerEvalArtifact\n >,\n | 'baseline'\n | 'method'\n | 'trainScenarios'\n | 'selectionScenarios'\n | 'finalScenarios'\n | 'dispatchCandidate'\n | 'judges'\n | 'codec'\n | 'scenarioFingerprint'\n>\n\nexport interface RunRagOptimizationOptions extends RagOptimizationBaseOptions {\n baseline: RagOptimizationConfig\n method: OptimizationMethod<RagAnswerEvalScenario, RagAnswerEvalArtifact>\n trainScenarios: readonly RagAnswerEvalScenario[]\n selectionScenarios: readonly RagAnswerEvalScenario[]\n finalScenarios: readonly RagAnswerEvalScenario[]\n run(input: {\n config: RagOptimizationConfig\n configSurface: string\n configSurfaceHash: string\n scenario: RagAnswerEvalScenario\n context: DispatchContext\n }): Promise<RagAnswerEvalArtifact>\n judges?: readonly JudgeConfig<RagAnswerEvalArtifact, RagAnswerEvalScenario>[]\n}\n\nexport interface RunRagOptimizationResult\n extends RunSerializedKnowledgeOptimizationResult<RagOptimizationConfig> {\n baselineConfig: RagOptimizationConfig\n winnerConfig: RagOptimizationConfig\n trainScenarios: readonly RagAnswerEvalScenario[]\n selectionScenarios: readonly RagAnswerEvalScenario[]\n finalScenarios: readonly RagAnswerEvalScenario[]\n}\n\n/** Optimizes retrieval and answer behavior together as one serialized RAG configuration. */\nexport async function runRagOptimization(\n options: RunRagOptimizationOptions,\n): Promise<RunRagOptimizationResult> {\n const {\n baseline,\n method,\n trainScenarios,\n selectionScenarios,\n finalScenarios,\n run,\n judges,\n ...runOptions\n } = options\n const result = await runSerializedKnowledgeOptimization({\n ...runOptions,\n baseline,\n method,\n trainScenarios,\n selectionScenarios,\n finalScenarios,\n codec: jsonObjectCandidateCodec<RagOptimizationConfig>(),\n judges: [...(judges ?? [ragAnswerQualityJudge()])],\n scenarioFingerprint: scenarioContentFingerprint,\n dispatchCandidate: ({ candidate, candidateSurface, candidateSurfaceHash, scenario, context }) =>\n run({\n config: candidate,\n configSurface: candidateSurface,\n configSurfaceHash: candidateSurfaceHash,\n scenario,\n context,\n }),\n })\n return {\n ...result,\n baselineConfig: result.baseline.value,\n winnerConfig: result.winner.value,\n trainScenarios: [...trainScenarios],\n selectionScenarios: [...selectionScenarios],\n finalScenarios: [...finalScenarios],\n }\n}\n","import { stableId } from './ids'\nimport type { KnowledgeEvent, KnowledgeEventType } from './types'\n\nexport interface KnowledgeEventQuery {\n type?: KnowledgeEventType\n target?: string\n limit?: number\n}\n\nexport function createKnowledgeEvent(input: {\n type: KnowledgeEventType\n actor?: string\n target?: string\n metadata?: Record<string, unknown>\n now?: () => Date\n}): KnowledgeEvent {\n const createdAt = (input.now ?? (() => new Date()))().toISOString()\n return {\n id: stableId(\n 'evt',\n `${input.type}:${input.target ?? ''}:${createdAt}:${JSON.stringify(input.metadata ?? {})}`,\n ),\n type: input.type,\n createdAt,\n // An absent optional is omitted, never written as `undefined`. An event\n // reaches canonical JSON — through a control-loop state fingerprint and\n // through the event log — and that encoder refuses a key with no value.\n ...(input.actor === undefined ? {} : { actor: input.actor }),\n ...(input.target === undefined ? {} : { target: input.target }),\n ...(input.metadata === undefined ? {} : { metadata: input.metadata }),\n }\n}\n","import {\n acquisitionPlansForKnowledgeGaps,\n type DataAcquisitionPlan,\n type KnowledgeAcquisitionMode,\n type KnowledgeBundle,\n type KnowledgeFreshness,\n type KnowledgeImportance,\n type KnowledgeReadinessReport,\n type KnowledgeRequirement,\n type KnowledgeRequirementCategory,\n type KnowledgeSensitivity,\n scoreKnowledgeReadiness,\n type UserQuestion,\n userQuestionsForKnowledgeGaps,\n} from '@tangle-network/agent-eval'\nimport { stringMetadata } from './metadata'\nimport { searchKnowledge } from './search'\nimport type { KnowledgeIndex, KnowledgeSearchResult } from './types'\n\nexport interface KnowledgeReadinessSpec {\n id: string\n description: string\n query: string\n requiredFor: string[]\n category: KnowledgeRequirementCategory\n acquisitionMode: KnowledgeAcquisitionMode\n importance: KnowledgeImportance\n freshness: KnowledgeFreshness\n sensitivity: KnowledgeSensitivity\n confidenceNeeded: number\n fallbackPolicy?: KnowledgeRequirement['fallbackPolicy']\n minSources?: number\n minHits?: number\n metadata?: Record<string, unknown>\n}\n\n/**\n * Defaults applied by `defineReadinessSpec` when the caller omits the field.\n *\n * These are deliberately conservative: a domain-specific topic that an agent\n * needs grounded to a high-confidence threshold from at least one authoritative\n * source. Override any field to specialise (e.g. `freshness: 'daily'` for a\n * topic that must reflect today's regulatory state).\n */\nexport const READINESS_SPEC_DEFAULTS = {\n category: 'domain_specific',\n acquisitionMode: 'search_web',\n importance: 'high',\n freshness: 'monthly',\n sensitivity: 'public',\n confidenceNeeded: 0.7,\n minSources: 1,\n minHits: 2,\n} as const satisfies Pick<\n KnowledgeReadinessSpec,\n | 'category'\n | 'acquisitionMode'\n | 'importance'\n | 'freshness'\n | 'sensitivity'\n | 'confidenceNeeded'\n | 'minSources'\n | 'minHits'\n>\n\n/**\n * Inputs accepted by `defineReadinessSpec`. The four fields the caller cannot\n * sanely default (id, description, query, requiredFor) are required; everything\n * else is optional and pulls from `READINESS_SPEC_DEFAULTS`.\n */\nexport type DefineReadinessSpecInput = Pick<\n KnowledgeReadinessSpec,\n 'id' | 'description' | 'query' | 'requiredFor'\n> &\n Partial<Omit<KnowledgeReadinessSpec, 'id' | 'description' | 'query' | 'requiredFor'>>\n\n/**\n * Builder that returns a fully-typed `KnowledgeReadinessSpec` from a slim input.\n *\n * Motivation: `KnowledgeReadinessSpec` has eleven required fields. Most of them\n * (category, acquisition mode, importance, freshness, sensitivity, confidence\n * threshold, source/hit minima) have a clear default for domain-specific KB\n * topics — agents end up copy-pasting the same boilerplate across every spec.\n * This helper collapses that boilerplate while keeping every field overridable.\n *\n * @example\n * defineReadinessSpec({\n * id: 'coop/intent-grounding',\n * description: 'Required grounding for coop pack intent stage',\n * query: 'flock size space ventilation predator',\n * requiredFor: ['IntentIntakeAgent', 'requirements'],\n * })\n *\n * @example // override defaults where the topic demands it\n * defineReadinessSpec({\n * id: 'medical/dosing',\n * description: 'Dosing guidance for compounding pharmacy',\n * query: 'compounding dose schedule',\n * requiredFor: ['DosingAgent'],\n * importance: 'blocking',\n * freshness: 'daily',\n * sensitivity: 'private',\n * confidenceNeeded: 0.95,\n * minSources: 3,\n * })\n */\nexport function defineReadinessSpec(input: DefineReadinessSpecInput): KnowledgeReadinessSpec {\n return {\n ...READINESS_SPEC_DEFAULTS,\n ...input,\n }\n}\n\nexport interface BuildEvalKnowledgeBundleOptions {\n taskId: string\n index: KnowledgeIndex\n specs: KnowledgeReadinessSpec[]\n userAnswers?: Record<string, string>\n searchLimit?: number\n metadata?: Record<string, unknown>\n now?: Date\n}\n\nexport interface EvalKnowledgeBundleBuildResult {\n bundle: KnowledgeBundle\n report: KnowledgeReadinessReport\n requirements: KnowledgeRequirement[]\n searchResultsByRequirement: Record<string, KnowledgeSearchResult[]>\n questions: UserQuestion[]\n acquisitionPlans: DataAcquisitionPlan[]\n}\n\nexport function buildEvalKnowledgeBundle(\n options: BuildEvalKnowledgeBundleOptions,\n): EvalKnowledgeBundleBuildResult {\n const searchLimit = options.searchLimit ?? 5\n const now = options.now ?? new Date()\n const searchResultsByRequirement: Record<string, KnowledgeSearchResult[]> = {}\n const requirements = options.specs.map((spec) => {\n const results = searchKnowledge(options.index, spec.query, searchLimit)\n searchResultsByRequirement[spec.id] = results\n return requirementFromSearch(options.index, spec, results, now)\n })\n const report = scoreKnowledgeReadiness({\n taskId: options.taskId,\n requirements,\n userAnswers: options.userAnswers,\n evidenceIds: requirements.flatMap((requirement) => requirement.evidenceIds),\n claimIds: [],\n wikiPageIds: unique(\n requirements.flatMap((requirement) =>\n pageIdsFromResults(searchResultsByRequirement[requirement.id] ?? []),\n ),\n ),\n metadata: options.metadata,\n })\n const questions = userQuestionsForKnowledgeGaps(report.blockingMissingRequirements)\n const acquisitionPlans = acquisitionPlansForKnowledgeGaps([\n ...report.blockingMissingRequirements,\n ...report.nonBlockingGaps,\n ])\n\n return {\n bundle: report.bundle,\n report,\n requirements,\n searchResultsByRequirement,\n questions,\n acquisitionPlans,\n }\n}\n\nfunction requirementFromSearch(\n index: KnowledgeIndex,\n spec: KnowledgeReadinessSpec,\n results: KnowledgeSearchResult[],\n now: Date,\n): KnowledgeRequirement {\n const hitCount = results.length\n const sourceIds = unique(results.flatMap((result) => result.page.sourceIds))\n const sources = index.sources.filter((source) => sourceIds.includes(source.id))\n const bestScore = results[0]?.normalizedScore ?? 0\n const sourceCoverage = spec.minSources\n ? Math.min(1, sourceIds.length / spec.minSources)\n : sourceIds.length > 0\n ? 1\n : 0\n const hitCoverage = spec.minHits ? Math.min(1, hitCount / spec.minHits) : hitCount > 0 ? 1 : 0\n const freshness = sourceFreshness(sources, now)\n const currentConfidence = round(Math.min(bestScore, sourceCoverage, hitCoverage, freshness.score))\n\n return {\n id: spec.id,\n description: spec.description,\n requiredFor: spec.requiredFor,\n category: spec.category,\n acquisitionMode: spec.acquisitionMode,\n importance: spec.importance,\n freshness: spec.freshness,\n sensitivity: spec.sensitivity,\n confidenceNeeded: spec.confidenceNeeded,\n currentConfidence,\n evidenceIds: unique([\n ...sourceIds.map((sourceId) => `source:${sourceId}`),\n ...results.map((result) => `page:${result.page.id}`),\n ]),\n fallbackPolicy:\n spec.fallbackPolicy ?? (spec.importance === 'blocking' ? 'block' : 'continue_with_caveat'),\n metadata: {\n ...spec.metadata,\n query: spec.query,\n hitCount,\n sourceCount: sourceIds.length,\n bestNormalizedScore: bestScore,\n expiredSourceIds: freshness.expiredSourceIds,\n freshnessScore: freshness.score,\n // An unknown freshness bound is absent from the record rather than present\n // and undefined: the two are the same JSON, so the canonical encoder refuses\n // the key instead of guessing which was meant.\n ...(freshness.validUntil === undefined ? {} : { validUntil: freshness.validUntil }),\n ...(freshness.lastVerifiedAt === undefined\n ? {}\n : { lastVerifiedAt: freshness.lastVerifiedAt }),\n },\n }\n}\n\nfunction sourceFreshness(\n sources: KnowledgeIndex['sources'],\n now: Date,\n): { score: number; validUntil?: string; lastVerifiedAt?: string; expiredSourceIds: string[] } {\n if (sources.length === 0) return { score: 0, expiredSourceIds: [] }\n const validUntilValues = sources\n .map(\n (source) =>\n source.validUntil ??\n stringMetadata(source.metadata, 'validUntil') ??\n stringMetadata(source.metadata, 'expiresAt'),\n )\n .filter(isIsoDate)\n const lastVerifiedValues = sources\n .map((source) => source.lastVerifiedAt ?? stringMetadata(source.metadata, 'lastVerifiedAt'))\n .filter(isIsoDate)\n const expiredSourceIds = sources\n .filter((source) => {\n const validUntil =\n source.validUntil ??\n stringMetadata(source.metadata, 'validUntil') ??\n stringMetadata(source.metadata, 'expiresAt')\n return validUntil ? Date.parse(validUntil) <= now.getTime() : false\n })\n .map((source) => source.id)\n return {\n score: expiredSourceIds.length > 0 ? 0 : 1,\n validUntil: earliestIso(validUntilValues),\n lastVerifiedAt: latestIso(lastVerifiedValues),\n expiredSourceIds,\n }\n}\n\nfunction isIsoDate(value: string | undefined): value is string {\n return Boolean(value && Number.isFinite(Date.parse(value)))\n}\n\nfunction earliestIso(values: string[]): string | undefined {\n return values.sort((a, b) => Date.parse(a) - Date.parse(b))[0]\n}\n\nfunction latestIso(values: string[]): string | undefined {\n return values.sort((a, b) => Date.parse(b) - Date.parse(a))[0]\n}\n\nfunction pageIdsFromResults(results: KnowledgeSearchResult[]): string[] {\n return results.map((result) => result.page.id)\n}\n\nfunction unique<T>(items: T[]): T[] {\n return [...new Set(items)]\n}\n\nfunction round(value: number): number {\n return Math.round(value * 1000) / 1000\n}\n","import {\n type BuildEvalKnowledgeBundleOptions,\n buildEvalKnowledgeBundle,\n type EvalKnowledgeBundleBuildResult,\n type KnowledgeReadinessSpec,\n} from './eval-readiness'\nimport type { KnowledgeIndex } from './types'\n\n/**\n * The subset of a research-loop options object the readiness gate needs:\n * the goal (default task id), the readiness specs, an optional task-id\n * override, and the rest of the bundle options minus the fields this helper\n * supplies (`taskId`/`index`/`specs`).\n *\n * Both the single-agent (`research-loop`) and two-agent (`verified-research-loop`)\n * options shapes satisfy this structurally, so the gate is single-sourced.\n */\nexport interface ReadinessGateOptions {\n goal: string\n readinessSpecs?: KnowledgeReadinessSpec[]\n readinessTaskId?: string\n readiness?: Omit<BuildEvalKnowledgeBundleOptions, 'taskId' | 'index' | 'specs'>\n}\n\n/**\n * Build the readiness bundle for a loop run over the given index, or\n * `undefined` when no readiness specs are configured (no gate to report).\n */\nexport function readinessFor(\n options: ReadinessGateOptions,\n index: KnowledgeIndex,\n): EvalKnowledgeBundleBuildResult | undefined {\n if (!options.readinessSpecs?.length) return undefined\n return buildEvalKnowledgeBundle({\n ...(options.readiness ?? {}),\n taskId: options.readinessTaskId ?? options.goal,\n index,\n specs: options.readinessSpecs,\n })\n}\n","import {\n blockingKnowledgeEval,\n type ControlEvalResult,\n type ControlRuntimeConfig,\n canonicalJson,\n objectiveEval,\n} from '@tangle-network/agent-eval'\nimport type {\n BuildEvalKnowledgeBundleOptions,\n EvalKnowledgeBundleBuildResult,\n KnowledgeReadinessSpec,\n} from './eval-readiness'\nimport { createKnowledgeEvent } from './events'\nimport { buildKnowledgeIndex } from './indexer'\nimport { lintKnowledgeIndex } from './lint'\nimport { type ApplyWriteBlocksResult, applyKnowledgeWriteBlocks } from './proposals'\nimport { readinessFor } from './readiness-helpers'\nimport {\n type AddSourceOptions,\n type AddSourceTextInput,\n addSourcePath,\n addSourceText,\n} from './sources'\nimport { initKnowledgeBase } from './store'\nimport type { KnowledgeEvent, KnowledgeIndex, KnowledgeLintFinding, SourceRecord } from './types'\nimport {\n type ValidateKnowledgeOptions,\n type ValidateKnowledgeResult,\n validateKnowledgeIndex,\n} from './validate'\n\nexport interface KnowledgeResearchLoopContext {\n root: string\n goal: string\n iteration: number\n index: KnowledgeIndex\n lintFindings: KnowledgeLintFinding[]\n validation: ValidateKnowledgeResult\n readiness?: EvalKnowledgeBundleBuildResult\n previousSteps: KnowledgeResearchLoopStep[]\n signal?: AbortSignal\n}\n\nexport interface KnowledgeResearchLoopDecision {\n /**\n * Free-form notes from the researcher. Keep this human-readable; products can\n * store it as the research transcript.\n */\n notes?: string\n /**\n * Local files to register as immutable sources before applying proposals.\n */\n sourcePaths?: string[]\n /**\n * Textual source artifacts discovered by an agent, browser worker, connector,\n * or deep-research process.\n */\n sourceTexts?: AddSourceTextInput[]\n /**\n * Safe write protocol text. The loop parses and applies only accepted\n * `---FILE: knowledge/...---` blocks.\n */\n proposalText?: string\n /**\n * The researcher decides when the wiki is good enough. The loop deliberately\n * does not encode a domain-specific definition of \"done\".\n */\n done?: boolean\n metadata?: Record<string, unknown>\n}\n\nexport interface KnowledgeResearchLoopStep {\n iteration: number\n notes?: string\n addedSources: SourceRecord[]\n applied?: ApplyWriteBlocksResult\n lintFindings: KnowledgeLintFinding[]\n validation: ValidateKnowledgeResult\n readiness?: EvalKnowledgeBundleBuildResult\n event: KnowledgeEvent\n done: boolean\n metadata?: Record<string, unknown>\n}\n\nexport interface RunKnowledgeResearchLoopOptions {\n pagesDirectory?: string\n root: string\n goal: string\n maxIterations?: number\n actor?: string\n strict?: ValidateKnowledgeOptions['strict']\n readinessSpecs?: KnowledgeReadinessSpec[]\n readinessTaskId?: string\n readiness?: Omit<BuildEvalKnowledgeBundleOptions, 'taskId' | 'index' | 'specs'>\n sourceOptions?: Pick<AddSourceOptions, 'adapters' | 'now'>\n signal?: AbortSignal\n step(\n context: KnowledgeResearchLoopContext,\n ): Promise<KnowledgeResearchLoopDecision> | KnowledgeResearchLoopDecision\n onStep?: (step: KnowledgeResearchLoopStep) => Promise<void> | void\n}\n\nexport interface KnowledgeResearchLoopResult {\n root: string\n goal: string\n iterations: number\n done: boolean\n index: KnowledgeIndex\n lintFindings: KnowledgeLintFinding[]\n validation: ValidateKnowledgeResult\n readiness?: EvalKnowledgeBundleBuildResult\n steps: KnowledgeResearchLoopStep[]\n}\n\nexport type KnowledgeControlLoopState = KnowledgeResearchLoopContext\nexport type KnowledgeControlLoopAction = KnowledgeResearchLoopDecision\nexport type KnowledgeControlLoopActionResult = KnowledgeResearchLoopStep\n\nexport interface KnowledgeControlLoopAdapterOptions {\n pagesDirectory?: string\n root: string\n goal: string\n actor?: string\n strict?: ValidateKnowledgeOptions['strict']\n readinessSpecs?: KnowledgeReadinessSpec[]\n readinessTaskId?: string\n readiness?: Omit<BuildEvalKnowledgeBundleOptions, 'taskId' | 'index' | 'specs'>\n sourceOptions?: Pick<AddSourceOptions, 'adapters' | 'now'>\n}\n\nexport type KnowledgeControlLoopAdapter = Pick<\n ControlRuntimeConfig<\n KnowledgeControlLoopState,\n KnowledgeControlLoopAction,\n KnowledgeControlLoopActionResult,\n ControlEvalResult\n >,\n 'intent' | 'observe' | 'validate' | 'act' | 'shouldStop' | 'stopPolicies'\n>\n\n/**\n * Adapter for running knowledge growth through `agent-eval`'s generic control\n * runtime. The caller still owns `decide`: that can be a proposer agent,\n * reviewer agent, deterministic policy, or a composition of all three.\n */\nexport function createKnowledgeControlLoopAdapter(\n options: KnowledgeControlLoopAdapterOptions,\n): KnowledgeControlLoopAdapter {\n let initialized = false\n const appliedSteps: KnowledgeResearchLoopStep[] = []\n\n return {\n intent: options.goal,\n async observe({ history, abortSignal }) {\n if (abortSignal.aborted) throw new Error('Knowledge control loop aborted')\n if (!initialized) {\n await initKnowledgeBase(options.root)\n initialized = true\n }\n const index = await buildKnowledgeIndex(options.root, options)\n const validation = validateKnowledgeIndex(index, { strict: options.strict })\n const lintFindings = lintKnowledgeIndex(index)\n const readiness = readinessFor(options, index)\n return {\n root: options.root,\n goal: options.goal,\n iteration: history.length + 1,\n index,\n lintFindings,\n validation,\n readiness,\n previousSteps: [...appliedSteps],\n signal: abortSignal,\n }\n },\n validate({ state }) {\n const errorFindings = state.validation.findings.filter(\n (finding) => finding.severity === 'error',\n )\n const evals: ControlEvalResult[] = [\n objectiveEval({\n id: 'knowledge-valid',\n passed: state.validation.ok,\n severity: 'critical',\n detail: state.validation.ok\n ? 'Knowledge index is valid.'\n : 'Knowledge index has validation errors.',\n metadata: { findings: state.validation.findings },\n }),\n objectiveEval({\n id: 'knowledge-lint-errors',\n passed: errorFindings.length === 0,\n severity: 'error',\n detail:\n errorFindings.length === 0\n ? 'No lint errors.'\n : `${errorFindings.length} lint error(s).`,\n metadata: { findings: errorFindings },\n }),\n ]\n if (state.readiness) evals.push(blockingKnowledgeEval(state.readiness.report))\n return evals\n },\n shouldStop() {\n return { stop: false, pass: false, reason: 'knowledge driver owns stop decisions' }\n },\n stopPolicies: {\n // `observe` hands the caller's AbortSignal to `act` through the state, and a\n // signal has no canonical JSON form. The loop's default fingerprint would\n // refuse the whole state, so fingerprint the observable knowledge and leave\n // the signal out — it carries no observable progress.\n stateFingerprint: ({ signal: _signal, ...observable }) => canonicalJson(observable),\n },\n async act(action, ctx) {\n const step = await applyKnowledgeResearchDecision(options, action, ctx.state.iteration)\n appliedSteps.push(step)\n return step\n },\n }\n}\n\nexport async function runKnowledgeResearchLoop(\n options: RunKnowledgeResearchLoopOptions,\n): Promise<KnowledgeResearchLoopResult> {\n const maxIterations = Math.max(1, options.maxIterations ?? 3)\n await initKnowledgeBase(options.root)\n const steps: KnowledgeResearchLoopStep[] = []\n let index = await buildKnowledgeIndex(options.root, options)\n let validation = validateKnowledgeIndex(index, { strict: options.strict })\n let lintFindings = lintKnowledgeIndex(index)\n let readiness = readinessFor(options, index)\n let done = false\n\n for (let iteration = 1; iteration <= maxIterations; iteration++) {\n if (options.signal?.aborted) throw new Error('Knowledge research loop aborted')\n const decision = await options.step({\n root: options.root,\n goal: options.goal,\n iteration,\n index,\n lintFindings,\n validation,\n readiness,\n previousSteps: steps,\n signal: options.signal,\n })\n\n done = Boolean(decision.done)\n const step = await applyKnowledgeResearchDecision(options, decision, iteration)\n index = await buildKnowledgeIndex(options.root, options)\n validation = step.validation\n lintFindings = step.lintFindings\n readiness = step.readiness\n steps.push(step)\n await options.onStep?.(step)\n\n if (done) break\n if (!step.applied && step.addedSources.length === 0) break\n }\n\n return {\n root: options.root,\n goal: options.goal,\n iterations: steps.length,\n done,\n index,\n lintFindings,\n validation,\n readiness,\n steps,\n }\n}\n\nasync function applyKnowledgeResearchDecision(\n options: KnowledgeControlLoopAdapterOptions,\n decision: KnowledgeResearchLoopDecision,\n iteration = 1,\n): Promise<KnowledgeResearchLoopStep> {\n const addedSources: SourceRecord[] = []\n for (const sourcePath of decision.sourcePaths ?? []) {\n addedSources.push(...(await addSourcePath(options.root, sourcePath, options.sourceOptions)))\n }\n for (const sourceText of decision.sourceTexts ?? []) {\n addedSources.push(await addSourceText(options.root, sourceText, options.sourceOptions))\n }\n\n const applied = decision.proposalText\n ? await applyKnowledgeWriteBlocks(options.root, decision.proposalText, {\n pagesDirectory: options.pagesDirectory,\n })\n : undefined\n\n const index = await buildKnowledgeIndex(options.root, options)\n const validation = validateKnowledgeIndex(index, { strict: options.strict })\n const lintFindings = lintKnowledgeIndex(index)\n const readiness = readinessFor(options, index)\n const done = Boolean(decision.done)\n const event = createKnowledgeEvent({\n type: 'research.iteration',\n actor: options.actor,\n target: options.root,\n metadata: {\n goal: options.goal,\n iteration,\n done,\n addedSourceCount: addedSources.length,\n ...(applied === undefined ? {} : { written: applied.written }),\n warningCount: applied?.warnings.length ?? 0,\n errorCount: validation.findings.filter((finding) => finding.severity === 'error').length,\n },\n })\n\n // Every optional below is omitted when it has no value rather than set to\n // `undefined`. A step joins the control-loop state, which is fingerprinted with\n // canonical JSON, and that encoder refuses a key present with no value.\n return {\n iteration,\n ...(decision.notes === undefined ? {} : { notes: decision.notes }),\n addedSources,\n ...(applied === undefined ? {} : { applied }),\n lintFindings,\n validation,\n ...(readiness === undefined ? {} : { readiness }),\n event,\n done,\n ...(decision.metadata === undefined ? {} : { metadata: decision.metadata }),\n }\n}\n","import { canonicalJson } from '@tangle-network/agent-eval'\nimport {\n type JudgeConfig,\n type OptimizationMethod,\n surfaceHash,\n} from '@tangle-network/agent-eval/campaign'\nimport type { AgentCandidateJsonValue as JsonValue } from '@tangle-network/agent-interface'\nimport {\n jsonObjectCandidateCodec,\n type RunSerializedKnowledgeOptimizationOptions,\n type RunSerializedKnowledgeOptimizationResult,\n runSerializedKnowledgeOptimization,\n} from './optimization'\nimport {\n buildRetrievalEvalDispatch,\n type RetrievalConfig,\n type RetrievalEvalArtifact,\n type RetrievalEvalRetriever,\n type RetrievalEvalScenario,\n type RetrievalMetricWeights,\n retrievalRecallJudge,\n} from './retrieval-eval'\nimport type { KnowledgeIndex } from './types'\n\ntype RetrievalOptimizationBaseOptions = Omit<\n RunSerializedKnowledgeOptimizationOptions<\n RetrievalConfig,\n RetrievalEvalScenario,\n RetrievalEvalArtifact\n >,\n | 'baseline'\n | 'method'\n | 'trainScenarios'\n | 'selectionScenarios'\n | 'finalScenarios'\n | 'dispatchCandidate'\n | 'judges'\n | 'codec'\n | 'scenarioFingerprint'\n>\n\nexport interface RunRetrievalImprovementLoopOptions extends RetrievalOptimizationBaseOptions {\n baseline: RetrievalConfig\n trainScenarios: readonly RetrievalEvalScenario[]\n selectionScenarios: readonly RetrievalEvalScenario[]\n finalScenarios: readonly RetrievalEvalScenario[]\n method: OptimizationMethod<RetrievalEvalScenario, RetrievalEvalArtifact>\n index?: KnowledgeIndex\n defaultK?: number\n retrieve?: RetrievalEvalRetriever\n judges?: readonly JudgeConfig<RetrievalEvalArtifact, RetrievalEvalScenario>[]\n metricWeights?: RetrievalMetricWeights\n}\n\nexport interface RunRetrievalImprovementLoopResult\n extends RunSerializedKnowledgeOptimizationResult<RetrievalConfig> {\n baselineConfig: RetrievalConfig\n winnerConfig: RetrievalConfig\n trainScenarios: readonly RetrievalEvalScenario[]\n selectionScenarios: readonly RetrievalEvalScenario[]\n finalScenarios: readonly RetrievalEvalScenario[]\n}\n\nexport async function runRetrievalImprovementLoop(\n options: RunRetrievalImprovementLoopOptions,\n): Promise<RunRetrievalImprovementLoopResult> {\n const dispatch = buildRetrievalEvalDispatch({\n index: options.index,\n defaultK: options.defaultK,\n retrieve: options.retrieve,\n })\n const {\n baseline,\n trainScenarios,\n selectionScenarios,\n finalScenarios,\n method,\n index: _index,\n defaultK: _defaultK,\n retrieve: _retrieve,\n judges,\n metricWeights,\n ...runOptions\n } = options\n const result = await runSerializedKnowledgeOptimization({\n ...runOptions,\n baseline,\n method,\n trainScenarios,\n selectionScenarios,\n finalScenarios,\n codec: jsonObjectCandidateCodec<RetrievalConfig>(),\n judges: [...(judges ?? [retrievalRecallJudge({ weights: metricWeights })])],\n scenarioFingerprint: retrievalScenarioFingerprint,\n dispatchCandidate: ({ candidateSurface, scenario, context }) =>\n dispatch(candidateSurface, scenario, context),\n })\n return {\n ...result,\n baselineConfig: result.baseline.value,\n winnerConfig: result.winner.value,\n trainScenarios: [...trainScenarios],\n selectionScenarios: [...selectionScenarios],\n finalScenarios: [...finalScenarios],\n }\n}\n\nfunction retrievalScenarioFingerprint(scenario: RetrievalEvalScenario): string {\n return surfaceHash(\n canonicalJson({\n query: scenario.query,\n expected: scenario.expected,\n k: scenario.k ?? null,\n } as JsonValue),\n )\n}\n","import { assertRagAnswerEvidence, ragAnswerEvidenceRejectionReasons } from './rag-answer-evidence'\nimport type {\n RagAnswerQualityResult,\n RagKnowledgeImprovementPhase,\n RagKnowledgeImprovementPhaseResult,\n RagKnowledgeUpdateResult,\n RagOptimizationSelection,\n RagPromotionResult,\n RetrievalOptimizationSelection,\n RunRagKnowledgeImprovementLoopOptions,\n RunRagKnowledgeImprovementLoopResult,\n} from './rag-improvement-loop'\nimport { type RunRagOptimizationResult, runRagOptimization } from './rag-optimization'\nimport {\n type KnowledgeResearchLoopDecision,\n type RunKnowledgeResearchLoopOptions,\n runKnowledgeResearchLoop,\n} from './research-loop'\nimport {\n type RunRetrievalImprovementLoopResult,\n runRetrievalImprovementLoop,\n} from './retrieval-optimization'\n\ntype MaybePromise<T> = T | Promise<T>\n\nexport async function runRagKnowledgeImprovementPhases(\n options: RunRagKnowledgeImprovementLoopOptions,\n previous?: RunRagKnowledgeImprovementLoopResult,\n): Promise<RunRagKnowledgeImprovementLoopResult> {\n assertConfiguredRequiredPhases(options)\n assertOptionalCostCeiling(options.answerQualityCostCeiling, 'answerQualityCostCeiling')\n const now = options.now ?? (() => new Date())\n const phases: RagKnowledgeImprovementPhaseResult[] = [...(previous?.phases ?? [])]\n let optimization = previous?.optimization\n let retrieval = previous?.retrieval\n let findings = [...(previous?.findings ?? [])]\n let acquisition = previous?.acquisition\n let knowledgeUpdate = previous?.knowledgeUpdate\n let answerQuality = previous?.answerQuality\n let promotion = previous?.promotion\n\n if (phaseEnabled(options, 'gap-diagnosis')) {\n if (options.diagnose) {\n findings = [\n ...(await runPhase(\n phases,\n now,\n 'gap-diagnosis',\n async () => {\n assertNotAborted(options.signal)\n return options.diagnose!({\n goal: options.goal,\n phases,\n optimization: selectRagOptimization(optimization),\n signal: options.signal,\n retrieval: selectRetrievalOptimization(retrieval),\n })\n },\n (diagnosed) => `${diagnosed.length} finding(s)`,\n )),\n ]\n } else {\n skipPhase(phases, now, 'gap-diagnosis', 'no diagnosis hook provided')\n }\n }\n\n if (phaseEnabled(options, 'knowledge-acquisition')) {\n if (options.acquireKnowledge) {\n acquisition = await runPhase(\n phases,\n now,\n 'knowledge-acquisition',\n async () => {\n assertNotAborted(options.signal)\n return options.acquireKnowledge!({\n goal: options.goal,\n phases,\n optimization: selectRagOptimization(optimization),\n signal: options.signal,\n retrieval: selectRetrievalOptimization(retrieval),\n findings,\n })\n },\n summarizeAcquisitionDecision,\n )\n } else {\n skipPhase(phases, now, 'knowledge-acquisition', 'no acquisition hook provided')\n }\n }\n\n if (phaseEnabled(options, 'knowledge-update')) {\n if (options.updateKnowledge) {\n knowledgeUpdate = await runPhase(\n phases,\n now,\n 'knowledge-update',\n async () => {\n assertNotAborted(options.signal)\n return options.updateKnowledge!({\n goal: options.goal,\n phases,\n optimization: selectRagOptimization(optimization),\n signal: options.signal,\n retrieval: selectRetrievalOptimization(retrieval),\n findings,\n acquisition,\n })\n },\n (result) => result.summary,\n )\n } else if (options.knowledgeResearch) {\n knowledgeUpdate = await runPhase(\n phases,\n now,\n 'knowledge-update',\n async () => {\n assertNotAborted(options.signal)\n return runKnowledgeResearchUpdate(options, acquisition)\n },\n (result) => result.summary,\n )\n } else {\n skipPhase(phases, now, 'knowledge-update', 'no update hook or research loop provided')\n }\n }\n\n if (\n phaseEnabled(options, 'rag-optimization') &&\n (options.optimization ||\n options.enabledPhases?.includes('rag-optimization') ||\n options.requiredPhases?.includes('rag-optimization'))\n ) {\n if (options.optimization) {\n optimization = await runPhase(\n phases,\n now,\n 'rag-optimization',\n async () => {\n assertNotAborted(options.signal)\n return runRagOptimization(options.optimization!)\n },\n summarizeRagOptimization,\n )\n } else {\n skipPhase(phases, now, 'rag-optimization', 'no full RAG optimization options provided')\n }\n }\n\n if (phaseEnabled(options, 'retrieval-tuning')) {\n if (options.retrieval) {\n retrieval = await runPhase(\n phases,\n now,\n 'retrieval-tuning',\n async () => {\n assertNotAborted(options.signal)\n return runRetrievalImprovementLoop(options.retrieval!)\n },\n summarizeRetrievalResult,\n )\n } else {\n skipPhase(phases, now, 'retrieval-tuning', 'no retrieval options provided')\n }\n }\n\n if (phaseEnabled(options, 'answer-quality')) {\n if (options.evaluateAnswers) {\n answerQuality = await runPhase(\n phases,\n now,\n 'answer-quality',\n async () => {\n assertNotAborted(options.signal)\n const result = await options.evaluateAnswers!({\n goal: options.goal,\n phases,\n optimization: selectRagOptimization(optimization),\n signal: options.signal,\n retrieval: selectRetrievalOptimization(retrieval),\n findings,\n acquisition,\n knowledgeUpdate,\n })\n assertRagAnswerEvidence(result)\n return result\n },\n summarizeAnswerQuality,\n )\n findings = [...findings, ...(answerQuality.findings ?? [])]\n } else {\n skipPhase(phases, now, 'answer-quality', 'no answer-quality hook provided')\n }\n }\n\n if (phaseEnabled(options, 'promotion')) {\n if (options.decidePromotion) {\n promotion = await runPhase(\n phases,\n now,\n 'promotion',\n async () => {\n assertNotAborted(options.signal)\n const evidenceRejection = rejectUnsafePromotionEvidence({\n optimization: optimization?.comparison,\n optimizationCostCeiling: options.optimization?.costCeiling,\n retrieval: retrieval?.comparison,\n retrievalCostCeiling: options.retrieval?.costCeiling,\n answerQuality,\n answerQualityCostCeiling: options.answerQualityCostCeiling,\n })\n if (evidenceRejection) return evidenceRejection\n return options.decidePromotion!({\n goal: options.goal,\n phases,\n optimization: selectRagOptimization(optimization),\n optimizationComparison: optimization?.comparison,\n signal: options.signal,\n retrieval: selectRetrievalOptimization(retrieval),\n retrievalComparison: retrieval?.comparison,\n findings,\n acquisition,\n knowledgeUpdate,\n answerQuality,\n })\n },\n (result) => `${result.promoted ? 'promoted' : 'held'}: ${result.reason}`,\n )\n } else {\n skipPhase(phases, now, 'promotion', 'no promotion decision hook provided')\n }\n }\n\n return {\n goal: options.goal,\n phases,\n optimization,\n retrieval,\n findings,\n acquisition,\n knowledgeUpdate,\n answerQuality,\n promotion,\n }\n}\n\nfunction rejectUnsafePromotionEvidence(evidence: {\n optimization?: RunRagOptimizationResult['comparison']\n optimizationCostCeiling?: number\n retrieval?: RunRetrievalImprovementLoopResult['comparison']\n retrievalCostCeiling?: number\n answerQuality?: RagAnswerQualityResult\n answerQualityCostCeiling?: number\n}): RagPromotionResult | undefined {\n const reasons: string[] = []\n if (!evidence.optimization && !evidence.retrieval && !evidence.answerQuality) {\n reasons.push('promotion requires final RAG, retrieval, or answer-quality evidence')\n }\n for (const [label, comparison, costCeiling] of [\n ['RAG', evidence.optimization, evidence.optimizationCostCeiling],\n ['retrieval', evidence.retrieval, evidence.retrievalCostCeiling],\n ] as const) {\n if (!comparison) continue\n if (!comparison.totalCost.accountingComplete) {\n reasons.push(`${label} final comparison has incomplete cost accounting`)\n }\n const optimizerSource = comparison.best.provenance?.source\n if (optimizerSource && optimizerSource.evidence !== 'observed') {\n reasons.push(`${label} optimizer package identity was not observed`)\n }\n if (!comparison.best.decision.promote) {\n reasons.push(\n comparison.best.decision.low < 0\n ? `${label} final comparison does not rule out a regression`\n : `${label} final comparison does not establish the required improvement`,\n )\n }\n if (\n costCeiling !== undefined &&\n exceedsCostCeiling(comparison.totalCost.totalCostUsd, costCeiling)\n ) {\n reasons.push(\n `${label} final comparison cost ${comparison.totalCost.totalCostUsd} exceeds ${costCeiling}`,\n )\n }\n }\n if (evidence.answerQuality) {\n reasons.push(\n ...ragAnswerEvidenceRejectionReasons(\n evidence.answerQuality,\n evidence.answerQualityCostCeiling,\n ),\n )\n }\n if (reasons.length === 0) return undefined\n return {\n promoted: false,\n reason: reasons.join('; '),\n }\n}\n\nfunction assertOptionalCostCeiling(value: number | undefined, label: string): void {\n if (value !== undefined && (!Number.isFinite(value) || value < 0)) {\n throw new Error(`${label} must be a non-negative finite number`)\n }\n}\n\nfunction exceedsCostCeiling(totalCostUsd: number, costCeiling: number): boolean {\n const tolerance = Number.EPSILON * Math.max(1, Math.abs(totalCostUsd), Math.abs(costCeiling)) * 8\n return totalCostUsd - costCeiling > tolerance\n}\n\nfunction summarizeRagOptimization(result: RunRagOptimizationResult): string {\n return `${result.methodName}; winner=${result.winner.surfaceHash}`\n}\n\nasync function runKnowledgeResearchUpdate(\n options: RunRagKnowledgeImprovementLoopOptions,\n acquisition: KnowledgeResearchLoopDecision | undefined,\n): Promise<RagKnowledgeUpdateResult> {\n const research = options.knowledgeResearch\n if (!research) {\n throw new Error('knowledgeResearch options are required to run the knowledge update phase')\n }\n const { goal, step, ...rest } = research\n const researchStep = step ?? acquisitionBackedResearchStep(acquisition)\n const maxIterations = step ? rest.maxIterations : 1\n const result = await runKnowledgeResearchLoop({\n ...rest,\n goal: goal ?? options.goal,\n maxIterations,\n signal: options.signal,\n step: researchStep,\n })\n return {\n applied: result.steps.some((stepResult) => {\n return stepResult.addedSources.length > 0 || Boolean(stepResult.applied)\n }),\n summary: `${result.iterations} research iteration(s); done=${String(result.done)}`,\n research: result,\n }\n}\n\nfunction acquisitionBackedResearchStep(\n acquisition: KnowledgeResearchLoopDecision | undefined,\n): RunKnowledgeResearchLoopOptions['step'] {\n if (!acquisition) {\n throw new Error(\n 'knowledgeResearch requires either a step hook or a knowledge-acquisition result to apply',\n )\n }\n return () => ({ ...acquisition, done: acquisition.done ?? true })\n}\n\nasync function runPhase<T>(\n phases: RagKnowledgeImprovementPhaseResult[],\n now: () => Date,\n phase: RagKnowledgeImprovementPhase,\n action: () => MaybePromise<T>,\n summarize: (result: T) => string,\n): Promise<T> {\n const startedAt = now().toISOString()\n try {\n const result = await action()\n phases.push({\n phase,\n status: 'completed',\n summary: summarize(result),\n startedAt,\n finishedAt: now().toISOString(),\n })\n return result\n } catch (error) {\n phases.push({\n phase,\n status: 'failed',\n summary: (error as Error).message,\n startedAt,\n finishedAt: now().toISOString(),\n })\n throw error\n }\n}\n\nfunction skipPhase(\n phases: RagKnowledgeImprovementPhaseResult[],\n now: () => Date,\n phase: RagKnowledgeImprovementPhase,\n summary: string,\n): void {\n const timestamp = now().toISOString()\n phases.push({ phase, status: 'skipped', summary, startedAt: timestamp, finishedAt: timestamp })\n}\n\nfunction summarizeRetrievalResult(result: RunRetrievalImprovementLoopResult): string {\n return `${result.methodName}; winner=${result.winner.surfaceHash}`\n}\n\nfunction selectRagOptimization(\n result: RunRagOptimizationResult | undefined,\n): RagOptimizationSelection | undefined {\n if (!result) return undefined\n return {\n methodName: result.methodName,\n baseline: structuredClone(result.baseline),\n winner: structuredClone(result.winner),\n baselineConfig: structuredClone(result.baselineConfig),\n winnerConfig: structuredClone(result.winnerConfig),\n }\n}\n\nfunction selectRetrievalOptimization(\n result: RunRetrievalImprovementLoopResult | undefined,\n): RetrievalOptimizationSelection | undefined {\n if (!result) return undefined\n return {\n methodName: result.methodName,\n baseline: structuredClone(result.baseline),\n winner: structuredClone(result.winner),\n baselineConfig: structuredClone(result.baselineConfig),\n winnerConfig: structuredClone(result.winnerConfig),\n }\n}\n\nfunction summarizeAcquisitionDecision(decision: KnowledgeResearchLoopDecision): string {\n const sourcePathCount = decision.sourcePaths?.length ?? 0\n const sourceTextCount = decision.sourceTexts?.length ?? 0\n const proposal = decision.proposalText ? 'proposal' : 'no proposal'\n return `${sourcePathCount} path source(s), ${sourceTextCount} text source(s), ${proposal}`\n}\n\nfunction summarizeAnswerQuality(result: RagAnswerQualityResult): string {\n const metrics = Object.entries(result.metrics)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([key, value]) => `${key}=${formatMetric(value)}`)\n .join(', ')\n return `${result.passed ? 'passed' : 'failed'}${metrics ? `; ${metrics}` : ''}`\n}\n\nfunction formatMetric(value: number): string {\n return Number.isFinite(value) ? value.toFixed(3) : String(value)\n}\n\nfunction phaseEnabled(\n options: RunRagKnowledgeImprovementLoopOptions,\n phase: RagKnowledgeImprovementPhase,\n): boolean {\n return !options.enabledPhases || options.enabledPhases.includes(phase)\n}\n\nfunction assertConfiguredRequiredPhases(options: RunRagKnowledgeImprovementLoopOptions): void {\n for (const phase of options.requiredPhases ?? []) {\n if (!phaseEnabled(options, phase)) {\n throw new Error(`required phase ${phase} is not enabled`)\n }\n if (!phaseConfigured(options, phase)) {\n throw new Error(requiredPhaseMessage(phase))\n }\n }\n}\n\nfunction phaseConfigured(\n options: RunRagKnowledgeImprovementLoopOptions,\n phase: RagKnowledgeImprovementPhase,\n): boolean {\n switch (phase) {\n case 'rag-optimization':\n return Boolean(options.optimization)\n case 'retrieval-tuning':\n return Boolean(options.retrieval)\n case 'gap-diagnosis':\n return Boolean(options.diagnose)\n case 'knowledge-acquisition':\n return Boolean(options.acquireKnowledge)\n case 'knowledge-update':\n return Boolean(options.updateKnowledge ?? options.knowledgeResearch)\n case 'answer-quality':\n return Boolean(options.evaluateAnswers)\n case 'promotion':\n return Boolean(options.decidePromotion)\n }\n}\n\nfunction requiredPhaseMessage(phase: RagKnowledgeImprovementPhase): string {\n switch (phase) {\n case 'rag-optimization':\n return 'required phase rag-optimization requires optimization options'\n case 'retrieval-tuning':\n return 'required phase retrieval-tuning requires retrieval options'\n case 'gap-diagnosis':\n return 'required phase gap-diagnosis requires a diagnose hook'\n case 'knowledge-acquisition':\n return 'required phase knowledge-acquisition requires an acquireKnowledge hook'\n case 'knowledge-update':\n return 'required phase knowledge-update requires updateKnowledge or knowledgeResearch'\n case 'answer-quality':\n return 'required phase answer-quality requires an evaluateAnswers hook'\n case 'promotion':\n return 'required phase promotion requires a decidePromotion hook'\n }\n}\n\nfunction assertNotAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted) {\n throw new Error('RAG knowledge improvement loop aborted')\n }\n}\n","import type { ComparisonCost } from '@tangle-network/agent-eval/campaign'\nimport type { AgentCandidateJsonValue as JsonValue } from '@tangle-network/agent-interface'\nimport { runRagKnowledgeImprovementPhases } from './rag-improvement-phases'\nimport type { RunRagOptimizationOptions, RunRagOptimizationResult } from './rag-optimization'\nimport type {\n KnowledgeResearchLoopDecision,\n KnowledgeResearchLoopResult,\n RunKnowledgeResearchLoopOptions,\n} from './research-loop'\nimport type {\n RunRetrievalImprovementLoopOptions,\n RunRetrievalImprovementLoopResult,\n} from './retrieval-optimization'\n\nexport type RagKnowledgeImprovementPhase =\n | 'rag-optimization'\n | 'retrieval-tuning'\n | 'gap-diagnosis'\n | 'knowledge-acquisition'\n | 'knowledge-update'\n | 'answer-quality'\n | 'promotion'\n\nexport type RagKnowledgeImprovementPhaseStatus = 'completed' | 'skipped' | 'failed'\n\nexport type RagGapKind =\n | 'missing-source'\n | 'stale-source'\n | 'retrieval-miss'\n | 'retrieval-noise'\n | 'chunking-mismatch'\n | 'missing-multihop-evidence'\n | 'generator-unsupported-claim'\n | 'citation-mismatch'\n | 'incorrect-abstention'\n | 'unknown'\n\nexport type RagGapSeverity = 'info' | 'warning' | 'error' | 'critical'\n\nexport interface RagGapFinding {\n id: string\n kind: RagGapKind\n severity: RagGapSeverity\n message: string\n scenarioId?: string\n evidence?: Record<string, JsonValue>\n}\n\nexport interface RagKnowledgeImprovementPhaseResult {\n phase: RagKnowledgeImprovementPhase\n status: RagKnowledgeImprovementPhaseStatus\n summary: string\n startedAt: string\n finishedAt: string\n metadata?: Record<string, JsonValue>\n}\n\nexport type RagOptimizationSelection = Pick<\n RunRagOptimizationResult,\n 'methodName' | 'baseline' | 'winner' | 'baselineConfig' | 'winnerConfig'\n>\n\nexport type RetrievalOptimizationSelection = Pick<\n RunRetrievalImprovementLoopResult,\n 'methodName' | 'baseline' | 'winner' | 'baselineConfig' | 'winnerConfig'\n>\n\nexport interface RagPhaseInputBase {\n goal: string\n phases: readonly RagKnowledgeImprovementPhaseResult[]\n /** Selected candidate only. Adaptive update callbacks run before final scoring starts. */\n optimization?: RagOptimizationSelection\n signal?: AbortSignal\n}\n\nexport interface RagDiagnosisInput extends RagPhaseInputBase {\n retrieval?: RetrievalOptimizationSelection\n}\n\nexport interface RagKnowledgeAcquisitionInput extends RagPhaseInputBase {\n retrieval?: RetrievalOptimizationSelection\n findings: readonly RagGapFinding[]\n}\n\nexport interface RagKnowledgeUpdateInput extends RagPhaseInputBase {\n retrieval?: RetrievalOptimizationSelection\n findings: readonly RagGapFinding[]\n acquisition?: KnowledgeResearchLoopDecision\n}\n\nexport interface RagKnowledgeUpdateResult {\n applied: boolean\n summary: string\n research?: KnowledgeResearchLoopResult\n metadata?: Record<string, JsonValue>\n}\n\nexport interface RagAnswerQualityInput extends RagPhaseInputBase {\n retrieval?: RetrievalOptimizationSelection\n findings: readonly RagGapFinding[]\n acquisition?: KnowledgeResearchLoopDecision\n knowledgeUpdate?: RagKnowledgeUpdateResult\n}\n\nexport interface RagAnswerQualityResult {\n passed: boolean\n metrics: Record<string, number>\n finalScenarioIds: readonly string[]\n datasetRef: string\n evaluatorRef: string\n cost: ComparisonCost\n findings?: readonly RagGapFinding[]\n metadata?: Record<string, JsonValue>\n}\n\nexport interface RagPromotionInput extends RagPhaseInputBase {\n retrieval?: RetrievalOptimizationSelection\n /** Full final-case result available only to the terminal promotion decision. */\n optimizationComparison?: RunRagOptimizationResult['comparison']\n /** Full final-case result available only to the terminal promotion decision. */\n retrievalComparison?: RunRetrievalImprovementLoopResult['comparison']\n findings: readonly RagGapFinding[]\n acquisition?: KnowledgeResearchLoopDecision\n knowledgeUpdate?: RagKnowledgeUpdateResult\n answerQuality?: RagAnswerQualityResult\n}\n\nexport interface RagPromotionResult {\n promoted: boolean\n reason: string\n metadata?: Record<string, JsonValue>\n}\n\nexport interface RagKnowledgeResearchOptions\n extends Omit<RunKnowledgeResearchLoopOptions, 'goal' | 'signal' | 'step'> {\n goal?: string\n step?: RunKnowledgeResearchLoopOptions['step']\n}\n\nexport interface RunRagKnowledgeImprovementLoopOptions {\n goal: string\n optimization?: RunRagOptimizationOptions\n retrieval?: RunRetrievalImprovementLoopOptions\n diagnose?: (input: RagDiagnosisInput) => MaybePromise<readonly RagGapFinding[]>\n acquireKnowledge?: (\n input: RagKnowledgeAcquisitionInput,\n ) => MaybePromise<KnowledgeResearchLoopDecision>\n knowledgeResearch?: RagKnowledgeResearchOptions\n updateKnowledge?: (input: RagKnowledgeUpdateInput) => MaybePromise<RagKnowledgeUpdateResult>\n evaluateAnswers?: (input: RagAnswerQualityInput) => MaybePromise<RagAnswerQualityResult>\n /** Maximum total answer-evaluation spend accepted for promotion. */\n answerQualityCostCeiling?: number\n /**\n * Makes a side-effect-free promotion decision after the library has rejected\n * missing, inconclusive, regressing, unaccounted, or over-budget final evidence.\n */\n decidePromotion?: (input: RagPromotionInput) => MaybePromise<RagPromotionResult>\n enabledPhases?: readonly RagKnowledgeImprovementPhase[]\n requiredPhases?: readonly RagKnowledgeImprovementPhase[]\n signal?: AbortSignal\n now?: () => Date\n}\n\nexport interface RunRagKnowledgeImprovementLoopResult {\n goal: string\n phases: readonly RagKnowledgeImprovementPhaseResult[]\n optimization?: RunRagOptimizationResult\n retrieval?: RunRetrievalImprovementLoopResult\n findings: readonly RagGapFinding[]\n acquisition?: KnowledgeResearchLoopDecision\n knowledgeUpdate?: RagKnowledgeUpdateResult\n answerQuality?: RagAnswerQualityResult\n promotion?: RagPromotionResult\n}\n\ntype MaybePromise<T> = T | Promise<T>\n\nexport async function runRagKnowledgeImprovementLoop(\n options: RunRagKnowledgeImprovementLoopOptions,\n): Promise<RunRagKnowledgeImprovementLoopResult> {\n return runRagKnowledgeImprovementPhases(options)\n}\n","import { createHash } from 'node:crypto'\nimport { cp, lstat, mkdir, mkdtemp, rm } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { dirname, join } from 'node:path'\nimport { canonicalJson, contentHash } from '@tangle-network/agent-eval'\nimport {\n canonicalPathsEqual,\n isMissingFile,\n listRegularFilesWithinRoot,\n readRegularFileWithinRoot,\n renameDurable,\n withSafeDirectory,\n} from '../durable-fs'\nimport { sha256, stableId } from '../ids'\nimport { writeKnowledgeIndex } from '../indexer'\nimport {\n KNOWLEDGE_RESEARCH_STATE_PATHS,\n type KnowledgeStateScope,\n normalizeKnowledgeStateScope,\n} from '../knowledge-state-scope'\nimport { withKnowledgeRead } from '../mutation-lock'\nimport { immutableJsonValue } from './activation'\nimport type {\n KnowledgeImprovementCandidateRecord,\n KnowledgeImprovementCandidateRef,\n KnowledgeImprovementEvidence,\n KnowledgeImprovementResult,\n KnowledgeImprovementRunState,\n KnowledgeImprovementTarget,\n ResolvedKnowledgeImprovementCandidate,\n ResolvedKnowledgeImprovementComparison,\n UseKnowledgeImprovementCandidateOptions,\n} from './contracts'\nimport {\n KnowledgeImprovementCandidateRefSchema,\n KnowledgeImprovementEvidenceSchema,\n safePathSegmentSchema,\n} from './contracts'\nimport {\n assertExactCandidatePlatform,\n candidateEvidenceRelativePath,\n loadKnowledgeImprovementStateFromRun,\n withKnowledgeImprovementRun,\n} from './state'\n\n/** Freeze the exact knowledge bytes and measured evidence a later approval may promote. */\nexport function knowledgeImprovementCandidateRef(\n result: Pick<KnowledgeImprovementResult, 'runId' | 'state' | 'candidate'>,\n): KnowledgeImprovementCandidateRef {\n if (!result.candidate) throw new Error('knowledge improvement result has no candidate')\n return candidateRefFor(result.runId, result.state, result.candidate)\n}\n\n/** Use both frozen sides of one measured comparison in isolated, integrity-checked copies. */\nexport async function withKnowledgeImprovementComparison<T>(\n options: UseKnowledgeImprovementCandidateOptions,\n use: (comparison: ResolvedKnowledgeImprovementComparison) => Promise<T> | T,\n): Promise<T> {\n assertExactCandidatePlatform()\n const reference = Object.freeze(KnowledgeImprovementCandidateRefSchema.parse(options.candidate))\n return withKnowledgeImprovementRun(options.root, reference.runId, false, async (runDir) => {\n const state = await loadKnowledgeImprovementStateFromRun(options.root, reference.runId, runDir)\n return withMeasuredCandidateSnapshot(options.root, runDir, state, reference, (resolved) =>\n withBaselineSnapshot(\n runDir,\n reference.baseHash,\n (baselineRoot) =>\n withIsolatedKnowledgeCopy(\n baselineRoot,\n reference.baseHash,\n 'baseline',\n (baseline) =>\n withIsolatedKnowledgeCopy(\n resolved.root,\n reference.candidateHash,\n 'candidate',\n (candidate) =>\n use(\n Object.freeze({\n reference,\n stateScope: Object.freeze(normalizeKnowledgeStateScope(state.stateScope)),\n evaluation: immutableJsonValue(structuredClone(resolved.evidence.evaluation)),\n baseline: Object.freeze({ root: baseline, hash: reference.baseHash }),\n candidate: Object.freeze({ root: candidate, hash: reference.candidateHash }),\n }),\n ),\n state.stateScope,\n ),\n state.stateScope,\n ),\n state.stateScope,\n ),\n )\n })\n}\n\n/** Use the frozen candidate side of one measured comparison. */\nexport async function withKnowledgeImprovementCandidate<T>(\n options: UseKnowledgeImprovementCandidateOptions,\n use: (candidate: ResolvedKnowledgeImprovementCandidate) => Promise<T> | T,\n): Promise<T> {\n assertExactCandidatePlatform()\n const candidateRef = Object.freeze(\n KnowledgeImprovementCandidateRefSchema.parse(options.candidate),\n )\n return withKnowledgeImprovementRun(options.root, candidateRef.runId, false, async (runDir) => {\n const state = await loadKnowledgeImprovementStateFromRun(\n options.root,\n candidateRef.runId,\n runDir,\n )\n return withMeasuredCandidateSnapshot(options.root, runDir, state, candidateRef, (resolved) =>\n withIsolatedKnowledgeCopy(\n resolved.root,\n candidateRef.candidateHash,\n 'candidate',\n (root) =>\n use(\n Object.freeze({\n root,\n candidate: candidateRef,\n stateScope: Object.freeze(normalizeKnowledgeStateScope(state.stateScope)),\n evaluation: immutableJsonValue(structuredClone(resolved.evidence.evaluation)),\n }),\n ),\n state.stateScope,\n ),\n )\n })\n}\n\nexport function candidateRefFor(\n runId: string,\n state: KnowledgeImprovementRunState,\n candidate: KnowledgeImprovementCandidateRecord,\n): KnowledgeImprovementCandidateRef {\n if (candidate.status !== 'candidate-ready' && candidate.status !== 'promoted') {\n throw new Error(`knowledge candidate '${candidate.candidateId}' is not ready`)\n }\n return candidateIdentityFor(runId, state, candidate)\n}\n\nexport function candidateIdentityFor(\n runId: string,\n state: KnowledgeImprovementRunState,\n candidate: KnowledgeImprovementCandidateRecord,\n): KnowledgeImprovementCandidateRef {\n if (!candidate.candidateHash) {\n throw new Error(`knowledge candidate '${candidate.candidateId}' has no content hash`)\n }\n if (!candidate.evidenceHash) {\n throw new Error(`knowledge candidate '${candidate.candidateId}' has no evidence hash`)\n }\n if (!candidate.promotionPlanHash) {\n throw new Error(`knowledge candidate '${candidate.candidateId}' has no promotion plan hash`)\n }\n return Object.freeze({\n kind: 'knowledge-improvement-candidate',\n runId,\n candidateId: candidate.candidateId,\n goalHash: sha256(state.goal),\n baseHash: candidate.baseHash,\n candidateHash: candidate.candidateHash,\n evidenceHash: candidate.evidenceHash,\n promotionPlanHash: candidate.promotionPlanHash,\n })\n}\n\nexport async function withMeasuredCandidateSnapshot<T>(\n liveRoot: string,\n runDir: string,\n state: KnowledgeImprovementRunState,\n candidateRef: KnowledgeImprovementCandidateRef,\n use: (snapshot: {\n root: string\n candidate: KnowledgeImprovementCandidateRecord\n evidence: KnowledgeImprovementEvidence\n }) => Promise<T> | T,\n): Promise<T> {\n await assertStateIdentity(liveRoot, candidateRef, state)\n const candidate = state.candidates.find((entry) => entry.candidateId === candidateRef.candidateId)\n if (!candidate) {\n throw new Error(`knowledge candidate '${candidateRef.candidateId}' does not exist`)\n }\n const expectedRef = candidateRefFor(candidateRef.runId, state, candidate)\n if (canonicalJson(expectedRef) !== canonicalJson(candidateRef)) {\n throw new Error('knowledge candidate approval does not match the measured candidate')\n }\n const evidence = await assertCandidateEvidence(runDir, candidateRef, state.implementationRef)\n const relativePath = join(\n 'candidates',\n candidate.candidateId,\n 'snapshots',\n candidateRef.candidateHash,\n )\n return withSafeDirectory(runDir, relativePath, false, async (root) => {\n if ((await hashKnowledgeBase(root, state.stateScope)) !== candidateRef.candidateHash) {\n throw new Error('knowledge candidate snapshot changed after approval')\n }\n const result = await use({ root, candidate, evidence })\n if ((await hashKnowledgeBase(root, state.stateScope)) !== candidateRef.candidateHash) {\n throw new Error('knowledge candidate snapshot changed during use')\n }\n return result\n })\n}\n\nasync function withIsolatedKnowledgeCopy<T>(\n sourceRoot: string,\n expectedHash: string,\n target: KnowledgeImprovementTarget,\n use: (root: string) => Promise<T> | T,\n scope?: KnowledgeStateScope,\n): Promise<T> {\n const isolationRoot = await mkdtemp(join(tmpdir(), 'agent-knowledge-snapshot-'))\n const snapshotRoot = join(isolationRoot, 'snapshot')\n try {\n await copyKnowledgeWorkspace(sourceRoot, snapshotRoot, scope)\n if ((await hashKnowledgeBase(snapshotRoot, scope)) !== expectedHash) {\n throw new Error(`isolated knowledge ${target} does not match its measured content`)\n }\n const result = await use(snapshotRoot)\n if ((await hashKnowledgeBase(snapshotRoot, scope)) !== expectedHash) {\n throw new Error(`knowledge ${target} snapshot changed during use`)\n }\n return result\n } finally {\n await rm(isolationRoot, { recursive: true, force: true })\n }\n}\n\nexport async function assertCandidateEvidence(\n runDir: string,\n candidate: KnowledgeImprovementCandidateRef,\n expectedImplementationRef: string,\n): Promise<KnowledgeImprovementEvidence> {\n const evidence = KnowledgeImprovementEvidenceSchema.parse(\n JSON.parse(\n (\n await readRegularFileWithinRoot(\n runDir,\n candidateEvidenceRelativePath(candidate.candidateId),\n )\n ).bytes.toString('utf8'),\n ),\n )\n const actualHash = contentHash(evidence)\n if (actualHash !== candidate.evidenceHash) {\n throw new Error(\n `knowledge candidate evidence changed after approval: expected ${candidate.evidenceHash}, got ${actualHash}`,\n )\n }\n if (\n evidence.runId !== candidate.runId ||\n evidence.candidateId !== candidate.candidateId ||\n evidence.goalHash !== candidate.goalHash ||\n evidence.implementationRef !== expectedImplementationRef ||\n evidence.baseHash !== candidate.baseHash ||\n evidence.candidateHash !== candidate.candidateHash ||\n evidence.promotionPlanHash !== candidate.promotionPlanHash ||\n evidence.evaluation.passed !== true\n ) {\n throw new Error('knowledge candidate evidence does not match the approved candidate')\n }\n return evidence\n}\n\nexport async function assertStateIdentity(\n root: string,\n candidateRef: KnowledgeImprovementCandidateRef,\n state: KnowledgeImprovementRunState,\n): Promise<void> {\n if (state.runId !== candidateRef.runId) {\n throw new Error('knowledge candidate run identity does not match persisted state')\n }\n if (!(await canonicalPathsEqual(state.root, root))) {\n throw new Error('knowledge candidate root does not match persisted state')\n }\n if (sha256(state.goal) !== candidateRef.goalHash) {\n throw new Error('knowledge candidate goal does not match persisted state')\n }\n if (state.baseHash !== candidateRef.baseHash) {\n throw new Error('knowledge candidate base does not match persisted state')\n }\n}\n\nexport async function createCandidateWorkspace(\n runDir: string,\n state: KnowledgeImprovementRunState,\n root: string,\n now: () => Date,\n): Promise<KnowledgeImprovementCandidateRecord> {\n const iteration = state.candidates.length + 1\n const candidateId = stableId('kcand', `${state.runId}:${iteration}:${now().toISOString()}`)\n const candidateRoot = candidateWorkspacePath(runDir, candidateId)\n await copyKnowledgeWorkspace(root, candidateRoot, state.stateScope)\n const createdAt = now().toISOString()\n return {\n iteration,\n candidateId,\n baseHash: state.baseHash,\n status: 'running',\n createdAt,\n updatedAt: createdAt,\n }\n}\n\nfunction candidateWorkspacePath(runDir: string, candidateId: string): string {\n return join(runDir, 'candidates', safePathSegmentSchema.parse(candidateId), 'workspace')\n}\n\nfunction baselineSnapshotPath(runDir: string): string {\n return join(runDir, 'baseline')\n}\n\nexport async function createBaselineSnapshot(\n runDir: string,\n root: string,\n expectedHash: string,\n scope?: KnowledgeStateScope,\n): Promise<void> {\n const target = baselineSnapshotPath(runDir)\n try {\n await assertBaselineSnapshot(runDir, expectedHash, scope)\n return\n } catch (error) {\n if (!isMissingFile(error)) throw error\n }\n const preparation = await mkdtemp(join(runDir, 'baseline-prepare-'))\n let activated = false\n try {\n await copyKnowledgeWorkspace(root, preparation, scope)\n const actualHash = await hashKnowledgeBase(preparation, scope)\n if (actualHash !== expectedHash) {\n throw new Error(\n `knowledge base changed while baseline was frozen: expected ${expectedHash}, got ${actualHash}`,\n )\n }\n await renameDurable(preparation, target)\n activated = true\n } finally {\n if (!activated) await rm(preparation, { recursive: true, force: true })\n }\n}\n\nexport async function ensureBaselineSnapshot(\n runDir: string,\n root: string,\n expectedHash: string,\n scope?: KnowledgeStateScope,\n): Promise<void> {\n try {\n await assertBaselineSnapshot(runDir, expectedHash, scope)\n } catch (error) {\n if (!isMissingFile(error)) throw error\n const liveHash = await hashKnowledgeBase(root, scope)\n if (liveHash !== expectedHash) {\n throw new Error(\n 'knowledge improvement baseline snapshot is missing and cannot be reconstructed',\n )\n }\n await createBaselineSnapshot(runDir, root, expectedHash, scope)\n }\n}\n\nasync function assertBaselineSnapshot(\n runDir: string,\n expectedHash: string,\n scope?: KnowledgeStateScope,\n): Promise<void> {\n await withBaselineSnapshot(runDir, expectedHash, () => undefined, scope)\n}\n\nexport async function withBaselineSnapshot<T>(\n runDir: string,\n expectedHash: string,\n use: (baselineRoot: string) => Promise<T> | T,\n scope?: KnowledgeStateScope,\n): Promise<T> {\n return withSafeDirectory(runDir, 'baseline', false, async (baselineRoot) => {\n const actualHash = await hashKnowledgeBase(baselineRoot, scope)\n if (actualHash !== expectedHash) {\n throw new Error(\n `knowledge improvement baseline changed: expected ${expectedHash}, got ${actualHash}`,\n )\n }\n return use(baselineRoot)\n })\n}\n\nexport async function withFrozenCandidateWorkspace<T>(\n runDir: string,\n candidate: KnowledgeImprovementCandidateRecord,\n candidateRoot: string,\n use: (snapshot: { root: string; hash: string }) => Promise<T> | T,\n scope?: KnowledgeStateScope,\n): Promise<T> {\n const snapshotsPath = join(\n 'candidates',\n safePathSegmentSchema.parse(candidate.candidateId),\n 'snapshots',\n )\n return withSafeDirectory(runDir, snapshotsPath, true, async (snapshotsDir) => {\n const preparation = await mkdtemp(join(snapshotsDir, 'prepare-'))\n let activated = false\n try {\n await copyKnowledgeWorkspace(candidateRoot, preparation, scope)\n const hash = await hashKnowledgeBase(preparation, scope)\n try {\n const result = await withSafeDirectory(snapshotsDir, hash, false, async (existing) => {\n if ((await hashKnowledgeBase(existing, scope)) !== hash) {\n throw new Error('knowledge candidate snapshot does not match its content identity')\n }\n return use({ root: existing, hash })\n })\n await rm(preparation, { recursive: true, force: true })\n activated = true\n return result\n } catch (error) {\n if (!isMissingFile(error)) throw error\n }\n await renameDurable(preparation, join(snapshotsDir, hash))\n activated = true\n return withSafeDirectory(snapshotsDir, hash, false, (root) => use({ root, hash }))\n } finally {\n if (!activated) await rm(preparation, { recursive: true, force: true })\n }\n })\n}\n\nexport function clearCandidateMeasurement(candidate: KnowledgeImprovementCandidateRecord): void {\n delete candidate.candidateHash\n delete candidate.evidenceHash\n delete candidate.promotionPlanHash\n}\n\nasync function copyKnowledgeWorkspace(\n sourceRoot: string,\n targetRoot: string,\n scope?: KnowledgeStateScope,\n): Promise<void> {\n const normalized = normalizeKnowledgeStateScope(scope)\n await withKnowledgeRead(sourceRoot, async () => {\n await rm(targetRoot, { recursive: true, force: true })\n await mkdir(join(targetRoot, normalized.pagesDirectory), { recursive: true })\n await mkdir(join(targetRoot, 'raw', 'sources'), { recursive: true })\n for (const path of knowledgeScopePaths(normalized)) {\n await copyIfExists(join(sourceRoot, path), join(targetRoot, path))\n }\n })\n await writeKnowledgeIndex(targetRoot, { pagesDirectory: normalized.pagesDirectory })\n}\n\nfunction knowledgeScopePaths(scope: KnowledgeStateScope): string[] {\n const normalized = normalizeKnowledgeStateScope(scope)\n return [\n normalized.pagesDirectory,\n 'raw',\n '.agent-knowledge/sources.json',\n ...(normalized.researchState ? KNOWLEDGE_RESEARCH_STATE_PATHS : []),\n ]\n}\n\nasync function copyIfExists(source: string, target: string): Promise<void> {\n let sourceStat: Awaited<ReturnType<typeof lstat>>\n try {\n sourceStat = await lstat(source)\n } catch (error) {\n if (isMissingFile(error)) return\n throw error\n }\n if (!sourceStat.isDirectory() && !sourceStat.isFile()) {\n throw new Error(`knowledge surface contains an unsupported filesystem entry: ${source}`)\n }\n await mkdir(dirname(target), { recursive: true })\n await cp(source, target, { recursive: sourceStat.isDirectory(), dereference: false })\n}\n\nexport async function hashKnowledgeBase(\n root: string,\n scope?: KnowledgeStateScope,\n): Promise<string> {\n return withKnowledgeRead(root, () => hashKnowledgeBaseUnlocked(root, scope))\n}\n\nasync function hashKnowledgeBaseUnlocked(\n root: string,\n scope?: KnowledgeStateScope,\n): Promise<string> {\n const normalized = normalizeKnowledgeStateScope(scope)\n const entries = await knowledgeHashEntries(root, normalized)\n const files = entries.map(({ path, hash, mode }) => ({ path, hash, mode }))\n return sha256(\n JSON.stringify(\n normalized.pagesDirectory === 'knowledge' && !normalized.researchState\n ? files\n : { scope: normalized, files },\n ),\n )\n}\n\nexport interface KnowledgeFileIdentity {\n path: string\n hash: string\n transactionHash: string\n mode: number\n}\n\nexport async function knowledgeHashEntries(\n root: string,\n scope?: KnowledgeStateScope,\n): Promise<KnowledgeFileIdentity[]> {\n const entries: KnowledgeFileIdentity[] = []\n for (const path of knowledgeScopePaths(scope ?? {})) {\n try {\n const files =\n path === '.agent-knowledge/sources.json' || path === '.agent-knowledge/events.json'\n ? [{ ...(await readRegularFileWithinRoot(root, path)), path }]\n : await listRegularFilesWithinRoot(root, path)\n for (const file of files)\n entries.push(knowledgeFileIdentity(file.path, file.bytes, file.mode))\n } catch (error) {\n if (!isMissingFile(error)) throw error\n }\n }\n entries.sort((a, b) => a.path.localeCompare(b.path))\n return entries\n}\n\nfunction knowledgeFileIdentity(path: string, bytes: Buffer, mode: number): KnowledgeFileIdentity {\n return {\n path,\n hash: sha256(bytes.toString('base64')),\n transactionHash: createHash('sha256').update(bytes).digest('hex'),\n mode,\n }\n}\n","import { createHash } from 'node:crypto'\nimport { canonicalJson, contentHash } from '@tangle-network/agent-eval'\nimport type { AgentImprovementActivationResult } from '@tangle-network/agent-interface'\nimport { readRegularFileWithinRoot } from '../durable-fs'\nimport {\n applyKnowledgeFileTransaction,\n assertKnowledgeMutationPath,\n finishKnowledgeFileTransaction,\n type KnowledgeFileMutation,\n type KnowledgeFileTransaction,\n type KnowledgeFileTransactionPlanEntry,\n knowledgeFileTransactionPlanHash,\n prepareKnowledgeFileTransaction,\n rollbackKnowledgeFileTransaction,\n} from '../file-transaction'\nimport { writeKnowledgeIndex } from '../indexer'\nimport { type KnowledgeStateScope, normalizeKnowledgeStateScope } from '../knowledge-state-scope'\nimport { withKnowledgeMutation } from '../mutation-lock'\nimport type { RunRagKnowledgeImprovementLoopResult } from '../rag-improvement-loop'\nimport type { ResolvedKnowledgeImprovementActivationPersistence } from './activation'\nimport {\n loadKnowledgeActivationRecord,\n persistKnowledgeActivationResult,\n resolveKnowledgeActivationPersistence,\n sourceKnowledgeHash,\n} from './activation'\nimport type {\n KnowledgeImprovementCandidateRecord,\n KnowledgeImprovementCandidateRef,\n KnowledgeImprovementMutationReceipt,\n KnowledgeImprovementMutationResult,\n KnowledgeImprovementOptions,\n KnowledgeImprovementRunState,\n KnowledgeImprovementTarget,\n PromoteKnowledgeCandidateOptions,\n RestoreKnowledgeCandidateBaselineOptions,\n} from './contracts'\nimport { DEFAULT_LEASE_TTL_MS, KnowledgeImprovementCandidateRefSchema } from './contracts'\nimport {\n acquireRunLease,\n appendLedger,\n assertExactCandidatePlatform,\n blockRun,\n loadKnowledgeImprovementEventsFromRun,\n loadKnowledgeImprovementStateFromRun,\n saveState,\n withKnowledgeImprovementRun,\n} from './state'\nimport {\n assertCandidateEvidence,\n assertStateIdentity,\n candidateIdentityFor,\n hashKnowledgeBase,\n knowledgeHashEntries,\n withBaselineSnapshot,\n withMeasuredCandidateSnapshot,\n} from './workspace'\n\n/** Promote one previously measured candidate without rerunning research or evaluation. */\nexport async function promoteKnowledgeCandidate(\n options: PromoteKnowledgeCandidateOptions,\n): Promise<KnowledgeImprovementMutationResult> {\n return transitionKnowledgeCandidate(options, 'candidate')\n}\n\n/** Restore the frozen baseline paired with one previously measured candidate. */\nexport async function restoreKnowledgeCandidateBaseline(\n options: RestoreKnowledgeCandidateBaselineOptions,\n): Promise<KnowledgeImprovementMutationResult> {\n return transitionKnowledgeCandidate(options, 'baseline')\n}\n\nasync function transitionKnowledgeCandidate(\n options: PromoteKnowledgeCandidateOptions,\n target: KnowledgeImprovementTarget,\n): Promise<KnowledgeImprovementMutationResult> {\n assertExactCandidatePlatform()\n const candidateRef = Object.freeze(\n KnowledgeImprovementCandidateRefSchema.parse(options.candidate),\n )\n const now = options.now ?? (() => new Date())\n const activation = options.activation\n ? resolveKnowledgeActivationPersistence(options.activation, candidateRef, target)\n : undefined\n return withKnowledgeImprovementRun(options.root, candidateRef.runId, false, async (runDir) => {\n const lease = await acquireRunLease(runDir, {\n ownerId: options.ownerId ?? `pid-${process.pid}`,\n ttlMs: options.leaseTtlMs ?? DEFAULT_LEASE_TTL_MS,\n })\n try {\n lease.assertOwned()\n const state = await loadKnowledgeImprovementStateFromRun(\n options.root,\n candidateRef.runId,\n runDir,\n )\n return await applyKnowledgeCandidateTarget(\n {\n root: options.root,\n runDir,\n state,\n candidateRef,\n leaseTtlMs: options.leaseTtlMs ?? DEFAULT_LEASE_TTL_MS,\n assertRunOwned: lease.assertOwned,\n now,\n onState: options.onState,\n activation,\n },\n target,\n )\n } finally {\n await lease.release()\n }\n })\n}\n\ninterface KnowledgeCandidateTransitionInput {\n root: string\n runDir: string\n state: KnowledgeImprovementRunState\n candidateRef: KnowledgeImprovementCandidateRef\n activation?: ResolvedKnowledgeImprovementActivationPersistence\n leaseTtlMs: number\n assertRunOwned(): void\n now: () => Date\n onState?: KnowledgeImprovementOptions['onState']\n lifecycle?: RunRagKnowledgeImprovementLoopResult\n}\n\nasync function applyKnowledgeCandidateTarget(\n input: KnowledgeCandidateTransitionInput,\n target: KnowledgeImprovementTarget,\n): Promise<KnowledgeImprovementMutationResult> {\n const { candidateRef, runDir, state } = input\n await assertStateIdentity(input.root, candidateRef, state)\n const candidate = state.candidates.find((entry) => entry.candidateId === candidateRef.candidateId)\n if (\n !candidate ||\n canonicalJson(candidateIdentityFor(candidateRef.runId, state, candidate)) !==\n canonicalJson(candidateRef)\n ) {\n throw new Error('knowledge candidate approval does not match the measured candidate')\n }\n const action = target === 'candidate' ? 'promotion' : 'restore'\n const desiredHash = target === 'candidate' ? candidateRef.candidateHash : candidateRef.baseHash\n const purpose = knowledgeCandidateTransitionPurpose(candidateRef, state.implementationRef, target)\n const recoveryOwner = input.activation\n ? `knowledge-improvement-activation:${input.activation.activation.digest}`\n : 'knowledge-improvement-candidate-transition'\n return withKnowledgeMutation(\n input.root,\n async (mutationLock) => {\n const assertOwned = () => {\n mutationLock.assertOwned()\n input.assertRunOwned()\n }\n assertOwned()\n const transactionRoot = mutationLock.transactionRoot\n const recovery =\n mutationLock.recovery?.purpose === purpose ? mutationLock.recovery : undefined\n if (!recovery) {\n await assertCandidateEvidence(runDir, candidateRef, state.implementationRef)\n }\n const existingActivation = input.activation\n ? await loadKnowledgeActivationRecord(\n runDir,\n candidateRef,\n input.activation.activation,\n target,\n input.activation.identity,\n )\n : null\n if (existingActivation) {\n if (recovery?.direction === 'rollback') {\n throw new Error('stored knowledge activation result conflicts with a pending rollback')\n }\n if (recovery) {\n const recoveredHash = await hashKnowledgeBase(input.root, state.stateScope)\n if (recoveredHash !== existingActivation.mutation.afterHash) {\n throw new Error('stored knowledge activation result does not match the recovered files')\n }\n await finishKnowledgeFileTransaction({\n root: input.root,\n transactionRoot,\n transaction: recovery.transaction,\n assertOwned,\n })\n }\n if (existingActivation.result.outcome.status === 'conflict') {\n const reason = candidateTransitionConflictReason(\n target,\n candidateRef,\n existingActivation.mutation.afterHash,\n )\n const blocked = await blockCandidateTransition(\n input,\n candidate,\n target,\n reason,\n existingActivation.mutation.afterHash,\n )\n return { ...blocked, activationResult: existingActivation.result }\n }\n return candidateTransitionResult(\n input,\n candidate,\n target === 'candidate' && state.status === 'promoted',\n false,\n existingActivation.mutation,\n existingActivation.result,\n )\n }\n if (recovery?.direction === 'rollback') {\n await finishKnowledgeFileTransaction({\n root: input.root,\n transactionRoot,\n transaction: recovery.transaction,\n assertOwned,\n })\n }\n const recovered = recovery?.direction === 'apply' ? recovery : undefined\n let pending: KnowledgeFileTransaction | null =\n input.activation && recovered ? recovered.transaction : null\n const currentHash = await hashKnowledgeBase(input.root, state.stateScope)\n let transactionId = recovered?.transactionId ?? null\n if (recovered && currentHash !== desiredHash) {\n throw new Error(`recovered knowledge ${action} does not match the approved target`)\n }\n if (state.status === 'promoted' && state.promotedCandidateId !== candidate.candidateId) {\n throw new Error(\n `knowledge run already promoted '${state.promotedCandidateId ?? 'unknown'}'`,\n )\n }\n if (\n target === 'candidate' &&\n state.status === 'promoted' &&\n currentHash !== candidateRef.candidateHash\n ) {\n throw new Error(\n `promoted knowledge base changed: expected ${candidateRef.candidateHash}, got ${currentHash}`,\n )\n }\n if (state.status !== 'promoted' && state.status !== 'candidate-ready') {\n throw new Error(\n `knowledge candidate is not ready for ${action}: run=${state.status}, candidate=${candidate.status}`,\n )\n }\n if (currentHash !== state.baseHash && currentHash !== candidateRef.candidateHash) {\n const reason =\n target === 'candidate'\n ? `base changed before promotion: expected ${state.baseHash}, got ${currentHash}`\n : `knowledge changed before restore: expected ${candidateRef.candidateHash}, got ${currentHash}`\n const mutation = Object.freeze({\n target,\n beforeHash: currentHash,\n afterHash: currentHash,\n changed: false,\n transactionId: null,\n recovered: false,\n }) satisfies KnowledgeImprovementMutationReceipt\n const activationResult = input.activation\n ? await persistKnowledgeActivationResult(\n runDir,\n candidateRef,\n input.activation,\n target,\n mutation,\n )\n : undefined\n const blocked = await blockCandidateTransition(\n input,\n candidate,\n target,\n reason,\n currentHash,\n )\n return activationResult ? { ...blocked, activationResult } : blocked\n }\n\n if (currentHash !== desiredHash && !pending) {\n pending = await withMeasuredCandidateSnapshot(\n input.root,\n runDir,\n state,\n candidateRef,\n (resolved) =>\n withBaselineSnapshot(\n runDir,\n state.baseHash,\n async (baselineRoot) => {\n const sourceRoot = target === 'candidate' ? baselineRoot : resolved.root\n const targetRoot = target === 'candidate' ? resolved.root : baselineRoot\n const plan = await knowledgeFilePlanEntries(\n sourceRoot,\n targetRoot,\n state.stateScope,\n )\n assertCandidateTransitionPlan(plan, candidateRef, target, state.stateScope)\n return prepareKnowledgeFileTransaction({\n root: input.root,\n transactionRoot,\n purpose,\n ...normalizeKnowledgeStateScope(state.stateScope),\n recoveryOwner,\n mutations: await knowledgePlanMutations(targetRoot, plan),\n includeUnchanged: true,\n now: input.now,\n })\n },\n state.stateScope,\n ),\n )\n if (!pending) {\n throw new Error(`knowledge ${action} plan unexpectedly contained no file changes`)\n }\n transactionId = pending.transactionId\n try {\n assertCandidateTransitionTransaction(pending, candidateRef, target, state.stateScope)\n } catch (error) {\n try {\n await rollbackKnowledgeFileTransaction({\n root: input.root,\n transactionRoot,\n transaction: pending,\n beforeCommit: assertOwned,\n })\n await finishKnowledgeFileTransaction({\n root: input.root,\n transactionRoot,\n transaction: pending,\n assertOwned,\n })\n } catch (cleanupError) {\n throw new AggregateError(\n [error, cleanupError],\n `invalid knowledge ${action} transaction could not be removed`,\n )\n }\n throw error\n }\n }\n try {\n if (pending) {\n await applyKnowledgeFileTransaction({\n root: input.root,\n transactionRoot,\n transaction: pending,\n beforeCommit: assertOwned,\n })\n }\n assertOwned()\n if ((await hashKnowledgeBase(input.root, state.stateScope)) !== desiredHash) {\n throw new Error(`knowledge ${action} content does not match the approved target`)\n }\n await writeKnowledgeIndex(input.root, state.stateScope)\n } catch (error) {\n if (!pending) throw error\n if (recovered && input.activation) throw error\n try {\n assertOwned()\n } catch (ownershipError) {\n throw new AggregateError(\n [error, ownershipError],\n `knowledge ${action} lost its lock and left the transaction pending`,\n )\n }\n try {\n await rollbackKnowledgeFileTransaction({\n root: input.root,\n transactionRoot,\n transaction: pending,\n beforeCommit: assertOwned,\n })\n await finishKnowledgeFileTransaction({\n root: input.root,\n transactionRoot,\n transaction: pending,\n assertOwned,\n })\n await writeKnowledgeIndex(input.root, state.stateScope)\n } catch (rollbackError) {\n throw new AggregateError(\n [error, rollbackError],\n `knowledge ${action} failed and could not restore the previous files`,\n )\n }\n throw error\n }\n candidate.status = target === 'candidate' ? 'promoted' : 'candidate-ready'\n candidate.updatedAt = input.now().toISOString()\n state.status = candidate.status\n if (target === 'candidate') state.promotedCandidateId = candidate.candidateId\n else delete state.promotedCandidateId\n delete state.blockedReason\n state.updatedAt = input.now().toISOString()\n await saveState(runDir, state, input.onState)\n await ensureCandidateTransitionEvent(runDir, candidateRef, target)\n let finalHash = await hashKnowledgeBase(input.root, state.stateScope)\n if (finalHash !== desiredHash) {\n throw new Error(`knowledge ${action} changed before its result was returned`)\n }\n const mutation = Object.freeze({\n target,\n beforeHash: transactionId ? sourceKnowledgeHash(candidateRef, target) : currentHash,\n afterHash: finalHash,\n changed: transactionId !== null,\n transactionId,\n recovered: recovered !== undefined,\n }) satisfies KnowledgeImprovementMutationReceipt\n const activationResult = input.activation\n ? await persistKnowledgeActivationResult(\n runDir,\n candidateRef,\n input.activation,\n target,\n mutation,\n )\n : undefined\n if ((await hashKnowledgeBase(input.root, state.stateScope)) !== finalHash) {\n throw new Error(`knowledge ${action} changed while its result was persisted`)\n }\n if (pending) {\n await finishKnowledgeFileTransaction({\n root: input.root,\n transactionRoot,\n transaction: pending,\n assertOwned,\n })\n }\n finalHash = await hashKnowledgeBase(input.root, state.stateScope)\n if (finalHash !== desiredHash) {\n throw new Error(`knowledge ${action} changed before its result was returned`)\n }\n return candidateTransitionResult(\n input,\n candidate,\n target === 'candidate',\n false,\n mutation,\n activationResult,\n )\n },\n {\n staleMs: input.leaseTtlMs,\n resumeTransaction: {\n purpose,\n recoveryOwner,\n validate: (transaction) =>\n assertCandidateTransitionTransaction(transaction, candidateRef, target, state.stateScope),\n deferFinish: input.activation !== undefined,\n },\n },\n )\n}\n\nfunction candidateTransitionConflictReason(\n target: KnowledgeImprovementTarget,\n candidate: KnowledgeImprovementCandidateRef,\n currentHash: string,\n): string {\n return target === 'candidate'\n ? `base changed before promotion: expected ${candidate.baseHash}, got ${currentHash}`\n : `knowledge changed before restore: expected ${candidate.candidateHash}, got ${currentHash}`\n}\n\nasync function blockCandidateTransition(\n input: KnowledgeCandidateTransitionInput,\n candidate: KnowledgeImprovementCandidateRecord,\n target: KnowledgeImprovementTarget,\n reason: string,\n currentHash: string,\n): Promise<KnowledgeImprovementMutationResult> {\n if (input.state.status === 'promoted') {\n candidate.status = 'blocked'\n candidate.updatedAt = input.now().toISOString()\n delete input.state.promotedCandidateId\n }\n await blockRun(input.runDir, input.state, reason, input.onState, input.now)\n await appendLedger(input.runDir, {\n type: target === 'candidate' ? 'promotion.blocked' : 'restore.blocked',\n runId: input.candidateRef.runId,\n candidateId: candidate.candidateId,\n reason,\n })\n return candidateTransitionResult(input, candidate, false, true, {\n target,\n beforeHash: currentHash,\n afterHash: currentHash,\n changed: false,\n transactionId: null,\n recovered: false,\n })\n}\n\nfunction candidateTransitionResult(\n input: KnowledgeCandidateTransitionInput,\n candidate: KnowledgeImprovementCandidateRecord,\n promoted: boolean,\n blocked: boolean,\n mutation: KnowledgeImprovementMutationReceipt,\n activationResult?: AgentImprovementActivationResult,\n): KnowledgeImprovementMutationResult {\n return {\n runId: input.candidateRef.runId,\n state: input.state,\n candidate,\n ...(input.lifecycle ? { lifecycle: input.lifecycle } : {}),\n mutation,\n ...(activationResult ? { activationResult } : {}),\n promoted,\n blocked,\n }\n}\n\nfunction knowledgeCandidateTransitionPurpose(\n candidate: KnowledgeImprovementCandidateRef,\n implementationRef: string,\n target: KnowledgeImprovementTarget,\n): string {\n const action = target === 'candidate' ? 'promotion' : 'restore'\n return `knowledge-${action}:${contentHash({ candidate, implementationRef })}`\n}\n\nexport async function knowledgeFilePlanEntries(\n sourceRoot: string,\n targetRoot: string,\n scope?: KnowledgeStateScope,\n): Promise<KnowledgeFileTransactionPlanEntry[]> {\n const [before, after] = await Promise.all([\n knowledgeHashEntries(sourceRoot, scope),\n knowledgeHashEntries(targetRoot, scope),\n ])\n const beforeByPath = new Map(before.map((entry) => [entry.path, entry]))\n const afterByPath = new Map(after.map((entry) => [entry.path, entry]))\n const paths = [\n ...new Set([...before.map((entry) => entry.path), ...after.map((entry) => entry.path)]),\n ].sort((left, right) => left.localeCompare(right))\n return paths.map((path) => {\n assertKnowledgeMutationPath(\n path,\n normalizeKnowledgeStateScope(scope).pagesDirectory,\n scope?.researchState,\n )\n const beforeEntry = beforeByPath.get(path)\n const afterEntry = afterByPath.get(path)\n return {\n path,\n beforeHash: beforeEntry?.transactionHash ?? null,\n afterHash: afterEntry?.transactionHash ?? null,\n ...(beforeEntry ? { beforeMode: beforeEntry.mode } : {}),\n ...(afterEntry ? { afterMode: afterEntry.mode } : {}),\n }\n })\n}\n\nasync function knowledgePlanMutations(\n targetRoot: string,\n plan: readonly KnowledgeFileTransactionPlanEntry[],\n): Promise<KnowledgeFileMutation[]> {\n return Promise.all(\n plan.map(async (entry) => {\n if (entry.afterHash === null) return { path: entry.path, content: null }\n const file = await readRegularFileWithinRoot(targetRoot, entry.path)\n const actualHash = createHash('sha256').update(file.bytes).digest('hex')\n if (actualHash !== entry.afterHash || file.mode !== entry.afterMode) {\n throw new Error(`knowledge target file changed before activation: ${entry.path}`)\n }\n return { path: entry.path, content: file.bytes, mode: file.mode }\n }),\n )\n}\n\nfunction assertCandidateTransitionPlan(\n plan: readonly KnowledgeFileTransactionPlanEntry[],\n candidate: KnowledgeImprovementCandidateRef,\n target: KnowledgeImprovementTarget,\n scope?: KnowledgeStateScope,\n): void {\n const approvedDirection = target === 'candidate' ? plan : reverseKnowledgeFilePlan(plan)\n const actualPlanHash = knowledgeFileTransactionPlanHash(\n approvedDirection,\n normalizeKnowledgeStateScope(scope).pagesDirectory,\n scope?.researchState,\n )\n if (actualPlanHash !== candidate.promotionPlanHash) {\n throw new Error(\n `knowledge candidate plan changed after approval: expected ${candidate.promotionPlanHash}, got ${actualPlanHash}`,\n )\n }\n}\n\nfunction assertCandidateTransitionTransaction(\n transaction: KnowledgeFileTransaction,\n candidate: KnowledgeImprovementCandidateRef,\n target: KnowledgeImprovementTarget,\n scope?: KnowledgeStateScope,\n): void {\n assertCandidateTransitionPlan(transaction.entries, candidate, target, scope)\n}\n\nfunction reverseKnowledgeFilePlan(\n plan: readonly KnowledgeFileTransactionPlanEntry[],\n): KnowledgeFileTransactionPlanEntry[] {\n return plan.map((entry) => ({\n path: entry.path,\n beforeHash: entry.afterHash,\n afterHash: entry.beforeHash,\n ...(entry.afterMode === undefined ? {} : { beforeMode: entry.afterMode }),\n ...(entry.beforeMode === undefined ? {} : { afterMode: entry.beforeMode }),\n }))\n}\n\nasync function ensureCandidateTransitionEvent(\n runDir: string,\n candidateRef: KnowledgeImprovementCandidateRef,\n target: KnowledgeImprovementTarget,\n): Promise<void> {\n if (await hasCandidateTransitionEvent(runDir, candidateRef, target)) return\n await appendLedger(runDir, {\n type: target === 'candidate' ? 'candidate.promoted' : 'candidate.restored',\n runId: candidateRef.runId,\n candidateId: candidateRef.candidateId,\n candidateHash: candidateRef.candidateHash,\n evidenceHash: candidateRef.evidenceHash,\n promotionPlanHash: candidateRef.promotionPlanHash,\n })\n}\n\nasync function hasCandidateTransitionEvent(\n runDir: string,\n candidateRef: KnowledgeImprovementCandidateRef,\n target: KnowledgeImprovementTarget,\n): Promise<boolean> {\n const eventType = target === 'candidate' ? 'candidate.promoted' : 'candidate.restored'\n let matched = false\n for (const row of await loadKnowledgeImprovementEventsFromRun(runDir)) {\n if (row.type !== eventType || row.candidateId !== candidateRef.candidateId) continue\n if (\n row.runId !== candidateRef.runId ||\n row.candidateHash !== candidateRef.candidateHash ||\n row.evidenceHash !== candidateRef.evidenceHash ||\n row.promotionPlanHash !== candidateRef.promotionPlanHash\n ) {\n throw new Error('persisted knowledge activation event conflicts with the approved candidate')\n }\n matched = true\n }\n return matched\n}\n","import { join } from 'node:path'\nimport { contentHash } from '@tangle-network/agent-eval'\nimport { writeJsonDurableWithinRoot } from '../durable-fs'\nimport type { EvalKnowledgeBundleBuildResult, KnowledgeReadinessSpec } from '../eval-readiness'\nimport { knowledgeFileTransactionPlanHash } from '../file-transaction'\nimport { sha256 } from '../ids'\nimport { assertImmutableRef } from '../immutable-ref'\nimport { buildKnowledgeIndex } from '../indexer'\nimport { normalizeKnowledgeStateScope } from '../knowledge-state-scope'\nimport { ragAnswerEvidenceRejectionReasons } from '../rag-answer-evidence'\nimport { type KnowledgeBaseQualityReport, scoreKnowledgeBaseIndex } from '../rag-eval'\nimport {\n type RagKnowledgeImprovementPhase,\n type RagKnowledgeResearchOptions,\n type RunRagKnowledgeImprovementLoopOptions,\n type RunRagKnowledgeImprovementLoopResult,\n runRagKnowledgeImprovementLoop,\n} from '../rag-improvement-loop'\nimport { runRagKnowledgeImprovementPhases } from '../rag-improvement-phases'\nimport { readinessFor } from '../readiness-helpers'\nimport { mean } from '../statistics'\nimport { type ValidateKnowledgeResult, validateKnowledgeIndex } from '../validate'\nimport type {\n KnowledgeImprovementCandidateRecord,\n KnowledgeImprovementMetric,\n KnowledgeImprovementOptions,\n KnowledgeImprovementRunState,\n} from './contracts'\nimport {\n EVALUATION_PHASES,\n improvementMetricSchema,\n KnowledgeImprovementEvidenceSchema,\n UPDATE_PHASES,\n} from './contracts'\nimport {\n appendLedger,\n candidateEvidenceRelativePath,\n saveState,\n withCandidateWorkspace,\n} from './state'\nimport { knowledgeFilePlanEntries } from './transition'\nimport {\n assertCandidateEvidence,\n candidateRefFor,\n clearCandidateMeasurement,\n hashKnowledgeBase,\n withBaselineSnapshot,\n withFrozenCandidateWorkspace,\n} from './workspace'\n\nexport function assertKnowledgeImprovementOptions(options: KnowledgeImprovementOptions): void {\n assertImmutableRef(options.implementationRef, 'knowledge improvement implementationRef')\n normalizeKnowledgeStateScope(options.stateScope)\n for (const phase of options.requiredPhases ?? []) {\n if (options.enabledPhases && !options.enabledPhases.includes(phase)) {\n throw new Error(`required phase ${phase} is not enabled`)\n }\n }\n if (\n options.answerQualityCostCeiling !== undefined &&\n (!Number.isFinite(options.answerQualityCostCeiling) || options.answerQualityCostCeiling < 0)\n ) {\n throw new Error(\n 'knowledge improvement answerQualityCostCeiling must be a non-negative finite number',\n )\n }\n if (options.ragOptimization) {\n assertImmutableRef(\n options.ragOptimization.executionRef,\n 'knowledge improvement RAG executionRef',\n )\n }\n if (options.retrieval) {\n assertImmutableRef(\n options.retrieval.executionRef,\n 'knowledge improvement retrieval executionRef',\n )\n }\n if (options.step && options.knowledgeResearch?.step) {\n throw new Error('improveKnowledgeBase accepts either step or knowledgeResearch.step, not both')\n }\n const updateDrivers = [\n Boolean(options.step ?? options.knowledgeResearch),\n Boolean(options.updateKnowledge),\n ].filter(Boolean).length\n if (updateDrivers > 1) {\n throw new Error(\n 'improveKnowledgeBase accepts only one knowledge-update driver: knowledgeResearch or updateKnowledge',\n )\n }\n}\n\nexport async function measureCandidate(\n runId: string,\n runDir: string,\n state: KnowledgeImprovementRunState,\n candidate: KnowledgeImprovementCandidateRecord,\n options: KnowledgeImprovementOptions,\n now: () => Date,\n): Promise<{\n candidate: KnowledgeImprovementCandidateRecord\n evaluation: KnowledgeImprovementMetric\n lifecycle?: RunRagKnowledgeImprovementLoopResult\n finalEvaluated: boolean\n}> {\n return withCandidateWorkspace(runDir, candidate, async (candidateRoot) => {\n const currentCandidateHash = await hashKnowledgeBase(candidateRoot, options.stateScope)\n if (\n candidate.status === 'candidate-ready' &&\n candidate.candidateHash === currentCandidateHash &&\n candidate.evidenceHash !== undefined &&\n candidate.promotionPlanHash !== undefined\n ) {\n const evidence = await assertCandidateEvidence(\n runDir,\n candidateRefFor(runId, state, candidate),\n state.implementationRef,\n )\n return {\n candidate,\n evaluation: evidence.evaluation,\n ...(evidence.lifecycle === null\n ? {}\n : { lifecycle: evidence.lifecycle as RunRagKnowledgeImprovementLoopResult }),\n finalEvaluated: shouldRunEvaluationStage(options),\n }\n }\n\n clearCandidateMeasurement(candidate)\n let lifecycle: RunRagKnowledgeImprovementLoopResult | undefined\n if (candidate.status === 'running') {\n lifecycle = await runCandidateUpdateLifecycle(runId, candidate, candidateRoot, options, now)\n }\n return withFrozenCandidateWorkspace(\n runDir,\n candidate,\n candidateRoot,\n async (snapshot) => {\n const development = await evaluateCandidate(\n runDir,\n state,\n candidate,\n snapshot,\n lifecycle,\n options,\n now,\n false,\n )\n if (!development.evaluation.passed || !shouldRunEvaluationStage(options)) {\n return {\n ...development,\n ...(lifecycle ? { lifecycle } : {}),\n finalEvaluated: false,\n }\n }\n\n candidate.finalEvaluationStartedAt = now().toISOString()\n candidate.updatedAt = candidate.finalEvaluationStartedAt\n state.updatedAt = candidate.finalEvaluationStartedAt\n await saveState(runDir, state, options.onState)\n await appendLedger(runDir, {\n type: 'candidate.final-evaluation-started',\n runId: state.runId,\n candidateId: candidate.candidateId,\n })\n lifecycle = await runCandidateEvaluationLifecycle(\n runId,\n runDir,\n candidate,\n snapshot.root,\n snapshot.hash,\n lifecycle,\n options,\n now,\n )\n const measured = await evaluateCandidate(\n runDir,\n state,\n candidate,\n snapshot,\n lifecycle,\n options,\n now,\n true,\n )\n return {\n ...measured,\n ...(lifecycle ? { lifecycle } : {}),\n finalEvaluated: true,\n }\n },\n options.stateScope,\n )\n })\n}\n\nasync function runCandidateUpdateLifecycle(\n runId: string,\n candidate: KnowledgeImprovementCandidateRecord,\n candidateRoot: string,\n options: KnowledgeImprovementOptions,\n now: () => Date,\n): Promise<RunRagKnowledgeImprovementLoopResult | undefined> {\n if (!shouldRunUpdateStage(options)) return undefined\n const lifecycle = await runRagKnowledgeImprovementLoop({\n goal: options.goal,\n diagnose: options.diagnose,\n acquireKnowledge: options.acquireKnowledge,\n knowledgeResearch: candidateKnowledgeResearchOptions(candidateRoot, options),\n updateKnowledge: candidateUpdateHook(runId, candidate, candidateRoot, options),\n enabledPhases: selectedStagePhases(options, UPDATE_PHASES),\n requiredPhases: selectedStageRequiredPhases(options, UPDATE_PHASES),\n signal: options.signal,\n now,\n })\n return lifecycle\n}\n\nasync function runCandidateEvaluationLifecycle(\n runId: string,\n runDir: string,\n candidate: KnowledgeImprovementCandidateRecord,\n candidateRoot: string,\n candidateHash: string,\n lifecycle: RunRagKnowledgeImprovementLoopResult | undefined,\n options: KnowledgeImprovementOptions,\n now: () => Date,\n): Promise<RunRagKnowledgeImprovementLoopResult | undefined> {\n if (!shouldRunEvaluationStage(options)) return undefined\n const candidateIndex = await buildKnowledgeIndex(candidateRoot, options.stateScope)\n return withBaselineSnapshot(\n runDir,\n candidate.baseHash,\n (baselineRoot) =>\n runRagKnowledgeImprovementPhases(\n {\n goal: options.goal,\n optimization: options.ragOptimization\n ? {\n ...options.ragOptimization,\n executionRef: candidateExecutionRef(\n options.ragOptimization.executionRef,\n candidateHash,\n ),\n runDir:\n options.ragOptimization.runDir ??\n join(runDir, 'rag-optimization', candidate.candidateId),\n run: (input) =>\n options.ragOptimization!.run({\n ...input,\n runId,\n iteration: candidate.iteration,\n candidateId: candidate.candidateId,\n root: candidateRoot,\n baselineRoot,\n candidateRoot,\n candidateIndex,\n baseHash: candidate.baseHash,\n }),\n }\n : undefined,\n retrieval: options.retrieval\n ? {\n ...options.retrieval,\n executionRef: candidateExecutionRef(options.retrieval.executionRef, candidateHash),\n index: candidateIndex,\n runDir:\n options.retrieval.runDir ?? join(runDir, 'retrieval', candidate.candidateId),\n }\n : undefined,\n evaluateAnswers: options.evaluateAnswers,\n answerQualityCostCeiling: options.answerQualityCostCeiling,\n decidePromotion: options.decidePromotion,\n enabledPhases: selectedStagePhases(options, EVALUATION_PHASES),\n requiredPhases: selectedStageRequiredPhases(options, EVALUATION_PHASES),\n signal: options.signal,\n now,\n },\n lifecycle,\n ),\n options.stateScope,\n )\n}\n\nfunction candidateExecutionRef(executionRef: string, candidateHash: string): string {\n return `sha256:${sha256(`${executionRef}\\n${candidateHash}`)}`\n}\n\nfunction candidateKnowledgeResearchOptions(\n candidateRoot: string,\n options: KnowledgeImprovementOptions,\n): RagKnowledgeResearchOptions | undefined {\n if (!options.step && !options.knowledgeResearch) return undefined\n const { step: researchStep, ...rest } = options.knowledgeResearch ?? {}\n const step = options.step ?? researchStep\n return {\n ...rest,\n root: candidateRoot,\n pagesDirectory: normalizeKnowledgeStateScope(options.stateScope).pagesDirectory,\n step,\n maxIterations:\n rest.maxIterations ?? (step ? (options.candidateResearchIterations ?? 3) : undefined),\n strict: rest.strict ?? options.strict,\n readinessSpecs: rest.readinessSpecs ?? options.readinessSpecs,\n readinessTaskId: rest.readinessTaskId ?? options.readinessTaskId,\n readiness: rest.readiness ?? options.readiness,\n }\n}\n\nfunction candidateUpdateHook(\n runId: string,\n candidate: KnowledgeImprovementCandidateRecord,\n candidateRoot: string,\n options: KnowledgeImprovementOptions,\n): RunRagKnowledgeImprovementLoopOptions['updateKnowledge'] {\n if (!options.updateKnowledge) return undefined\n return (input) =>\n options.updateKnowledge!({\n ...input,\n runId,\n iteration: candidate.iteration,\n candidateId: candidate.candidateId,\n root: candidateRoot,\n baselineRoot: options.root,\n candidateRoot,\n baseHash: candidate.baseHash,\n })\n}\n\nfunction shouldRunUpdateStage(options: KnowledgeImprovementOptions): boolean {\n const phases = selectedStagePhases(options, UPDATE_PHASES)\n if (phases.length === 0) return false\n return Boolean(\n (phases.includes('gap-diagnosis') && options.diagnose) ||\n (phases.includes('knowledge-acquisition') && options.acquireKnowledge) ||\n (phases.includes('knowledge-update') &&\n (options.step || options.knowledgeResearch || options.updateKnowledge)) ||\n selectedStageRequiredPhases(options, UPDATE_PHASES).length > 0,\n )\n}\n\nfunction shouldRunEvaluationStage(options: KnowledgeImprovementOptions): boolean {\n const phases = selectedStagePhases(options, EVALUATION_PHASES)\n if (phases.length === 0) return false\n return Boolean(\n (phases.includes('rag-optimization') && options.ragOptimization) ||\n (phases.includes('retrieval-tuning') && options.retrieval) ||\n (phases.includes('answer-quality') && options.evaluateAnswers) ||\n (phases.includes('promotion') && options.decidePromotion) ||\n options.evaluate ||\n selectedStageRequiredPhases(options, EVALUATION_PHASES).length > 0,\n )\n}\n\nfunction selectedStagePhases(\n options: Pick<KnowledgeImprovementOptions, 'enabledPhases'>,\n stagePhases: readonly RagKnowledgeImprovementPhase[],\n): RagKnowledgeImprovementPhase[] {\n const requested = options.enabledPhases ?? stagePhases\n return requested.filter((phase) => stagePhases.includes(phase))\n}\n\nfunction selectedStageRequiredPhases(\n options: Pick<KnowledgeImprovementOptions, 'requiredPhases'>,\n stagePhases: readonly RagKnowledgeImprovementPhase[],\n): RagKnowledgeImprovementPhase[] {\n return (options.requiredPhases ?? []).filter((phase) => stagePhases.includes(phase))\n}\n\nasync function evaluateCandidate(\n runDir: string,\n state: KnowledgeImprovementRunState,\n candidate: KnowledgeImprovementCandidateRecord,\n snapshot: { root: string; hash: string },\n lifecycle: RunRagKnowledgeImprovementLoopResult | undefined,\n options: KnowledgeImprovementOptions,\n now: () => Date,\n useConfiguredEvaluator: boolean,\n): Promise<{\n candidate: KnowledgeImprovementCandidateRecord\n evaluation: KnowledgeImprovementMetric\n}> {\n return withBaselineSnapshot(\n runDir,\n state.baseHash,\n async (baselineRoot) => {\n const [baselineIndex, candidateIndex] = await Promise.all([\n buildKnowledgeIndex(baselineRoot, options.stateScope),\n buildKnowledgeIndex(snapshot.root, options.stateScope),\n ])\n const validation = validateKnowledgeIndex(candidateIndex, { strict: options.strict })\n const readiness = readinessFor(options, candidateIndex)\n const kbQuality = scoreKnowledgeBaseIndex(candidateIndex, {\n strict: options.strict,\n ...options.kbQuality,\n })\n const candidateHash = snapshot.hash\n const evaluator = useConfiguredEvaluator ? options.evaluate : options.evaluateDevelopment\n const configuredMetric = evaluator\n ? evaluator({\n runId: state.runId,\n iteration: candidate.iteration,\n root: options.root,\n baselineRoot,\n candidateRoot: snapshot.root,\n baselineIndex,\n candidateIndex,\n baseHash: state.baseHash,\n candidateHash,\n validation,\n readiness,\n kbQuality,\n lifecycle,\n signal: options.signal,\n })\n : undefined\n const metric =\n configuredMetric ??\n defaultKnowledgeImprovementMetric(\n validation,\n readiness,\n options.readinessSpecs,\n kbQuality,\n lifecycle,\n )\n const evaluation = applyLifecycleFailures(\n normalizeMetric(await metric),\n lifecycle,\n options.answerQualityCostCeiling,\n )\n const measuredHash = await hashKnowledgeBase(snapshot.root, options.stateScope)\n if (measuredHash !== candidateHash) {\n throw new Error(\n `knowledge candidate changed during evaluation: expected ${candidateHash}, got ${measuredHash}`,\n )\n }\n candidate.candidateHash = candidateHash\n candidate.promotionPlanHash = knowledgeFileTransactionPlanHash(\n await knowledgeFilePlanEntries(baselineRoot, snapshot.root, options.stateScope),\n normalizeKnowledgeStateScope(options.stateScope).pagesDirectory,\n options.stateScope?.researchState,\n )\n const evidence = KnowledgeImprovementEvidenceSchema.parse(\n JSON.parse(\n JSON.stringify({\n kind: 'knowledge-improvement-evidence',\n runId: state.runId,\n candidateId: candidate.candidateId,\n iteration: candidate.iteration,\n goalHash: sha256(state.goal),\n implementationRef: state.implementationRef,\n baseHash: candidate.baseHash,\n candidateHash,\n promotionPlanHash: candidate.promotionPlanHash,\n validation,\n readiness: readiness ?? null,\n kbQuality,\n evaluation,\n lifecycle: lifecycle ?? null,\n }),\n ),\n )\n candidate.evidenceHash = contentHash(evidence)\n candidate.updatedAt = now().toISOString()\n await writeJsonDurableWithinRoot(\n runDir,\n candidateEvidenceRelativePath(candidate.candidateId),\n evidence,\n )\n await appendLedger(runDir, {\n type: 'candidate.evaluated',\n runId: state.runId,\n candidateId: candidate.candidateId,\n score: evaluation.score,\n passed: evaluation.passed,\n })\n return { candidate, evaluation }\n },\n options.stateScope,\n )\n}\n\nfunction defaultKnowledgeImprovementMetric(\n validation: ValidateKnowledgeResult,\n readiness: EvalKnowledgeBundleBuildResult | undefined,\n readinessSpecs: readonly KnowledgeReadinessSpec[] | undefined,\n kbQuality: KnowledgeBaseQualityReport,\n lifecycle: RunRagKnowledgeImprovementLoopResult | undefined,\n): KnowledgeImprovementMetric {\n const blockingMissing = readiness?.report.blockingMissingRequirements.length ?? 0\n const blockingTotal = readinessSpecs?.filter((spec) => spec.importance === 'blocking').length ?? 0\n const dimensions: Record<string, number> = {\n validation: validation.ok ? 1 : 0,\n kb_quality: kbQuality.ok ? 1 : 0,\n ...(blockingTotal > 0\n ? { blocking_readiness: Math.max(0, blockingTotal - blockingMissing) / blockingTotal }\n : {}),\n ...(lifecycle?.answerQuality\n ? { answer_quality: mean(Object.values(lifecycle.answerQuality.metrics)) }\n : {}),\n ...(lifecycle?.promotion ? { promotion_decision: lifecycle.promotion.promoted ? 1 : 0 } : {}),\n }\n const failedReasons = [\n validation.ok ? undefined : 'candidate validation failed',\n kbQuality.ok ? undefined : 'candidate KB quality check failed',\n blockingMissing === 0\n ? undefined\n : `${blockingMissing}/${blockingTotal} blocking knowledge requirements still missing`,\n ].filter((reason): reason is string => Boolean(reason))\n return {\n score: mean(Object.values(dimensions)),\n passed: failedReasons.length === 0,\n dimensions,\n notes: [\n failedReasons.length === 0 ? 'candidate passed configured checks' : failedReasons.join('; '),\n !lifecycle?.answerQuality && !lifecycle?.optimization && !lifecycle?.retrieval\n ? 'structural checks only; no task outcome evaluation was performed'\n : undefined,\n ]\n .filter((note): note is string => note !== undefined)\n .join('; '),\n provenance: {\n evaluator: '@tangle-network/agent-knowledge/default-knowledge-improvement-metric',\n version: '2',\n method: 'deterministic',\n },\n }\n}\n\nfunction applyLifecycleFailures(\n metric: KnowledgeImprovementMetric,\n lifecycle: RunRagKnowledgeImprovementLoopResult | undefined,\n answerQualityCostCeiling: number | undefined,\n): KnowledgeImprovementMetric {\n const answerQualityFailures = lifecycle?.answerQuality\n ? ragAnswerEvidenceRejectionReasons(lifecycle.answerQuality, answerQualityCostCeiling)\n : []\n const reasons = [\n metric.notes,\n ...answerQualityFailures,\n lifecycle?.promotion && !lifecycle.promotion.promoted\n ? `promotion decision held: ${lifecycle.promotion.reason}`\n : undefined,\n ].filter((reason): reason is string => Boolean(reason))\n const forcedFailure =\n answerQualityFailures.length > 0 ||\n Boolean(lifecycle?.promotion && !lifecycle.promotion.promoted)\n return {\n ...metric,\n passed: metric.passed && !forcedFailure,\n notes: reasons.length > 0 ? reasons.join('; ') : metric.notes,\n }\n}\n\nfunction normalizeMetric(metric: KnowledgeImprovementMetric): KnowledgeImprovementMetric {\n return improvementMetricSchema.parse(metric)\n}\n","import { canonicalJson } from '@tangle-network/agent-eval'\nimport { isMissingFile } from '../durable-fs'\nimport { normalizeKnowledgeStateScope } from '../knowledge-state-scope'\nimport { withKnowledgeMutation } from '../mutation-lock'\nimport type { RunRagKnowledgeImprovementLoopResult } from '../rag-improvement-loop'\nimport type {\n KnowledgeImprovementCandidateRecord,\n KnowledgeImprovementMetric,\n KnowledgeImprovementOptions,\n KnowledgeImprovementResult,\n} from './contracts'\nimport { DEFAULT_LEASE_TTL_MS, runIdSchema } from './contracts'\nimport { assertKnowledgeImprovementOptions, measureCandidate } from './evaluation'\nimport {\n acquireRunLease,\n appendLedger,\n assertExactCandidatePlatform,\n blockRun,\n findActiveCandidate,\n knowledgeImprovementRunId,\n loadKnowledgeImprovementStateFromRun,\n saveState,\n withKnowledgeImprovementRun,\n} from './state'\nimport {\n assertCandidateEvidence,\n candidateRefFor,\n createBaselineSnapshot,\n createCandidateWorkspace,\n ensureBaselineSnapshot,\n hashKnowledgeBase,\n withBaselineSnapshot,\n} from './workspace'\n\nexport async function improveKnowledgeBase(\n options: KnowledgeImprovementOptions,\n): Promise<KnowledgeImprovementResult> {\n assertExactCandidatePlatform()\n options = {\n ...options,\n ...(options.stateScope === undefined\n ? {}\n : { stateScope: Object.freeze(normalizeKnowledgeStateScope(options.stateScope)) }),\n }\n assertKnowledgeImprovementOptions(options)\n const now = options.now ?? (() => new Date())\n const runId = runIdSchema.parse(\n options.runId ?? knowledgeImprovementRunId(options.root, options.goal),\n )\n return withKnowledgeImprovementRun(options.root, runId, true, (runDir) =>\n improveKnowledgeBaseInRun(options, runId, runDir, now),\n )\n}\n\nasync function improveKnowledgeBaseInRun(\n options: KnowledgeImprovementOptions,\n runId: string,\n runDir: string,\n now: () => Date,\n): Promise<KnowledgeImprovementResult> {\n const lease = await acquireRunLease(runDir, {\n ownerId: options.ownerId ?? `pid-${process.pid}`,\n ttlMs: options.leaseTtlMs ?? DEFAULT_LEASE_TTL_MS,\n })\n\n try {\n lease.assertOwned()\n let state =\n options.resume === false\n ? null\n : await loadKnowledgeImprovementStateFromRun(options.root, runId, runDir).catch((error) => {\n if (isMissingFile(error)) return null\n throw error\n })\n if (!state) {\n const baseHash = await hashKnowledgeBase(options.root, options.stateScope)\n await createBaselineSnapshot(runDir, options.root, baseHash, options.stateScope)\n state = {\n runId,\n root: options.root,\n goal: options.goal,\n implementationRef: options.implementationRef,\n ...(options.stateScope === undefined\n ? {}\n : { stateScope: normalizeKnowledgeStateScope(options.stateScope) }),\n status: 'running',\n baseHash,\n createdAt: now().toISOString(),\n updatedAt: now().toISOString(),\n ownerId: lease.ownerId,\n candidates: [],\n }\n await saveState(runDir, state, options.onState)\n await appendLedger(runDir, { type: 'run.created', runId, baseHash })\n }\n if (\n canonicalJson(normalizeKnowledgeStateScope(state.stateScope)) !==\n canonicalJson(normalizeKnowledgeStateScope(options.stateScope))\n ) {\n throw new Error('knowledge improvement state does not match the requested stateScope')\n }\n if (state.goal !== options.goal) {\n throw new Error('knowledge improvement state does not match the requested goal')\n }\n if (state.implementationRef !== options.implementationRef) {\n throw new Error('knowledge improvement state does not match the requested implementationRef')\n }\n const promotedCandidateId = state.promotedCandidateId\n const promotedCandidate =\n state.status === 'promoted'\n ? state.candidates.find((candidate) => candidate.candidateId === promotedCandidateId)\n : undefined\n if (state.status === 'promoted' && !promotedCandidate) {\n throw new Error('promoted knowledge state has no promoted candidate')\n }\n if (state.status === 'promoted') {\n const promoted = promotedCandidate!\n const promotedState = state\n return withKnowledgeMutation(options.root, async () => {\n const currentHash = await hashKnowledgeBase(options.root, options.stateScope)\n if (currentHash !== promoted.candidateHash) {\n throw new Error(\n `promoted knowledge base changed: expected ${promoted.candidateHash}, got ${currentHash}`,\n )\n }\n const evidence = await assertCandidateEvidence(\n runDir,\n candidateRefFor(runId, promotedState, promoted),\n promotedState.implementationRef,\n )\n return {\n runId,\n state: promotedState,\n candidate: promoted,\n evaluation: evidence.evaluation,\n promoted: true,\n blocked: false,\n }\n })\n }\n await withKnowledgeMutation(options.root, () => undefined)\n await ensureBaselineSnapshot(runDir, options.root, state.baseHash, state.stateScope)\n\n if (state.status === 'blocked') {\n return { runId, state, promoted: false, blocked: true }\n }\n\n const maxCandidates = Math.max(1, options.maxCandidates ?? 1)\n let candidate = findActiveCandidate(state)\n let lastRejectedCandidate: KnowledgeImprovementCandidateRecord | undefined\n let lastRejectedEvaluation: KnowledgeImprovementMetric | undefined\n let lifecycle: RunRagKnowledgeImprovementLoopResult | undefined\n\n while (candidate || state.candidates.length < maxCandidates) {\n if (candidate?.status === 'running' && candidate.finalEvaluationStartedAt) {\n state = await blockRun(\n runDir,\n state,\n `candidate '${candidate.candidateId}' was interrupted after final evaluation started; refusing to reuse final cases`,\n options.onState,\n now,\n )\n return {\n runId,\n state,\n candidate,\n promoted: false,\n blocked: true,\n }\n }\n if (!candidate) {\n const currentHash = await hashKnowledgeBase(options.root, options.stateScope)\n if (currentHash !== state.baseHash) {\n state = await blockRun(\n runDir,\n state,\n `base changed before candidate creation: expected ${state.baseHash}, got ${currentHash}`,\n options.onState,\n now,\n )\n return { runId, state, promoted: false, blocked: true }\n }\n const activeState = state\n candidate = await withBaselineSnapshot(\n runDir,\n activeState.baseHash,\n (baselineRoot) => createCandidateWorkspace(runDir, activeState, baselineRoot, now),\n state.stateScope,\n )\n state.candidates.push(candidate)\n state.status = 'running'\n state.updatedAt = now().toISOString()\n await saveState(runDir, state, options.onState)\n await appendLedger(runDir, {\n type: 'candidate.created',\n runId,\n candidateId: candidate.candidateId,\n iteration: candidate.iteration,\n })\n }\n\n const measured = await measureCandidate(runId, runDir, state, candidate, options, now)\n candidate = measured.candidate\n const evaluation = measured.evaluation\n lifecycle = measured.lifecycle\n\n if (evaluation.passed) {\n candidate.status = 'candidate-ready'\n candidate.updatedAt = now().toISOString()\n state.status = 'candidate-ready'\n state.updatedAt = now().toISOString()\n await saveState(runDir, state, options.onState)\n await appendLedger(runDir, {\n type: 'candidate.ready',\n runId,\n candidateId: candidate.candidateId,\n })\n break\n }\n\n candidate.status = 'rejected'\n state.status = 'running'\n state.updatedAt = now().toISOString()\n await saveState(runDir, state, options.onState)\n await appendLedger(runDir, {\n type: 'candidate.rejected',\n runId,\n candidateId: candidate.candidateId,\n })\n lastRejectedCandidate = candidate\n lastRejectedEvaluation = evaluation\n candidate = undefined\n if (measured.finalEvaluated) break\n }\n\n if (!candidate) {\n state.status = 'rejected'\n state.updatedAt = now().toISOString()\n await saveState(runDir, state, options.onState)\n return {\n runId,\n state,\n candidate: lastRejectedCandidate,\n ...(lastRejectedEvaluation ? { evaluation: lastRejectedEvaluation } : {}),\n lifecycle,\n promoted: false,\n blocked: false,\n }\n }\n\n const evidence = await assertCandidateEvidence(\n runDir,\n candidateRefFor(runId, state, candidate),\n state.implementationRef,\n )\n return {\n runId,\n state,\n candidate,\n evaluation: evidence.evaluation,\n lifecycle,\n promoted: false,\n blocked: false,\n }\n } finally {\n await lease.release()\n }\n}\n","import type {\n DispatchContext,\n OptimizationMethod,\n Scenario,\n} from '@tangle-network/agent-eval/campaign'\nimport type { AgentCandidateJsonValue as JsonValue } from '@tangle-network/agent-interface'\nimport { sha256, stableId } from '../ids'\nimport { assertImmutableRef } from '../immutable-ref'\nimport {\n type RunSerializedKnowledgeOptimizationOptions,\n type RunSerializedKnowledgeOptimizationResult,\n runSerializedKnowledgeOptimization,\n} from '../optimization'\nimport type {\n KnowledgeImprovementOptions,\n KnowledgeImprovementResult,\n KnowledgeImprovementUpdateInput,\n} from './contracts'\nimport { improveKnowledgeBase } from './run'\nimport { hashKnowledgeBase } from './workspace'\n\ntype PolicyCandidateOptions = Omit<\n KnowledgeImprovementOptions,\n | 'root'\n | 'goal'\n | 'implementationRef'\n | 'runId'\n | 'maxCandidates'\n | 'step'\n | 'knowledgeResearch'\n | 'updateKnowledge'\n>\n\ntype PolicyOptimizationBaseOptions<\n TPolicy extends JsonValue,\n TScenario extends Scenario,\n TArtifact,\n> = Omit<\n RunSerializedKnowledgeOptimizationOptions<TPolicy, TScenario, TArtifact>,\n | 'baseline'\n | 'method'\n | 'trainScenarios'\n | 'selectionScenarios'\n | 'finalScenarios'\n | 'executionRef'\n>\n\nexport interface OptimizeKnowledgeBasePolicyOptions<\n TPolicy extends JsonValue,\n TScenario extends Scenario,\n TArtifact,\n> extends PolicyOptimizationBaseOptions<TPolicy, TScenario, TArtifact> {\n root: string\n goal: string\n baselinePolicy: TPolicy\n method: OptimizationMethod<TScenario, TArtifact>\n trainScenarios: readonly TScenario[]\n selectionScenarios: readonly TScenario[]\n finalScenarios: readonly TScenario[]\n /** Commit or content identity for evaluation, applyPolicy, and external dependencies. */\n policyApplicationRef: string\n /** Optional namespace for parallel materialization of the same measured policy. */\n candidateRunLabel?: string\n candidate?: PolicyCandidateOptions\n applyPolicy(\n input: KnowledgeImprovementUpdateInput & {\n policy: TPolicy\n policySurface: string\n policySurfaceHash: string\n optimizationMethod: string\n },\n ): Promise<{\n applied: boolean\n summary: string\n metadata?: Record<string, JsonValue>\n }>\n}\n\nexport interface OptimizeKnowledgeBasePolicyResult<TPolicy extends JsonValue> {\n optimization: RunSerializedKnowledgeOptimizationResult<TPolicy>\n improvement: KnowledgeImprovementResult\n}\n\n/**\n * Optimizes a serialized KB-maintenance policy, then materializes the selected\n * policy in one isolated knowledge candidate. Activation remains explicit.\n */\nexport async function optimizeKnowledgeBasePolicy<\n TPolicy extends JsonValue,\n TScenario extends Scenario,\n TArtifact,\n>(\n options: OptimizeKnowledgeBasePolicyOptions<TPolicy, TScenario, TArtifact>,\n): Promise<OptimizeKnowledgeBasePolicyResult<TPolicy>> {\n const {\n root,\n goal,\n baselinePolicy,\n method,\n trainScenarios,\n selectionScenarios,\n finalScenarios,\n policyApplicationRef,\n candidateRunLabel,\n candidate,\n applyPolicy,\n ...optimizationOptions\n } = options\n if (typeof root !== 'string' || !root.trim()) {\n throw new Error('optimizeKnowledgeBasePolicy root must be non-empty')\n }\n if (typeof goal !== 'string' || !goal.trim()) {\n throw new Error('optimizeKnowledgeBasePolicy goal must be non-empty')\n }\n assertImmutableRef(policyApplicationRef, 'optimizeKnowledgeBasePolicy policyApplicationRef')\n if (\n candidateRunLabel !== undefined &&\n (typeof candidateRunLabel !== 'string' || !candidateRunLabel.trim())\n ) {\n throw new Error('optimizeKnowledgeBasePolicy candidateRunLabel must be non-empty')\n }\n const baseHash = await hashKnowledgeBase(root, candidate?.stateScope)\n const optimization = await runSerializedKnowledgeOptimization({\n ...optimizationOptions,\n executionRef: policyApplicationRef,\n baseline: baselinePolicy,\n method,\n trainScenarios,\n selectionScenarios,\n finalScenarios,\n })\n const winner = optimization.winner\n const currentBaseHash = await hashKnowledgeBase(root, candidate?.stateScope)\n if (currentBaseHash !== baseHash) {\n throw new Error(\n `knowledge base changed during policy optimization: expected ${baseHash}, got ${currentBaseHash}`,\n )\n }\n const runId = stableId(\n 'kbpolicy',\n `${candidateRunLabel ?? 'default'}:${goal}:${optimization.methodName}:${winner.surfaceHash}:${policyApplicationRef}:${baseHash}`,\n )\n const improvement = await improveKnowledgeBase({\n ...(candidate ?? {}),\n root,\n goal,\n implementationRef: `sha256:${sha256(\n `${policyApplicationRef}\\n${winner.surfaceHash}\\n${optimization.methodName}`,\n )}`,\n runId,\n maxCandidates: 1,\n updateKnowledge: async (input) => {\n if (input.baseHash !== baseHash) {\n throw new Error(\n `knowledge base changed before policy materialization: expected ${baseHash}, got ${input.baseHash}`,\n )\n }\n const result = await applyPolicy({\n ...input,\n policy: structuredClone(winner.value),\n policySurface: winner.surface,\n policySurfaceHash: winner.surfaceHash,\n optimizationMethod: optimization.methodName,\n })\n return {\n ...result,\n metadata: {\n ...(result.metadata ?? {}),\n optimization: {\n method: optimization.methodName,\n policySurfaceHash: winner.surfaceHash,\n policyApplicationRef,\n },\n },\n }\n },\n })\n return { optimization, improvement }\n}\n\nexport type KnowledgePolicyDispatch<\n TPolicy extends JsonValue,\n TScenario extends Scenario,\n TArtifact,\n> = (input: {\n candidate: TPolicy\n candidateSurface: string\n candidateSurfaceHash: string\n scenario: TScenario\n context: DispatchContext\n}) => Promise<TArtifact>\n","import { createHash } from 'node:crypto'\nimport { join } from 'node:path'\nimport { canonicalJson, contentHash } from '@tangle-network/agent-eval'\nimport type { AgentCandidateJsonValue as JsonValue } from '@tangle-network/agent-interface'\nimport { z } from 'zod'\nimport { isMissingFile, readRegularFileWithinRoot, writeJsonDurableWithinRoot } from '../durable-fs'\nimport {\n applyKnowledgeFileTransaction,\n assertKnowledgeMutationPath,\n finishKnowledgeFileTransaction,\n type KnowledgeFileMutation,\n type KnowledgeFileTransaction,\n type KnowledgeFileTransactionPlanEntry,\n knowledgeFileTransactionPlanHash,\n prepareKnowledgeFileTransaction,\n} from '../file-transaction'\nimport { stableId } from '../ids'\nimport { writeKnowledgeIndex } from '../indexer'\nimport { type KnowledgeStateScope, normalizeKnowledgeStateScope } from '../knowledge-state-scope'\nimport { withKnowledgeMutation } from '../mutation-lock'\nimport { normalizePagesDirectory } from '../pages-directory'\nimport type { RagKnowledgeImprovementPhase } from '../rag-improvement-loop'\nimport type {\n KnowledgeImprovementCandidateRef,\n KnowledgeImprovementOptions,\n KnowledgeImprovementResult,\n} from './contracts'\nimport {\n EVALUATION_PHASES,\n immutableRefSchema,\n KB_IMPROVEMENT_PAGES_DIRECTORY,\n KnowledgeImprovementCandidateRefSchema,\n safePathSegmentSchema,\n} from './contracts'\nimport { improveKnowledgeBase } from './run'\nimport { knowledgeImprovementRunDir } from './state'\nimport { knowledgeFilePlanEntries } from './transition'\nimport { hashKnowledgeBase, withKnowledgeImprovementComparison } from './workspace'\n\nconst selectionPathSchema = z\n .string()\n .min(1)\n .transform((path, context) => {\n try {\n try {\n return assertKnowledgeMutationPath(path, KB_IMPROVEMENT_PAGES_DIRECTORY, true)\n } catch {\n return normalizePagesDirectory(path)\n }\n } catch (error) {\n context.addIssue({\n code: 'custom',\n message: error instanceof Error ? error.message : String(error),\n })\n return z.NEVER\n }\n })\nconst selectionMetadataSchema = z.record(z.string(), z.json())\nconst measuredSelectionLifecycleSchema = z\n .object({\n kind: z.literal('measured-knowledge-change-selection'),\n version: z.literal(1),\n selectionDigest: z.string().regex(/^[a-f0-9]{64}$/),\n sourceCandidateId: z.string().min(1),\n sourceEvidenceHash: z.string().regex(/^[a-f0-9]{64}$/),\n sourcePlanHash: z.string().regex(/^[a-f0-9]{64}$/),\n selectedPaths: z.array(selectionPathSchema),\n selectedCandidateHash: z.string().regex(/^[a-f0-9]{64}$/),\n selectedPlanHash: z.string().regex(/^[a-f0-9]{64}$/),\n })\n .strict()\nconst measuredSelectionReceiptSchema = z\n .object({\n kind: z.literal('measured-knowledge-change-selection-receipt'),\n version: z.literal(1),\n receiptHash: z.string().regex(/^[a-f0-9]{64}$/),\n selectionDigest: z.string().regex(/^[a-f0-9]{64}$/),\n sourceCandidate: KnowledgeImprovementCandidateRefSchema,\n sourcePlanHash: z.string().regex(/^[a-f0-9]{64}$/),\n selectedPaths: z.array(selectionPathSchema),\n derivedImplementationRef: immutableRefSchema,\n runId: z.string().min(1),\n derivedCandidateId: z.string().min(1),\n derivedCandidateStatus: z.string().min(1),\n selectedCandidateHash: z.string().regex(/^[a-f0-9]{64}$/),\n selectedPlanHash: z.string().regex(/^[a-f0-9]{64}$/),\n selectedEvidenceHash: z.string().regex(/^[a-f0-9]{64}$/),\n rationale: z.string().trim().min(1).optional(),\n metadata: selectionMetadataSchema.optional(),\n })\n .strict()\n\nexport type KnowledgeEvaluationPhase = Exclude<\n RagKnowledgeImprovementPhase,\n 'knowledge-acquisition' | 'knowledge-update'\n>\n\nexport interface ImproveSelectedKnowledgeCandidateOptions\n extends Omit<\n KnowledgeImprovementOptions,\n | 'root'\n | 'goal'\n | 'implementationRef'\n | 'runId'\n | 'step'\n | 'knowledgeResearch'\n | 'acquireKnowledge'\n | 'updateKnowledge'\n | 'enabledPhases'\n | 'requiredPhases'\n > {\n root: string\n goal: string\n /** Identity of the helper, policy, or human procedure choosing the subset. */\n implementationRef: string\n /** Previously measured whole candidate from which the subset is derived. */\n sourceCandidate: KnowledgeImprovementCandidateRef\n /** Exact changed file paths to carry into the derived candidate. */\n selectedPaths: readonly string[]\n /** Optional explicit run identity. The default includes the selection digest. */\n runId?: string\n /** Human-readable reason for selecting this subset. */\n rationale?: string\n /** JSON-safe policy output retained in the selection receipt. */\n selectionMetadata?: Record<string, JsonValue>\n /** Diagnosis and evaluation phases. `knowledge-update` is inserted by this helper. */\n enabledEvaluationPhases?: readonly KnowledgeEvaluationPhase[]\n /** Diagnosis and evaluation phases that must complete. `knowledge-update` is always required. */\n requiredEvaluationPhases?: readonly KnowledgeEvaluationPhase[]\n}\n\nexport type MeasuredKnowledgeSelectionReceipt = z.infer<typeof measuredSelectionReceiptSchema>\n\nexport interface ImproveSelectedKnowledgeCandidateResult extends KnowledgeImprovementResult {\n selection: MeasuredKnowledgeSelectionReceipt\n}\n\n/**\n * Derive a subset from an already measured candidate, then measure the subset as\n * a new candidate before it can be promoted.\n *\n * Directly filtering an activation plan is unsafe: a whole candidate can pass\n * while one page subset breaks links, removes supporting sources, or changes a\n * readiness score. This helper instead applies the chosen changed paths to an\n * isolated baseline, recomputes the index, runs the ordinary improvement\n * evaluator, and returns the ordinary candidate reference. Promotion therefore\n * remains one path and can never admit an unmeasured hybrid.\n */\nexport async function improveSelectedKnowledgeCandidate(\n options: ImproveSelectedKnowledgeCandidateOptions,\n): Promise<ImproveSelectedKnowledgeCandidateResult> {\n const sourceCandidate = Object.freeze(\n KnowledgeImprovementCandidateRefSchema.parse(options.sourceCandidate),\n )\n const requestedImplementationRef = immutableRefSchema.parse(options.implementationRef)\n const enabledEvaluationPhases = normalizeEvaluationPhases(\n options.enabledEvaluationPhases ?? ['gap-diagnosis', ...EVALUATION_PHASES],\n 'enabledEvaluationPhases',\n )\n const requiredEvaluationPhases = normalizeEvaluationPhases(\n options.requiredEvaluationPhases ?? [],\n 'requiredEvaluationPhases',\n )\n const metadata = options.selectionMetadata\n ? selectionMetadataSchema.parse(structuredClone(options.selectionMetadata))\n : undefined\n\n return withKnowledgeImprovementComparison(\n { root: options.root, candidate: sourceCandidate },\n async (source) => {\n const scope = normalizeKnowledgeStateScope(source.stateScope)\n if (\n options.stateScope !== undefined &&\n canonicalJson(normalizeKnowledgeStateScope(options.stateScope)) !== canonicalJson(scope)\n ) {\n throw new Error('selected knowledge candidate stateScope differs from its source')\n }\n const sourcePlan = await knowledgeFilePlanEntries(\n source.baseline.root,\n source.candidate.root,\n scope,\n )\n const sourcePlanHash = knowledgeFileTransactionPlanHash(\n sourcePlan,\n scope.pagesDirectory,\n scope.researchState,\n )\n if (sourcePlanHash !== sourceCandidate.promotionPlanHash) {\n throw new Error('source knowledge candidate plan no longer matches its measured identity')\n }\n const changedSourcePlan = sourcePlan\n .filter(planEntryChanged)\n .filter((entry) => notDerivedPath(entry, scope))\n const selectedPaths = normalizeSelectedPaths(options.selectedPaths, changedSourcePlan, scope)\n const selectionMaterial = immutableJson({\n kind: 'measured-knowledge-change-selection' as const,\n version: 1 as const,\n sourceCandidate,\n sourcePlanHash,\n selectedPaths,\n ...(options.rationale?.trim() ? { rationale: options.rationale.trim() } : {}),\n ...(metadata ? { metadata } : {}),\n })\n const selectionDigest = contentHash(selectionMaterial)\n const derivedImplementationRef = immutableRefSchema.parse(\n `sha256:${contentHash({\n engine: 'agent-knowledge/measured-selection-v1',\n implementationRef: requestedImplementationRef,\n selectionDigest,\n })}`,\n )\n const runId =\n options.runId ??\n stableId(\n 'kimpsel',\n canonicalJson({\n root: options.root,\n goal: options.goal,\n derivedImplementationRef,\n selectionDigest,\n }),\n )\n const selectedEntries = selectedPaths.map((path) => {\n const entry = changedSourcePlan.find((candidate) => candidate.path === path)\n if (!entry) throw new Error(`selected knowledge path disappeared: ${path}`)\n return entry\n })\n const selectionMutationPlanHash = knowledgeFileTransactionPlanHash(\n selectedEntries,\n scope.pagesDirectory,\n scope.researchState,\n )\n let lifecycleSelection: z.infer<typeof measuredSelectionLifecycleSchema> | undefined\n\n const result = await improveKnowledgeBase({\n ...improvementOptions(options),\n root: options.root,\n stateScope: scope,\n goal: options.goal,\n implementationRef: derivedImplementationRef,\n runId,\n enabledPhases: ['knowledge-update', ...enabledEvaluationPhases],\n requiredPhases: ['knowledge-update', ...requiredEvaluationPhases],\n async updateKnowledge(input) {\n const purpose = `knowledge-selected-candidate:${selectionDigest}`\n const recoveryOwner = `knowledge-selected-candidate:${sourceCandidate.candidateId}`\n await withKnowledgeMutation(\n input.candidateRoot,\n async (lock) => {\n lock.assertOwned()\n if (!lock.recovery && selectedEntries.length > 0) {\n const transaction = await prepareKnowledgeFileTransaction({\n root: input.candidateRoot,\n transactionRoot: lock.transactionRoot,\n purpose,\n ...scope,\n recoveryOwner,\n mutations: await selectionMutations(source.candidate.root, selectedEntries),\n now: options.now,\n })\n if (transaction) {\n assertSelectionTransaction(transaction, selectionMutationPlanHash)\n await applyKnowledgeFileTransaction({\n root: input.candidateRoot,\n transactionRoot: lock.transactionRoot,\n transaction,\n beforeCommit: lock.assertOwned,\n })\n await finishKnowledgeFileTransaction({\n root: input.candidateRoot,\n transactionRoot: lock.transactionRoot,\n transaction,\n assertOwned: lock.assertOwned,\n })\n }\n }\n await writeKnowledgeIndex(input.candidateRoot, scope)\n lock.assertOwned()\n },\n {\n resumeTransaction: {\n purpose,\n recoveryOwner,\n validate: (transaction) =>\n assertSelectionTransaction(transaction, selectionMutationPlanHash),\n },\n },\n )\n\n const selectedPlan = await knowledgeFilePlanEntries(\n source.baseline.root,\n input.candidateRoot,\n scope,\n )\n assertExactSelectedChanges(selectedPlan, selectedPaths, scope)\n const selectedPlanHash = knowledgeFileTransactionPlanHash(\n selectedPlan,\n scope.pagesDirectory,\n scope.researchState,\n )\n const selectedCandidateHash = await hashKnowledgeBase(input.candidateRoot, scope)\n lifecycleSelection = measuredSelectionLifecycleSchema.parse({\n kind: 'measured-knowledge-change-selection',\n version: 1,\n selectionDigest,\n sourceCandidateId: sourceCandidate.candidateId,\n sourceEvidenceHash: sourceCandidate.evidenceHash,\n sourcePlanHash,\n selectedPaths,\n selectedCandidateHash,\n selectedPlanHash,\n })\n return {\n applied: selectedPaths.length > 0,\n summary:\n selectedPaths.length > 0\n ? `Applied ${selectedPaths.length} selected measured change(s).`\n : 'Selected no changes; measuring the exact baseline as a null candidate.',\n metadata: { selection: lifecycleSelection },\n }\n },\n })\n\n const candidate = result.candidate\n if (!candidate?.candidateHash || !candidate.promotionPlanHash || !candidate.evidenceHash) {\n throw new Error('selected knowledge candidate did not produce measured candidate evidence')\n }\n const recordedSelection = measuredSelectionLifecycleSchema.parse(\n result.lifecycle?.knowledgeUpdate?.metadata?.selection ?? lifecycleSelection,\n )\n if (\n recordedSelection.selectionDigest !== selectionDigest ||\n recordedSelection.selectedCandidateHash !== candidate.candidateHash ||\n recordedSelection.selectedPlanHash !== candidate.promotionPlanHash ||\n canonicalJson(recordedSelection.selectedPaths) !== canonicalJson(selectedPaths)\n ) {\n throw new Error('selected knowledge candidate evidence does not bind the measured subset')\n }\n\n const receiptWithoutHash = immutableJson({\n kind: 'measured-knowledge-change-selection-receipt' as const,\n version: 1 as const,\n selectionDigest,\n sourceCandidate,\n sourcePlanHash,\n selectedPaths,\n derivedImplementationRef,\n runId: result.runId,\n derivedCandidateId: candidate.candidateId,\n derivedCandidateStatus: candidate.status,\n selectedCandidateHash: candidate.candidateHash,\n selectedPlanHash: candidate.promotionPlanHash,\n selectedEvidenceHash: candidate.evidenceHash,\n ...(options.rationale?.trim() ? { rationale: options.rationale.trim() } : {}),\n ...(metadata ? { metadata } : {}),\n })\n const receipt = measuredSelectionReceiptSchema.parse({\n ...receiptWithoutHash,\n receiptHash: contentHash(receiptWithoutHash),\n })\n await persistSelectionReceipt(options.root, receipt)\n return { ...result, selection: receipt }\n },\n )\n}\n\nfunction improvementOptions(\n options: ImproveSelectedKnowledgeCandidateOptions,\n): Omit<\n KnowledgeImprovementOptions,\n | 'root'\n | 'goal'\n | 'implementationRef'\n | 'runId'\n | 'step'\n | 'knowledgeResearch'\n | 'acquireKnowledge'\n | 'updateKnowledge'\n | 'enabledPhases'\n | 'requiredPhases'\n> {\n const {\n root: _root,\n goal: _goal,\n implementationRef: _implementationRef,\n sourceCandidate: _sourceCandidate,\n selectedPaths: _selectedPaths,\n runId: _runId,\n rationale: _rationale,\n selectionMetadata: _selectionMetadata,\n enabledEvaluationPhases: _enabledEvaluationPhases,\n requiredEvaluationPhases: _requiredEvaluationPhases,\n ...rest\n } = options\n return rest\n}\n\nfunction normalizeEvaluationPhases(\n phases: readonly RagKnowledgeImprovementPhase[],\n field: string,\n): KnowledgeEvaluationPhase[] {\n const unique = [...new Set(phases)]\n for (const phase of unique) {\n if (phase === 'knowledge-acquisition' || phase === 'knowledge-update') {\n throw new Error(`${field} cannot contain the selection-owned phase '${phase}'`)\n }\n }\n return unique as KnowledgeEvaluationPhase[]\n}\n\nfunction normalizeSelectedPaths(\n paths: readonly string[],\n changedPlan: readonly KnowledgeFileTransactionPlanEntry[],\n scope: KnowledgeStateScope,\n): string[] {\n const available = new Set(changedPlan.map((entry) => entry.path))\n const selected: string[] = []\n const seen = new Set<string>()\n for (const input of paths) {\n const path = assertKnowledgeMutationPath(\n selectionPathSchema.parse(input),\n normalizeKnowledgeStateScope(scope).pagesDirectory,\n scope.researchState,\n )\n if (!notDerivedPath({ path }, scope)) {\n throw new Error(`derived knowledge path cannot be selected directly: ${path}`)\n }\n if (seen.has(path)) throw new Error(`selected knowledge path is repeated: ${path}`)\n if (!available.has(path)) {\n throw new Error(`selected knowledge path is not a changed source-candidate file: ${path}`)\n }\n seen.add(path)\n selected.push(path)\n }\n return selected.sort((left, right) => left.localeCompare(right))\n}\n\nfunction planEntryChanged(entry: KnowledgeFileTransactionPlanEntry): boolean {\n return (\n entry.beforeHash !== entry.afterHash ||\n (entry.beforeHash !== null && entry.afterHash !== null && entry.beforeMode !== entry.afterMode)\n )\n}\n\nfunction notDerivedPath(entry: { path: string }, scope: KnowledgeStateScope): boolean {\n return entry.path !== `${normalizeKnowledgeStateScope(scope).pagesDirectory}/index.md`\n}\n\nasync function selectionMutations(\n sourceCandidateRoot: string,\n entries: readonly KnowledgeFileTransactionPlanEntry[],\n): Promise<KnowledgeFileMutation[]> {\n return Promise.all(\n entries.map(async (entry) => {\n if (entry.afterHash === null) return { path: entry.path, content: null }\n const file = await readRegularFileWithinRoot(sourceCandidateRoot, entry.path)\n const actualHash = createHash('sha256').update(file.bytes).digest('hex')\n if (actualHash !== entry.afterHash || file.mode !== entry.afterMode) {\n throw new Error(`source candidate changed before subset materialization: ${entry.path}`)\n }\n return { path: entry.path, content: file.bytes, mode: file.mode }\n }),\n )\n}\n\nfunction assertSelectionTransaction(\n transaction: KnowledgeFileTransaction,\n expectedPlanHash: string,\n): void {\n if (\n knowledgeFileTransactionPlanHash(\n transaction.entries,\n normalizePagesDirectory(transaction.pagesDirectory),\n transaction.researchState,\n ) !== expectedPlanHash\n ) {\n throw new Error('selected knowledge transaction does not match its approved path set')\n }\n}\n\nfunction assertExactSelectedChanges(\n plan: readonly KnowledgeFileTransactionPlanEntry[],\n selectedPaths: readonly string[],\n scope: KnowledgeStateScope,\n): void {\n const actual = plan\n .filter(planEntryChanged)\n .filter((entry) => notDerivedPath(entry, scope))\n .map((entry) => entry.path)\n .sort((left, right) => left.localeCompare(right))\n if (canonicalJson(actual) !== canonicalJson(selectedPaths)) {\n throw new Error(\n `selected knowledge candidate changed the wrong files: expected ${selectedPaths.join(', ') || '(none)'}, got ${actual.join(', ') || '(none)'}`,\n )\n }\n}\n\nasync function persistSelectionReceipt(\n root: string,\n receipt: MeasuredKnowledgeSelectionReceipt,\n): Promise<void> {\n const runDir = knowledgeImprovementRunDir(root, receipt.runId)\n const relativePath = join(\n 'candidates',\n safePathSegmentSchema.parse(receipt.derivedCandidateId),\n 'selection.json',\n ).replace(/\\\\/g, '/')\n try {\n const existing = measuredSelectionReceiptSchema.parse(\n JSON.parse((await readRegularFileWithinRoot(runDir, relativePath)).bytes.toString('utf8')),\n )\n if (canonicalJson(existing) !== canonicalJson(receipt)) {\n throw new Error('measured knowledge selection receipt conflicts with durable content')\n }\n return\n } catch (error) {\n if (!isMissingFile(error)) throw error\n }\n await writeJsonDurableWithinRoot(runDir, relativePath, receipt)\n}\n\nfunction immutableJson<T>(value: T): T {\n if (value === null || typeof value !== 'object') return value\n const children: readonly unknown[] = Array.isArray(value)\n ? value\n : Object.values(value as Record<string, unknown>)\n for (const child of children) immutableJson(child)\n return Object.freeze(value)\n}\n","import {\n type AgentCandidateKnowledgeRef,\n sha256DigestSchema,\n} from '@tangle-network/agent-interface'\n\nimport {\n type KnowledgeImprovementCandidateRef,\n KnowledgeImprovementCandidateRefSchema,\n} from './kb-improvement'\n\n/** Convert a measured knowledge candidate into the shared review and execution identity. */\nexport function toAgentCandidateKnowledgeRef(\n candidate: KnowledgeImprovementCandidateRef,\n): AgentCandidateKnowledgeRef {\n const parsed = KnowledgeImprovementCandidateRefSchema.parse(candidate)\n return {\n ...parsed,\n goalHash: prefixedDigest(parsed.goalHash),\n baseHash: prefixedDigest(parsed.baseHash),\n candidateHash: prefixedDigest(parsed.candidateHash),\n evidenceHash: prefixedDigest(parsed.evidenceHash),\n promotionPlanHash: prefixedDigest(parsed.promotionPlanHash),\n }\n}\n\n/** Recover agent-knowledge's candidate identity from the shared contract. */\nexport function fromAgentCandidateKnowledgeRef(\n candidate: AgentCandidateKnowledgeRef,\n): KnowledgeImprovementCandidateRef {\n return KnowledgeImprovementCandidateRefSchema.parse({\n ...candidate,\n goalHash: rawDigest(candidate.goalHash),\n baseHash: rawDigest(candidate.baseHash),\n candidateHash: rawDigest(candidate.candidateHash),\n evidenceHash: rawDigest(candidate.evidenceHash),\n promotionPlanHash: rawDigest(candidate.promotionPlanHash),\n })\n}\n\nfunction prefixedDigest(value: string) {\n return sha256DigestSchema.parse(`sha256:${value}`)\n}\n\nfunction rawDigest(value: string): string {\n return sha256DigestSchema.parse(value).slice('sha256:'.length)\n}\n","import type { KnowledgeFragment } from './sources/types'\n\n/**\n * Change detection across snapshots of one source's fragments.\n *\n * The output drives the continuous-ingestion loop: each `KnowledgeChange`\n * carries the eval dimensions affected (`affectedDimensions`), which an\n * agent-eval campaign scheduler consumes to decide which campaigns to\n * re-run. Three change kinds:\n *\n * - `added` — fragment id appears in `next` but not `prev`.\n * - `removed` — fragment id appears in `prev` but not `next`. Typical\n * trigger: an authority retires a Wex slug, or a state SOS reorganises\n * its forms catalogue.\n * - `modified` — fragment id appears in both, body hash differs. This\n * is the dominant change kind in practice — the Ryan-LLC v. FTC\n * vacatur case manifests as a `modified` on the Wex non-compete\n * fragment, NOT as a removed one.\n *\n * Unverifiable fragments are filtered out before diffing — comparing a\n * captcha-blocked snapshot against a real one would falsely fire every\n * fragment as removed. The caller can inspect the raw lists if they want\n * to surface block-page failures.\n *\n * Within-snapshot duplicate ids are an upstream bug; this function picks\n * the LAST one and emits a diagnostic via the `warnings` field.\n *\n * @stable\n */\n\nexport type KnowledgeChangeKind = 'added' | 'removed' | 'modified'\n\nexport interface KnowledgeChange {\n /** Source-scoped id (matches `KnowledgeFragment.id`). */\n fragmentId: string\n kind: KnowledgeChangeKind\n /**\n * For `added`: full body of the new fragment.\n * For `removed`: full body of the prior fragment.\n * For `modified`: unified-diff-style payload `{ before, after }` body strings.\n */\n diff?: { before?: string; after?: string }\n /**\n * Eval dimensions to re-score. Computed as the union of both fragments'\n * `dimensionHints`. The eval cron treats this as a set of campaign tags.\n */\n affectedDimensions: string[]\n /** URL of the affected authority page (from whichever side has it). */\n url?: string\n /**\n * Source-attested change time. For `modified`, takes the NEXT fragment's\n * `sourceUpdatedAt`. For `removed`, takes the PRIOR fragment's\n * `sourceUpdatedAt`. For `added`, takes the NEXT fragment's\n * `sourceUpdatedAt`. Consumers index changes by this date.\n */\n detectedAt: string\n}\n\nexport interface DetectChangesResult {\n changes: KnowledgeChange[]\n /** Counts by kind — handy for dashboards. */\n summary: { added: number; removed: number; modified: number }\n /** Non-fatal diagnostics (duplicate ids, dropped unverifiable fragments). */\n warnings: string[]\n}\n\nexport interface DetectChangesOptions {\n /**\n * When true (default), unverifiable fragments are dropped from both\n * sides before comparison. Set false ONLY when debugging block-page\n * issues — comparing against unverifiable content emits false\n * `removed`/`modified` changes.\n */\n skipUnverifiable?: boolean\n /**\n * When provided, only changes whose `affectedDimensions` intersect this\n * set are returned. Useful for cron loops that schedule per-dimension\n * eval campaigns and only care about a subset.\n */\n filterDimensions?: string[]\n}\n\nexport function detectChanges(\n prev: KnowledgeFragment[],\n next: KnowledgeFragment[],\n options: DetectChangesOptions = {},\n): DetectChangesResult {\n const skipUnverifiable = options.skipUnverifiable ?? true\n const warnings: string[] = []\n\n const { map: prevMap, warnings: prevWarn } = indexFragments(prev, skipUnverifiable, 'prev')\n const { map: nextMap, warnings: nextWarn } = indexFragments(next, skipUnverifiable, 'next')\n warnings.push(...prevWarn, ...nextWarn)\n\n const changes: KnowledgeChange[] = []\n const seen = new Set<string>()\n\n for (const [id, nextFragment] of nextMap) {\n seen.add(id)\n const prevFragment = prevMap.get(id)\n if (!prevFragment) {\n changes.push({\n fragmentId: id,\n kind: 'added',\n diff: { after: nextFragment.body },\n affectedDimensions: dedup(nextFragment.dimensionHints),\n url: nextFragment.provenance.url,\n detectedAt: nextFragment.provenance.sourceUpdatedAt,\n })\n continue\n }\n if (prevFragment.bodyHash !== nextFragment.bodyHash) {\n changes.push({\n fragmentId: id,\n kind: 'modified',\n diff: { before: prevFragment.body, after: nextFragment.body },\n affectedDimensions: dedup([...prevFragment.dimensionHints, ...nextFragment.dimensionHints]),\n url: nextFragment.provenance.url,\n detectedAt: nextFragment.provenance.sourceUpdatedAt,\n })\n }\n }\n\n for (const [id, prevFragment] of prevMap) {\n if (seen.has(id)) continue\n changes.push({\n fragmentId: id,\n kind: 'removed',\n diff: { before: prevFragment.body },\n affectedDimensions: dedup(prevFragment.dimensionHints),\n url: prevFragment.provenance.url,\n detectedAt: prevFragment.provenance.sourceUpdatedAt,\n })\n }\n\n const filtered = options.filterDimensions\n ? changes.filter((c) => c.affectedDimensions.some((d) => options.filterDimensions?.includes(d)))\n : changes\n\n return {\n changes: filtered,\n summary: {\n added: filtered.filter((c) => c.kind === 'added').length,\n removed: filtered.filter((c) => c.kind === 'removed').length,\n modified: filtered.filter((c) => c.kind === 'modified').length,\n },\n warnings,\n }\n}\n\nfunction indexFragments(\n fragments: KnowledgeFragment[],\n skipUnverifiable: boolean,\n side: string,\n): { map: Map<string, KnowledgeFragment>; warnings: string[] } {\n const map = new Map<string, KnowledgeFragment>()\n const warnings: string[] = []\n let dropped = 0\n for (const fragment of fragments) {\n if (skipUnverifiable && !fragment.provenance.verifiable) {\n dropped += 1\n continue\n }\n if (map.has(fragment.id)) {\n warnings.push(`${side}: duplicate fragment id ${fragment.id} — keeping last`)\n }\n map.set(fragment.id, fragment)\n }\n if (dropped > 0) {\n warnings.push(`${side}: dropped ${dropped} unverifiable fragment(s) before diff`)\n }\n return { map, warnings }\n}\n\nfunction dedup<T>(items: T[]): T[] {\n return [...new Set(items)]\n}\n","export interface ChunkingOptions {\n targetChars: number\n maxChars: number\n minChars: number\n overlapChars: number\n}\n\nexport interface KnowledgeChunk {\n index: number\n text: string\n headingPath: string\n charStart: number\n charEnd: number\n oversized: boolean\n}\n\nconst DEFAULT_OPTIONS: ChunkingOptions = {\n targetChars: 1000,\n maxChars: 1500,\n minChars: 160,\n overlapChars: 180,\n}\n\nexport function chunkMarkdown(\n content: string,\n options?: Partial<ChunkingOptions>,\n): KnowledgeChunk[] {\n const opts = normalizeOptions({ ...DEFAULT_OPTIONS, ...(options ?? {}) })\n const { body, bodyOffset } = stripFrontmatter(content)\n if (body.trim() === '') return []\n\n const sections = splitSections(body, bodyOffset)\n const chunks: KnowledgeChunk[] = []\n for (const section of sections) {\n for (const part of chunkText(section.text, opts)) {\n const start = section.start + part.start\n chunks.push({\n index: chunks.length,\n text: part.text,\n headingPath: section.headingPath,\n charStart: start,\n charEnd: start + part.text.length,\n oversized: part.text.length > opts.maxChars,\n })\n }\n }\n return chunks\n}\n\nexport function stripFrontmatter(content: string): { body: string; bodyOffset: number } {\n const normalized = content.replace(/\\r\\n/g, '\\n')\n if (!normalized.startsWith('---\\n')) return { body: normalized, bodyOffset: 0 }\n const match = /^---\\n[\\s\\S]*?\\n---\\s*\\n?/.exec(normalized)\n if (!match) return { body: normalized, bodyOffset: 0 }\n return { body: normalized.slice(match[0].length), bodyOffset: match[0].length }\n}\n\nfunction normalizeOptions(opts: ChunkingOptions): ChunkingOptions {\n if (opts.maxChars < opts.targetChars) opts.maxChars = opts.targetChars\n if (opts.overlapChars >= opts.targetChars) opts.overlapChars = Math.floor(opts.targetChars / 2)\n return opts\n}\n\ninterface Section {\n text: string\n start: number\n headingPath: string\n}\n\nfunction splitSections(body: string, bodyOffset: number): Section[] {\n const lines = body.split('\\n')\n const sections: Section[] = []\n const headings: Record<number, string> = {}\n let current: { lines: string[]; start: number; headingPath: string } = {\n lines: [],\n start: bodyOffset,\n headingPath: '',\n }\n let cursor = bodyOffset\n let fence: string | null = null\n\n const flush = () => {\n const text = current.lines.join('\\n')\n if (text.trim() !== '')\n sections.push({ text, start: current.start, headingPath: current.headingPath })\n }\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]!\n const lineLen = line.length + (i < lines.length - 1 ? 1 : 0)\n const fenceMatch = /^(`{3,}|~{3,})/.exec(line)\n if (fenceMatch) {\n const marker = fenceMatch[1]!\n fence = fence === null ? marker : line.startsWith(fence) ? null : fence\n current.lines.push(line)\n cursor += lineLen\n continue\n }\n const heading = fence === null ? /^(#{1,6})\\s+(.+?)\\s*$/.exec(line) : null\n if (heading) {\n flush()\n const level = heading[1]!.length\n headings[level] = heading[2]!.trim()\n for (let next = level + 1; next <= 6; next++) delete headings[next]\n current = {\n lines: [line],\n start: cursor,\n headingPath: Object.entries(headings)\n .sort(([a], [b]) => Number(a) - Number(b))\n .map(([levelText, title]) => `${'#'.repeat(Number(levelText))} ${title}`)\n .join(' > '),\n }\n cursor += lineLen\n continue\n }\n current.lines.push(line)\n cursor += lineLen\n }\n flush()\n return sections\n}\n\nfunction chunkText(text: string, opts: ChunkingOptions): Array<{ text: string; start: number }> {\n if (text.length <= opts.targetChars) return [{ text, start: 0 }]\n const atoms = splitAtoms(text)\n const chunks: Array<{ text: string; start: number }> = []\n let buffer = ''\n let bufferStart = 0\n for (const atom of atoms) {\n if (buffer === '') bufferStart = atom.start\n if (buffer.length > 0 && buffer.length + atom.text.length > opts.targetChars) {\n chunks.push({ text: buffer.trimEnd(), start: bufferStart })\n const overlap = buffer.slice(Math.max(0, buffer.length - opts.overlapChars))\n buffer = overlap + atom.text\n bufferStart = Math.max(bufferStart, atom.start - overlap.length)\n } else {\n buffer += atom.text\n }\n }\n if (buffer.trim() !== '') chunks.push({ text: buffer.trimEnd(), start: bufferStart })\n return mergeTinyChunks(chunks, opts)\n}\n\nfunction splitAtoms(text: string): Array<{ text: string; start: number }> {\n const parts: Array<{ text: string; start: number }> = []\n const paragraphs = text.split(/(\\n\\s*\\n)/)\n let cursor = 0\n for (let i = 0; i < paragraphs.length; i += 2) {\n const paragraph = (paragraphs[i] ?? '') + (paragraphs[i + 1] ?? '')\n if (paragraph === '') continue\n parts.push({ text: paragraph, start: cursor })\n cursor += paragraph.length\n }\n return parts\n}\n\nfunction mergeTinyChunks(\n chunks: Array<{ text: string; start: number }>,\n opts: ChunkingOptions,\n): Array<{ text: string; start: number }> {\n const out: Array<{ text: string; start: number }> = []\n for (const chunk of chunks) {\n const prev = out[out.length - 1]\n if (\n prev &&\n chunk.text.length < opts.minChars &&\n prev.text.length + chunk.text.length <= opts.maxChars\n ) {\n prev.text = `${prev.text}\\n\\n${chunk.text}`\n } else {\n out.push({ ...chunk })\n }\n }\n return out\n}\n","import {\n auditCurrentRunCitations,\n type KnowledgeCitationAuditIssue,\n type KnowledgeCitationAuditReport,\n} from './citation-resolution'\nimport type { RunScopedStores } from './run-scoped'\nimport type { KnowledgeLintFinding } from './types'\n\n/** Convert a chain-aware citation audit into the package lint vocabulary. */\nexport function knowledgeCitationAuditFindings(\n report: KnowledgeCitationAuditReport,\n): KnowledgeLintFinding[] {\n return report.issues.map(issueToFinding)\n}\n\n/** Lint only current-run pages against their complete declared visibility chain. */\nexport async function lintCurrentRunCitations(\n stores: RunScopedStores,\n runId: string,\n): Promise<KnowledgeLintFinding[]> {\n return knowledgeCitationAuditFindings(await auditCurrentRunCitations(stores, runId))\n}\n\nfunction issueToFinding(issue: KnowledgeCitationAuditIssue): KnowledgeLintFinding {\n const candidates = issue.candidates.map((candidate) => ({\n pageId: candidate.pageId,\n path: candidate.page.path,\n origin: candidate.origin,\n }))\n if (issue.kind === 'ambiguous') {\n return {\n type: 'ambiguous-citation',\n severity: 'error',\n page: issue.sourcePath,\n message:\n `Citation \"${issue.persistedCitation}\" resolves to ${issue.candidates.length} visible pages; ` +\n 'qualify it as here::<pageId>, inherited:<runId>::<pageId>, or shared::<pageId>.',\n metadata: {\n sourcePageId: issue.sourcePageId,\n sourceOrigin: issue.sourceOrigin,\n candidates,\n },\n }\n }\n return {\n type: 'broken-citation',\n severity: 'error',\n page: issue.sourcePath,\n message:\n issue.kind === 'self'\n ? `Page \"${issue.sourcePageId}\" cites itself through \"${issue.persistedCitation}\".`\n : `Citation \"${issue.persistedCitation}\" resolves to no visible page.`,\n metadata: {\n sourcePageId: issue.sourcePageId,\n sourceOrigin: issue.sourceOrigin,\n candidates,\n },\n }\n}\n","/**\n * The SINGLE-AGENT COLLECTION driver — the blind-collection baseline (Arm A).\n *\n * This is the honest null the depth A/B is measured against. The other drivers\n * spend extra inference to do something differentiated:\n * - `createVerifyingResearchDriver` runs an LLM gate per source (Arm B),\n * - `createResearchDrivingDriver` extracts claims, tracks corroboration, and\n * synthesizes deep follow-up questions to drive depth (Arm C).\n *\n * This driver does NONE of that. It is a pass-through: it accepts every source\n * the worker proposes and contributes no research, no gating, and no steering of\n * its own. The loop still dedups exact-uri duplicates before calling\n * `verifySource` (that is the loop's job, not the driver's), and the default\n * `foldGaps` (a plain bulleted list of the still-open readiness gaps) still folds\n * the gaps into the worker's next prompt — so the worker keeps researching, but\n * NOTHING intelligent sits between the worker and the knowledge base.\n *\n * In other words: ONE agent (the worker) collects sources round after round, and\n * the \"driver\" is an inert rubber stamp. That is exactly what \"single-agent\n * collection\" means — the topology with zero coordinator intelligence — so its\n * material-facts score is the floor every other arm must beat to justify its\n * extra inference cost.\n *\n * It adds NO router calls of its own: `verifySource` is a synchronous accept and\n * `foldGaps` is omitted so the loop uses its built-in gap list. So Arm A's cost\n * is the worker's cost alone — the cleanest possible blind-collection baseline.\n */\n\nimport type {\n ResearchDriver,\n ResearchSourceProposal,\n SourceVerdict,\n} from './verified-research-loop'\n\n/**\n * Build the single-agent collection driver. Accepts every source; never gates,\n * never researches, never steers beyond the loop's default open-gap list. The\n * worker is the only agent that thinks.\n */\nexport function createCollectionResearchDriver(): ResearchDriver {\n return {\n verifySource(_source: ResearchSourceProposal): SourceVerdict {\n return { accept: true }\n },\n }\n}\n","import { isDeepStrictEqual } from 'node:util'\n\nexport interface DiscoveryTask {\n id: string\n goal: string\n query?: string\n sourceHints?: string[]\n metadata?: Record<string, unknown>\n}\n\nexport interface DiscoveryResult {\n taskId: string\n summary: string\n sourceUris?: string[]\n claims?: Array<{ text: string; sourceUri?: string; confidence?: number }>\n followUpTasks?: DiscoveryTask[]\n metadata?: Record<string, unknown>\n}\n\nexport interface KnowledgeDiscoveryWorker {\n run(task: DiscoveryTask, signal?: AbortSignal): Promise<DiscoveryResult> | DiscoveryResult\n}\n\nexport interface KnowledgeDiscoveryDispatcher {\n dispatch(\n tasks: DiscoveryTask[],\n options?: {\n concurrency?: number\n signal?: AbortSignal\n },\n ): Promise<DiscoveryResult[]>\n}\n\nexport type DiscoveryLoopStopReason = 'complete' | 'max-rounds' | 'max-tasks' | 'aborted'\n\nexport interface DiscoveryLoopRound {\n round: number\n tasks: DiscoveryTask[]\n results: DiscoveryResult[]\n queuedFollowUps: DiscoveryTask[]\n}\n\nexport interface DiscoveryLoopResult {\n stopReason: DiscoveryLoopStopReason\n tasksDispatched: number\n results: DiscoveryResult[]\n rounds: DiscoveryLoopRound[]\n /** Tasks retained, not dropped, when a configured limit stops the loop. */\n pendingTasks: DiscoveryTask[]\n /** Structurally identical task identities ignored to prevent cycles. */\n duplicateTaskIds: string[]\n}\n\nexport interface RunDiscoveryLoopOptions {\n dispatcher: KnowledgeDiscoveryDispatcher\n initialTasks: readonly DiscoveryTask[]\n /** Maximum follow-up depth including the initial dispatch. Default 3. */\n maxRounds?: number\n /** Maximum tasks dispatched across all rounds. Default 24. */\n maxTasks?: number\n /** Forwarded to the dispatcher. Default 4. */\n concurrency?: number\n signal?: AbortSignal\n onRound?: (round: DiscoveryLoopRound) => Promise<void> | void\n}\n\n/**\n * Dispatch discovery tasks and recursively pursue worker-proposed follow-ups.\n *\n * The runner owns only bounded scheduling and accounting. Workers own search,\n * source verification, and domain-specific candidate shapes.\n */\nexport async function runDiscoveryLoop(\n options: RunDiscoveryLoopOptions,\n): Promise<DiscoveryLoopResult> {\n const maxRounds = positiveInteger(options.maxRounds ?? 3, 'maxRounds')\n const maxTasks = positiveInteger(options.maxTasks ?? 24, 'maxTasks')\n const concurrency = positiveInteger(options.concurrency ?? 4, 'concurrency')\n const known = new Map<string, DiscoveryTask>()\n const pending: DiscoveryTask[] = []\n const duplicateTaskIds = new Set<string>()\n enqueueTasks(options.initialTasks, known, pending, duplicateTaskIds)\n\n const rounds: DiscoveryLoopRound[] = []\n const results: DiscoveryResult[] = []\n let tasksDispatched = 0\n let aborted = false\n\n while (pending.length > 0 && rounds.length < maxRounds && tasksDispatched < maxTasks) {\n if (options.signal?.aborted) {\n aborted = true\n break\n }\n const capacity = maxTasks - tasksDispatched\n const tasks = pending.splice(0, capacity)\n let dispatched: DiscoveryResult[]\n try {\n dispatched = orderCompleteDispatch(\n tasks,\n await options.dispatcher.dispatch(tasks, {\n concurrency,\n signal: options.signal,\n }),\n )\n } catch (cause) {\n if (!options.signal?.aborted) throw cause\n pending.unshift(...tasks)\n aborted = true\n break\n }\n tasksDispatched += tasks.length\n results.push(...dispatched)\n\n const queuedFollowUps: DiscoveryTask[] = []\n for (const result of dispatched) {\n enqueueTasks(result.followUpTasks ?? [], known, queuedFollowUps, duplicateTaskIds)\n }\n pending.push(...queuedFollowUps)\n const round: DiscoveryLoopRound = {\n round: rounds.length + 1,\n tasks,\n results: dispatched,\n queuedFollowUps,\n }\n rounds.push(round)\n await options.onRound?.(round)\n if (options.signal?.aborted) {\n aborted = true\n break\n }\n }\n\n const stopReason: DiscoveryLoopStopReason = aborted\n ? 'aborted'\n : pending.length === 0\n ? 'complete'\n : tasksDispatched >= maxTasks\n ? 'max-tasks'\n : 'max-rounds'\n return {\n stopReason,\n tasksDispatched,\n results,\n rounds,\n pendingTasks: pending,\n duplicateTaskIds: [...duplicateTaskIds],\n }\n}\n\nexport function createLocalDiscoveryDispatcher(\n worker: KnowledgeDiscoveryWorker,\n): KnowledgeDiscoveryDispatcher {\n return {\n async dispatch(tasks, options = {}) {\n const concurrency = Math.max(1, options.concurrency ?? 4)\n const results: DiscoveryResult[] = []\n let cursor = 0\n async function runNext(): Promise<void> {\n while (cursor < tasks.length) {\n if (options.signal?.aborted) throw new Error('Discovery dispatch aborted')\n const task = tasks[cursor++]!\n results.push(await worker.run(task, options.signal))\n }\n }\n await Promise.all(Array.from({ length: Math.min(concurrency, tasks.length) }, runNext))\n return orderCompleteDispatch(tasks, results)\n },\n }\n}\n\nfunction enqueueTasks(\n tasks: readonly DiscoveryTask[],\n known: Map<string, DiscoveryTask>,\n destination: DiscoveryTask[],\n duplicateTaskIds: Set<string>,\n): void {\n for (const task of tasks) {\n assertTask(task)\n const prior = known.get(task.id)\n if (!prior) {\n known.set(task.id, task)\n destination.push(task)\n continue\n }\n if (!isDeepStrictEqual(prior, task)) {\n throw new Error(`Discovery task id '${task.id}' refers to conflicting tasks`)\n }\n duplicateTaskIds.add(task.id)\n }\n}\n\nfunction assertTask(task: DiscoveryTask): void {\n if (!task.id.trim()) throw new Error('Discovery task id must not be empty')\n if (!task.goal.trim()) throw new Error(`Discovery task '${task.id}' goal must not be empty`)\n}\n\nfunction orderCompleteDispatch(\n tasks: readonly DiscoveryTask[],\n results: readonly DiscoveryResult[],\n): DiscoveryResult[] {\n const order = new Map(tasks.map((task, index) => [task.id, index]))\n const received = new Set<string>()\n for (const result of results) {\n if (!order.has(result.taskId)) {\n throw new Error(`Discovery dispatcher returned unknown task '${result.taskId}'`)\n }\n if (received.has(result.taskId)) {\n throw new Error(`Discovery dispatcher returned task '${result.taskId}' more than once`)\n }\n received.add(result.taskId)\n }\n const missing = tasks.filter((task) => !received.has(task.id)).map((task) => task.id)\n if (missing.length > 0) {\n throw new Error(`Discovery dispatcher omitted tasks: ${missing.join(', ')}`)\n }\n return [...results].sort(\n (a, b) => (order.get(a.taskId) as number) - (order.get(b.taskId) as number),\n )\n}\n\nfunction positiveInteger(value: number, name: string): number {\n if (!Number.isInteger(value) || value < 1) {\n throw new Error(`Discovery loop ${name} must be a positive integer`)\n }\n return value\n}\n","import { buildKnowledgeIndex } from './indexer'\nimport { buildKnowledgeLexicalIndex, type KnowledgeLexicalIndex } from './lexical-index'\nimport { type KnowledgePagesOptions, normalizePagesDirectory } from './pages-directory'\nimport type { RetrievalEvalRetriever, RetrievedKnowledgeHit } from './retrieval-eval'\nimport { searchKnowledge } from './search'\nimport type { KnowledgeIndex, KnowledgeSearchResult } from './types'\n\nexport interface FileSystemSearchProviderOptions extends KnowledgePagesOptions {\n /** Knowledge-base root containing the pages directory and `.agent-knowledge/`. */\n root: string\n /** Optional warm index, useful when the caller already built one. */\n index?: KnowledgeIndex\n /** Default result count for `search()`. Defaults to 10. */\n defaultLimit?: number\n /**\n * `manual` caches the index until `refresh: true` or `invalidate()`.\n * `always` rebuilds from disk on every search.\n */\n refresh?: 'manual' | 'always'\n}\nexport interface FileSystemSearchOptions {\n limit?: number\n refresh?: boolean\n}\n\n/**\n * File-first retrieval over an `agent-knowledge` KB.\n *\n * This is the simple backend for products that want deterministic search over\n * markdown knowledge files before adding embeddings, rerankers, or a vector DB.\n */\nexport class FileSystemSearchProvider {\n readonly root: string\n /** Root-relative directory the provider indexes. */\n readonly pagesDirectory: string\n private index: KnowledgeIndex | undefined\n private lexicalIndex: KnowledgeLexicalIndex | undefined\n private readonly defaultLimit: number\n private readonly refreshMode: 'manual' | 'always'\n\n constructor(options: FileSystemSearchProviderOptions) {\n this.root = options.root\n this.pagesDirectory = normalizePagesDirectory(options.pagesDirectory)\n this.index = options.index\n this.defaultLimit = options.defaultLimit ?? 10\n this.refreshMode = options.refresh ?? 'manual'\n }\n\n async getIndex(options: FileSystemSearchOptions = {}): Promise<KnowledgeIndex> {\n if (this.refreshMode === 'always' || options.refresh || !this.index) {\n this.index = await buildKnowledgeIndex(this.root, { pagesDirectory: this.pagesDirectory })\n this.lexicalIndex = undefined\n }\n return this.index\n }\n\n async search(\n query: string,\n options: FileSystemSearchOptions = {},\n ): Promise<KnowledgeSearchResult[]> {\n const index = await this.getIndex(options)\n if (!this.lexicalIndex) this.lexicalIndex = buildKnowledgeLexicalIndex(index.pages)\n return searchKnowledge(index, query, {\n limit: options.limit ?? this.defaultLimit,\n lexicalIndex: this.lexicalIndex,\n })\n }\n\n async retrieve(\n query: string,\n options: FileSystemSearchOptions = {},\n ): Promise<RetrievedKnowledgeHit[]> {\n const hits = await this.search(query, options)\n return hits.map(hitFromSearchResult)\n }\n\n asRetrievalEvalRetriever(): RetrievalEvalRetriever {\n return async ({ config, scenario, k }) => ({\n hits: await this.retrieve(scenario.query, {\n limit: k,\n refresh: config.refresh === true,\n }),\n })\n }\n\n invalidate(): void {\n this.index = undefined\n this.lexicalIndex = undefined\n }\n}\n\nexport function createFileSystemSearchProvider(\n options: FileSystemSearchProviderOptions,\n): FileSystemSearchProvider {\n return new FileSystemSearchProvider(options)\n}\n\nfunction hitFromSearchResult(result: KnowledgeSearchResult): RetrievedKnowledgeHit {\n return {\n pageId: result.page.id,\n path: result.page.path,\n title: result.page.title,\n rank: result.rank,\n score: result.score,\n normalizedScore: result.normalizedScore,\n sourceIds: result.page.sourceIds,\n snippet: result.snippet,\n }\n}\n","import { readFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { z } from 'zod'\nimport { isMissingFile, writeJsonDurableWithinRoot } from './durable-fs'\nimport { withKnowledgeMutation, withKnowledgeRead } from './mutation-lock'\n\n/**\n * Knowledge freshness store: tracks when each `(workspaceId, sourceId)` pair\n * was last successfully refreshed, and reports staleness against a TTL.\n *\n * The contract is intentionally minimal and supports scheduled refresh loops:\n *\n * ```ts\n * const store = createFileSystemFreshnessStore({ root: '.agent-knowledge' })\n * for (const source of sources) {\n * if (await store.stale({ workspaceId, sourceId: source.id, ttlMs: DAY })) {\n * const fragments = await source.fetch({ cacheDir })\n * await persistFragments(fragments)\n * await store.mark({ workspaceId, sourceId: source.id, when: new Date() })\n * }\n * }\n * ```\n *\n * Per-tenant isolation is enforced by `workspaceId` keying. There is no\n * global mutable state across workspaces.\n *\n * Two adapters ship in-package:\n *\n * - `createFileSystemFreshnessStore`: JSON file under the knowledge root,\n * mirrors the layout convention already used by `sources.json`.\n * - `createD1FreshnessStoreStub`: complete bridge from the `D1Adapter` port\n * to this package's freshness interface. The port can be backed by D1,\n * PostgreSQL, SQLite, or another application-owned store.\n */\n\n/** Identity for one freshness record. */\nexport interface FreshnessKey {\n workspaceId: string\n sourceId: string\n}\n\n/** TTL bound for staleness checks. */\nexport interface FreshnessTtl extends FreshnessKey {\n /** Milliseconds; the record is stale when `Date.now() - last() > ttlMs`. */\n ttlMs: number\n /** Injected clock for deterministic tests; defaults to system time. */\n now?: Date\n}\n\n/** Mark argument. */\nexport interface FreshnessMark extends FreshnessKey {\n when: Date\n /** Optional content hash captured at refresh time; aids debugging. */\n contentHash?: string\n}\n\nexport interface KnowledgeFreshnessStore {\n /** Last refresh time, or null if never refreshed. */\n last(key: FreshnessKey): Promise<Date | null>\n /** Record a successful refresh. */\n mark(input: FreshnessMark): Promise<void>\n /** True iff `last(key)` is null or older than `ttlMs`. */\n stale(input: FreshnessTtl): Promise<boolean>\n /** All records for a workspace. */\n list(workspaceId: string): Promise<FreshnessRecord[]>\n}\n\nexport interface FreshnessRecord {\n workspaceId: string\n sourceId: string\n lastRefreshedAt: string\n contentHash?: string\n}\n\nexport interface FileSystemFreshnessStoreOptions {\n /**\n * Knowledge root. The store writes to `<root>/.agent-knowledge/freshness.json`,\n * mirroring the convention used by `sources.json`.\n */\n root: string\n}\n\nconst freshnessRecordSchema = z\n .object({\n workspaceId: z.string().min(1),\n sourceId: z.string().min(1),\n lastRefreshedAt: z.iso.datetime(),\n contentHash: z.string().min(1).optional(),\n })\n .strict()\nconst freshnessFileSchema = z\n .object({ records: z.record(z.string(), freshnessRecordSchema) })\n .strict()\n\n/**\n * Filesystem-backed implementation. Single JSON file per knowledge root,\n * indexed by `${workspaceId}::${sourceId}`. Reads parse on every call;\n * cron tick rate is well below the cost of one JSON parse.\n *\n * Writes share the package-wide filesystem lock, so multiple workers cannot\n * overwrite one another or run through an interrupted knowledge promotion.\n */\nexport function createFileSystemFreshnessStore(\n options: FileSystemFreshnessStoreOptions,\n): KnowledgeFreshnessStore {\n const path = join(options.root, '.agent-knowledge', 'freshness.json')\n\n const read = async (): Promise<Record<string, FreshnessRecord>> => {\n return withKnowledgeRead(options.root, async () => {\n try {\n return freshnessFileSchema.parse(JSON.parse(await readFile(path, 'utf8'))).records\n } catch (error) {\n if (isMissingFile(error)) return {}\n throw error\n }\n })\n }\n\n const write = async (records: Record<string, FreshnessRecord>): Promise<void> => {\n await writeJsonDurableWithinRoot(\n options.root,\n '.agent-knowledge/freshness.json',\n freshnessFileSchema.parse({ records }),\n )\n }\n\n return {\n async last(key) {\n const records = await read()\n const record = records[buildKey(key)]\n return record ? new Date(record.lastRefreshedAt) : null\n },\n async mark(input) {\n await withKnowledgeMutation(options.root, async () => {\n const records = await read()\n records[buildKey(input)] = {\n workspaceId: input.workspaceId,\n sourceId: input.sourceId,\n lastRefreshedAt: input.when.toISOString(),\n ...(input.contentHash === undefined ? {} : { contentHash: input.contentHash }),\n }\n await write(records)\n })\n },\n async stale(input) {\n const last = await this.last(input)\n if (!last) return true\n const now = input.now ?? new Date()\n return now.getTime() - last.getTime() > input.ttlMs\n },\n async list(workspaceId) {\n const records = await read()\n return Object.values(records).filter((r) => r.workspaceId === workspaceId)\n },\n }\n}\n\n/**\n * Bridge an application-owned database adapter to `KnowledgeFreshnessStore`.\n * The adapter may use D1, PostgreSQL, SQLite, or another durable store.\n *\n * The expected schema:\n *\n * ```sql\n * CREATE TABLE knowledge_freshness (\n * workspace_id TEXT NOT NULL,\n * source_id TEXT NOT NULL,\n * last_refreshed_at TEXT NOT NULL,\n * content_hash TEXT,\n * PRIMARY KEY (workspace_id, source_id)\n * );\n * ```\n */\nexport interface D1Adapter {\n get(workspaceId: string, sourceId: string): Promise<FreshnessRecord | null>\n upsert(record: FreshnessRecord): Promise<void>\n listByWorkspace(workspaceId: string): Promise<FreshnessRecord[]>\n}\n\nexport function createD1FreshnessStoreStub(adapter: D1Adapter): KnowledgeFreshnessStore {\n return {\n async last(key) {\n const record = await adapter.get(key.workspaceId, key.sourceId)\n return record ? new Date(record.lastRefreshedAt) : null\n },\n async mark(input) {\n await adapter.upsert({\n workspaceId: input.workspaceId,\n sourceId: input.sourceId,\n lastRefreshedAt: input.when.toISOString(),\n contentHash: input.contentHash,\n })\n },\n async stale(input) {\n const last = await this.last(input)\n if (!last) return true\n const now = input.now ?? new Date()\n return now.getTime() - last.getTime() > input.ttlMs\n },\n async list(workspaceId) {\n return adapter.listByWorkspace(workspaceId)\n },\n }\n}\n\nfunction buildKey(key: FreshnessKey): string {\n return `${key.workspaceId}::${key.sourceId}`\n}\n","/**\n * Invalidation propagation.\n *\n * A page whose own evidence refuted it carries an `invalidation`. That verdict\n * is invisible to a reader who arrives through a citation, so a page that cites\n * a refuted page records which of its citations are refuted. The pass is\n * planned as a diff, so a store already stamped produces no mutation and the\n * pass can run after every grading round.\n */\nimport { parseKnowledgeCitationReference, resolveKnowledgeCitation } from './citation-resolution'\nimport { formatFrontmatter } from './frontmatter'\nimport type { OriginatedPage } from './run-scoped'\nimport type { KnowledgeId, KnowledgePage } from './types'\n\n/** Frontmatter field naming the cited pages whose evidence refuted them. */\nexport const CITES_INVALIDATED_FIELD = 'citesInvalidated'\n\nexport interface KnowledgeInvalidationStamp {\n readonly page: KnowledgePage\n /** The value the field must hold, sorted and deduplicated. Empty removes the field. */\n readonly citesInvalidated: readonly KnowledgeId[]\n /** The value the page holds now, in the order it is stored. */\n readonly current: readonly KnowledgeId[]\n}\n\nexport interface KnowledgeInvalidationPlan {\n /** Every visible page carrying an invalidation, sorted by id. */\n readonly invalidatedPageIds: readonly KnowledgeId[]\n /** Only the pages whose stamp differs from what they hold, in path order. */\n readonly stamps: readonly KnowledgeInvalidationStamp[]\n}\n\n/**\n * Plan the `citesInvalidated` stamp for every page authored in the target\n * store.\n *\n * Citations resolve over the whole chain, so a page here may be stamped for\n * citing a refuted inherited or shared page. Only `here` pages are stamped: a\n * run does not write the stores it inherits or shares.\n */\nexport function planInvalidationPropagation(\n visiblePages: readonly OriginatedPage[],\n): KnowledgeInvalidationPlan {\n if (!Array.isArray(visiblePages)) {\n throw new TypeError('knowledge invalidation propagation requires the visible pages')\n }\n const invalidatedPageIds = [\n ...new Set(\n visiblePages\n .filter((entry) => entry.page.invalidation !== undefined)\n .map((entry) => entry.page.id),\n ),\n ].sort()\n\n const stamps: KnowledgeInvalidationStamp[] = []\n for (const entry of visiblePages) {\n if (entry.origin !== 'here') continue\n const page = entry.page\n const refuted = new Set<KnowledgeId>()\n for (const persisted of page.cites ?? []) {\n const resolution = resolveKnowledgeCitation(\n visiblePages,\n parseKnowledgeCitationReference(persisted),\n )\n if (resolution.resolved?.page.invalidation !== undefined) {\n refuted.add(resolution.resolved.page.id)\n }\n }\n const citesInvalidated = [...refuted].sort()\n const current = idList(page.frontmatter[CITES_INVALIDATED_FIELD])\n if (sameOrder(current, citesInvalidated)) continue\n stamps.push({ page, citesInvalidated, current })\n }\n stamps.sort((left, right) => left.page.path.localeCompare(right.page.path))\n return { invalidatedPageIds, stamps }\n}\n\n/**\n * Render one plan as a write-block proposal for `applyKnowledgeWriteBlocks`.\n *\n * Only the stamped field changes. The page is rendered through\n * `formatFrontmatter`, so its frontmatter is written in that writer's\n * normalized form.\n */\nexport function formatKnowledgeInvalidationProposal(plan: KnowledgeInvalidationPlan): string {\n return plan.stamps.map((stamp) => renderStampedBlock(stamp)).join('\\n')\n}\n\nfunction renderStampedBlock(stamp: KnowledgeInvalidationStamp): string {\n const frontmatter: Record<string, unknown> = { ...stamp.page.frontmatter }\n if (stamp.citesInvalidated.length === 0) delete frontmatter[CITES_INVALIDATED_FIELD]\n else frontmatter[CITES_INVALIDATED_FIELD] = [...stamp.citesInvalidated]\n const content = formatFrontmatter(frontmatter, stamp.page.text)\n return `---FILE: ${stamp.page.path}---\\n${content.replace(/\\n+$/, '')}\\n---END FILE---`\n}\n\nfunction idList(value: unknown): KnowledgeId[] {\n const values = typeof value === 'string' ? [value] : Array.isArray(value) ? value : []\n return values.filter((item): item is string => typeof item === 'string' && item.trim() !== '')\n}\n\nfunction sameOrder(left: readonly string[], right: readonly string[]): boolean {\n return left.length === right.length && left.every((item, index) => item === right[index])\n}\n","/**\n * HELD-OUT INVESTMENT-RESEARCH EVAL SET.\n *\n * The point of this file is the same FIREWALL the deep-question exam uses\n * (`tests/loops/held-out-exam.ts`): the material facts and their checkable\n * fragments are NEVER shown to a research loop. A loop is told only the company\n * + ticker + a research-as-of CUTOFF date, and asked to write an investment\n * thesis. AFTER it finishes, we grade the thesis it produced against THESE\n * facts — facts it never saw — so a high score is thesis QUALITY (it surfaced\n * the buried, material, non-obvious drivers) and not teaching-to-the-test.\n *\n * Each fact is a DEPTH fact by construction: a single ticker / company-name web\n * search does NOT surface it. They are the things buried in the filings or\n * knowable from then-available primary sources that a thorough analyst flags and\n * a one-shot search misses — customer/revenue/deposit concentration, a debt\n * maturity wall, a margin-trend reversal, a governance / related-party item, a\n * specific competitive or regulatory risk, an off-balance-sheet loss.\n *\n * THREE HARD RULES, enforced by how the data was gathered (see\n * docs/eval/investment-material-facts.md for the per-item provenance + the\n * curation-bias disclosure):\n *\n * 1. SPECIFIC + CHECKABLE. Each fact carries `expected` keyword groups — the\n * specific number / name / phrase — so a deterministic, model-free\n * substring grader (`gradeFactAgainstText`) can score \"did the thesis\n * surface it\". $0, reproducible, and it cannot leak the answer key into a\n * model the loop could observe.\n *\n * 2. DERIVED FROM REAL FETCHED EVIDENCE. Every fact records the primary source\n * it came from (`sourceUrl`, an SEC EDGAR 10-K) and the literal `evidence`\n * value read out of that document. Nothing here is invented; an item that\n * could not be independently sourced was DROPPED, not guessed (the drop log\n * is in the doc).\n *\n * 3. KNOWABLE AT THE CUTOFF. Every fact was disclosed in, or computable from, a\n * document available on or before the company's `cutoff` date. Post-cutoff\n * hindsight (the eventual bankruptcy / collapse) is NOT a checklist item —\n * it is recorded separately as `knownOutcome`, purely for the reader, and is\n * never graded.\n *\n * Grading mirrors the deep-question exam exactly: a fact is SURFACED when the\n * thesis text contains at least `minGroups` of its expected groups; a group is\n * satisfied when ANY of its `anyOf` fragments appears (case-insensitive\n * substring), so a faithful thesis phrased in its own words still grades as a\n * hit. `anyOf` groups model synonyms; the load-bearing tokens are the specific\n * numbers / names.\n */\n\n/** A required answer component: satisfied when any synonym fragment is present. */\nexport interface ExpectedGroup {\n /** Human label for the component (for the doc / audit). */\n label: string\n /** Case-insensitive substring fragments; any one present satisfies the group. */\n anyOf: string[]\n}\n\n/** Lens the fact belongs to — so a set can be checked for category coverage. */\nexport type MaterialFactLens =\n | 'concentration' // customer / revenue / deposit concentration\n | 'leverage' // debt load / maturity wall / interest burden\n | 'margin-trend' // gross/operating margin reversal\n | 'liquidity' // cash burn / negative operating cash flow\n | 'capital-return' // buyback / dividend draining the balance sheet\n | 'governance' // dual-class / related-party / control item\n | 'off-balance-sheet' // unrealized losses not in earnings/equity\n | 'regulatory' // a specific regulatory / legal / recall exposure\n\n/** One held-out material fact with a checkable expected answer + its provenance. */\nexport interface MaterialFact {\n /** Stable id, `ticker/fN`. */\n id: string\n /** Which analyst lens this fact exercises. For coverage + the doc. */\n lens: MaterialFactLens\n /**\n * The material fact, in plain words — for the doc/audit. NEVER shown to a loop.\n * This is the thing a thorough analyst would flag and a ticker search misses.\n */\n fact: string\n /**\n * The checkable answer as required keyword GROUPS. The thesis text must contain\n * at least `minGroups` of these groups (default: all). A group is satisfied\n * when ANY of its `anyOf` fragments appears (case-insensitive substring).\n */\n expected: ExpectedGroup[]\n /**\n * Minimum number of `expected` groups the thesis must contain to count the\n * fact SURFACED. Default = all groups (the strict bar). Lowered (and documented\n * inline) only when the fact is genuinely satisfiable by a subset.\n */\n minGroups?: number\n /**\n * PROVENANCE. The primary source URL this fact was read from — an SEC EDGAR\n * 10-K primary document, fetched live during curation.\n */\n sourceUrl: string\n /**\n * The literal value / phrase read out of `sourceUrl` that grounds the fact.\n * This is the \"cite the actual filing + the value\" requirement — verbatim or\n * near-verbatim from the filing, with the figure.\n */\n evidence: string\n}\n\n/** A company + the cutoff a loop researches as-of + its held-out material facts. */\nexport interface CompanyEvalCase {\n /** Ticker as of the cutoff. */\n ticker: string\n /** Legal name as of the cutoff (what the loop is told to research). */\n company: string\n /** SEC Central Index Key (CIK), zero-stripped — the EDGAR filer id. */\n cik: string\n /**\n * Research-as-of date (ISO). The loop must reason as if it is this date; every\n * `evidence` value was knowable on or before it. >= 18 months before this set\n * was curated, so the outcome is known but is NOT a checklist item.\n */\n cutoff: string\n /** Sector, for coverage / the curation-bias disclosure. */\n sector: string\n /**\n * The known POST-cutoff outcome — recorded for the reader ONLY, never graded.\n * Keeping it out of `facts` is what makes the set hindsight-free.\n */\n knownOutcome: string\n /** The held-out material facts for this company. */\n facts: MaterialFact[]\n}\n\n/**\n * The eval set. 5 public companies, 5-8 held-out material facts each, every fact\n * grounded in a primary SEC EDGAR 10-K filed on or before the cutoff.\n *\n * CURATION-BIAS DISCLOSURE (full version in the doc): all five are companies\n * whose buried risks later materialized, because that is where the material-vs-\n * surface distinction is sharpest AND where the figures are easy to verify after\n * the fact. This biases the set toward downside risks (two of the eight lenses,\n * concentration + leverage, dominate) and toward distressed names. A production\n * eval would balance these with companies whose buried facts were POSITIVE\n * drivers and with survivors. This set is honest about that and reports the lens\n * distribution so the bias is measurable, not hidden.\n */\nexport const investmentThesisSet: CompanyEvalCase[] = [\n {\n ticker: 'SIVB',\n company: 'SVB Financial Group',\n cik: '719739',\n cutoff: '2023-02-24',\n sector: 'Banking',\n knownOutcome:\n 'Failed in a deposit run and was placed in FDIC receivership on March 10, 2023; the holding company filed Chapter 11 on March 17, 2023.',\n facts: [\n {\n id: 'SIVB/f1',\n lens: 'off-balance-sheet',\n fact: 'Held-to-maturity (HTM) securities carried at $91.3B amortized cost had a fair value of only $76.2B — a ~$15.1B unrealized loss that, because the portfolio is HTM, never touched earnings or equity and sat only in the footnotes.',\n expected: [\n {\n label: 'HTM securities',\n anyOf: ['held-to-maturity', 'held to maturity', 'htm'],\n },\n {\n label: 'large unrealized loss (~$15B) / fair value gap',\n anyOf: [\n '15.1',\n '15.2',\n '$15 billion',\n '15 billion',\n '76,169',\n '76.2 billion',\n '91,321',\n 'unrealized loss',\n 'below amortized cost',\n 'fair value',\n ],\n },\n ],\n minGroups: 2,\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/719739/000071973923000021/sivb-20221231.htm',\n evidence:\n 'Balance sheet (Dec 31, 2022): \"Held-to-maturity securities, at amortized cost ... 91,321\" with parenthetical \"(fair value of $ 76,169 ...)\". The gap = $91,321M - $76,169M = ~$15,152M unrealized loss, disclosed only in the notes.',\n },\n {\n id: 'SIVB/f2',\n lens: 'off-balance-sheet',\n fact: \"The HTM unrealized loss (~$15.1B) was roughly equal to the company's entire $16.0B total stockholders' equity — a mark-to-market wipeout hidden by HTM accounting.\",\n expected: [\n {\n label: 'loss near/exceeds total equity',\n anyOf: [\n 'equity',\n 'capital',\n 'insolvent',\n 'wipe out',\n 'exceeds',\n 'nearly all',\n 'tangible book',\n '16,004',\n '16 billion',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/719739/000071973923000021/sivb-20221231.htm',\n evidence:\n '\"Total SVBFG stockholders\\' equity 16,004\" (Dec 31, 2022). The ~$15.15B HTM unrealized loss is ~95% of the $16.0B reported equity.',\n },\n {\n id: 'SIVB/f3',\n lens: 'concentration',\n fact: 'Estimated uninsured deposits in U.S. offices were $151.5B at year-end 2022 — the run-prone funding base; a high share of total deposits exceeded the FDIC limit.',\n expected: [\n {\n label: 'large uninsured deposit base',\n anyOf: [\n 'uninsured deposit',\n 'above the fdic',\n 'exceed the fdic',\n 'exceeds the fdic',\n '151.5',\n '$151 billion',\n 'fdic insurance limit',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/719739/000071973923000021/sivb-20221231.htm',\n evidence:\n '\"As of December 31, 2022 ... the amount of estimated uninsured deposits in U.S. offices that exceed the FDIC insurance limit were $151.5 billion\".',\n },\n {\n id: 'SIVB/f4',\n lens: 'margin-trend',\n fact: 'Cheap noninterest-bearing demand deposits fell 20 percentage points in one year — to 47% of total deposits from 67% — meaning funding costs were set to rise sharply as clients moved to interest-bearing accounts.',\n expected: [\n {\n label: 'deposit mix shift to costlier funding',\n anyOf: [\n 'noninterest-bearing',\n 'non-interest-bearing',\n 'noninterest bearing',\n 'deposit mix',\n 'funding cost',\n 'cost of deposits',\n 'interest-bearing',\n '47 percent',\n '20 percentage',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/719739/000071973923000021/sivb-20221231.htm',\n evidence:\n '\"Noninterest-bearing demand deposits to total deposits decreased by 20 percentage points to 47 percent as of December 31, 2022, compared to ... 2021.\"',\n },\n {\n id: 'SIVB/f5',\n lens: 'concentration',\n fact: 'The deposit and loan base was concentrated in a single client type — the \"innovation economy\" (venture-backed technology and life-science startups) — so a downturn in venture funding would hit deposits and credit simultaneously.',\n expected: [\n {\n label: 'concentration in tech / startups / innovation economy',\n anyOf: [\n 'innovation economy',\n 'technology',\n 'life science',\n 'venture',\n 'startup',\n 'early-stage',\n 'concentrat',\n 'single industry',\n 'sector concentration',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/719739/000071973923000021/sivb-20221231.htm',\n evidence:\n 'The 10-K repeatedly frames the franchise around clients in \"the innovation economy\" (technology, life science / healthcare, and the venture firms that back them) — a single-sector deposit + credit concentration.',\n },\n {\n id: 'SIVB/f6',\n lens: 'off-balance-sheet',\n fact: 'Available-for-sale (AFS) securities of $28.6B amortized cost were marked to a $26.1B fair value — a ~$2.5B loss that DID flow through equity (AOCI), the visible tip of a much larger unrealized-loss iceberg dominated by the footnote-only HTM book.',\n expected: [\n {\n label: 'AFS unrealized loss / AOCI',\n anyOf: [\n 'available-for-sale',\n 'available for sale',\n 'afs',\n 'aoci',\n 'accumulated other comprehensive',\n '28,602',\n '26,069',\n '2.5 billion',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/719739/000071973923000021/sivb-20221231.htm',\n evidence:\n '\"Available-for-sale securities, at fair value (cost of $ 28,602 ...) 26,069\" — a ~$2.5B AFS unrealized loss carried in AOCI, separate from and much smaller than the HTM gap.',\n },\n ],\n },\n {\n ticker: 'BBBY',\n company: 'Bed Bath & Beyond Inc.',\n cik: '886158',\n cutoff: '2022-04-21',\n sector: 'Specialty retail',\n knownOutcome: 'Filed for Chapter 11 bankruptcy on April 23, 2023; shareholders were wiped out.',\n facts: [\n {\n id: 'BBBY/f1',\n lens: 'capital-return',\n fact: 'The company had repurchased ~$11.685B of its own stock since 2004 — including $574.9M in fiscal 2021 alone, \"two years ahead of schedule\" — draining the balance sheet of a business that was losing money.',\n expected: [\n {\n label: 'massive buyback program',\n anyOf: [\n 'repurchas',\n 'buyback',\n 'buy back',\n 'share repurchase',\n '11.685',\n '$11.7 billion',\n '574.9',\n '$575 million',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/886158/000088615822000047/bbby-20220226.htm',\n evidence:\n '\"Since 2004 through the end of Fiscal 2021, we have repurchased approximately $11.685 billion of our common stock\"; FY2021 alone \"completed share repurchases of $574.9 million ... two years ahead of schedule.\"',\n },\n {\n id: 'BBBY/f2',\n lens: 'liquidity',\n fact: 'Operating cash flow collapsed to just $17.9M in FY2021, down from $268.1M and $590.9M in the two prior years — a near-total loss of internally generated cash while it kept buying back stock.',\n expected: [\n {\n label: 'operating cash flow collapse',\n anyOf: [\n 'operating cash flow',\n 'cash from operations',\n 'cash provided by operating',\n 'cash flow from operations',\n '17.9',\n '17,854',\n 'declining cash flow',\n 'cash generation',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/886158/000088615822000047/bbby-20220226.htm',\n evidence:\n 'Statement of cash flows: \"Net cash provided by operating activities 17,854 268,108 590,941\" (FY2021 / FY2020 / FY2019, $ thousands).',\n },\n {\n id: 'BBBY/f3',\n lens: 'liquidity',\n fact: \"Total shareholders' equity fell ~86% in one year — from $1.277B to $174.1M — as losses plus buybacks ate the equity cushion.\",\n expected: [\n {\n label: 'equity erosion',\n anyOf: [\n 'shareholders’ equity',\n \"shareholders' equity\",\n 'stockholders equity',\n 'book value',\n 'equity',\n 'net worth',\n '174.1',\n '174,145',\n 'eroded',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/886158/000088615822000047/bbby-20220226.htm',\n evidence:\n '\"Total shareholders\\' equity 174,145 1,276,936\" (FY2021 vs FY2020, $ thousands) — an ~86% decline in one year.',\n },\n {\n id: 'BBBY/f4',\n lens: 'liquidity',\n fact: 'The company posted a $559.6M net loss in FY2021 — yet spent $574.9M on buybacks the same year, i.e. it returned more cash to shareholders than it had, let alone earned.',\n expected: [\n {\n label: 'net loss FY2021',\n anyOf: [\n 'net loss',\n 'unprofitable',\n 'lost money',\n 'losing money',\n '559.6',\n '559,623',\n '$560 million',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/886158/000088615822000047/bbby-20220226.htm',\n evidence: '\"Net loss $ ( 559,623 )\" for fiscal 2021 ($ thousands).',\n },\n {\n id: 'BBBY/f5',\n lens: 'margin-trend',\n fact: 'Merchandise inventories rose to $1.725B even as sales fell — inventory building into a demand decline, a classic markdown-risk and cash-trap signal.',\n expected: [\n {\n label: 'inventory building into falling demand',\n anyOf: [\n 'inventor',\n 'merchandise inventories',\n 'overstock',\n 'markdown',\n '1,725',\n '1.7 billion',\n 'stockpile',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/886158/000088615822000047/bbby-20220226.htm',\n evidence:\n '\"Merchandise inventories 1,725,410 1,671,909\" ($ thousands) — inventory grew year over year while comparable sales declined.',\n },\n ],\n },\n {\n ticker: 'CVNA',\n company: 'Carvana Co.',\n cik: '1690820',\n cutoff: '2023-02-23',\n sector: 'Auto e-commerce',\n knownOutcome:\n 'The stock fell ~98% from its 2021 peak; the company narrowly avoided bankruptcy via a 2023 debt-exchange that cut and extended its obligations.',\n facts: [\n {\n id: 'CVNA/f1',\n lens: 'leverage',\n fact: 'Total debt had grown to $8.39B by year-end 2022 (from $5.45B) — a debt load far larger than the equity base, built up funding growth and the ADESA deal.',\n expected: [\n {\n label: 'large/growing debt load',\n anyOf: [\n 'total debt',\n 'long-term debt',\n 'leverage',\n 'highly leveraged',\n 'debt load',\n '8,391',\n '8.4 billion',\n '$8.4 billion',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1690820/000169082023000052/cvna-20221231.htm',\n evidence: '\"Total debt 8,391 5,447\" (Dec 31, 2022 vs 2021, $ millions).',\n },\n {\n id: 'CVNA/f2',\n lens: 'leverage',\n fact: 'Interest expense nearly tripled to $486M in 2022 (from $176M) — debt-service was consuming cash a still-unprofitable company did not have.',\n expected: [\n {\n label: 'rising interest burden',\n anyOf: [\n 'interest expense',\n 'interest cost',\n 'debt service',\n 'cost of debt',\n '486',\n 'interest burden',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1690820/000169082023000052/cvna-20221231.htm',\n evidence: '\"Interest expense 486 176\" (FY2022 vs FY2021, $ millions).',\n },\n {\n id: 'CVNA/f3',\n lens: 'leverage',\n fact: \"In May 2022 Carvana bought ADESA's U.S. physical auction business for ~$2.2B in cash — a debt-funded acquisition that stretched the balance sheet right as used-car demand turned.\",\n expected: [\n {\n label: 'ADESA acquisition ~$2.2B',\n anyOf: ['adesa', '2.2 billion', '$2.2 billion', 'physical auction', 'acquisition'],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1690820/000169082023000052/cvna-20221231.htm',\n evidence:\n '\"physical auction business of ADESA US Auction, LLC for approximately $2.2 billion in cash (the \\'ADESA Acquisition\\')\", closed 2022-05-09.',\n },\n {\n id: 'CVNA/f4',\n lens: 'governance',\n fact: 'Carvana leases hubs and properties from DriveTime — a company controlled by founder/CEO Ernest Garcia III and his father Ernest Garcia II — a recurring related-party arrangement with the controlling family.',\n expected: [\n {\n label: 'related-party with founder family / DriveTime',\n anyOf: [\n 'related party',\n 'related-party',\n 'drivetime',\n 'garcia',\n 'controlled by',\n 'affiliate of',\n 'conflict of interest',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1690820/000169082023000052/cvna-20221231.htm',\n evidence:\n 'Related Party Transactions note: lease agreements with \"DriveTime Automotive Group\", a related party \"due to Ernest Garcia II, Ernest Garcia III, and entities controlled by one or both of them\".',\n },\n {\n id: 'CVNA/f5',\n lens: 'liquidity',\n fact: 'The 2022 net loss was $2.894B — a loss far wider than prior years, showing the unit economics had not turned even at scale.',\n expected: [\n {\n label: 'large net loss FY2022',\n anyOf: [\n 'net loss',\n 'unprofitable',\n 'losing money',\n 'cash burn',\n '2,894',\n '2.9 billion',\n '$2.9 billion',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1690820/000169082023000052/cvna-20221231.htm',\n evidence: '\"Net loss $ (2,894 ...\" for fiscal 2022 ($ millions).',\n },\n ],\n },\n {\n ticker: 'PTON',\n company: 'Peloton Interactive, Inc.',\n cik: '1639825',\n cutoff: '2022-09-07',\n sector: 'Consumer fitness hardware',\n knownOutcome:\n 'The stock fell ~95% from its 2021 peak; the founder-CEO departed, the company underwent mass layoffs and a multi-year turnaround through fiscal 2024.',\n facts: [\n {\n id: 'PTON/f1',\n lens: 'margin-trend',\n fact: 'Connected Fitness (hardware) gross margin turned NEGATIVE — to (11)% in FY2022 — meaning Peloton lost money on every bike/tread it sold before any operating cost; revenue growth was masking a broken unit economics.',\n expected: [\n {\n label: 'negative / collapsing hardware gross margin',\n anyOf: [\n 'gross margin',\n 'negative margin',\n 'gross profit',\n 'margin compression',\n 'losing money on each',\n 'below cost',\n '(11)',\n '-11',\n 'negative gross',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1639825/000163982522000117/pton-20220630.htm',\n evidence:\n 'MD&A \"Gross Profit, and Gross Margin\" table: Connected Fitness \"Gross Margin decreased to (11)\" percent in fiscal 2022 — a negative hardware gross margin.',\n },\n {\n id: 'PTON/f2',\n lens: 'liquidity',\n fact: 'Inventories climbed to $1.105B as pandemic demand normalized — a glut of unsold equipment that tied up cash and risked markdowns.',\n expected: [\n {\n label: 'inventory glut',\n anyOf: [\n 'inventor',\n 'overstock',\n 'excess inventory',\n 'glut',\n 'markdown',\n 'unsold',\n '1,104',\n '1.1 billion',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1639825/000163982522000117/pton-20220630.htm',\n evidence: '\"Inventories, net 1,104.5 937\" (FY2022 vs FY2021, $ millions).',\n },\n {\n id: 'PTON/f3',\n lens: 'governance',\n fact: \"A dual-class structure gives Class B holders 20 votes per share vs 1 for Class A — concentrating control with insiders/founders and limiting public shareholders' say.\",\n expected: [\n {\n label: 'dual-class super-voting control',\n anyOf: [\n 'dual-class',\n 'dual class',\n 'class b',\n '20 votes',\n 'super-voting',\n 'supervoting',\n 'voting control',\n 'multiple votes per share',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1639825/000163982522000117/pton-20220630.htm',\n evidence:\n '\"Class B common stock has 20 votes per share and our Class A common stock has one vote per share.\"',\n },\n {\n id: 'PTON/f4',\n lens: 'liquidity',\n fact: 'Peloton reported a $2.827B net loss in FY2022 — an order-of-magnitude wider loss than the prior year, signaling the demand normalization had broken the model, not just dented it.',\n expected: [\n {\n label: 'large net loss FY2022',\n anyOf: [\n 'net loss',\n 'unprofitable',\n 'losing money',\n 'cash burn',\n '2,827',\n '2.8 billion',\n '$2.8 billion',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1639825/000163982522000117/pton-20220630.htm',\n evidence: '\"Net loss $ (2,827 ...\" for fiscal 2022 ($ millions).',\n },\n {\n id: 'PTON/f5',\n lens: 'regulatory',\n fact: 'Peloton was running a CPSC recall of its Tread+ treadmill (tied to injuries and a child death) — an open product-safety and legal exposure beyond the demand story.',\n expected: [\n {\n label: 'Tread+ / CPSC recall exposure',\n anyOf: [\n 'recall',\n 'cpsc',\n 'consumer product safety',\n 'tread+',\n 'tread plus',\n 'product safety',\n 'injuries',\n 'safety',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1639825/000163982522000117/pton-20220630.htm',\n evidence:\n '\"recall on Tread+, which we are conducting in collaboration with the Consumer Product Safety Commission (\\'CPSC\\')\"; the Tread product recalls \"in the fourth quarter of fiscal 2021 continued to impact\" results.',\n },\n {\n id: 'PTON/f6',\n lens: 'leverage',\n fact: 'Peloton was locked into ~$334M of manufacturing purchase commitments even as demand fell — contractual inventory it had to take on regardless of whether it could sell it.',\n expected: [\n {\n label: 'locked-in purchase commitments',\n anyOf: [\n 'purchase commitment',\n 'purchase obligation',\n 'minimum purchase',\n 'take-or-pay',\n 'committed to purchase',\n '334',\n 'manufacturing commitment',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1639825/000163982522000117/pton-20220630.htm',\n evidence:\n '\"purchase commitments related to the manufacture of Peloton products were estimated to be approximately $334\" million.',\n },\n ],\n },\n {\n ticker: 'SI',\n company: 'Silvergate Capital Corporation',\n cik: '1312109',\n cutoff: '2022-02-28',\n sector: 'Banking (digital-asset)',\n knownOutcome:\n 'After the FTX collapse triggered a deposit run, Silvergate announced a voluntary wind-down of Silvergate Bank and liquidation in March 2023.',\n facts: [\n {\n id: 'SI/f1',\n lens: 'concentration',\n fact: 'About 99.5% of total deposits were noninterest-bearing — essentially all funding was non-term money that could leave on demand, an extreme run-risk masked by very low funding cost.',\n expected: [\n {\n label: 'almost all deposits noninterest-bearing / on-demand',\n anyOf: [\n 'noninterest bearing',\n 'noninterest-bearing',\n 'non-interest-bearing',\n 'demand deposit',\n 'no term',\n 'on demand',\n '99.5',\n '99 percent',\n 'leave at any time',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1312109/000131210922000051/si-20211231.htm',\n evidence:\n '\"noninterest bearing deposits as a percentage of total deposits was 99.5% as of December 31, 2021.\"',\n },\n {\n id: 'SI/f2',\n lens: 'concentration',\n fact: 'Roughly 58% of deposits came from digital-currency EXCHANGES alone — a handful of correlated crypto counterparties whose own troubles would pull deposits out together.',\n expected: [\n {\n label: 'deposits concentrated in crypto exchanges',\n anyOf: [\n 'digital currency exchange',\n 'crypto exchange',\n 'exchanges represent',\n 'counterpart',\n 'concentrat',\n '58%',\n '58 percent',\n 'approximately 58',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1312109/000131210922000051/si-20211231.htm',\n evidence:\n '\"Deposits from digital currency exchanges represent approximately 58%\" of deposits.',\n },\n {\n id: 'SI/f3',\n lens: 'concentration',\n fact: 'The entire deposit franchise was tied to a single, volatile industry — digital-currency (crypto) customers — so a crypto downturn was a direct, undiversified funding shock.',\n expected: [\n {\n // The buried, depth signal is the CONCENTRATION framing — that the\n // whole deposit base is one undiversified industry bet — NOT the bare\n // fact that it banks crypto (a one-line ticker summary has that). So\n // bare \"crypto\" / \"digital asset\" are excluded; the load-bearing\n // tokens are the concentration / single-industry / undiversified\n // characterization or the filing's own \"digital currency customers\".\n label: 'single-industry deposit CONCENTRATION (not just \"it banks crypto\")',\n anyOf: [\n 'digital currency customers',\n 'single industry',\n 'one industry',\n 'single volatile industry',\n 'sector concentration',\n 'undiversified',\n 'concentrat',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1312109/000131210922000051/si-20211231.htm',\n evidence:\n 'The 10-K\\'s strategy and risk factors center the bank on \"digital currency customers\" and \"the concentration of our deposits\" in that single industry.',\n },\n {\n id: 'SI/f4',\n lens: 'liquidity',\n fact: 'Total deposits had ballooned to $14.3B (from $10.4B) — fast, hot-money growth from the crypto boom that could reverse just as fast.',\n expected: [\n {\n // The depth signal is the SIZE/character of the deposit base — the\n // specific $14.3B figure or the explicit hot-money / volatile-deposit\n // characterization — NOT bare \"total deposits\" / \"grew rapidly\", which\n // any growth-story summary trips. Those generic phrases are excluded.\n label: 'specific hot-money deposit base ($14.3B / volatile)',\n anyOf: [\n 'hot money',\n 'hot-money',\n 'volatile deposit',\n 'could reverse',\n '14.3 billion',\n '14,290',\n '$14.3b',\n '$14 billion',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1312109/000131210922000051/si-20211231.htm',\n evidence: '\"Total deposits $ 14,290,628\" ... prior year \"$ 10,411,278\" ($ thousands).',\n },\n {\n id: 'SI/f5',\n lens: 'concentration',\n fact: 'The franchise hinged on a single proprietary product — the Silvergate Exchange Network (SEN), a payment network built exclusively for the digital-currency industry — so its competitive moat and its deposit base were the SAME crypto-dependent bet, not two diversified ones.',\n expected: [\n {\n // The depth signal is naming the SPECIFIC proprietary product (the\n // Silvergate Exchange Network / SEN) and that the moat and the deposit\n // base are the same single bet — NOT bare \"proprietary\" / \"payment\n // network\", which a generic crypto-bank summary mentions. Those bare\n // terms are excluded; the SEN name or the single-product framing is\n // load-bearing.\n label: 'names the SEN single-product dependence (not generic \"payment network\")',\n anyOf: [\n 'silvergate exchange network',\n 'the sen',\n 'sen)',\n \"sen'\",\n 'single product',\n 'single-product',\n 'core product',\n 'one product',\n 'same bet',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1312109/000131210922000051/si-20211231.htm',\n evidence:\n \"\\\"Silvergate Exchange Network ('SEN'), our proprietary, virtually instantaneous payment network for participants in the digital currency industry\\\" — the bank's differentiator and its deposit magnet are the same crypto-only product.\",\n },\n ],\n },\n]\n\n/**\n * Grade ONE material fact against an investment thesis's full text. Returns\n * whether the thesis SURFACED it plus which expected groups were found. The\n * check is a deterministic case-insensitive substring scan — $0, model-free,\n * reproducible — so the eval never leaks into a model the loop could observe.\n */\nexport function gradeFactAgainstText(\n fact: MaterialFact,\n thesisText: string,\n): { surfaced: boolean; groupsFound: number; groupsTotal: number; foundLabels: string[] } {\n const haystack = thesisText.toLowerCase()\n const found = fact.expected.filter((group) =>\n group.anyOf.some((fragment) => haystack.includes(fragment.toLowerCase())),\n )\n const minGroups = fact.minGroups ?? fact.expected.length\n return {\n surfaced: found.length >= minGroups,\n groupsFound: found.length,\n groupsTotal: fact.expected.length,\n foundLabels: found.map((group) => group.label),\n }\n}\n\n/** Grade a whole company's thesis text: how many of its held-out facts it surfaces. */\nexport function gradeCompanyAgainstText(\n company: CompanyEvalCase,\n thesisText: string,\n): { surfaced: number; total: number; perFact: ReturnType<typeof gradeFactAgainstText>[] } {\n const perFact = company.facts.map((fact) => gradeFactAgainstText(fact, thesisText))\n return {\n surfaced: perFact.filter((result) => result.surfaced).length,\n total: company.facts.length,\n perFact,\n }\n}\n\n/** Total held-out facts across the set (the denominator the doc reports). */\nexport function totalMaterialFacts(set: CompanyEvalCase[] = investmentThesisSet): number {\n return set.reduce((sum, company) => sum + company.facts.length, 0)\n}\n\n/** Count facts per lens across the set — used to report (and bound) curation bias. */\nexport function lensDistribution(\n set: CompanyEvalCase[] = investmentThesisSet,\n): Record<MaterialFactLens, number> {\n const dist = {} as Record<MaterialFactLens, number>\n for (const company of set) {\n for (const fact of company.facts) {\n dist[fact.lens] = (dist[fact.lens] ?? 0) + 1\n }\n }\n return dist\n}\n","/**\n * `materialFactsSurfaced` — the held-out investment-research METRIC.\n *\n * Given a knowledge base a research loop built for a company and the company's\n * HELD-OUT material-fact checklist (`tests/eval/investment-thesis-set.ts`, never\n * shown to the loop), this returns the FRACTION of checklist items the KB's\n * pages surface + ground. The check is the same `$0`, model-free, deterministic\n * substring grader the loop's checklist already ships (`gradeFactAgainstText` /\n * `gradeCompanyAgainstText`) — so the answer key never reaches a model the loop\n * could observe, exactly the firewall the ML deep-question exam uses.\n *\n * The ONLY thing this file adds over the raw grader is the KB→text join: it reads\n * the curated pages (and the raw source text) the loop wrote and hands their\n * concatenation to the grader. That join mirrors `kbText` in the research-quality\n * A/B (research-driving-ab.test.ts) so the thesis metric and the ML-exam metric\n * read a KB the same way.\n *\n * WHY pages AND source text: an honest thesis surfaces a buried fact in its\n * curated thesis PAGE (the judgment), but a loop whose page is thin while its\n * fetched filings are rich should still get credit for what it actually pulled.\n * Grading the union is the faithful, not the lenient, choice — it rewards the\n * loop that REACHED the filing even if its synthesis was terse, and it cannot\n * manufacture a hit the underlying evidence does not contain.\n */\n\nimport { buildKnowledgeIndex } from './indexer'\nimport {\n type CompanyEvalCase,\n gradeCompanyAgainstText,\n gradeFactAgainstText,\n} from './investment-thesis-set'\nimport type { KnowledgeIndex } from './types'\n\n/** Per-fact grade plus the fact's id/lens, for the audit trail. */\nexport interface FactResult {\n id: string\n lens: CompanyEvalCase['facts'][number]['lens']\n surfaced: boolean\n groupsFound: number\n groupsTotal: number\n foundLabels: string[]\n}\n\n/** The metric's result for one company: the surfaced fraction + the per-fact trail. */\nexport interface MaterialFactsResult {\n ticker: string\n company: string\n /** Held-out facts the KB surfaced + grounded. */\n surfaced: number\n /** Total held-out facts for this company (the denominator). */\n total: number\n /** `surfaced / total` in [0, 1]. */\n fraction: number\n /** Per-fact grade, in checklist order, for the doc / audit. */\n perFact: FactResult[]\n}\n\n/**\n * Join a KB index into the single text blob the grader scans: every curated PAGE\n * (title + body) followed by every raw SOURCE (title + fetched text). This is the\n * text read AFTER the loop finished — it is never handed to the loop. Identical\n * in spirit to `kbText` in the research-quality A/B so both metrics read a KB the\n * same way.\n */\nexport function kbIndexToText(index: KnowledgeIndex): string {\n const pageText = index.pages.map((page) => `${page.title}\\n${page.text}`).join('\\n\\n')\n const sourceText = index.sources\n .map((source) => `${source.title ?? ''}\\n${source.text ?? ''}`)\n .join('\\n\\n')\n return `${pageText}\\n\\n${sourceText}`\n}\n\n/**\n * Grade one company's KB against its held-out material-fact checklist, given the\n * KB's already-joined text. The pure core — no I/O — so calibration can score a\n * hand-written shallow/deep thesis string directly and the live path can score a\n * real KB. Returns the surfaced FRACTION plus the per-fact audit trail.\n */\nexport function materialFactsSurfacedInText(\n company: CompanyEvalCase,\n kbText: string,\n): MaterialFactsResult {\n const grade = gradeCompanyAgainstText(company, kbText)\n const perFact: FactResult[] = company.facts.map((fact) => {\n const r = gradeFactAgainstText(fact, kbText)\n return {\n id: fact.id,\n lens: fact.lens,\n surfaced: r.surfaced,\n groupsFound: r.groupsFound,\n groupsTotal: r.groupsTotal,\n foundLabels: r.foundLabels,\n }\n })\n return {\n ticker: company.ticker,\n company: company.company,\n surfaced: grade.surfaced,\n total: grade.total,\n fraction: grade.total === 0 ? 0 : grade.surfaced / grade.total,\n perFact,\n }\n}\n\n/**\n * `materialFactsSurfaced(kb, checklist)` — the metric in its KB-reading form.\n *\n * `kb` is EITHER a knowledge-base root directory (the loop wrote pages there) or\n * an already-built `KnowledgeIndex`. `checklist` is the company's held-out\n * `CompanyEvalCase`. Returns the surfaced fraction + per-fact trail.\n *\n * The checklist is HELD OUT by construction: it lives in the test eval set, is\n * never passed to the loop, and is read only here, after the loop finished.\n */\nexport async function materialFactsSurfaced(\n kb: string | KnowledgeIndex,\n checklist: CompanyEvalCase,\n): Promise<MaterialFactsResult> {\n const index = typeof kb === 'string' ? await buildKnowledgeIndex(kb) : kb\n return materialFactsSurfacedInText(checklist, kbIndexToText(index))\n}\n","import type { KnowledgeReadinessReport } from '@tangle-network/agent-eval'\nimport {\n type BuildEvalKnowledgeBundleOptions,\n buildEvalKnowledgeBundle,\n type EvalKnowledgeBundleBuildResult,\n type KnowledgeReadinessSpec,\n} from './eval-readiness'\nimport { createKnowledgeEvent } from './events'\nimport { buildKnowledgeIndex } from './indexer'\nimport { FileSystemKbStore } from './kb-store'\nimport { applyKnowledgeWriteBlocks } from './proposals'\nimport { readinessFor } from './readiness-helpers'\nimport { searchKnowledge } from './search'\nimport {\n type AddSourceOptions,\n type AddSourceTextInput,\n addSourceText,\n snapshotSourceTextInput,\n} from './sources'\nimport { initKnowledgeBase } from './store'\nimport type { KnowledgeEvent, KnowledgeIndex, KnowledgeSearchResult, SourceRecord } from './types'\n\n/**\n * A knowledge gap the loop surfaces from `scoreKnowledgeReadiness`. The worker\n * targets these; the driver folds the unfilled remainder into the worker's next\n * prompt and runs its own gap-fill pass over them.\n */\nexport interface KnowledgeGap {\n /** Readiness-spec id this gap belongs to. */\n id: string\n /** Human-readable description of what's missing. */\n description: string\n /** The search query the readiness check ran for this requirement. */\n query: string\n /** True when the gap blocks readiness (vs. a soft, non-blocking gap). */\n blocking: boolean\n}\n\n/** A new source the worker (or driver) discovered and wants to add to the KB. */\nexport type ResearchSourceProposal = AddSourceTextInput\n\n/**\n * What a research agent contributes in one round. Both the worker and (when\n * `driverResearches` is on) the driver produce this shape — the worker ADDS\n * primary findings, the driver gap-FILLS the ones the worker missed.\n *\n * `proposalText` is the safe write-protocol text (`---FILE: knowledge/...---`\n * blocks). The loop only applies it AFTER the driver has verified the round's\n * sources, so a rejected source never reaches the curated pages.\n */\nexport interface ResearchContribution {\n /** Immutable sources to register (the raw evidence). */\n sources?: ResearchSourceProposal[]\n /** Safe write-protocol text producing curated `knowledge/*.md` pages. */\n proposalText?: string\n /**\n * Build the page write-protocol text FROM the sources the driver accepted —\n * the curated, citing pages the readiness gate searches. Receives the\n * registered `SourceRecord`s (with their assigned ids, so a page's frontmatter\n * `sources:` can cite them). Returns `---FILE: knowledge/...---` block text or\n * `undefined`. Runs after verification, so a page never cites a rejected\n * source. Concatenated after any static `proposalText`.\n */\n buildPages?: (acceptedSources: SourceRecord[]) => string | undefined\n /** Free-form research transcript — products can persist this. */\n notes?: string\n metadata?: Record<string, unknown>\n}\n\n/** Context handed to the worker each round. */\nexport interface WorkerResearchContext {\n root: string\n goal: string\n round: number\n index: KnowledgeIndex\n /** Gaps the readiness gate currently reports — what the worker should close. */\n gaps: KnowledgeGap[]\n /** Steer text the driver folded in from the previous round's remaining gaps. */\n steer?: string\n readiness: EvalKnowledgeBundleBuildResult\n signal?: AbortSignal\n}\n\n/** Context handed to the driver's verifier for one candidate source. */\nexport interface SourceVerificationContext {\n root: string\n goal: string\n round: number\n index: KnowledgeIndex\n gaps: KnowledgeGap[]\n /** Sources already accepted earlier THIS round (in-round dedup). */\n acceptedThisRound: ResearchSourceProposal[]\n signal?: AbortSignal\n}\n\n/** A single rejected source plus the reason the driver gave. */\nexport interface RejectedSource {\n source: ResearchSourceProposal\n reason: string\n}\n\n/** Context handed to the driver's gap-fill pass (only when `driverResearches`). */\nexport interface DriverResearchContext {\n root: string\n goal: string\n round: number\n index: KnowledgeIndex\n /** Gaps STILL open after the worker's accepted contribution applied. */\n remainingGaps: KnowledgeGap[]\n readiness: EvalKnowledgeBundleBuildResult\n signal?: AbortSignal\n}\n\n/**\n * The differentiated driver role.\n *\n * - `verifySource` — the gate the worker's additions pass before they commit.\n * Return `{ accept: true }` to keep a source or `{ accept: false, reason }`\n * to reject it (not real / not relevant / duplicate). The loop dedups exact\n * duplicates (same `uri` already in the KB or accepted this round) BEFORE\n * calling this, so the verifier only sees genuinely-new candidates.\n * - `research` — the driver's OWN gap-fill pass over the gaps the worker left\n * open. Only invoked when `driverResearches` is true.\n * - `foldGaps` — turn the remaining gaps into a steer string for the worker's\n * next prompt. Defaults to a compact bulleted list when omitted.\n * - `isComplete` — require the driver's research objectives as well as storage readiness.\n * - `checkpoint` — write whatever state the driver accumulated to durable\n * storage. Called at the end of every round, after `foldGaps`, so state that\n * a synchronous hook produced is on disk before the next round can crash.\n * - `prepareFold` — durably announce the next synchronous fold before it runs,\n * so a crash between question generation and `checkpoint` can be recovered.\n * - `commitSources` — confirm exact source records are durable after verification;\n * drivers with pending evidence must not count it before this callback.\n */\nexport interface ResearchDriver {\n verifySource(\n source: ResearchSourceProposal,\n ctx: SourceVerificationContext,\n ): Promise<SourceVerdict> | SourceVerdict\n research?(ctx: DriverResearchContext): Promise<ResearchContribution> | ResearchContribution\n foldGaps?(gaps: KnowledgeGap[]): string\n isComplete?(): boolean\n prepareFold?(): Promise<void> | void\n commitSources?(sources: readonly SourceRecord[]): Promise<void> | void\n checkpoint?(): Promise<void> | void\n}\n\nexport type SourceVerdict = { accept: true } | { accept: false; reason: string }\n\n/** The worker: primary research targeting the round's gaps. */\nexport type ResearchWorker = (\n ctx: WorkerResearchContext,\n) => Promise<ResearchContribution> | ResearchContribution\n\nexport interface VerifiedResearchLoopOptions {\n root: string\n goal: string\n worker: ResearchWorker\n driver: ResearchDriver\n /**\n * When false (default), the driver ONLY verifies + gates — a pure coordinator\n * that contributes no research of its own (the \"doesn't participate in the\n * work\" mode). When true, the driver also runs its `research` gap-fill pass\n * each round over the gaps the worker left open.\n */\n driverResearches?: boolean\n maxRounds?: number\n actor?: string\n /** Readiness specs define the gate; an empty list means the loop never gates. */\n readinessSpecs?: KnowledgeReadinessSpec[]\n readinessTaskId?: string\n readiness?: Omit<BuildEvalKnowledgeBundleOptions, 'taskId' | 'index' | 'specs'>\n sourceOptions?: Pick<AddSourceOptions, 'adapters' | 'now'>\n signal?: AbortSignal\n onRound?: (round: VerifiedResearchRound) => Promise<void> | void\n}\n\nexport interface VerifiedResearchRound {\n round: number\n /** Gaps reported at the START of the round (what the worker targeted). */\n gaps: KnowledgeGap[]\n /** Worker sources accepted by the driver and written to the KB. */\n acceptedWorkerSources: SourceRecord[]\n /** Worker sources the driver rejected (with reasons) — never written. */\n rejectedWorkerSources: RejectedSource[]\n /** Sources the driver itself added in its gap-fill pass. */\n driverSources: SourceRecord[]\n /** Curated pages written this round (worker proposal + driver proposal). */\n writtenPages: string[]\n readiness?: EvalKnowledgeBundleBuildResult\n /** True once readiness passes and the driver reports completion, when configured. */\n ready: boolean\n event: KnowledgeEvent\n notes: { worker?: string; driver?: string }\n}\n\nexport interface VerifiedResearchLoopResult {\n root: string\n goal: string\n rounds: number\n ready: boolean\n index: KnowledgeIndex\n readiness?: EvalKnowledgeBundleBuildResult\n steps: VerifiedResearchRound[]\n}\n\n/**\n * Two-agent (driver + worker) sibling of `runKnowledgeResearchLoop`.\n *\n * Both agents research to grow ONE knowledge base. The roles are differentiated:\n *\n * - **WORKER** = primary research. Each round it reads the open gaps, discovers\n * new sources, and proposes additions (`sources` + `proposalText`). It ADDS.\n * - **DRIVER** = the verifier / gap-filler / gate. It (1) VERIFIES the worker's\n * sources before they commit — dedup against the KB, then `verifySource`\n * rejects ones that aren't real/relevant; (2) GAP-FILLS the gaps the worker\n * missed with its own research pass (when `driverResearches`); (3) folds the\n * remaining gaps into the worker's next prompt; and (4) GATES on\n * `scoreKnowledgeReadiness` and optional `isComplete` — the loop stops when\n * readiness passes and the driver has no unfinished research.\n *\n * Set `driverResearches: false` (default) for the pure-coordinator mode: the\n * driver only verifies + gates and contributes no research itself.\n *\n * Composes existing atoms — `initKnowledgeBase`, `addSourceText`,\n * `applyKnowledgeWriteBlocks`, `buildEvalKnowledgeBundle` (the readiness gate),\n * and `searchKnowledge` — and reinvents none of them.\n */\nexport async function runVerifiedResearchLoop(\n options: VerifiedResearchLoopOptions,\n): Promise<VerifiedResearchLoopResult> {\n const maxRounds = Math.max(1, options.maxRounds ?? 3)\n await initKnowledgeBase(options.root)\n const store = new FileSystemKbStore({ root: options.root })\n const steps: VerifiedResearchRound[] = []\n let index = await buildKnowledgeIndex(options.root)\n // Reconcile source writes that completed before a previous process died while\n // confirming them to the driver. The records carry both original URI and hash.\n await confirmRegisteredSources(options.driver, index.sources)\n let readiness = readinessFor(options, index)\n let ready = isReady(readiness?.report) && (options.driver.isComplete?.() ?? true)\n let steer: string | undefined\n\n for (let round = 1; round <= maxRounds && !ready; round++) {\n if (options.signal?.aborted) throw new Error('Verified research loop aborted')\n\n const gaps = gapsFromReadiness(readiness)\n\n // 1. WORKER: primary research over the open gaps.\n const workerContribution = await options.worker({\n root: options.root,\n goal: options.goal,\n round,\n index,\n gaps,\n steer,\n readiness: requireReadiness(readiness, options),\n signal: options.signal,\n })\n\n // 2. DRIVER VERIFIES the worker's sources before they commit.\n const accepted: ResearchSourceProposal[] = []\n const rejectedWorkerSources: RejectedSource[] = []\n // Dedup against the ORIGINAL input uri. `addSourceText` rewrites `record.uri`\n // to a slugified raw path and stashes the caller's uri under\n // `metadata.originalUri`, so that — not the stored uri — is the round-to-round\n // identity a verifier dedups against.\n const existingUris = new Set(\n index.sources.flatMap((source) =>\n typeof source.metadata?.originalUri === 'string' ? [source.metadata.originalUri] : [],\n ),\n )\n for (const proposedSource of workerContribution.sources ?? []) {\n const source = snapshotSourceTextInput(proposedSource)\n if (isDuplicate(source, existingUris, accepted)) {\n rejectedWorkerSources.push({ source, reason: 'duplicate: already in the knowledge base' })\n continue\n }\n const verdict = await options.driver.verifySource(source, {\n root: options.root,\n goal: options.goal,\n round,\n index,\n gaps,\n acceptedThisRound: accepted,\n signal: options.signal,\n })\n if (verdict.accept) accepted.push(source)\n else rejectedWorkerSources.push({ source, reason: verdict.reason })\n }\n\n // Register the accepted worker sources, then apply the worker's curated\n // pages — but only when at least one source survived verification, so a\n // page never cites a rejected source.\n const acceptedWorkerSources = await registerSources(options, accepted)\n await confirmRegisteredSources(options.driver, acceptedWorkerSources)\n const writtenPages: string[] = []\n writtenPages.push(\n ...(await applyPages(options.root, workerContribution, acceptedWorkerSources)),\n )\n\n // Re-index so the driver's gap-fill pass sees the worker's contribution.\n index = await buildKnowledgeIndex(options.root)\n readiness = readinessFor(options, index)\n\n // 3. DRIVER GAP-FILLS the gaps the worker left open (opt-in).\n let driverSources: SourceRecord[] = []\n let driverNotes: string | undefined\n if (options.driverResearches && options.driver.research) {\n const remainingGaps = gapsFromReadiness(readiness)\n const driverContribution = await options.driver.research({\n root: options.root,\n goal: options.goal,\n round,\n index,\n remainingGaps,\n readiness: requireReadiness(readiness, options),\n signal: options.signal,\n })\n driverNotes = driverContribution.notes\n driverSources = await registerSources(options, driverContribution.sources ?? [])\n await confirmRegisteredSources(options.driver, driverSources)\n writtenPages.push(...(await applyPages(options.root, driverContribution, driverSources)))\n index = await buildKnowledgeIndex(options.root)\n readiness = readinessFor(options, index)\n }\n\n // 4. DRIVER GATES on readiness and folds the remainder into the next prompt.\n const driverComplete = options.driver.isComplete?.() ?? true\n ready = isReady(readiness?.report) && driverComplete\n const remainingGaps = gapsFromReadiness(readiness)\n if (ready || (remainingGaps.length === 0 && driverComplete)) {\n steer = undefined\n } else {\n await options.driver.prepareFold?.()\n steer = foldGaps(options.driver, remainingGaps)\n }\n\n const step: VerifiedResearchRound = {\n round,\n gaps,\n acceptedWorkerSources,\n rejectedWorkerSources,\n driverSources,\n writtenPages,\n readiness,\n ready,\n event: createKnowledgeEvent({\n type: 'research.iteration',\n actor: options.actor,\n target: options.root,\n metadata: {\n goal: options.goal,\n round,\n ready,\n acceptedWorkerSourceCount: acceptedWorkerSources.length,\n rejectedWorkerSourceCount: rejectedWorkerSources.length,\n driverSourceCount: driverSources.length,\n writtenPageCount: writtenPages.length,\n remainingGapCount: remainingGaps.length,\n },\n }),\n notes: { worker: workerContribution.notes, driver: driverNotes },\n }\n // Commit the driver's state before publishing the round event. A persisted\n // event therefore never claims a round whose generated questions were lost.\n await options.driver.checkpoint?.()\n await store.putEvent(step.event)\n\n steps.push(step)\n await options.onRound?.(step)\n }\n\n return {\n root: options.root,\n goal: options.goal,\n rounds: steps.length,\n ready,\n index,\n readiness,\n steps,\n }\n}\n\nfunction isReady(report: KnowledgeReadinessReport | undefined): boolean {\n // No specs ⇒ no gate ⇒ the loop runs to `maxRounds`. With specs, the gate is\n // \"no blocking gaps remain\".\n if (!report) return false\n return report.blockingMissingRequirements.length === 0\n}\n\nfunction gapsFromReadiness(readiness: EvalKnowledgeBundleBuildResult | undefined): KnowledgeGap[] {\n if (!readiness) return []\n const blocking = readiness.report.blockingMissingRequirements.map((requirement) =>\n gapFor(requirement, readiness, true),\n )\n const nonBlocking = readiness.report.nonBlockingGaps.map((requirement) =>\n gapFor(requirement, readiness, false),\n )\n return [...blocking, ...nonBlocking]\n}\n\nfunction gapFor(\n requirement: { id: string; description: string; metadata?: Record<string, unknown> },\n readiness: EvalKnowledgeBundleBuildResult,\n blocking: boolean,\n): KnowledgeGap {\n const spec = readiness.requirements.find((entry) => entry.id === requirement.id)\n const query =\n typeof spec?.metadata?.query === 'string' ? spec.metadata.query : requirement.description\n return { id: requirement.id, description: requirement.description, query, blocking }\n}\n\nfunction foldGaps(driver: ResearchDriver, gaps: KnowledgeGap[]): string | undefined {\n if (driver.foldGaps) return driver.foldGaps(gaps)\n if (gaps.length === 0) return undefined\n return [\n 'The knowledge base is still missing the following. Prioritise these next round:',\n ...gaps.map(\n (gap) => `- (${gap.blocking ? 'blocking' : 'soft'}) ${gap.description} [${gap.id}]`,\n ),\n ].join('\\n')\n}\n\nfunction isDuplicate(\n source: ResearchSourceProposal,\n existingUris: Set<string>,\n accepted: ResearchSourceProposal[],\n): boolean {\n return existingUris.has(source.uri) || accepted.some((candidate) => candidate.uri === source.uri)\n}\n\nasync function registerSources(\n options: VerifiedResearchLoopOptions,\n sources: ResearchSourceProposal[],\n): Promise<SourceRecord[]> {\n const records: SourceRecord[] = []\n for (const candidate of sources) {\n const source = snapshotSourceTextInput(candidate)\n records.push(await addSourceText(options.root, source, options.sourceOptions))\n }\n return records\n}\n\nasync function confirmRegisteredSources(\n driver: ResearchDriver,\n sources: readonly SourceRecord[],\n): Promise<void> {\n if (!driver.commitSources) return\n const textSources = sources.filter((source) => typeof source.metadata?.originalUri === 'string')\n if (textSources.length === 0) return\n await driver.commitSources(textSources)\n}\n\n/**\n * Apply a contribution's curated pages. Static `proposalText` plus a\n * `buildPages(acceptedSources)` result are concatenated and run through the safe\n * write protocol — but ONLY when at least one source survived verification, so a\n * page never cites a rejected (or absent) source.\n */\nasync function applyPages(\n root: string,\n contribution: ResearchContribution,\n acceptedSources: SourceRecord[],\n): Promise<string[]> {\n if (acceptedSources.length === 0) return []\n const parts: string[] = []\n if (contribution.proposalText) parts.push(contribution.proposalText)\n const built = contribution.buildPages?.(acceptedSources)\n if (built) parts.push(built)\n if (parts.length === 0) return []\n const applied = await applyKnowledgeWriteBlocks(root, parts.join('\\n'))\n return applied.written\n}\n\nfunction requireReadiness(\n readiness: EvalKnowledgeBundleBuildResult | undefined,\n options: VerifiedResearchLoopOptions,\n): EvalKnowledgeBundleBuildResult {\n if (readiness) return readiness\n // The worker/driver contexts type `readiness` as required for ergonomics; when\n // no specs are configured there is no gate to report, so synthesise an empty\n // bundle rather than forcing every caller to handle `undefined`.\n return buildEvalKnowledgeBundle({\n ...(options.readiness ?? {}),\n taskId: options.readinessTaskId ?? options.goal,\n index: emptyIndex(options.root),\n specs: [],\n })\n}\n\nfunction emptyIndex(root: string): KnowledgeIndex {\n return {\n root,\n generatedAt: new Date(0).toISOString(),\n sources: [],\n pages: [],\n graph: { nodes: [], edges: [] },\n }\n}\n\n/**\n * Helper for verifiers: does the candidate source's text/title overlap any page\n * the readiness search returns for a gap query? A cheap relevance heuristic the\n * driver can compose into `verifySource` (real verifiers can do more).\n */\nexport function sourceMatchesGaps(\n source: ResearchSourceProposal,\n index: KnowledgeIndex,\n gaps: KnowledgeGap[],\n): KnowledgeSearchResult[] {\n const haystack = `${source.title ?? ''}\\n${source.text}`.toLowerCase()\n const hits: KnowledgeSearchResult[] = []\n for (const gap of gaps) {\n for (const token of gap.query.toLowerCase().split(/\\s+/).filter(Boolean)) {\n if (haystack.includes(token)) {\n hits.push(...searchKnowledge(index, gap.query, 1))\n break\n }\n }\n }\n return hits\n}\n","/**\n * The INVESTMENT-THESIS research task.\n *\n * Given `{ company, ticker, cik, cutoff }`, drive the SAME two-agent research\n * loop the ML deep-question A/B uses (`runVerifiedResearchLoop` + the real web\n * worker) to research the company AS OF the cutoff — web + SEC EDGAR, both public\n * — and produce an investment-thesis PAGE in the knowledge base: a judgment, the\n * drivers, and the risks, grounded in what it fetched.\n *\n * This file builds NOTHING new for the loop: it composes the existing worker +\n * driver + loop, supplies the readiness specs that steer the worker toward the\n * filing-level evidence (the analyst lenses), then writes a synthesis thesis page\n * the metric (`materialFactsSurfaced`) grades against the HELD-OUT checklist.\n *\n * THE FIREWALL: the task is told ONLY company + ticker + cutoff (+ the generic\n * analyst-lens readiness specs every company gets). It is NEVER shown the\n * checklist. The checklist is read only afterward, by the metric. So a high score\n * is research depth, not teaching-to-the-test.\n */\n\nimport { join } from 'node:path'\nimport { writeFileDurableWithinRoot } from './durable-fs'\nimport { defineReadinessSpec, type KnowledgeReadinessSpec } from './eval-readiness'\nimport { slugify } from './ids'\nimport { buildKnowledgeIndex } from './indexer'\nimport { kbIndexToText } from './material-facts-metric'\nimport { withKnowledgeMutation } from './mutation-lock'\nimport {\n type ResearchDriver,\n runVerifiedResearchLoop,\n type VerifiedResearchLoopResult,\n} from './verified-research-loop'\nimport {\n createWebResearchWorker,\n type RouterClient,\n type WebResearchWorkerOptions,\n} from './web-research-worker'\n\n/** The minimal brief a thesis run is given — the firewall boundary. */\nexport interface ThesisTaskInput {\n /** Legal name as of the cutoff — what the loop researches. */\n company: string\n /** Ticker as of the cutoff. */\n ticker: string\n /** SEC Central Index Key (CIK), zero-stripped — the EDGAR filer id. */\n cik: string\n /** Research-as-of date (ISO). The loop must reason as if it is this date. */\n cutoff: string\n /** Sector, for the readiness query context (NOT a checklist hint). */\n sector?: string\n}\n\n/**\n * The generic analyst-lens readiness specs every company gets. They are the ONLY\n * thing the loop is told about WHAT to look for, and they name the LENSES a\n * thorough analyst checks (balance-sheet risk, concentration, leverage, margins,\n * liquidity, governance, regulatory) and where they live (the latest SEC 10-K) —\n * NOT the answers. They steer the worker's web/EDGAR search toward the filing,\n * not toward the held-out facts (which the loop never sees).\n *\n * `minSources` is set above 1 so the readiness gate stays UNMET after a single\n * fetch and the loop runs multiple rounds — the depth-driving driver needs >1\n * round to steer, exactly as the ML-exam multi-round probe established.\n */\nexport function thesisReadinessSpecs(input: ThesisTaskInput): KnowledgeReadinessSpec[] {\n const c = input.company\n const t = input.ticker\n const filing = `${c} ${t} SEC 10-K annual report SEC.gov EDGAR filing`\n return [\n defineReadinessSpec({\n id: 'thesis/filing',\n description: `the most recent SEC 10-K annual report for ${c} (${t}) filed on or before ${input.cutoff}, from SEC EDGAR`,\n query: filing,\n requiredFor: ['ResearchAgent'],\n importance: 'blocking',\n minSources: 2,\n minHits: 1,\n }),\n defineReadinessSpec({\n id: 'thesis/balance-sheet',\n description: `${c} balance-sheet risks: securities marked below cost, unrealized losses, leverage / total debt, debt maturities, interest expense`,\n query: `${c} ${t} 10-K balance sheet total debt unrealized losses interest expense leverage`,\n requiredFor: ['ResearchAgent'],\n importance: 'blocking',\n minSources: 2,\n minHits: 1,\n }),\n defineReadinessSpec({\n id: 'thesis/concentration-liquidity',\n description: `${c} concentration + liquidity: customer / deposit / revenue concentration, uninsured deposits, operating cash flow, net loss, inventory, equity erosion`,\n query: `${c} ${t} 10-K customer deposit concentration operating cash flow net loss inventory`,\n requiredFor: ['ResearchAgent'],\n importance: 'blocking',\n minSources: 2,\n minHits: 1,\n }),\n defineReadinessSpec({\n id: 'thesis/governance-regulatory',\n description: `${c} governance + regulatory: related-party transactions, dual-class / super-voting control, buybacks / dividends, recalls, regulatory or legal exposure, margin trends`,\n query: `${c} ${t} 10-K related party dual class share repurchase recall regulatory gross margin`,\n requiredFor: ['ResearchAgent'],\n importance: 'blocking',\n minSources: 2,\n minHits: 1,\n }),\n ]\n}\n\n/**\n * The thesis-writer prompt. After the loop has fetched + curated the filings, we\n * ask the model to SYNTHESIZE a thesis page from the curated KB text — a\n * judgment, the key drivers, and the material risks, grounded ONLY in the fetched\n * evidence. The held-out checklist is NOT in this prompt; the model writes from\n * what the loop actually pulled, so a fact only appears if the research surfaced\n * the underlying evidence.\n */\nfunction thesisSynthesisMessages(\n input: ThesisTaskInput,\n kbText: string,\n): { role: 'system' | 'user'; content: string }[] {\n const system =\n 'You are a buy-side investment analyst writing a thesis memo. You are given ' +\n 'the raw research your team gathered from public filings (SEC 10-K) and the web. ' +\n 'Write a thesis that a thorough analyst would write: lead with your JUDGMENT, ' +\n 'then the KEY DRIVERS, then the MATERIAL RISKS. Be specific and quantitative — ' +\n 'name the actual figures, balance-sheet items, concentrations, leverage, ' +\n 'margin trends, governance items, and regulatory exposures that appear in the ' +\n 'research. Surface the buried, non-obvious drivers a one-line ticker summary ' +\n 'misses. Ground every claim in the research provided; do NOT invent figures. ' +\n 'If the research does not contain a figure, do not state it.'\n const user = [\n `Company: ${input.company} (${input.ticker})`,\n `As-of date (reason as if it is this date): ${input.cutoff}`,\n input.sector ? `Sector: ${input.sector}` : '',\n '',\n 'Research gathered (filings + web excerpts):',\n '\"\"\"',\n kbText.slice(0, 24000),\n '\"\"\"',\n '',\n 'Write the investment thesis now. Structure:',\n '## Judgment',\n '## Key drivers',\n '## Material risks',\n ]\n .filter(Boolean)\n .join('\\n')\n return [\n { role: 'system', content: system },\n { role: 'user', content: user },\n ]\n}\n\n/** Write the synthesis thesis page into the KB so the index + metric pick it up. */\nasync function writeThesisPage(\n root: string,\n input: ThesisTaskInput,\n thesis: string,\n): Promise<string> {\n return withKnowledgeMutation(root, async () => {\n const relativePath = `knowledge/thesis-${slugify(input.ticker)}.md`\n const body = [\n '---',\n `title: Investment thesis — ${input.company} (${input.ticker})`,\n `ticker: ${input.ticker}`,\n `cutoff: ${input.cutoff}`,\n 'kind: investment-thesis',\n '---',\n `# Investment thesis — ${input.company} (${input.ticker}), as of ${input.cutoff}`,\n '',\n thesis.trim(),\n '',\n ].join('\\n')\n await writeFileDurableWithinRoot(root, relativePath, body, { encoding: 'utf8' })\n return join(root, relativePath)\n })\n}\n\nexport interface ThesisRunOptions {\n /** The KB root the loop writes into. */\n root: string\n /** Shared router client (web search + chat). Defaults to env creds. */\n router: RouterClient\n /** The driver — verify/dedup or research-driving. The loop's coordinator. */\n driver: ResearchDriver\n /** Round budget. Default 3 (the depth-driving driver needs >1). */\n maxRounds?: number\n /** Worker tuning forwarded to `createWebResearchWorker`. */\n workerOptions?: Omit<WebResearchWorkerOptions, 'router'>\n /** Max tokens for the synthesis pass. Default 1600 (above glm-5.2's reasoning floor). */\n synthesisMaxTokens?: number\n signal?: AbortSignal\n}\n\nexport interface ThesisRunResult {\n loop: VerifiedResearchLoopResult\n /** The synthesized thesis text. */\n thesis: string\n /** Path of the thesis page written into the KB. */\n thesisPath: string\n}\n\n/**\n * Run the full thesis task: drive the two-agent loop to research the company AS\n * OF the cutoff, then synthesize + write the thesis page. Returns the loop result\n * + the thesis text + the page path. The caller grades the KB with\n * `materialFactsSurfaced(root, checklist)` — the checklist is never passed here.\n */\nexport async function runInvestmentThesisTask(\n input: ThesisTaskInput,\n options: ThesisRunOptions,\n): Promise<ThesisRunResult> {\n const worker = createWebResearchWorker({ ...options.workerOptions, router: options.router })\n const goal = `${input.company} (${input.ticker}) investment thesis as of ${input.cutoff}`\n\n const loop = await runVerifiedResearchLoop({\n root: options.root,\n goal,\n worker,\n driver: options.driver,\n readinessSpecs: thesisReadinessSpecs(input),\n maxRounds: options.maxRounds ?? 3,\n signal: options.signal,\n })\n\n // Synthesize the thesis from what the loop actually curated + fetched.\n const index = await buildKnowledgeIndex(options.root)\n const kbText = kbIndexToText(index)\n const messages = thesisSynthesisMessages(input, kbText)\n const thesis = await options.router.chat(messages, options.synthesisMaxTokens ?? 1600)\n\n const thesisPath = await writeThesisPage(options.root, input, thesis)\n return { loop, thesis, thesisPath }\n}\n","/**\n * Retrieval briefing.\n *\n * A brief turns \"retrieved\" from something a run claims into something the\n * infrastructure can prove. It ranks the knowledge visible to a question,\n * renders it with the ids a later write must cite, and returns the ranked\n * results in the shape a retrieval receipt takes, so what an actor was given\n * is recorded rather than asserted.\n *\n * Pure: no clock, no filesystem, no network.\n */\nimport { canonicalCandidateDigest, type Sha256Digest } from '@tangle-network/agent-interface'\nimport {\n assertKnowledgeCitationsResolved,\n formatKnowledgeCitationReference,\n parseKnowledgeCitationReference,\n resolveKnowledgeCitation,\n} from './citation-resolution'\nimport type { OriginatedKnowledgeSearchResult } from './knowledge-use-receipts'\nimport type { OriginatedPage } from './run-scoped'\nimport {\n KNOWLEDGE_SEARCH_RETRIEVER_ID,\n type KnowledgeSearchHit,\n searchKnowledgePages,\n} from './search'\nimport type { KnowledgeId, KnowledgePage } from './types'\n\n/** Pages in a brief when the caller names no limit. */\nexport const DEFAULT_KNOWLEDGE_BRIEF_LIMIT = 5\n\nexport interface KnowledgeBriefOptions {\n /** Maximum pages in the brief. Defaults to 5. */\n limit?: number\n /**\n * Drop pages whose own evidence refuted them. Defaults to true, the opposite\n * of `searchKnowledge`: a brief is injected before a run's first token and\n * offers every page it names with an id ready to cite, so a refuted page in\n * it is an invitation to build on a dead claim.\n */\n excludeInvalidated?: boolean\n /** Match pages carrying at least one of these tags. */\n tags?: readonly string[]\n /** Match the exact string stored in `frontmatter.kind`. */\n kinds?: readonly string[]\n /**\n * Bound on the rendered brief. A page whose line does not fit is left out of\n * the whole brief, so `text`, `hits`, `citationIds`, and `results` always\n * describe one identical set of pages.\n */\n maxChars?: number\n}\n\nexport interface KnowledgeBrief {\n readonly question: string\n /** Retriever id to declare in a receipt minted from `results`. */\n readonly retrieverId: typeof KNOWLEDGE_SEARCH_RETRIEVER_ID\n /**\n * Digest of the retrieval settings this brief used. Pass it as the\n * `configDigest` of the receipt's retriever identity. The running package\n * version is the caller's to declare, because a bundled build cannot read it.\n */\n readonly retrieverConfigDigest: Sha256Digest\n readonly hits: readonly KnowledgeSearchHit[]\n /** The ids a write should persist in `cites`, in rank order. */\n readonly citationIds: readonly KnowledgeId[]\n /** Ranked results in the shape `createKnowledgeRetrievalReceipt` takes. */\n readonly results: readonly OriginatedKnowledgeSearchResult[]\n /** Deterministic Markdown: one `- [id] title — snippet` line per page, in rank order. */\n readonly text: string\n}\n\n/**\n * Rank the knowledge one question can see and render it for injection.\n *\n * The same page set produces the same brief on every run: ranking, ordering,\n * and rendering are deterministic, and no field carries a timestamp.\n */\nexport function buildKnowledgeBrief(\n visiblePages: readonly OriginatedPage[],\n question: string,\n options: KnowledgeBriefOptions = {},\n): KnowledgeBrief {\n if (!Array.isArray(visiblePages)) {\n throw new TypeError('knowledge brief requires the visible pages')\n }\n if (typeof question !== 'string' || question.trim().length === 0) {\n throw new TypeError('knowledge brief question must be a non-empty string')\n }\n const limit = options.limit ?? DEFAULT_KNOWLEDGE_BRIEF_LIMIT\n const excludeInvalidated = options.excludeInvalidated ?? true\n const maxChars = options.maxChars\n if (maxChars !== undefined && (!Number.isInteger(maxChars) || maxChars < 0)) {\n throw new Error(`knowledge brief maxChars must be a non-negative integer, got ${maxChars}`)\n }\n\n // Resolve citation addresses with the same owner used by read/write validation.\n // Keep a small candidate list per id so resolving links does not rescan the corpus.\n const byId = new Map<KnowledgeId, OriginatedPage[]>()\n for (const entry of visiblePages) {\n const matches = byId.get(entry.page.id) ?? []\n matches.push(entry)\n byId.set(entry.page.id, matches)\n }\n const qualified = (entry: OriginatedPage) =>\n formatKnowledgeCitationReference({ pageId: entry.page.id, origin: entry.origin })\n const originals = new Map<KnowledgePage, OriginatedPage>()\n const pages = visiblePages.map((entry) => {\n const page: KnowledgePage = {\n ...entry.page,\n id: qualified(entry),\n outLinks: entry.page.outLinks.flatMap((link: string) => {\n // A malformed link is not a ranking edge; retain the page unchanged so\n // citation audit can still diagnose it without making retrieval unavailable.\n try {\n const reference = parseKnowledgeCitationReference(link)\n const resolution = resolveKnowledgeCitation(byId.get(reference.pageId) ?? [], reference)\n return resolution.resolved ? [qualified(resolution.resolved)] : []\n } catch (error) {\n if (error instanceof TypeError) return []\n throw error\n }\n }),\n }\n originals.set(page, entry)\n return page\n })\n const ranked = searchKnowledgePages(pages, question, {\n limit,\n excludeInvalidated,\n ...(options.tags === undefined ? {} : { tags: options.tags }),\n ...(options.kinds === undefined ? {} : { kinds: options.kinds }),\n }).map((hit) => {\n const entry = originals.get(hit.page)!\n const candidates = byId.get(entry.page.id)!\n const reference = {\n pageId: entry.page.id,\n ...(candidates.length === 1 &&\n formatKnowledgeCitationReference({ pageId: entry.page.id }) === entry.page.id\n ? {}\n : { origin: entry.origin }),\n }\n // The whole visible chain determines ambiguity, not just this query's filtered hits.\n // Reusing one id within the SAME origin cannot be repaired with a qualifier.\n assertKnowledgeCitationsResolved(candidates, [reference])\n return {\n ...hit,\n page: entry.page,\n origin: entry.origin,\n citationId: formatKnowledgeCitationReference(reference),\n }\n })\n\n const hits: (KnowledgeSearchHit & OriginatedKnowledgeSearchResult)[] = []\n const lines: string[] = []\n let length = 0\n for (const hit of ranked) {\n const line = briefLine(hit)\n const next = length === 0 ? line.length : length + 1 + line.length\n if (maxChars !== undefined && next > maxChars) break\n hits.push(hit)\n lines.push(line)\n length = next\n }\n\n return Object.freeze({\n question: question.trim(),\n retrieverId: KNOWLEDGE_SEARCH_RETRIEVER_ID,\n retrieverConfigDigest: canonicalCandidateDigest({\n limit,\n excludeInvalidated,\n tags: options.tags === undefined ? null : [...options.tags],\n kinds: options.kinds === undefined ? null : [...options.kinds],\n maxChars: maxChars ?? null,\n }),\n hits: Object.freeze(hits),\n citationIds: Object.freeze(hits.map((hit) => hit.citationId)),\n results: Object.freeze(hits.map((hit) => Object.freeze(hit))),\n text: lines.join('\\n'),\n })\n}\n\nfunction briefLine(hit: KnowledgeSearchHit): string {\n const snippet = hit.snippet.replace(/\\s+/g, ' ').trim()\n return snippet === ''\n ? `- [${hit.citationId}] ${hit.page.title}`\n : `- [${hit.citationId}] ${hit.page.title} — ${snippet}`\n}\n","import {\n canonicalCandidateBytes,\n canonicalCandidateDigest,\n type Sha256Digest,\n sha256Bytes,\n sha256DigestSchema,\n} from '@tangle-network/agent-interface'\nimport type {\n KnowledgeVisibilityArtifactRef,\n KnowledgeVisibilityRef,\n KnowledgeVisibilitySnapshot,\n KnowledgeVisibilitySnapshotEntry,\n} from './knowledge-use-receipts'\nimport type { OriginatedPage, PageOrigin } from './run-scoped'\nimport type { KnowledgePage } from './types'\n\nexport const KNOWLEDGE_USE_RECEIPT_SCHEMA_VERSION = '2.0.0' as const\n\nexport const KNOWLEDGE_RECEIPT_DIGEST_ALGORITHM = 'rfc8785-sha256' as const\n\n/** Stable content identity for one exact knowledge page. */\nexport function knowledgePageDigest(page: KnowledgePage): Sha256Digest {\n validateKnowledgePage(page)\n return canonicalCandidateDigest({\n id: page.id,\n path: page.path,\n title: page.title,\n text: page.text,\n frontmatter: page.frontmatter,\n sourceIds: [...page.sourceIds],\n tags: [...page.tags],\n outLinks: [...page.outLinks],\n contradicts: [...(page.contradicts ?? [])],\n invalidation: page.invalidation ?? null,\n })\n}\n\n/** Snapshot the exact ordered current/ancestor/shared page view. */\nexport function createKnowledgeVisibilitySnapshot(\n visiblePages: readonly OriginatedPage[],\n): KnowledgeVisibilitySnapshot {\n if (!Array.isArray(visiblePages)) {\n throw new TypeError('knowledge visibility must be an array')\n }\n const identities = new Set<string>()\n const entries = visiblePages.map((entry, position) => {\n if (!entry || typeof entry !== 'object') {\n throw new TypeError(`knowledge visibility[${position}] must be an originated page`)\n }\n const origin = validateOrigin(entry.origin, `knowledge visibility[${position}].origin`)\n validateKnowledgePage(entry.page)\n const identity = visibilityIdentity(origin, entry.page.path)\n if (identities.has(identity)) {\n throw new Error(\n `knowledge visibility repeats path '${entry.page.path}' at origin '${origin}'`,\n )\n }\n identities.add(identity)\n return Object.freeze({\n position,\n pageId: entry.page.id,\n origin,\n path: entry.page.path,\n pageDigest: knowledgePageDigest(entry.page),\n sourceIds: Object.freeze([...entry.page.sourceIds]),\n invalidated: entry.page.invalidation !== undefined,\n })\n })\n const material = visibilityMaterial(entries)\n const snapshot: KnowledgeVisibilitySnapshot = Object.freeze({\n ...material,\n snapshotDigest: canonicalCandidateDigest(material),\n entries: Object.freeze(entries),\n })\n visibilityIndexes.set(snapshot, indexVisibility(snapshot))\n return snapshot\n}\n\n/**\n * Verify a snapshot's schema and canonical digest. The check runs once per\n * snapshot object; later calls with the same object are free.\n */\nexport function verifyKnowledgeVisibilitySnapshot(\n snapshot: KnowledgeVisibilitySnapshot,\n): KnowledgeVisibilitySnapshot {\n return visibilityIndexOf(snapshot).snapshot\n}\n\n/** Canonical bytes of a verified snapshot, for durable storage. */\nexport function encodeKnowledgeVisibilitySnapshot(\n snapshot: KnowledgeVisibilitySnapshot,\n): Uint8Array {\n const verified = verifyKnowledgeVisibilitySnapshot(snapshot)\n return canonicalCandidateBytes({\n schemaVersion: verified.schemaVersion,\n digestAlgorithm: verified.digestAlgorithm,\n snapshotDigest: verified.snapshotDigest,\n entries: visibilityMaterial(verified.entries).entries,\n })\n}\n\n/** Parse stored snapshot bytes and verify their schema and digest. */\nexport function decodeKnowledgeVisibilitySnapshot(bytes: Uint8Array): KnowledgeVisibilitySnapshot {\n if (!(bytes instanceof Uint8Array)) {\n throw new TypeError('knowledge visibility snapshot bytes must be a Uint8Array')\n }\n let parsed: unknown\n try {\n parsed = JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(bytes))\n } catch (error) {\n throw new Error(\n `knowledge visibility snapshot bytes are not JSON: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new TypeError('knowledge visibility snapshot must be an object')\n }\n const candidate = parsed as Record<string, unknown>\n if (!Array.isArray(candidate.entries)) {\n throw new TypeError('knowledge visibility snapshot entries must be an array')\n }\n const snapshot = Object.freeze({\n schemaVersion: candidate.schemaVersion as KnowledgeVisibilitySnapshot['schemaVersion'],\n digestAlgorithm: candidate.digestAlgorithm as KnowledgeVisibilitySnapshot['digestAlgorithm'],\n snapshotDigest: digest(candidate.snapshotDigest, 'knowledge visibility snapshotDigest'),\n entries: Object.freeze(\n candidate.entries.map((entry: unknown, position: number) => {\n if (!entry || typeof entry !== 'object') {\n throw new TypeError(`knowledge visibility[${position}] must be an object`)\n }\n const value = entry as Record<string, unknown>\n if (!Array.isArray(value.sourceIds)) {\n throw new TypeError(`knowledge visibility[${position}].sourceIds must be an array`)\n }\n return Object.freeze({\n position: value.position as number,\n pageId: value.pageId as string,\n origin: value.origin as PageOrigin,\n path: value.path as string,\n pageDigest: value.pageDigest as Sha256Digest,\n sourceIds: Object.freeze([...(value.sourceIds as string[])]),\n invalidated: value.invalidated as boolean,\n })\n }),\n ),\n })\n return verifyKnowledgeVisibilitySnapshot(snapshot)\n}\n\n/** Locator for snapshot bytes stored at `uri`. */\nexport function knowledgeVisibilityArtifactRef(input: {\n uri: string\n bytes: Uint8Array\n}): KnowledgeVisibilityArtifactRef {\n if (!input || typeof input !== 'object' || !(input.bytes instanceof Uint8Array)) {\n throw new TypeError('knowledge visibility artifact bytes must be a Uint8Array')\n }\n if (input.bytes.byteLength === 0) {\n throw new TypeError('knowledge visibility artifact bytes must not be empty')\n }\n return Object.freeze({\n uri: nonEmpty(input.uri, 'knowledge visibility artifact uri'),\n digest: sha256Bytes(input.bytes),\n byteLength: input.bytes.byteLength,\n })\n}\n\nexport interface VisibilityIndex {\n readonly snapshot: KnowledgeVisibilitySnapshot\n readonly byIdentity: ReadonlyMap<string, KnowledgeVisibilitySnapshotEntry>\n}\n\n// One verification and one join index per snapshot object, so N retrievals\n// over one view cost O(results) each after the first. A snapshot is a value:\n// a caller that needs a different view creates a new snapshot.\nconst visibilityIndexes = new WeakMap<KnowledgeVisibilitySnapshot, VisibilityIndex>()\n\nexport function visibilityIndexOf(snapshot: KnowledgeVisibilitySnapshot): VisibilityIndex {\n if (!snapshot || typeof snapshot !== 'object') {\n throw new TypeError('knowledge visibility snapshot is required')\n }\n const cached = visibilityIndexes.get(snapshot)\n if (cached !== undefined) return cached\n assertSchemaVersion(snapshot.schemaVersion, 'knowledge visibility')\n if (snapshot.digestAlgorithm !== KNOWLEDGE_RECEIPT_DIGEST_ALGORITHM) {\n throw new Error(\n `unsupported knowledge visibility digestAlgorithm '${snapshot.digestAlgorithm}'`,\n )\n }\n if (!Array.isArray(snapshot.entries)) {\n throw new TypeError('knowledge visibility snapshot entries must be an array')\n }\n const expected = canonicalCandidateDigest(visibilityMaterial(snapshot.entries))\n if (expected !== digest(snapshot.snapshotDigest, 'knowledge visibility snapshotDigest')) {\n throw new Error('knowledge visibility snapshot digest mismatch')\n }\n const index = indexVisibility(snapshot)\n visibilityIndexes.set(snapshot, index)\n return index\n}\n\nfunction indexVisibility(snapshot: KnowledgeVisibilitySnapshot): VisibilityIndex {\n const byIdentity = new Map<string, KnowledgeVisibilitySnapshotEntry>()\n for (const entry of snapshot.entries) {\n const identity = visibilityIdentity(entry.origin, entry.path)\n if (byIdentity.has(identity)) {\n throw new Error(\n `knowledge visibility repeats path '${entry.path}' at origin '${entry.origin}'`,\n )\n }\n byIdentity.set(identity, entry)\n }\n return { snapshot, byIdentity }\n}\n\nexport function visibilityIdentity(origin: PageOrigin, path: string): string {\n return `${origin}\\u0000${path}`\n}\n\nexport function assertSchemaVersion(value: unknown, label: string): void {\n if (value === KNOWLEDGE_USE_RECEIPT_SCHEMA_VERSION) return\n const hint =\n value === '1.0.0'\n ? '; 1.0.0 records embed the visibility snapshot and have no reader, create a 2.0.0 record from the snapshot'\n : ''\n throw new Error(`unsupported ${label} schemaVersion '${String(value)}'${hint}`)\n}\n\nfunction visibilityMaterial(entries: readonly KnowledgeVisibilitySnapshotEntry[]) {\n return {\n schemaVersion: KNOWLEDGE_USE_RECEIPT_SCHEMA_VERSION,\n digestAlgorithm: KNOWLEDGE_RECEIPT_DIGEST_ALGORITHM,\n entries: entries.map((entry, position) => {\n if (!entry || typeof entry !== 'object') {\n throw new TypeError(`knowledge visibility[${position}] must be an object`)\n }\n if (entry.position !== position) {\n throw new Error(\n `knowledge visibility position mismatch: expected ${position}, observed ${entry.position}`,\n )\n }\n if (!Array.isArray(entry.sourceIds)) {\n throw new TypeError(`knowledge visibility[${position}].sourceIds must be an array`)\n }\n return {\n position,\n pageId: nonEmpty(entry.pageId, `knowledge visibility[${position}].pageId`),\n origin: validateOrigin(entry.origin, `knowledge visibility[${position}].origin`),\n path: nonEmpty(entry.path, `knowledge visibility[${position}].path`),\n pageDigest: digest(entry.pageDigest, `knowledge visibility[${position}].pageDigest`),\n sourceIds: entry.sourceIds.map((sourceId, sourceIndex) =>\n nonEmpty(sourceId, `knowledge visibility[${position}].sourceIds[${sourceIndex}]`),\n ),\n invalidated: Boolean(entry.invalidated),\n }\n }),\n } as const\n}\n\nexport function normalizeVisibilityRef(input: KnowledgeVisibilityRef): KnowledgeVisibilityRef {\n if (!input || typeof input !== 'object') {\n throw new TypeError('knowledge retrieval visibility reference is required')\n }\n if (!Number.isSafeInteger(input.pageCount) || input.pageCount < 0) {\n throw new TypeError('knowledge retrieval visibility pageCount must be a non-negative integer')\n }\n return Object.freeze({\n snapshotDigest: digest(input.snapshotDigest, 'knowledge retrieval visibility snapshotDigest'),\n pageCount: input.pageCount,\n ...(input.artifact === undefined\n ? {}\n : {\n artifact: normalizeVisibilityArtifact(\n input.artifact,\n 'knowledge retrieval visibility artifact',\n ),\n }),\n })\n}\n\nexport function normalizeVisibilityArtifact(\n input: KnowledgeVisibilityArtifactRef,\n label: string,\n): KnowledgeVisibilityArtifactRef {\n if (!input || typeof input !== 'object') throw new TypeError(`${label} must be an object`)\n if (!Number.isSafeInteger(input.byteLength) || input.byteLength < 1) {\n throw new TypeError(`${label} byteLength must be a positive integer`)\n }\n return Object.freeze({\n uri: nonEmpty(input.uri, `${label} uri`),\n digest: digest(input.digest, `${label} digest`),\n byteLength: input.byteLength,\n })\n}\n\nexport function validateKnowledgePage(page: KnowledgePage): void {\n if (!page || typeof page !== 'object') throw new TypeError('knowledge page must be an object')\n nonEmpty(page.id, 'knowledge page id')\n nonEmpty(page.path, 'knowledge page path')\n nonEmpty(page.title, 'knowledge page title')\n if (typeof page.text !== 'string') throw new TypeError('knowledge page text must be a string')\n if (\n !page.frontmatter ||\n typeof page.frontmatter !== 'object' ||\n Array.isArray(page.frontmatter)\n ) {\n throw new TypeError('knowledge page frontmatter must be an object')\n }\n for (const [name, values] of [\n ['sourceIds', page.sourceIds],\n ['tags', page.tags],\n ['outLinks', page.outLinks],\n ] as const) {\n if (!Array.isArray(values) || values.some((value) => typeof value !== 'string')) {\n throw new TypeError(`knowledge page ${name} must be a string array`)\n }\n }\n}\n\nexport function validateOrigin(value: unknown, label: string): PageOrigin {\n if (value === 'here' || value === 'shared') return value\n if (\n typeof value === 'string' &&\n value.startsWith('inherited:') &&\n value.slice('inherited:'.length).trim().length > 0\n ) {\n return value as PageOrigin\n }\n throw new TypeError(`${label} is invalid: ${String(value)}`)\n}\n\nexport function digest(value: unknown, label: string): Sha256Digest {\n const parsed = sha256DigestSchema.safeParse(value)\n if (!parsed.success) throw new TypeError(`${label} must be a lowercase sha256 digest`)\n return parsed.data\n}\n\nexport function nonEmpty(value: unknown, label: string): string {\n if (typeof value !== 'string' || value.trim().length === 0) {\n throw new TypeError(`${label} must be a non-empty string`)\n }\n return value.trim()\n}\n","import type { EvidenceRef } from '@tangle-network/agent-eval/analyst'\nimport {\n canonicalCandidateDigest,\n type Sha256Digest,\n sha256Bytes,\n} from '@tangle-network/agent-interface'\nimport {\n assertSchemaVersion,\n createKnowledgeVisibilitySnapshot,\n decodeKnowledgeVisibilitySnapshot,\n digest,\n KNOWLEDGE_RECEIPT_DIGEST_ALGORITHM,\n KNOWLEDGE_USE_RECEIPT_SCHEMA_VERSION,\n knowledgePageDigest,\n nonEmpty,\n normalizeVisibilityArtifact,\n normalizeVisibilityRef,\n type VisibilityIndex,\n validateKnowledgePage,\n validateOrigin,\n visibilityIdentity,\n visibilityIndexOf,\n} from './knowledge-visibility'\nimport type { OriginatedPage, PageOrigin } from './run-scoped'\nimport type { KnowledgeSearchResult } from './types'\n\nexport {\n createKnowledgeVisibilitySnapshot,\n decodeKnowledgeVisibilitySnapshot,\n encodeKnowledgeVisibilitySnapshot,\n KNOWLEDGE_RECEIPT_DIGEST_ALGORITHM,\n KNOWLEDGE_USE_RECEIPT_SCHEMA_VERSION,\n knowledgePageDigest,\n knowledgeVisibilityArtifactRef,\n verifyKnowledgeVisibilitySnapshot,\n} from './knowledge-visibility'\nexport interface KnowledgeVisibilitySnapshotEntry {\n readonly position: number\n readonly pageId: string\n readonly origin: PageOrigin\n readonly path: string\n readonly pageDigest: Sha256Digest\n readonly sourceIds: readonly string[]\n readonly invalidated: boolean\n}\n\n/** Exact ordered page visibility presented to one retrieval operation. */\nexport interface KnowledgeVisibilitySnapshot {\n readonly schemaVersion: typeof KNOWLEDGE_USE_RECEIPT_SCHEMA_VERSION\n readonly digestAlgorithm: typeof KNOWLEDGE_RECEIPT_DIGEST_ALGORITHM\n readonly snapshotDigest: Sha256Digest\n readonly entries: readonly KnowledgeVisibilitySnapshotEntry[]\n}\n\n/** Content-addressed locator of the stored bytes of one visibility snapshot. */\nexport interface KnowledgeVisibilityArtifactRef {\n readonly uri: string\n /** Digest of the stored bytes, as `knowledgeVisibilityArtifactRef` computes it. */\n readonly digest: Sha256Digest\n readonly byteLength: number\n}\n\n/**\n * Compact identity of one exact visibility snapshot. The snapshot bytes live in\n * the artifact the reference names, or in another durable record the caller\n * keeps; the receipt carries only this reference.\n */\nexport interface KnowledgeVisibilityRef {\n readonly snapshotDigest: Sha256Digest\n readonly pageCount: number\n readonly artifact?: KnowledgeVisibilityArtifactRef\n}\n\nexport interface KnowledgeRetrieverIdentity {\n /** Stable implementation name, for example `token-overlap-v1`. */\n readonly id: string\n /** Published or application-defined implementation version. */\n readonly version: string\n /** Exact identity of every retrieval setting not represented elsewhere. */\n readonly configDigest: Sha256Digest\n}\n\nexport interface OriginatedKnowledgeSearchResult extends KnowledgeSearchResult {\n readonly origin: PageOrigin\n}\n\nexport interface KnowledgeRetrievalResultReceipt {\n readonly rank: number\n readonly pageId: string\n readonly origin: PageOrigin\n readonly path: string\n readonly pageDigest: Sha256Digest\n readonly rrfScore: number\n readonly normalizedScore: number\n readonly snippet: string\n readonly reasons: readonly string[]\n}\n\nexport type KnowledgeReceiptAttributeValue = string | number | boolean | null\n\n/**\n * Immutable proof of what one actor could see and what its retriever returned.\n * Final prose is not evidence that retrieval happened; this receipt is.\n */\nexport interface KnowledgeRetrievalReceipt {\n readonly schemaVersion: typeof KNOWLEDGE_USE_RECEIPT_SCHEMA_VERSION\n readonly kind: 'knowledge-retrieval'\n readonly digestAlgorithm: typeof KNOWLEDGE_RECEIPT_DIGEST_ALGORITHM\n readonly receiptDigest: Sha256Digest\n readonly createdAt: string\n readonly runId: string\n readonly actorId?: string\n readonly profileDigest?: Sha256Digest\n readonly executionRef?: Sha256Digest\n readonly query: string\n readonly retriever: KnowledgeRetrieverIdentity\n readonly visibility: KnowledgeVisibilityRef\n readonly results: readonly KnowledgeRetrievalResultReceipt[]\n readonly evidenceRefs: readonly EvidenceRef[]\n readonly attributes: Readonly<Record<string, KnowledgeReceiptAttributeValue>>\n}\n\nexport interface CreateKnowledgeRetrievalReceiptInput {\n readonly runId: string\n readonly actorId?: string\n readonly profileDigest?: Sha256Digest\n readonly executionRef?: Sha256Digest\n readonly query: string\n readonly retriever: KnowledgeRetrieverIdentity\n /**\n * The snapshot the retriever searched, created once with\n * `createKnowledgeVisibilitySnapshot` and reused for every retrieval over the\n * same view. Results join against its entries; the receipt stores only its\n * reference.\n */\n readonly visibility: KnowledgeVisibilitySnapshot\n /** Where the snapshot bytes are stored, when the caller has persisted them. */\n readonly visibilityArtifact?: KnowledgeVisibilityArtifactRef\n readonly results: readonly OriginatedKnowledgeSearchResult[]\n readonly evidenceRefs?: readonly EvidenceRef[]\n readonly attributes?: Readonly<Record<string, KnowledgeReceiptAttributeValue>>\n readonly createdAt?: Date | string\n}\n\n/**\n * Returns the stored bytes of the artifact, or `undefined` when nothing is\n * stored at its uri. A thrown error is reported as a load failure.\n */\nexport type KnowledgeVisibilityArtifactLoader = (\n artifact: KnowledgeVisibilityArtifactRef,\n) => Promise<Uint8Array | undefined> | Uint8Array | undefined\n\nexport type KnowledgeVisibilityUnavailableReason =\n | 'no-artifact-reference'\n | 'missing'\n | 'load-failed'\n\n/**\n * The visibility snapshot a receipt references could not be obtained, so the\n * result-to-visibility join cannot be proven. This is distinct from a snapshot\n * that loads and fails to match.\n */\nexport class KnowledgeVisibilityUnavailableError extends Error {\n readonly reason: KnowledgeVisibilityUnavailableReason\n readonly snapshotDigest: Sha256Digest\n readonly uri?: string\n\n constructor(input: {\n reason: KnowledgeVisibilityUnavailableReason\n snapshotDigest: Sha256Digest\n uri?: string\n cause?: unknown\n }) {\n const where = input.uri === undefined ? '' : ` at '${input.uri}'`\n const detail = {\n 'no-artifact-reference': 'the receipt carries no artifact reference',\n missing: `no artifact is stored${where}`,\n 'load-failed': `the artifact${where} could not be loaded`,\n }[input.reason]\n super(\n `knowledge visibility snapshot ${input.snapshotDigest} is unavailable: ${detail}`,\n input.cause === undefined ? undefined : { cause: input.cause },\n )\n this.name = 'KnowledgeVisibilityUnavailableError'\n this.reason = input.reason\n this.snapshotDigest = input.snapshotDigest\n if (input.uri !== undefined) this.uri = input.uri\n }\n}\n\nexport type KnowledgeUseRelation =\n | 'supports'\n | 'contradicts'\n | 'extends'\n | 'rederives'\n | 'background'\n\nexport type KnowledgeConsumerKind =\n | 'decision'\n | 'artifact'\n | 'experiment'\n | 'candidate'\n | 'message'\n | 'other'\n\nexport interface KnowledgeConsumerRef {\n readonly kind: KnowledgeConsumerKind\n readonly uri: string\n readonly digest?: Sha256Digest\n}\n\nexport interface KnowledgeUsedResult {\n readonly rank: number\n readonly pageId: string\n readonly origin: PageOrigin\n readonly path: string\n readonly pageDigest: Sha256Digest\n}\n\n/**\n * Immutable proof that one retrieved page was selected for a downstream\n * decision, artifact, experiment, candidate, or message.\n */\nexport interface KnowledgeUseReceipt {\n readonly schemaVersion: typeof KNOWLEDGE_USE_RECEIPT_SCHEMA_VERSION\n readonly kind: 'knowledge-use'\n readonly digestAlgorithm: typeof KNOWLEDGE_RECEIPT_DIGEST_ALGORITHM\n readonly receiptDigest: Sha256Digest\n readonly createdAt: string\n readonly runId: string\n readonly actorId?: string\n readonly profileDigest?: Sha256Digest\n readonly executionRef?: Sha256Digest\n readonly retrievalReceiptDigest: Sha256Digest\n readonly used: KnowledgeUsedResult\n readonly relation: KnowledgeUseRelation\n readonly consumer: KnowledgeConsumerRef\n readonly evidenceRefs: readonly EvidenceRef[]\n readonly attributes: Readonly<Record<string, KnowledgeReceiptAttributeValue>>\n}\n\nexport interface CreateKnowledgeUseReceiptInput {\n readonly retrieval: KnowledgeRetrievalReceipt\n /** Exact one-based rank from the retrieval receipt. */\n readonly selectedRank: number\n readonly relation: KnowledgeUseRelation\n readonly consumer: KnowledgeConsumerRef\n readonly evidenceRefs?: readonly EvidenceRef[]\n readonly attributes?: Readonly<Record<string, KnowledgeReceiptAttributeValue>>\n readonly createdAt?: Date | string\n}\n\n/**\n * Why a retrieval influenced nothing.\n *\n * `irrelevant` means the returned pages did not bear on the question.\n * `no-use` means they did bear on it and the consumer still used none of them.\n */\nexport type KnowledgeRetrievalDispositionRelation = 'irrelevant' | 'no-use'\n\n/**\n * Immutable proof that one retrieval led to no use.\n *\n * A use receipt requires a selected rank, so a retrieval that influenced\n * nothing would otherwise leave no record at all, and \"no evidence of use\" and\n * \"evidence of no use\" would look identical in the ledger.\n */\nexport interface KnowledgeRetrievalDisposition {\n readonly schemaVersion: typeof KNOWLEDGE_USE_RECEIPT_SCHEMA_VERSION\n readonly kind: 'knowledge-retrieval-disposition'\n readonly digestAlgorithm: typeof KNOWLEDGE_RECEIPT_DIGEST_ALGORITHM\n readonly receiptDigest: Sha256Digest\n readonly createdAt: string\n readonly runId: string\n readonly actorId?: string\n readonly profileDigest?: Sha256Digest\n readonly executionRef?: Sha256Digest\n readonly retrievalReceiptDigest: Sha256Digest\n readonly relation: KnowledgeRetrievalDispositionRelation\n readonly consumer: KnowledgeConsumerRef\n readonly evidenceRefs: readonly EvidenceRef[]\n readonly attributes: Readonly<Record<string, KnowledgeReceiptAttributeValue>>\n}\n\nexport interface CreateKnowledgeRetrievalDispositionInput {\n readonly retrieval: KnowledgeRetrievalReceipt\n readonly relation: KnowledgeRetrievalDispositionRelation\n readonly consumer: KnowledgeConsumerRef\n readonly evidenceRefs?: readonly EvidenceRef[]\n readonly attributes?: Readonly<Record<string, KnowledgeReceiptAttributeValue>>\n readonly createdAt?: Date | string\n}\n\n/**\n * Create a retrieval receipt over a precomputed snapshot. Every result must\n * occur in the snapshot with the same page id and bytes; the receipt stores the\n * snapshot's reference, not its entries.\n */\nexport function createKnowledgeRetrievalReceipt(\n input: CreateKnowledgeRetrievalReceiptInput,\n): KnowledgeRetrievalReceipt {\n if (!input || typeof input !== 'object') {\n throw new TypeError('knowledge retrieval receipt input is required')\n }\n const runId = nonEmpty(input.runId, 'knowledge retrieval runId')\n const actorId = optionalText(input.actorId, 'knowledge retrieval actorId')\n const profileDigest = optionalDigest(input.profileDigest, 'knowledge retrieval profileDigest')\n const executionRef = optionalDigest(input.executionRef, 'knowledge retrieval executionRef')\n const query = nonEmpty(input.query, 'knowledge retrieval query')\n const retriever = normalizeRetriever(input.retriever)\n const index = visibilityIndexOf(input.visibility)\n const artifact =\n input.visibilityArtifact === undefined\n ? undefined\n : normalizeVisibilityArtifact(\n input.visibilityArtifact,\n 'knowledge retrieval visibilityArtifact',\n )\n const visibility: KnowledgeVisibilityRef = Object.freeze({\n snapshotDigest: index.snapshot.snapshotDigest,\n pageCount: index.snapshot.entries.length,\n ...(artifact === undefined ? {} : { artifact }),\n })\n const results = normalizeRetrievalResults(input.results, index)\n const evidenceRefs = normalizeEvidenceRefs(input.evidenceRefs ?? [])\n const attributes = normalizeAttributes(input.attributes ?? {})\n const createdAt = isoTimestamp(input.createdAt, 'knowledge retrieval createdAt')\n const material = retrievalMaterial({\n createdAt,\n runId,\n actorId,\n profileDigest,\n executionRef,\n query,\n retriever,\n visibility,\n results,\n evidenceRefs,\n attributes,\n })\n return Object.freeze({\n ...material,\n receiptDigest: canonicalCandidateDigest(material),\n })\n}\n\n/**\n * Verify the receipt's schema, canonical digest, rank continuity, finite\n * scores, and well-formed visibility reference. This proves what the receipt\n * says; it does not prove that the results occur in the referenced snapshot.\n * Use `assertKnowledgeRetrievalMatchesVisibility` or\n * `assertKnowledgeRetrievalMatchesVisibilityArtifact` for that join.\n */\nexport function verifyKnowledgeRetrievalReceipt(\n receipt: KnowledgeRetrievalReceipt,\n): KnowledgeRetrievalReceipt {\n if (!receipt || typeof receipt !== 'object') {\n throw new TypeError('knowledge retrieval receipt is required')\n }\n assertSchemaVersion(receipt.schemaVersion, 'knowledge retrieval')\n if (receipt.kind !== 'knowledge-retrieval') {\n throw new Error(`knowledge retrieval receipt kind must be 'knowledge-retrieval'`)\n }\n if (receipt.digestAlgorithm !== KNOWLEDGE_RECEIPT_DIGEST_ALGORITHM) {\n throw new Error(`unsupported knowledge retrieval digestAlgorithm '${receipt.digestAlgorithm}'`)\n }\n const visibility = normalizeVisibilityRef(receipt.visibility)\n validateReceiptResultShape(receipt.results, visibility.pageCount)\n const material = retrievalMaterial({\n createdAt: isoTimestamp(receipt.createdAt, 'knowledge retrieval createdAt'),\n runId: nonEmpty(receipt.runId, 'knowledge retrieval runId'),\n actorId: optionalText(receipt.actorId, 'knowledge retrieval actorId'),\n profileDigest: optionalDigest(receipt.profileDigest, 'knowledge retrieval profileDigest'),\n executionRef: optionalDigest(receipt.executionRef, 'knowledge retrieval executionRef'),\n query: nonEmpty(receipt.query, 'knowledge retrieval query'),\n retriever: normalizeRetriever(receipt.retriever),\n visibility,\n results: receipt.results,\n evidenceRefs: normalizeEvidenceRefs(receipt.evidenceRefs),\n attributes: normalizeAttributes(receipt.attributes),\n })\n const expected = canonicalCandidateDigest(material)\n if (expected !== receipt.receiptDigest) {\n throw new Error('knowledge retrieval receipt digest mismatch')\n }\n return receipt\n}\n\n/**\n * Prove that the receipt references exactly this snapshot and that every\n * returned result occurs in it with the same page id and bytes. Pass the\n * snapshot itself, or the originated pages to snapshot them first.\n */\nexport function assertKnowledgeRetrievalMatchesVisibility(\n receipt: KnowledgeRetrievalReceipt,\n visibility: KnowledgeVisibilitySnapshot | readonly OriginatedPage[],\n): void {\n verifyKnowledgeRetrievalReceipt(receipt)\n const index = visibilityIndexOf(\n Array.isArray(visibility)\n ? createKnowledgeVisibilitySnapshot(visibility)\n : (visibility as KnowledgeVisibilitySnapshot),\n )\n assertReceiptJoinsVisibility(receipt, index)\n}\n\n/**\n * Load the snapshot artifact the receipt references, prove the stored bytes\n * match the reference, and prove every returned result occurs in the decoded\n * snapshot. A snapshot that cannot be obtained raises\n * `KnowledgeVisibilityUnavailableError`; it is never treated as empty.\n */\nexport async function assertKnowledgeRetrievalMatchesVisibilityArtifact(\n receipt: KnowledgeRetrievalReceipt,\n loadArtifact: KnowledgeVisibilityArtifactLoader,\n): Promise<KnowledgeVisibilitySnapshot> {\n verifyKnowledgeRetrievalReceipt(receipt)\n if (typeof loadArtifact !== 'function') {\n throw new TypeError('knowledge visibility artifact loader must be a function')\n }\n const reference = receipt.visibility\n if (reference.artifact === undefined) {\n throw new KnowledgeVisibilityUnavailableError({\n reason: 'no-artifact-reference',\n snapshotDigest: reference.snapshotDigest,\n })\n }\n const artifact = reference.artifact\n let bytes: Uint8Array | undefined\n try {\n bytes = await loadArtifact(artifact)\n } catch (error) {\n throw new KnowledgeVisibilityUnavailableError({\n reason: 'load-failed',\n snapshotDigest: reference.snapshotDigest,\n uri: artifact.uri,\n cause: error,\n })\n }\n if (bytes === undefined) {\n throw new KnowledgeVisibilityUnavailableError({\n reason: 'missing',\n snapshotDigest: reference.snapshotDigest,\n uri: artifact.uri,\n })\n }\n if (!(bytes instanceof Uint8Array)) {\n throw new TypeError(`knowledge visibility artifact '${artifact.uri}' loaded a non-byte value`)\n }\n if (bytes.byteLength !== artifact.byteLength) {\n throw new Error(\n `knowledge visibility artifact '${artifact.uri}' byteLength mismatch: expected ${artifact.byteLength}, observed ${bytes.byteLength}`,\n )\n }\n if (sha256Bytes(bytes) !== artifact.digest) {\n throw new Error(`knowledge visibility artifact '${artifact.uri}' digest mismatch`)\n }\n const snapshot = decodeKnowledgeVisibilitySnapshot(bytes)\n if (snapshot.snapshotDigest !== reference.snapshotDigest) {\n throw new Error(\n `knowledge visibility artifact '${artifact.uri}' holds snapshot ${snapshot.snapshotDigest}, not ${reference.snapshotDigest}`,\n )\n }\n assertReceiptJoinsVisibility(receipt, visibilityIndexOf(snapshot))\n return snapshot\n}\n\n/** Create a downstream-use receipt for one exact ranked result. */\nexport function createKnowledgeUseReceipt(\n input: CreateKnowledgeUseReceiptInput,\n): KnowledgeUseReceipt {\n if (!input || typeof input !== 'object') {\n throw new TypeError('knowledge use receipt input is required')\n }\n const retrieval = verifyKnowledgeRetrievalReceipt(input.retrieval)\n if (!Number.isSafeInteger(input.selectedRank) || input.selectedRank < 1) {\n throw new TypeError('knowledge use selectedRank must be a positive safe integer')\n }\n const selected = retrieval.results.find((result) => result.rank === input.selectedRank)\n if (!selected) {\n throw new Error(\n `knowledge use selectedRank ${input.selectedRank} was not returned by retrieval ${retrieval.receiptDigest}`,\n )\n }\n const relation = validateUseRelation(input.relation)\n const consumer = normalizeConsumer(input.consumer)\n const evidenceRefs = normalizeEvidenceRefs(input.evidenceRefs ?? [])\n const attributes = normalizeAttributes(input.attributes ?? {})\n const createdAt = isoTimestamp(input.createdAt, 'knowledge use createdAt')\n const used = Object.freeze({\n rank: selected.rank,\n pageId: selected.pageId,\n origin: selected.origin,\n path: selected.path,\n pageDigest: selected.pageDigest,\n })\n const material = useMaterial({\n createdAt,\n retrieval,\n used,\n relation,\n consumer,\n evidenceRefs,\n attributes,\n })\n return Object.freeze({\n ...material,\n receiptDigest: canonicalCandidateDigest(material),\n })\n}\n\n/** Verify one use receipt against the exact retrieval that authorized it. */\nexport function verifyKnowledgeUseReceipt(\n receipt: KnowledgeUseReceipt,\n retrieval: KnowledgeRetrievalReceipt,\n): KnowledgeUseReceipt {\n if (!receipt || typeof receipt !== 'object') {\n throw new TypeError('knowledge use receipt is required')\n }\n const verifiedRetrieval = verifyKnowledgeRetrievalReceipt(retrieval)\n assertSchemaVersion(receipt.schemaVersion, 'knowledge use')\n if (receipt.kind !== 'knowledge-use') {\n throw new Error(`knowledge use receipt kind must be 'knowledge-use'`)\n }\n if (receipt.digestAlgorithm !== KNOWLEDGE_RECEIPT_DIGEST_ALGORITHM) {\n throw new Error(`unsupported knowledge use digestAlgorithm '${receipt.digestAlgorithm}'`)\n }\n if (receipt.retrievalReceiptDigest !== verifiedRetrieval.receiptDigest) {\n throw new Error('knowledge use receipt references a different retrieval receipt')\n }\n const selected = verifiedRetrieval.results.find((result) => result.rank === receipt.used.rank)\n if (\n !selected ||\n selected.pageId !== receipt.used.pageId ||\n selected.origin !== receipt.used.origin ||\n selected.path !== receipt.used.path ||\n selected.pageDigest !== receipt.used.pageDigest\n ) {\n throw new Error('knowledge use receipt selected result does not match the retrieval receipt')\n }\n const material = useMaterial({\n createdAt: isoTimestamp(receipt.createdAt, 'knowledge use createdAt'),\n retrieval: verifiedRetrieval,\n used: receipt.used,\n relation: validateUseRelation(receipt.relation),\n consumer: normalizeConsumer(receipt.consumer),\n evidenceRefs: normalizeEvidenceRefs(receipt.evidenceRefs),\n attributes: normalizeAttributes(receipt.attributes),\n })\n const expected = canonicalCandidateDigest(material)\n if (expected !== receipt.receiptDigest) {\n throw new Error('knowledge use receipt digest mismatch')\n }\n return receipt\n}\n\n/** Record that one retrieval led to no use, with no rank to select. */\nexport function createKnowledgeRetrievalDisposition(\n input: CreateKnowledgeRetrievalDispositionInput,\n): KnowledgeRetrievalDisposition {\n if (!input || typeof input !== 'object') {\n throw new TypeError('knowledge retrieval disposition input is required')\n }\n const material = dispositionMaterial({\n createdAt: isoTimestamp(input.createdAt, 'knowledge retrieval disposition createdAt'),\n retrieval: verifyKnowledgeRetrievalReceipt(input.retrieval),\n relation: validateDispositionRelation(input.relation),\n consumer: normalizeConsumer(input.consumer),\n evidenceRefs: normalizeEvidenceRefs(input.evidenceRefs ?? []),\n attributes: normalizeAttributes(input.attributes ?? {}),\n })\n return Object.freeze({ ...material, receiptDigest: canonicalCandidateDigest(material) })\n}\n\n/** Verify one disposition against the exact retrieval that authorized it. */\nexport function verifyKnowledgeRetrievalDisposition(\n disposition: KnowledgeRetrievalDisposition,\n retrieval: KnowledgeRetrievalReceipt,\n): KnowledgeRetrievalDisposition {\n if (!disposition || typeof disposition !== 'object') {\n throw new TypeError('knowledge retrieval disposition is required')\n }\n const verifiedRetrieval = verifyKnowledgeRetrievalReceipt(retrieval)\n assertSchemaVersion(disposition.schemaVersion, 'knowledge retrieval disposition')\n if (disposition.kind !== 'knowledge-retrieval-disposition') {\n throw new Error(\n `knowledge retrieval disposition kind must be 'knowledge-retrieval-disposition'`,\n )\n }\n if (disposition.digestAlgorithm !== KNOWLEDGE_RECEIPT_DIGEST_ALGORITHM) {\n throw new Error(\n `unsupported knowledge retrieval disposition digestAlgorithm '${disposition.digestAlgorithm}'`,\n )\n }\n if (disposition.retrievalReceiptDigest !== verifiedRetrieval.receiptDigest) {\n throw new Error('knowledge retrieval disposition references a different retrieval receipt')\n }\n const material = dispositionMaterial({\n createdAt: isoTimestamp(disposition.createdAt, 'knowledge retrieval disposition createdAt'),\n retrieval: verifiedRetrieval,\n relation: validateDispositionRelation(disposition.relation),\n consumer: normalizeConsumer(disposition.consumer),\n evidenceRefs: normalizeEvidenceRefs(disposition.evidenceRefs),\n attributes: normalizeAttributes(disposition.attributes),\n })\n if (canonicalCandidateDigest(material) !== disposition.receiptDigest) {\n throw new Error('knowledge retrieval disposition digest mismatch')\n }\n return disposition\n}\n\nfunction assertReceiptJoinsVisibility(\n receipt: KnowledgeRetrievalReceipt,\n index: VisibilityIndex,\n): void {\n if (\n index.snapshot.snapshotDigest !== receipt.visibility.snapshotDigest ||\n index.snapshot.entries.length !== receipt.visibility.pageCount\n ) {\n throw new Error('knowledge retrieval receipt does not match the supplied visibility snapshot')\n }\n for (const result of receipt.results) {\n const entry = index.byIdentity.get(visibilityIdentity(result.origin, result.path))\n if (!entry || entry.pageId !== result.pageId || entry.pageDigest !== result.pageDigest) {\n throw new Error(\n `knowledge retrieval result rank ${result.rank} is not in the visibility snapshot`,\n )\n }\n }\n}\n\nfunction retrievalMaterial(input: {\n createdAt: string\n runId: string\n actorId?: string\n profileDigest?: Sha256Digest\n executionRef?: Sha256Digest\n query: string\n retriever: KnowledgeRetrieverIdentity\n visibility: KnowledgeVisibilityRef\n results: readonly KnowledgeRetrievalResultReceipt[]\n evidenceRefs: readonly EvidenceRef[]\n attributes: Readonly<Record<string, KnowledgeReceiptAttributeValue>>\n}) {\n return {\n schemaVersion: KNOWLEDGE_USE_RECEIPT_SCHEMA_VERSION,\n kind: 'knowledge-retrieval' as const,\n digestAlgorithm: KNOWLEDGE_RECEIPT_DIGEST_ALGORITHM,\n createdAt: input.createdAt,\n runId: input.runId,\n ...(input.actorId === undefined ? {} : { actorId: input.actorId }),\n ...(input.profileDigest === undefined ? {} : { profileDigest: input.profileDigest }),\n ...(input.executionRef === undefined ? {} : { executionRef: input.executionRef }),\n query: input.query,\n retriever: input.retriever,\n visibility: input.visibility,\n results: input.results,\n evidenceRefs: input.evidenceRefs,\n attributes: input.attributes,\n }\n}\n\n/**\n * The actor identity a downstream record inherits from the retrieval that\n * authorized it. A record that re-declared these could disagree with the\n * receipt it references.\n */\nfunction retrievalIdentity(retrieval: KnowledgeRetrievalReceipt) {\n return {\n runId: retrieval.runId,\n ...(retrieval.actorId === undefined ? {} : { actorId: retrieval.actorId }),\n ...(retrieval.profileDigest === undefined ? {} : { profileDigest: retrieval.profileDigest }),\n ...(retrieval.executionRef === undefined ? {} : { executionRef: retrieval.executionRef }),\n retrievalReceiptDigest: retrieval.receiptDigest,\n }\n}\n\nfunction useMaterial(input: {\n createdAt: string\n retrieval: KnowledgeRetrievalReceipt\n used: KnowledgeUsedResult\n relation: KnowledgeUseRelation\n consumer: KnowledgeConsumerRef\n evidenceRefs: readonly EvidenceRef[]\n attributes: Readonly<Record<string, KnowledgeReceiptAttributeValue>>\n}) {\n return {\n schemaVersion: KNOWLEDGE_USE_RECEIPT_SCHEMA_VERSION,\n kind: 'knowledge-use' as const,\n digestAlgorithm: KNOWLEDGE_RECEIPT_DIGEST_ALGORITHM,\n createdAt: input.createdAt,\n ...retrievalIdentity(input.retrieval),\n used: input.used,\n relation: input.relation,\n consumer: input.consumer,\n evidenceRefs: input.evidenceRefs,\n attributes: input.attributes,\n }\n}\n\nfunction dispositionMaterial(input: {\n createdAt: string\n retrieval: KnowledgeRetrievalReceipt\n relation: KnowledgeRetrievalDispositionRelation\n consumer: KnowledgeConsumerRef\n evidenceRefs: readonly EvidenceRef[]\n attributes: Readonly<Record<string, KnowledgeReceiptAttributeValue>>\n}) {\n return {\n schemaVersion: KNOWLEDGE_USE_RECEIPT_SCHEMA_VERSION,\n kind: 'knowledge-retrieval-disposition' as const,\n digestAlgorithm: KNOWLEDGE_RECEIPT_DIGEST_ALGORITHM,\n createdAt: input.createdAt,\n ...retrievalIdentity(input.retrieval),\n relation: input.relation,\n consumer: input.consumer,\n evidenceRefs: input.evidenceRefs,\n attributes: input.attributes,\n }\n}\n\nfunction validateDispositionRelation(\n value: KnowledgeRetrievalDispositionRelation,\n): KnowledgeRetrievalDispositionRelation {\n if (value !== 'irrelevant' && value !== 'no-use') {\n throw new TypeError(`knowledge retrieval disposition relation is invalid: ${String(value)}`)\n }\n return value\n}\n\nfunction normalizeRetrievalResults(\n results: readonly OriginatedKnowledgeSearchResult[],\n index: VisibilityIndex,\n): readonly KnowledgeRetrievalResultReceipt[] {\n if (!Array.isArray(results)) throw new TypeError('knowledge retrieval results must be an array')\n const seenRanks = new Set<number>()\n const seenPages = new Set<string>()\n const normalized = results.map((result, position) => {\n if (!result || typeof result !== 'object') {\n throw new TypeError(`knowledge retrieval results[${position}] must be an object`)\n }\n if (!Number.isSafeInteger(result.rank) || result.rank < 1) {\n throw new TypeError(`knowledge retrieval results[${position}].rank must be positive`)\n }\n if (seenRanks.has(result.rank)) {\n throw new Error(`knowledge retrieval repeats rank ${result.rank}`)\n }\n seenRanks.add(result.rank)\n const origin = validateOrigin(result.origin, `knowledge retrieval results[${position}].origin`)\n validateKnowledgePage(result.page)\n const identity = visibilityIdentity(origin, result.page.path)\n if (seenPages.has(identity)) {\n throw new Error(\n `knowledge retrieval repeats page '${result.page.path}' at origin '${origin}'`,\n )\n }\n seenPages.add(identity)\n const visibleEntry = index.byIdentity.get(identity)\n if (!visibleEntry) {\n throw new Error(\n `knowledge retrieval result '${result.page.path}' at origin '${origin}' was not visible`,\n )\n }\n const pageDigest = knowledgePageDigest(result.page)\n if (visibleEntry.pageId !== result.page.id || visibleEntry.pageDigest !== pageDigest) {\n throw new Error(\n `knowledge retrieval result '${result.page.path}' does not match its visibility snapshot`,\n )\n }\n assertResultScores(result, position)\n return Object.freeze({\n rank: result.rank,\n pageId: result.page.id,\n origin,\n path: result.page.path,\n pageDigest,\n rrfScore: result.rrfScore,\n normalizedScore: result.normalizedScore,\n snippet: typeof result.snippet === 'string' ? result.snippet : '',\n reasons: Object.freeze(\n result.reasons.map((reason: string, reasonIndex: number) =>\n nonEmpty(reason, `knowledge retrieval results[${position}].reasons[${reasonIndex}]`),\n ),\n ),\n })\n })\n normalized.sort((left, right) => left.rank - right.rank)\n assertContiguousRanks(normalized)\n return Object.freeze(normalized)\n}\n\nfunction validateReceiptResultShape(\n results: readonly KnowledgeRetrievalResultReceipt[],\n pageCount: number,\n): void {\n if (!Array.isArray(results)) throw new TypeError('knowledge retrieval results must be an array')\n if (results.length > pageCount) {\n throw new Error(\n `knowledge retrieval returns ${results.length} results from ${pageCount} visible pages`,\n )\n }\n assertContiguousRanks(results)\n const seen = new Set<string>()\n results.forEach((result, position) => {\n if (!result || typeof result !== 'object') {\n throw new TypeError(`knowledge retrieval results[${position}] must be an object`)\n }\n const origin = validateOrigin(result.origin, `knowledge retrieval results[${position}].origin`)\n const identity = visibilityIdentity(\n origin,\n nonEmpty(result.path, `knowledge retrieval results[${position}].path`),\n )\n if (seen.has(identity)) {\n throw new Error(`knowledge retrieval repeats visible page '${result.path}'`)\n }\n seen.add(identity)\n nonEmpty(result.pageId, `knowledge retrieval results[${position}].pageId`)\n digest(result.pageDigest, `knowledge retrieval results[${position}].pageDigest`)\n assertResultScores(result, position)\n if (typeof result.snippet !== 'string') {\n throw new TypeError(`knowledge retrieval results[${position}].snippet must be a string`)\n }\n if (!Array.isArray(result.reasons)) {\n throw new TypeError(`knowledge retrieval results[${position}].reasons must be an array`)\n }\n })\n}\n\n/**\n * Ranks a retriever returned: one-based, unique, and contiguous, so a receipt\n * cannot hide a result by omitting its rank.\n */\nfunction assertContiguousRanks(results: readonly { readonly rank: number }[]): void {\n results.forEach((result, position) => {\n if (result.rank !== position + 1) {\n throw new Error(\n `knowledge retrieval ranks must be contiguous from 1; expected ${position + 1}, observed ${result.rank}`,\n )\n }\n })\n}\n\n/** Scores a receipt may carry: finite, with the normalized score inside [0,1]. */\nfunction assertResultScores(\n result: { readonly rrfScore: number; readonly normalizedScore: number },\n position: number,\n): void {\n finite(result.rrfScore, `knowledge retrieval results[${position}].rrfScore`)\n finite(result.normalizedScore, `knowledge retrieval results[${position}].normalizedScore`)\n if (result.normalizedScore < 0 || result.normalizedScore > 1) {\n throw new TypeError(`knowledge retrieval results[${position}].normalizedScore must be in [0,1]`)\n }\n}\n\nfunction normalizeRetriever(input: KnowledgeRetrieverIdentity): KnowledgeRetrieverIdentity {\n if (!input || typeof input !== 'object') {\n throw new TypeError('knowledge retriever identity is required')\n }\n return Object.freeze({\n id: nonEmpty(input.id, 'knowledge retriever id'),\n version: nonEmpty(input.version, 'knowledge retriever version'),\n configDigest: digest(input.configDigest, 'knowledge retriever configDigest'),\n })\n}\n\nfunction normalizeConsumer(input: KnowledgeConsumerRef): KnowledgeConsumerRef {\n if (!input || typeof input !== 'object') {\n throw new TypeError('knowledge consumer reference is required')\n }\n const kinds: readonly KnowledgeConsumerKind[] = [\n 'decision',\n 'artifact',\n 'experiment',\n 'candidate',\n 'message',\n 'other',\n ]\n if (!kinds.includes(input.kind)) {\n throw new TypeError(`knowledge consumer kind is invalid: ${String(input.kind)}`)\n }\n return Object.freeze({\n kind: input.kind,\n uri: nonEmpty(input.uri, 'knowledge consumer uri'),\n ...(input.digest === undefined\n ? {}\n : { digest: digest(input.digest, 'knowledge consumer digest') }),\n })\n}\n\nfunction normalizeEvidenceRefs(values: readonly EvidenceRef[]): readonly EvidenceRef[] {\n if (!Array.isArray(values)) throw new TypeError('knowledge evidenceRefs must be an array')\n const allowed: readonly EvidenceRef['kind'][] = ['span', 'event', 'artifact', 'finding', 'metric']\n return Object.freeze(\n values.map((value, index) => {\n if (!value || typeof value !== 'object' || !allowed.includes(value.kind)) {\n throw new TypeError(`knowledge evidenceRefs[${index}].kind is invalid`)\n }\n return Object.freeze({\n kind: value.kind,\n uri: nonEmpty(value.uri, `knowledge evidenceRefs[${index}].uri`),\n ...(value.excerpt === undefined\n ? {}\n : { excerpt: nonEmpty(value.excerpt, `knowledge evidenceRefs[${index}].excerpt`) }),\n })\n }),\n )\n}\n\nfunction normalizeAttributes(\n input: Readonly<Record<string, KnowledgeReceiptAttributeValue>>,\n): Readonly<Record<string, KnowledgeReceiptAttributeValue>> {\n if (!input || typeof input !== 'object' || Array.isArray(input)) {\n throw new TypeError('knowledge receipt attributes must be an object')\n }\n const normalized: Record<string, KnowledgeReceiptAttributeValue> = {}\n for (const [key, value] of Object.entries(input)) {\n const name = nonEmpty(key, 'knowledge receipt attribute key')\n if (\n value !== null &&\n typeof value !== 'string' &&\n typeof value !== 'number' &&\n typeof value !== 'boolean'\n ) {\n throw new TypeError(`knowledge receipt attribute '${name}' has an unsupported value`)\n }\n if (typeof value === 'number') finite(value, `knowledge receipt attribute '${name}'`)\n normalized[name] = value\n }\n return Object.freeze(normalized)\n}\n\nfunction validateUseRelation(value: KnowledgeUseRelation): KnowledgeUseRelation {\n const allowed: readonly KnowledgeUseRelation[] = [\n 'supports',\n 'contradicts',\n 'extends',\n 'rederives',\n 'background',\n ]\n if (!allowed.includes(value)) {\n throw new TypeError(`knowledge use relation is invalid: ${String(value)}`)\n }\n return value\n}\n\nfunction optionalDigest(value: unknown, label: string): Sha256Digest | undefined {\n return value === undefined ? undefined : digest(value, label)\n}\n\nfunction optionalText(value: unknown, label: string): string | undefined {\n return value === undefined ? undefined : nonEmpty(value, label)\n}\n\nfunction finite(value: unknown, label: string): asserts value is number {\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n throw new TypeError(`${label} must be a finite number`)\n }\n}\n\nfunction isoTimestamp(value: Date | string | undefined, label: string): string {\n const date = value === undefined ? new Date() : value instanceof Date ? value : new Date(value)\n if (!Number.isFinite(date.getTime())) throw new TypeError(`${label} must be a valid timestamp`)\n return date.toISOString()\n}\n","/**\n * Provider-neutral knowledge tools.\n *\n * Knowledge owns what each tool does; a runtime only transports the definitions\n * and the calls. The shape is `ToolDefinition` from `@tangle-network/agent-interface`,\n * so no provider vocabulary reaches this package and no knowledge behavior\n * reaches a provider adapter.\n *\n * Every search mints a retrieval receipt. Configured receipt capture also\n * persists the exact visibility snapshot before delivering the receipt.\n */\n\nimport { join } from 'node:path'\nimport { pathToFileURL } from 'node:url'\nimport type { ToolDefinition } from '@tangle-network/agent-interface'\nimport { z } from 'zod'\nimport {\n parseKnowledgeCitationReference,\n resolveKnowledgeCitation,\n resolveRunScopedCitations,\n} from './citation-resolution'\nimport { isMissingFile, readRegularFileWithinRoot, writeFileDurableWithinRoot } from './durable-fs'\nimport { buildKnowledgeBrief, type KnowledgeBriefOptions } from './knowledge-brief'\nimport {\n createKnowledgeRetrievalReceipt,\n createKnowledgeVisibilitySnapshot,\n encodeKnowledgeVisibilitySnapshot,\n type KnowledgeRetrievalReceipt,\n knowledgeVisibilityArtifactRef,\n} from './knowledge-use-receipts'\nimport { withKnowledgeMutation } from './mutation-lock'\nimport { normalizePagesDirectory } from './pages-directory'\nimport { applyKnowledgeWriteBlocks, type KnowledgeWriteIntakeRequest } from './proposals'\nimport type { OriginatedPage, RunScopedStores } from './run-scoped'\nimport { parseKnowledgeWriteBlocks } from './write-protocol'\n\nexport interface CreateKnowledgeToolsOptions {\n readonly stores: RunScopedStores\n /** The run whose store is written and whose chain is read. */\n readonly runId: string\n /**\n * Version of this package the host is running. A bundled build cannot read\n * its own manifest, and a receipt that guessed the version would be a\n * receipt that lies about what ranked the results.\n */\n readonly retrieverVersion: string\n readonly actorId?: string\n readonly pagesDirectory?: string\n /** Intake settings for `knowledge_record`. Absent leaves the write ungated. */\n readonly intake?: Omit<KnowledgeWriteIntakeRequest, 'inheritedPages'>\n /** Retain prior and new bytes for every completed knowledge_record transaction. */\n readonly retainHistory?: boolean\n /** Brief settings for `knowledge_search`, overridden per call by the tool input. */\n readonly brief?: Omit<KnowledgeBriefOptions, 'limit'>\n /** Receipt sink. Exact visibility bytes are persisted in the run store before this is called. */\n readonly recordRetrieval?: (receipt: KnowledgeRetrievalReceipt) => Promise<void> | void\n readonly now?: () => Date\n}\n\nconst searchInput = z.object({\n question: z.string().min(1),\n limit: z.int().min(1).max(50).optional(),\n excludeInvalidated: z\n .boolean()\n .optional()\n .describe('False includes refuted pages for historical research.'),\n tags: z.array(z.string()).optional(),\n kinds: z.array(z.string()).optional(),\n})\nconst readInput = z.object({ pageId: z.string().min(1) })\nconst recordInput = z.object({\n proposal: z\n .string()\n .min(1)\n .describe(\n 'One or more complete FILE blocks. Each begins with ---FILE: <page-path>--- and ends with ---END FILE---, each on its own line. Put the page content between them. Every block must be valid; malformed or empty proposals write nothing and return an error.',\n ),\n})\nconst resolveInput = z.object({ references: z.array(z.string().min(1)).min(1) })\n\n/**\n * The four tools an agent needs to use a knowledge store: search, read, record,\n * resolve.\n */\nexport function createKnowledgeTools(options: CreateKnowledgeToolsOptions): ToolDefinition[] {\n const { stores, runId } = options\n if (!stores || typeof stores.loadChain !== 'function') {\n throw new TypeError('knowledge tools require run-scoped stores')\n }\n if (typeof runId !== 'string' || runId.trim().length === 0) {\n throw new TypeError('knowledge tools require a runId')\n }\n if (typeof options.retrieverVersion !== 'string' || options.retrieverVersion.trim() === '') {\n throw new TypeError('knowledge tools require the running retrieverVersion')\n }\n const pages =\n options.pagesDirectory === undefined ? {} : { pagesDirectory: options.pagesDirectory }\n const pagesDirectory = normalizePagesDirectory(options.pagesDirectory)\n\n return [\n tool(\n 'knowledge_search',\n 'Search visible knowledge with unambiguous citation handles. Optionally include refuted history or filter tags and kinds.',\n searchInput,\n async (input) => {\n const chain = await stores.loadChain(runId)\n const brief = buildKnowledgeBrief(chain, input.question, {\n ...options.brief,\n ...(input.limit === undefined ? {} : { limit: input.limit }),\n ...(input.excludeInvalidated === undefined\n ? {}\n : { excludeInvalidated: input.excludeInvalidated }),\n ...(input.tags === undefined ? {} : { tags: input.tags }),\n ...(input.kinds === undefined ? {} : { kinds: input.kinds }),\n })\n const visibility = createKnowledgeVisibilitySnapshot(chain)\n const visibilityArtifact = options.recordRetrieval\n ? await persistVisibility(stores.storePath(runId), visibility)\n : undefined\n const receipt = createKnowledgeRetrievalReceipt({\n runId,\n ...(options.actorId === undefined ? {} : { actorId: options.actorId }),\n query: brief.question,\n retriever: {\n id: brief.retrieverId,\n version: options.retrieverVersion,\n configDigest: brief.retrieverConfigDigest,\n },\n visibility,\n ...(visibilityArtifact ? { visibilityArtifact } : {}),\n results: brief.results,\n createdAt: options.now?.(),\n })\n await options.recordRetrieval?.(receipt)\n return {\n text: brief.text,\n citationIds: brief.citationIds,\n retrievalReceiptDigest: receipt.receiptDigest,\n receipt,\n }\n },\n ),\n\n tool(\n 'knowledge_read',\n 'Read one page by its id, optionally qualified with here::, shared:: or inherited:<runId>::.',\n readInput,\n async (input) => {\n const resolution = resolveKnowledgeCitation(\n await stores.loadChain(runId),\n parseKnowledgeCitationReference(input.pageId),\n )\n return {\n status: resolution.status,\n page:\n resolution.resolved === undefined\n ? null\n : {\n pageId: resolution.resolved.page.id,\n origin: resolution.resolved.origin,\n path: resolution.resolved.page.path,\n title: resolution.resolved.page.title,\n text: resolution.resolved.page.text,\n },\n candidates: resolution.candidates.map((candidate) => ({\n pageId: candidate.pageId,\n origin: candidate.origin,\n path: candidate.page.path,\n })),\n }\n },\n ),\n\n tool(\n 'knowledge_record',\n `Write pages into this run's store. Use complete blocks exactly like:\\n---FILE: ${pagesDirectory}/example.md---\\n# Example\\nPage content.\\n---END FILE---\\nUse paths under ${pagesDirectory}/. Both delimiters must be on their own lines. Malformed, unsafe, or empty proposals are rejected before writing any pages.`,\n recordInput,\n async (input) => {\n const parsed = parseKnowledgeWriteBlocks(input.proposal, [`${pagesDirectory}/`])\n // Tool success must mean the complete proposal was admitted, not a silent partial write.\n if (parsed.blocks.length === 0 || parsed.warnings.length > 0) {\n throw new Error(\n `knowledge_record rejected the proposal without writing any pages. Use ---FILE: ${pagesDirectory}/example.md--- followed by content and ---END FILE---, each delimiter on its own line. ${parsed.warnings.join(' ')}`,\n )\n }\n const intake = options.intake\n return applyKnowledgeWriteBlocks(stores.storePath(runId), input.proposal, {\n ...pages,\n retainHistory: options.retainHistory,\n ...(intake === undefined\n ? {}\n : { intake: { ...intake, inheritedPages: await inheritedOf(stores, runId) } }),\n })\n },\n ),\n\n tool(\n 'knowledge_resolve',\n 'Resolve page ids against everything this run can see, without hiding an ambiguity.',\n resolveInput,\n async (input) => ({\n resolutions: (\n await resolveRunScopedCitations(\n stores,\n runId,\n input.references.map((reference) => parseKnowledgeCitationReference(reference)),\n )\n ).map((resolution) => ({\n pageId: resolution.reference.pageId,\n ...(resolution.reference.origin === undefined\n ? {}\n : { origin: resolution.reference.origin }),\n status: resolution.status,\n candidates: resolution.candidates.map((candidate) => ({\n pageId: candidate.pageId,\n origin: candidate.origin,\n path: candidate.page.path,\n })),\n })),\n }),\n ),\n ]\n}\n\n/** Everything the run can see except what it wrote, which the write path reads itself. */\nasync function inheritedOf(\n stores: RunScopedStores,\n runId: string,\n): Promise<readonly OriginatedPage[]> {\n return (await stores.loadChain(runId)).filter((entry) => entry.origin !== 'here')\n}\n\nfunction tool<Schema extends z.ZodType>(\n name: string,\n description: string,\n inputSchema: Schema,\n handler: (input: z.infer<Schema>) => Promise<unknown>,\n): ToolDefinition {\n return {\n name,\n description,\n inputSchema,\n inputSchemaJson: z.toJSONSchema(inputSchema) as Record<string, unknown>,\n handler: (input: unknown) => handler(inputSchema.parse(input)),\n }\n}\n\n/** Snapshot artifacts are immutable evidence, separate from authoritative KB state. */\nasync function persistVisibility(\n root: string,\n snapshot: ReturnType<typeof createKnowledgeVisibilitySnapshot>,\n) {\n const bytes = encodeKnowledgeVisibilitySnapshot(snapshot)\n const path = `.agent-knowledge/retrieval-visibility/${snapshot.snapshotDigest.replace('sha256:', '')}.json`\n await withKnowledgeMutation(root, async () => {\n try {\n const existing = await readRegularFileWithinRoot(root, path)\n if (!Buffer.from(existing.bytes).equals(Buffer.from(bytes))) {\n throw new Error('stored knowledge visibility artifact does not match its content identity')\n }\n } catch (error) {\n if (!isMissingFile(error)) throw error\n await writeFileDurableWithinRoot(root, path, Buffer.from(bytes))\n }\n })\n return knowledgeVisibilityArtifactRef({ uri: pathToFileURL(join(root, path)).href, bytes })\n}\n","/**\n * Run-scope to shared-scope promotion.\n *\n * A run writes only its own store. Knowledge reaches the curated shared store\n * through this call and no other, and every promotion leaves a record naming\n * the source run, the promoted bytes, the support carried with them, the actor,\n * and the reason.\n *\n * A claim's cited support travels with it. Promoting a claim while leaving the\n * run-local pages it cites behind is what turns a resolved citation into a\n * dangling one, so the closure of cited pages is carried and the promotion is\n * refused when any citation would not resolve in the target.\n */\nimport { canonicalCandidateDigest, type Sha256Digest } from '@tangle-network/agent-interface'\nimport {\n assertKnowledgeCitationsResolved,\n parseKnowledgeCitationReference,\n resolveKnowledgeCitation,\n} from './citation-resolution'\nimport { isMissingFile, readRegularFileWithinRoot, writeJsonDurableWithinRoot } from './durable-fs'\nimport { commitKnowledgeFileMutations } from './file-transaction'\nimport { knowledgePageDigest } from './knowledge-use-receipts'\nimport { withKnowledgeMutation } from './mutation-lock'\nimport { type KnowledgePagesOptions, normalizePagesDirectory } from './pages-directory'\nimport {\n type OriginatedPage,\n originatedPages,\n type PageOrigin,\n type RunScopedStores,\n} from './run-scoped'\nimport { initKnowledgeBase, knowledgePageFromMarkdown, loadKnowledgePages } from './store'\nimport type { KnowledgeId, KnowledgePage } from './types'\n\nexport const KNOWLEDGE_PROMOTION_SCHEMA_VERSION = '1.0.0' as const\nexport const KNOWLEDGE_PROMOTION_DIGEST_ALGORITHM = 'rfc8785-sha256' as const\n\n/** Root-relative directory holding one JSON record per promotion. */\nexport const KNOWLEDGE_PROMOTIONS_DIRECTORY = '.agent-knowledge/promotions'\n\nexport type KnowledgePromotionErrorCode =\n | 'unknown-page'\n | 'ambiguous-support'\n | 'id-conflict'\n | 'path-conflict'\n\n/** A promotion that cannot be performed exactly as asked. */\nexport class KnowledgePromotionError extends Error {\n readonly code: KnowledgePromotionErrorCode\n\n constructor(code: KnowledgePromotionErrorCode, message: string) {\n super(message)\n this.name = 'KnowledgePromotionError'\n this.code = code\n }\n}\n\nexport interface KnowledgePromotionEntry {\n readonly pageId: KnowledgeId\n readonly path: string\n /** Where the page was read from in the source run's chain. */\n readonly sourceOrigin: PageOrigin\n readonly pageDigest: Sha256Digest\n /** False when the page travelled only because a promoted page cites it. */\n readonly requested: boolean\n}\n\n/** Immutable record of one promotion into a shared store. */\nexport interface KnowledgePromotionRecord {\n readonly schemaVersion: typeof KNOWLEDGE_PROMOTION_SCHEMA_VERSION\n readonly kind: 'knowledge-promotion'\n readonly digestAlgorithm: typeof KNOWLEDGE_PROMOTION_DIGEST_ALGORITHM\n readonly recordDigest: Sha256Digest\n readonly createdAt: string\n readonly runId: string\n readonly actor: string\n readonly reason: string\n /** Promoted pages first, then carried support, each group in path order. */\n readonly entries: readonly KnowledgePromotionEntry[]\n}\n\nexport interface PromoteRunScopedPagesOptions extends KnowledgePagesOptions {\n /** Stable ids of the pages this run authored and wants in shared scope. */\n readonly pageIds: readonly KnowledgeId[]\n /** The curated store every run reads and no run writes directly. */\n readonly sharedRoot: string\n /** Who decided to promote. */\n readonly actor: string\n /** Why this knowledge belongs in shared scope. */\n readonly reason: string\n readonly now?: () => Date\n}\n\n/**\n * Promote pages a run authored into the shared store, with their cited support.\n *\n * Support keeps its own evidence fields exactly as written, so a promoted claim\n * cannot inherit a confidence its support does not carry. Pages travel as the\n * bytes their store holds.\n *\n * Re-running the same promotion is safe: unchanged pages produce no file\n * mutation and the record is content-addressed, so it lands at the same path\n * with the same bytes.\n */\nexport async function promoteRunScopedPages(\n stores: RunScopedStores,\n runId: string,\n options: PromoteRunScopedPagesOptions,\n): Promise<KnowledgePromotionRecord> {\n const pagesDirectory = normalizePagesDirectory(options.pagesDirectory)\n const sharedRoot = nonEmpty(options.sharedRoot, 'promotion sharedRoot')\n const actor = nonEmpty(options.actor, 'promotion actor')\n const reason = nonEmpty(options.reason, 'promotion reason')\n if (!Array.isArray(options.pageIds) || options.pageIds.length === 0) {\n throw new TypeError('promotion pageIds must name at least one page')\n }\n\n const chain = await stores.loadChain(runId)\n const travellers = collectTravellers(chain, options.pageIds)\n const mutations = await Promise.all(\n travellers.map(async (traveller) => ({\n path: traveller.entry.page.path,\n content: await readPageBytes(stores, runId, traveller.entry, pagesDirectory),\n })),\n )\n\n await initKnowledgeBase(sharedRoot)\n return withKnowledgeMutation(sharedRoot, async (lock) => {\n const existing = await loadKnowledgePages(sharedRoot, { pagesDirectory })\n assertNoIdentityConflict(travellers, existing)\n\n const promotedPaths = new Set(travellers.map((traveller) => traveller.entry.page.path))\n const promotedView = originatedPages(\n [\n ...existing.filter((page) => !promotedPaths.has(page.path)),\n ...travellers.map((traveller) => traveller.entry.page),\n ],\n 'shared',\n )\n assertKnowledgeCitationsResolved(\n promotedView,\n travellers.flatMap((traveller) =>\n (traveller.entry.page.cites ?? []).map((persisted: string) =>\n parseKnowledgeCitationReference(persisted),\n ),\n ),\n )\n\n await commitKnowledgeFileMutations({\n root: sharedRoot,\n transactionRoot: lock.transactionRoot,\n purpose: `knowledge-promotion:${runId}`,\n mutations,\n pagesDirectory,\n assertOwned: lock.assertOwned,\n })\n\n const record = buildRecord({\n runId,\n actor,\n reason,\n travellers,\n createdAt: (options.now ?? (() => new Date()))().toISOString(),\n })\n await writeJsonDurableWithinRoot(\n sharedRoot,\n `${KNOWLEDGE_PROMOTIONS_DIRECTORY}/${record.recordDigest}.json`,\n record,\n )\n return record\n })\n}\n\n/** Read one promotion record written by `promoteRunScopedPages`. */\nexport async function loadKnowledgePromotionRecord(\n sharedRoot: string,\n recordDigest: Sha256Digest,\n): Promise<KnowledgePromotionRecord | null> {\n try {\n const snapshot = await readRegularFileWithinRoot(\n sharedRoot,\n `${KNOWLEDGE_PROMOTIONS_DIRECTORY}/${recordDigest}.json`,\n )\n return JSON.parse(snapshot.bytes.toString('utf8')) as KnowledgePromotionRecord\n } catch (error) {\n if (isMissingFile(error)) return null\n throw error\n }\n}\n\ninterface Traveller {\n readonly entry: OriginatedPage\n requested: boolean\n}\n\n/**\n * The requested pages plus the closure of the run-local pages they cite.\n *\n * A citation into the shared store needs no carrying, and an unresolved\n * citation is left to the target-side check, which reports every one of them\n * together rather than failing on the first.\n */\nfunction collectTravellers(\n chain: readonly OriginatedPage[],\n pageIds: readonly KnowledgeId[],\n): Traveller[] {\n const byId = new Map<KnowledgeId, Traveller>()\n const queue: Array<{ entry: OriginatedPage; requested: boolean }> = []\n\n for (const pageId of pageIds) {\n const authored = chain.filter((entry) => entry.origin === 'here' && entry.page.id === pageId)\n if (authored.length === 0) {\n throw new KnowledgePromotionError(\n 'unknown-page',\n `promotion page \"${pageId}\" was not authored by this run`,\n )\n }\n if (authored.length > 1) {\n throw new KnowledgePromotionError(\n 'ambiguous-support',\n `promotion page \"${pageId}\" names ${authored.length} pages in this run`,\n )\n }\n queue.push({ entry: authored[0]!, requested: true })\n }\n\n while (queue.length > 0) {\n const next = queue.shift()!\n const seen = byId.get(next.entry.page.id)\n if (seen) {\n if (next.requested) seen.requested = true\n if (seen.entry.page.path !== next.entry.page.path) {\n throw new KnowledgePromotionError(\n 'ambiguous-support',\n `promotion support \"${next.entry.page.id}\" names more than one visible page`,\n )\n }\n continue\n }\n byId.set(next.entry.page.id, { entry: next.entry, requested: next.requested })\n for (const persisted of next.entry.page.cites ?? []) {\n const resolution = resolveKnowledgeCitation(chain, parseKnowledgeCitationReference(persisted))\n const target = resolution.resolved\n if (target === undefined || target.origin === 'shared') continue\n queue.push({ entry: { page: target.page, origin: target.origin }, requested: false })\n }\n }\n\n return [...byId.values()].sort(\n (left, right) =>\n Number(right.requested) - Number(left.requested) ||\n left.entry.page.path.localeCompare(right.entry.page.path),\n )\n}\n\nfunction assertNoIdentityConflict(\n travellers: readonly Traveller[],\n existing: readonly KnowledgePage[],\n): void {\n for (const traveller of travellers) {\n const page = traveller.entry.page\n const idClash = existing.find((other) => other.id === page.id && other.path !== page.path)\n if (idClash) {\n throw new KnowledgePromotionError(\n 'id-conflict',\n `shared page \"${idClash.path}\" already holds id \"${page.id}\"; promoting \"${page.path}\" would create two`,\n )\n }\n const pathClash = existing.find((other) => other.path === page.path && other.id !== page.id)\n if (pathClash) {\n throw new KnowledgePromotionError(\n 'path-conflict',\n `shared page \"${page.path}\" holds id \"${pathClash.id}\", not \"${page.id}\"`,\n )\n }\n }\n}\n\n/**\n * The page as its own store holds it. A promoted page must be the same bytes\n * in both scopes, so the record's digest describes what a reader will load.\n */\nasync function readPageBytes(\n stores: RunScopedStores,\n runId: string,\n entry: OriginatedPage,\n pagesDirectory: string,\n): Promise<string> {\n const sourceRunId = sourceRunOf(entry.origin, runId)\n const snapshot = await readRegularFileWithinRoot(stores.storePath(sourceRunId), entry.page.path)\n const content = snapshot.bytes.toString('utf8')\n const page = knowledgePageFromMarkdown(entry.page.path, content, pagesDirectory)\n if (knowledgePageDigest(page) !== knowledgePageDigest(entry.page)) {\n throw new KnowledgePromotionError(\n 'path-conflict',\n `source page \"${entry.page.path}\" in run \"${sourceRunId}\" changed after the promotion snapshot`,\n )\n }\n return content\n}\n\nfunction sourceRunOf(origin: PageOrigin, runId: string): string {\n if (origin === 'here') return runId\n if (origin.startsWith('inherited:')) return origin.slice('inherited:'.length)\n throw new Error(`promotion cannot read the bytes of a ${origin} page`)\n}\n\nfunction buildRecord(input: {\n runId: string\n actor: string\n reason: string\n travellers: readonly Traveller[]\n createdAt: string\n}): KnowledgePromotionRecord {\n const entries: KnowledgePromotionEntry[] = input.travellers.map((traveller) =>\n Object.freeze({\n pageId: traveller.entry.page.id,\n path: traveller.entry.page.path,\n sourceOrigin: traveller.entry.origin,\n pageDigest: knowledgePageDigest(traveller.entry.page),\n requested: traveller.requested,\n }),\n )\n const material = {\n schemaVersion: KNOWLEDGE_PROMOTION_SCHEMA_VERSION,\n kind: 'knowledge-promotion' as const,\n digestAlgorithm: KNOWLEDGE_PROMOTION_DIGEST_ALGORITHM,\n createdAt: input.createdAt,\n runId: input.runId,\n actor: input.actor,\n reason: input.reason,\n entries,\n }\n return Object.freeze({ ...material, recordDigest: canonicalCandidateDigest(material) })\n}\n\nfunction nonEmpty(value: string, label: string): string {\n if (typeof value !== 'string' || value.trim().length === 0) {\n throw new TypeError(`${label} must be a non-empty string`)\n }\n return value.trim()\n}\n","/**\n * Bridge from `AnalystFinding` (agent-eval) to knowledge proposals.\n *\n * Closes the failure → wiki side of the recursive-self-improvement\n * loop: a knowledge-gap or knowledge-poisoning finding produced by an\n * analyst becomes a concrete proposal an operator (or auto-merge bot)\n * can review and apply. The bridge is intentionally lossless on the\n * fail-loud side — a finding the parser can't classify returns a\n * `KnowledgeProposalParseError` rather than a silent skip, so the\n * loop never accepts an underspecified edit.\n *\n * Subject grammar this bridge understands (analyst-side convention,\n * stamped in the kind prompts):\n *\n * agent-knowledge:wiki:<page-slug> create / update page\n * agent-knowledge:wiki:<page-slug>#<heading> insert section under page\n * agent-knowledge:claim:<topic> draft claim row\n * agent-knowledge:raw:<source-id> lift raw → curated\n * agent-knowledge:stale:<page-slug> mark page superseded\n *\n * Anything else (websearch:outdated:*, tool-doc:*, system-prompt:*,\n * memory:*) is NOT a knowledge-base concern and returns `null` so the\n * loop's improvement-applier handles it.\n */\n\nimport type { AnalystFinding, AnalystSeverity } from '@tangle-network/agent-eval'\nimport type { ClaimRef, KnowledgeClaim, KnowledgeWriteBlock } from './types'\n\nexport interface KnowledgeProposal {\n /**\n * Stable id derived from the finding so cross-run diffs share an\n * identity. Re-proposing the same finding produces the same id.\n */\n id: string\n /** The finding that generated this proposal — useful for audit + revert. */\n sourceFindingId: string\n /** What the proposal does. */\n kind:\n | 'create-page'\n | 'update-page'\n | 'append-section'\n | 'create-claim'\n | 'lift-raw'\n | 'mark-stale'\n /** Locus on disk (page slug or claim topic). */\n locus: string\n /**\n * Page write blocks the standard `applyKnowledgeWriteBlocks` consumer\n * accepts. Empty for proposals that don't change page text (e.g.\n * `create-claim` produces a `claim` field instead).\n */\n writeBlocks: KnowledgeWriteBlock[]\n /**\n * Granular claim draft for proposals whose unit-of-change is a claim\n * row rather than a whole page. `status: 'draft'` until reviewed.\n */\n claim?: KnowledgeClaim\n /** Per-proposal metadata: severity, confidence, source span. */\n metadata: {\n severity: AnalystSeverity\n confidence: number\n evidence_uri?: string\n analyst_id: string\n }\n}\n\nexport class KnowledgeProposalParseError extends Error {\n constructor(\n public readonly findingId: string,\n public readonly subject: string,\n message: string,\n ) {\n super(`proposeFromFinding(${findingId}, subject=${subject}): ${message}`)\n this.name = 'KnowledgeProposalParseError'\n }\n}\n\n/**\n * Convert one `AnalystFinding` into a knowledge proposal. Returns\n * `null` when the finding's locus isn't a knowledge-base concern\n * (`websearch:outdated:*`, `tool-doc:*`, `system-prompt:*`,\n * `memory:*`, missing subject). Throws when the locus IS a\n * knowledge-base concern but is malformed — that's a bug in the\n * analyst prompt and should fail loud.\n *\n * Caller convention: feed the function the analyst's full findings\n * list and filter out the `null`s; the orchestrator passes the\n * remaining proposals to the existing review / apply pipeline.\n */\nexport function proposeFromFinding(finding: AnalystFinding): KnowledgeProposal | null {\n if (!finding.subject) return null\n if (!finding.subject.startsWith('agent-knowledge:')) return null\n\n const rest = finding.subject.slice('agent-knowledge:'.length)\n const [kindPart, ...locusParts] = rest.split(':')\n const locus = locusParts.join(':')\n if (!kindPart || !locus) {\n throw new KnowledgeProposalParseError(\n finding.finding_id,\n finding.subject,\n 'expected `agent-knowledge:<kind>:<locus>` shape',\n )\n }\n\n const baseMeta: KnowledgeProposal['metadata'] = {\n severity: finding.severity,\n confidence: finding.confidence,\n evidence_uri: finding.evidence_refs[0]?.uri,\n analyst_id: finding.analyst_id,\n }\n\n switch (kindPart) {\n case 'wiki':\n return wikiProposal(finding, locus, baseMeta)\n case 'claim':\n return claimProposal(finding, locus, baseMeta)\n case 'raw':\n return liftRawProposal(finding, locus, baseMeta)\n case 'stale':\n return markStaleProposal(finding, locus, baseMeta)\n default:\n throw new KnowledgeProposalParseError(\n finding.finding_id,\n finding.subject,\n `unknown kind \"${kindPart}\" (expected one of: wiki | claim | raw | stale)`,\n )\n }\n}\n\nfunction wikiProposal(\n finding: AnalystFinding,\n locus: string,\n metadata: KnowledgeProposal['metadata'],\n): KnowledgeProposal {\n const hashIdx = locus.indexOf('#')\n const pageSlug = hashIdx >= 0 ? locus.slice(0, hashIdx) : locus\n const heading = hashIdx >= 0 ? locus.slice(hashIdx + 1) : null\n const path = `knowledge/${ensureSlug(pageSlug)}.md`\n\n const body = renderWikiBody(finding, pageSlug, heading)\n return {\n id: `prop-${finding.finding_id}`,\n sourceFindingId: finding.finding_id,\n kind: heading ? 'append-section' : 'create-page',\n locus: pageSlug,\n writeBlocks: [{ path, content: body }],\n metadata,\n }\n}\n\nfunction claimProposal(\n finding: AnalystFinding,\n locus: string,\n metadata: KnowledgeProposal['metadata'],\n): KnowledgeProposal {\n const refs: ClaimRef[] = finding.evidence_refs\n .filter((r) => r.uri)\n .map((r) => ({\n sourceId: `analyst-finding:${finding.finding_id}`,\n anchorId: r.uri,\n quote: r.excerpt,\n }))\n const claim: KnowledgeClaim = {\n id: `claim-${finding.finding_id}`,\n text: finding.recommended_action ?? finding.claim,\n refs,\n confidence: finding.confidence,\n status: 'draft',\n metadata: {\n analyst_id: finding.analyst_id,\n source_finding_id: finding.finding_id,\n topic: locus,\n },\n }\n return {\n id: `prop-${finding.finding_id}`,\n sourceFindingId: finding.finding_id,\n kind: 'create-claim',\n locus,\n writeBlocks: [],\n claim,\n metadata,\n }\n}\n\nfunction liftRawProposal(\n finding: AnalystFinding,\n sourceId: string,\n metadata: KnowledgeProposal['metadata'],\n): KnowledgeProposal {\n const path = `knowledge/${ensureSlug(sourceId)}.md`\n const body = [\n '---',\n `title: ${sourceId}`,\n `source: ${sourceId}`,\n `status: draft`,\n `lifted_from_finding: ${finding.finding_id}`,\n '---',\n '',\n '## Why this page exists',\n '',\n finding.claim,\n '',\n ...(finding.rationale ? ['## Rationale', '', finding.rationale, ''] : []),\n ...(finding.recommended_action\n ? ['## Recommended action', '', finding.recommended_action, '']\n : []),\n ].join('\\n')\n return {\n id: `prop-${finding.finding_id}`,\n sourceFindingId: finding.finding_id,\n kind: 'lift-raw',\n locus: sourceId,\n writeBlocks: [{ path, content: body }],\n metadata,\n }\n}\n\nfunction markStaleProposal(\n finding: AnalystFinding,\n pageSlug: string,\n metadata: KnowledgeProposal['metadata'],\n): KnowledgeProposal {\n const path = `knowledge/${ensureSlug(pageSlug)}.stale.md`\n const body = [\n '---',\n `title: ${pageSlug} (marked stale)`,\n `status: superseded`,\n `superseded_by_finding: ${finding.finding_id}`,\n `confidence: ${finding.confidence}`,\n '---',\n '',\n '## Why marked stale',\n '',\n finding.claim,\n '',\n ...(finding.rationale ? ['## Evidence', '', finding.rationale, ''] : []),\n ...(finding.recommended_action ? ['## Action', '', finding.recommended_action, ''] : []),\n ].join('\\n')\n return {\n id: `prop-${finding.finding_id}`,\n sourceFindingId: finding.finding_id,\n kind: 'mark-stale',\n locus: pageSlug,\n writeBlocks: [{ path, content: body }],\n metadata,\n }\n}\n\n/**\n * Plural convenience: filter + map across an entire findings batch\n * with one call. Parse errors collect into `errors[]`; the loop\n * decides per-error whether to abort or continue.\n */\nexport interface ProposeFromFindingsResult {\n proposals: KnowledgeProposal[]\n skipped: number\n errors: KnowledgeProposalParseError[]\n}\n\nexport function proposeFromFindings(\n findings: ReadonlyArray<AnalystFinding>,\n): ProposeFromFindingsResult {\n const proposals: KnowledgeProposal[] = []\n const errors: KnowledgeProposalParseError[] = []\n let skipped = 0\n for (const f of findings) {\n try {\n const p = proposeFromFinding(f)\n if (p) proposals.push(p)\n else skipped += 1\n } catch (err) {\n if (err instanceof KnowledgeProposalParseError) errors.push(err)\n else throw err\n }\n }\n return { proposals, skipped, errors }\n}\n\nfunction ensureSlug(s: string): string {\n return (\n s\n .toLowerCase()\n .replace(/[^a-z0-9-]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 200) || 'untitled'\n )\n}\n\nfunction renderWikiBody(finding: AnalystFinding, slug: string, heading: string | null): string {\n const title = humanize(slug)\n if (heading) {\n return [\n `## ${heading}`,\n '',\n finding.claim,\n '',\n ...(finding.rationale ? ['### Rationale', '', finding.rationale, ''] : []),\n ...(finding.recommended_action ? ['### Action', '', finding.recommended_action, ''] : []),\n `_Drafted from finding ${finding.finding_id} (confidence ${finding.confidence.toFixed(2)})._`,\n ].join('\\n')\n }\n return [\n '---',\n `title: ${title}`,\n `status: draft`,\n `drafted_from_finding: ${finding.finding_id}`,\n `confidence: ${finding.confidence}`,\n '---',\n '',\n `# ${title}`,\n '',\n finding.claim,\n '',\n ...(finding.rationale ? ['## Rationale', '', finding.rationale, ''] : []),\n ...(finding.recommended_action\n ? ['## Recommended action', '', finding.recommended_action, '']\n : []),\n ].join('\\n')\n}\n\nfunction humanize(slug: string): string {\n return (\n slug\n .split('-')\n .filter(Boolean)\n .map((w) => w[0]?.toUpperCase() + w.slice(1))\n .join(' ') || slug\n )\n}\n","import type {\n BuildEvalKnowledgeBundleOptions,\n EvalKnowledgeBundleBuildResult,\n KnowledgeReadinessSpec,\n} from './eval-readiness'\nimport { buildKnowledgeIndex } from './indexer'\nimport {\n type KnowledgeBaseQualityOptions,\n type KnowledgeBaseQualityReport,\n scoreKnowledgeBaseIndex,\n} from './rag-eval'\nimport { readinessFor } from './readiness-helpers'\nimport type { KnowledgeIndex } from './types'\nimport {\n type ValidateKnowledgeOptions,\n type ValidateKnowledgeResult,\n validateKnowledgeIndex,\n} from './validate'\n\nexport interface EvaluateKnowledgeBaseReadinessOptions {\n root: string\n goal: string\n readinessSpecs?: readonly KnowledgeReadinessSpec[]\n readinessTaskId?: string\n readiness?: Omit<BuildEvalKnowledgeBundleOptions, 'taskId' | 'index' | 'specs'>\n strict?: ValidateKnowledgeOptions['strict']\n kbQuality?: KnowledgeBaseQualityOptions\n}\n\nexport interface KnowledgeBaseReadinessEvaluation {\n ready: boolean\n summary: string\n index: KnowledgeIndex\n validation: ValidateKnowledgeResult\n readiness?: EvalKnowledgeBundleBuildResult\n kbQuality: KnowledgeBaseQualityReport\n dimensions: {\n validation: number\n kb_quality: number\n blocking_readiness: number\n }\n}\n\nexport async function evaluateKnowledgeBaseReadiness(\n options: EvaluateKnowledgeBaseReadinessOptions,\n): Promise<KnowledgeBaseReadinessEvaluation> {\n const index = await buildKnowledgeIndex(options.root)\n const validation = validateKnowledgeIndex(index, { strict: options.strict })\n const readiness = readinessFor(\n {\n ...options,\n readinessSpecs: options.readinessSpecs ? [...options.readinessSpecs] : undefined,\n },\n index,\n )\n const kbQuality = scoreKnowledgeBaseIndex(index, {\n strict: options.strict,\n ...options.kbQuality,\n })\n const blockingMissing = readiness?.report.blockingMissingRequirements.length ?? 0\n const blockingTotal =\n options.readinessSpecs?.filter((spec) => spec.importance === 'blocking').length ?? 0\n const blockingReadiness =\n blockingTotal === 0 ? 1 : Math.max(0, blockingTotal - blockingMissing) / blockingTotal\n const ready = validation.ok && kbQuality.ok && blockingMissing === 0\n const failures = [\n validation.ok ? undefined : `${validation.findings.length} validation finding(s)`,\n kbQuality.ok ? undefined : `${kbQuality.findings.length} KB quality finding(s)`,\n blockingMissing === 0\n ? undefined\n : `${blockingMissing}/${blockingTotal} blocking readiness requirement(s) missing`,\n ].filter((failure): failure is string => Boolean(failure))\n\n return {\n ready,\n summary: ready ? 'knowledge base passed readiness checks' : failures.join('; '),\n index,\n validation,\n readiness,\n kbQuality,\n dimensions: {\n validation: validation.ok ? 1 : 0,\n kb_quality: kbQuality.ok ? 1 : 0,\n blocking_readiness: blockingReadiness,\n },\n }\n}\n","import { canonicalCandidateJson } from '@tangle-network/agent-interface'\nimport type {\n KnowledgeId,\n KnowledgeRelation,\n KnowledgeRelationGraph,\n KnowledgeRelationNode,\n} from './types'\n\nexport type KnowledgeRelationGraphErrorCode =\n | 'invalid-node'\n | 'duplicate-node'\n | 'invalid-relation'\n | 'duplicate-relation'\n | 'undeclared-endpoint'\n | 'unknown-node'\n | 'invalid-query'\n\n/** A relation graph input or query that cannot be honored exactly. */\nexport class KnowledgeRelationGraphError extends Error {\n readonly code: KnowledgeRelationGraphErrorCode\n\n constructor(code: KnowledgeRelationGraphErrorCode, message: string) {\n super(message)\n this.name = 'KnowledgeRelationGraphError'\n this.code = code\n }\n}\n\nexport interface BuildKnowledgeRelationGraphInput {\n /**\n * Declared node inventory. When present, every relation endpoint must name\n * one declared node; an undeclared endpoint is refused rather than added.\n * When absent, the graph carries edges only and `nodes` is empty.\n */\n nodes?: readonly KnowledgeRelationNode[]\n relations: readonly KnowledgeRelation[]\n}\n\n/**\n * `out` follows `sourceId -> targetId`, `in` follows `targetId -> sourceId`,\n * `both` follows a relation from either end.\n */\nexport type KnowledgeRelationDirection = 'out' | 'in' | 'both'\n\nexport interface KnowledgeRelationQuery {\n /** Restrict to relations with this predicate. Every predicate when absent. */\n predicate?: string\n direction: KnowledgeRelationDirection\n}\n\nexport interface KnowledgeRelationWalkOptions extends KnowledgeRelationQuery {\n /** Most relations between the start node and a reported node. Unbounded when absent. */\n maxDepth?: number\n}\n\nexport interface KnowledgeRelationNeighbor {\n nodeId: KnowledgeId\n relation: KnowledgeRelation\n}\n\nexport interface KnowledgeRelationWalkStep {\n nodeId: KnowledgeId\n /** Number of relations between the start node and this node. */\n depth: number\n /** The node the search came from when it first reached this node. */\n from: KnowledgeId\n relation: KnowledgeRelation\n}\n\n/**\n * Build a labeled multi-edge graph from caller relations.\n *\n * The graph keeps one edge per `(sourceId, targetId, predicate)`, in first-seen\n * order. A repeated triple is accepted only when its weight and metadata are\n * identical in canonical JSON; any other repeat is a conflict and is refused.\n * Node and relation metadata must be finite, acyclic JSON so the graph\n * round-trips through `KnowledgeRelationGraphSchema` unchanged.\n */\nexport function buildKnowledgeRelationGraph(\n input: BuildKnowledgeRelationGraphInput,\n): KnowledgeRelationGraph {\n const declared =\n input.nodes === undefined ? undefined : new Map<KnowledgeId, KnowledgeRelationNode>()\n const nodes: KnowledgeRelationNode[] = []\n if (declared !== undefined) {\n for (const [position, node] of input.nodes!.entries()) {\n const normalized = normalizeNode(node, position)\n if (declared.has(normalized.id)) {\n throw new KnowledgeRelationGraphError(\n 'duplicate-node',\n `node \"${normalized.id}\" is declared more than once`,\n )\n }\n declared.set(normalized.id, normalized)\n nodes.push(normalized)\n }\n }\n\n const edges: KnowledgeRelation[] = []\n const canonicalByTriple = new Map<string, string>()\n for (const [position, relation] of input.relations.entries()) {\n const normalized = normalizeRelation(relation, position)\n if (declared !== undefined) {\n for (const endpoint of [normalized.sourceId, normalized.targetId]) {\n if (!declared.has(endpoint)) {\n throw new KnowledgeRelationGraphError(\n 'undeclared-endpoint',\n `relation ${describeTriple(normalized)} names undeclared node \"${endpoint}\"`,\n )\n }\n }\n }\n const canonical = canonicalRelationJson(normalized)\n const key = tripleKey(normalized)\n const prior = canonicalByTriple.get(key)\n if (prior !== undefined) {\n if (prior === canonical) continue\n throw new KnowledgeRelationGraphError(\n 'duplicate-relation',\n `relation ${describeTriple(normalized)} is repeated with different weight or metadata`,\n )\n }\n canonicalByTriple.set(key, canonical)\n edges.push(normalized)\n }\n return { nodes, edges }\n}\n\n/** Relations touching `id`, each with the node at the other end, in graph order. */\nexport function neighbors(\n graph: KnowledgeRelationGraph,\n id: KnowledgeId,\n query: KnowledgeRelationQuery,\n): KnowledgeRelationNeighbor[] {\n const index = indexOf(graph)\n validateQuery(query)\n assertKnownNode(index, id)\n return neighborsOf(index, id, query)\n}\n\n/**\n * Breadth-first traversal from `id` over matching relations. Each reachable\n * node is reported once, at the depth where the search first reached it; the\n * start node is never reported, so a cycle back to it adds no step.\n */\nexport function walk(\n graph: KnowledgeRelationGraph,\n id: KnowledgeId,\n options: KnowledgeRelationWalkOptions,\n): KnowledgeRelationWalkStep[] {\n const index = indexOf(graph)\n validateQuery(options)\n validateMaxDepth(options.maxDepth)\n assertKnownNode(index, id)\n const steps: KnowledgeRelationWalkStep[] = []\n for (const step of traverse(index, id, options, options.maxDepth)) steps.push(step)\n return steps\n}\n\n/**\n * Whether `to` is `from` or lies on a path of matching relations out of `from`.\n */\nexport function isReachable(\n graph: KnowledgeRelationGraph,\n from: KnowledgeId,\n to: KnowledgeId,\n query: KnowledgeRelationQuery,\n): boolean {\n const index = indexOf(graph)\n validateQuery(query)\n assertKnownNode(index, from)\n assertKnownNode(index, to)\n if (from === to) return true\n for (const step of traverse(index, from, query, undefined)) {\n if (step.nodeId === to) return true\n }\n return false\n}\n\ninterface RelationIndex {\n readonly outgoing: ReadonlyMap<KnowledgeId, readonly KnowledgeRelation[]>\n readonly incoming: ReadonlyMap<KnowledgeId, readonly KnowledgeRelation[]>\n readonly known: ReadonlySet<KnowledgeId>\n}\n\n// The query index is derived once per graph object. A graph is a value: build\n// a new one instead of mutating `nodes` or `edges` after the first query.\nconst indexes = new WeakMap<KnowledgeRelationGraph, RelationIndex>()\n\nfunction indexOf(graph: KnowledgeRelationGraph): RelationIndex {\n const cached = indexes.get(graph)\n if (cached !== undefined) return cached\n const outgoing = new Map<KnowledgeId, KnowledgeRelation[]>()\n const incoming = new Map<KnowledgeId, KnowledgeRelation[]>()\n const known = new Set<KnowledgeId>()\n for (const node of graph.nodes) known.add(node.id)\n for (const relation of graph.edges) {\n known.add(relation.sourceId)\n known.add(relation.targetId)\n push(outgoing, relation.sourceId, relation)\n push(incoming, relation.targetId, relation)\n }\n const index: RelationIndex = { outgoing, incoming, known }\n indexes.set(graph, index)\n return index\n}\n\nfunction push(\n map: Map<KnowledgeId, KnowledgeRelation[]>,\n key: KnowledgeId,\n relation: KnowledgeRelation,\n): void {\n const list = map.get(key)\n if (list === undefined) map.set(key, [relation])\n else list.push(relation)\n}\n\nfunction neighborsOf(\n index: RelationIndex,\n id: KnowledgeId,\n query: KnowledgeRelationQuery,\n): KnowledgeRelationNeighbor[] {\n const matches = (relation: KnowledgeRelation): boolean =>\n query.predicate === undefined || relation.predicate === query.predicate\n const result: KnowledgeRelationNeighbor[] = []\n if (query.direction !== 'in') {\n for (const relation of index.outgoing.get(id) ?? []) {\n if (matches(relation)) result.push({ nodeId: relation.targetId, relation })\n }\n }\n if (query.direction !== 'out') {\n for (const relation of index.incoming.get(id) ?? []) {\n // A self-loop already appears in the outgoing pass when both ends are followed.\n if (query.direction === 'both' && relation.sourceId === id) continue\n if (matches(relation)) result.push({ nodeId: relation.sourceId, relation })\n }\n }\n return result\n}\n\nfunction* traverse(\n index: RelationIndex,\n start: KnowledgeId,\n query: KnowledgeRelationQuery,\n maxDepth: number | undefined,\n): Generator<KnowledgeRelationWalkStep> {\n const visited = new Set<KnowledgeId>([start])\n const queue: Array<{ nodeId: KnowledgeId; depth: number }> = [{ nodeId: start, depth: 0 }]\n for (let head = 0; head < queue.length; head++) {\n const current = queue[head]!\n if (maxDepth !== undefined && current.depth >= maxDepth) continue\n for (const neighbor of neighborsOf(index, current.nodeId, query)) {\n if (visited.has(neighbor.nodeId)) continue\n visited.add(neighbor.nodeId)\n const depth = current.depth + 1\n yield { nodeId: neighbor.nodeId, depth, from: current.nodeId, relation: neighbor.relation }\n queue.push({ nodeId: neighbor.nodeId, depth })\n }\n }\n}\n\nfunction assertKnownNode(index: RelationIndex, id: KnowledgeId): void {\n if (!index.known.has(id)) {\n throw new KnowledgeRelationGraphError('unknown-node', `node \"${id}\" is not in the graph`)\n }\n}\n\nfunction validateQuery(query: KnowledgeRelationQuery): void {\n if (query.direction !== 'out' && query.direction !== 'in' && query.direction !== 'both') {\n throw new KnowledgeRelationGraphError(\n 'invalid-query',\n `direction must be \"out\", \"in\", or \"both\", got ${JSON.stringify(query.direction)}`,\n )\n }\n if (query.predicate !== undefined && !isNonEmptyString(query.predicate)) {\n throw new KnowledgeRelationGraphError('invalid-query', 'predicate must be a non-empty string')\n }\n}\n\nfunction validateMaxDepth(maxDepth: number | undefined): void {\n if (maxDepth === undefined) return\n if (!Number.isInteger(maxDepth) || maxDepth < 0) {\n throw new KnowledgeRelationGraphError(\n 'invalid-query',\n `maxDepth must be a non-negative integer, got ${JSON.stringify(maxDepth)}`,\n )\n }\n}\n\nfunction normalizeNode(node: KnowledgeRelationNode, position: number): KnowledgeRelationNode {\n if (!isNonEmptyString(node.id)) {\n throw new KnowledgeRelationGraphError('invalid-node', `node at ${position} has no id`)\n }\n if (!isNonEmptyString(node.kind)) {\n throw new KnowledgeRelationGraphError('invalid-node', `node \"${node.id}\" has no kind`)\n }\n if (node.label !== undefined && typeof node.label !== 'string') {\n throw new KnowledgeRelationGraphError('invalid-node', `node \"${node.id}\" label is not a string`)\n }\n if (node.metadata !== undefined)\n assertCanonicalMetadata(node.metadata, `node \"${node.id}\"`, 'invalid-node')\n return {\n id: node.id,\n kind: node.kind,\n ...(node.label !== undefined ? { label: node.label } : {}),\n ...(node.metadata !== undefined ? { metadata: node.metadata } : {}),\n }\n}\n\nfunction normalizeRelation(relation: KnowledgeRelation, position: number): KnowledgeRelation {\n for (const field of ['sourceId', 'targetId', 'predicate'] as const) {\n if (!isNonEmptyString(relation[field])) {\n throw new KnowledgeRelationGraphError(\n 'invalid-relation',\n `relation at ${position} has no ${field}`,\n )\n }\n }\n if (relation.weight !== undefined && !Number.isFinite(relation.weight)) {\n throw new KnowledgeRelationGraphError(\n 'invalid-relation',\n `relation ${describeTriple(relation)} weight must be a finite number`,\n )\n }\n return {\n sourceId: relation.sourceId,\n targetId: relation.targetId,\n predicate: relation.predicate,\n ...(relation.weight !== undefined ? { weight: relation.weight } : {}),\n ...(relation.metadata !== undefined ? { metadata: relation.metadata } : {}),\n }\n}\n\nfunction canonicalRelationJson(relation: KnowledgeRelation): string {\n if (relation.metadata !== undefined) {\n assertCanonicalMetadata(\n relation.metadata,\n `relation ${describeTriple(relation)}`,\n 'invalid-relation',\n )\n }\n return canonicalCandidateJson({\n ...(relation.weight !== undefined ? { weight: relation.weight } : {}),\n ...(relation.metadata !== undefined ? { metadata: relation.metadata } : {}),\n })\n}\n\nfunction assertCanonicalMetadata(\n metadata: Record<string, unknown>,\n subject: string,\n code: 'invalid-node' | 'invalid-relation',\n): void {\n if (metadata === null || typeof metadata !== 'object' || Array.isArray(metadata)) {\n throw new KnowledgeRelationGraphError(code, `${subject} metadata must be an object`)\n }\n try {\n canonicalCandidateJson(metadata)\n } catch (error) {\n throw new KnowledgeRelationGraphError(\n code,\n `${subject} metadata must be finite, acyclic JSON: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n}\n\nfunction tripleKey(relation: KnowledgeRelation): string {\n return JSON.stringify([relation.sourceId, relation.targetId, relation.predicate])\n}\n\nfunction describeTriple(relation: KnowledgeRelation): string {\n return `${relation.sourceId} -[${relation.predicate}]-> ${relation.targetId}`\n}\n\nfunction isNonEmptyString(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0\n}\n","import {\n type DatasetScenario,\n evaluateReleaseConfidence,\n type HeldOutGateDecision,\n type ReleaseConfidenceScorecard,\n type ReleaseTraceEvidence,\n type RunRecord,\n validateRunRecord,\n} from '@tangle-network/agent-eval'\nimport { stableId } from './ids'\nimport type { KnowledgeRelease } from './types'\n\nexport interface KnowledgeReleaseReport {\n release: KnowledgeRelease\n scorecard: ReleaseConfidenceScorecard\n candidateRuns: RunRecord[]\n baselineRuns: RunRecord[]\n}\n\n/**\n * Build a knowledge release report from candidate and baseline run records,\n * optional trace evidence, and an optional decision record.\n */\nexport interface KnowledgeReleaseInput {\n candidateId: string\n baselineId?: string\n candidateRuns: RunRecord[]\n baselineRuns?: RunRecord[]\n traces?: ReleaseTraceEvidence[]\n gateDecision?: HeldOutGateDecision | null\n /** Scenario corpus used to prove train and holdout split coverage. */\n scenarios?: readonly DatasetScenario[]\n /**\n * Require both a holdout scenario and a holdout run.\n * Provide `scenarios` with at least one `split: 'holdout'` item when true.\n */\n hasHoldout?: boolean\n /** Candidate is the search-best variant — a promotion precondition. Default true. */\n promotedIsBest?: boolean\n createdAt?: string\n minScore?: number\n}\n\nexport function knowledgeReleaseReport(input: KnowledgeReleaseInput): KnowledgeReleaseReport {\n const baselineRuns = input.baselineRuns ?? []\n const runRecords = [...input.candidateRuns, ...baselineRuns].map(validateRunRecord)\n const scorecard = evaluateReleaseConfidence({\n target: 'agent-knowledge-base',\n candidateId: input.candidateId,\n baselineId: input.baselineId ?? 'baseline',\n traces: input.traces ?? [],\n runs: runRecords,\n scenarios: input.scenarios,\n gateDecision: input.gateDecision ?? null,\n thresholds: {\n requireCorpus: false,\n // This report has run records but no scenario corpus, so it cannot require\n // a positive scenario count.\n minScenarioCount: 0,\n requireHoldout: input.hasHoldout ?? false,\n minHoldoutRuns: input.hasHoldout ? 1 : 0,\n minSearchRuns: 1,\n minMeanScore: input.minScore ?? 0.7,\n },\n })\n const release: KnowledgeRelease = {\n id: stableId('krel', `${input.candidateId}:${input.createdAt ?? new Date().toISOString()}`),\n candidateId: input.candidateId,\n createdAt: input.createdAt ?? new Date().toISOString(),\n promoted: scorecard.status !== 'fail' && (input.promotedIsBest ?? true),\n scorecard,\n runRecordIds: runRecords.map((record) => record.runId),\n }\n return { release, scorecard, candidateRuns: input.candidateRuns, baselineRuns }\n}\n","/**\n * Research-DRIVING driver for `runVerifiedResearchLoop`.\n *\n * The shipped drivers all FILTER the worker's sources:\n * - `createVerifyingResearchDriver` judges on-topic relevance,\n * - `createAdaptiveResearchDriver` dedups then triages then escalates,\n * - `createClaimGroundingVerifier` rejects misattributed citations.\n *\n * This driver does the OPPOSITE job: instead of narrowing the worker's output,\n * it DRIVES the research DEEPER each round. Its value is not \"fewer sources\" —\n * it is \"more answered, better-corroborated sub-questions\". Concretely, each\n * round it:\n *\n * 1. EXTRACTS the key claims from the worker's new sources (one LLM pass per\n * source, in `verifySource`; falls back to a deterministic sentence-pull\n * when the model is unavailable so a round never silently extracts nothing).\n * 2. TRACKS each claim's support — the set of INDEPENDENT sources (by canonical\n * host) that assert it — and detects CONTRADICTIONS between a new claim and\n * one already on the ledger.\n * 3. GENERATES the next round's DEEP sub-questions from the accumulated claims,\n * in four kinds — comparative (\"how does X's tradeoff differ from Y's?\"),\n * mechanism (\"under what precise condition does X fail?\"), gap (\"what\n * specific result is missing?\"), and contradiction (\"does any source\n * challenge claim Z?\").\n * 4. FLAGS weakly-supported claims (only ONE independent source) and\n * contradicted claims as INVALIDATION targets and demands the worker find\n * corroborating / refuting evidence for them.\n * 5. FOLDS the deep sub-questions + invalidation challenges into the worker's\n * next prompt via the loop's `foldGaps` → `steer` channel — that is the\n * mechanism that drives DEPTH and VALIDATION rather than breadth.\n *\n * COMPLETION (`isComplete` / the `done` judgment the caller gates on) does NOT\n * look at source COUNT. It is done only when every deep sub-question it raised\n * has been addressed AND every key claim is either supported by >= 2 independent\n * sources OR explicitly marked CONTESTED (a contradiction the loop surfaced and\n * could not resolve). A KB with twenty sources all asserting one unchallenged\n * claim is NOT done; a KB whose handful of claims are each corroborated or\n * contested IS.\n *\n * It reuses `runVerifiedResearchLoop` (it is a plain `ResearchDriver`), the web\n * worker, `claim-ledger.ts` (claim identity, independent-source identity, and\n * the merge rule), and the `RouterClient` chat surface; it reinvents none of\n * them.\n */\n\nimport {\n claimEvidenceId,\n claimId,\n deepQuestionId,\n claimSourceHost as hostOf,\n mergeClaimLedgers,\n normalizeClaimText,\n researchSourceVersionKey,\n} from './claim-ledger'\nimport { sha256, textSourceId } from './ids'\nimport { assertClaimLedgerId, type ClaimLedgerStore } from './kb-store'\nimport { snapshotSourceTextInput } from './sources'\nimport type {\n DeepQuestion,\n DeepQuestionKind,\n ResearchClaimEvidence,\n ResearchClaimLedger,\n ResearchClaimRecord,\n ResearchSourceVersion,\n SourceRecord,\n TrackedClaim,\n} from './types'\nimport type {\n KnowledgeGap,\n ResearchDriver,\n ResearchSourceProposal,\n SourceVerdict,\n SourceVerificationContext,\n} from './verified-research-loop'\nimport {\n createTangleRouterClient,\n type RouterClient,\n type TangleRouterOptions,\n} from './web-research-worker'\n\n// The live claim type and its durable ledger records live in `types.ts` with\n// the package's other public shapes. Re-exported here so existing importers\n// keep working.\nexport type {\n DeepQuestion,\n DeepQuestionKind,\n ResearchClaimEvidence,\n ResearchClaimLedger,\n ResearchClaimRecord,\n ResearchSourceVersion,\n TrackedClaim,\n}\n\n/** The driver's accumulated research state — the completion oracle reads this. */\nexport interface ResearchDrivingState {\n /** Every extracted claim backed by a registered source, by id. */\n claims: TrackedClaim[]\n /** Every deep sub-question raised, by id. */\n questions: DeepQuestion[]\n /** Claims with exactly one independent source AND not contested. */\n weaklySupported: TrackedClaim[]\n /** Claims supported by >= 2 independent sources. */\n corroborated: TrackedClaim[]\n /** Claims marked contested (a surfaced, unresolved contradiction). */\n contested: TrackedClaim[]\n /** Deep questions still unaddressed. */\n openQuestions: DeepQuestion[]\n /** How many rounds the driver has folded steer for. */\n rounds: number\n}\n\nexport interface ResearchDrivingDriverOptions {\n /** Router client for claim extraction + deep-question generation. */\n router?: RouterClient\n router_options?: TangleRouterOptions\n /**\n * A claim is CORROBORATED at this many INDEPENDENT supporting sources (distinct\n * canonical hosts). Default 2 — the task's \">= 2 independent sources\" bar.\n */\n minIndependentSources?: number\n /** Max deep sub-questions to fold into one round's steer. Default 6. */\n maxQuestionsPerRound?: number\n /** Max claims to extract from a single source. Default 3. */\n maxClaimsPerSource?: number\n /**\n * When the extractor LLM is unavailable, fall back to a deterministic claim\n * pull (the source's leading sentences) so the driver still drives. Default\n * true. Set false to require the model (claims will be empty without it).\n */\n deterministicFallback?: boolean\n /** Observe each round's generated steer (for instrumentation / the script). */\n onSteer?: (steer: ResearchDrivingSteer) => void\n}\n\n/**\n * Options for the durable driver: the same driver plus a store to keep its\n * belief state in.\n */\nexport interface PersistentResearchDrivingDriverOptions extends ResearchDrivingDriverOptions {\n /** Where the claim ledger is read from and written to. */\n store: ClaimLedgerStore\n /**\n * Names this run's ledger. Stable across resumes (that is what makes a resume\n * a resume) and distinct per run against one knowledge base. Must be a single\n * safe path segment — see `assertClaimLedgerId`.\n */\n ledgerId: string\n}\n\n/** What the driver folded into one round's worker prompt, surfaced for audit. */\nexport interface ResearchDrivingSteer {\n round: number\n deepQuestions: DeepQuestion[]\n /** Claims it demanded corroborating/refuting evidence for this round. */\n invalidationTargets: TrackedClaim[]\n /** The readiness gaps it interleaved (passed through from the loop). */\n gaps: KnowledgeGap[]\n /** The full steer text handed to the worker. */\n text: string\n}\n\n/**\n * The research-driving driver. It is a `ResearchDriver` (drops straight into\n * `runVerifiedResearchLoop`) PLUS a completion oracle and live state, mirroring\n * how `createAdaptiveResearchDriver` exposes `stats()`.\n */\nexport interface ResearchDrivingDriver extends ResearchDriver {\n /** Live snapshot of the claim ledger + deep questions. */\n researchState(): ResearchDrivingState\n /**\n * The completion oracle — gate `done` on THIS, not on source count. True when\n * every deep sub-question is addressed AND every claim is corroborated\n * (>= `minIndependentSources` independent sources) or explicitly contested.\n * False while any claim is weakly-supported or any deep question is open.\n * Returns false before any claim has been seen (nothing researched yet).\n */\n isComplete(): boolean\n /**\n * The last round's generated steer, or undefined before the first fold. Useful\n * to assert the driver produced deeper questions / invalidation challenges.\n */\n lastSteer(): ResearchDrivingSteer | undefined\n /**\n * Write the current belief state to the store. `verifySource` already persists\n * each pending observation; this exists for the state `foldGaps` produces —\n * the deep questions — which is raised by a synchronous hook and would\n * otherwise be lost if the process died before the next source arrived.\n *\n * `runVerifiedResearchLoop` calls this at the end of every round. A driver\n * built without a store has nothing to write and resolves immediately.\n */\n checkpoint(): Promise<void>\n /** Durably announce the next synchronous fold before it begins. */\n prepareFold(): Promise<void>\n /**\n * Confirm exact registered source records.\n * URI equality alone is insufficient: pending evidence is authorized only\n * when its expected content hash matches the registered record.\n */\n commitSources(sources: readonly SourceRecord[]): Promise<void>\n /** The ledger record as it would be written right now. */\n toLedger(): ResearchClaimLedger\n}\n\n/** A claim the extractor returns for one source. */\ninterface ExtractedClaim {\n text: string\n /** A claim id ALREADY on the ledger that this one CONTRADICTS, if the model says so. */\n contradictsExistingId?: string\n}\n\n/**\n * The in-memory driver. Its belief state lives for exactly as long as the\n * process does — use `createPersistentResearchDrivingDriver` when the run must\n * survive a crash or resume.\n */\nexport function createResearchDrivingDriver(\n options: ResearchDrivingDriverOptions = {},\n): ResearchDrivingDriver {\n return buildDriver(options)\n}\n\n/**\n * The durable driver: same behaviour, plus its claim ledger is read from the\n * store at construction and written back after every claim and every round.\n *\n * Construction is asynchronous because loading is I/O, and loading has to happen\n * before the caller can read `researchState()` or `isComplete()` — a driver that\n * loaded lazily would answer \"nothing researched, not complete\" for a run that\n * had already corroborated everything.\n */\nexport async function createPersistentResearchDrivingDriver(\n options: PersistentResearchDrivingDriverOptions,\n): Promise<ResearchDrivingDriver> {\n const ledgerId = assertClaimLedgerId(options.ledgerId)\n const existing = await options.store.getClaimLedger(ledgerId)\n const driver = buildDriver(options, { store: options.store, ledgerId }, existing ?? undefined)\n if (existing && (existing.preparedRounds ?? existing.rounds) > existing.rounds) {\n await driver.checkpoint()\n }\n return driver\n}\n\ninterface DriverPersistence {\n store: ClaimLedgerStore\n ledgerId: string\n}\n\nfunction buildDriver(\n options: ResearchDrivingDriverOptions,\n persistence?: DriverPersistence,\n restored?: ResearchClaimLedger,\n): ResearchDrivingDriver {\n const minIndependentSources = Math.max(2, options.minIndependentSources ?? 2)\n const maxQuestionsPerRound = Math.max(1, options.maxQuestionsPerRound ?? 6)\n const maxClaimsPerSource = Math.max(1, options.maxClaimsPerSource ?? 3)\n const deterministicFallback = options.deterministicFallback ?? true\n\n // The claim ledger, keyed by claim id (sha256 of the normalized claim text).\n const claims = new Map<string, TrackedClaim>(\n (restored?.claims ?? []).map((claim) => [claim.id, fromRecord(claim)]),\n )\n // Claim extraction and source registration are two separate durable writes.\n // Evidence remains inert until its exact source version is confirmed here.\n const claimEvidence = new Map<string, ResearchClaimEvidence>(\n (restored?.claimEvidence ?? []).map((evidence) => [evidence.id, evidence]),\n )\n const registeredSources = new Map<string, ResearchSourceVersion>(\n (restored?.registeredSources ?? []).map((source) => [source.sourceId, source]),\n )\n // Every deep question raised, by id — so we can mark them addressed later.\n const questions = new Map<string, DeepQuestion>(\n (restored?.questions ?? []).map((question) => [question.id, question]),\n )\n let rounds = restored?.rounds ?? 0\n let preparedRounds = Math.max(rounds, restored?.preparedRounds ?? rounds)\n let goal = restored?.goal\n let lastSteer: ResearchDrivingSteer | undefined\n\n // `prepareFold` is persisted before the synchronous fold starts. If the\n // process died during that fold, regenerate its deterministic questions now\n // and advance the in-memory round; `createPersistentResearchDrivingDriver`\n // checkpoints this recovered state before returning it.\n if (preparedRounds > rounds) {\n for (let round = rounds + 1; round <= preparedRounds; round += 1) {\n for (const question of synthesizeDeepQuestions([...claims.values()], round).slice(\n 0,\n maxQuestionsPerRound,\n )) {\n if (!questions.has(question.id)) questions.set(question.id, question)\n }\n }\n rounds = preparedRounds\n }\n\n function toLedger(): ResearchClaimLedger {\n return {\n schemaVersion: 2,\n id: persistence?.ledgerId ?? 'in-memory',\n ...(goal === undefined ? {} : { goal }),\n updatedAt: new Date().toISOString(),\n rounds,\n ...(preparedRounds > rounds ? { preparedRounds } : {}),\n claimEvidence: [...claimEvidence.values()].sort((left, right) =>\n left.id.localeCompare(right.id),\n ),\n registeredSources: [...registeredSources.values()].sort((left, right) =>\n left.sourceId.localeCompare(right.sourceId),\n ),\n claims: [...claims.values()]\n .map((claim) => ({\n ...claim,\n supportingHosts: [...new Set(claim.supportingHosts)].sort(),\n supportingUris: [...new Set(claim.supportingUris)].sort(),\n contradicts: [...new Set(claim.contradicts)].sort(),\n }))\n .sort((a, b) => a.id.localeCompare(b.id)),\n questions: [...questions.values()]\n .map((question) => ({\n ...question,\n claimIds: [...new Set(question.claimIds)].sort(),\n }))\n .sort((a, b) => a.id.localeCompare(b.id)),\n }\n }\n\n /**\n * Write this driver's belief state into the stored ledger and adopt the\n * result.\n *\n * It merges rather than overwrites, and then rehydrates from the merged\n * record, which is the whole of what makes knowledge compound across\n * workers. Two drivers on one ledger id — a resumed run beside a still-live\n * one, or two workers researching one goal in parallel — would otherwise each\n * write a whole record built from what it read before the other wrote, and\n * the later write would erase the earlier writer's claims. Rehydrating means\n * a claim another worker corroborated counts toward THIS driver's completion\n * oracle from the next round onward.\n */\n async function persist(): Promise<void> {\n if (!persistence) return\n const mine = toLedger()\n const merged = await persistence.store.mergeClaimLedger(persistence.ledgerId, (current) =>\n current === null ? mine : mergeClaimLedgers(current, mine),\n )\n claims.clear()\n for (const claim of merged.claims) claims.set(claim.id, fromRecord(claim))\n claimEvidence.clear()\n for (const evidence of merged.claimEvidence) claimEvidence.set(evidence.id, evidence)\n registeredSources.clear()\n for (const source of merged.registeredSources) {\n registeredSources.set(source.sourceId, source)\n }\n questions.clear()\n for (const question of merged.questions) questions.set(question.id, question)\n rounds = Math.max(rounds, merged.rounds)\n preparedRounds = Math.max(rounds, merged.preparedRounds ?? merged.rounds)\n goal = merged.goal ?? goal\n }\n\n async function prepareFold(): Promise<void> {\n if (!persistence) return\n preparedRounds = Math.max(preparedRounds, rounds + 1)\n await persist()\n }\n\n /**\n * A ledger accumulates evidence FOR a goal. Reusing one id across two goals\n * merges two runs' beliefs into one corroboration count, which is worse than\n * losing them, so it fails rather than merging.\n */\n function bindGoal(nextGoal: string): void {\n if (goal === undefined) {\n goal = nextGoal\n return\n }\n if (goal !== nextGoal) {\n throw new Error(\n `claim ledger '${persistence?.ledgerId ?? 'in-memory'}' accumulated evidence for goal ` +\n `'${goal}' and cannot be reused for '${nextGoal}'`,\n )\n }\n }\n\n function resolveRouter(): RouterClient {\n return options.router ?? createTangleRouterClient(options.router_options)\n }\n\n /** Record a claim from a source, growing its independent-source support. */\n function recordClaim(extracted: ExtractedClaim, sourceUri: string, round: number): TrackedClaim {\n const id = claimId(extracted.text)\n const host = hostOf(sourceUri)\n const existing = claims.get(id)\n if (existing) {\n if (host) existing.supportingHosts.add(host)\n addUnique(existing.supportingUris, sourceUri)\n linkContradiction(existing, extracted.contradictsExistingId)\n return existing\n }\n const tracked: TrackedClaim = {\n id,\n text: extracted.text.trim(),\n supportingHosts: new Set(host ? [host] : []),\n supportingUris: [sourceUri],\n contradicts: new Set(),\n contested: false,\n firstSeenRound: round,\n }\n linkContradiction(tracked, extracted.contradictsExistingId)\n claims.set(id, tracked)\n return tracked\n }\n\n /** Persist an extraction observation without treating its source as registered. */\n function recordEvidence(\n extracted: ExtractedClaim,\n sourceVersion: ResearchSourceVersion,\n round: number,\n ): ResearchClaimEvidence {\n const text = extracted.text.trim()\n const observedClaimId = claimId(text)\n const contradictsClaimId =\n extracted.contradictsExistingId === observedClaimId\n ? undefined\n : extracted.contradictsExistingId\n const evidence: ResearchClaimEvidence = {\n id: claimEvidenceId({\n claimId: observedClaimId,\n sourceId: sourceVersion.sourceId,\n sourceUri: sourceVersion.uri,\n sourceContentHash: sourceVersion.contentHash,\n contradictsClaimId,\n }),\n claimId: observedClaimId,\n text,\n sourceId: sourceVersion.sourceId,\n sourceUri: sourceVersion.uri,\n sourceContentHash: sourceVersion.contentHash,\n ...(contradictsClaimId === undefined ? {} : { contradictsClaimId }),\n firstSeenRound: round,\n }\n const existing = claimEvidence.get(evidence.id)\n if (!existing) {\n claimEvidence.set(evidence.id, evidence)\n return evidence\n }\n const earlier =\n evidence.firstSeenRound < existing.firstSeenRound ||\n (evidence.firstSeenRound === existing.firstSeenRound && evidence.text < existing.text)\n ? evidence\n : existing\n const merged = {\n ...earlier,\n firstSeenRound: Math.min(existing.firstSeenRound, evidence.firstSeenRound),\n }\n claimEvidence.set(merged.id, merged)\n return merged\n }\n\n /** Materialize evidence for newly confirmed exact source versions into live claims. */\n function materializeEvidenceFor(sourceVersions: ReadonlySet<string>): string[] {\n const evidence = [...claimEvidence.values()].filter((item) =>\n sourceVersions.has(sourceVersionKeyOfEvidence(item)),\n )\n const texts: string[] = []\n for (const item of evidence) {\n recordClaim(\n { text: item.text, contradictsExistingId: item.contradictsClaimId },\n item.sourceUri,\n item.firstSeenRound,\n )\n texts.push(item.text)\n }\n // A refuter can sort before the original claim, so close edges only after\n // every claim for this confirmation batch exists.\n for (const item of evidence) {\n const claim = claims.get(item.claimId)\n if (claim) linkContradiction(claim, item.contradictsClaimId)\n }\n return texts\n }\n\n async function commitSources(sources: readonly SourceRecord[]): Promise<void> {\n const versions = sources.map(sourceVersionOfRecord)\n const nextRegistered = new Map(registeredSources)\n const newlyRegistered = new Set<string>()\n for (const version of versions) {\n const key = researchSourceVersionKey(version)\n const existing = nextRegistered.get(version.sourceId)\n if (existing && researchSourceVersionKey(existing) !== key) {\n throw new Error(`registered source '${version.sourceId}' has conflicting immutable content`)\n }\n if (existing) continue\n nextRegistered.set(version.sourceId, version)\n newlyRegistered.add(key)\n }\n registeredSources.clear()\n for (const [sourceId, version] of nextRegistered) registeredSources.set(sourceId, version)\n if (newlyRegistered.size > 0) {\n markAddressed(materializeEvidenceFor(newlyRegistered))\n }\n await persist()\n }\n\n /** Wire a bidirectional contradiction edge and mark BOTH claims contested. */\n function linkContradiction(claim: TrackedClaim, otherId: string | undefined): void {\n if (!otherId || otherId === claim.id) return\n const other = claims.get(otherId)\n if (!other) return\n claim.contradicts.add(otherId)\n other.contradicts.add(claim.id)\n claim.contested = true\n other.contested = true\n }\n\n /** A claim's independent-source count = distinct canonical hosts. */\n function independentSupport(claim: TrackedClaim): number {\n return claim.supportingHosts.size\n }\n\n function isCorroborated(claim: TrackedClaim): boolean {\n return independentSupport(claim) >= minIndependentSources\n }\n\n /** Weakly-supported = NOT corroborated AND NOT contested → an invalidation target. */\n function isWeak(claim: TrackedClaim): boolean {\n return !isCorroborated(claim) && !claim.contested\n }\n\n function snapshot(): ResearchDrivingState {\n const all = [...claims.values()]\n const allQuestions = [...questions.values()]\n return {\n claims: all,\n questions: allQuestions,\n weaklySupported: all.filter(isWeak),\n corroborated: all.filter(isCorroborated),\n contested: all.filter((claim) => claim.contested),\n openQuestions: allQuestions.filter((question) => !question.addressed),\n rounds,\n }\n }\n\n /**\n * Mark deep questions addressed when later evidence speaks to them. A question\n * is addressed once a NEW claim's text shares enough content words with the\n * question — i.e. the worker brought back evidence on the thing we asked about.\n * Cheap and deterministic; the LLM is reserved for GENERATING questions, not\n * grading them, so the oracle stays a non-model check.\n */\n function markAddressed(newClaimTexts: string[]): void {\n for (const question of questions.values()) {\n if (question.addressed) continue\n // Contradiction questions resolve when one of their claims becomes\n // corroborated or contested (the disagreement was surfaced/settled).\n if (question.kind === 'contradiction') {\n const settled = question.claimIds.some((id) => {\n const claim = claims.get(id)\n return claim ? isCorroborated(claim) || claim.contested : false\n })\n if (settled) question.addressed = true\n continue\n }\n const qWords = contentWordSet(question.text)\n if (qWords.size === 0) continue\n for (const text of newClaimTexts) {\n const overlap = overlapFraction(qWords, contentWordSet(text))\n if (overlap >= 0.5) {\n question.addressed = true\n break\n }\n }\n }\n }\n\n return {\n /**\n * `verifySource` — the per-source hook. This driver does NOT filter for\n * relevance/dedup (other drivers do that, and the loop already dedups exact\n * uris). Its job here is to EXTRACT the source's claims and grow the ledger.\n * It accepts every source that yields at least one extractable claim; it\n * only rejects a source with NO extractable signal at all (empty/unusable),\n * because such a source cannot drive the research and pollutes the KB.\n */\n async verifySource(\n source: ResearchSourceProposal,\n ctx: SourceVerificationContext,\n ): Promise<SourceVerdict> {\n const sourceSnapshot = snapshotSourceTextInput(source)\n const goalSnapshot = ctx.goal\n const roundSnapshot = ctx.round\n const sourceVersion = sourceVersionOfProposal(sourceSnapshot)\n bindGoal(goalSnapshot)\n const extracted = await extractClaims(sourceSnapshot, goalSnapshot)\n if (extracted.length === 0) {\n return {\n accept: false,\n reason: 'no extractable claim: source yields nothing to drive the research deeper',\n }\n }\n for (const claim of extracted) {\n recordEvidence(claim, sourceVersion, roundSnapshot)\n }\n if (!persistence) {\n const key = researchSourceVersionKey(sourceVersion)\n registeredSources.set(sourceVersion.sourceId, sourceVersion)\n markAddressed(materializeEvidenceFor(new Set([key])))\n } else {\n const registered = registeredSources.get(sourceVersion.sourceId)\n if (\n registered &&\n researchSourceVersionKey(registered) === researchSourceVersionKey(sourceVersion)\n ) {\n // Direct callers can verify an exact version already present in the\n // registry. Its newly extracted evidence is safe to materialize now.\n markAddressed(materializeEvidenceFor(new Set([researchSourceVersionKey(sourceVersion)])))\n }\n }\n // Persist the observation BEFORE accepting. It remains pending until the\n // loop confirms source registration through `commitSources`, closing both\n // possible crash directions without a cross-store transaction.\n await persist()\n return { accept: true }\n },\n\n /**\n * `foldGaps` — the DEPTH driver. Runs after the worker's contribution is\n * applied each round. It builds the next round's steer from (1) the readiness\n * gaps the loop still reports, (2) freshly generated DEEP sub-questions, and\n * (3) INVALIDATION challenges for weakly-supported / contradicted claims.\n */\n foldGaps(gaps: KnowledgeGap[]): string {\n if (persistence && preparedRounds <= rounds) {\n throw new Error('persistent research driver must prepareFold before foldGaps')\n }\n rounds += 1\n const round = rounds\n const ledger = [...claims.values()]\n\n // Invalidation targets: claims with one source (need corroboration) OR\n // contradicted claims (need a refutation/resolution). These are what the\n // worker is told to go SHORE UP, not new breadth.\n const invalidationTargets = ledger.filter(\n (claim) => isWeak(claim) || claim.contradicts.size > 0,\n )\n\n // Generate this round's deep sub-questions from the actual ledger claims\n // and register them so completion can track whether they get addressed.\n const deepQuestions = synthesizeDeepQuestions(ledger, round).slice(0, maxQuestionsPerRound)\n for (const question of deepQuestions) {\n if (!questions.has(question.id)) questions.set(question.id, question)\n }\n\n const text = buildSteerText(gaps, deepQuestions, invalidationTargets, minIndependentSources)\n lastSteer = { round, deepQuestions, invalidationTargets, gaps, text }\n options.onSteer?.(lastSteer)\n return text\n },\n\n researchState: snapshot,\n\n isComplete(): boolean {\n const all = [...claims.values()]\n if (all.length === 0) return false\n const everyClaimSettled = all.every((claim) => isCorroborated(claim) || claim.contested)\n const everyQuestionAddressed = [...questions.values()].every((question) => question.addressed)\n return everyClaimSettled && everyQuestionAddressed\n },\n\n lastSteer(): ResearchDrivingSteer | undefined {\n return lastSteer\n },\n\n checkpoint: persist,\n\n prepareFold,\n\n commitSources,\n\n toLedger,\n }\n\n // -- claim extraction ------------------------------------------------------\n\n async function extractClaims(\n source: ResearchSourceProposal,\n goal: string,\n ): Promise<ExtractedClaim[]> {\n const ledger = claimsForExtraction()\n const fromLlm = await extractClaimsWithLlm(source, goal, ledger)\n if (fromLlm.length > 0) return fromLlm.slice(0, maxClaimsPerSource)\n if (deterministicFallback) return deterministicClaims(source).slice(0, maxClaimsPerSource)\n return []\n }\n\n function claimsForExtraction(): TrackedClaim[] {\n const known = new Map(claims)\n for (const evidence of claimEvidence.values()) {\n if (known.has(evidence.claimId)) continue\n known.set(evidence.claimId, {\n id: evidence.claimId,\n text: evidence.text,\n supportingHosts: new Set(),\n supportingUris: [],\n contradicts: new Set(),\n contested: false,\n firstSeenRound: evidence.firstSeenRound,\n })\n }\n return [...known.values()]\n }\n\n async function extractClaimsWithLlm(\n source: ResearchSourceProposal,\n goal: string,\n ledger: TrackedClaim[],\n ): Promise<ExtractedClaim[]> {\n let router: RouterClient\n try {\n router = resolveRouter()\n } catch {\n return []\n }\n const excerpt = source.text.slice(0, 1800)\n const ledgerLines = ledger\n .slice(0, 20)\n .map((claim) => `- [${claim.id}] ${claim.text}`)\n .join('\\n')\n const system =\n 'You extract the KEY factual claims a researcher would cite a page for, and flag ' +\n 'CONTRADICTIONS with claims already on the ledger. ' +\n \"A claim is one concrete, checkable assertion using the page's own terms and numbers. \" +\n 'Return ONLY a JSON array; each item is {\"claim\": string, \"contradicts\": string|null} where ' +\n 'contradicts is the bracketed [id] of a ledger claim this page DIRECTLY contradicts, else null. ' +\n `Return at most ${maxClaimsPerSource} claims. No prose.`\n const user = [\n `Research goal: ${goal}`,\n `Page title: ${source.title ?? '(none)'}`,\n ledgerLines ? `Claims already on the ledger:\\n${ledgerLines}` : 'Ledger is empty.',\n `Page excerpt:\\n${excerpt}`,\n 'Key claims as JSON [{\"claim\": \"...\", \"contradicts\": \"[id]\"|null}]:',\n ].join('\\n\\n')\n\n let raw = ''\n try {\n raw = await router.chat(\n [\n { role: 'system', content: system },\n { role: 'user', content: user },\n ],\n 1200,\n )\n } catch {\n return []\n }\n return parseExtractedClaims(raw, ledger)\n }\n\n /**\n * Deterministic fallback: pull the leading sentences as candidate claims. Used\n * only when the model is unavailable, so the driver still drives (and the\n * offline test runs with no creds). Each sentence becomes a checkable claim.\n */\n function deterministicClaims(source: ResearchSourceProposal): ExtractedClaim[] {\n const sentences = source.text\n .split(/(?<=[.!?])\\s+/)\n .map((sentence) => sentence.trim())\n .filter((sentence) => contentWordSet(sentence).size >= 3)\n return sentences.slice(0, maxClaimsPerSource).map((text) => ({ text }))\n }\n\n // -- deep-question synthesis ----------------------------------------------\n\n /**\n * Build the four deep-question kinds from the actual ledger claims. This is\n * intentionally deterministic (not an LLM call): the loop's `foldGaps` contract\n * is synchronous (`foldGaps(gaps): string`), and a template grounded in the\n * real claim text gives a faithful, non-fabricated sub-question every round —\n * comparative, mechanism, gap, and contradiction. Claim EXTRACTION, which runs\n * inside the awaited `verifySource`, is where the model does the open-ended\n * work; question generation just interrogates what was extracted.\n */\n function synthesizeDeepQuestions(ledger: TrackedClaim[], round: number): DeepQuestion[] {\n if (ledger.length === 0) return []\n const out: DeepQuestion[] = []\n\n // CONTRADICTION questions: for every contradiction edge, ask the worker to\n // find evidence that resolves which claim holds.\n for (const claim of ledger) {\n for (const otherId of claim.contradicts) {\n const other = ledger.find((entry) => entry.id === otherId)\n if (!other || other.id < claim.id) continue // emit each pair once\n out.push(\n makeQuestion(\n 'contradiction',\n `Does any independent source resolve the contradiction between \"${truncate(claim.text)}\" and \"${truncate(other.text)}\"? Find evidence that confirms or refutes one of them.`,\n [claim.id, other.id],\n round,\n ),\n )\n }\n }\n\n // GAP questions: for each weakly-supported claim, ask for the specific\n // corroborating result that is missing.\n for (const claim of ledger.filter((entry) => !entry.contested)) {\n if (claim.supportingHosts.size < minIndependentSources) {\n out.push(\n makeQuestion(\n 'gap',\n `Only one independent source supports \"${truncate(claim.text)}\". What specific corroborating result, dataset, or independent measurement is missing to confirm it?`,\n [claim.id],\n round,\n ),\n )\n }\n }\n\n // Probe where the best-supported claims stop holding.\n for (const claim of [...ledger]\n .sort((a, b) => b.supportingHosts.size - a.supportingHosts.size)\n .slice(0, 2)) {\n out.push(\n makeQuestion(\n 'mechanism',\n `Under what precise condition does \"${truncate(claim.text)}\" stop holding? Find a source that states the mechanism, limit, or failure mode.`,\n [claim.id],\n round,\n ),\n )\n }\n\n // Compare tradeoffs between the two best-supported claims.\n const ranked = [...ledger].sort((a, b) => b.supportingHosts.size - a.supportingHosts.size)\n if (ranked.length >= 2 && ranked[0] && ranked[1]) {\n out.push(\n makeQuestion(\n 'comparative',\n `How does the tradeoff in \"${truncate(ranked[0].text)}\" differ from \"${truncate(ranked[1].text)}\"? Find a source that compares them directly.`,\n [ranked[0].id, ranked[1].id],\n round,\n ),\n )\n }\n\n // Stable order: contradiction → gap → mechanism → comparative (most urgent\n // validation work first).\n const priority: Record<DeepQuestionKind, number> = {\n contradiction: 0,\n gap: 1,\n mechanism: 2,\n comparative: 3,\n }\n return out.sort((a, b) => priority[a.kind] - priority[b.kind])\n }\n}\n\n// ---------------------------------------------------------------------------\n// pure helpers\n// ---------------------------------------------------------------------------\n\nfunction sourceVersionOfProposal(source: ResearchSourceProposal): ResearchSourceVersion {\n const contentHash = sha256(source.text)\n return {\n sourceId: textSourceId(source.uri, contentHash),\n uri: source.uri,\n contentHash,\n }\n}\n\nfunction sourceVersionOfRecord(source: SourceRecord): ResearchSourceVersion {\n const originalUri = source.metadata?.originalUri\n if (typeof originalUri !== 'string' || originalUri.length === 0) {\n throw new Error(`registered source '${source.id}' has no originalUri`)\n }\n if (!/^[a-f0-9]{64}$/.test(source.contentHash)) {\n throw new Error(`registered source '${source.id}' contentHash is not a SHA-256 digest`)\n }\n const expectedSourceId = textSourceId(originalUri, source.contentHash)\n if (source.id !== expectedSourceId) {\n throw new Error(\n `registered source '${source.id}' does not match URI-and-content identity '${expectedSourceId}'`,\n )\n }\n return { sourceId: source.id, uri: originalUri, contentHash: source.contentHash }\n}\n\nfunction sourceVersionKeyOfEvidence(evidence: ResearchClaimEvidence): string {\n return researchSourceVersionKey({\n sourceId: evidence.sourceId,\n uri: evidence.sourceUri,\n contentHash: evidence.sourceContentHash,\n })\n}\n\nfunction makeQuestion(\n kind: DeepQuestionKind,\n text: string,\n claimIds: string[],\n raisedRound: number,\n): DeepQuestion {\n return {\n kind,\n text,\n id: deepQuestionId(kind, text),\n claimIds: [...new Set(claimIds)].sort(),\n addressed: false,\n raisedRound,\n }\n}\n\nfunction fromRecord(claim: ResearchClaimRecord): TrackedClaim {\n return {\n ...claim,\n supportingHosts: new Set(claim.supportingHosts),\n supportingUris: [...claim.supportingUris],\n contradicts: new Set(claim.contradicts),\n }\n}\n\n/**\n * Set-like insert into the array form. The ledger's collections are arrays so\n * they survive `JSON.stringify`; dedup is enforced here instead of by the type.\n */\nfunction addUnique(values: string[], value: string): void {\n if (!values.includes(value)) values.push(value)\n}\n\nconst stopwords = new Set([\n 'the',\n 'a',\n 'an',\n 'and',\n 'or',\n 'but',\n 'of',\n 'to',\n 'in',\n 'on',\n 'for',\n 'with',\n 'as',\n 'by',\n 'at',\n 'from',\n 'that',\n 'this',\n 'these',\n 'those',\n 'it',\n 'its',\n 'is',\n 'are',\n 'was',\n 'were',\n 'be',\n 'been',\n 'being',\n 'has',\n 'have',\n 'had',\n 'can',\n 'will',\n 'would',\n 'should',\n 'may',\n 'might',\n 'not',\n 'no',\n 'than',\n 'then',\n 'over',\n 'under',\n 'about',\n 'into',\n 'their',\n 'they',\n 'them',\n])\n\nfunction contentWordSet(text: string): Set<string> {\n return new Set(\n normalizeClaimText(text)\n .split(' ')\n .filter((word) => word.length >= 3 && !stopwords.has(word)),\n )\n}\n\nfunction overlapFraction(a: Set<string>, b: Set<string>): number {\n if (a.size === 0) return 0\n let hits = 0\n for (const word of a) if (b.has(word)) hits += 1\n return hits / a.size\n}\n\nfunction truncate(text: string, max = 140): string {\n const t = text.trim().replace(/\\s+/g, ' ')\n return t.length <= max ? t : `${t.slice(0, max - 1)}…`\n}\n\n/**\n * Parse the extractor's JSON array of `{claim, contradicts}` items, tolerant of\n * code fences / surrounding prose. `contradicts` is mapped from a `[id]` token to\n * a ledger claim id only when that id is actually on the ledger.\n */\nfunction parseExtractedClaims(raw: string, ledger: TrackedClaim[]): ExtractedClaim[] {\n const text = raw.trim()\n if (!text) return []\n const arrayMatch = text.match(/\\[[\\s\\S]*\\]/)\n if (!arrayMatch) return []\n let parsed: unknown\n try {\n parsed = JSON.parse(arrayMatch[0])\n } catch {\n return []\n }\n if (!Array.isArray(parsed)) return []\n const ledgerIds = new Set(ledger.map((claim) => claim.id))\n const out: ExtractedClaim[] = []\n for (const item of parsed) {\n if (!item || typeof item !== 'object') continue\n const record = item as { claim?: unknown; contradicts?: unknown }\n if (typeof record.claim !== 'string' || !record.claim.trim()) continue\n const contradictsId = extractBracketId(record.contradicts)\n out.push({\n text: record.claim.trim(),\n contradictsExistingId:\n contradictsId && ledgerIds.has(contradictsId) ? contradictsId : undefined,\n })\n }\n return out\n}\n\n/** Pull a ledger id out of a `contradicts` field: `\"[c_abc]\"` or `\"c_abc\"`. */\nfunction extractBracketId(value: unknown): string | undefined {\n if (typeof value !== 'string') return undefined\n const trimmed = value.trim()\n if (!trimmed || trimmed.toLowerCase() === 'null') return undefined\n const bracket = trimmed.match(/\\[([^\\]]+)\\]/)\n const id = (bracket?.[1] ?? trimmed).trim()\n return id.startsWith('c_') ? id : undefined\n}\n\n/**\n * Build the steer string handed to the worker's next prompt. Interleaves the\n * readiness gaps the loop still reports with the deep sub-questions and the\n * invalidation challenges — the part that drives DEPTH + VALIDATION.\n */\nfunction buildSteerText(\n gaps: KnowledgeGap[],\n deepQuestions: DeepQuestion[],\n invalidationTargets: TrackedClaim[],\n minIndependentSources: number,\n): string {\n const lines: string[] = []\n lines.push(\n 'Do NOT just add more sources. Go DEEPER and VALIDATE. Address the following before adding breadth:',\n )\n\n if (deepQuestions.length > 0) {\n lines.push('', 'Deep sub-questions to answer this round:')\n for (const question of deepQuestions) {\n lines.push(`- (${question.kind}) ${question.text}`)\n }\n }\n\n if (invalidationTargets.length > 0) {\n lines.push(\n '',\n `Claims needing corroboration or refutation (each must reach >= ${minIndependentSources} INDEPENDENT sources, or be shown contested):`,\n )\n for (const claim of invalidationTargets) {\n const reason =\n claim.contradicts.size > 0\n ? 'CONTRADICTED by another source — find evidence that resolves it'\n : `only ${claim.supportingHosts.size} independent source — find a SECOND, independent corroborating source`\n lines.push(`- \"${truncate(claim.text)}\" — ${reason}`)\n }\n }\n\n if (gaps.length > 0) {\n lines.push('', 'Readiness gaps still open:')\n for (const gap of gaps) {\n lines.push(`- (${gap.blocking ? 'blocking' : 'soft'}) ${gap.description} [${gap.id}]`)\n }\n }\n\n return lines.join('\\n')\n}\n"],"mappings":"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AK;EACL,QAAQ;EACR,QAAQ;EACR,cACE;EACF,OAAO;GACL;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MAAC;MAAoB;MAAoB;KAAK;IACvD,GACA;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WAAW;IACX,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;EACF;CACF;CACA;EACE,QAAQ;EACR,SAAS;EACT,KAAK;EACL,QAAQ;EACR,QAAQ;EACR,cAAc;EACd,OAAO;GACL;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UAAU;GACZ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;EACF;CACF;CACA;EACE,QAAQ;EACR,SAAS;EACT,KAAK;EACL,QAAQ;EACR,QAAQ;EACR,cACE;EACF,OAAO;GACL;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UAAU;GACZ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UAAU;GACZ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MAAC;MAAS;MAAe;MAAgB;MAAoB;KAAa;IACnF,CACF;IACA,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UAAU;GACZ;EACF;CACF;CACA;EACE,QAAQ;EACR,SAAS;EACT,KAAK;EACL,QAAQ;EACR,QAAQ;EACR,cACE;EACF,OAAO;GACL;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UAAU;GACZ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UAAU;GACZ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;EACF;CACF;CACA;EACE,QAAQ;EACR,SAAS;EACT,KAAK;EACL,QAAQ;EACR,QAAQ;EACR,cACE;EACF,OAAO;GACL;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KAOE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KAKE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UAAU;GACZ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KAOE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;EACF;CACF;AACF;;;;;;;AAQA,SAAgB,qBACd,MACA,YACwF;CACxF,MAAM,WAAW,WAAW,YAAY;CACxC,MAAM,QAAQ,KAAK,SAAS,QAAQ,UAClC,MAAM,MAAM,MAAM,aAAa,SAAS,SAAS,SAAS,YAAY,CAAC,CAAC,CAC1E;CACA,MAAM,YAAY,KAAK,aAAa,KAAK,SAAS;CAClD,OAAO;EACL,UAAU,MAAM,UAAU;EAC1B,aAAa,MAAM;EACnB,aAAa,KAAK,SAAS;EAC3B,aAAa,MAAM,KAAK,UAAU,MAAM,KAAK;CAC/C;AACF;;AA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"}
1
+ {"version":3,"file":"index.js","names":["exceedsCostCeiling","stopwords","contentWords","stopwords","nonEmpty","hostOf"],"sources":["../src/web-research-worker.ts","../src/adaptive-driver.ts","../src/knowledge-state-scope.ts","../src/kb-improvement/contracts.ts","../src/kb-improvement/state.ts","../src/kb-improvement/activation.ts","../src/rag-answer-evidence.ts","../src/claim-grounding.ts","../src/rag-eval/answer.ts","../src/rag-eval/providers.ts","../src/rag-eval/scoring.ts","../src/rag-eval/calibration.ts","../src/rag-eval/knowledge-base.ts","../src/rag-optimization.ts","../src/events.ts","../src/eval-readiness.ts","../src/readiness-helpers.ts","../src/research-loop.ts","../src/retrieval-optimization.ts","../src/rag-improvement-phases.ts","../src/rag-improvement-loop.ts","../src/kb-improvement/workspace.ts","../src/kb-improvement/transition.ts","../src/kb-improvement/evaluation.ts","../src/kb-improvement/run.ts","../src/kb-improvement/optimization.ts","../src/kb-improvement/selected-candidate.ts","../src/agent-candidate.ts","../src/changes.ts","../src/chunking.ts","../src/citation-lint.ts","../src/collection-research-driver.ts","../src/discovery.ts","../src/filesystem-search-provider.ts","../src/freshness.ts","../src/invalidation-propagation.ts","../src/investment-thesis-set.ts","../src/material-facts-metric.ts","../src/verified-research-loop.ts","../src/investment-thesis-task.ts","../src/knowledge-brief.ts","../src/knowledge-use-receipts.ts","../src/knowledge-tools.ts","../src/promotion.ts","../src/propose-from-finding.ts","../src/readiness-check.ts","../src/relation-graph.ts","../src/release.ts","../src/research-driving-driver.ts"],"sourcesContent":["/**\n * Real web-research worker + verifying driver for `runVerifiedResearchLoop`.\n *\n * This is the GENERAL, any-topic implementation behind the two-agent research\n * loop's live arm. Given the open knowledge gaps the readiness gate surfaces,\n * the worker:\n *\n * 1. asks an LLM (glm-5.2 by default) to turn each gap into focused web\n * search queries,\n * 2. runs a REAL web search over the Tangle router (`POST /v1/search` — the\n * same endpoint `tcloud mcp`'s `web_search` tool forwards to), so there is\n * no hardcoded corpus,\n * 3. fetches the top results with the repo's polite, cached `politeFetch` and\n * reduces each page to text with `htmlToText`,\n * 4. proposes the readable, verifiable pages as `ResearchSourceProposal`s plus\n * a `buildPages` that writes citing `knowledge/*.md` pages from the sources\n * the driver accepts.\n *\n * The verifying DRIVER is the differentiated role from the two-agent loop: a\n * second LLM pass that judges each fetched source's on-topic relevance to the\n * goal + open gaps and rejects off-topic / spam / already-covered material. The\n * worker ADDS; the driver GATES. Together they build a cleaner knowledge base\n * than a single agent at the same compute budget.\n *\n * Model and search requests use the published TCloud SDK. Knowledge owns the\n * research policy, not HTTP, bearer headers, retries or provider rate cards.\n * Point it at any router with `baseUrl`; supply `apiKey` or `TANGLE_API_KEY`.\n */\n\nimport { type SearchProvider, TCloudClient, TCloudError } from '@tangle-network/tcloud'\nimport { htmlToText } from './sources/html'\nimport { politeFetch } from './sources/http'\nimport type { SourceRecord } from './types'\nimport type {\n KnowledgeGap,\n ResearchContribution,\n ResearchDriver,\n ResearchSourceProposal,\n ResearchWorker,\n SourceVerdict,\n SourceVerificationContext,\n WorkerResearchContext,\n} from './verified-research-loop'\n\n/** Default router model. Plain id (no namespace) — see CLAUDE/creds notes. */\nconst DEFAULT_MODEL = 'glm-5.2'\n/** Default router base. */\nconst DEFAULT_BASE_URL = 'https://router.tangle.tools/v1'\n/**\n * glm-5.2 spends its first tokens on hidden `reasoning_content`; below ~1200\n * output tokens it returns EMPTY visible content. Floor every call so a\n * reasoning model never silently yields nothing. (Verified creds note.)\n */\nconst MIN_MAX_TOKENS = 1200\n\n/** One live web result, as the router's `/v1/search` returns it. */\nexport interface WebSearchHit {\n title: string\n url: string\n snippet?: string\n}\n\n/**\n * The two router capabilities the worker/driver need. Injectable so tests can\n * supply a client; the default uses the published TCloud SDK.\n */\nexport interface RouterClient {\n /** Live web search — returns title/url/snippet hits. */\n search(query: string, opts?: { maxResults?: number }): Promise<WebSearchHit[]>\n /** Chat completion — returns the assistant message's visible text. */\n chat(\n messages: { role: 'system' | 'user'; content: string }[],\n maxTokens?: number,\n ): Promise<string>\n /** Cumulative cost (chat + search) since this client was created. */\n usage(): RouterUsage\n}\n\n/**\n * Cumulative router cost — the per-arm signal the A/B reports ALONGSIDE quality,\n * so \"2.3 fewer sources\" can be read against the token/$/latency it cost. A\n * two-agent round is one worker pass plus N `verifySource` LLM calls; counting\n * each call here is what surfaces that the two-agent loop spends more inference\n * than its \"equal passes\" budget implies.\n */\nexport interface RouterUsage {\n chatCalls: number\n searchCalls: number\n promptTokens: number\n completionTokens: number\n /** Reported cost only. NaN once a successful response omits its cost receipt. */\n usd: number\n wallMs: number\n}\n\nexport interface TangleRouterOptions {\n /** Router base URL. Defaults to `https://router.tangle.tools/v1`. */\n baseUrl?: string\n /** Bearer key. Defaults to `process.env.TANGLE_API_KEY`. */\n apiKey?: string\n /** Chat model id. Defaults to `glm-5.2`. */\n model?: string\n /** Optional preferred search provider (exa | you | perplexity | …). */\n searchProvider?: string\n /** SDK retries for 429/502/503/504. Default 4. Kept for API compatibility. */\n maxRetries?: number\n /** Initial SDK retry backoff in ms. Default 1500. */\n retryBaseMs?: number\n signal?: AbortSignal\n}\n\n/** Compatibility error facade. HTTP execution and classification belong to TCloud. */\nexport class RouterError extends Error {\n constructor(\n public readonly status: number,\n message: string,\n ) {\n super(`router ${status}: ${message}`)\n this.name = 'RouterError'\n }\n}\n\n/** Adapt Knowledge's public contract to the published SDK, without a second transport. */\nexport function createTangleRouterClient(options: TangleRouterOptions = {}): RouterClient {\n const apiKey = options.apiKey ?? process.env.TANGLE_API_KEY\n if (!apiKey) throw new RouterError(401, 'no TANGLE_API_KEY (pass apiKey or set the env var)')\n const client = new TCloudClient({\n baseURL: (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, ''),\n apiKey,\n model: options.model ?? DEFAULT_MODEL,\n // Preserve the unbounded reasoning timeout. The caller can cancel the actual request.\n timeout: 0,\n retry: {\n maxRetries: Math.max(0, options.maxRetries ?? 4),\n initialBackoffMs: Math.max(1, options.retryBaseMs ?? 1500),\n retryableStatuses: [429, 502, 503, 504],\n },\n })\n const acc: RouterUsage = {\n chatCalls: 0,\n searchCalls: 0,\n promptTokens: 0,\n completionTokens: 0,\n usd: 0,\n wallMs: 0,\n }\n // NaN is deliberately not zero: an incomplete bill must not win a cost comparison.\n const recordCost = (cost: number | undefined) => {\n acc.usd += typeof cost === 'number' && Number.isFinite(cost) && cost >= 0 ? cost : Number.NaN\n }\n const translate = (error: unknown): never => {\n // Preserve the caller's exact abort reason, including non-Error reasons.\n options.signal?.throwIfAborted()\n if (error instanceof TCloudError) throw new RouterError(error.status, error.message)\n throw error\n }\n\n return {\n async search(query, opts) {\n options.signal?.throwIfAborted()\n const started = Date.now()\n try {\n const response = await client.search({\n query,\n ...(options.searchProvider ? { provider: options.searchProvider as SearchProvider } : {}),\n ...(opts?.maxResults != null ? { maxResults: opts.maxResults } : {}),\n signal: options.signal,\n })\n recordCost(response.usage?.billed_cost)\n return (response.data ?? [])\n .filter((hit) => typeof hit?.url === 'string' && hit.url.length > 0)\n .map((hit) => ({ title: hit.title ?? hit.url, url: hit.url, snippet: hit.snippet }))\n } catch (error) {\n return translate(error)\n } finally {\n acc.searchCalls += 1\n acc.wallMs += Date.now() - started\n }\n },\n async chat(messages, maxTokens) {\n options.signal?.throwIfAborted()\n const started = Date.now()\n try {\n const response = await client.chat({\n messages,\n maxTokens: Math.max(MIN_MAX_TOKENS, maxTokens ?? MIN_MAX_TOKENS),\n temperature: 0.2,\n signal: options.signal,\n })\n acc.chatCalls += 1\n acc.promptTokens += response.usage?.prompt_tokens ?? 0\n acc.completionTokens += response.usage?.completion_tokens ?? 0\n // Per-response cost, not a shared-client usage delta that races parallel calls.\n recordCost(response.tangle?.costSource === 'receipt' ? response.tangle.costUsd : undefined)\n return response.choices?.[0]?.message?.content ?? ''\n } catch (error) {\n return translate(error)\n } finally {\n acc.wallMs += Date.now() - started\n }\n },\n usage() {\n return { ...acc }\n },\n }\n}\n\nexport interface WebResearchWorkerOptions {\n /** Router client. Defaults to a live Tangle router client from env creds. */\n router?: RouterClient\n router_options?: TangleRouterOptions\n /** Max search queries the LLM may form per gap. Default 2. */\n queriesPerGap?: number\n /** Max web results fetched per query. Default 3. */\n resultsPerQuery?: number\n /** Hard cap on sources proposed per round (across all gaps). Default 6. */\n maxSourcesPerRound?: number\n /** Disk cache dir for `politeFetch`. Optional; speeds repeat runs. */\n cacheDir?: string\n /** Minimum readable text length to keep a fetched page. Default 200. */\n minTextChars?: number\n /** Max chars of page text stored per source (keeps pages bounded). Default 4000. */\n maxTextChars?: number\n}\n\n/** Bind run cancellation to the default router without changing an injected client. */\nfunction resolveRouter(\n opts: {\n router?: RouterClient\n router_options?: TangleRouterOptions\n },\n signal?: AbortSignal,\n): RouterClient {\n if (opts.router) return opts.router\n const requestSignal = combineRouterSignals(signal, opts.router_options?.signal)\n return createTangleRouterClient({ ...opts.router_options, signal: requestSignal })\n}\n\nfunction combineRouterSignals(\n runSignal: AbortSignal | undefined,\n configuredSignal: AbortSignal | undefined,\n): AbortSignal | undefined {\n return runSignal && configuredSignal\n ? AbortSignal.any([runSignal, configuredSignal])\n : (runSignal ?? configuredSignal)\n}\n\nfunction throwIfRouterAborted(\n runSignal: AbortSignal | undefined,\n opts: { router?: RouterClient; router_options?: TangleRouterOptions },\n): void {\n runSignal?.throwIfAborted()\n if (!opts.router) opts.router_options?.signal?.throwIfAborted()\n}\n\n/**\n * The real web-research worker. Conforms to the loop's `ResearchWorker`\n * contract: given the open gaps, it returns the sources it found plus a\n * `buildPages` that emits citing pages from the sources the driver accepted.\n */\nexport function createWebResearchWorker(options: WebResearchWorkerOptions = {}): ResearchWorker {\n const queriesPerGap = Math.max(1, options.queriesPerGap ?? 2)\n const resultsPerQuery = Math.max(1, options.resultsPerQuery ?? 3)\n const maxSourcesPerRound = Math.max(1, options.maxSourcesPerRound ?? 6)\n const minTextChars = Math.max(1, options.minTextChars ?? 200)\n const maxTextChars = Math.max(minTextChars, options.maxTextChars ?? 4000)\n\n return async (ctx: WorkerResearchContext): Promise<ResearchContribution> => {\n const assertActive = () => throwIfRouterAborted(ctx.signal, options)\n assertActive()\n const router = resolveRouter(options, ctx.signal)\n const fetchSignal = options.router\n ? ctx.signal\n : combineRouterSignals(ctx.signal, options.router_options?.signal)\n // Target the BLOCKING gaps first; fall back to all gaps if none are blocking.\n const targetGaps = ctx.gaps.filter((gap) => gap.blocking)\n const gaps = targetGaps.length > 0 ? targetGaps : ctx.gaps\n if (gaps.length === 0) {\n return { sources: [], notes: 'no open gaps to research' }\n }\n\n const queries = await formSearchQueries(router, ctx, gaps, queriesPerGap, assertActive)\n assertActive()\n const proposals: ResearchSourceProposal[] = []\n const seenUris = new Set<string>()\n\n for (const query of queries) {\n if (proposals.length >= maxSourcesPerRound) break\n assertActive()\n let hits: WebSearchHit[]\n try {\n hits = await router.search(query, { maxResults: resultsPerQuery })\n } catch (error) {\n assertActive()\n // A single failed query must not sink the round — record nothing, move on.\n if ((error as { name?: string } | null)?.name === 'AbortError') throw error\n continue\n }\n assertActive()\n for (const hit of hits) {\n assertActive()\n if (proposals.length >= maxSourcesPerRound) break\n if (seenUris.has(hit.url)) continue\n const fetched = await politeFetch(hit.url, {\n signal: fetchSignal,\n cacheDir: options.cacheDir,\n })\n assertActive()\n if (!fetched.verifiable) continue\n const text = htmlToText(fetched.body).slice(0, maxTextChars)\n if (text.length < minTextChars) continue\n seenUris.add(hit.url)\n proposals.push({\n uri: hit.url,\n title: hit.title || hit.url,\n text,\n // We just fetched + verified this page, so stamp `lastVerifiedAt` with\n // fetch time. Do NOT set `validUntil`: a live page has no inherent\n // future expiry, and the readiness freshness check treats any\n // `validUntil <= now` as EXPIRED (score 0). The page's `Last-Modified`\n // is a PAST date, so writing it here would mark every real source stale\n // and zero out coverage. Record it as provenance metadata instead.\n lastVerifiedAt: fetched.fetchedAt,\n metadata: {\n discoveredVia: query,\n snippet: hit.snippet ?? '',\n goal: ctx.goal,\n sourceUpdatedAt: fetched.sourceUpdatedAt,\n },\n })\n }\n }\n\n assertActive()\n return {\n sources: proposals,\n buildPages: buildCitingPages(proposals),\n notes: `web-research worker: ${queries.length} queries → ${proposals.length} fetched sources`,\n }\n }\n}\n\n/**\n * Ask the LLM to turn the open gaps into focused web search queries. Falls back\n * to the gap's own readiness query if the model returns nothing parseable, so a\n * model hiccup degrades to a sane search rather than an empty round.\n */\nasync function formSearchQueries(\n router: RouterClient,\n ctx: WorkerResearchContext,\n gaps: KnowledgeGap[],\n queriesPerGap: number,\n assertActive: () => void,\n): Promise<string[]> {\n const gapLines = gaps\n .map((gap, i) => `${i + 1}. ${gap.description} (readiness query: \"${gap.query}\")`)\n .join('\\n')\n const want = gaps.length * queriesPerGap\n const system =\n 'You are a research librarian. Turn knowledge gaps into precise web search queries that will ' +\n 'surface authoritative primary sources (papers, docs, standards, official pages). ' +\n 'Return ONLY a JSON array of query strings, no prose.'\n const user = [\n `Research goal: ${ctx.goal}`,\n ctx.steer ? `Steer from the coordinator:\\n${ctx.steer}` : '',\n `Open knowledge gaps:\\n${gapLines}`,\n `Return up to ${want} search query strings as a JSON array (e.g. [\"query one\",\"query two\"]).`,\n ]\n .filter(Boolean)\n .join('\\n\\n')\n\n let raw = ''\n try {\n raw = await router.chat(\n [\n { role: 'system', content: system },\n { role: 'user', content: user },\n ],\n MIN_MAX_TOKENS,\n )\n assertActive()\n } catch (error) {\n assertActive()\n if ((error as { name?: string } | null)?.name === 'AbortError') throw error\n raw = ''\n }\n const parsed = parseQueryList(raw)\n const fromLlm = parsed.slice(0, want)\n if (fromLlm.length > 0) return dedupeStrings(fromLlm)\n // Degrade to the readiness queries themselves — still a real search.\n return dedupeStrings(gaps.map((gap) => gap.query || gap.description))\n}\n\n/** Parse a JSON array of query strings, tolerant of code fences / surrounding prose. */\nfunction parseQueryList(raw: string): string[] {\n const text = raw.trim()\n if (!text) return []\n const candidates: string[] = []\n // Prefer a fenced or bare JSON array.\n const arrayMatch = text.match(/\\[[\\s\\S]*\\]/)\n if (arrayMatch) {\n try {\n const arr = JSON.parse(arrayMatch[0]) as unknown[]\n for (const item of arr)\n if (typeof item === 'string' && item.trim()) candidates.push(item.trim())\n } catch {\n /* fall through to line parsing */\n }\n }\n if (candidates.length === 0) {\n for (const line of text.split('\\n')) {\n const cleaned = line\n .replace(/^\\s*(?:[-*]|\\d+[.)])\\s*/, '')\n .replace(/^[\"']|[\"']$/g, '')\n .trim()\n if (cleaned && cleaned.length > 2 && !cleaned.startsWith('{')) candidates.push(cleaned)\n }\n }\n return candidates\n}\n\nfunction dedupeStrings(values: string[]): string[] {\n const seen = new Set<string>()\n const out: string[] = []\n for (const value of values) {\n const key = value.toLowerCase().trim()\n if (key && !seen.has(key)) {\n seen.add(key)\n out.push(value.trim())\n }\n }\n return out\n}\n\n/**\n * Build the curated `knowledge/*.md` pages from the sources the driver accepted.\n * Each page cites the registered source by its assigned `record.id` (matched back\n * to the proposal via `metadata.originalUri`, which `addSourceText` stashes).\n */\nfunction buildCitingPages(\n proposals: ResearchSourceProposal[],\n): (acceptedSources: SourceRecord[]) => string | undefined {\n return (acceptedSources) => {\n if (acceptedSources.length === 0) return undefined\n const blocks = acceptedSources.map((record) => {\n const proposal = proposals.find((p) => p.uri === record.metadata?.originalUri)\n const uri = proposal?.uri ?? record.id\n const slug =\n uri\n .replace(/^https?:\\/\\//, '')\n .replace(/[^a-z0-9]+/gi, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 120) || record.id\n const title = proposal?.title ?? record.id\n const body = proposal?.text ?? ''\n return [\n `---FILE: knowledge/${slug}.md---`,\n '---',\n `title: ${escapeYaml(title)}`,\n `sources: [\"${record.id}\"]`,\n `source_url: ${uri}`,\n '---',\n `# ${title}`,\n '',\n body,\n '',\n `Source: ${uri}`,\n '---END FILE---',\n ].join('\\n')\n })\n return blocks.join('\\n')\n }\n}\n\nfunction escapeYaml(value: string): string {\n // Keep the frontmatter line single-valued and safe: collapse newlines, strip\n // quotes that would break the scalar.\n return value\n .replace(/[\\r\\n]+/g, ' ')\n .replace(/\"/g, \"'\")\n .trim()\n}\n\nexport interface VerifyingDriverOptions {\n router?: RouterClient\n router_options?: TangleRouterOptions\n /**\n * When the LLM verdict can't be parsed, default to REJECT (fail-closed) so a\n * model hiccup never poisons the KB with an unverified source. Set `true` to\n * accept-on-parse-failure only if you have a reason to. Default false.\n */\n acceptOnParseFailure?: boolean\n}\n\n/**\n * The verifying driver: a real LLM pass that judges each candidate source's\n * on-topic relevance to the goal + open gaps and whether it duplicates material\n * already accepted this round. This is the differentiated coordinator role — it\n * GATES the worker's additions; it adds nothing itself.\n *\n * The loop already dedups exact-uri duplicates and only calls this on genuinely\n * new candidates, so the verifier focuses on relevance + near-duplicate\n * judgement, not bookkeeping.\n */\nexport function createVerifyingResearchDriver(\n options: VerifyingDriverOptions = {},\n): ResearchDriver {\n const acceptOnParseFailure = options.acceptOnParseFailure ?? false\n return {\n async verifySource(\n source: ResearchSourceProposal,\n ctx: SourceVerificationContext,\n ): Promise<SourceVerdict> {\n const assertActive = () => throwIfRouterAborted(ctx.signal, options)\n assertActive()\n const router = resolveRouter(options, ctx.signal)\n const gapLines = ctx.gaps\n .map((gap) => `- ${gap.description} (query: \"${gap.query}\")`)\n .join('\\n')\n const acceptedTitles = ctx.acceptedThisRound\n .map((accepted) => `- ${accepted.title ?? accepted.uri}`)\n .join('\\n')\n const excerpt = source.text.slice(0, 1500)\n const system =\n 'You verify whether a fetched web source belongs in a curated knowledge base. ' +\n 'Accept a source ONLY if it is genuinely on-topic for the research goal and helps close ' +\n 'one of the open gaps, AND it is not a near-duplicate of an already-accepted source. ' +\n 'Reject spam, listicles, off-topic pages, marketing, and near-duplicates. ' +\n 'Respond with ONLY a JSON object: {\"accept\": true|false, \"reason\": \"<short reason>\"}.'\n const user = [\n `Research goal: ${ctx.goal}`,\n `Open gaps:\\n${gapLines || '(none specified)'}`,\n acceptedTitles\n ? `Already accepted this round:\\n${acceptedTitles}`\n : 'Nothing accepted yet this round.',\n `Candidate source:\\nURL: ${source.uri}\\nTitle: ${source.title ?? '(none)'}\\nExcerpt:\\n${excerpt}`,\n 'Verdict as JSON {\"accept\": boolean, \"reason\": string}:',\n ].join('\\n\\n')\n\n let raw = ''\n try {\n raw = await router.chat(\n [\n { role: 'system', content: system },\n { role: 'user', content: user },\n ],\n MIN_MAX_TOKENS,\n )\n assertActive()\n } catch (error) {\n assertActive()\n if ((error as { name?: string } | null)?.name === 'AbortError') throw error\n // Router failure: fail-closed (reject) so an unverified source can't slip in.\n return acceptOnParseFailure\n ? { accept: true }\n : { accept: false, reason: `verifier unavailable: ${(error as Error).message}` }\n }\n\n const verdict = parseVerdict(raw)\n if (verdict) return verdict\n return acceptOnParseFailure\n ? { accept: true }\n : { accept: false, reason: 'verifier returned an unparseable verdict' }\n },\n }\n}\n\n/** Parse the verifier's `{accept, reason}` JSON, tolerant of fences / prose. */\nfunction parseVerdict(raw: string): SourceVerdict | null {\n const text = raw.trim()\n if (!text) return null\n const objMatch = text.match(/\\{[\\s\\S]*\\}/)\n if (!objMatch) return null\n try {\n const parsed = JSON.parse(objMatch[0]) as { accept?: unknown; reason?: unknown }\n if (typeof parsed.accept !== 'boolean') return null\n if (parsed.accept) return { accept: true }\n return {\n accept: false,\n reason:\n typeof parsed.reason === 'string' && parsed.reason.trim()\n ? parsed.reason.trim()\n : 'rejected by verifier',\n }\n } catch {\n return null\n }\n}\n","/**\n * Adaptive verifier mode for `runVerifiedResearchLoop`.\n *\n * The cost/quality A/B (`docs/results/cost-quality.md`) found the LLM relevance\n * verifier's cleanliness win is dominated by DE-DUPLICATION — which a\n * deterministic content-hash / canonical-URL check captures at ~none of the LLM\n * premium — and that an LLM check only earns its dollar on the off-scope tail.\n * The honest production move it names is: do the cheap deterministic work first,\n * spend the LLM only where it pays. This module is that driver.\n *\n * Per candidate source the adaptive driver runs THREE stages, cheapest first,\n * and stops at the first that decides:\n *\n * 1. DEDUP ($0, no LLM). Reject a source whose CONTENT (normalized-text hash)\n * or whose CANONICAL URL matches one already accepted this round or already\n * in the knowledge base. This is the de-dup the relevance judge was being\n * paid to do; doing it deterministically is free and exact.\n *\n * 2. HEURISTIC TRIAGE ($0, no LLM). For a unique survivor, a cheap host /\n * title / length signal classifies it as clearly-keep, clearly-drop, or\n * AMBIGUOUS. Clear cases are resolved without a model: an authoritative host\n * (arxiv, *.edu, *.gov, official docs) with a substantial readable body is\n * kept; an obvious spam/listicle/marketing title or a too-thin body is\n * dropped. Only genuinely ambiguous survivors fall through.\n *\n * 3. LLM ESCALATION ($, one call). ONLY the ambiguous survivors reach the LLM\n * `verifySource` — the shipped `createVerifyingResearchDriver` relevance\n * judge. This is where the verifier earns its premium: the off-scope tail a\n * cheap rule can't adjudicate.\n *\n * The result is the cost/quality frontier point the doc predicted: most of the\n * cleanliness (dedup + clear drops) at a fraction of the LLM $/calls (only the\n * ambiguous tail pays). It is a real `ResearchDriver` — same contract the\n * two-agent loop already gates on — and reuses `sha256`, the relevance verifier,\n * and the index; it reinvents none of them.\n */\n\nimport { sha256 } from './ids'\nimport type {\n ResearchSourceProposal,\n SourceVerdict,\n SourceVerificationContext,\n} from './verified-research-loop'\nimport {\n createVerifyingResearchDriver,\n type RouterClient,\n type TangleRouterOptions,\n type VerifyingDriverOptions,\n} from './web-research-worker'\n\n/**\n * Canonicalize a URL for duplicate detection: lowercase host, strip a leading\n * `www.`, drop the scheme, the fragment, a trailing slash, and tracking query\n * params (`utm_*`, `ref`, `fbclid`, `gclid`, …). Two URLs that differ only by\n * those decorations canonicalize to the same key, so the dedup stage treats them\n * as the same source. Falls back to the lowercased raw string when the input is\n * not a parseable absolute URL (so non-http identifiers still dedup by equality).\n */\nexport function canonicalizeUrl(uri: string): string {\n const trimmed = uri.trim()\n try {\n const url = new URL(trimmed)\n const host = url.hostname.toLowerCase().replace(/^www\\./, '')\n // Keep only non-tracking query params, sorted for stable ordering.\n const kept: [string, string][] = []\n for (const [key, value] of url.searchParams) {\n const lower = key.toLowerCase()\n if (lower.startsWith('utm_')) continue\n if (trackingParams.has(lower)) continue\n kept.push([key, value])\n }\n kept.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n const query = kept.map(([k, v]) => `${k}=${v}`).join('&')\n const path = url.pathname.replace(/\\/+$/, '') || '/'\n return `${host}${path}${query ? `?${query}` : ''}`\n } catch {\n return trimmed.toLowerCase()\n }\n}\n\n/** Tracking / referrer query params dropped during URL canonicalization. */\nconst trackingParams = new Set([\n 'ref',\n 'ref_src',\n 'source',\n 'fbclid',\n 'gclid',\n 'mc_cid',\n 'mc_eid',\n 'igshid',\n 'spm',\n '_hsenc',\n '_hsmi',\n])\n\n/**\n * A stable content key for a fetched page: the sha256 of its normalized text\n * (lowercased, punctuation/whitespace collapsed). Two pages whose readable body\n * is the same modulo formatting collide here, so the dedup stage rejects a\n * mirror/syndication of an already-accepted source even when the URL differs.\n */\nexport function contentKey(text: string): string {\n const normalized = text\n .toLowerCase()\n .replace(/[^\\p{L}\\p{N}\\s]+/gu, ' ')\n .replace(/\\s+/g, ' ')\n .trim()\n return sha256(normalized)\n}\n\n/** Why the deterministic dedup stage rejected a candidate (for audit/notes). */\nexport type DedupReason = 'duplicate-url' | 'duplicate-content'\n\n/** The cheap-triage classification of a unique survivor. */\nexport type TriageClass = 'keep' | 'drop' | 'ambiguous'\n\n/** One source's adaptive routing decision, for instrumentation and the doc. */\nexport interface AdaptiveDecision {\n uri: string\n /** The stage that decided this source: dedup | heuristic | llm. */\n stage: 'dedup' | 'heuristic' | 'llm'\n accepted: boolean\n /** The triage class assigned (set once past dedup). */\n triage?: TriageClass\n reason?: string\n}\n\n/** Running tally of where the adaptive driver spent its decisions. */\nexport interface AdaptiveStats {\n total: number\n /** Rejected by deterministic dedup (URL or content). $0. */\n dedupRejected: number\n /** Kept by the cheap heuristic without an LLM call. $0. */\n heuristicKept: number\n /** Dropped by the cheap heuristic without an LLM call. $0. */\n heuristicDropped: number\n /** Escalated to the LLM relevance verifier ($ — the only paid stage). */\n llmCalls: number\n /** Of the escalations, how many the LLM accepted. */\n llmAccepted: number\n decisions: AdaptiveDecision[]\n}\n\nexport interface AdaptiveDriverOptions {\n /** Router client for the LLM escalation. Defaults to a live client from env. */\n router?: RouterClient\n router_options?: TangleRouterOptions\n /** Passed through to the escalation relevance verifier. */\n verifying?: Pick<VerifyingDriverOptions, 'acceptOnParseFailure'>\n /**\n * Hosts an authoritative source lives on. A unique survivor on one of these,\n * with a substantial body, is KEPT deterministically (no LLM). Suffix-matched\n * against the canonical host, so `arxiv.org` matches `export.arxiv.org`. The\n * defaults cover papers, official docs, and standards bodies.\n */\n authoritativeHosts?: string[]\n /**\n * Title/snippet patterns that mark obvious spam / listicle / marketing — a\n * unique survivor matching one is DROPPED deterministically (no LLM).\n */\n spamPatterns?: RegExp[]\n /**\n * Below this many readable chars a survivor is too thin to be a real reference\n * and is dropped deterministically. Default 400.\n */\n minBodyChars?: number\n /**\n * A survivor whose body is at or above this many chars AND on an authoritative\n * host is kept without an LLM call. Default 600.\n */\n substantialBodyChars?: number\n /** Receives each routing decision as it is made (for live instrumentation). */\n onDecision?: (decision: AdaptiveDecision) => void\n}\n\n/** Default authoritative host suffixes — papers, official docs, standards. */\nconst defaultAuthoritativeHosts = [\n 'arxiv.org',\n 'aclanthology.org',\n 'openreview.net',\n 'dl.acm.org',\n 'ieeexplore.ieee.org',\n 'nature.com',\n 'science.org',\n 'pubmed.ncbi.nlm.nih.gov',\n 'ncbi.nlm.nih.gov',\n '.edu',\n '.gov',\n 'docs.python.org',\n 'pytorch.org',\n 'tensorflow.org',\n 'huggingface.co',\n 'github.com',\n 'developer.mozilla.org',\n 'wikipedia.org',\n 'w3.org',\n 'ietf.org',\n 'rfc-editor.org',\n]\n\n/** Default spam/listicle/marketing title patterns. */\nconst defaultSpamPatterns = [\n /\\bbuy\\b.*\\b(cheap|now|deal|sale|discount)\\b/i,\n /\\b\\d+\\s+(things|ways|reasons|tips|tricks|secrets|hacks)\\b.*\\b(you|that|will)\\b/i,\n /\\bshock(ing|ed)?\\b/i,\n /\\bclickbait\\b/i,\n /!!!|\\$\\$\\$/,\n /\\b(coupon|promo code|affiliate|sponsored)\\b/i,\n /\\bbest .* (of \\d{4}|in \\d{4})\\b/i,\n]\n\n/**\n * Classify a UNIQUE survivor (already past dedup) with cheap host/title/length\n * signals only — no LLM. Returns `keep`, `drop`, or `ambiguous`. `ambiguous` is\n * the residue the LLM is reserved for: on-topic-looking pages on unknown hosts\n * with a plausible body, which a host/title rule cannot adjudicate.\n */\nexport function triageSource(\n source: ResearchSourceProposal,\n options: {\n authoritativeHosts: string[]\n spamPatterns: RegExp[]\n minBodyChars: number\n substantialBodyChars: number\n },\n): { triage: TriageClass; reason: string } {\n const titleAndSnippet = `${source.title ?? ''} ${\n typeof source.metadata?.snippet === 'string' ? source.metadata.snippet : ''\n }`.trim()\n const bodyLen = source.text.trim().length\n\n // Clear DROP: obvious spam/listicle/marketing title, OR a too-thin body that\n // can't be a real reference.\n for (const pattern of options.spamPatterns) {\n if (pattern.test(titleAndSnippet)) {\n return { triage: 'drop', reason: `spam/listicle title (${pattern.source})` }\n }\n }\n if (bodyLen < options.minBodyChars) {\n return { triage: 'drop', reason: `thin body (${bodyLen} < ${options.minBodyChars} chars)` }\n }\n\n // Clear KEEP: an authoritative host with a substantial readable body. The host\n // is a strong prior for a real reference; the length rules out a stub page.\n const host = hostOf(source.uri)\n const authoritative =\n host.length > 0 && options.authoritativeHosts.some((suffix) => hostMatches(host, suffix))\n if (authoritative && bodyLen >= options.substantialBodyChars) {\n return { triage: 'keep', reason: `authoritative host ${host} + substantial body (${bodyLen})` }\n }\n\n // Everything else is AMBIGUOUS — an unknown host with a plausible body. This\n // is exactly the off-scope tail the LLM relevance judge is reserved for.\n return { triage: 'ambiguous', reason: `unknown host ${host || '(none)'}, body ${bodyLen} chars` }\n}\n\nfunction hostOf(uri: string): string {\n try {\n return new URL(uri.trim()).hostname.toLowerCase().replace(/^www\\./, '')\n } catch {\n return ''\n }\n}\n\n/** Suffix host match: `.edu` matches `mit.edu`; `arxiv.org` matches `export.arxiv.org`. */\nfunction hostMatches(host: string, suffix: string): boolean {\n if (suffix.startsWith('.')) return host.endsWith(suffix) || host === suffix.slice(1)\n return host === suffix || host.endsWith(`.${suffix}`)\n}\n\nexport interface AdaptiveResearchDriver {\n verifySource(\n source: ResearchSourceProposal,\n ctx: SourceVerificationContext,\n ): Promise<SourceVerdict>\n /** Live tally of where decisions were spent — the cost/quality instrumentation. */\n stats(): AdaptiveStats\n}\n\n/**\n * Build the adaptive verifier. The deterministic stages (dedup + heuristic\n * triage) cost $0; only AMBIGUOUS survivors escalate to the LLM relevance\n * verifier. `stats()` exposes where every decision was spent so the A/B can read\n * the LLM $/calls the adaptive driver saved against the cleanliness it kept.\n *\n * Dedup state is kept on the driver instance: it tracks the canonical URLs and\n * content hashes it has ACCEPTED, plus those it sees in the verification\n * context's `acceptedThisRound` and the KB index. Use one driver per loop run.\n */\nexport function createAdaptiveResearchDriver(\n options: AdaptiveDriverOptions = {},\n): AdaptiveResearchDriver {\n const authoritativeHosts = options.authoritativeHosts ?? defaultAuthoritativeHosts\n const spamPatterns = options.spamPatterns ?? defaultSpamPatterns\n const minBodyChars = Math.max(1, options.minBodyChars ?? 400)\n const substantialBodyChars = Math.max(minBodyChars, options.substantialBodyChars ?? 600)\n\n // The shipped LLM relevance verifier — the ONLY paid stage, reused, not rebuilt.\n const relevance = createVerifyingResearchDriver({\n router: options.router,\n router_options: options.router_options,\n acceptOnParseFailure: options.verifying?.acceptOnParseFailure,\n })\n\n // Dedup memory across the run: every URL/content key this driver ACCEPTED.\n const acceptedUrlKeys = new Set<string>()\n const acceptedContentKeys = new Set<string>()\n\n const stats: AdaptiveStats = {\n total: 0,\n dedupRejected: 0,\n heuristicKept: 0,\n heuristicDropped: 0,\n llmCalls: 0,\n llmAccepted: 0,\n decisions: [],\n }\n\n function record(decision: AdaptiveDecision): void {\n stats.decisions.push(decision)\n options.onDecision?.(decision)\n }\n\n return {\n async verifySource(source, ctx): Promise<SourceVerdict> {\n stats.total += 1\n const urlKey = canonicalizeUrl(source.uri)\n const cKey = contentKey(source.text)\n\n // ---- STAGE 1: DETERMINISTIC DEDUP ($0) ----------------------------------\n // Seed the dup sets from what the loop already accepted this round AND from\n // the KB index, so a duplicate of an existing source is caught even if this\n // driver instance hasn't seen it yet.\n const roundUrlKeys = new Set(\n ctx.acceptedThisRound.map((accepted) => canonicalizeUrl(accepted.uri)),\n )\n const roundContentKeys = new Set(\n ctx.acceptedThisRound.map((accepted) => contentKey(accepted.text)),\n )\n const indexUrlKeys = new Set(\n ctx.index.sources.flatMap((indexed) =>\n typeof indexed.metadata?.originalUri === 'string'\n ? [canonicalizeUrl(indexed.metadata.originalUri)]\n : [],\n ),\n )\n const dupUrl =\n acceptedUrlKeys.has(urlKey) || roundUrlKeys.has(urlKey) || indexUrlKeys.has(urlKey)\n const dupContent = acceptedContentKeys.has(cKey) || roundContentKeys.has(cKey)\n if (dupUrl || dupContent) {\n stats.dedupRejected += 1\n const reason: DedupReason = dupUrl ? 'duplicate-url' : 'duplicate-content'\n record({ uri: source.uri, stage: 'dedup', accepted: false, reason })\n return { accept: false, reason: `dedup: ${reason}` }\n }\n\n // ---- STAGE 2: CHEAP HEURISTIC TRIAGE ($0) -------------------------------\n const { triage, reason } = triageSource(source, {\n authoritativeHosts,\n spamPatterns,\n minBodyChars,\n substantialBodyChars,\n })\n if (triage === 'keep') {\n stats.heuristicKept += 1\n acceptedUrlKeys.add(urlKey)\n acceptedContentKeys.add(cKey)\n record({ uri: source.uri, stage: 'heuristic', accepted: true, triage, reason })\n return { accept: true }\n }\n if (triage === 'drop') {\n stats.heuristicDropped += 1\n record({ uri: source.uri, stage: 'heuristic', accepted: false, triage, reason })\n return { accept: false, reason: `heuristic drop: ${reason}` }\n }\n\n // ---- STAGE 3: LLM ESCALATION ($ — ambiguous tail only) ------------------\n stats.llmCalls += 1\n const verdict = await relevance.verifySource(source, ctx)\n if (verdict.accept) {\n stats.llmAccepted += 1\n acceptedUrlKeys.add(urlKey)\n acceptedContentKeys.add(cKey)\n }\n record({\n uri: source.uri,\n stage: 'llm',\n accepted: verdict.accept,\n triage,\n reason: verdict.accept ? 'llm accepted' : verdict.reason,\n })\n return verdict\n },\n stats(): AdaptiveStats {\n return {\n ...stats,\n decisions: [...stats.decisions],\n }\n },\n }\n}\n","import { z } from 'zod'\nimport { normalizePagesDirectory } from './pages-directory'\n\n/** Authoritative local state included in a KB improvement candidate. */\nexport interface KnowledgeStateScope {\n /** Root-relative Markdown pages directory. Defaults to `knowledge`. */\n pagesDirectory?: string\n /** Include claim ledgers and research events. Excludes indexes, locks, and receipt artifacts. */\n researchState?: boolean\n}\n\nexport const knowledgeStateScopeSchema = z\n .object({\n pagesDirectory: z\n .string()\n .transform((value) => normalizePagesDirectory(value))\n .optional(),\n researchState: z.boolean().optional(),\n })\n .strict()\n\nexport function normalizeKnowledgeStateScope(scope: KnowledgeStateScope = {}) {\n const parsed = knowledgeStateScopeSchema.parse(scope)\n return {\n pagesDirectory: normalizePagesDirectory(parsed.pagesDirectory),\n researchState: parsed.researchState ?? false,\n }\n}\n\nexport const KNOWLEDGE_RESEARCH_STATE_PATHS = [\n '.agent-knowledge/claim-ledgers',\n '.agent-knowledge/events.json',\n] as const\n","import { contentHash, type RunRecord, validateRunRecord } from '@tangle-network/agent-eval'\nimport {\n type AgentImprovementActivation,\n type AgentImprovementActivationResult,\n agentImprovementActivationResultSchema,\n} from '@tangle-network/agent-interface'\nimport { z } from 'zod'\nimport type {\n BuildEvalKnowledgeBundleOptions,\n EvalKnowledgeBundleBuildResult,\n KnowledgeReadinessSpec,\n} from '../eval-readiness'\nimport { type KnowledgeStateScope, knowledgeStateScopeSchema } from '../knowledge-state-scope'\nimport { DEFAULT_PAGES_DIRECTORY } from '../pages-directory'\nimport type {\n KnowledgeBaseQualityOptions,\n KnowledgeBaseQualityReport,\n RagAnswerEvalArtifact,\n} from '../rag-eval'\nimport type {\n RagKnowledgeImprovementPhase,\n RagKnowledgeResearchOptions,\n RagKnowledgeUpdateInput,\n RagKnowledgeUpdateResult,\n RunRagKnowledgeImprovementLoopOptions,\n RunRagKnowledgeImprovementLoopResult,\n} from '../rag-improvement-loop'\nimport type { RunRagOptimizationOptions } from '../rag-optimization'\nimport type { RunKnowledgeResearchLoopOptions } from '../research-loop'\nimport type { RunRetrievalImprovementLoopOptions } from '../retrieval-optimization'\nimport type { KnowledgeIndex } from '../types'\nimport type { ValidateKnowledgeOptions, ValidateKnowledgeResult } from '../validate'\n\nexport type KnowledgeImprovementStatus =\n | 'running'\n | 'candidate-ready'\n | 'promoted'\n | 'rejected'\n | 'blocked'\n\ninterface KnowledgeImprovementMetricProvenanceBase {\n evaluator: string\n version: string\n}\n\nexport type KnowledgeImprovementMetricProvenance =\n | (KnowledgeImprovementMetricProvenanceBase & {\n method: 'deterministic'\n })\n | (KnowledgeImprovementMetricProvenanceBase & {\n method: 'sampled' | 'composite'\n corpusHash: string\n runRecords: RunRecord[]\n })\n | (KnowledgeImprovementMetricProvenanceBase & {\n method: 'model'\n model: string\n corpusHash: string\n runRecords: RunRecord[]\n })\n\nexport interface KnowledgeImprovementMetric {\n score: number\n passed: boolean\n dimensions?: Record<string, number>\n notes?: string\n provenance: KnowledgeImprovementMetricProvenance\n}\n\nexport interface KnowledgeImprovementEvaluationInput {\n runId: string\n iteration: number\n root: string\n baselineRoot: string\n candidateRoot: string\n baselineIndex: KnowledgeIndex\n candidateIndex: KnowledgeIndex\n baseHash: string\n candidateHash: string\n validation: ValidateKnowledgeResult\n readiness?: EvalKnowledgeBundleBuildResult\n kbQuality: KnowledgeBaseQualityReport\n lifecycle?: RunRagKnowledgeImprovementLoopResult\n signal?: AbortSignal\n}\n\nexport type KnowledgeImprovementEvaluator = (\n input: KnowledgeImprovementEvaluationInput,\n) => Promise<KnowledgeImprovementMetric> | KnowledgeImprovementMetric\n\nexport interface KnowledgeImprovementCandidateRecord {\n iteration: number\n candidateId: string\n baseHash: string\n candidateHash?: string\n evidenceHash?: string\n promotionPlanHash?: string\n /** Durable one-way boundary preventing final-case reuse after interruption. */\n finalEvaluationStartedAt?: string\n status: KnowledgeImprovementStatus\n createdAt: string\n updatedAt: string\n}\n\nexport interface KnowledgeImprovementRunState {\n stateScope?: KnowledgeStateScope\n runId: string\n root: string\n goal: string\n implementationRef: string\n status: KnowledgeImprovementStatus\n baseHash: string\n createdAt: string\n updatedAt: string\n ownerId?: string\n candidates: KnowledgeImprovementCandidateRecord[]\n promotedCandidateId?: string\n blockedReason?: string\n}\n\nexport interface KnowledgeImprovementResult {\n runId: string\n state: KnowledgeImprovementRunState\n candidate?: KnowledgeImprovementCandidateRecord\n evaluation?: KnowledgeImprovementMetric\n lifecycle?: RunRagKnowledgeImprovementLoopResult\n promoted: boolean\n blocked: boolean\n}\n\nexport type KnowledgeImprovementTarget = 'candidate' | 'baseline'\n\nexport interface KnowledgeImprovementMutationReceipt {\n target: KnowledgeImprovementTarget\n beforeHash: string\n afterHash: string\n changed: boolean\n transactionId: string | null\n recovered: boolean\n}\n\nexport interface KnowledgeImprovementMutationResult extends KnowledgeImprovementResult {\n candidate: KnowledgeImprovementCandidateRecord\n mutation: KnowledgeImprovementMutationReceipt\n activationResult?: AgentImprovementActivationResult\n}\n\nexport interface KnowledgeImprovementActivationPersistence {\n activation: AgentImprovementActivation\n attemptedAt: string\n identity: string\n /** May run again after interruption; keep this deterministic and free of external side effects. */\n createResult(\n mutation: KnowledgeImprovementMutationReceipt,\n ): Promise<AgentImprovementActivationResult> | AgentImprovementActivationResult\n}\n\nexport const digestSchema = z.string().regex(/^[a-f0-9]{64}$/)\nexport const immutableRefSchema = z.string().regex(/^(?:sha256:[a-f0-9]{64}|git:[a-f0-9]{40})$/)\n\nexport const runIdSchema = z.string().min(1).max(2_048)\n\nexport const safePathSegmentSchema = z\n .string()\n .min(1)\n .max(128)\n .regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/)\n\nexport const knowledgeImprovementMutationReceiptSchema = z\n .object({\n target: z.enum(['candidate', 'baseline']),\n beforeHash: digestSchema,\n afterHash: digestSchema,\n changed: z.boolean(),\n transactionId: z.string().uuid().nullable(),\n recovered: z.boolean(),\n })\n .strict()\n\nexport interface KnowledgeImprovementActivationRecord {\n kind: 'knowledge-improvement-activation-result'\n candidateId: string\n mutation: KnowledgeImprovementMutationReceipt\n result: AgentImprovementActivationResult\n}\n\nexport const knowledgeImprovementActivationRecordSchema: z.ZodType<KnowledgeImprovementActivationRecord> =\n z\n .object({\n kind: z.literal('knowledge-improvement-activation-result'),\n candidateId: safePathSegmentSchema,\n mutation: knowledgeImprovementMutationReceiptSchema,\n result: agentImprovementActivationResultSchema,\n })\n .strict()\n\nconst improvementStatusSchema = z.enum([\n 'running',\n 'candidate-ready',\n 'promoted',\n 'rejected',\n 'blocked',\n])\n\nconst runRecordSchema = z.custom<RunRecord>((value) => {\n try {\n validateRunRecord(value)\n return true\n } catch {\n return false\n }\n}, 'invalid agent-eval RunRecord')\n\nconst deterministicMetricProvenanceSchema = z\n .object({\n evaluator: z.string().min(1),\n version: z.string().min(1),\n method: z.literal('deterministic'),\n })\n .strict()\n\nconst measuredMetricProvenanceSchema = z\n .object({\n evaluator: z.string().min(1),\n version: z.string().min(1),\n method: z.enum(['sampled', 'composite']),\n corpusHash: digestSchema,\n runRecords: z.array(runRecordSchema).min(1),\n })\n .strict()\n\nconst modelMetricProvenanceSchema = z\n .object({\n evaluator: z.string().min(1),\n version: z.string().min(1),\n method: z.literal('model'),\n model: z.string().min(1),\n corpusHash: digestSchema,\n runRecords: z.array(runRecordSchema).min(1),\n })\n .strict()\n\nexport const improvementMetricSchema = z\n .object({\n score: z.number().finite().min(0).max(1),\n passed: z.boolean(),\n dimensions: z.record(z.string(), z.number().finite()).optional(),\n notes: z.string().optional(),\n provenance: z.discriminatedUnion('method', [\n deterministicMetricProvenanceSchema,\n measuredMetricProvenanceSchema,\n modelMetricProvenanceSchema,\n ]),\n })\n .strict()\n .superRefine((metric, context) => {\n if (metric.provenance.method === 'deterministic') return\n const actualCorpusHash = contentHash(metric.provenance.runRecords)\n if (actualCorpusHash !== metric.provenance.corpusHash) {\n context.addIssue({\n code: 'custom',\n path: ['provenance', 'corpusHash'],\n message: 'metric corpus hash must bind the complete RunRecord array',\n })\n }\n })\n\nconst candidateRecordSchema = z\n .object({\n iteration: z.number().int().positive(),\n candidateId: safePathSegmentSchema,\n baseHash: digestSchema,\n candidateHash: digestSchema.optional(),\n evidenceHash: digestSchema.optional(),\n promotionPlanHash: digestSchema.optional(),\n finalEvaluationStartedAt: z.iso.datetime().optional(),\n status: improvementStatusSchema,\n createdAt: z.iso.datetime(),\n updatedAt: z.iso.datetime(),\n })\n .strict()\n\nexport const KnowledgeImprovementRunStateSchema = z\n .object({\n stateScope: knowledgeStateScopeSchema.optional(),\n runId: runIdSchema,\n root: z.string().min(1),\n goal: z.string().min(1),\n implementationRef: immutableRefSchema,\n status: improvementStatusSchema,\n baseHash: digestSchema,\n createdAt: z.iso.datetime(),\n updatedAt: z.iso.datetime(),\n ownerId: z.string().min(1).optional(),\n candidates: z.array(candidateRecordSchema),\n promotedCandidateId: safePathSegmentSchema.optional(),\n blockedReason: z.string().min(1).optional(),\n })\n .strict()\n .superRefine((state, context) => {\n const candidateIds = new Set<string>()\n for (const [index, candidate] of state.candidates.entries()) {\n if (candidateIds.has(candidate.candidateId)) {\n context.addIssue({\n code: 'custom',\n path: ['candidates', index, 'candidateId'],\n message: 'candidate ids must be unique within an improvement run',\n })\n }\n candidateIds.add(candidate.candidateId)\n if (candidate.baseHash !== state.baseHash) {\n context.addIssue({\n code: 'custom',\n path: ['candidates', index, 'baseHash'],\n message: 'candidate base hash must match its improvement run',\n })\n }\n if (candidate.status === 'candidate-ready') {\n if (!candidate.candidateHash || !candidate.evidenceHash || !candidate.promotionPlanHash) {\n context.addIssue({\n code: 'custom',\n path: ['candidates', index],\n message: 'ready candidates require content, evidence, and promotion-plan identities',\n })\n }\n }\n if (\n candidate.status === 'promoted' &&\n (!candidate.candidateHash || !candidate.evidenceHash || !candidate.promotionPlanHash)\n ) {\n context.addIssue({\n code: 'custom',\n path: ['candidates', index],\n message: 'promoted candidates require content, evidence, and promotion-plan identities',\n })\n }\n if (\n candidate.status === 'promoted' &&\n Boolean(candidate.evidenceHash) !== Boolean(candidate.promotionPlanHash)\n ) {\n context.addIssue({\n code: 'custom',\n path: ['candidates', index],\n message: 'promoted candidate evidence and promotion-plan identities must appear together',\n })\n }\n if (candidate.status === 'promoted' && state.status !== 'promoted') {\n context.addIssue({\n code: 'custom',\n path: ['candidates', index, 'status'],\n message: 'only a promoted run may contain a promoted candidate',\n })\n }\n }\n if (state.status === 'promoted') {\n const promoted = state.candidates.filter(\n (candidate) => candidate.candidateId === state.promotedCandidateId,\n )\n if (promoted.length !== 1 || promoted[0]?.status !== 'promoted') {\n context.addIssue({\n code: 'custom',\n path: ['promotedCandidateId'],\n message: 'promoted state must identify exactly one promoted candidate',\n })\n }\n } else if (state.promotedCandidateId !== undefined) {\n context.addIssue({\n code: 'custom',\n path: ['promotedCandidateId'],\n message: 'only a promoted run may identify a promoted candidate',\n })\n }\n if (\n state.status === 'candidate-ready' &&\n state.candidates.filter((candidate) => candidate.status === 'candidate-ready').length !== 1\n ) {\n context.addIssue({\n code: 'custom',\n path: ['status'],\n message: 'candidate-ready state must contain exactly one ready candidate',\n })\n }\n if (state.status === 'blocked' && state.blockedReason === undefined) {\n context.addIssue({\n code: 'custom',\n path: ['blockedReason'],\n message: 'blocked state must include a reason',\n })\n }\n })\n\nexport const KnowledgeImprovementEvidenceSchema = z\n .object({\n kind: z.literal('knowledge-improvement-evidence'),\n runId: runIdSchema,\n candidateId: safePathSegmentSchema,\n iteration: z.number().int().positive(),\n goalHash: digestSchema,\n implementationRef: immutableRefSchema,\n baseHash: digestSchema,\n candidateHash: digestSchema,\n promotionPlanHash: digestSchema,\n validation: z.unknown(),\n readiness: z.unknown().nullable(),\n kbQuality: z.unknown(),\n evaluation: improvementMetricSchema,\n lifecycle: z.unknown().nullable(),\n })\n .strict()\n\nexport type KnowledgeImprovementEvidence = z.infer<typeof KnowledgeImprovementEvidenceSchema>\n\n/** Portable identity of one measured candidate. Paths and mutable run state are deliberately excluded. */\nexport const KnowledgeImprovementCandidateRefSchema = z\n .object({\n kind: z.literal('knowledge-improvement-candidate'),\n runId: runIdSchema,\n candidateId: safePathSegmentSchema,\n goalHash: digestSchema,\n baseHash: digestSchema,\n candidateHash: digestSchema,\n evidenceHash: digestSchema,\n promotionPlanHash: digestSchema,\n })\n .strict()\n\nexport type KnowledgeImprovementCandidateRef = z.infer<\n typeof KnowledgeImprovementCandidateRefSchema\n>\n\nexport interface PromoteKnowledgeCandidateOptions {\n root: string\n candidate: KnowledgeImprovementCandidateRef\n activation?: KnowledgeImprovementActivationPersistence\n ownerId?: string\n leaseTtlMs?: number\n now?: () => Date\n onState?: (state: KnowledgeImprovementRunState) => Promise<void> | void\n}\n\nexport type RestoreKnowledgeCandidateBaselineOptions = PromoteKnowledgeCandidateOptions\n\nexport interface LoadKnowledgeImprovementActivationResultOptions {\n root: string\n candidate: KnowledgeImprovementCandidateRef\n activation: AgentImprovementActivation\n identity: string\n}\n\nexport interface UseKnowledgeImprovementCandidateOptions {\n root: string\n candidate: KnowledgeImprovementCandidateRef\n}\n\nexport interface ResolvedKnowledgeImprovementComparisonSnapshot {\n root: string\n hash: string\n}\n\nexport interface ResolvedKnowledgeImprovementComparison {\n stateScope?: KnowledgeStateScope\n reference: KnowledgeImprovementCandidateRef\n evaluation: KnowledgeImprovementMetric\n baseline: ResolvedKnowledgeImprovementComparisonSnapshot\n candidate: ResolvedKnowledgeImprovementComparisonSnapshot\n}\n\nexport interface ResolvedKnowledgeImprovementCandidate {\n stateScope?: KnowledgeStateScope\n root: string\n candidate: KnowledgeImprovementCandidateRef\n evaluation: KnowledgeImprovementMetric\n}\n\nexport interface KnowledgeImprovementRetrievalOptions\n extends Omit<RunRetrievalImprovementLoopOptions, 'index' | 'runDir'> {\n runDir?: RunRetrievalImprovementLoopOptions['runDir']\n}\n\nexport type KnowledgeImprovementRagOptimizationRunInput = Parameters<\n RunRagOptimizationOptions['run']\n>[0] & {\n runId: string\n iteration: number\n candidateId: string\n root: string\n baselineRoot: string\n candidateRoot: string\n candidateIndex: KnowledgeIndex\n baseHash: string\n}\n\nexport interface KnowledgeImprovementRagOptimizationOptions\n extends Omit<RunRagOptimizationOptions, 'run' | 'runDir'> {\n runDir?: RunRagOptimizationOptions['runDir']\n run(input: KnowledgeImprovementRagOptimizationRunInput): Promise<RagAnswerEvalArtifact>\n}\n\nexport interface KnowledgeImprovementUpdateInput extends RagKnowledgeUpdateInput {\n runId: string\n iteration: number\n candidateId: string\n root: string\n baselineRoot: string\n candidateRoot: string\n baseHash: string\n}\n\nexport type KnowledgeImprovementUpdate = (\n input: KnowledgeImprovementUpdateInput,\n) => Promise<RagKnowledgeUpdateResult> | RagKnowledgeUpdateResult\n\nexport interface KnowledgeImprovementOptions {\n /** Declared authoritative local state, frozen and restored with each candidate. */\n stateScope?: KnowledgeStateScope\n root: string\n goal: string\n /**\n * Immutable identity covering callbacks, evaluation policy, models, indexes,\n * external services, and all other behavior that can affect this run.\n */\n implementationRef: string\n runId?: string\n ownerId?: string\n leaseTtlMs?: number\n resume?: boolean\n maxCandidates?: number\n candidateResearchIterations?: number\n strict?: ValidateKnowledgeOptions['strict']\n readinessSpecs?: KnowledgeReadinessSpec[]\n readinessTaskId?: string\n readiness?: Omit<BuildEvalKnowledgeBundleOptions, 'taskId' | 'index' | 'specs'>\n kbQuality?: KnowledgeBaseQualityOptions\n step?: RunKnowledgeResearchLoopOptions['step']\n knowledgeResearch?: Omit<RagKnowledgeResearchOptions, 'root'>\n ragOptimization?: KnowledgeImprovementRagOptimizationOptions\n retrieval?: KnowledgeImprovementRetrievalOptions\n diagnose?: NonNullable<RunRagKnowledgeImprovementLoopOptions['diagnose']>\n acquireKnowledge?: NonNullable<RunRagKnowledgeImprovementLoopOptions['acquireKnowledge']>\n updateKnowledge?: KnowledgeImprovementUpdate\n evaluateAnswers?: NonNullable<RunRagKnowledgeImprovementLoopOptions['evaluateAnswers']>\n answerQualityCostCeiling?: RunRagKnowledgeImprovementLoopOptions['answerQualityCostCeiling']\n decidePromotion?: NonNullable<RunRagKnowledgeImprovementLoopOptions['decidePromotion']>\n enabledPhases?: readonly RagKnowledgeImprovementPhase[]\n requiredPhases?: readonly RagKnowledgeImprovementPhase[]\n /** Repeatable candidate screening that must not use final cases. */\n evaluateDevelopment?: KnowledgeImprovementEvaluator\n /** Single-use final evaluator. A failure ends the run. */\n evaluate?: KnowledgeImprovementEvaluator\n signal?: AbortSignal\n now?: () => Date\n onState?: (state: KnowledgeImprovementRunState) => Promise<void> | void\n}\n\nexport interface LeaseHandle {\n ownerId: string\n assertOwned(): void\n release(): Promise<void>\n}\n\nexport const DEFAULT_LEASE_TTL_MS = 15 * 60 * 1000\n\nexport const UPDATE_PHASES: readonly RagKnowledgeImprovementPhase[] = [\n 'gap-diagnosis',\n 'knowledge-acquisition',\n 'knowledge-update',\n]\n\nexport const EVALUATION_PHASES: readonly RagKnowledgeImprovementPhase[] = [\n 'rag-optimization',\n 'retrieval-tuning',\n 'answer-quality',\n 'promotion',\n]\n\n/**\n * The pages directory every knowledge-improvement path reads and writes.\n *\n * This subsystem has no option for a caller-chosen pages directory: the\n * workspace it snapshots, the plan it hashes, and the transaction it applies\n * all address the default tree. Naming it once means the write allowlist, the\n * plan hash, and the generated-page set cannot disagree about which tree they\n * are talking about, and threading a real choice through later changes one\n * constant instead of hunting call sites.\n */\nexport const KB_IMPROVEMENT_PAGES_DIRECTORY = DEFAULT_PAGES_DIRECTORY\n","import { stat } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { canonicalJson, contentHash } from '@tangle-network/agent-eval'\nimport {\n canonicalPathsEqual,\n isMissingFile,\n listRegularFilesWithinRoot,\n readRegularFileWithinRoot,\n relativeWithinRoot,\n withSafeDirectory,\n writeJsonDurableWithinRoot,\n} from '../durable-fs'\nimport { sha256, slugify, stableId } from '../ids'\nimport { acquireDurableFileLock } from '../mutation-lock'\nimport { layoutFor } from '../store'\nimport type {\n KnowledgeImprovementCandidateRecord,\n KnowledgeImprovementOptions,\n KnowledgeImprovementRunState,\n LeaseHandle,\n} from './contracts'\nimport { KnowledgeImprovementRunStateSchema, runIdSchema, safePathSegmentSchema } from './contracts'\n\nexport function knowledgeImprovementRunId(root: string, goal: string): string {\n return stableId('kimpr', `${root}:${goal}`)\n}\n\nexport function knowledgeImprovementRunDir(root: string, runId: string): string {\n const parsedRunId = runIdSchema.parse(runId)\n const safeRunId = safePathSegmentSchema.safeParse(parsedRunId)\n const runSegment = safeRunId.success\n ? safeRunId.data\n : `${slugify(parsedRunId).slice(0, 72)}-${sha256(parsedRunId).slice(0, 16)}`\n const improvementsDir = join(layoutFor(root).cacheDir, 'improvements')\n const runDir = join(improvementsDir, runSegment)\n if (relativeWithinRoot(improvementsDir, runDir) === undefined) {\n throw new Error('knowledge improvement run directory escaped its root')\n }\n return runDir\n}\n\nexport async function withKnowledgeImprovementRun<T>(\n root: string,\n runId: string,\n create: boolean,\n use: (runDir: string) => Promise<T> | T,\n): Promise<T> {\n const runDir = knowledgeImprovementRunDir(root, runId)\n const relativePath = relativeWithinRoot(root, runDir)\n if (!relativePath) throw new Error('knowledge improvement run directory escaped its root')\n return withSafeDirectory(root, relativePath, create, async (openedRunDir) => {\n const result = await use(openedRunDir)\n const openedIdentity = await stat(openedRunDir)\n const currentIdentity = await withSafeDirectory(root, relativePath, false, (currentRunDir) =>\n stat(currentRunDir),\n )\n if (openedIdentity.dev !== currentIdentity.dev || openedIdentity.ino !== currentIdentity.ino) {\n throw new Error('knowledge improvement run directory changed during use')\n }\n return result\n })\n}\n\nexport async function loadKnowledgeImprovementState(\n root: string,\n runId: string,\n): Promise<KnowledgeImprovementRunState | null> {\n const expectedRunId = runIdSchema.parse(runId)\n try {\n return await withKnowledgeImprovementRun(root, expectedRunId, false, (runDir) =>\n loadKnowledgeImprovementStateFromRun(root, expectedRunId, runDir),\n )\n } catch (error) {\n if (isMissingFile(error)) return null\n throw error\n }\n}\n\nexport async function loadKnowledgeImprovementStateFromRun(\n root: string,\n runId: string,\n runDir: string,\n): Promise<KnowledgeImprovementRunState> {\n const stateFile = await readRegularFileWithinRoot(runDir, 'state.json')\n const raw = JSON.parse(stateFile.bytes.toString('utf8')) as unknown\n const state = KnowledgeImprovementRunStateSchema.parse(raw) as KnowledgeImprovementRunState\n if (state.runId !== runId) {\n throw new Error('knowledge improvement state does not match the requested run')\n }\n if (!(await canonicalPathsEqual(state.root, root))) {\n throw new Error('knowledge improvement state does not match the requested root')\n }\n for (const candidate of state.candidates) {\n if (candidate.status === 'running') await assertCandidateWorkspace(runDir, candidate)\n }\n return state\n}\n\nasync function assertCandidateWorkspace(\n runDir: string,\n candidate: Pick<KnowledgeImprovementCandidateRecord, 'candidateId'>,\n): Promise<void> {\n await withCandidateWorkspace(runDir, candidate, () => undefined)\n}\n\nexport async function withCandidateWorkspace<T>(\n runDir: string,\n candidate: Pick<KnowledgeImprovementCandidateRecord, 'candidateId'>,\n use: (candidateRoot: string) => Promise<T> | T,\n): Promise<T> {\n return withSafeDirectory(\n runDir,\n join('candidates', safePathSegmentSchema.parse(candidate.candidateId), 'workspace'),\n false,\n use,\n )\n}\n\nexport function findActiveCandidate(\n state: KnowledgeImprovementRunState,\n): KnowledgeImprovementCandidateRecord | undefined {\n return [...state.candidates]\n .reverse()\n .find((candidate) => candidate.status === 'candidate-ready' || candidate.status === 'running')\n}\n\nexport interface KnowledgeImprovementEvent extends Record<string, unknown> {\n at: string\n type: string\n}\n\nexport async function loadKnowledgeImprovementEvents(\n root: string,\n runId: string,\n): Promise<KnowledgeImprovementEvent[]> {\n const parsedRunId = runIdSchema.parse(runId)\n try {\n return await withKnowledgeImprovementRun(root, parsedRunId, false, (runDir) =>\n loadKnowledgeImprovementEventsFromRun(runDir),\n )\n } catch (error) {\n if (isMissingFile(error)) return []\n throw error\n }\n}\n\nexport async function loadKnowledgeImprovementEventsFromRun(\n runDir: string,\n): Promise<KnowledgeImprovementEvent[]> {\n const events: KnowledgeImprovementEvent[] = []\n try {\n for (const file of await listRegularFilesWithinRoot(runDir, 'events')) {\n const name = file.path.slice('events/'.length)\n if (name.includes('/') || !name.endsWith('.json')) {\n throw new Error(`knowledge event store contains an unsupported entry: ${name}`)\n }\n events.push(parseKnowledgeImprovementEvent(JSON.parse(file.bytes.toString('utf8'))))\n }\n } catch (error) {\n if (!isMissingFile(error)) throw error\n }\n\n const unique = new Map<string, KnowledgeImprovementEvent>()\n for (const event of events) {\n const { at: _at, ...semantic } = event\n unique.set(contentHash(semantic), event)\n }\n return [...unique.values()].sort((left, right) => left.at.localeCompare(right.at))\n}\n\nfunction parseKnowledgeImprovementEvent(value: unknown): KnowledgeImprovementEvent {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('knowledge improvement event is not an object')\n }\n const event = value as Record<string, unknown>\n if (typeof event.at !== 'string' || typeof event.type !== 'string') {\n throw new Error('knowledge improvement event is missing at or type')\n }\n return event as KnowledgeImprovementEvent\n}\n\nexport async function acquireRunLease(\n runDir: string,\n options: { ownerId: string; ttlMs: number },\n): Promise<LeaseHandle> {\n const path = join(runDir, 'run.lock.durable')\n const acquired = await acquireDurableFileLock(runDir, {\n lockfilePath: path,\n staleMs: options.ttlMs,\n })\n return {\n ownerId: options.ownerId,\n assertOwned: acquired.assertOwned,\n release: acquired.release,\n }\n}\n\nexport async function blockRun(\n runDir: string,\n state: KnowledgeImprovementRunState,\n reason: string,\n onState: KnowledgeImprovementOptions['onState'],\n now: () => Date,\n): Promise<KnowledgeImprovementRunState> {\n state.status = 'blocked'\n state.blockedReason = reason\n state.updatedAt = now().toISOString()\n await saveState(runDir, state, onState)\n return state\n}\n\nexport async function saveState(\n runDir: string,\n state: KnowledgeImprovementRunState,\n onState?: KnowledgeImprovementOptions['onState'],\n): Promise<void> {\n await writeJsonDurableWithinRoot(\n runDir,\n 'state.json',\n KnowledgeImprovementRunStateSchema.parse(state),\n )\n await onState?.(state)\n}\n\nexport async function appendLedger(runDir: string, value: Record<string, unknown>): Promise<void> {\n const type = value.type\n if (typeof type !== 'string' || type.length === 0) {\n throw new Error('knowledge improvement event requires a type')\n }\n const relativePath = join('events', `${contentHash(value)}.json`).replace(/\\\\/g, '/')\n try {\n const file = await readRegularFileWithinRoot(runDir, relativePath)\n const existing = parseKnowledgeImprovementEvent(JSON.parse(file.bytes.toString('utf8')))\n const { at: _at, ...semantic } = existing\n if (canonicalJson(semantic) !== canonicalJson(value)) {\n throw new Error('knowledge improvement event identity conflicts with durable content')\n }\n return\n } catch (error) {\n if (!isMissingFile(error)) throw error\n }\n await writeJsonDurableWithinRoot(runDir, relativePath, {\n at: new Date().toISOString(),\n ...value,\n })\n}\n\nexport function candidateEvidenceRelativePath(candidateId: string): string {\n return join('candidates', safePathSegmentSchema.parse(candidateId), 'evidence.json').replace(\n /\\\\/g,\n '/',\n )\n}\n\nexport function assertExactCandidatePlatform(): void {\n if (process.platform !== 'linux') {\n throw new Error('exact knowledge candidate workflows require Linux directory descriptors')\n }\n}\n","import { canonicalJson } from '@tangle-network/agent-eval'\nimport {\n type AgentImprovementActivation,\n type AgentImprovementActivationResult,\n agentImprovementActivationResultSchema,\n agentImprovementActivationSchema,\n canonicalCandidateDigest,\n omitTopLevelDigest,\n type Sha256Digest,\n sha256DigestSchema,\n} from '@tangle-network/agent-interface'\nimport { z } from 'zod'\nimport { isMissingFile, readRegularFileWithinRoot, writeJsonDurableWithinRoot } from '../durable-fs'\nimport type {\n KnowledgeImprovementActivationPersistence,\n KnowledgeImprovementActivationRecord,\n KnowledgeImprovementCandidateRef,\n KnowledgeImprovementMutationReceipt,\n KnowledgeImprovementTarget,\n LoadKnowledgeImprovementActivationResultOptions,\n} from './contracts'\nimport {\n digestSchema,\n KnowledgeImprovementCandidateRefSchema,\n knowledgeImprovementActivationRecordSchema,\n knowledgeImprovementMutationReceiptSchema,\n} from './contracts'\nimport { assertExactCandidatePlatform, withKnowledgeImprovementRun } from './state'\n\n/** Load the durable result for one exact activation without changing knowledge or run state. */\nexport async function loadKnowledgeImprovementActivationResult(\n options: LoadKnowledgeImprovementActivationResultOptions,\n): Promise<AgentImprovementActivationResult | null> {\n assertExactCandidatePlatform()\n const candidate = Object.freeze(KnowledgeImprovementCandidateRefSchema.parse(options.candidate))\n const activation = verifyCanonicalKnowledgeActivation(options.activation)\n const target = targetForKnowledgeActivation(activation)\n assertKnowledgeActivationAuthority(activation, candidate, target, options.identity)\n return withKnowledgeImprovementRun(options.root, candidate.runId, false, async (runDir) => {\n const record = await loadKnowledgeActivationRecord(\n runDir,\n candidate,\n activation,\n target,\n options.identity,\n )\n return record?.result ?? null\n })\n}\n\nexport interface ResolvedKnowledgeImprovementActivationPersistence\n extends KnowledgeImprovementActivationPersistence {\n activation: AgentImprovementActivation\n}\n\nexport function sourceKnowledgeHash(\n candidate: KnowledgeImprovementCandidateRef,\n target: KnowledgeImprovementTarget,\n): string {\n return target === 'candidate' ? candidate.baseHash : candidate.candidateHash\n}\n\nfunction targetForKnowledgeActivation(\n activation: AgentImprovementActivation,\n): KnowledgeImprovementTarget {\n return activation.intent === 'activate-candidate' ? 'candidate' : 'baseline'\n}\n\nexport function resolveKnowledgeActivationPersistence(\n input: KnowledgeImprovementActivationPersistence,\n candidate: KnowledgeImprovementCandidateRef,\n target: KnowledgeImprovementTarget,\n): ResolvedKnowledgeImprovementActivationPersistence {\n const activation = verifyCanonicalKnowledgeActivation(input.activation)\n assertKnowledgeActivationAuthority(activation, candidate, target, input.identity)\n const attemptedAt = z.iso.datetime().parse(input.attemptedAt)\n if (\n Date.parse(attemptedAt) < Date.parse(activation.authorizedAt) ||\n Date.parse(attemptedAt) >= Date.parse(activation.expiresAt)\n ) {\n throw new Error('knowledge activation attempt is outside its authorization window')\n }\n return Object.freeze({\n activation,\n attemptedAt,\n identity: input.identity,\n createResult: input.createResult,\n })\n}\n\nfunction assertKnowledgeActivationAuthority(\n activation: AgentImprovementActivation,\n candidate: KnowledgeImprovementCandidateRef,\n target: KnowledgeImprovementTarget,\n identity: string,\n): void {\n if (!identity.trim()) throw new Error('knowledge activation identity is required')\n if (targetForKnowledgeActivation(activation) !== target) {\n throw new Error('knowledge activation intent does not match the requested transition')\n }\n if (activation.targets.length !== 1) {\n throw new Error('knowledge activation requires exactly one target')\n }\n const authorizedTarget = activation.targets[0]\n if (authorizedTarget.surface !== 'knowledge' || authorizedTarget.identity !== identity) {\n throw new Error('knowledge activation target does not match this knowledge base')\n }\n if (\n authorizedTarget.expectedBaseDigest !==\n prefixedKnowledgeDigest(sourceKnowledgeHash(candidate, target))\n ) {\n throw new Error('knowledge activation does not authorize the measured source state')\n }\n}\n\nfunction verifyCanonicalKnowledgeActivation(\n value: AgentImprovementActivation,\n): AgentImprovementActivation {\n const activation = agentImprovementActivationSchema.parse(value)\n if (canonicalCandidateDigest(omitTopLevelDigest(activation)) !== activation.digest) {\n throw new Error('knowledge activation digest does not match its canonical content')\n }\n return immutableJsonValue(structuredClone(activation))\n}\n\nfunction verifyCanonicalKnowledgeActivationResult(\n value: AgentImprovementActivationResult,\n): AgentImprovementActivationResult {\n const result = agentImprovementActivationResultSchema.parse(value)\n if (canonicalCandidateDigest(omitTopLevelDigest(result)) !== result.digest) {\n throw new Error('knowledge activation result digest does not match its canonical content')\n }\n return immutableJsonValue(structuredClone(result))\n}\n\nexport async function persistKnowledgeActivationResult(\n runDir: string,\n candidate: KnowledgeImprovementCandidateRef,\n persistence: ResolvedKnowledgeImprovementActivationPersistence,\n target: KnowledgeImprovementTarget,\n mutation: KnowledgeImprovementMutationReceipt,\n): Promise<AgentImprovementActivationResult> {\n const result = assertKnowledgeActivationResult(\n persistence.activation,\n candidate,\n target,\n persistence.identity,\n mutation,\n await persistence.createResult(Object.freeze({ ...mutation })),\n persistence.attemptedAt,\n )\n const record = knowledgeImprovementActivationRecordSchema.parse({\n kind: 'knowledge-improvement-activation-result',\n candidateId: candidate.candidateId,\n mutation,\n result,\n })\n const existing = await loadKnowledgeActivationRecord(\n runDir,\n candidate,\n persistence.activation,\n target,\n persistence.identity,\n )\n if (existing) {\n if (canonicalJson(existing) !== canonicalJson(record)) {\n throw new Error('knowledge activation result identity conflicts with durable content')\n }\n return existing.result\n }\n await writeJsonDurableWithinRoot(\n runDir,\n knowledgeActivationResultPath(persistence.activation.digest),\n record,\n )\n const stored = await loadKnowledgeActivationRecord(\n runDir,\n candidate,\n persistence.activation,\n target,\n persistence.identity,\n )\n if (!stored || canonicalJson(stored) !== canonicalJson(record)) {\n throw new Error('knowledge activation result was not durably persisted')\n }\n return stored.result\n}\n\nexport async function loadKnowledgeActivationRecord(\n runDir: string,\n candidate: KnowledgeImprovementCandidateRef,\n activation: AgentImprovementActivation,\n target: KnowledgeImprovementTarget,\n identity: string,\n): Promise<KnowledgeImprovementActivationRecord | null> {\n let raw: unknown\n try {\n const file = await readRegularFileWithinRoot(\n runDir,\n knowledgeActivationResultPath(activation.digest),\n )\n raw = JSON.parse(file.bytes.toString('utf8')) as unknown\n } catch (error) {\n if (isMissingFile(error)) return null\n throw error\n }\n const record = knowledgeImprovementActivationRecordSchema.parse(raw)\n if (record.candidateId !== candidate.candidateId) {\n throw new Error('knowledge activation result belongs to another candidate')\n }\n const result = assertKnowledgeActivationResult(\n activation,\n candidate,\n target,\n identity,\n record.mutation,\n record.result,\n )\n return immutableJsonValue({ ...record, result })\n}\n\nfunction assertKnowledgeActivationResult(\n activation: AgentImprovementActivation,\n candidate: KnowledgeImprovementCandidateRef,\n target: KnowledgeImprovementTarget,\n identity: string,\n mutationInput: KnowledgeImprovementMutationReceipt,\n resultInput: AgentImprovementActivationResult,\n attemptedAt?: string,\n): AgentImprovementActivationResult {\n assertKnowledgeActivationAuthority(activation, candidate, target, identity)\n const mutation = knowledgeImprovementMutationReceiptSchema.parse(mutationInput)\n const result = verifyCanonicalKnowledgeActivationResult(resultInput)\n if (\n result.idempotencyKey !== activation.digest ||\n (attemptedAt !== undefined && result.attemptedAt !== attemptedAt) ||\n Date.parse(result.attemptedAt) < Date.parse(activation.authorizedAt) ||\n Date.parse(result.attemptedAt) >= Date.parse(activation.expiresAt) ||\n mutation.target !== target ||\n mutation.changed !== (mutation.beforeHash !== mutation.afterHash) ||\n (!mutation.changed && (mutation.transactionId !== null || mutation.recovered))\n ) {\n throw new Error('knowledge activation result does not bind its authorized mutation')\n }\n\n const sourceDigest = prefixedKnowledgeDigest(sourceKnowledgeHash(candidate, target))\n const desiredDigest = prefixedKnowledgeDigest(\n target === 'candidate' ? candidate.candidateHash : candidate.baseHash,\n )\n const beforeDigest = prefixedKnowledgeDigest(mutation.beforeHash)\n const afterDigest = prefixedKnowledgeDigest(mutation.afterHash)\n const outcome = result.outcome\n if (mutation.changed) {\n if (\n mutation.transactionId === null ||\n beforeDigest !== sourceDigest ||\n afterDigest !== desiredDigest ||\n outcome.status !== 'applied' ||\n outcome.transactionId !== mutation.transactionId ||\n outcome.targets.length !== 1 ||\n outcome.targets[0]?.surface !== 'knowledge' ||\n outcome.targets[0]?.identity !== identity ||\n outcome.targets[0]?.beforeDigest !== beforeDigest ||\n outcome.targets[0]?.afterDigest !== afterDigest\n ) {\n throw new Error('knowledge activation result does not prove the applied transaction')\n }\n return result\n }\n\n const expectedStatus = afterDigest === desiredDigest ? 'already-applied' : 'conflict'\n if (\n afterDigest === sourceDigest ||\n outcome.status !== expectedStatus ||\n outcome.targets.length !== 1 ||\n outcome.targets[0]?.surface !== 'knowledge' ||\n outcome.targets[0]?.identity !== identity ||\n outcome.targets[0]?.currentDigest !== afterDigest\n ) {\n throw new Error('knowledge activation result does not prove the observed target state')\n }\n return result\n}\n\nfunction knowledgeActivationResultPath(digest: Sha256Digest): string {\n const parsed = sha256DigestSchema.parse(digest)\n return `activation-results/${parsed.slice('sha256:'.length)}.json`\n}\n\nfunction prefixedKnowledgeDigest(hash: string): Sha256Digest {\n return sha256DigestSchema.parse(`sha256:${digestSchema.parse(hash)}`)\n}\n\nexport function immutableJsonValue<T>(value: T): T {\n if (value === null || typeof value !== 'object') return value\n for (const child of Object.values(value)) immutableJsonValue(child)\n return Object.freeze(value)\n}\n","import type { ComparisonCost } from '@tangle-network/agent-eval/campaign'\nimport { assertImmutableRef } from './immutable-ref'\n\ninterface RagAnswerEvidence {\n passed: boolean\n metrics: Record<string, number>\n finalScenarioIds: readonly string[]\n datasetRef: string\n evaluatorRef: string\n cost: ComparisonCost\n}\n\nexport function assertRagAnswerEvidence(result: RagAnswerEvidence): void {\n if (!result || typeof result !== 'object') {\n throw new Error('answer-quality evidence must be an object')\n }\n if (typeof result.passed !== 'boolean') {\n throw new Error('answer-quality evidence requires a boolean passed verdict')\n }\n assertImmutableRef(result.datasetRef, 'answer-quality datasetRef')\n assertImmutableRef(result.evaluatorRef, 'answer-quality evaluatorRef')\n if (\n !Array.isArray(result.finalScenarioIds) ||\n result.finalScenarioIds.length < 2 ||\n new Set(result.finalScenarioIds).size !== result.finalScenarioIds.length ||\n result.finalScenarioIds.some((id) => typeof id !== 'string' || id.trim().length === 0)\n ) {\n throw new Error('answer-quality evidence requires at least 2 unique final scenario IDs')\n }\n if (!result.metrics || typeof result.metrics !== 'object' || Array.isArray(result.metrics)) {\n throw new Error('answer-quality evidence requires non-empty finite metrics')\n }\n const metrics = Object.entries(result.metrics)\n if (\n metrics.length === 0 ||\n metrics.some(([key, value]) => key.trim().length === 0 || !Number.isFinite(value))\n ) {\n throw new Error('answer-quality evidence requires non-empty finite metrics')\n }\n if (!result.cost || typeof result.cost !== 'object') {\n throw new Error('answer-quality evidence requires cost accounting')\n }\n if (\n !Number.isFinite(result.cost.totalCostUsd) ||\n result.cost.totalCostUsd < 0 ||\n typeof result.cost.accountingComplete !== 'boolean' ||\n !Array.isArray(result.cost.incompleteReasons) ||\n result.cost.incompleteReasons.some((reason) => typeof reason !== 'string' || !reason.trim())\n ) {\n throw new Error('answer-quality evidence has invalid cost accounting')\n }\n if (result.cost.accountingComplete && result.cost.incompleteReasons.length > 0) {\n throw new Error('complete answer-quality cost accounting cannot include incomplete reasons')\n }\n}\n\nexport function ragAnswerEvidenceRejectionReasons(\n evidence: RagAnswerEvidence,\n costCeiling: number | undefined,\n): string[] {\n const reasons: string[] = []\n if (!evidence.passed) reasons.push('answer-quality evaluation failed')\n if (!evidence.cost.accountingComplete) {\n reasons.push('answer-quality final comparison has incomplete cost accounting')\n }\n if (costCeiling === undefined) {\n reasons.push('answer-quality promotion requires answerQualityCostCeiling')\n } else if (exceedsCostCeiling(evidence.cost.totalCostUsd, costCeiling)) {\n reasons.push(\n `answer-quality final comparison cost ${evidence.cost.totalCostUsd} exceeds ${costCeiling}`,\n )\n }\n return reasons\n}\n\nfunction exceedsCostCeiling(totalCostUsd: number, costCeiling: number): boolean {\n const tolerance = Number.EPSILON * Math.max(1, Math.abs(totalCostUsd), Math.abs(costCeiling)) * 8\n return totalCostUsd - costCeiling > tolerance\n}\n","/**\n * Claim-grounding mode for `runVerifiedResearchLoop`.\n *\n * The two-agent loop's existing verifier judges a source's on-topic RELEVANCE\n * (is this page about the goal?). On the topic sets we have measured, its\n * cleanliness win is dominated by DE-DUPLICATION — which a deterministic\n * content-hash / canonical-URL check captures at ~none of the LLM premium (see\n * `docs/results/cost-quality.md`). That makes the LLM verifier look expensive\n * for what a cheap rule already does.\n *\n * Claim-grounding targets a DIFFERENT, harder error band: a citation that is\n * relevant and unique but **misattributed** — the page is on-topic, the URL is\n * real, yet the specific CLAIM the source is cited for does NOT actually appear\n * in the page. This is the citation-fabrication failure mode of LLM research:\n * the model writes a plausible sentence and hangs a real URL off it that never\n * says any such thing. Neither de-dup nor a relevance judge catches it (both can\n * pass a misattributed-but-on-topic page); only checking the claim against the\n * fetched text does.\n *\n * The check is EXECUTABLE GROUND TRUTH, not another LLM opinion: the worker\n * attaches the specific claim it is citing the source for, and the verifier\n * tests whether that claim is PRESENT (verbatim, normalized, or as a sufficient\n * content-word overlap / close paraphrase) in the `htmlToText` output of the\n * page the worker actually fetched. A claim that is not grounded is rejected as\n * misattributed. Because the oracle is deterministic text presence — not a model\n * call — it is a deployable, non-oracle verifier: it can run in production with\n * zero inference cost, OR be composed with the LLM relevance verifier so the\n * loop rejects BOTH off-topic AND misattributed sources.\n *\n * This module is content-free and any-topic: it adds (1) a way for a proposal to\n * carry the claim it is cited for, (2) the `groundClaimInText` oracle, and (3) a\n * `ResearchDriver` that gates on grounding. It composes the existing\n * `ResearchDriver` / `ResearchSourceProposal` contracts and the shipped\n * `htmlToText`; it reinvents none of them.\n */\n\nimport type {\n ResearchSourceProposal,\n SourceVerdict,\n SourceVerificationContext,\n} from './verified-research-loop'\nimport {\n createTangleRouterClient,\n type RouterClient,\n type TangleRouterOptions,\n} from './web-research-worker'\n\n/**\n * Metadata key under which a proposal carries the specific claim it is cited\n * for. The worker sets `metadata[citedClaimKey] = '<the claim>'`; the\n * claim-grounding driver reads it and checks it against the fetched page text.\n */\nexport const citedClaimKey = 'citedClaim'\n\n/** Read the cited claim a proposal carries, if any. */\nexport function citedClaimOf(source: ResearchSourceProposal): string | undefined {\n const claim = source.metadata?.[citedClaimKey]\n return typeof claim === 'string' && claim.trim() ? claim.trim() : undefined\n}\n\n/** Attach a cited claim to a proposal (immutably returns a new proposal). */\nexport function withCitedClaim(\n source: ResearchSourceProposal,\n claim: string,\n): ResearchSourceProposal {\n return { ...source, metadata: { ...source.metadata, [citedClaimKey]: claim } }\n}\n\nexport interface GroundingResult {\n /** True when the claim is sufficiently present in the page text. */\n grounded: boolean\n /** How the claim matched (or why it didn't). For audit/notes. */\n mode: 'verbatim' | 'normalized' | 'overlap' | 'absent' | 'empty-claim' | 'empty-text'\n /**\n * Fraction of the claim's content words found in the page text. 1 for a\n * verbatim/normalized hit; the measured overlap otherwise.\n */\n overlap: number\n /** Content words present in the claim but NOT in the page text. */\n missingWords: string[]\n}\n\nexport interface GroundClaimOptions {\n /**\n * Minimum fraction of the claim's content words that must appear in the page\n * text to count as a close paraphrase when there is no verbatim/normalized\n * hit. Default 0.7 — a high bar, because a misattribution is exactly a claim\n * whose specific words the page does not contain.\n */\n minOverlap?: number\n /**\n * Content words shorter than this are ignored (drops \"the\", \"of\", \"is\", …)\n * and never count toward overlap. Default 3.\n */\n minWordLength?: number\n}\n\n/**\n * Stopwords stripped before overlap scoring so the bar measures the claim's\n * SUBSTANTIVE words (the numbers, nouns, methods it asserts), not filler a\n * misattributed page would trivially share with the real one.\n */\nconst stopwords = new Set([\n 'the',\n 'a',\n 'an',\n 'and',\n 'or',\n 'but',\n 'of',\n 'to',\n 'in',\n 'on',\n 'for',\n 'with',\n 'as',\n 'by',\n 'at',\n 'from',\n 'that',\n 'this',\n 'these',\n 'those',\n 'it',\n 'its',\n 'is',\n 'are',\n 'was',\n 'were',\n 'be',\n 'been',\n 'being',\n 'has',\n 'have',\n 'had',\n 'can',\n 'will',\n 'would',\n 'should',\n 'may',\n 'might',\n 'not',\n 'no',\n 'than',\n 'then',\n 'over',\n 'under',\n 'about',\n 'into',\n 'their',\n 'they',\n 'them',\n])\n\n/** Normalize for presence checks: lowercase, collapse whitespace + punctuation. */\nfunction normalize(text: string): string {\n return text\n .toLowerCase()\n .replace(/[^\\p{L}\\p{N}\\s]+/gu, ' ')\n .replace(/\\s+/g, ' ')\n .trim()\n}\n\n/** The claim's substantive content words (deduped, stopwords + short words removed). */\nfunction contentWords(claim: string, minWordLength: number): string[] {\n const words = normalize(claim)\n .split(' ')\n .filter((word) => word.length >= minWordLength && !stopwords.has(word))\n return [...new Set(words)]\n}\n\n/**\n * THE ORACLE. Is `claim` grounded in `pageText` (the `htmlToText` output of the\n * page the worker fetched)? Deterministic, no model call:\n *\n * 1. verbatim — the claim string appears as-is (case-insensitive).\n * 2. normalized — the claim appears after collapsing punctuation/whitespace\n * on both sides (so \"5.4x\" vs \"5.4 x\", smart quotes, etc. still match).\n * 3. overlap — a close paraphrase: at least `minOverlap` of the claim's\n * substantive content words appear in the page text. A misattributed page\n * fails here because the SPECIFIC words the claim asserts are absent.\n *\n * Returns the match mode, the measured overlap, and the missing content words —\n * enough for the driver to give a precise rejection reason and for a test/doc to\n * audit WHY a claim grounded or didn't.\n */\nexport function groundClaimInText(\n claim: string,\n pageText: string,\n options: GroundClaimOptions = {},\n): GroundingResult {\n const minOverlap = options.minOverlap ?? 0.7\n const minWordLength = Math.max(1, options.minWordLength ?? 3)\n\n const claimTrimmed = claim.trim()\n if (!claimTrimmed) return { grounded: false, mode: 'empty-claim', overlap: 0, missingWords: [] }\n if (!pageText.trim()) return { grounded: false, mode: 'empty-text', overlap: 0, missingWords: [] }\n\n const haystackLower = pageText.toLowerCase()\n if (haystackLower.includes(claimTrimmed.toLowerCase())) {\n return { grounded: true, mode: 'verbatim', overlap: 1, missingWords: [] }\n }\n\n const haystackNorm = normalize(pageText)\n const claimNorm = normalize(claimTrimmed)\n if (claimNorm && haystackNorm.includes(claimNorm)) {\n return { grounded: true, mode: 'normalized', overlap: 1, missingWords: [] }\n }\n\n const words = contentWords(claimTrimmed, minWordLength)\n if (words.length === 0) {\n // The claim has no substantive content words (all stopwords/short). With no\n // verbatim/normalized hit there is nothing to ground — treat as absent.\n return { grounded: false, mode: 'absent', overlap: 0, missingWords: [] }\n }\n // Word-boundary presence so \"rotary\" does not match inside \"rotaryxyz\".\n const present = words.filter((word) =>\n new RegExp(`\\\\b${word.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}\\\\b`).test(haystackNorm),\n )\n const missingWords = words.filter((word) => !present.includes(word))\n const overlap = present.length / words.length\n const grounded = overlap >= minOverlap\n return { grounded, mode: grounded ? 'overlap' : 'absent', overlap, missingWords }\n}\n\nexport interface ClaimGroundingDriverOptions extends GroundClaimOptions {\n /**\n * Optional second verifier to compose AFTER grounding passes. When set, a\n * source must BOTH ground its claim AND pass this verifier (e.g. the LLM\n * relevance driver's `verifySource`). Lets the loop reject off-topic AND\n * misattributed sources in one driver. Omit for the pure, zero-inference\n * grounding gate.\n */\n relevanceVerifier?: (\n source: ResearchSourceProposal,\n ctx: SourceVerificationContext,\n ) => Promise<SourceVerdict> | SourceVerdict\n /**\n * What to do when a proposal carries NO cited claim. `'reject'` (default) is\n * fail-closed: in claim-grounding mode every source must declare what it is\n * cited for, so an un-annotated source is treated as ungrounded. `'accept'`\n * lets unannotated sources through to the relevance verifier, if present.\n */\n onMissingClaim?: 'reject' | 'accept'\n}\n\n/**\n * A `ResearchDriver`-shaped verifier (just the `verifySource` arm) that gates on\n * CLAIM GROUNDING: it rejects a source whose cited claim is not present in its\n * fetched page text — a misattributed / fabricated citation — and (optionally)\n * composes a relevance verifier after grounding passes.\n *\n * The returned function matches `ResearchDriver['verifySource']`, so it drops\n * straight into `runVerifiedResearchLoop` as `{ verifySource: createClaimGroundingVerifier(...) }`.\n */\nexport function createClaimGroundingVerifier(options: ClaimGroundingDriverOptions = {}) {\n const onMissingClaim = options.onMissingClaim ?? 'reject'\n return async function verifySource(\n source: ResearchSourceProposal,\n ctx: SourceVerificationContext,\n ): Promise<SourceVerdict> {\n const claim = citedClaimOf(source)\n if (!claim) {\n if (onMissingClaim === 'reject') {\n return {\n accept: false,\n reason: 'no cited claim: claim-grounding mode requires every source to declare its claim',\n }\n }\n return options.relevanceVerifier ? options.relevanceVerifier(source, ctx) : { accept: true }\n }\n\n const grounding = groundClaimInText(claim, source.text, options)\n if (!grounding.grounded) {\n const detail =\n grounding.mode === 'empty-text'\n ? 'fetched page has no text'\n : `claim not found in the fetched page (overlap ${(grounding.overlap * 100).toFixed(0)}%${\n grounding.missingWords.length\n ? `, missing: ${grounding.missingWords.slice(0, 6).join(', ')}`\n : ''\n })`\n return {\n accept: false,\n reason: `misattributed citation: ${detail}`,\n }\n }\n\n if (options.relevanceVerifier) return options.relevanceVerifier(source, ctx)\n return { accept: true }\n }\n}\n\nexport interface WorkerClaimDecorationOptions {\n router?: RouterClient\n router_options?: TangleRouterOptions\n /** Max output tokens for the claim-extraction call. Default 1200 (glm floor). */\n maxTokens?: number\n}\n\n/**\n * Ask an LLM to state, for one source, the single specific factual claim a\n * researcher would cite THIS page for toward the goal. Used to DECORATE the\n * sources a relevance-only worker produced with the claim a citation would make,\n * so the claim-grounding verifier has something executable to check. The model\n * is told to ground the claim in the provided excerpt; the verifier then checks\n * it against the FULL page text independently — the model does not get to mark\n * its own homework.\n *\n * Returns the proposal annotated via `withCitedClaim`, or the original proposal\n * unchanged if the model returns nothing parseable (the verifier's\n * `onMissingClaim` policy then decides).\n */\nexport function createClaimDecorator(options: WorkerClaimDecorationOptions = {}) {\n const maxTokens = options.maxTokens ?? 1200\n return async function decorate(\n source: ResearchSourceProposal,\n goal: string,\n ): Promise<ResearchSourceProposal> {\n const router = options.router ?? createTangleRouterClient(options.router_options)\n const excerpt = source.text.slice(0, 1500)\n const system =\n 'You extract the single most important factual claim a researcher would cite a page for. ' +\n \"State ONE concrete, checkable sentence using the page's own key terms and numbers. \" +\n 'Do NOT invent facts not in the excerpt. Respond with ONLY the claim sentence, no prose.'\n const user = [\n `Research goal: ${goal}`,\n `Page title: ${source.title ?? '(none)'}`,\n `Page excerpt:\\n${excerpt}`,\n 'The single claim this page should be cited for:',\n ].join('\\n\\n')\n let raw = ''\n try {\n raw = await router.chat(\n [\n { role: 'system', content: system },\n { role: 'user', content: user },\n ],\n maxTokens,\n )\n } catch {\n return source\n }\n const claim = raw.trim().split('\\n')[0]?.trim()\n if (!claim) return source\n return withCitedClaim(source, claim)\n }\n}\n","import { groundClaimInText } from '../claim-grounding'\nimport { mean } from '../statistics'\nimport type {\n RagAnswerEvalArtifact,\n RagAnswerEvalScenario,\n RagAnswerQualityJudgeOptions,\n RagEvalCitation,\n RagEvalClaim,\n RagEvalContext,\n RagRequiredContext,\n} from './contracts'\n\nexport function requiredContextTargets(scenario: RagAnswerEvalScenario): RagRequiredContext[] {\n if (scenario.requiredContext?.length) return [...scenario.requiredContext]\n return (scenario.expectedClaims ?? []).map((text) => ({ text }))\n}\n\nexport function requiredContextTexts(scenario: RagAnswerEvalScenario): string[] {\n return requiredContextTargets(scenario).flatMap((target) => (target.text ? [target.text] : []))\n}\n\nexport function contextMatchesTarget(context: RagEvalContext, target: RagRequiredContext): boolean {\n if (target.id && context.id === target.id) return true\n if (target.pageId && context.pageId === target.pageId) return true\n if (target.sourceId && context.sourceId === target.sourceId) return true\n if (target.anchorId && context.anchorId === target.anchorId) return true\n if (target.text && textSupportScore(target.text, context.text) >= 0.7) return true\n return false\n}\n\nexport function contextIsRelevant(\n context: RagEvalContext,\n scenario: RagAnswerEvalScenario,\n): boolean {\n return contextRelevanceScore(context, scenario) >= 0.3\n}\n\nexport function contextRelevanceScore(\n context: RagEvalContext,\n scenario: RagAnswerEvalScenario,\n): number {\n const targets = [\n scenario.query,\n scenario.referenceAnswer,\n ...(scenario.expectedClaims ?? []),\n ...requiredContextTexts(scenario),\n ].filter((value): value is string => Boolean(value?.trim()))\n if (targets.length === 0) return 1\n return Math.max(...targets.map((target) => textSupportScore(target, context.text)))\n}\n\nexport function claimSupport(\n claim: string,\n contexts: readonly RagEvalContext[],\n options: Pick<RagAnswerQualityJudgeOptions, 'minClaimSupport'>,\n): boolean {\n if (contexts.length === 0) return false\n const combined = contexts.map((context) => context.text).join('\\n\\n')\n const deterministic = groundClaimInText(claim, combined, {\n minOverlap: options.minClaimSupport ?? 0.7,\n })\n return (\n deterministic.grounded || textSupportScore(claim, combined) >= (options.minClaimSupport ?? 0.7)\n )\n}\n\nexport function scoreCitations(\n claims: readonly RagEvalClaim[],\n artifact: RagAnswerEvalArtifact,\n scenario: RagAnswerEvalScenario,\n options: Pick<RagAnswerQualityJudgeOptions, 'minClaimSupport'>,\n): { support: number; citedClaimCount: number; supportedCitationCount: number } {\n if (claims.length === 0)\n return { support: scenario.unanswerable ? 1 : 0, citedClaimCount: 0, supportedCitationCount: 0 }\n const citations = artifact.citations ?? []\n const citedClaims = claims.filter((claim) => citationsForClaim(claim, citations).length > 0)\n if (citedClaims.length === 0) {\n return {\n support: scenario.requireCitations ? 0 : 1,\n citedClaimCount: 0,\n supportedCitationCount: 0,\n }\n }\n let supportedCitationCount = 0\n for (const claim of citedClaims) {\n const citedContexts = contextsForClaim(claim, citations, artifact.contexts)\n if (claimSupport(claim.text, citedContexts, options)) supportedCitationCount += 1\n }\n return {\n support: supportedCitationCount / citedClaims.length,\n citedClaimCount: citedClaims.length,\n supportedCitationCount,\n }\n}\n\nfunction citationsForClaim(\n claim: RagEvalClaim,\n citations: readonly RagEvalCitation[],\n): RagEvalCitation[] {\n const claimCitationIds = new Set(claim.citationIds ?? [])\n return citations.filter((citation) => {\n return citation.claimId === claim.id || (citation.id && claimCitationIds.has(citation.id))\n })\n}\n\nfunction contextsForClaim(\n claim: RagEvalClaim,\n citations: readonly RagEvalCitation[],\n contexts: readonly RagEvalContext[],\n): readonly RagEvalContext[] {\n const matchedCitations = citationsForClaim(claim, citations)\n const matchedContexts = contexts.filter((context) =>\n matchedCitations.some((citation) => {\n if (citation.contextId && citation.contextId === context.id) return true\n if (citation.pageId && citation.pageId === context.pageId) return true\n if (citation.sourceId && citation.sourceId === context.sourceId) return true\n if (citation.anchorId && citation.anchorId === context.anchorId) return true\n return false\n }),\n )\n return matchedContexts.length > 0 ? matchedContexts : contexts\n}\n\nexport function scoreAnswerRelevance(\n artifact: RagAnswerEvalArtifact,\n scenario: RagAnswerEvalScenario,\n abstained: boolean,\n): number {\n if (scenario.unanswerable) return abstained ? 1 : 0\n if (abstained) return 0\n const targets = [\n scenario.referenceAnswer,\n ...(scenario.expectedClaims ?? []),\n scenario.query,\n ].filter((value): value is string => Boolean(value?.trim()))\n return Math.max(...targets.map((target) => textSupportScore(target, artifact.answer)))\n}\n\nexport function scoreAnswerCorrectness(\n artifact: RagAnswerEvalArtifact,\n scenario: RagAnswerEvalScenario,\n abstained: boolean,\n): number {\n if (scenario.unanswerable) return abstained ? 1 : 0\n const expected = scenario.expectedClaims ?? []\n const forbidden = scenario.forbiddenClaims ?? []\n const expectedScore =\n expected.length === 0\n ? scoreAnswerRelevance(artifact, scenario, abstained)\n : mean(expected.map((claim) => textSupportScore(claim, artifact.answer)))\n const forbiddenPenalty =\n forbidden.length === 0\n ? 0\n : forbidden.filter((claim) => textSupportScore(claim, artifact.answer) >= 0.7).length /\n forbidden.length\n return clamp01(expectedScore * (1 - forbiddenPenalty))\n}\n\nexport function normalizeClaims(artifact: RagAnswerEvalArtifact): RagEvalClaim[] {\n if (artifact.claims?.length) return [...artifact.claims]\n return splitSentences(artifact.answer).map((text, index) => ({ id: `claim-${index + 1}`, text }))\n}\n\nfunction splitSentences(text: string): string[] {\n return text\n .split(/(?<=[.!?])\\s+/)\n .map((sentence) => sentence.trim())\n .filter((sentence) => sentence.length > 0 && !looksLikeAbstention(sentence))\n}\n\nexport function looksLikeAbstention(answer: string): boolean {\n const normalized = answer.toLowerCase()\n return [\n \"i don't know\",\n 'i do not know',\n 'not enough information',\n 'cannot answer',\n \"can't answer\",\n 'insufficient information',\n 'no reliable answer',\n ].some((phrase) => normalized.includes(phrase))\n}\n\nfunction textSupportScore(needle: string, haystack: string): number {\n const needleWords = contentWords(needle)\n if (needleWords.length === 0) return 0\n const haystackWords = new Set(contentWords(haystack))\n const present = needleWords.filter((word) => haystackWords.has(word))\n return present.length / needleWords.length\n}\n\nfunction contentWords(text: string): string[] {\n const normalized = text\n .toLowerCase()\n .replace(/[^\\p{L}\\p{N}\\s]+/gu, ' ')\n .split(/\\s+/)\n .map((word) => stem(word.trim()))\n .filter((word) => (word.length >= 3 || /^\\d+$/.test(word)) && !stopwords.has(word))\n return [...new Set(normalized)]\n}\n\nfunction stem(word: string): string {\n if (word.endsWith('ies') && word.length > 4) return `${word.slice(0, -3)}y`\n if (word.endsWith('ing') && word.length > 5) return word.slice(0, -3)\n if (word.endsWith('ed') && word.length > 4) return word.slice(0, -2)\n if (word.endsWith('s') && word.length > 3) return word.slice(0, -1)\n return word\n}\n\nexport function neutralScore(condition: boolean): number {\n return condition ? 1 : 0\n}\n\nexport function clamp01(value: number): number {\n if (!Number.isFinite(value)) return 0\n return Math.max(0, Math.min(1, value))\n}\n\nconst stopwords = new Set([\n 'the',\n 'a',\n 'an',\n 'and',\n 'or',\n 'but',\n 'of',\n 'to',\n 'in',\n 'on',\n 'for',\n 'with',\n 'as',\n 'by',\n 'at',\n 'from',\n 'that',\n 'this',\n 'these',\n 'those',\n 'it',\n 'its',\n 'is',\n 'are',\n 'was',\n 'were',\n 'be',\n 'been',\n 'being',\n 'has',\n 'have',\n 'had',\n 'can',\n 'will',\n 'would',\n 'should',\n 'may',\n 'might',\n 'not',\n 'no',\n 'than',\n 'then',\n 'over',\n 'under',\n 'about',\n 'into',\n 'their',\n 'they',\n 'them',\n 'what',\n 'when',\n 'where',\n 'who',\n 'why',\n 'how',\n])\n","import { clamp01, normalizeClaims, requiredContextTexts } from './answer'\nimport type { ExternalRagEvalScore, RagAnswerEvalCase, RagEvalMetricKey } from './contracts'\n\nconst metricAliases: Record<string, RagEvalMetricKey> = {\n answer_correctness: 'answer_correctness',\n answer_relevance: 'answer_relevance',\n answer_relevancy: 'answer_relevance',\n answerrelevancy: 'answer_relevance',\n context_precision: 'context_precision',\n context_recall: 'context_recall',\n context_relevance: 'context_relevance',\n context_relevancy: 'context_relevance',\n context_sufficiency: 'context_sufficiency',\n contextual_precision: 'context_precision',\n contextual_recall: 'context_recall',\n contextual_relevancy: 'context_relevance',\n faithfulness: 'faithfulness',\n groundedness: 'groundedness',\n claim_recall: 'context_recall',\n claim_precision: 'faithfulness',\n citation_support: 'citation_support',\n abstention: 'abstention',\n unsupported_answer_rate: 'unsupported_answer_rate',\n}\n\nexport function normalizeExternalRagScores(\n scores: readonly ExternalRagEvalScore[],\n): Record<string, Record<RagEvalMetricKey, number>> {\n const normalized: Record<string, Record<RagEvalMetricKey, number>> = {}\n for (const item of scores) {\n const provider = item.provider || 'custom'\n const providerScores = (normalized[provider] ?? {}) as Record<RagEvalMetricKey, number>\n for (const [key, value] of Object.entries(item.scores)) {\n const canonical = metricAliases[normalizeMetricName(key)]\n if (!canonical) continue\n if (Number.isFinite(value)) providerScores[canonical] = clamp01(value)\n }\n normalized[provider] = providerScores\n }\n return normalized\n}\n\nexport function toRagasEvaluationRows(cases: readonly RagAnswerEvalCase[]) {\n return cases.map(({ scenario, artifact }) => ({\n user_input: scenario.query,\n response: artifact.answer,\n retrieved_contexts: artifact.contexts.map((context) => context.text),\n reference: scenario.referenceAnswer,\n reference_contexts: requiredContextTexts(scenario),\n }))\n}\n\nexport function toDeepEvalTestCases(cases: readonly RagAnswerEvalCase[]) {\n return cases.map(({ scenario, artifact }) => ({\n input: scenario.query,\n actual_output: artifact.answer,\n expected_output: scenario.referenceAnswer,\n retrieval_context: artifact.contexts.map((context) => context.text),\n context: requiredContextTexts(scenario),\n }))\n}\n\nexport function toTruLensRecords(cases: readonly RagAnswerEvalCase[]) {\n return cases.map(({ scenario, artifact }) => ({\n input: scenario.query,\n output: artifact.answer,\n context: artifact.contexts.map((context) => context.text).join('\\n\\n'),\n }))\n}\n\nexport function toRagCheckerRecords(cases: readonly RagAnswerEvalCase[]) {\n return cases.map(({ scenario, artifact }) => ({\n query_id: scenario.id,\n query: scenario.query,\n gt_answer: scenario.referenceAnswer,\n response: artifact.answer,\n retrieved_context: artifact.contexts.map((context) => ({\n doc_id: context.id,\n text: context.text,\n })),\n claims: normalizeClaims(artifact).map((claim) => claim.text),\n }))\n}\n\nfunction normalizeMetricName(metric: string): string {\n return metric\n .trim()\n .toLowerCase()\n .replace(/[@/.-]+/g, '_')\n .replace(/\\s+/g, '_')\n}\n","import type { JudgeConfig } from '@tangle-network/agent-eval/campaign'\nimport type { RagGapFinding } from '../rag-improvement-loop'\nimport { mean } from '../statistics'\nimport {\n claimSupport,\n clamp01,\n contextIsRelevant,\n contextMatchesTarget,\n contextRelevanceScore,\n looksLikeAbstention,\n neutralScore,\n normalizeClaims,\n requiredContextTargets,\n scoreAnswerCorrectness,\n scoreAnswerRelevance,\n scoreCitations,\n} from './answer'\nimport type {\n RagAnswerEvalArtifact,\n RagAnswerEvalScenario,\n RagAnswerMetricSummary,\n RagAnswerQualityJudgeOptions,\n RagEvalMetricKey,\n} from './contracts'\nimport { normalizeExternalRagScores } from './providers'\n\nconst defaultThresholds: Partial<Record<RagEvalMetricKey, number>> = {\n context_precision: 0.5,\n context_recall: 0.8,\n context_relevance: 0.5,\n context_sufficiency: 0.8,\n faithfulness: 0.9,\n answer_relevance: 0.7,\n citation_support: 0.9,\n abstention: 1,\n unsupported_answer_rate: 0,\n}\n\nconst defaultWeights: Partial<Record<RagEvalMetricKey, number>> = {\n context_relevance: 1,\n context_sufficiency: 1,\n faithfulness: 2,\n answer_relevance: 1,\n citation_support: 1,\n abstention: 1,\n}\n\nexport function ragAnswerQualityJudge(\n options: RagAnswerQualityJudgeOptions = {},\n): JudgeConfig<RagAnswerEvalArtifact, RagAnswerEvalScenario> {\n return {\n name: options.name ?? 'rag-answer-quality',\n dimensions: [\n { key: 'context_precision', description: 'share of retrieved context that is useful' },\n { key: 'context_recall', description: 'share of required evidence present in context' },\n { key: 'context_relevance', description: 'context relevance to the query and answer target' },\n { key: 'context_sufficiency', description: 'whether context is enough to answer' },\n { key: 'faithfulness', description: 'share of answer claims supported by retrieved context' },\n { key: 'answer_relevance', description: 'answer addresses the user query' },\n { key: 'answer_correctness', description: 'answer contains expected claims' },\n { key: 'citation_support', description: 'citations support the claims they cite' },\n { key: 'abstention', description: 'answer abstains exactly when the case is unanswerable' },\n ],\n appliesTo: (scenario) => scenario.kind === 'rag-answer-eval',\n async score({ artifact, scenario }) {\n const summary = scoreRagAnswerArtifact(artifact, scenario, options)\n return {\n dimensions: summary.metrics,\n composite: summary.composite,\n notes: summary.findings.map((finding) => finding.message).join('; '),\n }\n },\n }\n}\n\nexport function scoreRagAnswerArtifact(\n artifact: RagAnswerEvalArtifact,\n scenario: RagAnswerEvalScenario,\n options: RagAnswerQualityJudgeOptions = {},\n): RagAnswerMetricSummary {\n const claims = normalizeClaims(artifact)\n const abstained = artifact.abstained ?? looksLikeAbstention(artifact.answer)\n const requiredTargets = requiredContextTargets(scenario)\n const matchedRequiredContextCount = requiredTargets.filter((target) =>\n artifact.contexts.some((context) => contextMatchesTarget(context, target)),\n ).length\n const requiredContextCount = requiredTargets.length\n const contextRecall =\n requiredContextCount === 0\n ? neutralScore(Boolean(scenario.unanswerable) || artifact.contexts.length > 0)\n : matchedRequiredContextCount / requiredContextCount\n const relevantContextCount = artifact.contexts.filter((context) =>\n contextIsRelevant(context, scenario),\n ).length\n const contextPrecision =\n artifact.contexts.length === 0\n ? scenario.unanswerable\n ? 1\n : 0\n : relevantContextCount / artifact.contexts.length\n const contextRelevance =\n artifact.contexts.length === 0\n ? scenario.unanswerable\n ? 1\n : 0\n : mean(artifact.contexts.map((context) => contextRelevanceScore(context, scenario)))\n const contextSufficiency = requiredContextCount === 0 ? contextRelevance : contextRecall\n const support = claims.map((claim) => claimSupport(claim.text, artifact.contexts, options))\n const supportedClaimCount = support.filter(Boolean).length\n const faithfulness =\n claims.length === 0 ? (abstained ? 1 : 0) : supportedClaimCount / Math.max(1, claims.length)\n const citation = scoreCitations(claims, artifact, scenario, options)\n const answerRelevance = scoreAnswerRelevance(artifact, scenario, abstained)\n const answerCorrectness = scoreAnswerCorrectness(artifact, scenario, abstained)\n const abstention = scenario.unanswerable ? (abstained ? 1 : 0) : abstained ? 0 : 1\n const unsupportedAnswerRate =\n claims.length === 0 ? (abstained ? 0 : 1) : 1 - supportedClaimCount / Math.max(1, claims.length)\n\n const deterministicMetrics: Record<RagEvalMetricKey, number> = {\n context_precision: clamp01(contextPrecision),\n context_recall: clamp01(contextRecall),\n context_relevance: clamp01(contextRelevance),\n context_sufficiency: clamp01(contextSufficiency),\n faithfulness: clamp01(faithfulness),\n groundedness: clamp01(faithfulness),\n answer_relevance: clamp01(answerRelevance),\n answer_correctness: clamp01(answerCorrectness),\n citation_support: clamp01(citation.support),\n abstention: clamp01(abstention),\n unsupported_answer_rate: clamp01(unsupportedAnswerRate),\n }\n const providerScores = normalizeExternalRagScores(artifact.externalScores ?? [])\n const metrics = mergeMetrics(deterministicMetrics, providerScores, options.externalScorePolicy)\n const thresholds = { ...defaultThresholds, ...scenario.thresholds, ...options.thresholds }\n const findings = diagnoseRagAnswerFailure(metrics, scenario, thresholds)\n const composite = weightedComposite(metrics, options.weights ?? defaultWeights)\n\n return {\n metrics,\n composite,\n passed: findings.every(\n (finding) => finding.severity !== 'error' && finding.severity !== 'critical',\n ),\n findings,\n claimCount: claims.length,\n supportedClaimCount,\n citedClaimCount: citation.citedClaimCount,\n supportedCitationCount: citation.supportedCitationCount,\n matchedRequiredContextCount,\n requiredContextCount,\n providerScores,\n }\n}\n\nexport function diagnoseRagAnswerFailure(\n metrics: Record<RagEvalMetricKey, number>,\n scenario: RagAnswerEvalScenario,\n thresholds: Partial<Record<RagEvalMetricKey, number>> = defaultThresholds,\n): RagGapFinding[] {\n const findings: RagGapFinding[] = []\n if (below(metrics.context_recall, thresholds.context_recall)) {\n findings.push({\n id: `${scenario.id}:context-recall`,\n kind: scenario.slices?.includes('multi-source')\n ? 'missing-multihop-evidence'\n : 'retrieval-miss',\n severity: 'error',\n scenarioId: scenario.id,\n message: 'Required evidence was not present in retrieved context.',\n evidence: { context_recall: metrics.context_recall },\n })\n }\n if (below(metrics.context_precision, thresholds.context_precision)) {\n findings.push({\n id: `${scenario.id}:context-precision`,\n kind: 'retrieval-noise',\n severity: 'warning',\n scenarioId: scenario.id,\n message: 'Retrieved context contains too much irrelevant material.',\n evidence: { context_precision: metrics.context_precision },\n })\n }\n if (below(metrics.faithfulness, thresholds.faithfulness)) {\n findings.push({\n id: `${scenario.id}:faithfulness`,\n kind: 'generator-unsupported-claim',\n severity: 'error',\n scenarioId: scenario.id,\n message: 'The answer contains claims not supported by retrieved context.',\n evidence: { faithfulness: metrics.faithfulness },\n })\n }\n if (below(metrics.citation_support, thresholds.citation_support)) {\n findings.push({\n id: `${scenario.id}:citation-support`,\n kind: 'citation-mismatch',\n severity: 'error',\n scenarioId: scenario.id,\n message: 'Citations do not support the claims they are attached to.',\n evidence: { citation_support: metrics.citation_support },\n })\n }\n if (below(metrics.abstention, thresholds.abstention)) {\n findings.push({\n id: `${scenario.id}:abstention`,\n kind: 'incorrect-abstention',\n severity: 'error',\n scenarioId: scenario.id,\n message: scenario.unanswerable\n ? 'The system answered a case marked unanswerable.'\n : 'The system abstained from an answerable case.',\n evidence: { abstention: metrics.abstention },\n })\n }\n return findings\n}\n\nfunction mergeMetrics(\n deterministic: Record<RagEvalMetricKey, number>,\n providerScores: Record<string, Record<RagEvalMetricKey, number>>,\n policy: RagAnswerQualityJudgeOptions['externalScorePolicy'] = 'prefer-external',\n): Record<RagEvalMetricKey, number> {\n if (policy === 'deterministic-first') return deterministic\n const merged = { ...deterministic }\n for (const scores of Object.values(providerScores)) {\n for (const [key, value] of Object.entries(scores) as Array<[RagEvalMetricKey, number]>) {\n merged[key] = value\n if (key === 'groundedness') merged.faithfulness = value\n if (key === 'faithfulness') merged.groundedness = value\n }\n }\n return merged\n}\n\nexport function aggregateRagAnswerMetrics(\n summaries: readonly RagAnswerMetricSummary[],\n): Record<string, number> {\n const keys = new Set<RagEvalMetricKey>()\n for (const summary of summaries) {\n for (const key of Object.keys(summary.metrics) as RagEvalMetricKey[]) keys.add(key)\n }\n const out: Record<string, number> = {}\n for (const key of [...keys].sort()) {\n out[key] = mean(summaries.map((summary) => summary.metrics[key]))\n }\n out.composite = mean(summaries.map((summary) => summary.composite))\n return out\n}\n\nfunction weightedComposite(\n metrics: Record<RagEvalMetricKey, number>,\n weights: Partial<Record<RagEvalMetricKey, number>>,\n): number {\n let weighted = 0\n let total = 0\n for (const [key, weight] of Object.entries(weights) as Array<[RagEvalMetricKey, number]>) {\n if (!Number.isFinite(weight) || weight <= 0) continue\n const metric = metrics[key]\n if (!Number.isFinite(metric)) continue\n const value = key === 'unsupported_answer_rate' ? 1 - metric : metric\n weighted += value * weight\n total += weight\n }\n return total === 0 ? 0 : weighted / total\n}\n\nfunction below(metric: number, threshold: number | undefined): boolean {\n return threshold !== undefined && metric < threshold\n}\n","import { contentHash } from '@tangle-network/agent-eval'\nimport { assertImmutableRef } from '../immutable-ref'\nimport type { RagAnswerQualityResult, RagGapFinding } from '../rag-improvement-loop'\nimport type {\n RagAnswerMetricSummary,\n RagAnswerQualityHookOptions,\n RagCalibrationOptions,\n RagCalibrationResult,\n} from './contracts'\nimport { aggregateRagAnswerMetrics, ragAnswerQualityJudge, scoreRagAnswerArtifact } from './scoring'\n\nexport function createRagAnswerQualityHook(\n options: RagAnswerQualityHookOptions,\n): () => Promise<RagAnswerQualityResult> {\n assertImmutableRef(options.evaluatorRef, 'RAG answer evaluatorRef')\n const finalScenarioIds = options.scenarios.map((scenario) => scenario.id)\n if (\n finalScenarioIds.length < 2 ||\n new Set(finalScenarioIds).size !== finalScenarioIds.length ||\n finalScenarioIds.some((id) => !id.trim())\n ) {\n throw new Error('RAG answer quality requires at least 2 unique final scenarios')\n }\n const datasetRef = `sha256:${contentHash(options.scenarios)}`\n return async () => {\n const summaries: RagAnswerMetricSummary[] = []\n const findings: RagGapFinding[] = []\n for (const scenario of options.scenarios) {\n const initialArtifact = await options.run(scenario)\n const external = await options.externalEvaluator?.({ scenario, artifact: initialArtifact })\n const artifact = external\n ? {\n ...initialArtifact,\n externalScores: [\n ...(initialArtifact.externalScores ?? []),\n ...(Array.isArray(external) ? external : [external]),\n ],\n }\n : initialArtifact\n const summary = scoreRagAnswerArtifact(artifact, scenario, {\n thresholds: options.thresholds,\n weights: options.weights,\n })\n summaries.push(summary)\n findings.push(...summary.findings)\n }\n const metrics = aggregateRagAnswerMetrics(summaries)\n const cost =\n typeof options.cost === 'function' ? await options.cost() : structuredClone(options.cost)\n return {\n passed: findings.length === 0,\n metrics,\n finalScenarioIds,\n datasetRef,\n evaluatorRef: options.evaluatorRef,\n cost,\n findings,\n metadata: { scenarioCount: options.scenarios.length },\n }\n }\n}\n\nexport async function calibrateRagAnswerJudge(\n options: RagCalibrationOptions,\n): Promise<RagCalibrationResult> {\n const judge = options.judge ?? ragAnswerQualityJudge()\n const strong = await judge.score({\n artifact: options.strong,\n scenario: options.scenario,\n signal: options.signal ?? new AbortController().signal,\n })\n const weak = await judge.score({\n artifact: options.weak,\n scenario: options.scenario,\n signal: options.signal ?? new AbortController().signal,\n })\n const strongScore = strong.composite\n const weakScore = weak.composite\n const minStrongScore = options.minStrongScore ?? 0.7\n const maxWeakScore = options.maxWeakScore ?? 0.3\n return {\n passed: strongScore >= minStrongScore && weakScore <= maxWeakScore,\n strongScore,\n weakScore,\n gap: strongScore - weakScore,\n }\n}\n","import { lintKnowledgeIndex } from '../lint'\nimport type { RagGapFinding } from '../rag-improvement-loop'\nimport type { KnowledgeIndex } from '../types'\nimport { validateKnowledgeIndex } from '../validate'\nimport type { KnowledgeBaseQualityOptions, KnowledgeBaseQualityReport } from './contracts'\nimport { detectNearDuplicatePages } from './near-duplicates'\n\nexport function scoreKnowledgeBaseIndex(\n index: KnowledgeIndex,\n options: KnowledgeBaseQualityOptions = {},\n): KnowledgeBaseQualityReport {\n const validation = validateKnowledgeIndex(index, { strict: options.strict })\n const lintFindings = lintKnowledgeIndex(index)\n const now = options.now ?? new Date()\n const staleSourceCount = index.sources.filter((source) => {\n return source.validUntil ? Date.parse(source.validUntil) < now.getTime() : false\n }).length\n const sourceHashCounts = new Map<string, number>()\n for (const source of index.sources) {\n sourceHashCounts.set(source.contentHash, (sourceHashCounts.get(source.contentHash) ?? 0) + 1)\n }\n const duplicateSourceHashCount = [...sourceHashCounts.values()].filter(\n (count) => count > 1,\n ).length\n const pagesWithInlineCitations = index.pages.filter(\n (page) => sourceRefs(page.text).length > 0,\n ).length\n const pagesWithSources = index.pages.filter((page) => page.sourceIds.length > 0).length\n const nearDuplicates = detectNearDuplicatePages(index.pages, options.nearDuplicates)\n const maxNearDuplicatePageRate = unitInterval(\n options.maxNearDuplicatePageRate ?? 1,\n 'maxNearDuplicatePageRate',\n )\n const metrics = {\n page_count: index.pages.length,\n source_count: index.sources.length,\n citation_rate: index.pages.length === 0 ? 1 : pagesWithInlineCitations / index.pages.length,\n source_backed_page_rate: index.pages.length === 0 ? 1 : pagesWithSources / index.pages.length,\n stale_source_rate: index.sources.length === 0 ? 0 : staleSourceCount / index.sources.length,\n duplicate_source_hash_rate:\n index.sources.length === 0 ? 0 : duplicateSourceHashCount / index.sources.length,\n lint_error_count: validation.findings.filter((finding) => finding.severity === 'error').length,\n lint_warning_count: lintFindings.filter((finding) => finding.severity === 'warning').length,\n near_duplicate_page_rate: nearDuplicates.duplicatePageRate,\n near_duplicate_page_count: nearDuplicates.duplicatePageCount,\n near_duplicate_pair_count: nearDuplicates.duplicatePairCount,\n }\n const findings: RagGapFinding[] = []\n if (metrics.lint_error_count > 0) {\n findings.push({\n id: 'kb:lint-errors',\n kind: 'unknown',\n severity: 'critical',\n message: `${metrics.lint_error_count} validation error(s) in the knowledge index.`,\n evidence: { lint_error_count: metrics.lint_error_count },\n })\n }\n if (metrics.citation_rate < (options.minCitationRate ?? 0)) {\n findings.push({\n id: 'kb:citation-rate',\n kind: 'missing-source',\n severity: 'error',\n message: 'Inline citation coverage is below the configured minimum.',\n evidence: { citation_rate: metrics.citation_rate },\n })\n }\n if (metrics.stale_source_rate > (options.maxStaleSourceRate ?? 1)) {\n findings.push({\n id: 'kb:stale-source-rate',\n kind: 'stale-source',\n severity: 'error',\n message: 'Stale source rate exceeds the configured maximum.',\n evidence: { stale_source_rate: metrics.stale_source_rate },\n })\n }\n if (nearDuplicates.truncated && maxNearDuplicatePageRate < 1) {\n findings.push({\n id: 'kb:near-duplicate-analysis-truncated',\n kind: 'unknown',\n severity: 'error',\n message:\n 'Near-duplicate analysis reached a configured bound, so the duplicate-page gate cannot be evaluated completely.',\n evidence: {\n candidate_pair_count: nearDuplicates.candidatePairCount,\n compared_pair_count: nearDuplicates.comparedPairCount,\n duplicate_pair_count: nearDuplicates.duplicatePairCount,\n },\n })\n } else if (metrics.near_duplicate_page_rate > maxNearDuplicatePageRate) {\n findings.push({\n id: 'kb:near-duplicate-page-rate',\n kind: 'unknown',\n severity: 'error',\n message: 'Near-duplicate page rate exceeds the configured maximum.',\n evidence: {\n near_duplicate_page_rate: metrics.near_duplicate_page_rate,\n near_duplicate_page_count: metrics.near_duplicate_page_count,\n near_duplicate_pair_count: metrics.near_duplicate_pair_count,\n threshold: nearDuplicates.threshold,\n },\n })\n }\n return { ok: findings.length === 0, metrics, nearDuplicates, findings }\n}\n\nfunction sourceRefs(text: string): string[] {\n const refs: string[] = []\n const regex = /\\[\\^([A-Za-z0-9_-]+)(?:#([A-Za-z0-9_.:-]+))?\\]/g\n let match = regex.exec(text)\n while (match !== null) {\n refs.push(match[0])\n match = regex.exec(text)\n }\n return refs\n}\n\nfunction unitInterval(value: number, name: string): number {\n if (!Number.isFinite(value) || value < 0 || value > 1) {\n throw new Error(`${name} must be a finite number in [0, 1]`)\n }\n return value\n}\n","import type {\n DispatchContext,\n JudgeConfig,\n OptimizationMethod,\n} from '@tangle-network/agent-eval/campaign'\nimport type { AgentCandidateJsonValue as JsonValue } from '@tangle-network/agent-interface'\nimport {\n jsonObjectCandidateCodec,\n type RunSerializedKnowledgeOptimizationOptions,\n type RunSerializedKnowledgeOptimizationResult,\n runSerializedKnowledgeOptimization,\n scenarioContentFingerprint,\n} from './optimization'\nimport type { RagAnswerEvalArtifact, RagAnswerEvalScenario } from './rag-eval'\nimport { ragAnswerQualityJudge } from './rag-eval'\n\nexport type RagOptimizationConfig = Record<string, JsonValue>\n\ntype RagOptimizationBaseOptions = Omit<\n RunSerializedKnowledgeOptimizationOptions<\n RagOptimizationConfig,\n RagAnswerEvalScenario,\n RagAnswerEvalArtifact\n >,\n | 'baseline'\n | 'method'\n | 'trainScenarios'\n | 'selectionScenarios'\n | 'finalScenarios'\n | 'dispatchCandidate'\n | 'judges'\n | 'codec'\n | 'scenarioFingerprint'\n>\n\nexport interface RunRagOptimizationOptions extends RagOptimizationBaseOptions {\n baseline: RagOptimizationConfig\n method: OptimizationMethod<RagAnswerEvalScenario, RagAnswerEvalArtifact>\n trainScenarios: readonly RagAnswerEvalScenario[]\n selectionScenarios: readonly RagAnswerEvalScenario[]\n finalScenarios: readonly RagAnswerEvalScenario[]\n run(input: {\n config: RagOptimizationConfig\n configSurface: string\n configSurfaceHash: string\n scenario: RagAnswerEvalScenario\n context: DispatchContext\n }): Promise<RagAnswerEvalArtifact>\n judges?: readonly JudgeConfig<RagAnswerEvalArtifact, RagAnswerEvalScenario>[]\n}\n\nexport interface RunRagOptimizationResult\n extends RunSerializedKnowledgeOptimizationResult<RagOptimizationConfig> {\n baselineConfig: RagOptimizationConfig\n winnerConfig: RagOptimizationConfig\n trainScenarios: readonly RagAnswerEvalScenario[]\n selectionScenarios: readonly RagAnswerEvalScenario[]\n finalScenarios: readonly RagAnswerEvalScenario[]\n}\n\n/** Optimizes retrieval and answer behavior together as one serialized RAG configuration. */\nexport async function runRagOptimization(\n options: RunRagOptimizationOptions,\n): Promise<RunRagOptimizationResult> {\n const {\n baseline,\n method,\n trainScenarios,\n selectionScenarios,\n finalScenarios,\n run,\n judges,\n ...runOptions\n } = options\n const result = await runSerializedKnowledgeOptimization({\n ...runOptions,\n baseline,\n method,\n trainScenarios,\n selectionScenarios,\n finalScenarios,\n codec: jsonObjectCandidateCodec<RagOptimizationConfig>(),\n judges: [...(judges ?? [ragAnswerQualityJudge()])],\n scenarioFingerprint: scenarioContentFingerprint,\n dispatchCandidate: ({ candidate, candidateSurface, candidateSurfaceHash, scenario, context }) =>\n run({\n config: candidate,\n configSurface: candidateSurface,\n configSurfaceHash: candidateSurfaceHash,\n scenario,\n context,\n }),\n })\n return {\n ...result,\n baselineConfig: result.baseline.value,\n winnerConfig: result.winner.value,\n trainScenarios: [...trainScenarios],\n selectionScenarios: [...selectionScenarios],\n finalScenarios: [...finalScenarios],\n }\n}\n","import { stableId } from './ids'\nimport type { KnowledgeEvent, KnowledgeEventType } from './types'\n\nexport interface KnowledgeEventQuery {\n type?: KnowledgeEventType\n target?: string\n limit?: number\n}\n\nexport function createKnowledgeEvent(input: {\n type: KnowledgeEventType\n actor?: string\n target?: string\n metadata?: Record<string, unknown>\n now?: () => Date\n}): KnowledgeEvent {\n const createdAt = (input.now ?? (() => new Date()))().toISOString()\n return {\n id: stableId(\n 'evt',\n `${input.type}:${input.target ?? ''}:${createdAt}:${JSON.stringify(input.metadata ?? {})}`,\n ),\n type: input.type,\n createdAt,\n // An absent optional is omitted, never written as `undefined`. An event\n // reaches canonical JSON — through a control-loop state fingerprint and\n // through the event log — and that encoder refuses a key with no value.\n ...(input.actor === undefined ? {} : { actor: input.actor }),\n ...(input.target === undefined ? {} : { target: input.target }),\n ...(input.metadata === undefined ? {} : { metadata: input.metadata }),\n }\n}\n","import {\n acquisitionPlansForKnowledgeGaps,\n type DataAcquisitionPlan,\n type KnowledgeAcquisitionMode,\n type KnowledgeBundle,\n type KnowledgeFreshness,\n type KnowledgeImportance,\n type KnowledgeReadinessReport,\n type KnowledgeRequirement,\n type KnowledgeRequirementCategory,\n type KnowledgeSensitivity,\n scoreKnowledgeReadiness,\n type UserQuestion,\n userQuestionsForKnowledgeGaps,\n} from '@tangle-network/agent-eval'\nimport { stringMetadata } from './metadata'\nimport { searchKnowledge } from './search'\nimport type { KnowledgeIndex, KnowledgeSearchResult } from './types'\n\nexport interface KnowledgeReadinessSpec {\n id: string\n description: string\n query: string\n requiredFor: string[]\n category: KnowledgeRequirementCategory\n acquisitionMode: KnowledgeAcquisitionMode\n importance: KnowledgeImportance\n freshness: KnowledgeFreshness\n sensitivity: KnowledgeSensitivity\n confidenceNeeded: number\n fallbackPolicy?: KnowledgeRequirement['fallbackPolicy']\n minSources?: number\n minHits?: number\n metadata?: Record<string, unknown>\n}\n\n/**\n * Defaults applied by `defineReadinessSpec` when the caller omits the field.\n *\n * These are deliberately conservative: a domain-specific topic that an agent\n * needs grounded to a high-confidence threshold from at least one authoritative\n * source. Override any field to specialise (e.g. `freshness: 'daily'` for a\n * topic that must reflect today's regulatory state).\n */\nexport const READINESS_SPEC_DEFAULTS = {\n category: 'domain_specific',\n acquisitionMode: 'search_web',\n importance: 'high',\n freshness: 'monthly',\n sensitivity: 'public',\n confidenceNeeded: 0.7,\n minSources: 1,\n minHits: 2,\n} as const satisfies Pick<\n KnowledgeReadinessSpec,\n | 'category'\n | 'acquisitionMode'\n | 'importance'\n | 'freshness'\n | 'sensitivity'\n | 'confidenceNeeded'\n | 'minSources'\n | 'minHits'\n>\n\n/**\n * Inputs accepted by `defineReadinessSpec`. The four fields the caller cannot\n * sanely default (id, description, query, requiredFor) are required; everything\n * else is optional and pulls from `READINESS_SPEC_DEFAULTS`.\n */\nexport type DefineReadinessSpecInput = Pick<\n KnowledgeReadinessSpec,\n 'id' | 'description' | 'query' | 'requiredFor'\n> &\n Partial<Omit<KnowledgeReadinessSpec, 'id' | 'description' | 'query' | 'requiredFor'>>\n\n/**\n * Builder that returns a fully-typed `KnowledgeReadinessSpec` from a slim input.\n *\n * Motivation: `KnowledgeReadinessSpec` has eleven required fields. Most of them\n * (category, acquisition mode, importance, freshness, sensitivity, confidence\n * threshold, source/hit minima) have a clear default for domain-specific KB\n * topics — agents end up copy-pasting the same boilerplate across every spec.\n * This helper collapses that boilerplate while keeping every field overridable.\n *\n * @example\n * defineReadinessSpec({\n * id: 'coop/intent-grounding',\n * description: 'Required grounding for coop pack intent stage',\n * query: 'flock size space ventilation predator',\n * requiredFor: ['IntentIntakeAgent', 'requirements'],\n * })\n *\n * @example // override defaults where the topic demands it\n * defineReadinessSpec({\n * id: 'medical/dosing',\n * description: 'Dosing guidance for compounding pharmacy',\n * query: 'compounding dose schedule',\n * requiredFor: ['DosingAgent'],\n * importance: 'blocking',\n * freshness: 'daily',\n * sensitivity: 'private',\n * confidenceNeeded: 0.95,\n * minSources: 3,\n * })\n */\nexport function defineReadinessSpec(input: DefineReadinessSpecInput): KnowledgeReadinessSpec {\n return {\n ...READINESS_SPEC_DEFAULTS,\n ...input,\n }\n}\n\nexport interface BuildEvalKnowledgeBundleOptions {\n taskId: string\n index: KnowledgeIndex\n specs: KnowledgeReadinessSpec[]\n userAnswers?: Record<string, string>\n searchLimit?: number\n metadata?: Record<string, unknown>\n now?: Date\n}\n\nexport interface EvalKnowledgeBundleBuildResult {\n bundle: KnowledgeBundle\n report: KnowledgeReadinessReport\n requirements: KnowledgeRequirement[]\n searchResultsByRequirement: Record<string, KnowledgeSearchResult[]>\n questions: UserQuestion[]\n acquisitionPlans: DataAcquisitionPlan[]\n}\n\nexport function buildEvalKnowledgeBundle(\n options: BuildEvalKnowledgeBundleOptions,\n): EvalKnowledgeBundleBuildResult {\n const searchLimit = options.searchLimit ?? 5\n const now = options.now ?? new Date()\n const searchResultsByRequirement: Record<string, KnowledgeSearchResult[]> = {}\n const requirements = options.specs.map((spec) => {\n const results = searchKnowledge(options.index, spec.query, searchLimit)\n searchResultsByRequirement[spec.id] = results\n return requirementFromSearch(options.index, spec, results, now)\n })\n const report = scoreKnowledgeReadiness({\n taskId: options.taskId,\n requirements,\n userAnswers: options.userAnswers,\n evidenceIds: requirements.flatMap((requirement) => requirement.evidenceIds),\n claimIds: [],\n wikiPageIds: unique(\n requirements.flatMap((requirement) =>\n pageIdsFromResults(searchResultsByRequirement[requirement.id] ?? []),\n ),\n ),\n metadata: options.metadata,\n })\n const questions = userQuestionsForKnowledgeGaps(report.blockingMissingRequirements)\n const acquisitionPlans = acquisitionPlansForKnowledgeGaps([\n ...report.blockingMissingRequirements,\n ...report.nonBlockingGaps,\n ])\n\n return {\n bundle: report.bundle,\n report,\n requirements,\n searchResultsByRequirement,\n questions,\n acquisitionPlans,\n }\n}\n\nfunction requirementFromSearch(\n index: KnowledgeIndex,\n spec: KnowledgeReadinessSpec,\n results: KnowledgeSearchResult[],\n now: Date,\n): KnowledgeRequirement {\n const hitCount = results.length\n const sourceIds = unique(results.flatMap((result) => result.page.sourceIds))\n const sources = index.sources.filter((source) => sourceIds.includes(source.id))\n const bestScore = results[0]?.normalizedScore ?? 0\n const sourceCoverage = spec.minSources\n ? Math.min(1, sourceIds.length / spec.minSources)\n : sourceIds.length > 0\n ? 1\n : 0\n const hitCoverage = spec.minHits ? Math.min(1, hitCount / spec.minHits) : hitCount > 0 ? 1 : 0\n const freshness = sourceFreshness(sources, now)\n const currentConfidence = round(Math.min(bestScore, sourceCoverage, hitCoverage, freshness.score))\n\n return {\n id: spec.id,\n description: spec.description,\n requiredFor: spec.requiredFor,\n category: spec.category,\n acquisitionMode: spec.acquisitionMode,\n importance: spec.importance,\n freshness: spec.freshness,\n sensitivity: spec.sensitivity,\n confidenceNeeded: spec.confidenceNeeded,\n currentConfidence,\n evidenceIds: unique([\n ...sourceIds.map((sourceId) => `source:${sourceId}`),\n ...results.map((result) => `page:${result.page.id}`),\n ]),\n fallbackPolicy:\n spec.fallbackPolicy ?? (spec.importance === 'blocking' ? 'block' : 'continue_with_caveat'),\n metadata: {\n ...spec.metadata,\n query: spec.query,\n hitCount,\n sourceCount: sourceIds.length,\n bestNormalizedScore: bestScore,\n expiredSourceIds: freshness.expiredSourceIds,\n freshnessScore: freshness.score,\n // An unknown freshness bound is absent from the record rather than present\n // and undefined: the two are the same JSON, so the canonical encoder refuses\n // the key instead of guessing which was meant.\n ...(freshness.validUntil === undefined ? {} : { validUntil: freshness.validUntil }),\n ...(freshness.lastVerifiedAt === undefined\n ? {}\n : { lastVerifiedAt: freshness.lastVerifiedAt }),\n },\n }\n}\n\nfunction sourceFreshness(\n sources: KnowledgeIndex['sources'],\n now: Date,\n): { score: number; validUntil?: string; lastVerifiedAt?: string; expiredSourceIds: string[] } {\n if (sources.length === 0) return { score: 0, expiredSourceIds: [] }\n const validUntilValues = sources\n .map(\n (source) =>\n source.validUntil ??\n stringMetadata(source.metadata, 'validUntil') ??\n stringMetadata(source.metadata, 'expiresAt'),\n )\n .filter(isIsoDate)\n const lastVerifiedValues = sources\n .map((source) => source.lastVerifiedAt ?? stringMetadata(source.metadata, 'lastVerifiedAt'))\n .filter(isIsoDate)\n const expiredSourceIds = sources\n .filter((source) => {\n const validUntil =\n source.validUntil ??\n stringMetadata(source.metadata, 'validUntil') ??\n stringMetadata(source.metadata, 'expiresAt')\n return validUntil ? Date.parse(validUntil) <= now.getTime() : false\n })\n .map((source) => source.id)\n return {\n score: expiredSourceIds.length > 0 ? 0 : 1,\n validUntil: earliestIso(validUntilValues),\n lastVerifiedAt: latestIso(lastVerifiedValues),\n expiredSourceIds,\n }\n}\n\nfunction isIsoDate(value: string | undefined): value is string {\n return Boolean(value && Number.isFinite(Date.parse(value)))\n}\n\nfunction earliestIso(values: string[]): string | undefined {\n return values.sort((a, b) => Date.parse(a) - Date.parse(b))[0]\n}\n\nfunction latestIso(values: string[]): string | undefined {\n return values.sort((a, b) => Date.parse(b) - Date.parse(a))[0]\n}\n\nfunction pageIdsFromResults(results: KnowledgeSearchResult[]): string[] {\n return results.map((result) => result.page.id)\n}\n\nfunction unique<T>(items: T[]): T[] {\n return [...new Set(items)]\n}\n\nfunction round(value: number): number {\n return Math.round(value * 1000) / 1000\n}\n","import {\n type BuildEvalKnowledgeBundleOptions,\n buildEvalKnowledgeBundle,\n type EvalKnowledgeBundleBuildResult,\n type KnowledgeReadinessSpec,\n} from './eval-readiness'\nimport type { KnowledgeIndex } from './types'\n\n/**\n * The subset of a research-loop options object the readiness gate needs:\n * the goal (default task id), the readiness specs, an optional task-id\n * override, and the rest of the bundle options minus the fields this helper\n * supplies (`taskId`/`index`/`specs`).\n *\n * Both the single-agent (`research-loop`) and two-agent (`verified-research-loop`)\n * options shapes satisfy this structurally, so the gate is single-sourced.\n */\nexport interface ReadinessGateOptions {\n goal: string\n readinessSpecs?: KnowledgeReadinessSpec[]\n readinessTaskId?: string\n readiness?: Omit<BuildEvalKnowledgeBundleOptions, 'taskId' | 'index' | 'specs'>\n}\n\n/**\n * Build the readiness bundle for a loop run over the given index, or\n * `undefined` when no readiness specs are configured (no gate to report).\n */\nexport function readinessFor(\n options: ReadinessGateOptions,\n index: KnowledgeIndex,\n): EvalKnowledgeBundleBuildResult | undefined {\n if (!options.readinessSpecs?.length) return undefined\n return buildEvalKnowledgeBundle({\n ...(options.readiness ?? {}),\n taskId: options.readinessTaskId ?? options.goal,\n index,\n specs: options.readinessSpecs,\n })\n}\n","import {\n blockingKnowledgeEval,\n type ControlEvalResult,\n type ControlRuntimeConfig,\n canonicalJson,\n objectiveEval,\n} from '@tangle-network/agent-eval'\nimport type {\n BuildEvalKnowledgeBundleOptions,\n EvalKnowledgeBundleBuildResult,\n KnowledgeReadinessSpec,\n} from './eval-readiness'\nimport { createKnowledgeEvent } from './events'\nimport { buildKnowledgeIndex } from './indexer'\nimport { lintKnowledgeIndex } from './lint'\nimport { type ApplyWriteBlocksResult, applyKnowledgeWriteBlocks } from './proposals'\nimport { readinessFor } from './readiness-helpers'\nimport {\n type AddSourceOptions,\n type AddSourceTextInput,\n addSourcePath,\n addSourceText,\n} from './sources'\nimport { initKnowledgeBase } from './store'\nimport type { KnowledgeEvent, KnowledgeIndex, KnowledgeLintFinding, SourceRecord } from './types'\nimport {\n type ValidateKnowledgeOptions,\n type ValidateKnowledgeResult,\n validateKnowledgeIndex,\n} from './validate'\n\nexport interface KnowledgeResearchLoopContext {\n root: string\n goal: string\n iteration: number\n index: KnowledgeIndex\n lintFindings: KnowledgeLintFinding[]\n validation: ValidateKnowledgeResult\n readiness?: EvalKnowledgeBundleBuildResult\n previousSteps: KnowledgeResearchLoopStep[]\n signal?: AbortSignal\n}\n\nexport interface KnowledgeResearchLoopDecision {\n /**\n * Free-form notes from the researcher. Keep this human-readable; products can\n * store it as the research transcript.\n */\n notes?: string\n /**\n * Local files to register as immutable sources before applying proposals.\n */\n sourcePaths?: string[]\n /**\n * Textual source artifacts discovered by an agent, browser worker, connector,\n * or deep-research process.\n */\n sourceTexts?: AddSourceTextInput[]\n /**\n * Safe write protocol text. The loop parses and applies only accepted\n * `---FILE: knowledge/...---` blocks.\n */\n proposalText?: string\n /**\n * The researcher decides when the wiki is good enough. The loop deliberately\n * does not encode a domain-specific definition of \"done\".\n */\n done?: boolean\n metadata?: Record<string, unknown>\n}\n\nexport interface KnowledgeResearchLoopStep {\n iteration: number\n notes?: string\n addedSources: SourceRecord[]\n applied?: ApplyWriteBlocksResult\n lintFindings: KnowledgeLintFinding[]\n validation: ValidateKnowledgeResult\n readiness?: EvalKnowledgeBundleBuildResult\n event: KnowledgeEvent\n done: boolean\n metadata?: Record<string, unknown>\n}\n\nexport interface RunKnowledgeResearchLoopOptions {\n pagesDirectory?: string\n root: string\n goal: string\n maxIterations?: number\n actor?: string\n strict?: ValidateKnowledgeOptions['strict']\n readinessSpecs?: KnowledgeReadinessSpec[]\n readinessTaskId?: string\n readiness?: Omit<BuildEvalKnowledgeBundleOptions, 'taskId' | 'index' | 'specs'>\n sourceOptions?: Pick<AddSourceOptions, 'adapters' | 'now'>\n signal?: AbortSignal\n step(\n context: KnowledgeResearchLoopContext,\n ): Promise<KnowledgeResearchLoopDecision> | KnowledgeResearchLoopDecision\n onStep?: (step: KnowledgeResearchLoopStep) => Promise<void> | void\n}\n\nexport interface KnowledgeResearchLoopResult {\n root: string\n goal: string\n iterations: number\n done: boolean\n index: KnowledgeIndex\n lintFindings: KnowledgeLintFinding[]\n validation: ValidateKnowledgeResult\n readiness?: EvalKnowledgeBundleBuildResult\n steps: KnowledgeResearchLoopStep[]\n}\n\nexport type KnowledgeControlLoopState = KnowledgeResearchLoopContext\nexport type KnowledgeControlLoopAction = KnowledgeResearchLoopDecision\nexport type KnowledgeControlLoopActionResult = KnowledgeResearchLoopStep\n\nexport interface KnowledgeControlLoopAdapterOptions {\n pagesDirectory?: string\n root: string\n goal: string\n actor?: string\n strict?: ValidateKnowledgeOptions['strict']\n readinessSpecs?: KnowledgeReadinessSpec[]\n readinessTaskId?: string\n readiness?: Omit<BuildEvalKnowledgeBundleOptions, 'taskId' | 'index' | 'specs'>\n sourceOptions?: Pick<AddSourceOptions, 'adapters' | 'now'>\n}\n\nexport type KnowledgeControlLoopAdapter = Pick<\n ControlRuntimeConfig<\n KnowledgeControlLoopState,\n KnowledgeControlLoopAction,\n KnowledgeControlLoopActionResult,\n ControlEvalResult\n >,\n 'intent' | 'observe' | 'validate' | 'act' | 'shouldStop' | 'stopPolicies'\n>\n\n/**\n * Adapter for running knowledge growth through `agent-eval`'s generic control\n * runtime. The caller still owns `decide`: that can be a proposer agent,\n * reviewer agent, deterministic policy, or a composition of all three.\n */\nexport function createKnowledgeControlLoopAdapter(\n options: KnowledgeControlLoopAdapterOptions,\n): KnowledgeControlLoopAdapter {\n let initialized = false\n const appliedSteps: KnowledgeResearchLoopStep[] = []\n\n return {\n intent: options.goal,\n async observe({ history, abortSignal }) {\n if (abortSignal.aborted) throw new Error('Knowledge control loop aborted')\n if (!initialized) {\n await initKnowledgeBase(options.root)\n initialized = true\n }\n const index = await buildKnowledgeIndex(options.root, options)\n const validation = validateKnowledgeIndex(index, { strict: options.strict })\n const lintFindings = lintKnowledgeIndex(index)\n const readiness = readinessFor(options, index)\n return {\n root: options.root,\n goal: options.goal,\n iteration: history.length + 1,\n index,\n lintFindings,\n validation,\n readiness,\n previousSteps: [...appliedSteps],\n signal: abortSignal,\n }\n },\n validate({ state }) {\n const errorFindings = state.validation.findings.filter(\n (finding) => finding.severity === 'error',\n )\n const evals: ControlEvalResult[] = [\n objectiveEval({\n id: 'knowledge-valid',\n passed: state.validation.ok,\n severity: 'critical',\n detail: state.validation.ok\n ? 'Knowledge index is valid.'\n : 'Knowledge index has validation errors.',\n metadata: { findings: state.validation.findings },\n }),\n objectiveEval({\n id: 'knowledge-lint-errors',\n passed: errorFindings.length === 0,\n severity: 'error',\n detail:\n errorFindings.length === 0\n ? 'No lint errors.'\n : `${errorFindings.length} lint error(s).`,\n metadata: { findings: errorFindings },\n }),\n ]\n if (state.readiness) evals.push(blockingKnowledgeEval(state.readiness.report))\n return evals\n },\n shouldStop() {\n return { stop: false, pass: false, reason: 'knowledge driver owns stop decisions' }\n },\n stopPolicies: {\n // `observe` hands the caller's AbortSignal to `act` through the state, and a\n // signal has no canonical JSON form. The loop's default fingerprint would\n // refuse the whole state, so fingerprint the observable knowledge and leave\n // the signal out — it carries no observable progress.\n stateFingerprint: ({ signal: _signal, ...observable }) => canonicalJson(observable),\n },\n async act(action, ctx) {\n const step = await applyKnowledgeResearchDecision(options, action, ctx.state.iteration)\n appliedSteps.push(step)\n return step\n },\n }\n}\n\nexport async function runKnowledgeResearchLoop(\n options: RunKnowledgeResearchLoopOptions,\n): Promise<KnowledgeResearchLoopResult> {\n const maxIterations = Math.max(1, options.maxIterations ?? 3)\n await initKnowledgeBase(options.root)\n const steps: KnowledgeResearchLoopStep[] = []\n let index = await buildKnowledgeIndex(options.root, options)\n let validation = validateKnowledgeIndex(index, { strict: options.strict })\n let lintFindings = lintKnowledgeIndex(index)\n let readiness = readinessFor(options, index)\n let done = false\n\n for (let iteration = 1; iteration <= maxIterations; iteration++) {\n if (options.signal?.aborted) throw new Error('Knowledge research loop aborted')\n const decision = await options.step({\n root: options.root,\n goal: options.goal,\n iteration,\n index,\n lintFindings,\n validation,\n readiness,\n previousSteps: steps,\n signal: options.signal,\n })\n\n done = Boolean(decision.done)\n const step = await applyKnowledgeResearchDecision(options, decision, iteration)\n index = await buildKnowledgeIndex(options.root, options)\n validation = step.validation\n lintFindings = step.lintFindings\n readiness = step.readiness\n steps.push(step)\n await options.onStep?.(step)\n\n if (done) break\n if (!step.applied && step.addedSources.length === 0) break\n }\n\n return {\n root: options.root,\n goal: options.goal,\n iterations: steps.length,\n done,\n index,\n lintFindings,\n validation,\n readiness,\n steps,\n }\n}\n\nasync function applyKnowledgeResearchDecision(\n options: KnowledgeControlLoopAdapterOptions,\n decision: KnowledgeResearchLoopDecision,\n iteration = 1,\n): Promise<KnowledgeResearchLoopStep> {\n const addedSources: SourceRecord[] = []\n for (const sourcePath of decision.sourcePaths ?? []) {\n addedSources.push(...(await addSourcePath(options.root, sourcePath, options.sourceOptions)))\n }\n for (const sourceText of decision.sourceTexts ?? []) {\n addedSources.push(await addSourceText(options.root, sourceText, options.sourceOptions))\n }\n\n const applied = decision.proposalText\n ? await applyKnowledgeWriteBlocks(options.root, decision.proposalText, {\n pagesDirectory: options.pagesDirectory,\n })\n : undefined\n\n const index = await buildKnowledgeIndex(options.root, options)\n const validation = validateKnowledgeIndex(index, { strict: options.strict })\n const lintFindings = lintKnowledgeIndex(index)\n const readiness = readinessFor(options, index)\n const done = Boolean(decision.done)\n const event = createKnowledgeEvent({\n type: 'research.iteration',\n actor: options.actor,\n target: options.root,\n metadata: {\n goal: options.goal,\n iteration,\n done,\n addedSourceCount: addedSources.length,\n ...(applied === undefined ? {} : { written: applied.written }),\n warningCount: applied?.warnings.length ?? 0,\n errorCount: validation.findings.filter((finding) => finding.severity === 'error').length,\n },\n })\n\n // Every optional below is omitted when it has no value rather than set to\n // `undefined`. A step joins the control-loop state, which is fingerprinted with\n // canonical JSON, and that encoder refuses a key present with no value.\n return {\n iteration,\n ...(decision.notes === undefined ? {} : { notes: decision.notes }),\n addedSources,\n ...(applied === undefined ? {} : { applied }),\n lintFindings,\n validation,\n ...(readiness === undefined ? {} : { readiness }),\n event,\n done,\n ...(decision.metadata === undefined ? {} : { metadata: decision.metadata }),\n }\n}\n","import { canonicalJson } from '@tangle-network/agent-eval'\nimport {\n type JudgeConfig,\n type OptimizationMethod,\n surfaceHash,\n} from '@tangle-network/agent-eval/campaign'\nimport type { AgentCandidateJsonValue as JsonValue } from '@tangle-network/agent-interface'\nimport {\n jsonObjectCandidateCodec,\n type RunSerializedKnowledgeOptimizationOptions,\n type RunSerializedKnowledgeOptimizationResult,\n runSerializedKnowledgeOptimization,\n} from './optimization'\nimport {\n buildRetrievalEvalDispatch,\n type RetrievalConfig,\n type RetrievalEvalArtifact,\n type RetrievalEvalRetriever,\n type RetrievalEvalScenario,\n type RetrievalMetricWeights,\n retrievalRecallJudge,\n} from './retrieval-eval'\nimport type { KnowledgeIndex } from './types'\n\ntype RetrievalOptimizationBaseOptions = Omit<\n RunSerializedKnowledgeOptimizationOptions<\n RetrievalConfig,\n RetrievalEvalScenario,\n RetrievalEvalArtifact\n >,\n | 'baseline'\n | 'method'\n | 'trainScenarios'\n | 'selectionScenarios'\n | 'finalScenarios'\n | 'dispatchCandidate'\n | 'judges'\n | 'codec'\n | 'scenarioFingerprint'\n>\n\nexport interface RunRetrievalImprovementLoopOptions extends RetrievalOptimizationBaseOptions {\n baseline: RetrievalConfig\n trainScenarios: readonly RetrievalEvalScenario[]\n selectionScenarios: readonly RetrievalEvalScenario[]\n finalScenarios: readonly RetrievalEvalScenario[]\n method: OptimizationMethod<RetrievalEvalScenario, RetrievalEvalArtifact>\n index?: KnowledgeIndex\n defaultK?: number\n retrieve?: RetrievalEvalRetriever\n judges?: readonly JudgeConfig<RetrievalEvalArtifact, RetrievalEvalScenario>[]\n metricWeights?: RetrievalMetricWeights\n}\n\nexport interface RunRetrievalImprovementLoopResult\n extends RunSerializedKnowledgeOptimizationResult<RetrievalConfig> {\n baselineConfig: RetrievalConfig\n winnerConfig: RetrievalConfig\n trainScenarios: readonly RetrievalEvalScenario[]\n selectionScenarios: readonly RetrievalEvalScenario[]\n finalScenarios: readonly RetrievalEvalScenario[]\n}\n\nexport async function runRetrievalImprovementLoop(\n options: RunRetrievalImprovementLoopOptions,\n): Promise<RunRetrievalImprovementLoopResult> {\n const dispatch = buildRetrievalEvalDispatch({\n index: options.index,\n defaultK: options.defaultK,\n retrieve: options.retrieve,\n })\n const {\n baseline,\n trainScenarios,\n selectionScenarios,\n finalScenarios,\n method,\n index: _index,\n defaultK: _defaultK,\n retrieve: _retrieve,\n judges,\n metricWeights,\n ...runOptions\n } = options\n const result = await runSerializedKnowledgeOptimization({\n ...runOptions,\n baseline,\n method,\n trainScenarios,\n selectionScenarios,\n finalScenarios,\n codec: jsonObjectCandidateCodec<RetrievalConfig>(),\n judges: [...(judges ?? [retrievalRecallJudge({ weights: metricWeights })])],\n scenarioFingerprint: retrievalScenarioFingerprint,\n dispatchCandidate: ({ candidateSurface, scenario, context }) =>\n dispatch(candidateSurface, scenario, context),\n })\n return {\n ...result,\n baselineConfig: result.baseline.value,\n winnerConfig: result.winner.value,\n trainScenarios: [...trainScenarios],\n selectionScenarios: [...selectionScenarios],\n finalScenarios: [...finalScenarios],\n }\n}\n\nfunction retrievalScenarioFingerprint(scenario: RetrievalEvalScenario): string {\n return surfaceHash(\n canonicalJson({\n query: scenario.query,\n expected: scenario.expected,\n k: scenario.k ?? null,\n } as JsonValue),\n )\n}\n","import { assertRagAnswerEvidence, ragAnswerEvidenceRejectionReasons } from './rag-answer-evidence'\nimport type {\n RagAnswerQualityResult,\n RagKnowledgeImprovementPhase,\n RagKnowledgeImprovementPhaseResult,\n RagKnowledgeUpdateResult,\n RagOptimizationSelection,\n RagPromotionResult,\n RetrievalOptimizationSelection,\n RunRagKnowledgeImprovementLoopOptions,\n RunRagKnowledgeImprovementLoopResult,\n} from './rag-improvement-loop'\nimport { type RunRagOptimizationResult, runRagOptimization } from './rag-optimization'\nimport {\n type KnowledgeResearchLoopDecision,\n type RunKnowledgeResearchLoopOptions,\n runKnowledgeResearchLoop,\n} from './research-loop'\nimport {\n type RunRetrievalImprovementLoopResult,\n runRetrievalImprovementLoop,\n} from './retrieval-optimization'\n\ntype MaybePromise<T> = T | Promise<T>\n\nexport async function runRagKnowledgeImprovementPhases(\n options: RunRagKnowledgeImprovementLoopOptions,\n previous?: RunRagKnowledgeImprovementLoopResult,\n): Promise<RunRagKnowledgeImprovementLoopResult> {\n assertConfiguredRequiredPhases(options)\n assertOptionalCostCeiling(options.answerQualityCostCeiling, 'answerQualityCostCeiling')\n const now = options.now ?? (() => new Date())\n const phases: RagKnowledgeImprovementPhaseResult[] = [...(previous?.phases ?? [])]\n let optimization = previous?.optimization\n let retrieval = previous?.retrieval\n let findings = [...(previous?.findings ?? [])]\n let acquisition = previous?.acquisition\n let knowledgeUpdate = previous?.knowledgeUpdate\n let answerQuality = previous?.answerQuality\n let promotion = previous?.promotion\n\n if (phaseEnabled(options, 'gap-diagnosis')) {\n if (options.diagnose) {\n findings = [\n ...(await runPhase(\n phases,\n now,\n 'gap-diagnosis',\n async () => {\n assertNotAborted(options.signal)\n return options.diagnose!({\n goal: options.goal,\n phases,\n optimization: selectRagOptimization(optimization),\n signal: options.signal,\n retrieval: selectRetrievalOptimization(retrieval),\n })\n },\n (diagnosed) => `${diagnosed.length} finding(s)`,\n )),\n ]\n } else {\n skipPhase(phases, now, 'gap-diagnosis', 'no diagnosis hook provided')\n }\n }\n\n if (phaseEnabled(options, 'knowledge-acquisition')) {\n if (options.acquireKnowledge) {\n acquisition = await runPhase(\n phases,\n now,\n 'knowledge-acquisition',\n async () => {\n assertNotAborted(options.signal)\n return options.acquireKnowledge!({\n goal: options.goal,\n phases,\n optimization: selectRagOptimization(optimization),\n signal: options.signal,\n retrieval: selectRetrievalOptimization(retrieval),\n findings,\n })\n },\n summarizeAcquisitionDecision,\n )\n } else {\n skipPhase(phases, now, 'knowledge-acquisition', 'no acquisition hook provided')\n }\n }\n\n if (phaseEnabled(options, 'knowledge-update')) {\n if (options.updateKnowledge) {\n knowledgeUpdate = await runPhase(\n phases,\n now,\n 'knowledge-update',\n async () => {\n assertNotAborted(options.signal)\n return options.updateKnowledge!({\n goal: options.goal,\n phases,\n optimization: selectRagOptimization(optimization),\n signal: options.signal,\n retrieval: selectRetrievalOptimization(retrieval),\n findings,\n acquisition,\n })\n },\n (result) => result.summary,\n )\n } else if (options.knowledgeResearch) {\n knowledgeUpdate = await runPhase(\n phases,\n now,\n 'knowledge-update',\n async () => {\n assertNotAborted(options.signal)\n return runKnowledgeResearchUpdate(options, acquisition)\n },\n (result) => result.summary,\n )\n } else {\n skipPhase(phases, now, 'knowledge-update', 'no update hook or research loop provided')\n }\n }\n\n if (\n phaseEnabled(options, 'rag-optimization') &&\n (options.optimization ||\n options.enabledPhases?.includes('rag-optimization') ||\n options.requiredPhases?.includes('rag-optimization'))\n ) {\n if (options.optimization) {\n optimization = await runPhase(\n phases,\n now,\n 'rag-optimization',\n async () => {\n assertNotAborted(options.signal)\n return runRagOptimization(options.optimization!)\n },\n summarizeRagOptimization,\n )\n } else {\n skipPhase(phases, now, 'rag-optimization', 'no full RAG optimization options provided')\n }\n }\n\n if (phaseEnabled(options, 'retrieval-tuning')) {\n if (options.retrieval) {\n retrieval = await runPhase(\n phases,\n now,\n 'retrieval-tuning',\n async () => {\n assertNotAborted(options.signal)\n return runRetrievalImprovementLoop(options.retrieval!)\n },\n summarizeRetrievalResult,\n )\n } else {\n skipPhase(phases, now, 'retrieval-tuning', 'no retrieval options provided')\n }\n }\n\n if (phaseEnabled(options, 'answer-quality')) {\n if (options.evaluateAnswers) {\n answerQuality = await runPhase(\n phases,\n now,\n 'answer-quality',\n async () => {\n assertNotAborted(options.signal)\n const result = await options.evaluateAnswers!({\n goal: options.goal,\n phases,\n optimization: selectRagOptimization(optimization),\n signal: options.signal,\n retrieval: selectRetrievalOptimization(retrieval),\n findings,\n acquisition,\n knowledgeUpdate,\n })\n assertRagAnswerEvidence(result)\n return result\n },\n summarizeAnswerQuality,\n )\n findings = [...findings, ...(answerQuality.findings ?? [])]\n } else {\n skipPhase(phases, now, 'answer-quality', 'no answer-quality hook provided')\n }\n }\n\n if (phaseEnabled(options, 'promotion')) {\n if (options.decidePromotion) {\n promotion = await runPhase(\n phases,\n now,\n 'promotion',\n async () => {\n assertNotAborted(options.signal)\n const evidenceRejection = rejectUnsafePromotionEvidence({\n optimization: optimization?.comparison,\n optimizationCostCeiling: options.optimization?.costCeiling,\n retrieval: retrieval?.comparison,\n retrievalCostCeiling: options.retrieval?.costCeiling,\n answerQuality,\n answerQualityCostCeiling: options.answerQualityCostCeiling,\n })\n if (evidenceRejection) return evidenceRejection\n return options.decidePromotion!({\n goal: options.goal,\n phases,\n optimization: selectRagOptimization(optimization),\n optimizationComparison: optimization?.comparison,\n signal: options.signal,\n retrieval: selectRetrievalOptimization(retrieval),\n retrievalComparison: retrieval?.comparison,\n findings,\n acquisition,\n knowledgeUpdate,\n answerQuality,\n })\n },\n (result) => `${result.promoted ? 'promoted' : 'held'}: ${result.reason}`,\n )\n } else {\n skipPhase(phases, now, 'promotion', 'no promotion decision hook provided')\n }\n }\n\n return {\n goal: options.goal,\n phases,\n optimization,\n retrieval,\n findings,\n acquisition,\n knowledgeUpdate,\n answerQuality,\n promotion,\n }\n}\n\nfunction rejectUnsafePromotionEvidence(evidence: {\n optimization?: RunRagOptimizationResult['comparison']\n optimizationCostCeiling?: number\n retrieval?: RunRetrievalImprovementLoopResult['comparison']\n retrievalCostCeiling?: number\n answerQuality?: RagAnswerQualityResult\n answerQualityCostCeiling?: number\n}): RagPromotionResult | undefined {\n const reasons: string[] = []\n if (!evidence.optimization && !evidence.retrieval && !evidence.answerQuality) {\n reasons.push('promotion requires final RAG, retrieval, or answer-quality evidence')\n }\n for (const [label, comparison, costCeiling] of [\n ['RAG', evidence.optimization, evidence.optimizationCostCeiling],\n ['retrieval', evidence.retrieval, evidence.retrievalCostCeiling],\n ] as const) {\n if (!comparison) continue\n if (!comparison.totalCost.accountingComplete) {\n reasons.push(`${label} final comparison has incomplete cost accounting`)\n }\n const optimizerSource = comparison.best.provenance?.source\n if (optimizerSource && optimizerSource.evidence !== 'observed') {\n reasons.push(`${label} optimizer package identity was not observed`)\n }\n if (!comparison.best.decision.promote) {\n reasons.push(\n comparison.best.decision.low < 0\n ? `${label} final comparison does not rule out a regression`\n : `${label} final comparison does not establish the required improvement`,\n )\n }\n if (\n costCeiling !== undefined &&\n exceedsCostCeiling(comparison.totalCost.totalCostUsd, costCeiling)\n ) {\n reasons.push(\n `${label} final comparison cost ${comparison.totalCost.totalCostUsd} exceeds ${costCeiling}`,\n )\n }\n }\n if (evidence.answerQuality) {\n reasons.push(\n ...ragAnswerEvidenceRejectionReasons(\n evidence.answerQuality,\n evidence.answerQualityCostCeiling,\n ),\n )\n }\n if (reasons.length === 0) return undefined\n return {\n promoted: false,\n reason: reasons.join('; '),\n }\n}\n\nfunction assertOptionalCostCeiling(value: number | undefined, label: string): void {\n if (value !== undefined && (!Number.isFinite(value) || value < 0)) {\n throw new Error(`${label} must be a non-negative finite number`)\n }\n}\n\nfunction exceedsCostCeiling(totalCostUsd: number, costCeiling: number): boolean {\n const tolerance = Number.EPSILON * Math.max(1, Math.abs(totalCostUsd), Math.abs(costCeiling)) * 8\n return totalCostUsd - costCeiling > tolerance\n}\n\nfunction summarizeRagOptimization(result: RunRagOptimizationResult): string {\n return `${result.methodName}; winner=${result.winner.surfaceHash}`\n}\n\nasync function runKnowledgeResearchUpdate(\n options: RunRagKnowledgeImprovementLoopOptions,\n acquisition: KnowledgeResearchLoopDecision | undefined,\n): Promise<RagKnowledgeUpdateResult> {\n const research = options.knowledgeResearch\n if (!research) {\n throw new Error('knowledgeResearch options are required to run the knowledge update phase')\n }\n const { goal, step, ...rest } = research\n const researchStep = step ?? acquisitionBackedResearchStep(acquisition)\n const maxIterations = step ? rest.maxIterations : 1\n const result = await runKnowledgeResearchLoop({\n ...rest,\n goal: goal ?? options.goal,\n maxIterations,\n signal: options.signal,\n step: researchStep,\n })\n return {\n applied: result.steps.some((stepResult) => {\n return stepResult.addedSources.length > 0 || Boolean(stepResult.applied)\n }),\n summary: `${result.iterations} research iteration(s); done=${String(result.done)}`,\n research: result,\n }\n}\n\nfunction acquisitionBackedResearchStep(\n acquisition: KnowledgeResearchLoopDecision | undefined,\n): RunKnowledgeResearchLoopOptions['step'] {\n if (!acquisition) {\n throw new Error(\n 'knowledgeResearch requires either a step hook or a knowledge-acquisition result to apply',\n )\n }\n return () => ({ ...acquisition, done: acquisition.done ?? true })\n}\n\nasync function runPhase<T>(\n phases: RagKnowledgeImprovementPhaseResult[],\n now: () => Date,\n phase: RagKnowledgeImprovementPhase,\n action: () => MaybePromise<T>,\n summarize: (result: T) => string,\n): Promise<T> {\n const startedAt = now().toISOString()\n try {\n const result = await action()\n phases.push({\n phase,\n status: 'completed',\n summary: summarize(result),\n startedAt,\n finishedAt: now().toISOString(),\n })\n return result\n } catch (error) {\n phases.push({\n phase,\n status: 'failed',\n summary: (error as Error).message,\n startedAt,\n finishedAt: now().toISOString(),\n })\n throw error\n }\n}\n\nfunction skipPhase(\n phases: RagKnowledgeImprovementPhaseResult[],\n now: () => Date,\n phase: RagKnowledgeImprovementPhase,\n summary: string,\n): void {\n const timestamp = now().toISOString()\n phases.push({ phase, status: 'skipped', summary, startedAt: timestamp, finishedAt: timestamp })\n}\n\nfunction summarizeRetrievalResult(result: RunRetrievalImprovementLoopResult): string {\n return `${result.methodName}; winner=${result.winner.surfaceHash}`\n}\n\nfunction selectRagOptimization(\n result: RunRagOptimizationResult | undefined,\n): RagOptimizationSelection | undefined {\n if (!result) return undefined\n return {\n methodName: result.methodName,\n baseline: structuredClone(result.baseline),\n winner: structuredClone(result.winner),\n baselineConfig: structuredClone(result.baselineConfig),\n winnerConfig: structuredClone(result.winnerConfig),\n }\n}\n\nfunction selectRetrievalOptimization(\n result: RunRetrievalImprovementLoopResult | undefined,\n): RetrievalOptimizationSelection | undefined {\n if (!result) return undefined\n return {\n methodName: result.methodName,\n baseline: structuredClone(result.baseline),\n winner: structuredClone(result.winner),\n baselineConfig: structuredClone(result.baselineConfig),\n winnerConfig: structuredClone(result.winnerConfig),\n }\n}\n\nfunction summarizeAcquisitionDecision(decision: KnowledgeResearchLoopDecision): string {\n const sourcePathCount = decision.sourcePaths?.length ?? 0\n const sourceTextCount = decision.sourceTexts?.length ?? 0\n const proposal = decision.proposalText ? 'proposal' : 'no proposal'\n return `${sourcePathCount} path source(s), ${sourceTextCount} text source(s), ${proposal}`\n}\n\nfunction summarizeAnswerQuality(result: RagAnswerQualityResult): string {\n const metrics = Object.entries(result.metrics)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([key, value]) => `${key}=${formatMetric(value)}`)\n .join(', ')\n return `${result.passed ? 'passed' : 'failed'}${metrics ? `; ${metrics}` : ''}`\n}\n\nfunction formatMetric(value: number): string {\n return Number.isFinite(value) ? value.toFixed(3) : String(value)\n}\n\nfunction phaseEnabled(\n options: RunRagKnowledgeImprovementLoopOptions,\n phase: RagKnowledgeImprovementPhase,\n): boolean {\n return !options.enabledPhases || options.enabledPhases.includes(phase)\n}\n\nfunction assertConfiguredRequiredPhases(options: RunRagKnowledgeImprovementLoopOptions): void {\n for (const phase of options.requiredPhases ?? []) {\n if (!phaseEnabled(options, phase)) {\n throw new Error(`required phase ${phase} is not enabled`)\n }\n if (!phaseConfigured(options, phase)) {\n throw new Error(requiredPhaseMessage(phase))\n }\n }\n}\n\nfunction phaseConfigured(\n options: RunRagKnowledgeImprovementLoopOptions,\n phase: RagKnowledgeImprovementPhase,\n): boolean {\n switch (phase) {\n case 'rag-optimization':\n return Boolean(options.optimization)\n case 'retrieval-tuning':\n return Boolean(options.retrieval)\n case 'gap-diagnosis':\n return Boolean(options.diagnose)\n case 'knowledge-acquisition':\n return Boolean(options.acquireKnowledge)\n case 'knowledge-update':\n return Boolean(options.updateKnowledge ?? options.knowledgeResearch)\n case 'answer-quality':\n return Boolean(options.evaluateAnswers)\n case 'promotion':\n return Boolean(options.decidePromotion)\n }\n}\n\nfunction requiredPhaseMessage(phase: RagKnowledgeImprovementPhase): string {\n switch (phase) {\n case 'rag-optimization':\n return 'required phase rag-optimization requires optimization options'\n case 'retrieval-tuning':\n return 'required phase retrieval-tuning requires retrieval options'\n case 'gap-diagnosis':\n return 'required phase gap-diagnosis requires a diagnose hook'\n case 'knowledge-acquisition':\n return 'required phase knowledge-acquisition requires an acquireKnowledge hook'\n case 'knowledge-update':\n return 'required phase knowledge-update requires updateKnowledge or knowledgeResearch'\n case 'answer-quality':\n return 'required phase answer-quality requires an evaluateAnswers hook'\n case 'promotion':\n return 'required phase promotion requires a decidePromotion hook'\n }\n}\n\nfunction assertNotAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted) {\n throw new Error('RAG knowledge improvement loop aborted')\n }\n}\n","import type { ComparisonCost } from '@tangle-network/agent-eval/campaign'\nimport type { AgentCandidateJsonValue as JsonValue } from '@tangle-network/agent-interface'\nimport { runRagKnowledgeImprovementPhases } from './rag-improvement-phases'\nimport type { RunRagOptimizationOptions, RunRagOptimizationResult } from './rag-optimization'\nimport type {\n KnowledgeResearchLoopDecision,\n KnowledgeResearchLoopResult,\n RunKnowledgeResearchLoopOptions,\n} from './research-loop'\nimport type {\n RunRetrievalImprovementLoopOptions,\n RunRetrievalImprovementLoopResult,\n} from './retrieval-optimization'\n\nexport type RagKnowledgeImprovementPhase =\n | 'rag-optimization'\n | 'retrieval-tuning'\n | 'gap-diagnosis'\n | 'knowledge-acquisition'\n | 'knowledge-update'\n | 'answer-quality'\n | 'promotion'\n\nexport type RagKnowledgeImprovementPhaseStatus = 'completed' | 'skipped' | 'failed'\n\nexport type RagGapKind =\n | 'missing-source'\n | 'stale-source'\n | 'retrieval-miss'\n | 'retrieval-noise'\n | 'chunking-mismatch'\n | 'missing-multihop-evidence'\n | 'generator-unsupported-claim'\n | 'citation-mismatch'\n | 'incorrect-abstention'\n | 'unknown'\n\nexport type RagGapSeverity = 'info' | 'warning' | 'error' | 'critical'\n\nexport interface RagGapFinding {\n id: string\n kind: RagGapKind\n severity: RagGapSeverity\n message: string\n scenarioId?: string\n evidence?: Record<string, JsonValue>\n}\n\nexport interface RagKnowledgeImprovementPhaseResult {\n phase: RagKnowledgeImprovementPhase\n status: RagKnowledgeImprovementPhaseStatus\n summary: string\n startedAt: string\n finishedAt: string\n metadata?: Record<string, JsonValue>\n}\n\nexport type RagOptimizationSelection = Pick<\n RunRagOptimizationResult,\n 'methodName' | 'baseline' | 'winner' | 'baselineConfig' | 'winnerConfig'\n>\n\nexport type RetrievalOptimizationSelection = Pick<\n RunRetrievalImprovementLoopResult,\n 'methodName' | 'baseline' | 'winner' | 'baselineConfig' | 'winnerConfig'\n>\n\nexport interface RagPhaseInputBase {\n goal: string\n phases: readonly RagKnowledgeImprovementPhaseResult[]\n /** Selected candidate only. Adaptive update callbacks run before final scoring starts. */\n optimization?: RagOptimizationSelection\n signal?: AbortSignal\n}\n\nexport interface RagDiagnosisInput extends RagPhaseInputBase {\n retrieval?: RetrievalOptimizationSelection\n}\n\nexport interface RagKnowledgeAcquisitionInput extends RagPhaseInputBase {\n retrieval?: RetrievalOptimizationSelection\n findings: readonly RagGapFinding[]\n}\n\nexport interface RagKnowledgeUpdateInput extends RagPhaseInputBase {\n retrieval?: RetrievalOptimizationSelection\n findings: readonly RagGapFinding[]\n acquisition?: KnowledgeResearchLoopDecision\n}\n\nexport interface RagKnowledgeUpdateResult {\n applied: boolean\n summary: string\n research?: KnowledgeResearchLoopResult\n metadata?: Record<string, JsonValue>\n}\n\nexport interface RagAnswerQualityInput extends RagPhaseInputBase {\n retrieval?: RetrievalOptimizationSelection\n findings: readonly RagGapFinding[]\n acquisition?: KnowledgeResearchLoopDecision\n knowledgeUpdate?: RagKnowledgeUpdateResult\n}\n\nexport interface RagAnswerQualityResult {\n passed: boolean\n metrics: Record<string, number>\n finalScenarioIds: readonly string[]\n datasetRef: string\n evaluatorRef: string\n cost: ComparisonCost\n findings?: readonly RagGapFinding[]\n metadata?: Record<string, JsonValue>\n}\n\nexport interface RagPromotionInput extends RagPhaseInputBase {\n retrieval?: RetrievalOptimizationSelection\n /** Full final-case result available only to the terminal promotion decision. */\n optimizationComparison?: RunRagOptimizationResult['comparison']\n /** Full final-case result available only to the terminal promotion decision. */\n retrievalComparison?: RunRetrievalImprovementLoopResult['comparison']\n findings: readonly RagGapFinding[]\n acquisition?: KnowledgeResearchLoopDecision\n knowledgeUpdate?: RagKnowledgeUpdateResult\n answerQuality?: RagAnswerQualityResult\n}\n\nexport interface RagPromotionResult {\n promoted: boolean\n reason: string\n metadata?: Record<string, JsonValue>\n}\n\nexport interface RagKnowledgeResearchOptions\n extends Omit<RunKnowledgeResearchLoopOptions, 'goal' | 'signal' | 'step'> {\n goal?: string\n step?: RunKnowledgeResearchLoopOptions['step']\n}\n\nexport interface RunRagKnowledgeImprovementLoopOptions {\n goal: string\n optimization?: RunRagOptimizationOptions\n retrieval?: RunRetrievalImprovementLoopOptions\n diagnose?: (input: RagDiagnosisInput) => MaybePromise<readonly RagGapFinding[]>\n acquireKnowledge?: (\n input: RagKnowledgeAcquisitionInput,\n ) => MaybePromise<KnowledgeResearchLoopDecision>\n knowledgeResearch?: RagKnowledgeResearchOptions\n updateKnowledge?: (input: RagKnowledgeUpdateInput) => MaybePromise<RagKnowledgeUpdateResult>\n evaluateAnswers?: (input: RagAnswerQualityInput) => MaybePromise<RagAnswerQualityResult>\n /** Maximum total answer-evaluation spend accepted for promotion. */\n answerQualityCostCeiling?: number\n /**\n * Makes a side-effect-free promotion decision after the library has rejected\n * missing, inconclusive, regressing, unaccounted, or over-budget final evidence.\n */\n decidePromotion?: (input: RagPromotionInput) => MaybePromise<RagPromotionResult>\n enabledPhases?: readonly RagKnowledgeImprovementPhase[]\n requiredPhases?: readonly RagKnowledgeImprovementPhase[]\n signal?: AbortSignal\n now?: () => Date\n}\n\nexport interface RunRagKnowledgeImprovementLoopResult {\n goal: string\n phases: readonly RagKnowledgeImprovementPhaseResult[]\n optimization?: RunRagOptimizationResult\n retrieval?: RunRetrievalImprovementLoopResult\n findings: readonly RagGapFinding[]\n acquisition?: KnowledgeResearchLoopDecision\n knowledgeUpdate?: RagKnowledgeUpdateResult\n answerQuality?: RagAnswerQualityResult\n promotion?: RagPromotionResult\n}\n\ntype MaybePromise<T> = T | Promise<T>\n\nexport async function runRagKnowledgeImprovementLoop(\n options: RunRagKnowledgeImprovementLoopOptions,\n): Promise<RunRagKnowledgeImprovementLoopResult> {\n return runRagKnowledgeImprovementPhases(options)\n}\n","import { createHash } from 'node:crypto'\nimport { cp, lstat, mkdir, mkdtemp, rm } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { dirname, join } from 'node:path'\nimport { canonicalJson, contentHash } from '@tangle-network/agent-eval'\nimport {\n canonicalPathsEqual,\n isMissingFile,\n listRegularFilesWithinRoot,\n readRegularFileWithinRoot,\n renameDurable,\n withSafeDirectory,\n} from '../durable-fs'\nimport { sha256, stableId } from '../ids'\nimport { writeKnowledgeIndex } from '../indexer'\nimport {\n KNOWLEDGE_RESEARCH_STATE_PATHS,\n type KnowledgeStateScope,\n normalizeKnowledgeStateScope,\n} from '../knowledge-state-scope'\nimport { withKnowledgeRead } from '../mutation-lock'\nimport { immutableJsonValue } from './activation'\nimport type {\n KnowledgeImprovementCandidateRecord,\n KnowledgeImprovementCandidateRef,\n KnowledgeImprovementEvidence,\n KnowledgeImprovementResult,\n KnowledgeImprovementRunState,\n KnowledgeImprovementTarget,\n ResolvedKnowledgeImprovementCandidate,\n ResolvedKnowledgeImprovementComparison,\n UseKnowledgeImprovementCandidateOptions,\n} from './contracts'\nimport {\n KnowledgeImprovementCandidateRefSchema,\n KnowledgeImprovementEvidenceSchema,\n safePathSegmentSchema,\n} from './contracts'\nimport {\n assertExactCandidatePlatform,\n candidateEvidenceRelativePath,\n loadKnowledgeImprovementStateFromRun,\n withKnowledgeImprovementRun,\n} from './state'\n\n/** Freeze the exact knowledge bytes and measured evidence a later approval may promote. */\nexport function knowledgeImprovementCandidateRef(\n result: Pick<KnowledgeImprovementResult, 'runId' | 'state' | 'candidate'>,\n): KnowledgeImprovementCandidateRef {\n if (!result.candidate) throw new Error('knowledge improvement result has no candidate')\n return candidateRefFor(result.runId, result.state, result.candidate)\n}\n\n/** Use both frozen sides of one measured comparison in isolated, integrity-checked copies. */\nexport async function withKnowledgeImprovementComparison<T>(\n options: UseKnowledgeImprovementCandidateOptions,\n use: (comparison: ResolvedKnowledgeImprovementComparison) => Promise<T> | T,\n): Promise<T> {\n assertExactCandidatePlatform()\n const reference = Object.freeze(KnowledgeImprovementCandidateRefSchema.parse(options.candidate))\n return withKnowledgeImprovementRun(options.root, reference.runId, false, async (runDir) => {\n const state = await loadKnowledgeImprovementStateFromRun(options.root, reference.runId, runDir)\n return withMeasuredCandidateSnapshot(options.root, runDir, state, reference, (resolved) =>\n withBaselineSnapshot(\n runDir,\n reference.baseHash,\n (baselineRoot) =>\n withIsolatedKnowledgeCopy(\n baselineRoot,\n reference.baseHash,\n 'baseline',\n (baseline) =>\n withIsolatedKnowledgeCopy(\n resolved.root,\n reference.candidateHash,\n 'candidate',\n (candidate) =>\n use(\n Object.freeze({\n reference,\n stateScope: Object.freeze(normalizeKnowledgeStateScope(state.stateScope)),\n evaluation: immutableJsonValue(structuredClone(resolved.evidence.evaluation)),\n baseline: Object.freeze({ root: baseline, hash: reference.baseHash }),\n candidate: Object.freeze({ root: candidate, hash: reference.candidateHash }),\n }),\n ),\n state.stateScope,\n ),\n state.stateScope,\n ),\n state.stateScope,\n ),\n )\n })\n}\n\n/** Use the frozen candidate side of one measured comparison. */\nexport async function withKnowledgeImprovementCandidate<T>(\n options: UseKnowledgeImprovementCandidateOptions,\n use: (candidate: ResolvedKnowledgeImprovementCandidate) => Promise<T> | T,\n): Promise<T> {\n assertExactCandidatePlatform()\n const candidateRef = Object.freeze(\n KnowledgeImprovementCandidateRefSchema.parse(options.candidate),\n )\n return withKnowledgeImprovementRun(options.root, candidateRef.runId, false, async (runDir) => {\n const state = await loadKnowledgeImprovementStateFromRun(\n options.root,\n candidateRef.runId,\n runDir,\n )\n return withMeasuredCandidateSnapshot(options.root, runDir, state, candidateRef, (resolved) =>\n withIsolatedKnowledgeCopy(\n resolved.root,\n candidateRef.candidateHash,\n 'candidate',\n (root) =>\n use(\n Object.freeze({\n root,\n candidate: candidateRef,\n stateScope: Object.freeze(normalizeKnowledgeStateScope(state.stateScope)),\n evaluation: immutableJsonValue(structuredClone(resolved.evidence.evaluation)),\n }),\n ),\n state.stateScope,\n ),\n )\n })\n}\n\nexport function candidateRefFor(\n runId: string,\n state: KnowledgeImprovementRunState,\n candidate: KnowledgeImprovementCandidateRecord,\n): KnowledgeImprovementCandidateRef {\n if (candidate.status !== 'candidate-ready' && candidate.status !== 'promoted') {\n throw new Error(`knowledge candidate '${candidate.candidateId}' is not ready`)\n }\n return candidateIdentityFor(runId, state, candidate)\n}\n\nexport function candidateIdentityFor(\n runId: string,\n state: KnowledgeImprovementRunState,\n candidate: KnowledgeImprovementCandidateRecord,\n): KnowledgeImprovementCandidateRef {\n if (!candidate.candidateHash) {\n throw new Error(`knowledge candidate '${candidate.candidateId}' has no content hash`)\n }\n if (!candidate.evidenceHash) {\n throw new Error(`knowledge candidate '${candidate.candidateId}' has no evidence hash`)\n }\n if (!candidate.promotionPlanHash) {\n throw new Error(`knowledge candidate '${candidate.candidateId}' has no promotion plan hash`)\n }\n return Object.freeze({\n kind: 'knowledge-improvement-candidate',\n runId,\n candidateId: candidate.candidateId,\n goalHash: sha256(state.goal),\n baseHash: candidate.baseHash,\n candidateHash: candidate.candidateHash,\n evidenceHash: candidate.evidenceHash,\n promotionPlanHash: candidate.promotionPlanHash,\n })\n}\n\nexport async function withMeasuredCandidateSnapshot<T>(\n liveRoot: string,\n runDir: string,\n state: KnowledgeImprovementRunState,\n candidateRef: KnowledgeImprovementCandidateRef,\n use: (snapshot: {\n root: string\n candidate: KnowledgeImprovementCandidateRecord\n evidence: KnowledgeImprovementEvidence\n }) => Promise<T> | T,\n): Promise<T> {\n await assertStateIdentity(liveRoot, candidateRef, state)\n const candidate = state.candidates.find((entry) => entry.candidateId === candidateRef.candidateId)\n if (!candidate) {\n throw new Error(`knowledge candidate '${candidateRef.candidateId}' does not exist`)\n }\n const expectedRef = candidateRefFor(candidateRef.runId, state, candidate)\n if (canonicalJson(expectedRef) !== canonicalJson(candidateRef)) {\n throw new Error('knowledge candidate approval does not match the measured candidate')\n }\n const evidence = await assertCandidateEvidence(runDir, candidateRef, state.implementationRef)\n const relativePath = join(\n 'candidates',\n candidate.candidateId,\n 'snapshots',\n candidateRef.candidateHash,\n )\n return withSafeDirectory(runDir, relativePath, false, async (root) => {\n if ((await hashKnowledgeBase(root, state.stateScope)) !== candidateRef.candidateHash) {\n throw new Error('knowledge candidate snapshot changed after approval')\n }\n const result = await use({ root, candidate, evidence })\n if ((await hashKnowledgeBase(root, state.stateScope)) !== candidateRef.candidateHash) {\n throw new Error('knowledge candidate snapshot changed during use')\n }\n return result\n })\n}\n\nasync function withIsolatedKnowledgeCopy<T>(\n sourceRoot: string,\n expectedHash: string,\n target: KnowledgeImprovementTarget,\n use: (root: string) => Promise<T> | T,\n scope?: KnowledgeStateScope,\n): Promise<T> {\n const isolationRoot = await mkdtemp(join(tmpdir(), 'agent-knowledge-snapshot-'))\n const snapshotRoot = join(isolationRoot, 'snapshot')\n try {\n await copyKnowledgeWorkspace(sourceRoot, snapshotRoot, scope)\n if ((await hashKnowledgeBase(snapshotRoot, scope)) !== expectedHash) {\n throw new Error(`isolated knowledge ${target} does not match its measured content`)\n }\n const result = await use(snapshotRoot)\n if ((await hashKnowledgeBase(snapshotRoot, scope)) !== expectedHash) {\n throw new Error(`knowledge ${target} snapshot changed during use`)\n }\n return result\n } finally {\n await rm(isolationRoot, { recursive: true, force: true })\n }\n}\n\nexport async function assertCandidateEvidence(\n runDir: string,\n candidate: KnowledgeImprovementCandidateRef,\n expectedImplementationRef: string,\n): Promise<KnowledgeImprovementEvidence> {\n const evidence = KnowledgeImprovementEvidenceSchema.parse(\n JSON.parse(\n (\n await readRegularFileWithinRoot(\n runDir,\n candidateEvidenceRelativePath(candidate.candidateId),\n )\n ).bytes.toString('utf8'),\n ),\n )\n const actualHash = contentHash(evidence)\n if (actualHash !== candidate.evidenceHash) {\n throw new Error(\n `knowledge candidate evidence changed after approval: expected ${candidate.evidenceHash}, got ${actualHash}`,\n )\n }\n if (\n evidence.runId !== candidate.runId ||\n evidence.candidateId !== candidate.candidateId ||\n evidence.goalHash !== candidate.goalHash ||\n evidence.implementationRef !== expectedImplementationRef ||\n evidence.baseHash !== candidate.baseHash ||\n evidence.candidateHash !== candidate.candidateHash ||\n evidence.promotionPlanHash !== candidate.promotionPlanHash ||\n evidence.evaluation.passed !== true\n ) {\n throw new Error('knowledge candidate evidence does not match the approved candidate')\n }\n return evidence\n}\n\nexport async function assertStateIdentity(\n root: string,\n candidateRef: KnowledgeImprovementCandidateRef,\n state: KnowledgeImprovementRunState,\n): Promise<void> {\n if (state.runId !== candidateRef.runId) {\n throw new Error('knowledge candidate run identity does not match persisted state')\n }\n if (!(await canonicalPathsEqual(state.root, root))) {\n throw new Error('knowledge candidate root does not match persisted state')\n }\n if (sha256(state.goal) !== candidateRef.goalHash) {\n throw new Error('knowledge candidate goal does not match persisted state')\n }\n if (state.baseHash !== candidateRef.baseHash) {\n throw new Error('knowledge candidate base does not match persisted state')\n }\n}\n\nexport async function createCandidateWorkspace(\n runDir: string,\n state: KnowledgeImprovementRunState,\n root: string,\n now: () => Date,\n): Promise<KnowledgeImprovementCandidateRecord> {\n const iteration = state.candidates.length + 1\n const candidateId = stableId('kcand', `${state.runId}:${iteration}:${now().toISOString()}`)\n const candidateRoot = candidateWorkspacePath(runDir, candidateId)\n await copyKnowledgeWorkspace(root, candidateRoot, state.stateScope)\n const createdAt = now().toISOString()\n return {\n iteration,\n candidateId,\n baseHash: state.baseHash,\n status: 'running',\n createdAt,\n updatedAt: createdAt,\n }\n}\n\nfunction candidateWorkspacePath(runDir: string, candidateId: string): string {\n return join(runDir, 'candidates', safePathSegmentSchema.parse(candidateId), 'workspace')\n}\n\nfunction baselineSnapshotPath(runDir: string): string {\n return join(runDir, 'baseline')\n}\n\nexport async function createBaselineSnapshot(\n runDir: string,\n root: string,\n expectedHash: string,\n scope?: KnowledgeStateScope,\n): Promise<void> {\n const target = baselineSnapshotPath(runDir)\n try {\n await assertBaselineSnapshot(runDir, expectedHash, scope)\n return\n } catch (error) {\n if (!isMissingFile(error)) throw error\n }\n const preparation = await mkdtemp(join(runDir, 'baseline-prepare-'))\n let activated = false\n try {\n await copyKnowledgeWorkspace(root, preparation, scope)\n const actualHash = await hashKnowledgeBase(preparation, scope)\n if (actualHash !== expectedHash) {\n throw new Error(\n `knowledge base changed while baseline was frozen: expected ${expectedHash}, got ${actualHash}`,\n )\n }\n await renameDurable(preparation, target)\n activated = true\n } finally {\n if (!activated) await rm(preparation, { recursive: true, force: true })\n }\n}\n\nexport async function ensureBaselineSnapshot(\n runDir: string,\n root: string,\n expectedHash: string,\n scope?: KnowledgeStateScope,\n): Promise<void> {\n try {\n await assertBaselineSnapshot(runDir, expectedHash, scope)\n } catch (error) {\n if (!isMissingFile(error)) throw error\n const liveHash = await hashKnowledgeBase(root, scope)\n if (liveHash !== expectedHash) {\n throw new Error(\n 'knowledge improvement baseline snapshot is missing and cannot be reconstructed',\n )\n }\n await createBaselineSnapshot(runDir, root, expectedHash, scope)\n }\n}\n\nasync function assertBaselineSnapshot(\n runDir: string,\n expectedHash: string,\n scope?: KnowledgeStateScope,\n): Promise<void> {\n await withBaselineSnapshot(runDir, expectedHash, () => undefined, scope)\n}\n\nexport async function withBaselineSnapshot<T>(\n runDir: string,\n expectedHash: string,\n use: (baselineRoot: string) => Promise<T> | T,\n scope?: KnowledgeStateScope,\n): Promise<T> {\n return withSafeDirectory(runDir, 'baseline', false, async (baselineRoot) => {\n const actualHash = await hashKnowledgeBase(baselineRoot, scope)\n if (actualHash !== expectedHash) {\n throw new Error(\n `knowledge improvement baseline changed: expected ${expectedHash}, got ${actualHash}`,\n )\n }\n return use(baselineRoot)\n })\n}\n\nexport async function withFrozenCandidateWorkspace<T>(\n runDir: string,\n candidate: KnowledgeImprovementCandidateRecord,\n candidateRoot: string,\n use: (snapshot: { root: string; hash: string }) => Promise<T> | T,\n scope?: KnowledgeStateScope,\n): Promise<T> {\n const snapshotsPath = join(\n 'candidates',\n safePathSegmentSchema.parse(candidate.candidateId),\n 'snapshots',\n )\n return withSafeDirectory(runDir, snapshotsPath, true, async (snapshotsDir) => {\n const preparation = await mkdtemp(join(snapshotsDir, 'prepare-'))\n let activated = false\n try {\n await copyKnowledgeWorkspace(candidateRoot, preparation, scope)\n const hash = await hashKnowledgeBase(preparation, scope)\n try {\n const result = await withSafeDirectory(snapshotsDir, hash, false, async (existing) => {\n if ((await hashKnowledgeBase(existing, scope)) !== hash) {\n throw new Error('knowledge candidate snapshot does not match its content identity')\n }\n return use({ root: existing, hash })\n })\n await rm(preparation, { recursive: true, force: true })\n activated = true\n return result\n } catch (error) {\n if (!isMissingFile(error)) throw error\n }\n await renameDurable(preparation, join(snapshotsDir, hash))\n activated = true\n return withSafeDirectory(snapshotsDir, hash, false, (root) => use({ root, hash }))\n } finally {\n if (!activated) await rm(preparation, { recursive: true, force: true })\n }\n })\n}\n\nexport function clearCandidateMeasurement(candidate: KnowledgeImprovementCandidateRecord): void {\n delete candidate.candidateHash\n delete candidate.evidenceHash\n delete candidate.promotionPlanHash\n}\n\nasync function copyKnowledgeWorkspace(\n sourceRoot: string,\n targetRoot: string,\n scope?: KnowledgeStateScope,\n): Promise<void> {\n const normalized = normalizeKnowledgeStateScope(scope)\n await withKnowledgeRead(sourceRoot, async () => {\n await rm(targetRoot, { recursive: true, force: true })\n await mkdir(join(targetRoot, normalized.pagesDirectory), { recursive: true })\n await mkdir(join(targetRoot, 'raw', 'sources'), { recursive: true })\n for (const path of knowledgeScopePaths(normalized)) {\n await copyIfExists(join(sourceRoot, path), join(targetRoot, path))\n }\n })\n await writeKnowledgeIndex(targetRoot, { pagesDirectory: normalized.pagesDirectory })\n}\n\nfunction knowledgeScopePaths(scope: KnowledgeStateScope): string[] {\n const normalized = normalizeKnowledgeStateScope(scope)\n return [\n normalized.pagesDirectory,\n 'raw',\n '.agent-knowledge/sources.json',\n ...(normalized.researchState ? KNOWLEDGE_RESEARCH_STATE_PATHS : []),\n ]\n}\n\nasync function copyIfExists(source: string, target: string): Promise<void> {\n let sourceStat: Awaited<ReturnType<typeof lstat>>\n try {\n sourceStat = await lstat(source)\n } catch (error) {\n if (isMissingFile(error)) return\n throw error\n }\n if (!sourceStat.isDirectory() && !sourceStat.isFile()) {\n throw new Error(`knowledge surface contains an unsupported filesystem entry: ${source}`)\n }\n await mkdir(dirname(target), { recursive: true })\n await cp(source, target, { recursive: sourceStat.isDirectory(), dereference: false })\n}\n\nexport async function hashKnowledgeBase(\n root: string,\n scope?: KnowledgeStateScope,\n): Promise<string> {\n return withKnowledgeRead(root, () => hashKnowledgeBaseUnlocked(root, scope))\n}\n\nasync function hashKnowledgeBaseUnlocked(\n root: string,\n scope?: KnowledgeStateScope,\n): Promise<string> {\n const normalized = normalizeKnowledgeStateScope(scope)\n const entries = await knowledgeHashEntries(root, normalized)\n const files = entries.map(({ path, hash, mode }) => ({ path, hash, mode }))\n return sha256(\n JSON.stringify(\n normalized.pagesDirectory === 'knowledge' && !normalized.researchState\n ? files\n : { scope: normalized, files },\n ),\n )\n}\n\nexport interface KnowledgeFileIdentity {\n path: string\n hash: string\n transactionHash: string\n mode: number\n}\n\nexport async function knowledgeHashEntries(\n root: string,\n scope?: KnowledgeStateScope,\n): Promise<KnowledgeFileIdentity[]> {\n const entries: KnowledgeFileIdentity[] = []\n for (const path of knowledgeScopePaths(scope ?? {})) {\n try {\n const files =\n path === '.agent-knowledge/sources.json' || path === '.agent-knowledge/events.json'\n ? [{ ...(await readRegularFileWithinRoot(root, path)), path }]\n : await listRegularFilesWithinRoot(root, path)\n for (const file of files)\n entries.push(knowledgeFileIdentity(file.path, file.bytes, file.mode))\n } catch (error) {\n if (!isMissingFile(error)) throw error\n }\n }\n entries.sort((a, b) => a.path.localeCompare(b.path))\n return entries\n}\n\nfunction knowledgeFileIdentity(path: string, bytes: Buffer, mode: number): KnowledgeFileIdentity {\n return {\n path,\n hash: sha256(bytes.toString('base64')),\n transactionHash: createHash('sha256').update(bytes).digest('hex'),\n mode,\n }\n}\n","import { createHash } from 'node:crypto'\nimport { canonicalJson, contentHash } from '@tangle-network/agent-eval'\nimport type { AgentImprovementActivationResult } from '@tangle-network/agent-interface'\nimport { readRegularFileWithinRoot } from '../durable-fs'\nimport {\n applyKnowledgeFileTransaction,\n assertKnowledgeMutationPath,\n finishKnowledgeFileTransaction,\n type KnowledgeFileMutation,\n type KnowledgeFileTransaction,\n type KnowledgeFileTransactionPlanEntry,\n knowledgeFileTransactionPlanHash,\n prepareKnowledgeFileTransaction,\n rollbackKnowledgeFileTransaction,\n} from '../file-transaction'\nimport { writeKnowledgeIndex } from '../indexer'\nimport { type KnowledgeStateScope, normalizeKnowledgeStateScope } from '../knowledge-state-scope'\nimport { withKnowledgeMutation } from '../mutation-lock'\nimport type { RunRagKnowledgeImprovementLoopResult } from '../rag-improvement-loop'\nimport type { ResolvedKnowledgeImprovementActivationPersistence } from './activation'\nimport {\n loadKnowledgeActivationRecord,\n persistKnowledgeActivationResult,\n resolveKnowledgeActivationPersistence,\n sourceKnowledgeHash,\n} from './activation'\nimport type {\n KnowledgeImprovementCandidateRecord,\n KnowledgeImprovementCandidateRef,\n KnowledgeImprovementMutationReceipt,\n KnowledgeImprovementMutationResult,\n KnowledgeImprovementOptions,\n KnowledgeImprovementRunState,\n KnowledgeImprovementTarget,\n PromoteKnowledgeCandidateOptions,\n RestoreKnowledgeCandidateBaselineOptions,\n} from './contracts'\nimport { DEFAULT_LEASE_TTL_MS, KnowledgeImprovementCandidateRefSchema } from './contracts'\nimport {\n acquireRunLease,\n appendLedger,\n assertExactCandidatePlatform,\n blockRun,\n loadKnowledgeImprovementEventsFromRun,\n loadKnowledgeImprovementStateFromRun,\n saveState,\n withKnowledgeImprovementRun,\n} from './state'\nimport {\n assertCandidateEvidence,\n assertStateIdentity,\n candidateIdentityFor,\n hashKnowledgeBase,\n knowledgeHashEntries,\n withBaselineSnapshot,\n withMeasuredCandidateSnapshot,\n} from './workspace'\n\n/** Promote one previously measured candidate without rerunning research or evaluation. */\nexport async function promoteKnowledgeCandidate(\n options: PromoteKnowledgeCandidateOptions,\n): Promise<KnowledgeImprovementMutationResult> {\n return transitionKnowledgeCandidate(options, 'candidate')\n}\n\n/** Restore the frozen baseline paired with one previously measured candidate. */\nexport async function restoreKnowledgeCandidateBaseline(\n options: RestoreKnowledgeCandidateBaselineOptions,\n): Promise<KnowledgeImprovementMutationResult> {\n return transitionKnowledgeCandidate(options, 'baseline')\n}\n\nasync function transitionKnowledgeCandidate(\n options: PromoteKnowledgeCandidateOptions,\n target: KnowledgeImprovementTarget,\n): Promise<KnowledgeImprovementMutationResult> {\n assertExactCandidatePlatform()\n const candidateRef = Object.freeze(\n KnowledgeImprovementCandidateRefSchema.parse(options.candidate),\n )\n const now = options.now ?? (() => new Date())\n const activation = options.activation\n ? resolveKnowledgeActivationPersistence(options.activation, candidateRef, target)\n : undefined\n return withKnowledgeImprovementRun(options.root, candidateRef.runId, false, async (runDir) => {\n const lease = await acquireRunLease(runDir, {\n ownerId: options.ownerId ?? `pid-${process.pid}`,\n ttlMs: options.leaseTtlMs ?? DEFAULT_LEASE_TTL_MS,\n })\n try {\n lease.assertOwned()\n const state = await loadKnowledgeImprovementStateFromRun(\n options.root,\n candidateRef.runId,\n runDir,\n )\n return await applyKnowledgeCandidateTarget(\n {\n root: options.root,\n runDir,\n state,\n candidateRef,\n leaseTtlMs: options.leaseTtlMs ?? DEFAULT_LEASE_TTL_MS,\n assertRunOwned: lease.assertOwned,\n now,\n onState: options.onState,\n activation,\n },\n target,\n )\n } finally {\n await lease.release()\n }\n })\n}\n\ninterface KnowledgeCandidateTransitionInput {\n root: string\n runDir: string\n state: KnowledgeImprovementRunState\n candidateRef: KnowledgeImprovementCandidateRef\n activation?: ResolvedKnowledgeImprovementActivationPersistence\n leaseTtlMs: number\n assertRunOwned(): void\n now: () => Date\n onState?: KnowledgeImprovementOptions['onState']\n lifecycle?: RunRagKnowledgeImprovementLoopResult\n}\n\nasync function applyKnowledgeCandidateTarget(\n input: KnowledgeCandidateTransitionInput,\n target: KnowledgeImprovementTarget,\n): Promise<KnowledgeImprovementMutationResult> {\n const { candidateRef, runDir, state } = input\n await assertStateIdentity(input.root, candidateRef, state)\n const candidate = state.candidates.find((entry) => entry.candidateId === candidateRef.candidateId)\n if (\n !candidate ||\n canonicalJson(candidateIdentityFor(candidateRef.runId, state, candidate)) !==\n canonicalJson(candidateRef)\n ) {\n throw new Error('knowledge candidate approval does not match the measured candidate')\n }\n const action = target === 'candidate' ? 'promotion' : 'restore'\n const desiredHash = target === 'candidate' ? candidateRef.candidateHash : candidateRef.baseHash\n const purpose = knowledgeCandidateTransitionPurpose(candidateRef, state.implementationRef, target)\n const recoveryOwner = input.activation\n ? `knowledge-improvement-activation:${input.activation.activation.digest}`\n : 'knowledge-improvement-candidate-transition'\n return withKnowledgeMutation(\n input.root,\n async (mutationLock) => {\n const assertOwned = () => {\n mutationLock.assertOwned()\n input.assertRunOwned()\n }\n assertOwned()\n const transactionRoot = mutationLock.transactionRoot\n const recovery =\n mutationLock.recovery?.purpose === purpose ? mutationLock.recovery : undefined\n if (!recovery) {\n await assertCandidateEvidence(runDir, candidateRef, state.implementationRef)\n }\n const existingActivation = input.activation\n ? await loadKnowledgeActivationRecord(\n runDir,\n candidateRef,\n input.activation.activation,\n target,\n input.activation.identity,\n )\n : null\n if (existingActivation) {\n if (recovery?.direction === 'rollback') {\n throw new Error('stored knowledge activation result conflicts with a pending rollback')\n }\n if (recovery) {\n const recoveredHash = await hashKnowledgeBase(input.root, state.stateScope)\n if (recoveredHash !== existingActivation.mutation.afterHash) {\n throw new Error('stored knowledge activation result does not match the recovered files')\n }\n await finishKnowledgeFileTransaction({\n root: input.root,\n transactionRoot,\n transaction: recovery.transaction,\n assertOwned,\n })\n }\n if (existingActivation.result.outcome.status === 'conflict') {\n const reason = candidateTransitionConflictReason(\n target,\n candidateRef,\n existingActivation.mutation.afterHash,\n )\n const blocked = await blockCandidateTransition(\n input,\n candidate,\n target,\n reason,\n existingActivation.mutation.afterHash,\n )\n return { ...blocked, activationResult: existingActivation.result }\n }\n return candidateTransitionResult(\n input,\n candidate,\n target === 'candidate' && state.status === 'promoted',\n false,\n existingActivation.mutation,\n existingActivation.result,\n )\n }\n if (recovery?.direction === 'rollback') {\n await finishKnowledgeFileTransaction({\n root: input.root,\n transactionRoot,\n transaction: recovery.transaction,\n assertOwned,\n })\n }\n const recovered = recovery?.direction === 'apply' ? recovery : undefined\n let pending: KnowledgeFileTransaction | null =\n input.activation && recovered ? recovered.transaction : null\n const currentHash = await hashKnowledgeBase(input.root, state.stateScope)\n let transactionId = recovered?.transactionId ?? null\n if (recovered && currentHash !== desiredHash) {\n throw new Error(`recovered knowledge ${action} does not match the approved target`)\n }\n if (state.status === 'promoted' && state.promotedCandidateId !== candidate.candidateId) {\n throw new Error(\n `knowledge run already promoted '${state.promotedCandidateId ?? 'unknown'}'`,\n )\n }\n if (\n target === 'candidate' &&\n state.status === 'promoted' &&\n currentHash !== candidateRef.candidateHash\n ) {\n throw new Error(\n `promoted knowledge base changed: expected ${candidateRef.candidateHash}, got ${currentHash}`,\n )\n }\n if (state.status !== 'promoted' && state.status !== 'candidate-ready') {\n throw new Error(\n `knowledge candidate is not ready for ${action}: run=${state.status}, candidate=${candidate.status}`,\n )\n }\n if (currentHash !== state.baseHash && currentHash !== candidateRef.candidateHash) {\n const reason =\n target === 'candidate'\n ? `base changed before promotion: expected ${state.baseHash}, got ${currentHash}`\n : `knowledge changed before restore: expected ${candidateRef.candidateHash}, got ${currentHash}`\n const mutation = Object.freeze({\n target,\n beforeHash: currentHash,\n afterHash: currentHash,\n changed: false,\n transactionId: null,\n recovered: false,\n }) satisfies KnowledgeImprovementMutationReceipt\n const activationResult = input.activation\n ? await persistKnowledgeActivationResult(\n runDir,\n candidateRef,\n input.activation,\n target,\n mutation,\n )\n : undefined\n const blocked = await blockCandidateTransition(\n input,\n candidate,\n target,\n reason,\n currentHash,\n )\n return activationResult ? { ...blocked, activationResult } : blocked\n }\n\n if (currentHash !== desiredHash && !pending) {\n pending = await withMeasuredCandidateSnapshot(\n input.root,\n runDir,\n state,\n candidateRef,\n (resolved) =>\n withBaselineSnapshot(\n runDir,\n state.baseHash,\n async (baselineRoot) => {\n const sourceRoot = target === 'candidate' ? baselineRoot : resolved.root\n const targetRoot = target === 'candidate' ? resolved.root : baselineRoot\n const plan = await knowledgeFilePlanEntries(\n sourceRoot,\n targetRoot,\n state.stateScope,\n )\n assertCandidateTransitionPlan(plan, candidateRef, target, state.stateScope)\n return prepareKnowledgeFileTransaction({\n root: input.root,\n transactionRoot,\n purpose,\n ...normalizeKnowledgeStateScope(state.stateScope),\n recoveryOwner,\n mutations: await knowledgePlanMutations(targetRoot, plan),\n includeUnchanged: true,\n now: input.now,\n })\n },\n state.stateScope,\n ),\n )\n if (!pending) {\n throw new Error(`knowledge ${action} plan unexpectedly contained no file changes`)\n }\n transactionId = pending.transactionId\n try {\n assertCandidateTransitionTransaction(pending, candidateRef, target, state.stateScope)\n } catch (error) {\n try {\n await rollbackKnowledgeFileTransaction({\n root: input.root,\n transactionRoot,\n transaction: pending,\n beforeCommit: assertOwned,\n })\n await finishKnowledgeFileTransaction({\n root: input.root,\n transactionRoot,\n transaction: pending,\n assertOwned,\n })\n } catch (cleanupError) {\n throw new AggregateError(\n [error, cleanupError],\n `invalid knowledge ${action} transaction could not be removed`,\n )\n }\n throw error\n }\n }\n try {\n if (pending) {\n await applyKnowledgeFileTransaction({\n root: input.root,\n transactionRoot,\n transaction: pending,\n beforeCommit: assertOwned,\n })\n }\n assertOwned()\n if ((await hashKnowledgeBase(input.root, state.stateScope)) !== desiredHash) {\n throw new Error(`knowledge ${action} content does not match the approved target`)\n }\n await writeKnowledgeIndex(input.root, state.stateScope)\n } catch (error) {\n if (!pending) throw error\n if (recovered && input.activation) throw error\n try {\n assertOwned()\n } catch (ownershipError) {\n throw new AggregateError(\n [error, ownershipError],\n `knowledge ${action} lost its lock and left the transaction pending`,\n )\n }\n try {\n await rollbackKnowledgeFileTransaction({\n root: input.root,\n transactionRoot,\n transaction: pending,\n beforeCommit: assertOwned,\n })\n await finishKnowledgeFileTransaction({\n root: input.root,\n transactionRoot,\n transaction: pending,\n assertOwned,\n })\n await writeKnowledgeIndex(input.root, state.stateScope)\n } catch (rollbackError) {\n throw new AggregateError(\n [error, rollbackError],\n `knowledge ${action} failed and could not restore the previous files`,\n )\n }\n throw error\n }\n candidate.status = target === 'candidate' ? 'promoted' : 'candidate-ready'\n candidate.updatedAt = input.now().toISOString()\n state.status = candidate.status\n if (target === 'candidate') state.promotedCandidateId = candidate.candidateId\n else delete state.promotedCandidateId\n delete state.blockedReason\n state.updatedAt = input.now().toISOString()\n await saveState(runDir, state, input.onState)\n await ensureCandidateTransitionEvent(runDir, candidateRef, target)\n let finalHash = await hashKnowledgeBase(input.root, state.stateScope)\n if (finalHash !== desiredHash) {\n throw new Error(`knowledge ${action} changed before its result was returned`)\n }\n const mutation = Object.freeze({\n target,\n beforeHash: transactionId ? sourceKnowledgeHash(candidateRef, target) : currentHash,\n afterHash: finalHash,\n changed: transactionId !== null,\n transactionId,\n recovered: recovered !== undefined,\n }) satisfies KnowledgeImprovementMutationReceipt\n const activationResult = input.activation\n ? await persistKnowledgeActivationResult(\n runDir,\n candidateRef,\n input.activation,\n target,\n mutation,\n )\n : undefined\n if ((await hashKnowledgeBase(input.root, state.stateScope)) !== finalHash) {\n throw new Error(`knowledge ${action} changed while its result was persisted`)\n }\n if (pending) {\n await finishKnowledgeFileTransaction({\n root: input.root,\n transactionRoot,\n transaction: pending,\n assertOwned,\n })\n }\n finalHash = await hashKnowledgeBase(input.root, state.stateScope)\n if (finalHash !== desiredHash) {\n throw new Error(`knowledge ${action} changed before its result was returned`)\n }\n return candidateTransitionResult(\n input,\n candidate,\n target === 'candidate',\n false,\n mutation,\n activationResult,\n )\n },\n {\n staleMs: input.leaseTtlMs,\n resumeTransaction: {\n purpose,\n recoveryOwner,\n validate: (transaction) =>\n assertCandidateTransitionTransaction(transaction, candidateRef, target, state.stateScope),\n deferFinish: input.activation !== undefined,\n },\n },\n )\n}\n\nfunction candidateTransitionConflictReason(\n target: KnowledgeImprovementTarget,\n candidate: KnowledgeImprovementCandidateRef,\n currentHash: string,\n): string {\n return target === 'candidate'\n ? `base changed before promotion: expected ${candidate.baseHash}, got ${currentHash}`\n : `knowledge changed before restore: expected ${candidate.candidateHash}, got ${currentHash}`\n}\n\nasync function blockCandidateTransition(\n input: KnowledgeCandidateTransitionInput,\n candidate: KnowledgeImprovementCandidateRecord,\n target: KnowledgeImprovementTarget,\n reason: string,\n currentHash: string,\n): Promise<KnowledgeImprovementMutationResult> {\n if (input.state.status === 'promoted') {\n candidate.status = 'blocked'\n candidate.updatedAt = input.now().toISOString()\n delete input.state.promotedCandidateId\n }\n await blockRun(input.runDir, input.state, reason, input.onState, input.now)\n await appendLedger(input.runDir, {\n type: target === 'candidate' ? 'promotion.blocked' : 'restore.blocked',\n runId: input.candidateRef.runId,\n candidateId: candidate.candidateId,\n reason,\n })\n return candidateTransitionResult(input, candidate, false, true, {\n target,\n beforeHash: currentHash,\n afterHash: currentHash,\n changed: false,\n transactionId: null,\n recovered: false,\n })\n}\n\nfunction candidateTransitionResult(\n input: KnowledgeCandidateTransitionInput,\n candidate: KnowledgeImprovementCandidateRecord,\n promoted: boolean,\n blocked: boolean,\n mutation: KnowledgeImprovementMutationReceipt,\n activationResult?: AgentImprovementActivationResult,\n): KnowledgeImprovementMutationResult {\n return {\n runId: input.candidateRef.runId,\n state: input.state,\n candidate,\n ...(input.lifecycle ? { lifecycle: input.lifecycle } : {}),\n mutation,\n ...(activationResult ? { activationResult } : {}),\n promoted,\n blocked,\n }\n}\n\nfunction knowledgeCandidateTransitionPurpose(\n candidate: KnowledgeImprovementCandidateRef,\n implementationRef: string,\n target: KnowledgeImprovementTarget,\n): string {\n const action = target === 'candidate' ? 'promotion' : 'restore'\n return `knowledge-${action}:${contentHash({ candidate, implementationRef })}`\n}\n\nexport async function knowledgeFilePlanEntries(\n sourceRoot: string,\n targetRoot: string,\n scope?: KnowledgeStateScope,\n): Promise<KnowledgeFileTransactionPlanEntry[]> {\n const [before, after] = await Promise.all([\n knowledgeHashEntries(sourceRoot, scope),\n knowledgeHashEntries(targetRoot, scope),\n ])\n const beforeByPath = new Map(before.map((entry) => [entry.path, entry]))\n const afterByPath = new Map(after.map((entry) => [entry.path, entry]))\n const paths = [\n ...new Set([...before.map((entry) => entry.path), ...after.map((entry) => entry.path)]),\n ].sort((left, right) => left.localeCompare(right))\n return paths.map((path) => {\n assertKnowledgeMutationPath(\n path,\n normalizeKnowledgeStateScope(scope).pagesDirectory,\n scope?.researchState,\n )\n const beforeEntry = beforeByPath.get(path)\n const afterEntry = afterByPath.get(path)\n return {\n path,\n beforeHash: beforeEntry?.transactionHash ?? null,\n afterHash: afterEntry?.transactionHash ?? null,\n ...(beforeEntry ? { beforeMode: beforeEntry.mode } : {}),\n ...(afterEntry ? { afterMode: afterEntry.mode } : {}),\n }\n })\n}\n\nasync function knowledgePlanMutations(\n targetRoot: string,\n plan: readonly KnowledgeFileTransactionPlanEntry[],\n): Promise<KnowledgeFileMutation[]> {\n return Promise.all(\n plan.map(async (entry) => {\n if (entry.afterHash === null) return { path: entry.path, content: null }\n const file = await readRegularFileWithinRoot(targetRoot, entry.path)\n const actualHash = createHash('sha256').update(file.bytes).digest('hex')\n if (actualHash !== entry.afterHash || file.mode !== entry.afterMode) {\n throw new Error(`knowledge target file changed before activation: ${entry.path}`)\n }\n return { path: entry.path, content: file.bytes, mode: file.mode }\n }),\n )\n}\n\nfunction assertCandidateTransitionPlan(\n plan: readonly KnowledgeFileTransactionPlanEntry[],\n candidate: KnowledgeImprovementCandidateRef,\n target: KnowledgeImprovementTarget,\n scope?: KnowledgeStateScope,\n): void {\n const approvedDirection = target === 'candidate' ? plan : reverseKnowledgeFilePlan(plan)\n const actualPlanHash = knowledgeFileTransactionPlanHash(\n approvedDirection,\n normalizeKnowledgeStateScope(scope).pagesDirectory,\n scope?.researchState,\n )\n if (actualPlanHash !== candidate.promotionPlanHash) {\n throw new Error(\n `knowledge candidate plan changed after approval: expected ${candidate.promotionPlanHash}, got ${actualPlanHash}`,\n )\n }\n}\n\nfunction assertCandidateTransitionTransaction(\n transaction: KnowledgeFileTransaction,\n candidate: KnowledgeImprovementCandidateRef,\n target: KnowledgeImprovementTarget,\n scope?: KnowledgeStateScope,\n): void {\n assertCandidateTransitionPlan(transaction.entries, candidate, target, scope)\n}\n\nfunction reverseKnowledgeFilePlan(\n plan: readonly KnowledgeFileTransactionPlanEntry[],\n): KnowledgeFileTransactionPlanEntry[] {\n return plan.map((entry) => ({\n path: entry.path,\n beforeHash: entry.afterHash,\n afterHash: entry.beforeHash,\n ...(entry.afterMode === undefined ? {} : { beforeMode: entry.afterMode }),\n ...(entry.beforeMode === undefined ? {} : { afterMode: entry.beforeMode }),\n }))\n}\n\nasync function ensureCandidateTransitionEvent(\n runDir: string,\n candidateRef: KnowledgeImprovementCandidateRef,\n target: KnowledgeImprovementTarget,\n): Promise<void> {\n if (await hasCandidateTransitionEvent(runDir, candidateRef, target)) return\n await appendLedger(runDir, {\n type: target === 'candidate' ? 'candidate.promoted' : 'candidate.restored',\n runId: candidateRef.runId,\n candidateId: candidateRef.candidateId,\n candidateHash: candidateRef.candidateHash,\n evidenceHash: candidateRef.evidenceHash,\n promotionPlanHash: candidateRef.promotionPlanHash,\n })\n}\n\nasync function hasCandidateTransitionEvent(\n runDir: string,\n candidateRef: KnowledgeImprovementCandidateRef,\n target: KnowledgeImprovementTarget,\n): Promise<boolean> {\n const eventType = target === 'candidate' ? 'candidate.promoted' : 'candidate.restored'\n let matched = false\n for (const row of await loadKnowledgeImprovementEventsFromRun(runDir)) {\n if (row.type !== eventType || row.candidateId !== candidateRef.candidateId) continue\n if (\n row.runId !== candidateRef.runId ||\n row.candidateHash !== candidateRef.candidateHash ||\n row.evidenceHash !== candidateRef.evidenceHash ||\n row.promotionPlanHash !== candidateRef.promotionPlanHash\n ) {\n throw new Error('persisted knowledge activation event conflicts with the approved candidate')\n }\n matched = true\n }\n return matched\n}\n","import { join } from 'node:path'\nimport { contentHash } from '@tangle-network/agent-eval'\nimport { writeJsonDurableWithinRoot } from '../durable-fs'\nimport type { EvalKnowledgeBundleBuildResult, KnowledgeReadinessSpec } from '../eval-readiness'\nimport { knowledgeFileTransactionPlanHash } from '../file-transaction'\nimport { sha256 } from '../ids'\nimport { assertImmutableRef } from '../immutable-ref'\nimport { buildKnowledgeIndex } from '../indexer'\nimport { normalizeKnowledgeStateScope } from '../knowledge-state-scope'\nimport { ragAnswerEvidenceRejectionReasons } from '../rag-answer-evidence'\nimport { type KnowledgeBaseQualityReport, scoreKnowledgeBaseIndex } from '../rag-eval'\nimport {\n type RagKnowledgeImprovementPhase,\n type RagKnowledgeResearchOptions,\n type RunRagKnowledgeImprovementLoopOptions,\n type RunRagKnowledgeImprovementLoopResult,\n runRagKnowledgeImprovementLoop,\n} from '../rag-improvement-loop'\nimport { runRagKnowledgeImprovementPhases } from '../rag-improvement-phases'\nimport { readinessFor } from '../readiness-helpers'\nimport { mean } from '../statistics'\nimport { type ValidateKnowledgeResult, validateKnowledgeIndex } from '../validate'\nimport type {\n KnowledgeImprovementCandidateRecord,\n KnowledgeImprovementMetric,\n KnowledgeImprovementOptions,\n KnowledgeImprovementRunState,\n} from './contracts'\nimport {\n EVALUATION_PHASES,\n improvementMetricSchema,\n KnowledgeImprovementEvidenceSchema,\n UPDATE_PHASES,\n} from './contracts'\nimport {\n appendLedger,\n candidateEvidenceRelativePath,\n saveState,\n withCandidateWorkspace,\n} from './state'\nimport { knowledgeFilePlanEntries } from './transition'\nimport {\n assertCandidateEvidence,\n candidateRefFor,\n clearCandidateMeasurement,\n hashKnowledgeBase,\n withBaselineSnapshot,\n withFrozenCandidateWorkspace,\n} from './workspace'\n\nexport function assertKnowledgeImprovementOptions(options: KnowledgeImprovementOptions): void {\n assertImmutableRef(options.implementationRef, 'knowledge improvement implementationRef')\n normalizeKnowledgeStateScope(options.stateScope)\n for (const phase of options.requiredPhases ?? []) {\n if (options.enabledPhases && !options.enabledPhases.includes(phase)) {\n throw new Error(`required phase ${phase} is not enabled`)\n }\n }\n if (\n options.answerQualityCostCeiling !== undefined &&\n (!Number.isFinite(options.answerQualityCostCeiling) || options.answerQualityCostCeiling < 0)\n ) {\n throw new Error(\n 'knowledge improvement answerQualityCostCeiling must be a non-negative finite number',\n )\n }\n if (options.ragOptimization) {\n assertImmutableRef(\n options.ragOptimization.executionRef,\n 'knowledge improvement RAG executionRef',\n )\n }\n if (options.retrieval) {\n assertImmutableRef(\n options.retrieval.executionRef,\n 'knowledge improvement retrieval executionRef',\n )\n }\n if (options.step && options.knowledgeResearch?.step) {\n throw new Error('improveKnowledgeBase accepts either step or knowledgeResearch.step, not both')\n }\n const updateDrivers = [\n Boolean(options.step ?? options.knowledgeResearch),\n Boolean(options.updateKnowledge),\n ].filter(Boolean).length\n if (updateDrivers > 1) {\n throw new Error(\n 'improveKnowledgeBase accepts only one knowledge-update driver: knowledgeResearch or updateKnowledge',\n )\n }\n}\n\nexport async function measureCandidate(\n runId: string,\n runDir: string,\n state: KnowledgeImprovementRunState,\n candidate: KnowledgeImprovementCandidateRecord,\n options: KnowledgeImprovementOptions,\n now: () => Date,\n): Promise<{\n candidate: KnowledgeImprovementCandidateRecord\n evaluation: KnowledgeImprovementMetric\n lifecycle?: RunRagKnowledgeImprovementLoopResult\n finalEvaluated: boolean\n}> {\n return withCandidateWorkspace(runDir, candidate, async (candidateRoot) => {\n const currentCandidateHash = await hashKnowledgeBase(candidateRoot, options.stateScope)\n if (\n candidate.status === 'candidate-ready' &&\n candidate.candidateHash === currentCandidateHash &&\n candidate.evidenceHash !== undefined &&\n candidate.promotionPlanHash !== undefined\n ) {\n const evidence = await assertCandidateEvidence(\n runDir,\n candidateRefFor(runId, state, candidate),\n state.implementationRef,\n )\n return {\n candidate,\n evaluation: evidence.evaluation,\n ...(evidence.lifecycle === null\n ? {}\n : { lifecycle: evidence.lifecycle as RunRagKnowledgeImprovementLoopResult }),\n finalEvaluated: shouldRunEvaluationStage(options),\n }\n }\n\n clearCandidateMeasurement(candidate)\n let lifecycle: RunRagKnowledgeImprovementLoopResult | undefined\n if (candidate.status === 'running') {\n lifecycle = await runCandidateUpdateLifecycle(runId, candidate, candidateRoot, options, now)\n }\n return withFrozenCandidateWorkspace(\n runDir,\n candidate,\n candidateRoot,\n async (snapshot) => {\n const development = await evaluateCandidate(\n runDir,\n state,\n candidate,\n snapshot,\n lifecycle,\n options,\n now,\n false,\n )\n if (!development.evaluation.passed || !shouldRunEvaluationStage(options)) {\n return {\n ...development,\n ...(lifecycle ? { lifecycle } : {}),\n finalEvaluated: false,\n }\n }\n\n candidate.finalEvaluationStartedAt = now().toISOString()\n candidate.updatedAt = candidate.finalEvaluationStartedAt\n state.updatedAt = candidate.finalEvaluationStartedAt\n await saveState(runDir, state, options.onState)\n await appendLedger(runDir, {\n type: 'candidate.final-evaluation-started',\n runId: state.runId,\n candidateId: candidate.candidateId,\n })\n lifecycle = await runCandidateEvaluationLifecycle(\n runId,\n runDir,\n candidate,\n snapshot.root,\n snapshot.hash,\n lifecycle,\n options,\n now,\n )\n const measured = await evaluateCandidate(\n runDir,\n state,\n candidate,\n snapshot,\n lifecycle,\n options,\n now,\n true,\n )\n return {\n ...measured,\n ...(lifecycle ? { lifecycle } : {}),\n finalEvaluated: true,\n }\n },\n options.stateScope,\n )\n })\n}\n\nasync function runCandidateUpdateLifecycle(\n runId: string,\n candidate: KnowledgeImprovementCandidateRecord,\n candidateRoot: string,\n options: KnowledgeImprovementOptions,\n now: () => Date,\n): Promise<RunRagKnowledgeImprovementLoopResult | undefined> {\n if (!shouldRunUpdateStage(options)) return undefined\n const lifecycle = await runRagKnowledgeImprovementLoop({\n goal: options.goal,\n diagnose: options.diagnose,\n acquireKnowledge: options.acquireKnowledge,\n knowledgeResearch: candidateKnowledgeResearchOptions(candidateRoot, options),\n updateKnowledge: candidateUpdateHook(runId, candidate, candidateRoot, options),\n enabledPhases: selectedStagePhases(options, UPDATE_PHASES),\n requiredPhases: selectedStageRequiredPhases(options, UPDATE_PHASES),\n signal: options.signal,\n now,\n })\n return lifecycle\n}\n\nasync function runCandidateEvaluationLifecycle(\n runId: string,\n runDir: string,\n candidate: KnowledgeImprovementCandidateRecord,\n candidateRoot: string,\n candidateHash: string,\n lifecycle: RunRagKnowledgeImprovementLoopResult | undefined,\n options: KnowledgeImprovementOptions,\n now: () => Date,\n): Promise<RunRagKnowledgeImprovementLoopResult | undefined> {\n if (!shouldRunEvaluationStage(options)) return undefined\n const candidateIndex = await buildKnowledgeIndex(candidateRoot, options.stateScope)\n return withBaselineSnapshot(\n runDir,\n candidate.baseHash,\n (baselineRoot) =>\n runRagKnowledgeImprovementPhases(\n {\n goal: options.goal,\n optimization: options.ragOptimization\n ? {\n ...options.ragOptimization,\n executionRef: candidateExecutionRef(\n options.ragOptimization.executionRef,\n candidateHash,\n ),\n runDir:\n options.ragOptimization.runDir ??\n join(runDir, 'rag-optimization', candidate.candidateId),\n run: (input) =>\n options.ragOptimization!.run({\n ...input,\n runId,\n iteration: candidate.iteration,\n candidateId: candidate.candidateId,\n root: candidateRoot,\n baselineRoot,\n candidateRoot,\n candidateIndex,\n baseHash: candidate.baseHash,\n }),\n }\n : undefined,\n retrieval: options.retrieval\n ? {\n ...options.retrieval,\n executionRef: candidateExecutionRef(options.retrieval.executionRef, candidateHash),\n index: candidateIndex,\n runDir:\n options.retrieval.runDir ?? join(runDir, 'retrieval', candidate.candidateId),\n }\n : undefined,\n evaluateAnswers: options.evaluateAnswers,\n answerQualityCostCeiling: options.answerQualityCostCeiling,\n decidePromotion: options.decidePromotion,\n enabledPhases: selectedStagePhases(options, EVALUATION_PHASES),\n requiredPhases: selectedStageRequiredPhases(options, EVALUATION_PHASES),\n signal: options.signal,\n now,\n },\n lifecycle,\n ),\n options.stateScope,\n )\n}\n\nfunction candidateExecutionRef(executionRef: string, candidateHash: string): string {\n return `sha256:${sha256(`${executionRef}\\n${candidateHash}`)}`\n}\n\nfunction candidateKnowledgeResearchOptions(\n candidateRoot: string,\n options: KnowledgeImprovementOptions,\n): RagKnowledgeResearchOptions | undefined {\n if (!options.step && !options.knowledgeResearch) return undefined\n const { step: researchStep, ...rest } = options.knowledgeResearch ?? {}\n const step = options.step ?? researchStep\n return {\n ...rest,\n root: candidateRoot,\n pagesDirectory: normalizeKnowledgeStateScope(options.stateScope).pagesDirectory,\n step,\n maxIterations:\n rest.maxIterations ?? (step ? (options.candidateResearchIterations ?? 3) : undefined),\n strict: rest.strict ?? options.strict,\n readinessSpecs: rest.readinessSpecs ?? options.readinessSpecs,\n readinessTaskId: rest.readinessTaskId ?? options.readinessTaskId,\n readiness: rest.readiness ?? options.readiness,\n }\n}\n\nfunction candidateUpdateHook(\n runId: string,\n candidate: KnowledgeImprovementCandidateRecord,\n candidateRoot: string,\n options: KnowledgeImprovementOptions,\n): RunRagKnowledgeImprovementLoopOptions['updateKnowledge'] {\n if (!options.updateKnowledge) return undefined\n return (input) =>\n options.updateKnowledge!({\n ...input,\n runId,\n iteration: candidate.iteration,\n candidateId: candidate.candidateId,\n root: candidateRoot,\n baselineRoot: options.root,\n candidateRoot,\n baseHash: candidate.baseHash,\n })\n}\n\nfunction shouldRunUpdateStage(options: KnowledgeImprovementOptions): boolean {\n const phases = selectedStagePhases(options, UPDATE_PHASES)\n if (phases.length === 0) return false\n return Boolean(\n (phases.includes('gap-diagnosis') && options.diagnose) ||\n (phases.includes('knowledge-acquisition') && options.acquireKnowledge) ||\n (phases.includes('knowledge-update') &&\n (options.step || options.knowledgeResearch || options.updateKnowledge)) ||\n selectedStageRequiredPhases(options, UPDATE_PHASES).length > 0,\n )\n}\n\nfunction shouldRunEvaluationStage(options: KnowledgeImprovementOptions): boolean {\n const phases = selectedStagePhases(options, EVALUATION_PHASES)\n if (phases.length === 0) return false\n return Boolean(\n (phases.includes('rag-optimization') && options.ragOptimization) ||\n (phases.includes('retrieval-tuning') && options.retrieval) ||\n (phases.includes('answer-quality') && options.evaluateAnswers) ||\n (phases.includes('promotion') && options.decidePromotion) ||\n options.evaluate ||\n selectedStageRequiredPhases(options, EVALUATION_PHASES).length > 0,\n )\n}\n\nfunction selectedStagePhases(\n options: Pick<KnowledgeImprovementOptions, 'enabledPhases'>,\n stagePhases: readonly RagKnowledgeImprovementPhase[],\n): RagKnowledgeImprovementPhase[] {\n const requested = options.enabledPhases ?? stagePhases\n return requested.filter((phase) => stagePhases.includes(phase))\n}\n\nfunction selectedStageRequiredPhases(\n options: Pick<KnowledgeImprovementOptions, 'requiredPhases'>,\n stagePhases: readonly RagKnowledgeImprovementPhase[],\n): RagKnowledgeImprovementPhase[] {\n return (options.requiredPhases ?? []).filter((phase) => stagePhases.includes(phase))\n}\n\nasync function evaluateCandidate(\n runDir: string,\n state: KnowledgeImprovementRunState,\n candidate: KnowledgeImprovementCandidateRecord,\n snapshot: { root: string; hash: string },\n lifecycle: RunRagKnowledgeImprovementLoopResult | undefined,\n options: KnowledgeImprovementOptions,\n now: () => Date,\n useConfiguredEvaluator: boolean,\n): Promise<{\n candidate: KnowledgeImprovementCandidateRecord\n evaluation: KnowledgeImprovementMetric\n}> {\n return withBaselineSnapshot(\n runDir,\n state.baseHash,\n async (baselineRoot) => {\n const [baselineIndex, candidateIndex] = await Promise.all([\n buildKnowledgeIndex(baselineRoot, options.stateScope),\n buildKnowledgeIndex(snapshot.root, options.stateScope),\n ])\n const validation = validateKnowledgeIndex(candidateIndex, { strict: options.strict })\n const readiness = readinessFor(options, candidateIndex)\n const kbQuality = scoreKnowledgeBaseIndex(candidateIndex, {\n strict: options.strict,\n ...options.kbQuality,\n })\n const candidateHash = snapshot.hash\n const evaluator = useConfiguredEvaluator ? options.evaluate : options.evaluateDevelopment\n const configuredMetric = evaluator\n ? evaluator({\n runId: state.runId,\n iteration: candidate.iteration,\n root: options.root,\n baselineRoot,\n candidateRoot: snapshot.root,\n baselineIndex,\n candidateIndex,\n baseHash: state.baseHash,\n candidateHash,\n validation,\n readiness,\n kbQuality,\n lifecycle,\n signal: options.signal,\n })\n : undefined\n const metric =\n configuredMetric ??\n defaultKnowledgeImprovementMetric(\n validation,\n readiness,\n options.readinessSpecs,\n kbQuality,\n lifecycle,\n )\n const evaluation = applyLifecycleFailures(\n normalizeMetric(await metric),\n lifecycle,\n options.answerQualityCostCeiling,\n )\n const measuredHash = await hashKnowledgeBase(snapshot.root, options.stateScope)\n if (measuredHash !== candidateHash) {\n throw new Error(\n `knowledge candidate changed during evaluation: expected ${candidateHash}, got ${measuredHash}`,\n )\n }\n candidate.candidateHash = candidateHash\n candidate.promotionPlanHash = knowledgeFileTransactionPlanHash(\n await knowledgeFilePlanEntries(baselineRoot, snapshot.root, options.stateScope),\n normalizeKnowledgeStateScope(options.stateScope).pagesDirectory,\n options.stateScope?.researchState,\n )\n const evidence = KnowledgeImprovementEvidenceSchema.parse(\n JSON.parse(\n JSON.stringify({\n kind: 'knowledge-improvement-evidence',\n runId: state.runId,\n candidateId: candidate.candidateId,\n iteration: candidate.iteration,\n goalHash: sha256(state.goal),\n implementationRef: state.implementationRef,\n baseHash: candidate.baseHash,\n candidateHash,\n promotionPlanHash: candidate.promotionPlanHash,\n validation,\n readiness: readiness ?? null,\n kbQuality,\n evaluation,\n lifecycle: lifecycle ?? null,\n }),\n ),\n )\n candidate.evidenceHash = contentHash(evidence)\n candidate.updatedAt = now().toISOString()\n await writeJsonDurableWithinRoot(\n runDir,\n candidateEvidenceRelativePath(candidate.candidateId),\n evidence,\n )\n await appendLedger(runDir, {\n type: 'candidate.evaluated',\n runId: state.runId,\n candidateId: candidate.candidateId,\n score: evaluation.score,\n passed: evaluation.passed,\n })\n return { candidate, evaluation }\n },\n options.stateScope,\n )\n}\n\nfunction defaultKnowledgeImprovementMetric(\n validation: ValidateKnowledgeResult,\n readiness: EvalKnowledgeBundleBuildResult | undefined,\n readinessSpecs: readonly KnowledgeReadinessSpec[] | undefined,\n kbQuality: KnowledgeBaseQualityReport,\n lifecycle: RunRagKnowledgeImprovementLoopResult | undefined,\n): KnowledgeImprovementMetric {\n const blockingMissing = readiness?.report.blockingMissingRequirements.length ?? 0\n const blockingTotal = readinessSpecs?.filter((spec) => spec.importance === 'blocking').length ?? 0\n const dimensions: Record<string, number> = {\n validation: validation.ok ? 1 : 0,\n kb_quality: kbQuality.ok ? 1 : 0,\n ...(blockingTotal > 0\n ? { blocking_readiness: Math.max(0, blockingTotal - blockingMissing) / blockingTotal }\n : {}),\n ...(lifecycle?.answerQuality\n ? { answer_quality: mean(Object.values(lifecycle.answerQuality.metrics)) }\n : {}),\n ...(lifecycle?.promotion ? { promotion_decision: lifecycle.promotion.promoted ? 1 : 0 } : {}),\n }\n const failedReasons = [\n validation.ok ? undefined : 'candidate validation failed',\n kbQuality.ok ? undefined : 'candidate KB quality check failed',\n blockingMissing === 0\n ? undefined\n : `${blockingMissing}/${blockingTotal} blocking knowledge requirements still missing`,\n ].filter((reason): reason is string => Boolean(reason))\n return {\n score: mean(Object.values(dimensions)),\n passed: failedReasons.length === 0,\n dimensions,\n notes: [\n failedReasons.length === 0 ? 'candidate passed configured checks' : failedReasons.join('; '),\n !lifecycle?.answerQuality && !lifecycle?.optimization && !lifecycle?.retrieval\n ? 'structural checks only; no task outcome evaluation was performed'\n : undefined,\n ]\n .filter((note): note is string => note !== undefined)\n .join('; '),\n provenance: {\n evaluator: '@tangle-network/agent-knowledge/default-knowledge-improvement-metric',\n version: '2',\n method: 'deterministic',\n },\n }\n}\n\nfunction applyLifecycleFailures(\n metric: KnowledgeImprovementMetric,\n lifecycle: RunRagKnowledgeImprovementLoopResult | undefined,\n answerQualityCostCeiling: number | undefined,\n): KnowledgeImprovementMetric {\n const answerQualityFailures = lifecycle?.answerQuality\n ? ragAnswerEvidenceRejectionReasons(lifecycle.answerQuality, answerQualityCostCeiling)\n : []\n const reasons = [\n metric.notes,\n ...answerQualityFailures,\n lifecycle?.promotion && !lifecycle.promotion.promoted\n ? `promotion decision held: ${lifecycle.promotion.reason}`\n : undefined,\n ].filter((reason): reason is string => Boolean(reason))\n const forcedFailure =\n answerQualityFailures.length > 0 ||\n Boolean(lifecycle?.promotion && !lifecycle.promotion.promoted)\n return {\n ...metric,\n passed: metric.passed && !forcedFailure,\n notes: reasons.length > 0 ? reasons.join('; ') : metric.notes,\n }\n}\n\nfunction normalizeMetric(metric: KnowledgeImprovementMetric): KnowledgeImprovementMetric {\n return improvementMetricSchema.parse(metric)\n}\n","import { canonicalJson } from '@tangle-network/agent-eval'\nimport { isMissingFile } from '../durable-fs'\nimport { normalizeKnowledgeStateScope } from '../knowledge-state-scope'\nimport { withKnowledgeMutation } from '../mutation-lock'\nimport type { RunRagKnowledgeImprovementLoopResult } from '../rag-improvement-loop'\nimport type {\n KnowledgeImprovementCandidateRecord,\n KnowledgeImprovementMetric,\n KnowledgeImprovementOptions,\n KnowledgeImprovementResult,\n} from './contracts'\nimport { DEFAULT_LEASE_TTL_MS, runIdSchema } from './contracts'\nimport { assertKnowledgeImprovementOptions, measureCandidate } from './evaluation'\nimport {\n acquireRunLease,\n appendLedger,\n assertExactCandidatePlatform,\n blockRun,\n findActiveCandidate,\n knowledgeImprovementRunId,\n loadKnowledgeImprovementStateFromRun,\n saveState,\n withKnowledgeImprovementRun,\n} from './state'\nimport {\n assertCandidateEvidence,\n candidateRefFor,\n createBaselineSnapshot,\n createCandidateWorkspace,\n ensureBaselineSnapshot,\n hashKnowledgeBase,\n withBaselineSnapshot,\n} from './workspace'\n\nexport async function improveKnowledgeBase(\n options: KnowledgeImprovementOptions,\n): Promise<KnowledgeImprovementResult> {\n assertExactCandidatePlatform()\n options = {\n ...options,\n ...(options.stateScope === undefined\n ? {}\n : { stateScope: Object.freeze(normalizeKnowledgeStateScope(options.stateScope)) }),\n }\n assertKnowledgeImprovementOptions(options)\n const now = options.now ?? (() => new Date())\n const runId = runIdSchema.parse(\n options.runId ?? knowledgeImprovementRunId(options.root, options.goal),\n )\n return withKnowledgeImprovementRun(options.root, runId, true, (runDir) =>\n improveKnowledgeBaseInRun(options, runId, runDir, now),\n )\n}\n\nasync function improveKnowledgeBaseInRun(\n options: KnowledgeImprovementOptions,\n runId: string,\n runDir: string,\n now: () => Date,\n): Promise<KnowledgeImprovementResult> {\n const lease = await acquireRunLease(runDir, {\n ownerId: options.ownerId ?? `pid-${process.pid}`,\n ttlMs: options.leaseTtlMs ?? DEFAULT_LEASE_TTL_MS,\n })\n\n try {\n lease.assertOwned()\n let state =\n options.resume === false\n ? null\n : await loadKnowledgeImprovementStateFromRun(options.root, runId, runDir).catch((error) => {\n if (isMissingFile(error)) return null\n throw error\n })\n if (!state) {\n const baseHash = await hashKnowledgeBase(options.root, options.stateScope)\n await createBaselineSnapshot(runDir, options.root, baseHash, options.stateScope)\n state = {\n runId,\n root: options.root,\n goal: options.goal,\n implementationRef: options.implementationRef,\n ...(options.stateScope === undefined\n ? {}\n : { stateScope: normalizeKnowledgeStateScope(options.stateScope) }),\n status: 'running',\n baseHash,\n createdAt: now().toISOString(),\n updatedAt: now().toISOString(),\n ownerId: lease.ownerId,\n candidates: [],\n }\n await saveState(runDir, state, options.onState)\n await appendLedger(runDir, { type: 'run.created', runId, baseHash })\n }\n if (\n canonicalJson(normalizeKnowledgeStateScope(state.stateScope)) !==\n canonicalJson(normalizeKnowledgeStateScope(options.stateScope))\n ) {\n throw new Error('knowledge improvement state does not match the requested stateScope')\n }\n if (state.goal !== options.goal) {\n throw new Error('knowledge improvement state does not match the requested goal')\n }\n if (state.implementationRef !== options.implementationRef) {\n throw new Error('knowledge improvement state does not match the requested implementationRef')\n }\n const promotedCandidateId = state.promotedCandidateId\n const promotedCandidate =\n state.status === 'promoted'\n ? state.candidates.find((candidate) => candidate.candidateId === promotedCandidateId)\n : undefined\n if (state.status === 'promoted' && !promotedCandidate) {\n throw new Error('promoted knowledge state has no promoted candidate')\n }\n if (state.status === 'promoted') {\n const promoted = promotedCandidate!\n const promotedState = state\n return withKnowledgeMutation(options.root, async () => {\n const currentHash = await hashKnowledgeBase(options.root, options.stateScope)\n if (currentHash !== promoted.candidateHash) {\n throw new Error(\n `promoted knowledge base changed: expected ${promoted.candidateHash}, got ${currentHash}`,\n )\n }\n const evidence = await assertCandidateEvidence(\n runDir,\n candidateRefFor(runId, promotedState, promoted),\n promotedState.implementationRef,\n )\n return {\n runId,\n state: promotedState,\n candidate: promoted,\n evaluation: evidence.evaluation,\n promoted: true,\n blocked: false,\n }\n })\n }\n await withKnowledgeMutation(options.root, () => undefined)\n await ensureBaselineSnapshot(runDir, options.root, state.baseHash, state.stateScope)\n\n if (state.status === 'blocked') {\n return { runId, state, promoted: false, blocked: true }\n }\n\n const maxCandidates = Math.max(1, options.maxCandidates ?? 1)\n let candidate = findActiveCandidate(state)\n let lastRejectedCandidate: KnowledgeImprovementCandidateRecord | undefined\n let lastRejectedEvaluation: KnowledgeImprovementMetric | undefined\n let lifecycle: RunRagKnowledgeImprovementLoopResult | undefined\n\n while (candidate || state.candidates.length < maxCandidates) {\n if (candidate?.status === 'running' && candidate.finalEvaluationStartedAt) {\n state = await blockRun(\n runDir,\n state,\n `candidate '${candidate.candidateId}' was interrupted after final evaluation started; refusing to reuse final cases`,\n options.onState,\n now,\n )\n return {\n runId,\n state,\n candidate,\n promoted: false,\n blocked: true,\n }\n }\n if (!candidate) {\n const currentHash = await hashKnowledgeBase(options.root, options.stateScope)\n if (currentHash !== state.baseHash) {\n state = await blockRun(\n runDir,\n state,\n `base changed before candidate creation: expected ${state.baseHash}, got ${currentHash}`,\n options.onState,\n now,\n )\n return { runId, state, promoted: false, blocked: true }\n }\n const activeState = state\n candidate = await withBaselineSnapshot(\n runDir,\n activeState.baseHash,\n (baselineRoot) => createCandidateWorkspace(runDir, activeState, baselineRoot, now),\n state.stateScope,\n )\n state.candidates.push(candidate)\n state.status = 'running'\n state.updatedAt = now().toISOString()\n await saveState(runDir, state, options.onState)\n await appendLedger(runDir, {\n type: 'candidate.created',\n runId,\n candidateId: candidate.candidateId,\n iteration: candidate.iteration,\n })\n }\n\n const measured = await measureCandidate(runId, runDir, state, candidate, options, now)\n candidate = measured.candidate\n const evaluation = measured.evaluation\n lifecycle = measured.lifecycle\n\n if (evaluation.passed) {\n candidate.status = 'candidate-ready'\n candidate.updatedAt = now().toISOString()\n state.status = 'candidate-ready'\n state.updatedAt = now().toISOString()\n await saveState(runDir, state, options.onState)\n await appendLedger(runDir, {\n type: 'candidate.ready',\n runId,\n candidateId: candidate.candidateId,\n })\n break\n }\n\n candidate.status = 'rejected'\n state.status = 'running'\n state.updatedAt = now().toISOString()\n await saveState(runDir, state, options.onState)\n await appendLedger(runDir, {\n type: 'candidate.rejected',\n runId,\n candidateId: candidate.candidateId,\n })\n lastRejectedCandidate = candidate\n lastRejectedEvaluation = evaluation\n candidate = undefined\n if (measured.finalEvaluated) break\n }\n\n if (!candidate) {\n state.status = 'rejected'\n state.updatedAt = now().toISOString()\n await saveState(runDir, state, options.onState)\n return {\n runId,\n state,\n candidate: lastRejectedCandidate,\n ...(lastRejectedEvaluation ? { evaluation: lastRejectedEvaluation } : {}),\n lifecycle,\n promoted: false,\n blocked: false,\n }\n }\n\n const evidence = await assertCandidateEvidence(\n runDir,\n candidateRefFor(runId, state, candidate),\n state.implementationRef,\n )\n return {\n runId,\n state,\n candidate,\n evaluation: evidence.evaluation,\n lifecycle,\n promoted: false,\n blocked: false,\n }\n } finally {\n await lease.release()\n }\n}\n","import type {\n DispatchContext,\n OptimizationMethod,\n Scenario,\n} from '@tangle-network/agent-eval/campaign'\nimport type { AgentCandidateJsonValue as JsonValue } from '@tangle-network/agent-interface'\nimport { sha256, stableId } from '../ids'\nimport { assertImmutableRef } from '../immutable-ref'\nimport {\n type RunSerializedKnowledgeOptimizationOptions,\n type RunSerializedKnowledgeOptimizationResult,\n runSerializedKnowledgeOptimization,\n} from '../optimization'\nimport type {\n KnowledgeImprovementOptions,\n KnowledgeImprovementResult,\n KnowledgeImprovementUpdateInput,\n} from './contracts'\nimport { improveKnowledgeBase } from './run'\nimport { hashKnowledgeBase } from './workspace'\n\ntype PolicyCandidateOptions = Omit<\n KnowledgeImprovementOptions,\n | 'root'\n | 'goal'\n | 'implementationRef'\n | 'runId'\n | 'maxCandidates'\n | 'step'\n | 'knowledgeResearch'\n | 'updateKnowledge'\n>\n\ntype PolicyOptimizationBaseOptions<\n TPolicy extends JsonValue,\n TScenario extends Scenario,\n TArtifact,\n> = Omit<\n RunSerializedKnowledgeOptimizationOptions<TPolicy, TScenario, TArtifact>,\n | 'baseline'\n | 'method'\n | 'trainScenarios'\n | 'selectionScenarios'\n | 'finalScenarios'\n | 'executionRef'\n>\n\nexport interface OptimizeKnowledgeBasePolicyOptions<\n TPolicy extends JsonValue,\n TScenario extends Scenario,\n TArtifact,\n> extends PolicyOptimizationBaseOptions<TPolicy, TScenario, TArtifact> {\n root: string\n goal: string\n baselinePolicy: TPolicy\n method: OptimizationMethod<TScenario, TArtifact>\n trainScenarios: readonly TScenario[]\n selectionScenarios: readonly TScenario[]\n finalScenarios: readonly TScenario[]\n /** Commit or content identity for evaluation, applyPolicy, and external dependencies. */\n policyApplicationRef: string\n /** Optional namespace for parallel materialization of the same measured policy. */\n candidateRunLabel?: string\n candidate?: PolicyCandidateOptions\n applyPolicy(\n input: KnowledgeImprovementUpdateInput & {\n policy: TPolicy\n policySurface: string\n policySurfaceHash: string\n optimizationMethod: string\n },\n ): Promise<{\n applied: boolean\n summary: string\n metadata?: Record<string, JsonValue>\n }>\n}\n\nexport interface OptimizeKnowledgeBasePolicyResult<TPolicy extends JsonValue> {\n optimization: RunSerializedKnowledgeOptimizationResult<TPolicy>\n improvement: KnowledgeImprovementResult\n}\n\n/**\n * Optimizes a serialized KB-maintenance policy, then materializes the selected\n * policy in one isolated knowledge candidate. Activation remains explicit.\n */\nexport async function optimizeKnowledgeBasePolicy<\n TPolicy extends JsonValue,\n TScenario extends Scenario,\n TArtifact,\n>(\n options: OptimizeKnowledgeBasePolicyOptions<TPolicy, TScenario, TArtifact>,\n): Promise<OptimizeKnowledgeBasePolicyResult<TPolicy>> {\n const {\n root,\n goal,\n baselinePolicy,\n method,\n trainScenarios,\n selectionScenarios,\n finalScenarios,\n policyApplicationRef,\n candidateRunLabel,\n candidate,\n applyPolicy,\n ...optimizationOptions\n } = options\n if (typeof root !== 'string' || !root.trim()) {\n throw new Error('optimizeKnowledgeBasePolicy root must be non-empty')\n }\n if (typeof goal !== 'string' || !goal.trim()) {\n throw new Error('optimizeKnowledgeBasePolicy goal must be non-empty')\n }\n assertImmutableRef(policyApplicationRef, 'optimizeKnowledgeBasePolicy policyApplicationRef')\n if (\n candidateRunLabel !== undefined &&\n (typeof candidateRunLabel !== 'string' || !candidateRunLabel.trim())\n ) {\n throw new Error('optimizeKnowledgeBasePolicy candidateRunLabel must be non-empty')\n }\n const baseHash = await hashKnowledgeBase(root, candidate?.stateScope)\n const optimization = await runSerializedKnowledgeOptimization({\n ...optimizationOptions,\n executionRef: policyApplicationRef,\n baseline: baselinePolicy,\n method,\n trainScenarios,\n selectionScenarios,\n finalScenarios,\n })\n const winner = optimization.winner\n const currentBaseHash = await hashKnowledgeBase(root, candidate?.stateScope)\n if (currentBaseHash !== baseHash) {\n throw new Error(\n `knowledge base changed during policy optimization: expected ${baseHash}, got ${currentBaseHash}`,\n )\n }\n const runId = stableId(\n 'kbpolicy',\n `${candidateRunLabel ?? 'default'}:${goal}:${optimization.methodName}:${winner.surfaceHash}:${policyApplicationRef}:${baseHash}`,\n )\n const improvement = await improveKnowledgeBase({\n ...(candidate ?? {}),\n root,\n goal,\n implementationRef: `sha256:${sha256(\n `${policyApplicationRef}\\n${winner.surfaceHash}\\n${optimization.methodName}`,\n )}`,\n runId,\n maxCandidates: 1,\n updateKnowledge: async (input) => {\n if (input.baseHash !== baseHash) {\n throw new Error(\n `knowledge base changed before policy materialization: expected ${baseHash}, got ${input.baseHash}`,\n )\n }\n const result = await applyPolicy({\n ...input,\n policy: structuredClone(winner.value),\n policySurface: winner.surface,\n policySurfaceHash: winner.surfaceHash,\n optimizationMethod: optimization.methodName,\n })\n return {\n ...result,\n metadata: {\n ...(result.metadata ?? {}),\n optimization: {\n method: optimization.methodName,\n policySurfaceHash: winner.surfaceHash,\n policyApplicationRef,\n },\n },\n }\n },\n })\n return { optimization, improvement }\n}\n\nexport type KnowledgePolicyDispatch<\n TPolicy extends JsonValue,\n TScenario extends Scenario,\n TArtifact,\n> = (input: {\n candidate: TPolicy\n candidateSurface: string\n candidateSurfaceHash: string\n scenario: TScenario\n context: DispatchContext\n}) => Promise<TArtifact>\n","import { createHash } from 'node:crypto'\nimport { join } from 'node:path'\nimport { canonicalJson, contentHash } from '@tangle-network/agent-eval'\nimport type { AgentCandidateJsonValue as JsonValue } from '@tangle-network/agent-interface'\nimport { z } from 'zod'\nimport { isMissingFile, readRegularFileWithinRoot, writeJsonDurableWithinRoot } from '../durable-fs'\nimport {\n applyKnowledgeFileTransaction,\n assertKnowledgeMutationPath,\n finishKnowledgeFileTransaction,\n type KnowledgeFileMutation,\n type KnowledgeFileTransaction,\n type KnowledgeFileTransactionPlanEntry,\n knowledgeFileTransactionPlanHash,\n prepareKnowledgeFileTransaction,\n} from '../file-transaction'\nimport { stableId } from '../ids'\nimport { writeKnowledgeIndex } from '../indexer'\nimport { type KnowledgeStateScope, normalizeKnowledgeStateScope } from '../knowledge-state-scope'\nimport { withKnowledgeMutation } from '../mutation-lock'\nimport { normalizePagesDirectory } from '../pages-directory'\nimport type { RagKnowledgeImprovementPhase } from '../rag-improvement-loop'\nimport type {\n KnowledgeImprovementCandidateRef,\n KnowledgeImprovementOptions,\n KnowledgeImprovementResult,\n} from './contracts'\nimport {\n EVALUATION_PHASES,\n immutableRefSchema,\n KB_IMPROVEMENT_PAGES_DIRECTORY,\n KnowledgeImprovementCandidateRefSchema,\n safePathSegmentSchema,\n} from './contracts'\nimport { improveKnowledgeBase } from './run'\nimport { knowledgeImprovementRunDir } from './state'\nimport { knowledgeFilePlanEntries } from './transition'\nimport { hashKnowledgeBase, withKnowledgeImprovementComparison } from './workspace'\n\nconst selectionPathSchema = z\n .string()\n .min(1)\n .transform((path, context) => {\n try {\n try {\n return assertKnowledgeMutationPath(path, KB_IMPROVEMENT_PAGES_DIRECTORY, true)\n } catch {\n return normalizePagesDirectory(path)\n }\n } catch (error) {\n context.addIssue({\n code: 'custom',\n message: error instanceof Error ? error.message : String(error),\n })\n return z.NEVER\n }\n })\nconst selectionMetadataSchema = z.record(z.string(), z.json())\nconst measuredSelectionLifecycleSchema = z\n .object({\n kind: z.literal('measured-knowledge-change-selection'),\n version: z.literal(1),\n selectionDigest: z.string().regex(/^[a-f0-9]{64}$/),\n sourceCandidateId: z.string().min(1),\n sourceEvidenceHash: z.string().regex(/^[a-f0-9]{64}$/),\n sourcePlanHash: z.string().regex(/^[a-f0-9]{64}$/),\n selectedPaths: z.array(selectionPathSchema),\n selectedCandidateHash: z.string().regex(/^[a-f0-9]{64}$/),\n selectedPlanHash: z.string().regex(/^[a-f0-9]{64}$/),\n })\n .strict()\nconst measuredSelectionReceiptSchema = z\n .object({\n kind: z.literal('measured-knowledge-change-selection-receipt'),\n version: z.literal(1),\n receiptHash: z.string().regex(/^[a-f0-9]{64}$/),\n selectionDigest: z.string().regex(/^[a-f0-9]{64}$/),\n sourceCandidate: KnowledgeImprovementCandidateRefSchema,\n sourcePlanHash: z.string().regex(/^[a-f0-9]{64}$/),\n selectedPaths: z.array(selectionPathSchema),\n derivedImplementationRef: immutableRefSchema,\n runId: z.string().min(1),\n derivedCandidateId: z.string().min(1),\n derivedCandidateStatus: z.string().min(1),\n selectedCandidateHash: z.string().regex(/^[a-f0-9]{64}$/),\n selectedPlanHash: z.string().regex(/^[a-f0-9]{64}$/),\n selectedEvidenceHash: z.string().regex(/^[a-f0-9]{64}$/),\n rationale: z.string().trim().min(1).optional(),\n metadata: selectionMetadataSchema.optional(),\n })\n .strict()\n\nexport type KnowledgeEvaluationPhase = Exclude<\n RagKnowledgeImprovementPhase,\n 'knowledge-acquisition' | 'knowledge-update'\n>\n\nexport interface ImproveSelectedKnowledgeCandidateOptions\n extends Omit<\n KnowledgeImprovementOptions,\n | 'root'\n | 'goal'\n | 'implementationRef'\n | 'runId'\n | 'step'\n | 'knowledgeResearch'\n | 'acquireKnowledge'\n | 'updateKnowledge'\n | 'enabledPhases'\n | 'requiredPhases'\n > {\n root: string\n goal: string\n /** Identity of the helper, policy, or human procedure choosing the subset. */\n implementationRef: string\n /** Previously measured whole candidate from which the subset is derived. */\n sourceCandidate: KnowledgeImprovementCandidateRef\n /** Exact changed file paths to carry into the derived candidate. */\n selectedPaths: readonly string[]\n /** Optional explicit run identity. The default includes the selection digest. */\n runId?: string\n /** Human-readable reason for selecting this subset. */\n rationale?: string\n /** JSON-safe policy output retained in the selection receipt. */\n selectionMetadata?: Record<string, JsonValue>\n /** Diagnosis and evaluation phases. `knowledge-update` is inserted by this helper. */\n enabledEvaluationPhases?: readonly KnowledgeEvaluationPhase[]\n /** Diagnosis and evaluation phases that must complete. `knowledge-update` is always required. */\n requiredEvaluationPhases?: readonly KnowledgeEvaluationPhase[]\n}\n\nexport type MeasuredKnowledgeSelectionReceipt = z.infer<typeof measuredSelectionReceiptSchema>\n\nexport interface ImproveSelectedKnowledgeCandidateResult extends KnowledgeImprovementResult {\n selection: MeasuredKnowledgeSelectionReceipt\n}\n\n/**\n * Derive a subset from an already measured candidate, then measure the subset as\n * a new candidate before it can be promoted.\n *\n * Directly filtering an activation plan is unsafe: a whole candidate can pass\n * while one page subset breaks links, removes supporting sources, or changes a\n * readiness score. This helper instead applies the chosen changed paths to an\n * isolated baseline, recomputes the index, runs the ordinary improvement\n * evaluator, and returns the ordinary candidate reference. Promotion therefore\n * remains one path and can never admit an unmeasured hybrid.\n */\nexport async function improveSelectedKnowledgeCandidate(\n options: ImproveSelectedKnowledgeCandidateOptions,\n): Promise<ImproveSelectedKnowledgeCandidateResult> {\n const sourceCandidate = Object.freeze(\n KnowledgeImprovementCandidateRefSchema.parse(options.sourceCandidate),\n )\n const requestedImplementationRef = immutableRefSchema.parse(options.implementationRef)\n const enabledEvaluationPhases = normalizeEvaluationPhases(\n options.enabledEvaluationPhases ?? ['gap-diagnosis', ...EVALUATION_PHASES],\n 'enabledEvaluationPhases',\n )\n const requiredEvaluationPhases = normalizeEvaluationPhases(\n options.requiredEvaluationPhases ?? [],\n 'requiredEvaluationPhases',\n )\n const metadata = options.selectionMetadata\n ? selectionMetadataSchema.parse(structuredClone(options.selectionMetadata))\n : undefined\n\n return withKnowledgeImprovementComparison(\n { root: options.root, candidate: sourceCandidate },\n async (source) => {\n const scope = normalizeKnowledgeStateScope(source.stateScope)\n if (\n options.stateScope !== undefined &&\n canonicalJson(normalizeKnowledgeStateScope(options.stateScope)) !== canonicalJson(scope)\n ) {\n throw new Error('selected knowledge candidate stateScope differs from its source')\n }\n const sourcePlan = await knowledgeFilePlanEntries(\n source.baseline.root,\n source.candidate.root,\n scope,\n )\n const sourcePlanHash = knowledgeFileTransactionPlanHash(\n sourcePlan,\n scope.pagesDirectory,\n scope.researchState,\n )\n if (sourcePlanHash !== sourceCandidate.promotionPlanHash) {\n throw new Error('source knowledge candidate plan no longer matches its measured identity')\n }\n const changedSourcePlan = sourcePlan\n .filter(planEntryChanged)\n .filter((entry) => notDerivedPath(entry, scope))\n const selectedPaths = normalizeSelectedPaths(options.selectedPaths, changedSourcePlan, scope)\n const selectionMaterial = immutableJson({\n kind: 'measured-knowledge-change-selection' as const,\n version: 1 as const,\n sourceCandidate,\n sourcePlanHash,\n selectedPaths,\n ...(options.rationale?.trim() ? { rationale: options.rationale.trim() } : {}),\n ...(metadata ? { metadata } : {}),\n })\n const selectionDigest = contentHash(selectionMaterial)\n const derivedImplementationRef = immutableRefSchema.parse(\n `sha256:${contentHash({\n engine: 'agent-knowledge/measured-selection-v1',\n implementationRef: requestedImplementationRef,\n selectionDigest,\n })}`,\n )\n const runId =\n options.runId ??\n stableId(\n 'kimpsel',\n canonicalJson({\n root: options.root,\n goal: options.goal,\n derivedImplementationRef,\n selectionDigest,\n }),\n )\n const selectedEntries = selectedPaths.map((path) => {\n const entry = changedSourcePlan.find((candidate) => candidate.path === path)\n if (!entry) throw new Error(`selected knowledge path disappeared: ${path}`)\n return entry\n })\n const selectionMutationPlanHash = knowledgeFileTransactionPlanHash(\n selectedEntries,\n scope.pagesDirectory,\n scope.researchState,\n )\n let lifecycleSelection: z.infer<typeof measuredSelectionLifecycleSchema> | undefined\n\n const result = await improveKnowledgeBase({\n ...improvementOptions(options),\n root: options.root,\n stateScope: scope,\n goal: options.goal,\n implementationRef: derivedImplementationRef,\n runId,\n enabledPhases: ['knowledge-update', ...enabledEvaluationPhases],\n requiredPhases: ['knowledge-update', ...requiredEvaluationPhases],\n async updateKnowledge(input) {\n const purpose = `knowledge-selected-candidate:${selectionDigest}`\n const recoveryOwner = `knowledge-selected-candidate:${sourceCandidate.candidateId}`\n await withKnowledgeMutation(\n input.candidateRoot,\n async (lock) => {\n lock.assertOwned()\n if (!lock.recovery && selectedEntries.length > 0) {\n const transaction = await prepareKnowledgeFileTransaction({\n root: input.candidateRoot,\n transactionRoot: lock.transactionRoot,\n purpose,\n ...scope,\n recoveryOwner,\n mutations: await selectionMutations(source.candidate.root, selectedEntries),\n now: options.now,\n })\n if (transaction) {\n assertSelectionTransaction(transaction, selectionMutationPlanHash)\n await applyKnowledgeFileTransaction({\n root: input.candidateRoot,\n transactionRoot: lock.transactionRoot,\n transaction,\n beforeCommit: lock.assertOwned,\n })\n await finishKnowledgeFileTransaction({\n root: input.candidateRoot,\n transactionRoot: lock.transactionRoot,\n transaction,\n assertOwned: lock.assertOwned,\n })\n }\n }\n await writeKnowledgeIndex(input.candidateRoot, scope)\n lock.assertOwned()\n },\n {\n resumeTransaction: {\n purpose,\n recoveryOwner,\n validate: (transaction) =>\n assertSelectionTransaction(transaction, selectionMutationPlanHash),\n },\n },\n )\n\n const selectedPlan = await knowledgeFilePlanEntries(\n source.baseline.root,\n input.candidateRoot,\n scope,\n )\n assertExactSelectedChanges(selectedPlan, selectedPaths, scope)\n const selectedPlanHash = knowledgeFileTransactionPlanHash(\n selectedPlan,\n scope.pagesDirectory,\n scope.researchState,\n )\n const selectedCandidateHash = await hashKnowledgeBase(input.candidateRoot, scope)\n lifecycleSelection = measuredSelectionLifecycleSchema.parse({\n kind: 'measured-knowledge-change-selection',\n version: 1,\n selectionDigest,\n sourceCandidateId: sourceCandidate.candidateId,\n sourceEvidenceHash: sourceCandidate.evidenceHash,\n sourcePlanHash,\n selectedPaths,\n selectedCandidateHash,\n selectedPlanHash,\n })\n return {\n applied: selectedPaths.length > 0,\n summary:\n selectedPaths.length > 0\n ? `Applied ${selectedPaths.length} selected measured change(s).`\n : 'Selected no changes; measuring the exact baseline as a null candidate.',\n metadata: { selection: lifecycleSelection },\n }\n },\n })\n\n const candidate = result.candidate\n if (!candidate?.candidateHash || !candidate.promotionPlanHash || !candidate.evidenceHash) {\n throw new Error('selected knowledge candidate did not produce measured candidate evidence')\n }\n const recordedSelection = measuredSelectionLifecycleSchema.parse(\n result.lifecycle?.knowledgeUpdate?.metadata?.selection ?? lifecycleSelection,\n )\n if (\n recordedSelection.selectionDigest !== selectionDigest ||\n recordedSelection.selectedCandidateHash !== candidate.candidateHash ||\n recordedSelection.selectedPlanHash !== candidate.promotionPlanHash ||\n canonicalJson(recordedSelection.selectedPaths) !== canonicalJson(selectedPaths)\n ) {\n throw new Error('selected knowledge candidate evidence does not bind the measured subset')\n }\n\n const receiptWithoutHash = immutableJson({\n kind: 'measured-knowledge-change-selection-receipt' as const,\n version: 1 as const,\n selectionDigest,\n sourceCandidate,\n sourcePlanHash,\n selectedPaths,\n derivedImplementationRef,\n runId: result.runId,\n derivedCandidateId: candidate.candidateId,\n derivedCandidateStatus: candidate.status,\n selectedCandidateHash: candidate.candidateHash,\n selectedPlanHash: candidate.promotionPlanHash,\n selectedEvidenceHash: candidate.evidenceHash,\n ...(options.rationale?.trim() ? { rationale: options.rationale.trim() } : {}),\n ...(metadata ? { metadata } : {}),\n })\n const receipt = measuredSelectionReceiptSchema.parse({\n ...receiptWithoutHash,\n receiptHash: contentHash(receiptWithoutHash),\n })\n await persistSelectionReceipt(options.root, receipt)\n return { ...result, selection: receipt }\n },\n )\n}\n\nfunction improvementOptions(\n options: ImproveSelectedKnowledgeCandidateOptions,\n): Omit<\n KnowledgeImprovementOptions,\n | 'root'\n | 'goal'\n | 'implementationRef'\n | 'runId'\n | 'step'\n | 'knowledgeResearch'\n | 'acquireKnowledge'\n | 'updateKnowledge'\n | 'enabledPhases'\n | 'requiredPhases'\n> {\n const {\n root: _root,\n goal: _goal,\n implementationRef: _implementationRef,\n sourceCandidate: _sourceCandidate,\n selectedPaths: _selectedPaths,\n runId: _runId,\n rationale: _rationale,\n selectionMetadata: _selectionMetadata,\n enabledEvaluationPhases: _enabledEvaluationPhases,\n requiredEvaluationPhases: _requiredEvaluationPhases,\n ...rest\n } = options\n return rest\n}\n\nfunction normalizeEvaluationPhases(\n phases: readonly RagKnowledgeImprovementPhase[],\n field: string,\n): KnowledgeEvaluationPhase[] {\n const unique = [...new Set(phases)]\n for (const phase of unique) {\n if (phase === 'knowledge-acquisition' || phase === 'knowledge-update') {\n throw new Error(`${field} cannot contain the selection-owned phase '${phase}'`)\n }\n }\n return unique as KnowledgeEvaluationPhase[]\n}\n\nfunction normalizeSelectedPaths(\n paths: readonly string[],\n changedPlan: readonly KnowledgeFileTransactionPlanEntry[],\n scope: KnowledgeStateScope,\n): string[] {\n const available = new Set(changedPlan.map((entry) => entry.path))\n const selected: string[] = []\n const seen = new Set<string>()\n for (const input of paths) {\n const path = assertKnowledgeMutationPath(\n selectionPathSchema.parse(input),\n normalizeKnowledgeStateScope(scope).pagesDirectory,\n scope.researchState,\n )\n if (!notDerivedPath({ path }, scope)) {\n throw new Error(`derived knowledge path cannot be selected directly: ${path}`)\n }\n if (seen.has(path)) throw new Error(`selected knowledge path is repeated: ${path}`)\n if (!available.has(path)) {\n throw new Error(`selected knowledge path is not a changed source-candidate file: ${path}`)\n }\n seen.add(path)\n selected.push(path)\n }\n return selected.sort((left, right) => left.localeCompare(right))\n}\n\nfunction planEntryChanged(entry: KnowledgeFileTransactionPlanEntry): boolean {\n return (\n entry.beforeHash !== entry.afterHash ||\n (entry.beforeHash !== null && entry.afterHash !== null && entry.beforeMode !== entry.afterMode)\n )\n}\n\nfunction notDerivedPath(entry: { path: string }, scope: KnowledgeStateScope): boolean {\n return entry.path !== `${normalizeKnowledgeStateScope(scope).pagesDirectory}/index.md`\n}\n\nasync function selectionMutations(\n sourceCandidateRoot: string,\n entries: readonly KnowledgeFileTransactionPlanEntry[],\n): Promise<KnowledgeFileMutation[]> {\n return Promise.all(\n entries.map(async (entry) => {\n if (entry.afterHash === null) return { path: entry.path, content: null }\n const file = await readRegularFileWithinRoot(sourceCandidateRoot, entry.path)\n const actualHash = createHash('sha256').update(file.bytes).digest('hex')\n if (actualHash !== entry.afterHash || file.mode !== entry.afterMode) {\n throw new Error(`source candidate changed before subset materialization: ${entry.path}`)\n }\n return { path: entry.path, content: file.bytes, mode: file.mode }\n }),\n )\n}\n\nfunction assertSelectionTransaction(\n transaction: KnowledgeFileTransaction,\n expectedPlanHash: string,\n): void {\n if (\n knowledgeFileTransactionPlanHash(\n transaction.entries,\n normalizePagesDirectory(transaction.pagesDirectory),\n transaction.researchState,\n ) !== expectedPlanHash\n ) {\n throw new Error('selected knowledge transaction does not match its approved path set')\n }\n}\n\nfunction assertExactSelectedChanges(\n plan: readonly KnowledgeFileTransactionPlanEntry[],\n selectedPaths: readonly string[],\n scope: KnowledgeStateScope,\n): void {\n const actual = plan\n .filter(planEntryChanged)\n .filter((entry) => notDerivedPath(entry, scope))\n .map((entry) => entry.path)\n .sort((left, right) => left.localeCompare(right))\n if (canonicalJson(actual) !== canonicalJson(selectedPaths)) {\n throw new Error(\n `selected knowledge candidate changed the wrong files: expected ${selectedPaths.join(', ') || '(none)'}, got ${actual.join(', ') || '(none)'}`,\n )\n }\n}\n\nasync function persistSelectionReceipt(\n root: string,\n receipt: MeasuredKnowledgeSelectionReceipt,\n): Promise<void> {\n const runDir = knowledgeImprovementRunDir(root, receipt.runId)\n const relativePath = join(\n 'candidates',\n safePathSegmentSchema.parse(receipt.derivedCandidateId),\n 'selection.json',\n ).replace(/\\\\/g, '/')\n try {\n const existing = measuredSelectionReceiptSchema.parse(\n JSON.parse((await readRegularFileWithinRoot(runDir, relativePath)).bytes.toString('utf8')),\n )\n if (canonicalJson(existing) !== canonicalJson(receipt)) {\n throw new Error('measured knowledge selection receipt conflicts with durable content')\n }\n return\n } catch (error) {\n if (!isMissingFile(error)) throw error\n }\n await writeJsonDurableWithinRoot(runDir, relativePath, receipt)\n}\n\nfunction immutableJson<T>(value: T): T {\n if (value === null || typeof value !== 'object') return value\n const children: readonly unknown[] = Array.isArray(value)\n ? value\n : Object.values(value as Record<string, unknown>)\n for (const child of children) immutableJson(child)\n return Object.freeze(value)\n}\n","import {\n type AgentCandidateKnowledgeRef,\n sha256DigestSchema,\n} from '@tangle-network/agent-interface'\n\nimport {\n type KnowledgeImprovementCandidateRef,\n KnowledgeImprovementCandidateRefSchema,\n} from './kb-improvement'\n\n/** Convert a measured knowledge candidate into the shared review and execution identity. */\nexport function toAgentCandidateKnowledgeRef(\n candidate: KnowledgeImprovementCandidateRef,\n): AgentCandidateKnowledgeRef {\n const parsed = KnowledgeImprovementCandidateRefSchema.parse(candidate)\n return {\n ...parsed,\n goalHash: prefixedDigest(parsed.goalHash),\n baseHash: prefixedDigest(parsed.baseHash),\n candidateHash: prefixedDigest(parsed.candidateHash),\n evidenceHash: prefixedDigest(parsed.evidenceHash),\n promotionPlanHash: prefixedDigest(parsed.promotionPlanHash),\n }\n}\n\n/** Recover agent-knowledge's candidate identity from the shared contract. */\nexport function fromAgentCandidateKnowledgeRef(\n candidate: AgentCandidateKnowledgeRef,\n): KnowledgeImprovementCandidateRef {\n return KnowledgeImprovementCandidateRefSchema.parse({\n ...candidate,\n goalHash: rawDigest(candidate.goalHash),\n baseHash: rawDigest(candidate.baseHash),\n candidateHash: rawDigest(candidate.candidateHash),\n evidenceHash: rawDigest(candidate.evidenceHash),\n promotionPlanHash: rawDigest(candidate.promotionPlanHash),\n })\n}\n\nfunction prefixedDigest(value: string) {\n return sha256DigestSchema.parse(`sha256:${value}`)\n}\n\nfunction rawDigest(value: string): string {\n return sha256DigestSchema.parse(value).slice('sha256:'.length)\n}\n","import type { KnowledgeFragment } from './sources/types'\n\n/**\n * Change detection across snapshots of one source's fragments.\n *\n * The output drives the continuous-ingestion loop: each `KnowledgeChange`\n * carries the eval dimensions affected (`affectedDimensions`), which an\n * agent-eval campaign scheduler consumes to decide which campaigns to\n * re-run. Three change kinds:\n *\n * - `added` — fragment id appears in `next` but not `prev`.\n * - `removed` — fragment id appears in `prev` but not `next`. Typical\n * trigger: an authority retires a Wex slug, or a state SOS reorganises\n * its forms catalogue.\n * - `modified` — fragment id appears in both, body hash differs. This\n * is the dominant change kind in practice — the Ryan-LLC v. FTC\n * vacatur case manifests as a `modified` on the Wex non-compete\n * fragment, NOT as a removed one.\n *\n * Unverifiable fragments are filtered out before diffing — comparing a\n * captcha-blocked snapshot against a real one would falsely fire every\n * fragment as removed. The caller can inspect the raw lists if they want\n * to surface block-page failures.\n *\n * Within-snapshot duplicate ids are an upstream bug; this function picks\n * the LAST one and emits a diagnostic via the `warnings` field.\n *\n * @stable\n */\n\nexport type KnowledgeChangeKind = 'added' | 'removed' | 'modified'\n\nexport interface KnowledgeChange {\n /** Source-scoped id (matches `KnowledgeFragment.id`). */\n fragmentId: string\n kind: KnowledgeChangeKind\n /**\n * For `added`: full body of the new fragment.\n * For `removed`: full body of the prior fragment.\n * For `modified`: unified-diff-style payload `{ before, after }` body strings.\n */\n diff?: { before?: string; after?: string }\n /**\n * Eval dimensions to re-score. Computed as the union of both fragments'\n * `dimensionHints`. The eval cron treats this as a set of campaign tags.\n */\n affectedDimensions: string[]\n /** URL of the affected authority page (from whichever side has it). */\n url?: string\n /**\n * Source-attested change time. For `modified`, takes the NEXT fragment's\n * `sourceUpdatedAt`. For `removed`, takes the PRIOR fragment's\n * `sourceUpdatedAt`. For `added`, takes the NEXT fragment's\n * `sourceUpdatedAt`. Consumers index changes by this date.\n */\n detectedAt: string\n}\n\nexport interface DetectChangesResult {\n changes: KnowledgeChange[]\n /** Counts by kind — handy for dashboards. */\n summary: { added: number; removed: number; modified: number }\n /** Non-fatal diagnostics (duplicate ids, dropped unverifiable fragments). */\n warnings: string[]\n}\n\nexport interface DetectChangesOptions {\n /**\n * When true (default), unverifiable fragments are dropped from both\n * sides before comparison. Set false ONLY when debugging block-page\n * issues — comparing against unverifiable content emits false\n * `removed`/`modified` changes.\n */\n skipUnverifiable?: boolean\n /**\n * When provided, only changes whose `affectedDimensions` intersect this\n * set are returned. Useful for cron loops that schedule per-dimension\n * eval campaigns and only care about a subset.\n */\n filterDimensions?: string[]\n}\n\nexport function detectChanges(\n prev: KnowledgeFragment[],\n next: KnowledgeFragment[],\n options: DetectChangesOptions = {},\n): DetectChangesResult {\n const skipUnverifiable = options.skipUnverifiable ?? true\n const warnings: string[] = []\n\n const { map: prevMap, warnings: prevWarn } = indexFragments(prev, skipUnverifiable, 'prev')\n const { map: nextMap, warnings: nextWarn } = indexFragments(next, skipUnverifiable, 'next')\n warnings.push(...prevWarn, ...nextWarn)\n\n const changes: KnowledgeChange[] = []\n const seen = new Set<string>()\n\n for (const [id, nextFragment] of nextMap) {\n seen.add(id)\n const prevFragment = prevMap.get(id)\n if (!prevFragment) {\n changes.push({\n fragmentId: id,\n kind: 'added',\n diff: { after: nextFragment.body },\n affectedDimensions: dedup(nextFragment.dimensionHints),\n url: nextFragment.provenance.url,\n detectedAt: nextFragment.provenance.sourceUpdatedAt,\n })\n continue\n }\n if (prevFragment.bodyHash !== nextFragment.bodyHash) {\n changes.push({\n fragmentId: id,\n kind: 'modified',\n diff: { before: prevFragment.body, after: nextFragment.body },\n affectedDimensions: dedup([...prevFragment.dimensionHints, ...nextFragment.dimensionHints]),\n url: nextFragment.provenance.url,\n detectedAt: nextFragment.provenance.sourceUpdatedAt,\n })\n }\n }\n\n for (const [id, prevFragment] of prevMap) {\n if (seen.has(id)) continue\n changes.push({\n fragmentId: id,\n kind: 'removed',\n diff: { before: prevFragment.body },\n affectedDimensions: dedup(prevFragment.dimensionHints),\n url: prevFragment.provenance.url,\n detectedAt: prevFragment.provenance.sourceUpdatedAt,\n })\n }\n\n const filtered = options.filterDimensions\n ? changes.filter((c) => c.affectedDimensions.some((d) => options.filterDimensions?.includes(d)))\n : changes\n\n return {\n changes: filtered,\n summary: {\n added: filtered.filter((c) => c.kind === 'added').length,\n removed: filtered.filter((c) => c.kind === 'removed').length,\n modified: filtered.filter((c) => c.kind === 'modified').length,\n },\n warnings,\n }\n}\n\nfunction indexFragments(\n fragments: KnowledgeFragment[],\n skipUnverifiable: boolean,\n side: string,\n): { map: Map<string, KnowledgeFragment>; warnings: string[] } {\n const map = new Map<string, KnowledgeFragment>()\n const warnings: string[] = []\n let dropped = 0\n for (const fragment of fragments) {\n if (skipUnverifiable && !fragment.provenance.verifiable) {\n dropped += 1\n continue\n }\n if (map.has(fragment.id)) {\n warnings.push(`${side}: duplicate fragment id ${fragment.id} — keeping last`)\n }\n map.set(fragment.id, fragment)\n }\n if (dropped > 0) {\n warnings.push(`${side}: dropped ${dropped} unverifiable fragment(s) before diff`)\n }\n return { map, warnings }\n}\n\nfunction dedup<T>(items: T[]): T[] {\n return [...new Set(items)]\n}\n","export interface ChunkingOptions {\n targetChars: number\n maxChars: number\n minChars: number\n overlapChars: number\n}\n\nexport interface KnowledgeChunk {\n index: number\n text: string\n headingPath: string\n charStart: number\n charEnd: number\n oversized: boolean\n}\n\nconst DEFAULT_OPTIONS: ChunkingOptions = {\n targetChars: 1000,\n maxChars: 1500,\n minChars: 160,\n overlapChars: 180,\n}\n\nexport function chunkMarkdown(\n content: string,\n options?: Partial<ChunkingOptions>,\n): KnowledgeChunk[] {\n const opts = normalizeOptions({ ...DEFAULT_OPTIONS, ...(options ?? {}) })\n const { body, bodyOffset } = stripFrontmatter(content)\n if (body.trim() === '') return []\n\n const sections = splitSections(body, bodyOffset)\n const chunks: KnowledgeChunk[] = []\n for (const section of sections) {\n for (const part of chunkText(section.text, opts)) {\n const start = section.start + part.start\n chunks.push({\n index: chunks.length,\n text: part.text,\n headingPath: section.headingPath,\n charStart: start,\n charEnd: start + part.text.length,\n oversized: part.text.length > opts.maxChars,\n })\n }\n }\n return chunks\n}\n\nexport function stripFrontmatter(content: string): { body: string; bodyOffset: number } {\n const normalized = content.replace(/\\r\\n/g, '\\n')\n if (!normalized.startsWith('---\\n')) return { body: normalized, bodyOffset: 0 }\n const match = /^---\\n[\\s\\S]*?\\n---\\s*\\n?/.exec(normalized)\n if (!match) return { body: normalized, bodyOffset: 0 }\n return { body: normalized.slice(match[0].length), bodyOffset: match[0].length }\n}\n\nfunction normalizeOptions(opts: ChunkingOptions): ChunkingOptions {\n if (opts.maxChars < opts.targetChars) opts.maxChars = opts.targetChars\n if (opts.overlapChars >= opts.targetChars) opts.overlapChars = Math.floor(opts.targetChars / 2)\n return opts\n}\n\ninterface Section {\n text: string\n start: number\n headingPath: string\n}\n\nfunction splitSections(body: string, bodyOffset: number): Section[] {\n const lines = body.split('\\n')\n const sections: Section[] = []\n const headings: Record<number, string> = {}\n let current: { lines: string[]; start: number; headingPath: string } = {\n lines: [],\n start: bodyOffset,\n headingPath: '',\n }\n let cursor = bodyOffset\n let fence: string | null = null\n\n const flush = () => {\n const text = current.lines.join('\\n')\n if (text.trim() !== '')\n sections.push({ text, start: current.start, headingPath: current.headingPath })\n }\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]!\n const lineLen = line.length + (i < lines.length - 1 ? 1 : 0)\n const fenceMatch = /^(`{3,}|~{3,})/.exec(line)\n if (fenceMatch) {\n const marker = fenceMatch[1]!\n fence = fence === null ? marker : line.startsWith(fence) ? null : fence\n current.lines.push(line)\n cursor += lineLen\n continue\n }\n const heading = fence === null ? /^(#{1,6})\\s+(.+?)\\s*$/.exec(line) : null\n if (heading) {\n flush()\n const level = heading[1]!.length\n headings[level] = heading[2]!.trim()\n for (let next = level + 1; next <= 6; next++) delete headings[next]\n current = {\n lines: [line],\n start: cursor,\n headingPath: Object.entries(headings)\n .sort(([a], [b]) => Number(a) - Number(b))\n .map(([levelText, title]) => `${'#'.repeat(Number(levelText))} ${title}`)\n .join(' > '),\n }\n cursor += lineLen\n continue\n }\n current.lines.push(line)\n cursor += lineLen\n }\n flush()\n return sections\n}\n\nfunction chunkText(text: string, opts: ChunkingOptions): Array<{ text: string; start: number }> {\n if (text.length <= opts.targetChars) return [{ text, start: 0 }]\n const atoms = splitAtoms(text)\n const chunks: Array<{ text: string; start: number }> = []\n let buffer = ''\n let bufferStart = 0\n for (const atom of atoms) {\n if (buffer === '') bufferStart = atom.start\n if (buffer.length > 0 && buffer.length + atom.text.length > opts.targetChars) {\n chunks.push({ text: buffer.trimEnd(), start: bufferStart })\n const overlap = buffer.slice(Math.max(0, buffer.length - opts.overlapChars))\n buffer = overlap + atom.text\n bufferStart = Math.max(bufferStart, atom.start - overlap.length)\n } else {\n buffer += atom.text\n }\n }\n if (buffer.trim() !== '') chunks.push({ text: buffer.trimEnd(), start: bufferStart })\n return mergeTinyChunks(chunks, opts)\n}\n\nfunction splitAtoms(text: string): Array<{ text: string; start: number }> {\n const parts: Array<{ text: string; start: number }> = []\n const paragraphs = text.split(/(\\n\\s*\\n)/)\n let cursor = 0\n for (let i = 0; i < paragraphs.length; i += 2) {\n const paragraph = (paragraphs[i] ?? '') + (paragraphs[i + 1] ?? '')\n if (paragraph === '') continue\n parts.push({ text: paragraph, start: cursor })\n cursor += paragraph.length\n }\n return parts\n}\n\nfunction mergeTinyChunks(\n chunks: Array<{ text: string; start: number }>,\n opts: ChunkingOptions,\n): Array<{ text: string; start: number }> {\n const out: Array<{ text: string; start: number }> = []\n for (const chunk of chunks) {\n const prev = out[out.length - 1]\n if (\n prev &&\n chunk.text.length < opts.minChars &&\n prev.text.length + chunk.text.length <= opts.maxChars\n ) {\n prev.text = `${prev.text}\\n\\n${chunk.text}`\n } else {\n out.push({ ...chunk })\n }\n }\n return out\n}\n","import {\n auditCurrentRunCitations,\n type KnowledgeCitationAuditIssue,\n type KnowledgeCitationAuditReport,\n} from './citation-resolution'\nimport type { RunScopedStores } from './run-scoped'\nimport type { KnowledgeLintFinding } from './types'\n\n/** Convert a chain-aware citation audit into the package lint vocabulary. */\nexport function knowledgeCitationAuditFindings(\n report: KnowledgeCitationAuditReport,\n): KnowledgeLintFinding[] {\n return report.issues.map(issueToFinding)\n}\n\n/** Lint only current-run pages against their complete declared visibility chain. */\nexport async function lintCurrentRunCitations(\n stores: RunScopedStores,\n runId: string,\n): Promise<KnowledgeLintFinding[]> {\n return knowledgeCitationAuditFindings(await auditCurrentRunCitations(stores, runId))\n}\n\nfunction issueToFinding(issue: KnowledgeCitationAuditIssue): KnowledgeLintFinding {\n const candidates = issue.candidates.map((candidate) => ({\n pageId: candidate.pageId,\n path: candidate.page.path,\n origin: candidate.origin,\n }))\n if (issue.kind === 'ambiguous') {\n return {\n type: 'ambiguous-citation',\n severity: 'error',\n page: issue.sourcePath,\n message:\n `Citation \"${issue.persistedCitation}\" resolves to ${issue.candidates.length} visible pages; ` +\n 'qualify it as here::<pageId>, inherited:<runId>::<pageId>, or shared::<pageId>.',\n metadata: {\n sourcePageId: issue.sourcePageId,\n sourceOrigin: issue.sourceOrigin,\n candidates,\n },\n }\n }\n return {\n type: 'broken-citation',\n severity: 'error',\n page: issue.sourcePath,\n message:\n issue.kind === 'self'\n ? `Page \"${issue.sourcePageId}\" cites itself through \"${issue.persistedCitation}\".`\n : `Citation \"${issue.persistedCitation}\" resolves to no visible page.`,\n metadata: {\n sourcePageId: issue.sourcePageId,\n sourceOrigin: issue.sourceOrigin,\n candidates,\n },\n }\n}\n","/**\n * The SINGLE-AGENT COLLECTION driver — the blind-collection baseline (Arm A).\n *\n * This is the honest null the depth A/B is measured against. The other drivers\n * spend extra inference to do something differentiated:\n * - `createVerifyingResearchDriver` runs an LLM gate per source (Arm B),\n * - `createResearchDrivingDriver` extracts claims, tracks corroboration, and\n * synthesizes deep follow-up questions to drive depth (Arm C).\n *\n * This driver does NONE of that. It is a pass-through: it accepts every source\n * the worker proposes and contributes no research, no gating, and no steering of\n * its own. The loop still dedups exact-uri duplicates before calling\n * `verifySource` (that is the loop's job, not the driver's), and the default\n * `foldGaps` (a plain bulleted list of the still-open readiness gaps) still folds\n * the gaps into the worker's next prompt — so the worker keeps researching, but\n * NOTHING intelligent sits between the worker and the knowledge base.\n *\n * In other words: ONE agent (the worker) collects sources round after round, and\n * the \"driver\" is an inert rubber stamp. That is exactly what \"single-agent\n * collection\" means — the topology with zero coordinator intelligence — so its\n * material-facts score is the floor every other arm must beat to justify its\n * extra inference cost.\n *\n * It adds NO router calls of its own: `verifySource` is a synchronous accept and\n * `foldGaps` is omitted so the loop uses its built-in gap list. So Arm A's cost\n * is the worker's cost alone — the cleanest possible blind-collection baseline.\n */\n\nimport type {\n ResearchDriver,\n ResearchSourceProposal,\n SourceVerdict,\n} from './verified-research-loop'\n\n/**\n * Build the single-agent collection driver. Accepts every source; never gates,\n * never researches, never steers beyond the loop's default open-gap list. The\n * worker is the only agent that thinks.\n */\nexport function createCollectionResearchDriver(): ResearchDriver {\n return {\n verifySource(_source: ResearchSourceProposal): SourceVerdict {\n return { accept: true }\n },\n }\n}\n","import { isDeepStrictEqual } from 'node:util'\n\nexport interface DiscoveryTask {\n id: string\n goal: string\n query?: string\n sourceHints?: string[]\n metadata?: Record<string, unknown>\n}\n\nexport interface DiscoveryResult {\n taskId: string\n summary: string\n sourceUris?: string[]\n claims?: Array<{ text: string; sourceUri?: string; confidence?: number }>\n followUpTasks?: DiscoveryTask[]\n metadata?: Record<string, unknown>\n}\n\nexport interface KnowledgeDiscoveryWorker {\n run(task: DiscoveryTask, signal?: AbortSignal): Promise<DiscoveryResult> | DiscoveryResult\n}\n\nexport interface KnowledgeDiscoveryDispatcher {\n dispatch(\n tasks: DiscoveryTask[],\n options?: {\n concurrency?: number\n signal?: AbortSignal\n },\n ): Promise<DiscoveryResult[]>\n}\n\nexport type DiscoveryLoopStopReason = 'complete' | 'max-rounds' | 'max-tasks' | 'aborted'\n\nexport interface DiscoveryLoopRound {\n round: number\n tasks: DiscoveryTask[]\n results: DiscoveryResult[]\n queuedFollowUps: DiscoveryTask[]\n}\n\nexport interface DiscoveryLoopResult {\n stopReason: DiscoveryLoopStopReason\n tasksDispatched: number\n results: DiscoveryResult[]\n rounds: DiscoveryLoopRound[]\n /** Tasks retained, not dropped, when a configured limit stops the loop. */\n pendingTasks: DiscoveryTask[]\n /** Structurally identical task identities ignored to prevent cycles. */\n duplicateTaskIds: string[]\n}\n\nexport interface RunDiscoveryLoopOptions {\n dispatcher: KnowledgeDiscoveryDispatcher\n initialTasks: readonly DiscoveryTask[]\n /** Maximum follow-up depth including the initial dispatch. Default 3. */\n maxRounds?: number\n /** Maximum tasks dispatched across all rounds. Default 24. */\n maxTasks?: number\n /** Forwarded to the dispatcher. Default 4. */\n concurrency?: number\n signal?: AbortSignal\n onRound?: (round: DiscoveryLoopRound) => Promise<void> | void\n}\n\n/**\n * Dispatch discovery tasks and recursively pursue worker-proposed follow-ups.\n *\n * The runner owns only bounded scheduling and accounting. Workers own search,\n * source verification, and domain-specific candidate shapes.\n */\nexport async function runDiscoveryLoop(\n options: RunDiscoveryLoopOptions,\n): Promise<DiscoveryLoopResult> {\n const maxRounds = positiveInteger(options.maxRounds ?? 3, 'maxRounds')\n const maxTasks = positiveInteger(options.maxTasks ?? 24, 'maxTasks')\n const concurrency = positiveInteger(options.concurrency ?? 4, 'concurrency')\n const known = new Map<string, DiscoveryTask>()\n const pending: DiscoveryTask[] = []\n const duplicateTaskIds = new Set<string>()\n enqueueTasks(options.initialTasks, known, pending, duplicateTaskIds)\n\n const rounds: DiscoveryLoopRound[] = []\n const results: DiscoveryResult[] = []\n let tasksDispatched = 0\n let aborted = false\n\n while (pending.length > 0 && rounds.length < maxRounds && tasksDispatched < maxTasks) {\n if (options.signal?.aborted) {\n aborted = true\n break\n }\n const capacity = maxTasks - tasksDispatched\n const tasks = pending.splice(0, capacity)\n let dispatched: DiscoveryResult[]\n try {\n dispatched = orderCompleteDispatch(\n tasks,\n await options.dispatcher.dispatch(tasks, {\n concurrency,\n signal: options.signal,\n }),\n )\n } catch (cause) {\n if (!options.signal?.aborted) throw cause\n pending.unshift(...tasks)\n aborted = true\n break\n }\n tasksDispatched += tasks.length\n results.push(...dispatched)\n\n const queuedFollowUps: DiscoveryTask[] = []\n for (const result of dispatched) {\n enqueueTasks(result.followUpTasks ?? [], known, queuedFollowUps, duplicateTaskIds)\n }\n pending.push(...queuedFollowUps)\n const round: DiscoveryLoopRound = {\n round: rounds.length + 1,\n tasks,\n results: dispatched,\n queuedFollowUps,\n }\n rounds.push(round)\n await options.onRound?.(round)\n if (options.signal?.aborted) {\n aborted = true\n break\n }\n }\n\n const stopReason: DiscoveryLoopStopReason = aborted\n ? 'aborted'\n : pending.length === 0\n ? 'complete'\n : tasksDispatched >= maxTasks\n ? 'max-tasks'\n : 'max-rounds'\n return {\n stopReason,\n tasksDispatched,\n results,\n rounds,\n pendingTasks: pending,\n duplicateTaskIds: [...duplicateTaskIds],\n }\n}\n\nexport function createLocalDiscoveryDispatcher(\n worker: KnowledgeDiscoveryWorker,\n): KnowledgeDiscoveryDispatcher {\n return {\n async dispatch(tasks, options = {}) {\n const concurrency = Math.max(1, options.concurrency ?? 4)\n const results: DiscoveryResult[] = []\n let cursor = 0\n async function runNext(): Promise<void> {\n while (cursor < tasks.length) {\n if (options.signal?.aborted) throw new Error('Discovery dispatch aborted')\n const task = tasks[cursor++]!\n results.push(await worker.run(task, options.signal))\n }\n }\n await Promise.all(Array.from({ length: Math.min(concurrency, tasks.length) }, runNext))\n return orderCompleteDispatch(tasks, results)\n },\n }\n}\n\nfunction enqueueTasks(\n tasks: readonly DiscoveryTask[],\n known: Map<string, DiscoveryTask>,\n destination: DiscoveryTask[],\n duplicateTaskIds: Set<string>,\n): void {\n for (const task of tasks) {\n assertTask(task)\n const prior = known.get(task.id)\n if (!prior) {\n known.set(task.id, task)\n destination.push(task)\n continue\n }\n if (!isDeepStrictEqual(prior, task)) {\n throw new Error(`Discovery task id '${task.id}' refers to conflicting tasks`)\n }\n duplicateTaskIds.add(task.id)\n }\n}\n\nfunction assertTask(task: DiscoveryTask): void {\n if (!task.id.trim()) throw new Error('Discovery task id must not be empty')\n if (!task.goal.trim()) throw new Error(`Discovery task '${task.id}' goal must not be empty`)\n}\n\nfunction orderCompleteDispatch(\n tasks: readonly DiscoveryTask[],\n results: readonly DiscoveryResult[],\n): DiscoveryResult[] {\n const order = new Map(tasks.map((task, index) => [task.id, index]))\n const received = new Set<string>()\n for (const result of results) {\n if (!order.has(result.taskId)) {\n throw new Error(`Discovery dispatcher returned unknown task '${result.taskId}'`)\n }\n if (received.has(result.taskId)) {\n throw new Error(`Discovery dispatcher returned task '${result.taskId}' more than once`)\n }\n received.add(result.taskId)\n }\n const missing = tasks.filter((task) => !received.has(task.id)).map((task) => task.id)\n if (missing.length > 0) {\n throw new Error(`Discovery dispatcher omitted tasks: ${missing.join(', ')}`)\n }\n return [...results].sort(\n (a, b) => (order.get(a.taskId) as number) - (order.get(b.taskId) as number),\n )\n}\n\nfunction positiveInteger(value: number, name: string): number {\n if (!Number.isInteger(value) || value < 1) {\n throw new Error(`Discovery loop ${name} must be a positive integer`)\n }\n return value\n}\n","import { buildKnowledgeIndex } from './indexer'\nimport { buildKnowledgeLexicalIndex, type KnowledgeLexicalIndex } from './lexical-index'\nimport { type KnowledgePagesOptions, normalizePagesDirectory } from './pages-directory'\nimport type { RetrievalEvalRetriever, RetrievedKnowledgeHit } from './retrieval-eval'\nimport { searchKnowledge } from './search'\nimport type { KnowledgeIndex, KnowledgeSearchResult } from './types'\n\nexport interface FileSystemSearchProviderOptions extends KnowledgePagesOptions {\n /** Knowledge-base root containing the pages directory and `.agent-knowledge/`. */\n root: string\n /** Optional warm index, useful when the caller already built one. */\n index?: KnowledgeIndex\n /** Default result count for `search()`. Defaults to 10. */\n defaultLimit?: number\n /**\n * `manual` caches the index until `refresh: true` or `invalidate()`.\n * `always` rebuilds from disk on every search.\n */\n refresh?: 'manual' | 'always'\n}\nexport interface FileSystemSearchOptions {\n limit?: number\n refresh?: boolean\n}\n\n/**\n * File-first retrieval over an `agent-knowledge` KB.\n *\n * This is the simple backend for products that want deterministic search over\n * markdown knowledge files before adding embeddings, rerankers, or a vector DB.\n */\nexport class FileSystemSearchProvider {\n readonly root: string\n /** Root-relative directory the provider indexes. */\n readonly pagesDirectory: string\n private index: KnowledgeIndex | undefined\n private lexicalIndex: KnowledgeLexicalIndex | undefined\n private readonly defaultLimit: number\n private readonly refreshMode: 'manual' | 'always'\n\n constructor(options: FileSystemSearchProviderOptions) {\n this.root = options.root\n this.pagesDirectory = normalizePagesDirectory(options.pagesDirectory)\n this.index = options.index\n this.defaultLimit = options.defaultLimit ?? 10\n this.refreshMode = options.refresh ?? 'manual'\n }\n\n async getIndex(options: FileSystemSearchOptions = {}): Promise<KnowledgeIndex> {\n if (this.refreshMode === 'always' || options.refresh || !this.index) {\n this.index = await buildKnowledgeIndex(this.root, { pagesDirectory: this.pagesDirectory })\n this.lexicalIndex = undefined\n }\n return this.index\n }\n\n async search(\n query: string,\n options: FileSystemSearchOptions = {},\n ): Promise<KnowledgeSearchResult[]> {\n const index = await this.getIndex(options)\n if (!this.lexicalIndex) this.lexicalIndex = buildKnowledgeLexicalIndex(index.pages)\n return searchKnowledge(index, query, {\n limit: options.limit ?? this.defaultLimit,\n lexicalIndex: this.lexicalIndex,\n })\n }\n\n async retrieve(\n query: string,\n options: FileSystemSearchOptions = {},\n ): Promise<RetrievedKnowledgeHit[]> {\n const hits = await this.search(query, options)\n return hits.map(hitFromSearchResult)\n }\n\n asRetrievalEvalRetriever(): RetrievalEvalRetriever {\n return async ({ config, scenario, k }) => ({\n hits: await this.retrieve(scenario.query, {\n limit: k,\n refresh: config.refresh === true,\n }),\n })\n }\n\n invalidate(): void {\n this.index = undefined\n this.lexicalIndex = undefined\n }\n}\n\nexport function createFileSystemSearchProvider(\n options: FileSystemSearchProviderOptions,\n): FileSystemSearchProvider {\n return new FileSystemSearchProvider(options)\n}\n\nfunction hitFromSearchResult(result: KnowledgeSearchResult): RetrievedKnowledgeHit {\n return {\n pageId: result.page.id,\n path: result.page.path,\n title: result.page.title,\n rank: result.rank,\n score: result.score,\n normalizedScore: result.normalizedScore,\n sourceIds: result.page.sourceIds,\n snippet: result.snippet,\n }\n}\n","import { readFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { z } from 'zod'\nimport { isMissingFile, writeJsonDurableWithinRoot } from './durable-fs'\nimport { withKnowledgeMutation, withKnowledgeRead } from './mutation-lock'\n\n/**\n * Knowledge freshness store: tracks when each `(workspaceId, sourceId)` pair\n * was last successfully refreshed, and reports staleness against a TTL.\n *\n * The contract is intentionally minimal and supports scheduled refresh loops:\n *\n * ```ts\n * const store = createFileSystemFreshnessStore({ root: '.agent-knowledge' })\n * for (const source of sources) {\n * if (await store.stale({ workspaceId, sourceId: source.id, ttlMs: DAY })) {\n * const fragments = await source.fetch({ cacheDir })\n * await persistFragments(fragments)\n * await store.mark({ workspaceId, sourceId: source.id, when: new Date() })\n * }\n * }\n * ```\n *\n * Per-tenant isolation is enforced by `workspaceId` keying. There is no\n * global mutable state across workspaces.\n *\n * Two adapters ship in-package:\n *\n * - `createFileSystemFreshnessStore`: JSON file under the knowledge root,\n * mirrors the layout convention already used by `sources.json`.\n * - `createD1FreshnessStoreStub`: complete bridge from the `D1Adapter` port\n * to this package's freshness interface. The port can be backed by D1,\n * PostgreSQL, SQLite, or another application-owned store.\n */\n\n/** Identity for one freshness record. */\nexport interface FreshnessKey {\n workspaceId: string\n sourceId: string\n}\n\n/** TTL bound for staleness checks. */\nexport interface FreshnessTtl extends FreshnessKey {\n /** Milliseconds; the record is stale when `Date.now() - last() > ttlMs`. */\n ttlMs: number\n /** Injected clock for deterministic tests; defaults to system time. */\n now?: Date\n}\n\n/** Mark argument. */\nexport interface FreshnessMark extends FreshnessKey {\n when: Date\n /** Optional content hash captured at refresh time; aids debugging. */\n contentHash?: string\n}\n\nexport interface KnowledgeFreshnessStore {\n /** Last refresh time, or null if never refreshed. */\n last(key: FreshnessKey): Promise<Date | null>\n /** Record a successful refresh. */\n mark(input: FreshnessMark): Promise<void>\n /** True iff `last(key)` is null or older than `ttlMs`. */\n stale(input: FreshnessTtl): Promise<boolean>\n /** All records for a workspace. */\n list(workspaceId: string): Promise<FreshnessRecord[]>\n}\n\nexport interface FreshnessRecord {\n workspaceId: string\n sourceId: string\n lastRefreshedAt: string\n contentHash?: string\n}\n\nexport interface FileSystemFreshnessStoreOptions {\n /**\n * Knowledge root. The store writes to `<root>/.agent-knowledge/freshness.json`,\n * mirroring the convention used by `sources.json`.\n */\n root: string\n}\n\nconst freshnessRecordSchema = z\n .object({\n workspaceId: z.string().min(1),\n sourceId: z.string().min(1),\n lastRefreshedAt: z.iso.datetime(),\n contentHash: z.string().min(1).optional(),\n })\n .strict()\nconst freshnessFileSchema = z\n .object({ records: z.record(z.string(), freshnessRecordSchema) })\n .strict()\n\n/**\n * Filesystem-backed implementation. Single JSON file per knowledge root,\n * indexed by `${workspaceId}::${sourceId}`. Reads parse on every call;\n * cron tick rate is well below the cost of one JSON parse.\n *\n * Writes share the package-wide filesystem lock, so multiple workers cannot\n * overwrite one another or run through an interrupted knowledge promotion.\n */\nexport function createFileSystemFreshnessStore(\n options: FileSystemFreshnessStoreOptions,\n): KnowledgeFreshnessStore {\n const path = join(options.root, '.agent-knowledge', 'freshness.json')\n\n const read = async (): Promise<Record<string, FreshnessRecord>> => {\n return withKnowledgeRead(options.root, async () => {\n try {\n return freshnessFileSchema.parse(JSON.parse(await readFile(path, 'utf8'))).records\n } catch (error) {\n if (isMissingFile(error)) return {}\n throw error\n }\n })\n }\n\n const write = async (records: Record<string, FreshnessRecord>): Promise<void> => {\n await writeJsonDurableWithinRoot(\n options.root,\n '.agent-knowledge/freshness.json',\n freshnessFileSchema.parse({ records }),\n )\n }\n\n return {\n async last(key) {\n const records = await read()\n const record = records[buildKey(key)]\n return record ? new Date(record.lastRefreshedAt) : null\n },\n async mark(input) {\n await withKnowledgeMutation(options.root, async () => {\n const records = await read()\n records[buildKey(input)] = {\n workspaceId: input.workspaceId,\n sourceId: input.sourceId,\n lastRefreshedAt: input.when.toISOString(),\n ...(input.contentHash === undefined ? {} : { contentHash: input.contentHash }),\n }\n await write(records)\n })\n },\n async stale(input) {\n const last = await this.last(input)\n if (!last) return true\n const now = input.now ?? new Date()\n return now.getTime() - last.getTime() > input.ttlMs\n },\n async list(workspaceId) {\n const records = await read()\n return Object.values(records).filter((r) => r.workspaceId === workspaceId)\n },\n }\n}\n\n/**\n * Bridge an application-owned database adapter to `KnowledgeFreshnessStore`.\n * The adapter may use D1, PostgreSQL, SQLite, or another durable store.\n *\n * The expected schema:\n *\n * ```sql\n * CREATE TABLE knowledge_freshness (\n * workspace_id TEXT NOT NULL,\n * source_id TEXT NOT NULL,\n * last_refreshed_at TEXT NOT NULL,\n * content_hash TEXT,\n * PRIMARY KEY (workspace_id, source_id)\n * );\n * ```\n */\nexport interface D1Adapter {\n get(workspaceId: string, sourceId: string): Promise<FreshnessRecord | null>\n upsert(record: FreshnessRecord): Promise<void>\n listByWorkspace(workspaceId: string): Promise<FreshnessRecord[]>\n}\n\nexport function createD1FreshnessStoreStub(adapter: D1Adapter): KnowledgeFreshnessStore {\n return {\n async last(key) {\n const record = await adapter.get(key.workspaceId, key.sourceId)\n return record ? new Date(record.lastRefreshedAt) : null\n },\n async mark(input) {\n await adapter.upsert({\n workspaceId: input.workspaceId,\n sourceId: input.sourceId,\n lastRefreshedAt: input.when.toISOString(),\n contentHash: input.contentHash,\n })\n },\n async stale(input) {\n const last = await this.last(input)\n if (!last) return true\n const now = input.now ?? new Date()\n return now.getTime() - last.getTime() > input.ttlMs\n },\n async list(workspaceId) {\n return adapter.listByWorkspace(workspaceId)\n },\n }\n}\n\nfunction buildKey(key: FreshnessKey): string {\n return `${key.workspaceId}::${key.sourceId}`\n}\n","/**\n * Invalidation propagation.\n *\n * A page whose own evidence refuted it carries an `invalidation`. That verdict\n * is invisible to a reader who arrives through a citation, so a page that cites\n * a refuted page records which of its citations are refuted. The pass is\n * planned as a diff, so a store already stamped produces no mutation and the\n * pass can run after every grading round.\n */\nimport { parseKnowledgeCitationReference, resolveKnowledgeCitation } from './citation-resolution'\nimport { formatFrontmatter } from './frontmatter'\nimport type { OriginatedPage } from './run-scoped'\nimport type { KnowledgeId, KnowledgePage } from './types'\n\n/** Frontmatter field naming the cited pages whose evidence refuted them. */\nexport const CITES_INVALIDATED_FIELD = 'citesInvalidated'\n\nexport interface KnowledgeInvalidationStamp {\n readonly page: KnowledgePage\n /** The value the field must hold, sorted and deduplicated. Empty removes the field. */\n readonly citesInvalidated: readonly KnowledgeId[]\n /** The value the page holds now, in the order it is stored. */\n readonly current: readonly KnowledgeId[]\n}\n\nexport interface KnowledgeInvalidationPlan {\n /** Every visible page carrying an invalidation, sorted by id. */\n readonly invalidatedPageIds: readonly KnowledgeId[]\n /** Only the pages whose stamp differs from what they hold, in path order. */\n readonly stamps: readonly KnowledgeInvalidationStamp[]\n}\n\n/**\n * Plan the `citesInvalidated` stamp for every page authored in the target\n * store.\n *\n * Citations resolve over the whole chain, so a page here may be stamped for\n * citing a refuted inherited or shared page. Only `here` pages are stamped: a\n * run does not write the stores it inherits or shares.\n */\nexport function planInvalidationPropagation(\n visiblePages: readonly OriginatedPage[],\n): KnowledgeInvalidationPlan {\n if (!Array.isArray(visiblePages)) {\n throw new TypeError('knowledge invalidation propagation requires the visible pages')\n }\n const invalidatedPageIds = [\n ...new Set(\n visiblePages\n .filter((entry) => entry.page.invalidation !== undefined)\n .map((entry) => entry.page.id),\n ),\n ].sort()\n\n const stamps: KnowledgeInvalidationStamp[] = []\n for (const entry of visiblePages) {\n if (entry.origin !== 'here') continue\n const page = entry.page\n const refuted = new Set<KnowledgeId>()\n for (const persisted of page.cites ?? []) {\n const resolution = resolveKnowledgeCitation(\n visiblePages,\n parseKnowledgeCitationReference(persisted),\n )\n if (resolution.resolved?.page.invalidation !== undefined) {\n refuted.add(resolution.resolved.page.id)\n }\n }\n const citesInvalidated = [...refuted].sort()\n const current = idList(page.frontmatter[CITES_INVALIDATED_FIELD])\n if (sameOrder(current, citesInvalidated)) continue\n stamps.push({ page, citesInvalidated, current })\n }\n stamps.sort((left, right) => left.page.path.localeCompare(right.page.path))\n return { invalidatedPageIds, stamps }\n}\n\n/**\n * Render one plan as a write-block proposal for `applyKnowledgeWriteBlocks`.\n *\n * Only the stamped field changes. The page is rendered through\n * `formatFrontmatter`, so its frontmatter is written in that writer's\n * normalized form.\n */\nexport function formatKnowledgeInvalidationProposal(plan: KnowledgeInvalidationPlan): string {\n return plan.stamps.map((stamp) => renderStampedBlock(stamp)).join('\\n')\n}\n\nfunction renderStampedBlock(stamp: KnowledgeInvalidationStamp): string {\n const frontmatter: Record<string, unknown> = { ...stamp.page.frontmatter }\n if (stamp.citesInvalidated.length === 0) delete frontmatter[CITES_INVALIDATED_FIELD]\n else frontmatter[CITES_INVALIDATED_FIELD] = [...stamp.citesInvalidated]\n const content = formatFrontmatter(frontmatter, stamp.page.text)\n return `---FILE: ${stamp.page.path}---\\n${content.replace(/\\n+$/, '')}\\n---END FILE---`\n}\n\nfunction idList(value: unknown): KnowledgeId[] {\n const values = typeof value === 'string' ? [value] : Array.isArray(value) ? value : []\n return values.filter((item): item is string => typeof item === 'string' && item.trim() !== '')\n}\n\nfunction sameOrder(left: readonly string[], right: readonly string[]): boolean {\n return left.length === right.length && left.every((item, index) => item === right[index])\n}\n","/**\n * HELD-OUT INVESTMENT-RESEARCH EVAL SET.\n *\n * The point of this file is the same FIREWALL the deep-question exam uses\n * (`tests/loops/held-out-exam.ts`): the material facts and their checkable\n * fragments are NEVER shown to a research loop. A loop is told only the company\n * + ticker + a research-as-of CUTOFF date, and asked to write an investment\n * thesis. AFTER it finishes, we grade the thesis it produced against THESE\n * facts — facts it never saw — so a high score is thesis QUALITY (it surfaced\n * the buried, material, non-obvious drivers) and not teaching-to-the-test.\n *\n * Each fact is a DEPTH fact by construction: a single ticker / company-name web\n * search does NOT surface it. They are the things buried in the filings or\n * knowable from then-available primary sources that a thorough analyst flags and\n * a one-shot search misses — customer/revenue/deposit concentration, a debt\n * maturity wall, a margin-trend reversal, a governance / related-party item, a\n * specific competitive or regulatory risk, an off-balance-sheet loss.\n *\n * THREE HARD RULES, enforced by how the data was gathered (see\n * docs/eval/investment-material-facts.md for the per-item provenance + the\n * curation-bias disclosure):\n *\n * 1. SPECIFIC + CHECKABLE. Each fact carries `expected` keyword groups — the\n * specific number / name / phrase — so a deterministic, model-free\n * substring grader (`gradeFactAgainstText`) can score \"did the thesis\n * surface it\". $0, reproducible, and it cannot leak the answer key into a\n * model the loop could observe.\n *\n * 2. DERIVED FROM REAL FETCHED EVIDENCE. Every fact records the primary source\n * it came from (`sourceUrl`, an SEC EDGAR 10-K) and the literal `evidence`\n * value read out of that document. Nothing here is invented; an item that\n * could not be independently sourced was DROPPED, not guessed (the drop log\n * is in the doc).\n *\n * 3. KNOWABLE AT THE CUTOFF. Every fact was disclosed in, or computable from, a\n * document available on or before the company's `cutoff` date. Post-cutoff\n * hindsight (the eventual bankruptcy / collapse) is NOT a checklist item —\n * it is recorded separately as `knownOutcome`, purely for the reader, and is\n * never graded.\n *\n * Grading mirrors the deep-question exam exactly: a fact is SURFACED when the\n * thesis text contains at least `minGroups` of its expected groups; a group is\n * satisfied when ANY of its `anyOf` fragments appears (case-insensitive\n * substring), so a faithful thesis phrased in its own words still grades as a\n * hit. `anyOf` groups model synonyms; the load-bearing tokens are the specific\n * numbers / names.\n */\n\n/** A required answer component: satisfied when any synonym fragment is present. */\nexport interface ExpectedGroup {\n /** Human label for the component (for the doc / audit). */\n label: string\n /** Case-insensitive substring fragments; any one present satisfies the group. */\n anyOf: string[]\n}\n\n/** Lens the fact belongs to — so a set can be checked for category coverage. */\nexport type MaterialFactLens =\n | 'concentration' // customer / revenue / deposit concentration\n | 'leverage' // debt load / maturity wall / interest burden\n | 'margin-trend' // gross/operating margin reversal\n | 'liquidity' // cash burn / negative operating cash flow\n | 'capital-return' // buyback / dividend draining the balance sheet\n | 'governance' // dual-class / related-party / control item\n | 'off-balance-sheet' // unrealized losses not in earnings/equity\n | 'regulatory' // a specific regulatory / legal / recall exposure\n\n/** One held-out material fact with a checkable expected answer + its provenance. */\nexport interface MaterialFact {\n /** Stable id, `ticker/fN`. */\n id: string\n /** Which analyst lens this fact exercises. For coverage + the doc. */\n lens: MaterialFactLens\n /**\n * The material fact, in plain words — for the doc/audit. NEVER shown to a loop.\n * This is the thing a thorough analyst would flag and a ticker search misses.\n */\n fact: string\n /**\n * The checkable answer as required keyword GROUPS. The thesis text must contain\n * at least `minGroups` of these groups (default: all). A group is satisfied\n * when ANY of its `anyOf` fragments appears (case-insensitive substring).\n */\n expected: ExpectedGroup[]\n /**\n * Minimum number of `expected` groups the thesis must contain to count the\n * fact SURFACED. Default = all groups (the strict bar). Lowered (and documented\n * inline) only when the fact is genuinely satisfiable by a subset.\n */\n minGroups?: number\n /**\n * PROVENANCE. The primary source URL this fact was read from — an SEC EDGAR\n * 10-K primary document, fetched live during curation.\n */\n sourceUrl: string\n /**\n * The literal value / phrase read out of `sourceUrl` that grounds the fact.\n * This is the \"cite the actual filing + the value\" requirement — verbatim or\n * near-verbatim from the filing, with the figure.\n */\n evidence: string\n}\n\n/** A company + the cutoff a loop researches as-of + its held-out material facts. */\nexport interface CompanyEvalCase {\n /** Ticker as of the cutoff. */\n ticker: string\n /** Legal name as of the cutoff (what the loop is told to research). */\n company: string\n /** SEC Central Index Key (CIK), zero-stripped — the EDGAR filer id. */\n cik: string\n /**\n * Research-as-of date (ISO). The loop must reason as if it is this date; every\n * `evidence` value was knowable on or before it. >= 18 months before this set\n * was curated, so the outcome is known but is NOT a checklist item.\n */\n cutoff: string\n /** Sector, for coverage / the curation-bias disclosure. */\n sector: string\n /**\n * The known POST-cutoff outcome — recorded for the reader ONLY, never graded.\n * Keeping it out of `facts` is what makes the set hindsight-free.\n */\n knownOutcome: string\n /** The held-out material facts for this company. */\n facts: MaterialFact[]\n}\n\n/**\n * The eval set. 5 public companies, 5-8 held-out material facts each, every fact\n * grounded in a primary SEC EDGAR 10-K filed on or before the cutoff.\n *\n * CURATION-BIAS DISCLOSURE (full version in the doc): all five are companies\n * whose buried risks later materialized, because that is where the material-vs-\n * surface distinction is sharpest AND where the figures are easy to verify after\n * the fact. This biases the set toward downside risks (two of the eight lenses,\n * concentration + leverage, dominate) and toward distressed names. A production\n * eval would balance these with companies whose buried facts were POSITIVE\n * drivers and with survivors. This set is honest about that and reports the lens\n * distribution so the bias is measurable, not hidden.\n */\nexport const investmentThesisSet: CompanyEvalCase[] = [\n {\n ticker: 'SIVB',\n company: 'SVB Financial Group',\n cik: '719739',\n cutoff: '2023-02-24',\n sector: 'Banking',\n knownOutcome:\n 'Failed in a deposit run and was placed in FDIC receivership on March 10, 2023; the holding company filed Chapter 11 on March 17, 2023.',\n facts: [\n {\n id: 'SIVB/f1',\n lens: 'off-balance-sheet',\n fact: 'Held-to-maturity (HTM) securities carried at $91.3B amortized cost had a fair value of only $76.2B — a ~$15.1B unrealized loss that, because the portfolio is HTM, never touched earnings or equity and sat only in the footnotes.',\n expected: [\n {\n label: 'HTM securities',\n anyOf: ['held-to-maturity', 'held to maturity', 'htm'],\n },\n {\n label: 'large unrealized loss (~$15B) / fair value gap',\n anyOf: [\n '15.1',\n '15.2',\n '$15 billion',\n '15 billion',\n '76,169',\n '76.2 billion',\n '91,321',\n 'unrealized loss',\n 'below amortized cost',\n 'fair value',\n ],\n },\n ],\n minGroups: 2,\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/719739/000071973923000021/sivb-20221231.htm',\n evidence:\n 'Balance sheet (Dec 31, 2022): \"Held-to-maturity securities, at amortized cost ... 91,321\" with parenthetical \"(fair value of $ 76,169 ...)\". The gap = $91,321M - $76,169M = ~$15,152M unrealized loss, disclosed only in the notes.',\n },\n {\n id: 'SIVB/f2',\n lens: 'off-balance-sheet',\n fact: \"The HTM unrealized loss (~$15.1B) was roughly equal to the company's entire $16.0B total stockholders' equity — a mark-to-market wipeout hidden by HTM accounting.\",\n expected: [\n {\n label: 'loss near/exceeds total equity',\n anyOf: [\n 'equity',\n 'capital',\n 'insolvent',\n 'wipe out',\n 'exceeds',\n 'nearly all',\n 'tangible book',\n '16,004',\n '16 billion',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/719739/000071973923000021/sivb-20221231.htm',\n evidence:\n '\"Total SVBFG stockholders\\' equity 16,004\" (Dec 31, 2022). The ~$15.15B HTM unrealized loss is ~95% of the $16.0B reported equity.',\n },\n {\n id: 'SIVB/f3',\n lens: 'concentration',\n fact: 'Estimated uninsured deposits in U.S. offices were $151.5B at year-end 2022 — the run-prone funding base; a high share of total deposits exceeded the FDIC limit.',\n expected: [\n {\n label: 'large uninsured deposit base',\n anyOf: [\n 'uninsured deposit',\n 'above the fdic',\n 'exceed the fdic',\n 'exceeds the fdic',\n '151.5',\n '$151 billion',\n 'fdic insurance limit',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/719739/000071973923000021/sivb-20221231.htm',\n evidence:\n '\"As of December 31, 2022 ... the amount of estimated uninsured deposits in U.S. offices that exceed the FDIC insurance limit were $151.5 billion\".',\n },\n {\n id: 'SIVB/f4',\n lens: 'margin-trend',\n fact: 'Cheap noninterest-bearing demand deposits fell 20 percentage points in one year — to 47% of total deposits from 67% — meaning funding costs were set to rise sharply as clients moved to interest-bearing accounts.',\n expected: [\n {\n label: 'deposit mix shift to costlier funding',\n anyOf: [\n 'noninterest-bearing',\n 'non-interest-bearing',\n 'noninterest bearing',\n 'deposit mix',\n 'funding cost',\n 'cost of deposits',\n 'interest-bearing',\n '47 percent',\n '20 percentage',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/719739/000071973923000021/sivb-20221231.htm',\n evidence:\n '\"Noninterest-bearing demand deposits to total deposits decreased by 20 percentage points to 47 percent as of December 31, 2022, compared to ... 2021.\"',\n },\n {\n id: 'SIVB/f5',\n lens: 'concentration',\n fact: 'The deposit and loan base was concentrated in a single client type — the \"innovation economy\" (venture-backed technology and life-science startups) — so a downturn in venture funding would hit deposits and credit simultaneously.',\n expected: [\n {\n label: 'concentration in tech / startups / innovation economy',\n anyOf: [\n 'innovation economy',\n 'technology',\n 'life science',\n 'venture',\n 'startup',\n 'early-stage',\n 'concentrat',\n 'single industry',\n 'sector concentration',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/719739/000071973923000021/sivb-20221231.htm',\n evidence:\n 'The 10-K repeatedly frames the franchise around clients in \"the innovation economy\" (technology, life science / healthcare, and the venture firms that back them) — a single-sector deposit + credit concentration.',\n },\n {\n id: 'SIVB/f6',\n lens: 'off-balance-sheet',\n fact: 'Available-for-sale (AFS) securities of $28.6B amortized cost were marked to a $26.1B fair value — a ~$2.5B loss that DID flow through equity (AOCI), the visible tip of a much larger unrealized-loss iceberg dominated by the footnote-only HTM book.',\n expected: [\n {\n label: 'AFS unrealized loss / AOCI',\n anyOf: [\n 'available-for-sale',\n 'available for sale',\n 'afs',\n 'aoci',\n 'accumulated other comprehensive',\n '28,602',\n '26,069',\n '2.5 billion',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/719739/000071973923000021/sivb-20221231.htm',\n evidence:\n '\"Available-for-sale securities, at fair value (cost of $ 28,602 ...) 26,069\" — a ~$2.5B AFS unrealized loss carried in AOCI, separate from and much smaller than the HTM gap.',\n },\n ],\n },\n {\n ticker: 'BBBY',\n company: 'Bed Bath & Beyond Inc.',\n cik: '886158',\n cutoff: '2022-04-21',\n sector: 'Specialty retail',\n knownOutcome: 'Filed for Chapter 11 bankruptcy on April 23, 2023; shareholders were wiped out.',\n facts: [\n {\n id: 'BBBY/f1',\n lens: 'capital-return',\n fact: 'The company had repurchased ~$11.685B of its own stock since 2004 — including $574.9M in fiscal 2021 alone, \"two years ahead of schedule\" — draining the balance sheet of a business that was losing money.',\n expected: [\n {\n label: 'massive buyback program',\n anyOf: [\n 'repurchas',\n 'buyback',\n 'buy back',\n 'share repurchase',\n '11.685',\n '$11.7 billion',\n '574.9',\n '$575 million',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/886158/000088615822000047/bbby-20220226.htm',\n evidence:\n '\"Since 2004 through the end of Fiscal 2021, we have repurchased approximately $11.685 billion of our common stock\"; FY2021 alone \"completed share repurchases of $574.9 million ... two years ahead of schedule.\"',\n },\n {\n id: 'BBBY/f2',\n lens: 'liquidity',\n fact: 'Operating cash flow collapsed to just $17.9M in FY2021, down from $268.1M and $590.9M in the two prior years — a near-total loss of internally generated cash while it kept buying back stock.',\n expected: [\n {\n label: 'operating cash flow collapse',\n anyOf: [\n 'operating cash flow',\n 'cash from operations',\n 'cash provided by operating',\n 'cash flow from operations',\n '17.9',\n '17,854',\n 'declining cash flow',\n 'cash generation',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/886158/000088615822000047/bbby-20220226.htm',\n evidence:\n 'Statement of cash flows: \"Net cash provided by operating activities 17,854 268,108 590,941\" (FY2021 / FY2020 / FY2019, $ thousands).',\n },\n {\n id: 'BBBY/f3',\n lens: 'liquidity',\n fact: \"Total shareholders' equity fell ~86% in one year — from $1.277B to $174.1M — as losses plus buybacks ate the equity cushion.\",\n expected: [\n {\n label: 'equity erosion',\n anyOf: [\n 'shareholders’ equity',\n \"shareholders' equity\",\n 'stockholders equity',\n 'book value',\n 'equity',\n 'net worth',\n '174.1',\n '174,145',\n 'eroded',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/886158/000088615822000047/bbby-20220226.htm',\n evidence:\n '\"Total shareholders\\' equity 174,145 1,276,936\" (FY2021 vs FY2020, $ thousands) — an ~86% decline in one year.',\n },\n {\n id: 'BBBY/f4',\n lens: 'liquidity',\n fact: 'The company posted a $559.6M net loss in FY2021 — yet spent $574.9M on buybacks the same year, i.e. it returned more cash to shareholders than it had, let alone earned.',\n expected: [\n {\n label: 'net loss FY2021',\n anyOf: [\n 'net loss',\n 'unprofitable',\n 'lost money',\n 'losing money',\n '559.6',\n '559,623',\n '$560 million',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/886158/000088615822000047/bbby-20220226.htm',\n evidence: '\"Net loss $ ( 559,623 )\" for fiscal 2021 ($ thousands).',\n },\n {\n id: 'BBBY/f5',\n lens: 'margin-trend',\n fact: 'Merchandise inventories rose to $1.725B even as sales fell — inventory building into a demand decline, a classic markdown-risk and cash-trap signal.',\n expected: [\n {\n label: 'inventory building into falling demand',\n anyOf: [\n 'inventor',\n 'merchandise inventories',\n 'overstock',\n 'markdown',\n '1,725',\n '1.7 billion',\n 'stockpile',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/886158/000088615822000047/bbby-20220226.htm',\n evidence:\n '\"Merchandise inventories 1,725,410 1,671,909\" ($ thousands) — inventory grew year over year while comparable sales declined.',\n },\n ],\n },\n {\n ticker: 'CVNA',\n company: 'Carvana Co.',\n cik: '1690820',\n cutoff: '2023-02-23',\n sector: 'Auto e-commerce',\n knownOutcome:\n 'The stock fell ~98% from its 2021 peak; the company narrowly avoided bankruptcy via a 2023 debt-exchange that cut and extended its obligations.',\n facts: [\n {\n id: 'CVNA/f1',\n lens: 'leverage',\n fact: 'Total debt had grown to $8.39B by year-end 2022 (from $5.45B) — a debt load far larger than the equity base, built up funding growth and the ADESA deal.',\n expected: [\n {\n label: 'large/growing debt load',\n anyOf: [\n 'total debt',\n 'long-term debt',\n 'leverage',\n 'highly leveraged',\n 'debt load',\n '8,391',\n '8.4 billion',\n '$8.4 billion',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1690820/000169082023000052/cvna-20221231.htm',\n evidence: '\"Total debt 8,391 5,447\" (Dec 31, 2022 vs 2021, $ millions).',\n },\n {\n id: 'CVNA/f2',\n lens: 'leverage',\n fact: 'Interest expense nearly tripled to $486M in 2022 (from $176M) — debt-service was consuming cash a still-unprofitable company did not have.',\n expected: [\n {\n label: 'rising interest burden',\n anyOf: [\n 'interest expense',\n 'interest cost',\n 'debt service',\n 'cost of debt',\n '486',\n 'interest burden',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1690820/000169082023000052/cvna-20221231.htm',\n evidence: '\"Interest expense 486 176\" (FY2022 vs FY2021, $ millions).',\n },\n {\n id: 'CVNA/f3',\n lens: 'leverage',\n fact: \"In May 2022 Carvana bought ADESA's U.S. physical auction business for ~$2.2B in cash — a debt-funded acquisition that stretched the balance sheet right as used-car demand turned.\",\n expected: [\n {\n label: 'ADESA acquisition ~$2.2B',\n anyOf: ['adesa', '2.2 billion', '$2.2 billion', 'physical auction', 'acquisition'],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1690820/000169082023000052/cvna-20221231.htm',\n evidence:\n '\"physical auction business of ADESA US Auction, LLC for approximately $2.2 billion in cash (the \\'ADESA Acquisition\\')\", closed 2022-05-09.',\n },\n {\n id: 'CVNA/f4',\n lens: 'governance',\n fact: 'Carvana leases hubs and properties from DriveTime — a company controlled by founder/CEO Ernest Garcia III and his father Ernest Garcia II — a recurring related-party arrangement with the controlling family.',\n expected: [\n {\n label: 'related-party with founder family / DriveTime',\n anyOf: [\n 'related party',\n 'related-party',\n 'drivetime',\n 'garcia',\n 'controlled by',\n 'affiliate of',\n 'conflict of interest',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1690820/000169082023000052/cvna-20221231.htm',\n evidence:\n 'Related Party Transactions note: lease agreements with \"DriveTime Automotive Group\", a related party \"due to Ernest Garcia II, Ernest Garcia III, and entities controlled by one or both of them\".',\n },\n {\n id: 'CVNA/f5',\n lens: 'liquidity',\n fact: 'The 2022 net loss was $2.894B — a loss far wider than prior years, showing the unit economics had not turned even at scale.',\n expected: [\n {\n label: 'large net loss FY2022',\n anyOf: [\n 'net loss',\n 'unprofitable',\n 'losing money',\n 'cash burn',\n '2,894',\n '2.9 billion',\n '$2.9 billion',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1690820/000169082023000052/cvna-20221231.htm',\n evidence: '\"Net loss $ (2,894 ...\" for fiscal 2022 ($ millions).',\n },\n ],\n },\n {\n ticker: 'PTON',\n company: 'Peloton Interactive, Inc.',\n cik: '1639825',\n cutoff: '2022-09-07',\n sector: 'Consumer fitness hardware',\n knownOutcome:\n 'The stock fell ~95% from its 2021 peak; the founder-CEO departed, the company underwent mass layoffs and a multi-year turnaround through fiscal 2024.',\n facts: [\n {\n id: 'PTON/f1',\n lens: 'margin-trend',\n fact: 'Connected Fitness (hardware) gross margin turned NEGATIVE — to (11)% in FY2022 — meaning Peloton lost money on every bike/tread it sold before any operating cost; revenue growth was masking a broken unit economics.',\n expected: [\n {\n label: 'negative / collapsing hardware gross margin',\n anyOf: [\n 'gross margin',\n 'negative margin',\n 'gross profit',\n 'margin compression',\n 'losing money on each',\n 'below cost',\n '(11)',\n '-11',\n 'negative gross',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1639825/000163982522000117/pton-20220630.htm',\n evidence:\n 'MD&A \"Gross Profit, and Gross Margin\" table: Connected Fitness \"Gross Margin decreased to (11)\" percent in fiscal 2022 — a negative hardware gross margin.',\n },\n {\n id: 'PTON/f2',\n lens: 'liquidity',\n fact: 'Inventories climbed to $1.105B as pandemic demand normalized — a glut of unsold equipment that tied up cash and risked markdowns.',\n expected: [\n {\n label: 'inventory glut',\n anyOf: [\n 'inventor',\n 'overstock',\n 'excess inventory',\n 'glut',\n 'markdown',\n 'unsold',\n '1,104',\n '1.1 billion',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1639825/000163982522000117/pton-20220630.htm',\n evidence: '\"Inventories, net 1,104.5 937\" (FY2022 vs FY2021, $ millions).',\n },\n {\n id: 'PTON/f3',\n lens: 'governance',\n fact: \"A dual-class structure gives Class B holders 20 votes per share vs 1 for Class A — concentrating control with insiders/founders and limiting public shareholders' say.\",\n expected: [\n {\n label: 'dual-class super-voting control',\n anyOf: [\n 'dual-class',\n 'dual class',\n 'class b',\n '20 votes',\n 'super-voting',\n 'supervoting',\n 'voting control',\n 'multiple votes per share',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1639825/000163982522000117/pton-20220630.htm',\n evidence:\n '\"Class B common stock has 20 votes per share and our Class A common stock has one vote per share.\"',\n },\n {\n id: 'PTON/f4',\n lens: 'liquidity',\n fact: 'Peloton reported a $2.827B net loss in FY2022 — an order-of-magnitude wider loss than the prior year, signaling the demand normalization had broken the model, not just dented it.',\n expected: [\n {\n label: 'large net loss FY2022',\n anyOf: [\n 'net loss',\n 'unprofitable',\n 'losing money',\n 'cash burn',\n '2,827',\n '2.8 billion',\n '$2.8 billion',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1639825/000163982522000117/pton-20220630.htm',\n evidence: '\"Net loss $ (2,827 ...\" for fiscal 2022 ($ millions).',\n },\n {\n id: 'PTON/f5',\n lens: 'regulatory',\n fact: 'Peloton was running a CPSC recall of its Tread+ treadmill (tied to injuries and a child death) — an open product-safety and legal exposure beyond the demand story.',\n expected: [\n {\n label: 'Tread+ / CPSC recall exposure',\n anyOf: [\n 'recall',\n 'cpsc',\n 'consumer product safety',\n 'tread+',\n 'tread plus',\n 'product safety',\n 'injuries',\n 'safety',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1639825/000163982522000117/pton-20220630.htm',\n evidence:\n '\"recall on Tread+, which we are conducting in collaboration with the Consumer Product Safety Commission (\\'CPSC\\')\"; the Tread product recalls \"in the fourth quarter of fiscal 2021 continued to impact\" results.',\n },\n {\n id: 'PTON/f6',\n lens: 'leverage',\n fact: 'Peloton was locked into ~$334M of manufacturing purchase commitments even as demand fell — contractual inventory it had to take on regardless of whether it could sell it.',\n expected: [\n {\n label: 'locked-in purchase commitments',\n anyOf: [\n 'purchase commitment',\n 'purchase obligation',\n 'minimum purchase',\n 'take-or-pay',\n 'committed to purchase',\n '334',\n 'manufacturing commitment',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1639825/000163982522000117/pton-20220630.htm',\n evidence:\n '\"purchase commitments related to the manufacture of Peloton products were estimated to be approximately $334\" million.',\n },\n ],\n },\n {\n ticker: 'SI',\n company: 'Silvergate Capital Corporation',\n cik: '1312109',\n cutoff: '2022-02-28',\n sector: 'Banking (digital-asset)',\n knownOutcome:\n 'After the FTX collapse triggered a deposit run, Silvergate announced a voluntary wind-down of Silvergate Bank and liquidation in March 2023.',\n facts: [\n {\n id: 'SI/f1',\n lens: 'concentration',\n fact: 'About 99.5% of total deposits were noninterest-bearing — essentially all funding was non-term money that could leave on demand, an extreme run-risk masked by very low funding cost.',\n expected: [\n {\n label: 'almost all deposits noninterest-bearing / on-demand',\n anyOf: [\n 'noninterest bearing',\n 'noninterest-bearing',\n 'non-interest-bearing',\n 'demand deposit',\n 'no term',\n 'on demand',\n '99.5',\n '99 percent',\n 'leave at any time',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1312109/000131210922000051/si-20211231.htm',\n evidence:\n '\"noninterest bearing deposits as a percentage of total deposits was 99.5% as of December 31, 2021.\"',\n },\n {\n id: 'SI/f2',\n lens: 'concentration',\n fact: 'Roughly 58% of deposits came from digital-currency EXCHANGES alone — a handful of correlated crypto counterparties whose own troubles would pull deposits out together.',\n expected: [\n {\n label: 'deposits concentrated in crypto exchanges',\n anyOf: [\n 'digital currency exchange',\n 'crypto exchange',\n 'exchanges represent',\n 'counterpart',\n 'concentrat',\n '58%',\n '58 percent',\n 'approximately 58',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1312109/000131210922000051/si-20211231.htm',\n evidence:\n '\"Deposits from digital currency exchanges represent approximately 58%\" of deposits.',\n },\n {\n id: 'SI/f3',\n lens: 'concentration',\n fact: 'The entire deposit franchise was tied to a single, volatile industry — digital-currency (crypto) customers — so a crypto downturn was a direct, undiversified funding shock.',\n expected: [\n {\n // The buried, depth signal is the CONCENTRATION framing — that the\n // whole deposit base is one undiversified industry bet — NOT the bare\n // fact that it banks crypto (a one-line ticker summary has that). So\n // bare \"crypto\" / \"digital asset\" are excluded; the load-bearing\n // tokens are the concentration / single-industry / undiversified\n // characterization or the filing's own \"digital currency customers\".\n label: 'single-industry deposit CONCENTRATION (not just \"it banks crypto\")',\n anyOf: [\n 'digital currency customers',\n 'single industry',\n 'one industry',\n 'single volatile industry',\n 'sector concentration',\n 'undiversified',\n 'concentrat',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1312109/000131210922000051/si-20211231.htm',\n evidence:\n 'The 10-K\\'s strategy and risk factors center the bank on \"digital currency customers\" and \"the concentration of our deposits\" in that single industry.',\n },\n {\n id: 'SI/f4',\n lens: 'liquidity',\n fact: 'Total deposits had ballooned to $14.3B (from $10.4B) — fast, hot-money growth from the crypto boom that could reverse just as fast.',\n expected: [\n {\n // The depth signal is the SIZE/character of the deposit base — the\n // specific $14.3B figure or the explicit hot-money / volatile-deposit\n // characterization — NOT bare \"total deposits\" / \"grew rapidly\", which\n // any growth-story summary trips. Those generic phrases are excluded.\n label: 'specific hot-money deposit base ($14.3B / volatile)',\n anyOf: [\n 'hot money',\n 'hot-money',\n 'volatile deposit',\n 'could reverse',\n '14.3 billion',\n '14,290',\n '$14.3b',\n '$14 billion',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1312109/000131210922000051/si-20211231.htm',\n evidence: '\"Total deposits $ 14,290,628\" ... prior year \"$ 10,411,278\" ($ thousands).',\n },\n {\n id: 'SI/f5',\n lens: 'concentration',\n fact: 'The franchise hinged on a single proprietary product — the Silvergate Exchange Network (SEN), a payment network built exclusively for the digital-currency industry — so its competitive moat and its deposit base were the SAME crypto-dependent bet, not two diversified ones.',\n expected: [\n {\n // The depth signal is naming the SPECIFIC proprietary product (the\n // Silvergate Exchange Network / SEN) and that the moat and the deposit\n // base are the same single bet — NOT bare \"proprietary\" / \"payment\n // network\", which a generic crypto-bank summary mentions. Those bare\n // terms are excluded; the SEN name or the single-product framing is\n // load-bearing.\n label: 'names the SEN single-product dependence (not generic \"payment network\")',\n anyOf: [\n 'silvergate exchange network',\n 'the sen',\n 'sen)',\n \"sen'\",\n 'single product',\n 'single-product',\n 'core product',\n 'one product',\n 'same bet',\n ],\n },\n ],\n sourceUrl:\n 'https://www.sec.gov/Archives/edgar/data/1312109/000131210922000051/si-20211231.htm',\n evidence:\n \"\\\"Silvergate Exchange Network ('SEN'), our proprietary, virtually instantaneous payment network for participants in the digital currency industry\\\" — the bank's differentiator and its deposit magnet are the same crypto-only product.\",\n },\n ],\n },\n]\n\n/**\n * Grade ONE material fact against an investment thesis's full text. Returns\n * whether the thesis SURFACED it plus which expected groups were found. The\n * check is a deterministic case-insensitive substring scan — $0, model-free,\n * reproducible — so the eval never leaks into a model the loop could observe.\n */\nexport function gradeFactAgainstText(\n fact: MaterialFact,\n thesisText: string,\n): { surfaced: boolean; groupsFound: number; groupsTotal: number; foundLabels: string[] } {\n const haystack = thesisText.toLowerCase()\n const found = fact.expected.filter((group) =>\n group.anyOf.some((fragment) => haystack.includes(fragment.toLowerCase())),\n )\n const minGroups = fact.minGroups ?? fact.expected.length\n return {\n surfaced: found.length >= minGroups,\n groupsFound: found.length,\n groupsTotal: fact.expected.length,\n foundLabels: found.map((group) => group.label),\n }\n}\n\n/** Grade a whole company's thesis text: how many of its held-out facts it surfaces. */\nexport function gradeCompanyAgainstText(\n company: CompanyEvalCase,\n thesisText: string,\n): { surfaced: number; total: number; perFact: ReturnType<typeof gradeFactAgainstText>[] } {\n const perFact = company.facts.map((fact) => gradeFactAgainstText(fact, thesisText))\n return {\n surfaced: perFact.filter((result) => result.surfaced).length,\n total: company.facts.length,\n perFact,\n }\n}\n\n/** Total held-out facts across the set (the denominator the doc reports). */\nexport function totalMaterialFacts(set: CompanyEvalCase[] = investmentThesisSet): number {\n return set.reduce((sum, company) => sum + company.facts.length, 0)\n}\n\n/** Count facts per lens across the set — used to report (and bound) curation bias. */\nexport function lensDistribution(\n set: CompanyEvalCase[] = investmentThesisSet,\n): Record<MaterialFactLens, number> {\n const dist = {} as Record<MaterialFactLens, number>\n for (const company of set) {\n for (const fact of company.facts) {\n dist[fact.lens] = (dist[fact.lens] ?? 0) + 1\n }\n }\n return dist\n}\n","/**\n * `materialFactsSurfaced` — the held-out investment-research METRIC.\n *\n * Given a knowledge base a research loop built for a company and the company's\n * HELD-OUT material-fact checklist (`tests/eval/investment-thesis-set.ts`, never\n * shown to the loop), this returns the FRACTION of checklist items the KB's\n * pages surface + ground. The check is the same `$0`, model-free, deterministic\n * substring grader the loop's checklist already ships (`gradeFactAgainstText` /\n * `gradeCompanyAgainstText`) — so the answer key never reaches a model the loop\n * could observe, exactly the firewall the ML deep-question exam uses.\n *\n * The ONLY thing this file adds over the raw grader is the KB→text join: it reads\n * the curated pages (and the raw source text) the loop wrote and hands their\n * concatenation to the grader. That join mirrors `kbText` in the research-quality\n * A/B (research-driving-ab.test.ts) so the thesis metric and the ML-exam metric\n * read a KB the same way.\n *\n * WHY pages AND source text: an honest thesis surfaces a buried fact in its\n * curated thesis PAGE (the judgment), but a loop whose page is thin while its\n * fetched filings are rich should still get credit for what it actually pulled.\n * Grading the union is the faithful, not the lenient, choice — it rewards the\n * loop that REACHED the filing even if its synthesis was terse, and it cannot\n * manufacture a hit the underlying evidence does not contain.\n */\n\nimport { buildKnowledgeIndex } from './indexer'\nimport {\n type CompanyEvalCase,\n gradeCompanyAgainstText,\n gradeFactAgainstText,\n} from './investment-thesis-set'\nimport type { KnowledgeIndex } from './types'\n\n/** Per-fact grade plus the fact's id/lens, for the audit trail. */\nexport interface FactResult {\n id: string\n lens: CompanyEvalCase['facts'][number]['lens']\n surfaced: boolean\n groupsFound: number\n groupsTotal: number\n foundLabels: string[]\n}\n\n/** The metric's result for one company: the surfaced fraction + the per-fact trail. */\nexport interface MaterialFactsResult {\n ticker: string\n company: string\n /** Held-out facts the KB surfaced + grounded. */\n surfaced: number\n /** Total held-out facts for this company (the denominator). */\n total: number\n /** `surfaced / total` in [0, 1]. */\n fraction: number\n /** Per-fact grade, in checklist order, for the doc / audit. */\n perFact: FactResult[]\n}\n\n/**\n * Join a KB index into the single text blob the grader scans: every curated PAGE\n * (title + body) followed by every raw SOURCE (title + fetched text). This is the\n * text read AFTER the loop finished — it is never handed to the loop. Identical\n * in spirit to `kbText` in the research-quality A/B so both metrics read a KB the\n * same way.\n */\nexport function kbIndexToText(index: KnowledgeIndex): string {\n const pageText = index.pages.map((page) => `${page.title}\\n${page.text}`).join('\\n\\n')\n const sourceText = index.sources\n .map((source) => `${source.title ?? ''}\\n${source.text ?? ''}`)\n .join('\\n\\n')\n return `${pageText}\\n\\n${sourceText}`\n}\n\n/**\n * Grade one company's KB against its held-out material-fact checklist, given the\n * KB's already-joined text. The pure core — no I/O — so calibration can score a\n * hand-written shallow/deep thesis string directly and the live path can score a\n * real KB. Returns the surfaced FRACTION plus the per-fact audit trail.\n */\nexport function materialFactsSurfacedInText(\n company: CompanyEvalCase,\n kbText: string,\n): MaterialFactsResult {\n const grade = gradeCompanyAgainstText(company, kbText)\n const perFact: FactResult[] = company.facts.map((fact) => {\n const r = gradeFactAgainstText(fact, kbText)\n return {\n id: fact.id,\n lens: fact.lens,\n surfaced: r.surfaced,\n groupsFound: r.groupsFound,\n groupsTotal: r.groupsTotal,\n foundLabels: r.foundLabels,\n }\n })\n return {\n ticker: company.ticker,\n company: company.company,\n surfaced: grade.surfaced,\n total: grade.total,\n fraction: grade.total === 0 ? 0 : grade.surfaced / grade.total,\n perFact,\n }\n}\n\n/**\n * `materialFactsSurfaced(kb, checklist)` — the metric in its KB-reading form.\n *\n * `kb` is EITHER a knowledge-base root directory (the loop wrote pages there) or\n * an already-built `KnowledgeIndex`. `checklist` is the company's held-out\n * `CompanyEvalCase`. Returns the surfaced fraction + per-fact trail.\n *\n * The checklist is HELD OUT by construction: it lives in the test eval set, is\n * never passed to the loop, and is read only here, after the loop finished.\n */\nexport async function materialFactsSurfaced(\n kb: string | KnowledgeIndex,\n checklist: CompanyEvalCase,\n): Promise<MaterialFactsResult> {\n const index = typeof kb === 'string' ? await buildKnowledgeIndex(kb) : kb\n return materialFactsSurfacedInText(checklist, kbIndexToText(index))\n}\n","import type { KnowledgeReadinessReport } from '@tangle-network/agent-eval'\nimport {\n type BuildEvalKnowledgeBundleOptions,\n buildEvalKnowledgeBundle,\n type EvalKnowledgeBundleBuildResult,\n type KnowledgeReadinessSpec,\n} from './eval-readiness'\nimport { createKnowledgeEvent } from './events'\nimport { buildKnowledgeIndex } from './indexer'\nimport { FileSystemKbStore } from './kb-store'\nimport { applyKnowledgeWriteBlocks } from './proposals'\nimport { readinessFor } from './readiness-helpers'\nimport { searchKnowledge } from './search'\nimport {\n type AddSourceOptions,\n type AddSourceTextInput,\n addSourceText,\n snapshotSourceTextInput,\n} from './sources'\nimport { initKnowledgeBase } from './store'\nimport type { KnowledgeEvent, KnowledgeIndex, KnowledgeSearchResult, SourceRecord } from './types'\n\n/**\n * A knowledge gap the loop surfaces from `scoreKnowledgeReadiness`. The worker\n * targets these; the driver folds the unfilled remainder into the worker's next\n * prompt and runs its own gap-fill pass over them.\n */\nexport interface KnowledgeGap {\n /** Readiness-spec id this gap belongs to. */\n id: string\n /** Human-readable description of what's missing. */\n description: string\n /** The search query the readiness check ran for this requirement. */\n query: string\n /** True when the gap blocks readiness (vs. a soft, non-blocking gap). */\n blocking: boolean\n}\n\n/** A new source the worker (or driver) discovered and wants to add to the KB. */\nexport type ResearchSourceProposal = AddSourceTextInput\n\n/**\n * What a research agent contributes in one round. Both the worker and (when\n * `driverResearches` is on) the driver produce this shape — the worker ADDS\n * primary findings, the driver gap-FILLS the ones the worker missed.\n *\n * `proposalText` is the safe write-protocol text (`---FILE: knowledge/...---`\n * blocks). The loop only applies it AFTER the driver has verified the round's\n * sources, so a rejected source never reaches the curated pages.\n */\nexport interface ResearchContribution {\n /** Immutable sources to register (the raw evidence). */\n sources?: ResearchSourceProposal[]\n /** Safe write-protocol text producing curated `knowledge/*.md` pages. */\n proposalText?: string\n /**\n * Build the page write-protocol text FROM the sources the driver accepted —\n * the curated, citing pages the readiness gate searches. Receives the\n * registered `SourceRecord`s (with their assigned ids, so a page's frontmatter\n * `sources:` can cite them). Returns `---FILE: knowledge/...---` block text or\n * `undefined`. Runs after verification, so a page never cites a rejected\n * source. Concatenated after any static `proposalText`.\n */\n buildPages?: (acceptedSources: SourceRecord[]) => string | undefined\n /** Free-form research transcript — products can persist this. */\n notes?: string\n metadata?: Record<string, unknown>\n}\n\n/** Context handed to the worker each round. */\nexport interface WorkerResearchContext {\n root: string\n goal: string\n round: number\n index: KnowledgeIndex\n /** Gaps the readiness gate currently reports — what the worker should close. */\n gaps: KnowledgeGap[]\n /** Steer text the driver folded in from the previous round's remaining gaps. */\n steer?: string\n readiness: EvalKnowledgeBundleBuildResult\n signal?: AbortSignal\n}\n\n/** Context handed to the driver's verifier for one candidate source. */\nexport interface SourceVerificationContext {\n root: string\n goal: string\n round: number\n index: KnowledgeIndex\n gaps: KnowledgeGap[]\n /** Sources already accepted earlier THIS round (in-round dedup). */\n acceptedThisRound: ResearchSourceProposal[]\n signal?: AbortSignal\n}\n\n/** A single rejected source plus the reason the driver gave. */\nexport interface RejectedSource {\n source: ResearchSourceProposal\n reason: string\n}\n\n/** Context handed to the driver's gap-fill pass (only when `driverResearches`). */\nexport interface DriverResearchContext {\n root: string\n goal: string\n round: number\n index: KnowledgeIndex\n /** Gaps STILL open after the worker's accepted contribution applied. */\n remainingGaps: KnowledgeGap[]\n readiness: EvalKnowledgeBundleBuildResult\n signal?: AbortSignal\n}\n\n/**\n * The differentiated driver role.\n *\n * - `verifySource` — the gate the worker's additions pass before they commit.\n * Return `{ accept: true }` to keep a source or `{ accept: false, reason }`\n * to reject it (not real / not relevant / duplicate). The loop dedups exact\n * duplicates (same `uri` already in the KB or accepted this round) BEFORE\n * calling this, so the verifier only sees genuinely-new candidates.\n * - `research` — the driver's OWN gap-fill pass over the gaps the worker left\n * open. Only invoked when `driverResearches` is true.\n * - `foldGaps` — turn the remaining gaps into a steer string for the worker's\n * next prompt. Defaults to a compact bulleted list when omitted.\n * - `isComplete` — require the driver's research objectives as well as storage readiness.\n * - `checkpoint` — write whatever state the driver accumulated to durable\n * storage. Called at the end of every round, after `foldGaps`, so state that\n * a synchronous hook produced is on disk before the next round can crash.\n * - `prepareFold` — durably announce the next synchronous fold before it runs,\n * so a crash between question generation and `checkpoint` can be recovered.\n * - `commitSources` — confirm exact source records are durable after verification;\n * drivers with pending evidence must not count it before this callback.\n */\nexport interface ResearchDriver {\n verifySource(\n source: ResearchSourceProposal,\n ctx: SourceVerificationContext,\n ): Promise<SourceVerdict> | SourceVerdict\n research?(ctx: DriverResearchContext): Promise<ResearchContribution> | ResearchContribution\n foldGaps?(gaps: KnowledgeGap[]): string\n isComplete?(): boolean\n prepareFold?(): Promise<void> | void\n commitSources?(sources: readonly SourceRecord[]): Promise<void> | void\n checkpoint?(): Promise<void> | void\n}\n\nexport type SourceVerdict = { accept: true } | { accept: false; reason: string }\n\n/** The worker: primary research targeting the round's gaps. */\nexport type ResearchWorker = (\n ctx: WorkerResearchContext,\n) => Promise<ResearchContribution> | ResearchContribution\n\nexport interface VerifiedResearchLoopOptions {\n root: string\n goal: string\n worker: ResearchWorker\n driver: ResearchDriver\n /**\n * When false (default), the driver ONLY verifies + gates — a pure coordinator\n * that contributes no research of its own (the \"doesn't participate in the\n * work\" mode). When true, the driver also runs its `research` gap-fill pass\n * each round over the gaps the worker left open.\n */\n driverResearches?: boolean\n maxRounds?: number\n actor?: string\n /** Readiness specs define the gate; an empty list means the loop never gates. */\n readinessSpecs?: KnowledgeReadinessSpec[]\n readinessTaskId?: string\n readiness?: Omit<BuildEvalKnowledgeBundleOptions, 'taskId' | 'index' | 'specs'>\n sourceOptions?: Pick<AddSourceOptions, 'adapters' | 'now'>\n signal?: AbortSignal\n onRound?: (round: VerifiedResearchRound) => Promise<void> | void\n}\n\nexport interface VerifiedResearchRound {\n round: number\n /** Gaps reported at the START of the round (what the worker targeted). */\n gaps: KnowledgeGap[]\n /** Worker sources accepted by the driver and written to the KB. */\n acceptedWorkerSources: SourceRecord[]\n /** Worker sources the driver rejected (with reasons) — never written. */\n rejectedWorkerSources: RejectedSource[]\n /** Sources the driver itself added in its gap-fill pass. */\n driverSources: SourceRecord[]\n /** Curated pages written this round (worker proposal + driver proposal). */\n writtenPages: string[]\n readiness?: EvalKnowledgeBundleBuildResult\n /** True once readiness passes and the driver reports completion, when configured. */\n ready: boolean\n event: KnowledgeEvent\n notes: { worker?: string; driver?: string }\n}\n\nexport interface VerifiedResearchLoopResult {\n root: string\n goal: string\n rounds: number\n ready: boolean\n index: KnowledgeIndex\n readiness?: EvalKnowledgeBundleBuildResult\n steps: VerifiedResearchRound[]\n}\n\n/**\n * Two-agent (driver + worker) sibling of `runKnowledgeResearchLoop`.\n *\n * Both agents research to grow ONE knowledge base. The roles are differentiated:\n *\n * - **WORKER** = primary research. Each round it reads the open gaps, discovers\n * new sources, and proposes additions (`sources` + `proposalText`). It ADDS.\n * - **DRIVER** = the verifier / gap-filler / gate. It (1) VERIFIES the worker's\n * sources before they commit — dedup against the KB, then `verifySource`\n * rejects ones that aren't real/relevant; (2) GAP-FILLS the gaps the worker\n * missed with its own research pass (when `driverResearches`); (3) folds the\n * remaining gaps into the worker's next prompt; and (4) GATES on\n * `scoreKnowledgeReadiness` and optional `isComplete` — the loop stops when\n * readiness passes and the driver has no unfinished research.\n *\n * Set `driverResearches: false` (default) for the pure-coordinator mode: the\n * driver only verifies + gates and contributes no research itself.\n *\n * Composes existing atoms — `initKnowledgeBase`, `addSourceText`,\n * `applyKnowledgeWriteBlocks`, `buildEvalKnowledgeBundle` (the readiness gate),\n * and `searchKnowledge` — and reinvents none of them.\n */\nexport async function runVerifiedResearchLoop(\n options: VerifiedResearchLoopOptions,\n): Promise<VerifiedResearchLoopResult> {\n const assertActive = () => options.signal?.throwIfAborted()\n assertActive()\n const maxRounds = Math.max(1, options.maxRounds ?? 3)\n await initKnowledgeBase(options.root)\n assertActive()\n const store = new FileSystemKbStore({ root: options.root })\n const steps: VerifiedResearchRound[] = []\n let index = await buildKnowledgeIndex(options.root)\n assertActive()\n // Reconcile source writes that completed before a previous process died while\n // confirming them to the driver. The records carry both original URI and hash.\n await confirmRegisteredSources(options.driver, index.sources)\n assertActive()\n let readiness = readinessFor(options, index)\n let ready = isReady(readiness?.report) && (options.driver.isComplete?.() ?? true)\n let steer: string | undefined\n\n for (let round = 1; round <= maxRounds && !ready; round++) {\n assertActive()\n\n const gaps = gapsFromReadiness(readiness)\n\n // 1. WORKER: primary research over the open gaps.\n const workerContribution = await options.worker({\n root: options.root,\n goal: options.goal,\n round,\n index,\n gaps,\n steer,\n readiness: requireReadiness(readiness, options),\n signal: options.signal,\n })\n assertActive()\n\n // 2. DRIVER VERIFIES the worker's sources before they commit.\n const accepted: ResearchSourceProposal[] = []\n const rejectedWorkerSources: RejectedSource[] = []\n // Dedup against the ORIGINAL input uri. `addSourceText` rewrites `record.uri`\n // to a slugified raw path and stashes the caller's uri under\n // `metadata.originalUri`, so that — not the stored uri — is the round-to-round\n // identity a verifier dedups against.\n const existingUris = new Set(\n index.sources.flatMap((source) =>\n typeof source.metadata?.originalUri === 'string' ? [source.metadata.originalUri] : [],\n ),\n )\n for (const proposedSource of workerContribution.sources ?? []) {\n const source = snapshotSourceTextInput(proposedSource)\n if (isDuplicate(source, existingUris, accepted)) {\n rejectedWorkerSources.push({ source, reason: 'duplicate: already in the knowledge base' })\n continue\n }\n const verdict = await options.driver.verifySource(source, {\n root: options.root,\n goal: options.goal,\n round,\n index,\n gaps,\n acceptedThisRound: accepted,\n signal: options.signal,\n })\n assertActive()\n if (verdict.accept) accepted.push(source)\n else rejectedWorkerSources.push({ source, reason: verdict.reason })\n }\n\n // Register the accepted worker sources, then apply the worker's curated\n // pages — but only when at least one source survived verification, so a\n // page never cites a rejected source.\n const acceptedWorkerSources = await registerSources(options, accepted)\n assertActive()\n await confirmRegisteredSources(options.driver, acceptedWorkerSources)\n assertActive()\n const writtenPages: string[] = []\n writtenPages.push(\n ...(await applyPages(options.root, workerContribution, acceptedWorkerSources)),\n )\n assertActive()\n\n // Re-index so the driver's gap-fill pass sees the worker's contribution.\n index = await buildKnowledgeIndex(options.root)\n assertActive()\n readiness = readinessFor(options, index)\n\n // 3. DRIVER GAP-FILLS the gaps the worker left open (opt-in).\n let driverSources: SourceRecord[] = []\n let driverNotes: string | undefined\n if (options.driverResearches && options.driver.research) {\n const remainingGaps = gapsFromReadiness(readiness)\n const driverContribution = await options.driver.research({\n root: options.root,\n goal: options.goal,\n round,\n index,\n remainingGaps,\n readiness: requireReadiness(readiness, options),\n signal: options.signal,\n })\n assertActive()\n driverNotes = driverContribution.notes\n driverSources = await registerSources(options, driverContribution.sources ?? [])\n assertActive()\n await confirmRegisteredSources(options.driver, driverSources)\n assertActive()\n writtenPages.push(...(await applyPages(options.root, driverContribution, driverSources)))\n assertActive()\n index = await buildKnowledgeIndex(options.root)\n assertActive()\n readiness = readinessFor(options, index)\n }\n\n // 4. DRIVER GATES on readiness and folds the remainder into the next prompt.\n const driverComplete = options.driver.isComplete?.() ?? true\n ready = isReady(readiness?.report) && driverComplete\n const remainingGaps = gapsFromReadiness(readiness)\n if (ready || (remainingGaps.length === 0 && driverComplete)) {\n steer = undefined\n } else {\n await options.driver.prepareFold?.()\n assertActive()\n steer = foldGaps(options.driver, remainingGaps)\n }\n\n const step: VerifiedResearchRound = {\n round,\n gaps,\n acceptedWorkerSources,\n rejectedWorkerSources,\n driverSources,\n writtenPages,\n readiness,\n ready,\n event: createKnowledgeEvent({\n type: 'research.iteration',\n actor: options.actor,\n target: options.root,\n metadata: {\n goal: options.goal,\n round,\n ready,\n acceptedWorkerSourceCount: acceptedWorkerSources.length,\n rejectedWorkerSourceCount: rejectedWorkerSources.length,\n driverSourceCount: driverSources.length,\n writtenPageCount: writtenPages.length,\n remainingGapCount: remainingGaps.length,\n },\n }),\n notes: { worker: workerContribution.notes, driver: driverNotes },\n }\n // Commit the driver's state before publishing the round event. A persisted\n // event therefore never claims a round whose generated questions were lost.\n await options.driver.checkpoint?.()\n assertActive()\n await store.putEvent(step.event)\n assertActive()\n\n steps.push(step)\n await options.onRound?.(step)\n assertActive()\n }\n\n assertActive()\n return {\n root: options.root,\n goal: options.goal,\n rounds: steps.length,\n ready,\n index,\n readiness,\n steps,\n }\n}\n\nfunction isReady(report: KnowledgeReadinessReport | undefined): boolean {\n // No specs ⇒ no gate ⇒ the loop runs to `maxRounds`. With specs, the gate is\n // \"no blocking gaps remain\".\n if (!report) return false\n return report.blockingMissingRequirements.length === 0\n}\n\nfunction gapsFromReadiness(readiness: EvalKnowledgeBundleBuildResult | undefined): KnowledgeGap[] {\n if (!readiness) return []\n const blocking = readiness.report.blockingMissingRequirements.map((requirement) =>\n gapFor(requirement, readiness, true),\n )\n const nonBlocking = readiness.report.nonBlockingGaps.map((requirement) =>\n gapFor(requirement, readiness, false),\n )\n return [...blocking, ...nonBlocking]\n}\n\nfunction gapFor(\n requirement: { id: string; description: string; metadata?: Record<string, unknown> },\n readiness: EvalKnowledgeBundleBuildResult,\n blocking: boolean,\n): KnowledgeGap {\n const spec = readiness.requirements.find((entry) => entry.id === requirement.id)\n const query =\n typeof spec?.metadata?.query === 'string' ? spec.metadata.query : requirement.description\n return { id: requirement.id, description: requirement.description, query, blocking }\n}\n\nfunction foldGaps(driver: ResearchDriver, gaps: KnowledgeGap[]): string | undefined {\n if (driver.foldGaps) return driver.foldGaps(gaps)\n if (gaps.length === 0) return undefined\n return [\n 'The knowledge base is still missing the following. Prioritise these next round:',\n ...gaps.map(\n (gap) => `- (${gap.blocking ? 'blocking' : 'soft'}) ${gap.description} [${gap.id}]`,\n ),\n ].join('\\n')\n}\n\nfunction isDuplicate(\n source: ResearchSourceProposal,\n existingUris: Set<string>,\n accepted: ResearchSourceProposal[],\n): boolean {\n return existingUris.has(source.uri) || accepted.some((candidate) => candidate.uri === source.uri)\n}\n\nasync function registerSources(\n options: VerifiedResearchLoopOptions,\n sources: ResearchSourceProposal[],\n): Promise<SourceRecord[]> {\n const records: SourceRecord[] = []\n for (const candidate of sources) {\n options.signal?.throwIfAborted()\n const source = snapshotSourceTextInput(candidate)\n records.push(await addSourceText(options.root, source, options.sourceOptions))\n options.signal?.throwIfAborted()\n }\n return records\n}\n\nasync function confirmRegisteredSources(\n driver: ResearchDriver,\n sources: readonly SourceRecord[],\n): Promise<void> {\n if (!driver.commitSources) return\n const textSources = sources.filter((source) => typeof source.metadata?.originalUri === 'string')\n if (textSources.length === 0) return\n await driver.commitSources(textSources)\n}\n\n/**\n * Apply a contribution's curated pages. Static `proposalText` plus a\n * `buildPages(acceptedSources)` result are concatenated and run through the safe\n * write protocol — but ONLY when at least one source survived verification, so a\n * page never cites a rejected (or absent) source.\n */\nasync function applyPages(\n root: string,\n contribution: ResearchContribution,\n acceptedSources: SourceRecord[],\n): Promise<string[]> {\n if (acceptedSources.length === 0) return []\n const parts: string[] = []\n if (contribution.proposalText) parts.push(contribution.proposalText)\n const built = contribution.buildPages?.(acceptedSources)\n if (built) parts.push(built)\n if (parts.length === 0) return []\n const applied = await applyKnowledgeWriteBlocks(root, parts.join('\\n'))\n return applied.written\n}\n\nfunction requireReadiness(\n readiness: EvalKnowledgeBundleBuildResult | undefined,\n options: VerifiedResearchLoopOptions,\n): EvalKnowledgeBundleBuildResult {\n if (readiness) return readiness\n // The worker/driver contexts type `readiness` as required for ergonomics; when\n // no specs are configured there is no gate to report, so synthesise an empty\n // bundle rather than forcing every caller to handle `undefined`.\n return buildEvalKnowledgeBundle({\n ...(options.readiness ?? {}),\n taskId: options.readinessTaskId ?? options.goal,\n index: emptyIndex(options.root),\n specs: [],\n })\n}\n\nfunction emptyIndex(root: string): KnowledgeIndex {\n return {\n root,\n generatedAt: new Date(0).toISOString(),\n sources: [],\n pages: [],\n graph: { nodes: [], edges: [] },\n }\n}\n\n/**\n * Helper for verifiers: does the candidate source's text/title overlap any page\n * the readiness search returns for a gap query? A cheap relevance heuristic the\n * driver can compose into `verifySource` (real verifiers can do more).\n */\nexport function sourceMatchesGaps(\n source: ResearchSourceProposal,\n index: KnowledgeIndex,\n gaps: KnowledgeGap[],\n): KnowledgeSearchResult[] {\n const haystack = `${source.title ?? ''}\\n${source.text}`.toLowerCase()\n const hits: KnowledgeSearchResult[] = []\n for (const gap of gaps) {\n for (const token of gap.query.toLowerCase().split(/\\s+/).filter(Boolean)) {\n if (haystack.includes(token)) {\n hits.push(...searchKnowledge(index, gap.query, 1))\n break\n }\n }\n }\n return hits\n}\n","/**\n * The INVESTMENT-THESIS research task.\n *\n * Given `{ company, ticker, cik, cutoff }`, drive the SAME two-agent research\n * loop the ML deep-question A/B uses (`runVerifiedResearchLoop` + the real web\n * worker) to research the company AS OF the cutoff — web + SEC EDGAR, both public\n * — and produce an investment-thesis PAGE in the knowledge base: a judgment, the\n * drivers, and the risks, grounded in what it fetched.\n *\n * This file builds NOTHING new for the loop: it composes the existing worker +\n * driver + loop, supplies the readiness specs that steer the worker toward the\n * filing-level evidence (the analyst lenses), then writes a synthesis thesis page\n * the metric (`materialFactsSurfaced`) grades against the HELD-OUT checklist.\n *\n * THE FIREWALL: the task is told ONLY company + ticker + cutoff (+ the generic\n * analyst-lens readiness specs every company gets). It is NEVER shown the\n * checklist. The checklist is read only afterward, by the metric. So a high score\n * is research depth, not teaching-to-the-test.\n */\n\nimport { join } from 'node:path'\nimport { writeFileDurableWithinRoot } from './durable-fs'\nimport { defineReadinessSpec, type KnowledgeReadinessSpec } from './eval-readiness'\nimport { slugify } from './ids'\nimport { buildKnowledgeIndex } from './indexer'\nimport { kbIndexToText } from './material-facts-metric'\nimport { withKnowledgeMutation } from './mutation-lock'\nimport {\n type ResearchDriver,\n runVerifiedResearchLoop,\n type VerifiedResearchLoopResult,\n} from './verified-research-loop'\nimport {\n createWebResearchWorker,\n type RouterClient,\n type WebResearchWorkerOptions,\n} from './web-research-worker'\n\n/** The minimal brief a thesis run is given — the firewall boundary. */\nexport interface ThesisTaskInput {\n /** Legal name as of the cutoff — what the loop researches. */\n company: string\n /** Ticker as of the cutoff. */\n ticker: string\n /** SEC Central Index Key (CIK), zero-stripped — the EDGAR filer id. */\n cik: string\n /** Research-as-of date (ISO). The loop must reason as if it is this date. */\n cutoff: string\n /** Sector, for the readiness query context (NOT a checklist hint). */\n sector?: string\n}\n\n/**\n * The generic analyst-lens readiness specs every company gets. They are the ONLY\n * thing the loop is told about WHAT to look for, and they name the LENSES a\n * thorough analyst checks (balance-sheet risk, concentration, leverage, margins,\n * liquidity, governance, regulatory) and where they live (the latest SEC 10-K) —\n * NOT the answers. They steer the worker's web/EDGAR search toward the filing,\n * not toward the held-out facts (which the loop never sees).\n *\n * `minSources` is set above 1 so the readiness gate stays UNMET after a single\n * fetch and the loop runs multiple rounds — the depth-driving driver needs >1\n * round to steer, exactly as the ML-exam multi-round probe established.\n */\nexport function thesisReadinessSpecs(input: ThesisTaskInput): KnowledgeReadinessSpec[] {\n const c = input.company\n const t = input.ticker\n const filing = `${c} ${t} SEC 10-K annual report SEC.gov EDGAR filing`\n return [\n defineReadinessSpec({\n id: 'thesis/filing',\n description: `the most recent SEC 10-K annual report for ${c} (${t}) filed on or before ${input.cutoff}, from SEC EDGAR`,\n query: filing,\n requiredFor: ['ResearchAgent'],\n importance: 'blocking',\n minSources: 2,\n minHits: 1,\n }),\n defineReadinessSpec({\n id: 'thesis/balance-sheet',\n description: `${c} balance-sheet risks: securities marked below cost, unrealized losses, leverage / total debt, debt maturities, interest expense`,\n query: `${c} ${t} 10-K balance sheet total debt unrealized losses interest expense leverage`,\n requiredFor: ['ResearchAgent'],\n importance: 'blocking',\n minSources: 2,\n minHits: 1,\n }),\n defineReadinessSpec({\n id: 'thesis/concentration-liquidity',\n description: `${c} concentration + liquidity: customer / deposit / revenue concentration, uninsured deposits, operating cash flow, net loss, inventory, equity erosion`,\n query: `${c} ${t} 10-K customer deposit concentration operating cash flow net loss inventory`,\n requiredFor: ['ResearchAgent'],\n importance: 'blocking',\n minSources: 2,\n minHits: 1,\n }),\n defineReadinessSpec({\n id: 'thesis/governance-regulatory',\n description: `${c} governance + regulatory: related-party transactions, dual-class / super-voting control, buybacks / dividends, recalls, regulatory or legal exposure, margin trends`,\n query: `${c} ${t} 10-K related party dual class share repurchase recall regulatory gross margin`,\n requiredFor: ['ResearchAgent'],\n importance: 'blocking',\n minSources: 2,\n minHits: 1,\n }),\n ]\n}\n\n/**\n * The thesis-writer prompt. After the loop has fetched + curated the filings, we\n * ask the model to SYNTHESIZE a thesis page from the curated KB text — a\n * judgment, the key drivers, and the material risks, grounded ONLY in the fetched\n * evidence. The held-out checklist is NOT in this prompt; the model writes from\n * what the loop actually pulled, so a fact only appears if the research surfaced\n * the underlying evidence.\n */\nfunction thesisSynthesisMessages(\n input: ThesisTaskInput,\n kbText: string,\n): { role: 'system' | 'user'; content: string }[] {\n const system =\n 'You are a buy-side investment analyst writing a thesis memo. You are given ' +\n 'the raw research your team gathered from public filings (SEC 10-K) and the web. ' +\n 'Write a thesis that a thorough analyst would write: lead with your JUDGMENT, ' +\n 'then the KEY DRIVERS, then the MATERIAL RISKS. Be specific and quantitative — ' +\n 'name the actual figures, balance-sheet items, concentrations, leverage, ' +\n 'margin trends, governance items, and regulatory exposures that appear in the ' +\n 'research. Surface the buried, non-obvious drivers a one-line ticker summary ' +\n 'misses. Ground every claim in the research provided; do NOT invent figures. ' +\n 'If the research does not contain a figure, do not state it.'\n const user = [\n `Company: ${input.company} (${input.ticker})`,\n `As-of date (reason as if it is this date): ${input.cutoff}`,\n input.sector ? `Sector: ${input.sector}` : '',\n '',\n 'Research gathered (filings + web excerpts):',\n '\"\"\"',\n kbText.slice(0, 24000),\n '\"\"\"',\n '',\n 'Write the investment thesis now. Structure:',\n '## Judgment',\n '## Key drivers',\n '## Material risks',\n ]\n .filter(Boolean)\n .join('\\n')\n return [\n { role: 'system', content: system },\n { role: 'user', content: user },\n ]\n}\n\n/** Write the synthesis thesis page into the KB so the index + metric pick it up. */\nasync function writeThesisPage(\n root: string,\n input: ThesisTaskInput,\n thesis: string,\n): Promise<string> {\n return withKnowledgeMutation(root, async () => {\n const relativePath = `knowledge/thesis-${slugify(input.ticker)}.md`\n const body = [\n '---',\n `title: Investment thesis — ${input.company} (${input.ticker})`,\n `ticker: ${input.ticker}`,\n `cutoff: ${input.cutoff}`,\n 'kind: investment-thesis',\n '---',\n `# Investment thesis — ${input.company} (${input.ticker}), as of ${input.cutoff}`,\n '',\n thesis.trim(),\n '',\n ].join('\\n')\n await writeFileDurableWithinRoot(root, relativePath, body, { encoding: 'utf8' })\n return join(root, relativePath)\n })\n}\n\nexport interface ThesisRunOptions {\n /** The KB root the loop writes into. */\n root: string\n /** Shared router client (web search + chat). Defaults to env creds. */\n router: RouterClient\n /** The driver — verify/dedup or research-driving. The loop's coordinator. */\n driver: ResearchDriver\n /** Round budget. Default 3 (the depth-driving driver needs >1). */\n maxRounds?: number\n /** Worker tuning forwarded to `createWebResearchWorker`. */\n workerOptions?: Omit<WebResearchWorkerOptions, 'router'>\n /** Max tokens for the synthesis pass. Default 1600 (above glm-5.2's reasoning floor). */\n synthesisMaxTokens?: number\n signal?: AbortSignal\n}\n\nexport interface ThesisRunResult {\n loop: VerifiedResearchLoopResult\n /** The synthesized thesis text. */\n thesis: string\n /** Path of the thesis page written into the KB. */\n thesisPath: string\n}\n\n/**\n * Run the full thesis task: drive the two-agent loop to research the company AS\n * OF the cutoff, then synthesize + write the thesis page. Returns the loop result\n * + the thesis text + the page path. The caller grades the KB with\n * `materialFactsSurfaced(root, checklist)` — the checklist is never passed here.\n */\nexport async function runInvestmentThesisTask(\n input: ThesisTaskInput,\n options: ThesisRunOptions,\n): Promise<ThesisRunResult> {\n const worker = createWebResearchWorker({ ...options.workerOptions, router: options.router })\n const goal = `${input.company} (${input.ticker}) investment thesis as of ${input.cutoff}`\n\n const loop = await runVerifiedResearchLoop({\n root: options.root,\n goal,\n worker,\n driver: options.driver,\n readinessSpecs: thesisReadinessSpecs(input),\n maxRounds: options.maxRounds ?? 3,\n signal: options.signal,\n })\n\n // Synthesize the thesis from what the loop actually curated + fetched.\n const index = await buildKnowledgeIndex(options.root)\n const kbText = kbIndexToText(index)\n const messages = thesisSynthesisMessages(input, kbText)\n const thesis = await options.router.chat(messages, options.synthesisMaxTokens ?? 1600)\n\n const thesisPath = await writeThesisPage(options.root, input, thesis)\n return { loop, thesis, thesisPath }\n}\n","/**\n * Retrieval briefing.\n *\n * A brief turns \"retrieved\" from something a run claims into something the\n * infrastructure can prove. It ranks the knowledge visible to a question,\n * renders it with the ids a later write must cite, and returns the ranked\n * results in the shape a retrieval receipt takes, so what an actor was given\n * is recorded rather than asserted.\n *\n * Pure: no clock, no filesystem, no network.\n */\nimport { canonicalCandidateDigest, type Sha256Digest } from '@tangle-network/agent-interface'\nimport {\n assertKnowledgeCitationsResolved,\n formatKnowledgeCitationReference,\n parseKnowledgeCitationReference,\n resolveKnowledgeCitation,\n} from './citation-resolution'\nimport type { OriginatedKnowledgeSearchResult } from './knowledge-use-receipts'\nimport type { OriginatedPage } from './run-scoped'\nimport {\n KNOWLEDGE_SEARCH_RETRIEVER_ID,\n type KnowledgeSearchHit,\n searchKnowledgePages,\n} from './search'\nimport type { KnowledgeId, KnowledgePage } from './types'\n\n/** Pages in a brief when the caller names no limit. */\nexport const DEFAULT_KNOWLEDGE_BRIEF_LIMIT = 5\n\nexport interface KnowledgeBriefOptions {\n /** Maximum pages in the brief. Defaults to 5. */\n limit?: number\n /**\n * Drop pages whose own evidence refuted them. Defaults to true, the opposite\n * of `searchKnowledge`: a brief is injected before a run's first token and\n * offers every page it names with an id ready to cite, so a refuted page in\n * it is an invitation to build on a dead claim.\n */\n excludeInvalidated?: boolean\n /** Match pages carrying at least one of these tags. */\n tags?: readonly string[]\n /** Match the exact string stored in `frontmatter.kind`. */\n kinds?: readonly string[]\n /**\n * Bound on the rendered brief. A page whose line does not fit is left out of\n * the whole brief, so `text`, `hits`, `citationIds`, and `results` always\n * describe one identical set of pages.\n */\n maxChars?: number\n}\n\nexport interface KnowledgeBrief {\n readonly question: string\n /** Retriever id to declare in a receipt minted from `results`. */\n readonly retrieverId: typeof KNOWLEDGE_SEARCH_RETRIEVER_ID\n /**\n * Digest of the retrieval settings this brief used. Pass it as the\n * `configDigest` of the receipt's retriever identity. The running package\n * version is the caller's to declare, because a bundled build cannot read it.\n */\n readonly retrieverConfigDigest: Sha256Digest\n readonly hits: readonly KnowledgeSearchHit[]\n /** The ids a write should persist in `cites`, in rank order. */\n readonly citationIds: readonly KnowledgeId[]\n /** Ranked results in the shape `createKnowledgeRetrievalReceipt` takes. */\n readonly results: readonly OriginatedKnowledgeSearchResult[]\n /** Deterministic Markdown: one `- [id] title — snippet` line per page, in rank order. */\n readonly text: string\n}\n\n/**\n * Rank the knowledge one question can see and render it for injection.\n *\n * The same page set produces the same brief on every run: ranking, ordering,\n * and rendering are deterministic, and no field carries a timestamp.\n */\nexport function buildKnowledgeBrief(\n visiblePages: readonly OriginatedPage[],\n question: string,\n options: KnowledgeBriefOptions = {},\n): KnowledgeBrief {\n if (!Array.isArray(visiblePages)) {\n throw new TypeError('knowledge brief requires the visible pages')\n }\n if (typeof question !== 'string' || question.trim().length === 0) {\n throw new TypeError('knowledge brief question must be a non-empty string')\n }\n const limit = options.limit ?? DEFAULT_KNOWLEDGE_BRIEF_LIMIT\n const excludeInvalidated = options.excludeInvalidated ?? true\n const maxChars = options.maxChars\n if (maxChars !== undefined && (!Number.isInteger(maxChars) || maxChars < 0)) {\n throw new Error(`knowledge brief maxChars must be a non-negative integer, got ${maxChars}`)\n }\n\n // Resolve citation addresses with the same owner used by read/write validation.\n // Keep a small candidate list per id so resolving links does not rescan the corpus.\n const byId = new Map<KnowledgeId, OriginatedPage[]>()\n for (const entry of visiblePages) {\n const matches = byId.get(entry.page.id) ?? []\n matches.push(entry)\n byId.set(entry.page.id, matches)\n }\n const qualified = (entry: OriginatedPage) =>\n formatKnowledgeCitationReference({ pageId: entry.page.id, origin: entry.origin })\n const originals = new Map<KnowledgePage, OriginatedPage>()\n const pages = visiblePages.map((entry) => {\n const page: KnowledgePage = {\n ...entry.page,\n id: qualified(entry),\n outLinks: entry.page.outLinks.flatMap((link: string) => {\n // A malformed link is not a ranking edge; retain the page unchanged so\n // citation audit can still diagnose it without making retrieval unavailable.\n try {\n const reference = parseKnowledgeCitationReference(link)\n const resolution = resolveKnowledgeCitation(byId.get(reference.pageId) ?? [], reference)\n return resolution.resolved ? [qualified(resolution.resolved)] : []\n } catch (error) {\n if (error instanceof TypeError) return []\n throw error\n }\n }),\n }\n originals.set(page, entry)\n return page\n })\n const ranked = searchKnowledgePages(pages, question, {\n limit,\n excludeInvalidated,\n ...(options.tags === undefined ? {} : { tags: options.tags }),\n ...(options.kinds === undefined ? {} : { kinds: options.kinds }),\n }).map((hit) => {\n const entry = originals.get(hit.page)!\n const candidates = byId.get(entry.page.id)!\n const reference = {\n pageId: entry.page.id,\n ...(candidates.length === 1 &&\n formatKnowledgeCitationReference({ pageId: entry.page.id }) === entry.page.id\n ? {}\n : { origin: entry.origin }),\n }\n // The whole visible chain determines ambiguity, not just this query's filtered hits.\n // Reusing one id within the SAME origin cannot be repaired with a qualifier.\n assertKnowledgeCitationsResolved(candidates, [reference])\n return {\n ...hit,\n page: entry.page,\n origin: entry.origin,\n citationId: formatKnowledgeCitationReference(reference),\n }\n })\n\n const hits: (KnowledgeSearchHit & OriginatedKnowledgeSearchResult)[] = []\n const lines: string[] = []\n let length = 0\n for (const hit of ranked) {\n const line = briefLine(hit)\n const next = length === 0 ? line.length : length + 1 + line.length\n if (maxChars !== undefined && next > maxChars) break\n hits.push(hit)\n lines.push(line)\n length = next\n }\n\n return Object.freeze({\n question: question.trim(),\n retrieverId: KNOWLEDGE_SEARCH_RETRIEVER_ID,\n retrieverConfigDigest: canonicalCandidateDigest({\n limit,\n excludeInvalidated,\n tags: options.tags === undefined ? null : [...options.tags],\n kinds: options.kinds === undefined ? null : [...options.kinds],\n maxChars: maxChars ?? null,\n }),\n hits: Object.freeze(hits),\n citationIds: Object.freeze(hits.map((hit) => hit.citationId)),\n results: Object.freeze(hits.map((hit) => Object.freeze(hit))),\n text: lines.join('\\n'),\n })\n}\n\nfunction briefLine(hit: KnowledgeSearchHit): string {\n const snippet = hit.snippet.replace(/\\s+/g, ' ').trim()\n return snippet === ''\n ? `- [${hit.citationId}] ${hit.page.title}`\n : `- [${hit.citationId}] ${hit.page.title} — ${snippet}`\n}\n","import type { EvidenceRef } from '@tangle-network/agent-eval/analyst'\nimport {\n canonicalCandidateDigest,\n type Sha256Digest,\n sha256Bytes,\n} from '@tangle-network/agent-interface'\nimport {\n assertSchemaVersion,\n createKnowledgeVisibilitySnapshot,\n decodeKnowledgeVisibilitySnapshot,\n digest,\n KNOWLEDGE_RECEIPT_DIGEST_ALGORITHM,\n KNOWLEDGE_USE_RECEIPT_SCHEMA_VERSION,\n knowledgePageDigest,\n nonEmpty,\n normalizeVisibilityArtifact,\n normalizeVisibilityRef,\n type VisibilityIndex,\n validateKnowledgePage,\n validateOrigin,\n visibilityIdentity,\n visibilityIndexOf,\n} from './knowledge-visibility'\nimport type { OriginatedPage, PageOrigin } from './run-scoped'\nimport type { KnowledgeSearchResult } from './types'\n\nexport {\n createKnowledgeVisibilitySnapshot,\n decodeKnowledgeVisibilitySnapshot,\n encodeKnowledgeVisibilitySnapshot,\n KNOWLEDGE_RECEIPT_DIGEST_ALGORITHM,\n KNOWLEDGE_USE_RECEIPT_SCHEMA_VERSION,\n knowledgePageDigest,\n knowledgeVisibilityArtifactRef,\n verifyKnowledgeVisibilitySnapshot,\n} from './knowledge-visibility'\nexport interface KnowledgeVisibilitySnapshotEntry {\n readonly position: number\n readonly pageId: string\n readonly origin: PageOrigin\n readonly path: string\n readonly pageDigest: Sha256Digest\n readonly sourceIds: readonly string[]\n readonly invalidated: boolean\n}\n\n/** Exact ordered page visibility presented to one retrieval operation. */\nexport interface KnowledgeVisibilitySnapshot {\n readonly schemaVersion: typeof KNOWLEDGE_USE_RECEIPT_SCHEMA_VERSION\n readonly digestAlgorithm: typeof KNOWLEDGE_RECEIPT_DIGEST_ALGORITHM\n readonly snapshotDigest: Sha256Digest\n readonly entries: readonly KnowledgeVisibilitySnapshotEntry[]\n}\n\n/** Content-addressed locator of the stored bytes of one visibility snapshot. */\nexport interface KnowledgeVisibilityArtifactRef {\n readonly uri: string\n /** Digest of the stored bytes, as `knowledgeVisibilityArtifactRef` computes it. */\n readonly digest: Sha256Digest\n readonly byteLength: number\n}\n\n/**\n * Compact identity of one exact visibility snapshot. The snapshot bytes live in\n * the artifact the reference names, or in another durable record the caller\n * keeps; the receipt carries only this reference.\n */\nexport interface KnowledgeVisibilityRef {\n readonly snapshotDigest: Sha256Digest\n readonly pageCount: number\n readonly artifact?: KnowledgeVisibilityArtifactRef\n}\n\nexport interface KnowledgeRetrieverIdentity {\n /** Stable implementation name, for example `token-overlap-v1`. */\n readonly id: string\n /** Published or application-defined implementation version. */\n readonly version: string\n /** Exact identity of every retrieval setting not represented elsewhere. */\n readonly configDigest: Sha256Digest\n}\n\nexport interface OriginatedKnowledgeSearchResult extends KnowledgeSearchResult {\n readonly origin: PageOrigin\n}\n\nexport interface KnowledgeRetrievalResultReceipt {\n readonly rank: number\n readonly pageId: string\n readonly origin: PageOrigin\n readonly path: string\n readonly pageDigest: Sha256Digest\n readonly rrfScore: number\n readonly normalizedScore: number\n readonly snippet: string\n readonly reasons: readonly string[]\n}\n\nexport type KnowledgeReceiptAttributeValue = string | number | boolean | null\n\n/**\n * Immutable proof of what one actor could see and what its retriever returned.\n * Final prose is not evidence that retrieval happened; this receipt is.\n */\nexport interface KnowledgeRetrievalReceipt {\n readonly schemaVersion: typeof KNOWLEDGE_USE_RECEIPT_SCHEMA_VERSION\n readonly kind: 'knowledge-retrieval'\n readonly digestAlgorithm: typeof KNOWLEDGE_RECEIPT_DIGEST_ALGORITHM\n readonly receiptDigest: Sha256Digest\n readonly createdAt: string\n readonly runId: string\n readonly actorId?: string\n readonly profileDigest?: Sha256Digest\n readonly executionRef?: Sha256Digest\n readonly query: string\n readonly retriever: KnowledgeRetrieverIdentity\n readonly visibility: KnowledgeVisibilityRef\n readonly results: readonly KnowledgeRetrievalResultReceipt[]\n readonly evidenceRefs: readonly EvidenceRef[]\n readonly attributes: Readonly<Record<string, KnowledgeReceiptAttributeValue>>\n}\n\nexport interface CreateKnowledgeRetrievalReceiptInput {\n readonly runId: string\n readonly actorId?: string\n readonly profileDigest?: Sha256Digest\n readonly executionRef?: Sha256Digest\n readonly query: string\n readonly retriever: KnowledgeRetrieverIdentity\n /**\n * The snapshot the retriever searched, created once with\n * `createKnowledgeVisibilitySnapshot` and reused for every retrieval over the\n * same view. Results join against its entries; the receipt stores only its\n * reference.\n */\n readonly visibility: KnowledgeVisibilitySnapshot\n /** Where the snapshot bytes are stored, when the caller has persisted them. */\n readonly visibilityArtifact?: KnowledgeVisibilityArtifactRef\n readonly results: readonly OriginatedKnowledgeSearchResult[]\n readonly evidenceRefs?: readonly EvidenceRef[]\n readonly attributes?: Readonly<Record<string, KnowledgeReceiptAttributeValue>>\n readonly createdAt?: Date | string\n}\n\n/**\n * Returns the stored bytes of the artifact, or `undefined` when nothing is\n * stored at its uri. A thrown error is reported as a load failure.\n */\nexport type KnowledgeVisibilityArtifactLoader = (\n artifact: KnowledgeVisibilityArtifactRef,\n) => Promise<Uint8Array | undefined> | Uint8Array | undefined\n\nexport type KnowledgeVisibilityUnavailableReason =\n | 'no-artifact-reference'\n | 'missing'\n | 'load-failed'\n\n/**\n * The visibility snapshot a receipt references could not be obtained, so the\n * result-to-visibility join cannot be proven. This is distinct from a snapshot\n * that loads and fails to match.\n */\nexport class KnowledgeVisibilityUnavailableError extends Error {\n readonly reason: KnowledgeVisibilityUnavailableReason\n readonly snapshotDigest: Sha256Digest\n readonly uri?: string\n\n constructor(input: {\n reason: KnowledgeVisibilityUnavailableReason\n snapshotDigest: Sha256Digest\n uri?: string\n cause?: unknown\n }) {\n const where = input.uri === undefined ? '' : ` at '${input.uri}'`\n const detail = {\n 'no-artifact-reference': 'the receipt carries no artifact reference',\n missing: `no artifact is stored${where}`,\n 'load-failed': `the artifact${where} could not be loaded`,\n }[input.reason]\n super(\n `knowledge visibility snapshot ${input.snapshotDigest} is unavailable: ${detail}`,\n input.cause === undefined ? undefined : { cause: input.cause },\n )\n this.name = 'KnowledgeVisibilityUnavailableError'\n this.reason = input.reason\n this.snapshotDigest = input.snapshotDigest\n if (input.uri !== undefined) this.uri = input.uri\n }\n}\n\nexport type KnowledgeUseRelation =\n | 'supports'\n | 'contradicts'\n | 'extends'\n | 'rederives'\n | 'background'\n\nexport type KnowledgeConsumerKind =\n | 'decision'\n | 'artifact'\n | 'experiment'\n | 'candidate'\n | 'message'\n | 'other'\n\nexport interface KnowledgeConsumerRef {\n readonly kind: KnowledgeConsumerKind\n readonly uri: string\n readonly digest?: Sha256Digest\n}\n\nexport interface KnowledgeUsedResult {\n readonly rank: number\n readonly pageId: string\n readonly origin: PageOrigin\n readonly path: string\n readonly pageDigest: Sha256Digest\n}\n\n/**\n * Immutable proof that one retrieved page was selected for a downstream\n * decision, artifact, experiment, candidate, or message.\n */\nexport interface KnowledgeUseReceipt {\n readonly schemaVersion: typeof KNOWLEDGE_USE_RECEIPT_SCHEMA_VERSION\n readonly kind: 'knowledge-use'\n readonly digestAlgorithm: typeof KNOWLEDGE_RECEIPT_DIGEST_ALGORITHM\n readonly receiptDigest: Sha256Digest\n readonly createdAt: string\n readonly runId: string\n readonly actorId?: string\n readonly profileDigest?: Sha256Digest\n readonly executionRef?: Sha256Digest\n readonly retrievalReceiptDigest: Sha256Digest\n readonly used: KnowledgeUsedResult\n readonly relation: KnowledgeUseRelation\n readonly consumer: KnowledgeConsumerRef\n readonly evidenceRefs: readonly EvidenceRef[]\n readonly attributes: Readonly<Record<string, KnowledgeReceiptAttributeValue>>\n}\n\nexport interface CreateKnowledgeUseReceiptInput {\n readonly retrieval: KnowledgeRetrievalReceipt\n /** Exact one-based rank from the retrieval receipt. */\n readonly selectedRank: number\n readonly relation: KnowledgeUseRelation\n readonly consumer: KnowledgeConsumerRef\n readonly evidenceRefs?: readonly EvidenceRef[]\n readonly attributes?: Readonly<Record<string, KnowledgeReceiptAttributeValue>>\n readonly createdAt?: Date | string\n}\n\n/**\n * Why a retrieval influenced nothing.\n *\n * `irrelevant` means the returned pages did not bear on the question.\n * `no-use` means they did bear on it and the consumer still used none of them.\n */\nexport type KnowledgeRetrievalDispositionRelation = 'irrelevant' | 'no-use'\n\n/**\n * Immutable proof that one retrieval led to no use.\n *\n * A use receipt requires a selected rank, so a retrieval that influenced\n * nothing would otherwise leave no record at all, and \"no evidence of use\" and\n * \"evidence of no use\" would look identical in the ledger.\n */\nexport interface KnowledgeRetrievalDisposition {\n readonly schemaVersion: typeof KNOWLEDGE_USE_RECEIPT_SCHEMA_VERSION\n readonly kind: 'knowledge-retrieval-disposition'\n readonly digestAlgorithm: typeof KNOWLEDGE_RECEIPT_DIGEST_ALGORITHM\n readonly receiptDigest: Sha256Digest\n readonly createdAt: string\n readonly runId: string\n readonly actorId?: string\n readonly profileDigest?: Sha256Digest\n readonly executionRef?: Sha256Digest\n readonly retrievalReceiptDigest: Sha256Digest\n readonly relation: KnowledgeRetrievalDispositionRelation\n readonly consumer: KnowledgeConsumerRef\n readonly evidenceRefs: readonly EvidenceRef[]\n readonly attributes: Readonly<Record<string, KnowledgeReceiptAttributeValue>>\n}\n\nexport interface CreateKnowledgeRetrievalDispositionInput {\n readonly retrieval: KnowledgeRetrievalReceipt\n readonly relation: KnowledgeRetrievalDispositionRelation\n readonly consumer: KnowledgeConsumerRef\n readonly evidenceRefs?: readonly EvidenceRef[]\n readonly attributes?: Readonly<Record<string, KnowledgeReceiptAttributeValue>>\n readonly createdAt?: Date | string\n}\n\n/**\n * Create a retrieval receipt over a precomputed snapshot. Every result must\n * occur in the snapshot with the same page id and bytes; the receipt stores the\n * snapshot's reference, not its entries.\n */\nexport function createKnowledgeRetrievalReceipt(\n input: CreateKnowledgeRetrievalReceiptInput,\n): KnowledgeRetrievalReceipt {\n if (!input || typeof input !== 'object') {\n throw new TypeError('knowledge retrieval receipt input is required')\n }\n const runId = nonEmpty(input.runId, 'knowledge retrieval runId')\n const actorId = optionalText(input.actorId, 'knowledge retrieval actorId')\n const profileDigest = optionalDigest(input.profileDigest, 'knowledge retrieval profileDigest')\n const executionRef = optionalDigest(input.executionRef, 'knowledge retrieval executionRef')\n const query = nonEmpty(input.query, 'knowledge retrieval query')\n const retriever = normalizeRetriever(input.retriever)\n const index = visibilityIndexOf(input.visibility)\n const artifact =\n input.visibilityArtifact === undefined\n ? undefined\n : normalizeVisibilityArtifact(\n input.visibilityArtifact,\n 'knowledge retrieval visibilityArtifact',\n )\n const visibility: KnowledgeVisibilityRef = Object.freeze({\n snapshotDigest: index.snapshot.snapshotDigest,\n pageCount: index.snapshot.entries.length,\n ...(artifact === undefined ? {} : { artifact }),\n })\n const results = normalizeRetrievalResults(input.results, index)\n const evidenceRefs = normalizeEvidenceRefs(input.evidenceRefs ?? [])\n const attributes = normalizeAttributes(input.attributes ?? {})\n const createdAt = isoTimestamp(input.createdAt, 'knowledge retrieval createdAt')\n const material = retrievalMaterial({\n createdAt,\n runId,\n actorId,\n profileDigest,\n executionRef,\n query,\n retriever,\n visibility,\n results,\n evidenceRefs,\n attributes,\n })\n return Object.freeze({\n ...material,\n receiptDigest: canonicalCandidateDigest(material),\n })\n}\n\n/**\n * Verify the receipt's schema, canonical digest, rank continuity, finite\n * scores, and well-formed visibility reference. This proves what the receipt\n * says; it does not prove that the results occur in the referenced snapshot.\n * Use `assertKnowledgeRetrievalMatchesVisibility` or\n * `assertKnowledgeRetrievalMatchesVisibilityArtifact` for that join.\n */\nexport function verifyKnowledgeRetrievalReceipt(\n receipt: KnowledgeRetrievalReceipt,\n): KnowledgeRetrievalReceipt {\n if (!receipt || typeof receipt !== 'object') {\n throw new TypeError('knowledge retrieval receipt is required')\n }\n assertSchemaVersion(receipt.schemaVersion, 'knowledge retrieval')\n if (receipt.kind !== 'knowledge-retrieval') {\n throw new Error(`knowledge retrieval receipt kind must be 'knowledge-retrieval'`)\n }\n if (receipt.digestAlgorithm !== KNOWLEDGE_RECEIPT_DIGEST_ALGORITHM) {\n throw new Error(`unsupported knowledge retrieval digestAlgorithm '${receipt.digestAlgorithm}'`)\n }\n const visibility = normalizeVisibilityRef(receipt.visibility)\n validateReceiptResultShape(receipt.results, visibility.pageCount)\n const material = retrievalMaterial({\n createdAt: isoTimestamp(receipt.createdAt, 'knowledge retrieval createdAt'),\n runId: nonEmpty(receipt.runId, 'knowledge retrieval runId'),\n actorId: optionalText(receipt.actorId, 'knowledge retrieval actorId'),\n profileDigest: optionalDigest(receipt.profileDigest, 'knowledge retrieval profileDigest'),\n executionRef: optionalDigest(receipt.executionRef, 'knowledge retrieval executionRef'),\n query: nonEmpty(receipt.query, 'knowledge retrieval query'),\n retriever: normalizeRetriever(receipt.retriever),\n visibility,\n results: receipt.results,\n evidenceRefs: normalizeEvidenceRefs(receipt.evidenceRefs),\n attributes: normalizeAttributes(receipt.attributes),\n })\n const expected = canonicalCandidateDigest(material)\n if (expected !== receipt.receiptDigest) {\n throw new Error('knowledge retrieval receipt digest mismatch')\n }\n return receipt\n}\n\n/**\n * Prove that the receipt references exactly this snapshot and that every\n * returned result occurs in it with the same page id and bytes. Pass the\n * snapshot itself, or the originated pages to snapshot them first.\n */\nexport function assertKnowledgeRetrievalMatchesVisibility(\n receipt: KnowledgeRetrievalReceipt,\n visibility: KnowledgeVisibilitySnapshot | readonly OriginatedPage[],\n): void {\n verifyKnowledgeRetrievalReceipt(receipt)\n const index = visibilityIndexOf(\n Array.isArray(visibility)\n ? createKnowledgeVisibilitySnapshot(visibility)\n : (visibility as KnowledgeVisibilitySnapshot),\n )\n assertReceiptJoinsVisibility(receipt, index)\n}\n\n/**\n * Load the snapshot artifact the receipt references, prove the stored bytes\n * match the reference, and prove every returned result occurs in the decoded\n * snapshot. A snapshot that cannot be obtained raises\n * `KnowledgeVisibilityUnavailableError`; it is never treated as empty.\n */\nexport async function assertKnowledgeRetrievalMatchesVisibilityArtifact(\n receipt: KnowledgeRetrievalReceipt,\n loadArtifact: KnowledgeVisibilityArtifactLoader,\n): Promise<KnowledgeVisibilitySnapshot> {\n verifyKnowledgeRetrievalReceipt(receipt)\n if (typeof loadArtifact !== 'function') {\n throw new TypeError('knowledge visibility artifact loader must be a function')\n }\n const reference = receipt.visibility\n if (reference.artifact === undefined) {\n throw new KnowledgeVisibilityUnavailableError({\n reason: 'no-artifact-reference',\n snapshotDigest: reference.snapshotDigest,\n })\n }\n const artifact = reference.artifact\n let bytes: Uint8Array | undefined\n try {\n bytes = await loadArtifact(artifact)\n } catch (error) {\n throw new KnowledgeVisibilityUnavailableError({\n reason: 'load-failed',\n snapshotDigest: reference.snapshotDigest,\n uri: artifact.uri,\n cause: error,\n })\n }\n if (bytes === undefined) {\n throw new KnowledgeVisibilityUnavailableError({\n reason: 'missing',\n snapshotDigest: reference.snapshotDigest,\n uri: artifact.uri,\n })\n }\n if (!(bytes instanceof Uint8Array)) {\n throw new TypeError(`knowledge visibility artifact '${artifact.uri}' loaded a non-byte value`)\n }\n if (bytes.byteLength !== artifact.byteLength) {\n throw new Error(\n `knowledge visibility artifact '${artifact.uri}' byteLength mismatch: expected ${artifact.byteLength}, observed ${bytes.byteLength}`,\n )\n }\n if (sha256Bytes(bytes) !== artifact.digest) {\n throw new Error(`knowledge visibility artifact '${artifact.uri}' digest mismatch`)\n }\n const snapshot = decodeKnowledgeVisibilitySnapshot(bytes)\n if (snapshot.snapshotDigest !== reference.snapshotDigest) {\n throw new Error(\n `knowledge visibility artifact '${artifact.uri}' holds snapshot ${snapshot.snapshotDigest}, not ${reference.snapshotDigest}`,\n )\n }\n assertReceiptJoinsVisibility(receipt, visibilityIndexOf(snapshot))\n return snapshot\n}\n\n/** Create a downstream-use receipt for one exact ranked result. */\nexport function createKnowledgeUseReceipt(\n input: CreateKnowledgeUseReceiptInput,\n): KnowledgeUseReceipt {\n if (!input || typeof input !== 'object') {\n throw new TypeError('knowledge use receipt input is required')\n }\n const retrieval = verifyKnowledgeRetrievalReceipt(input.retrieval)\n if (!Number.isSafeInteger(input.selectedRank) || input.selectedRank < 1) {\n throw new TypeError('knowledge use selectedRank must be a positive safe integer')\n }\n const selected = retrieval.results.find((result) => result.rank === input.selectedRank)\n if (!selected) {\n throw new Error(\n `knowledge use selectedRank ${input.selectedRank} was not returned by retrieval ${retrieval.receiptDigest}`,\n )\n }\n const relation = validateUseRelation(input.relation)\n const consumer = normalizeConsumer(input.consumer)\n const evidenceRefs = normalizeEvidenceRefs(input.evidenceRefs ?? [])\n const attributes = normalizeAttributes(input.attributes ?? {})\n const createdAt = isoTimestamp(input.createdAt, 'knowledge use createdAt')\n const used = Object.freeze({\n rank: selected.rank,\n pageId: selected.pageId,\n origin: selected.origin,\n path: selected.path,\n pageDigest: selected.pageDigest,\n })\n const material = useMaterial({\n createdAt,\n retrieval,\n used,\n relation,\n consumer,\n evidenceRefs,\n attributes,\n })\n return Object.freeze({\n ...material,\n receiptDigest: canonicalCandidateDigest(material),\n })\n}\n\n/** Verify one use receipt against the exact retrieval that authorized it. */\nexport function verifyKnowledgeUseReceipt(\n receipt: KnowledgeUseReceipt,\n retrieval: KnowledgeRetrievalReceipt,\n): KnowledgeUseReceipt {\n if (!receipt || typeof receipt !== 'object') {\n throw new TypeError('knowledge use receipt is required')\n }\n const verifiedRetrieval = verifyKnowledgeRetrievalReceipt(retrieval)\n assertSchemaVersion(receipt.schemaVersion, 'knowledge use')\n if (receipt.kind !== 'knowledge-use') {\n throw new Error(`knowledge use receipt kind must be 'knowledge-use'`)\n }\n if (receipt.digestAlgorithm !== KNOWLEDGE_RECEIPT_DIGEST_ALGORITHM) {\n throw new Error(`unsupported knowledge use digestAlgorithm '${receipt.digestAlgorithm}'`)\n }\n if (receipt.retrievalReceiptDigest !== verifiedRetrieval.receiptDigest) {\n throw new Error('knowledge use receipt references a different retrieval receipt')\n }\n const selected = verifiedRetrieval.results.find((result) => result.rank === receipt.used.rank)\n if (\n !selected ||\n selected.pageId !== receipt.used.pageId ||\n selected.origin !== receipt.used.origin ||\n selected.path !== receipt.used.path ||\n selected.pageDigest !== receipt.used.pageDigest\n ) {\n throw new Error('knowledge use receipt selected result does not match the retrieval receipt')\n }\n const material = useMaterial({\n createdAt: isoTimestamp(receipt.createdAt, 'knowledge use createdAt'),\n retrieval: verifiedRetrieval,\n used: receipt.used,\n relation: validateUseRelation(receipt.relation),\n consumer: normalizeConsumer(receipt.consumer),\n evidenceRefs: normalizeEvidenceRefs(receipt.evidenceRefs),\n attributes: normalizeAttributes(receipt.attributes),\n })\n const expected = canonicalCandidateDigest(material)\n if (expected !== receipt.receiptDigest) {\n throw new Error('knowledge use receipt digest mismatch')\n }\n return receipt\n}\n\n/** Record that one retrieval led to no use, with no rank to select. */\nexport function createKnowledgeRetrievalDisposition(\n input: CreateKnowledgeRetrievalDispositionInput,\n): KnowledgeRetrievalDisposition {\n if (!input || typeof input !== 'object') {\n throw new TypeError('knowledge retrieval disposition input is required')\n }\n const material = dispositionMaterial({\n createdAt: isoTimestamp(input.createdAt, 'knowledge retrieval disposition createdAt'),\n retrieval: verifyKnowledgeRetrievalReceipt(input.retrieval),\n relation: validateDispositionRelation(input.relation),\n consumer: normalizeConsumer(input.consumer),\n evidenceRefs: normalizeEvidenceRefs(input.evidenceRefs ?? []),\n attributes: normalizeAttributes(input.attributes ?? {}),\n })\n return Object.freeze({ ...material, receiptDigest: canonicalCandidateDigest(material) })\n}\n\n/** Verify one disposition against the exact retrieval that authorized it. */\nexport function verifyKnowledgeRetrievalDisposition(\n disposition: KnowledgeRetrievalDisposition,\n retrieval: KnowledgeRetrievalReceipt,\n): KnowledgeRetrievalDisposition {\n if (!disposition || typeof disposition !== 'object') {\n throw new TypeError('knowledge retrieval disposition is required')\n }\n const verifiedRetrieval = verifyKnowledgeRetrievalReceipt(retrieval)\n assertSchemaVersion(disposition.schemaVersion, 'knowledge retrieval disposition')\n if (disposition.kind !== 'knowledge-retrieval-disposition') {\n throw new Error(\n `knowledge retrieval disposition kind must be 'knowledge-retrieval-disposition'`,\n )\n }\n if (disposition.digestAlgorithm !== KNOWLEDGE_RECEIPT_DIGEST_ALGORITHM) {\n throw new Error(\n `unsupported knowledge retrieval disposition digestAlgorithm '${disposition.digestAlgorithm}'`,\n )\n }\n if (disposition.retrievalReceiptDigest !== verifiedRetrieval.receiptDigest) {\n throw new Error('knowledge retrieval disposition references a different retrieval receipt')\n }\n const material = dispositionMaterial({\n createdAt: isoTimestamp(disposition.createdAt, 'knowledge retrieval disposition createdAt'),\n retrieval: verifiedRetrieval,\n relation: validateDispositionRelation(disposition.relation),\n consumer: normalizeConsumer(disposition.consumer),\n evidenceRefs: normalizeEvidenceRefs(disposition.evidenceRefs),\n attributes: normalizeAttributes(disposition.attributes),\n })\n if (canonicalCandidateDigest(material) !== disposition.receiptDigest) {\n throw new Error('knowledge retrieval disposition digest mismatch')\n }\n return disposition\n}\n\nfunction assertReceiptJoinsVisibility(\n receipt: KnowledgeRetrievalReceipt,\n index: VisibilityIndex,\n): void {\n if (\n index.snapshot.snapshotDigest !== receipt.visibility.snapshotDigest ||\n index.snapshot.entries.length !== receipt.visibility.pageCount\n ) {\n throw new Error('knowledge retrieval receipt does not match the supplied visibility snapshot')\n }\n for (const result of receipt.results) {\n const entry = index.byIdentity.get(visibilityIdentity(result.origin, result.path))\n if (!entry || entry.pageId !== result.pageId || entry.pageDigest !== result.pageDigest) {\n throw new Error(\n `knowledge retrieval result rank ${result.rank} is not in the visibility snapshot`,\n )\n }\n }\n}\n\nfunction retrievalMaterial(input: {\n createdAt: string\n runId: string\n actorId?: string\n profileDigest?: Sha256Digest\n executionRef?: Sha256Digest\n query: string\n retriever: KnowledgeRetrieverIdentity\n visibility: KnowledgeVisibilityRef\n results: readonly KnowledgeRetrievalResultReceipt[]\n evidenceRefs: readonly EvidenceRef[]\n attributes: Readonly<Record<string, KnowledgeReceiptAttributeValue>>\n}) {\n return {\n schemaVersion: KNOWLEDGE_USE_RECEIPT_SCHEMA_VERSION,\n kind: 'knowledge-retrieval' as const,\n digestAlgorithm: KNOWLEDGE_RECEIPT_DIGEST_ALGORITHM,\n createdAt: input.createdAt,\n runId: input.runId,\n ...(input.actorId === undefined ? {} : { actorId: input.actorId }),\n ...(input.profileDigest === undefined ? {} : { profileDigest: input.profileDigest }),\n ...(input.executionRef === undefined ? {} : { executionRef: input.executionRef }),\n query: input.query,\n retriever: input.retriever,\n visibility: input.visibility,\n results: input.results,\n evidenceRefs: input.evidenceRefs,\n attributes: input.attributes,\n }\n}\n\n/**\n * The actor identity a downstream record inherits from the retrieval that\n * authorized it. A record that re-declared these could disagree with the\n * receipt it references.\n */\nfunction retrievalIdentity(retrieval: KnowledgeRetrievalReceipt) {\n return {\n runId: retrieval.runId,\n ...(retrieval.actorId === undefined ? {} : { actorId: retrieval.actorId }),\n ...(retrieval.profileDigest === undefined ? {} : { profileDigest: retrieval.profileDigest }),\n ...(retrieval.executionRef === undefined ? {} : { executionRef: retrieval.executionRef }),\n retrievalReceiptDigest: retrieval.receiptDigest,\n }\n}\n\nfunction useMaterial(input: {\n createdAt: string\n retrieval: KnowledgeRetrievalReceipt\n used: KnowledgeUsedResult\n relation: KnowledgeUseRelation\n consumer: KnowledgeConsumerRef\n evidenceRefs: readonly EvidenceRef[]\n attributes: Readonly<Record<string, KnowledgeReceiptAttributeValue>>\n}) {\n return {\n schemaVersion: KNOWLEDGE_USE_RECEIPT_SCHEMA_VERSION,\n kind: 'knowledge-use' as const,\n digestAlgorithm: KNOWLEDGE_RECEIPT_DIGEST_ALGORITHM,\n createdAt: input.createdAt,\n ...retrievalIdentity(input.retrieval),\n used: input.used,\n relation: input.relation,\n consumer: input.consumer,\n evidenceRefs: input.evidenceRefs,\n attributes: input.attributes,\n }\n}\n\nfunction dispositionMaterial(input: {\n createdAt: string\n retrieval: KnowledgeRetrievalReceipt\n relation: KnowledgeRetrievalDispositionRelation\n consumer: KnowledgeConsumerRef\n evidenceRefs: readonly EvidenceRef[]\n attributes: Readonly<Record<string, KnowledgeReceiptAttributeValue>>\n}) {\n return {\n schemaVersion: KNOWLEDGE_USE_RECEIPT_SCHEMA_VERSION,\n kind: 'knowledge-retrieval-disposition' as const,\n digestAlgorithm: KNOWLEDGE_RECEIPT_DIGEST_ALGORITHM,\n createdAt: input.createdAt,\n ...retrievalIdentity(input.retrieval),\n relation: input.relation,\n consumer: input.consumer,\n evidenceRefs: input.evidenceRefs,\n attributes: input.attributes,\n }\n}\n\nfunction validateDispositionRelation(\n value: KnowledgeRetrievalDispositionRelation,\n): KnowledgeRetrievalDispositionRelation {\n if (value !== 'irrelevant' && value !== 'no-use') {\n throw new TypeError(`knowledge retrieval disposition relation is invalid: ${String(value)}`)\n }\n return value\n}\n\nfunction normalizeRetrievalResults(\n results: readonly OriginatedKnowledgeSearchResult[],\n index: VisibilityIndex,\n): readonly KnowledgeRetrievalResultReceipt[] {\n if (!Array.isArray(results)) throw new TypeError('knowledge retrieval results must be an array')\n const seenRanks = new Set<number>()\n const seenPages = new Set<string>()\n const normalized = results.map((result, position) => {\n if (!result || typeof result !== 'object') {\n throw new TypeError(`knowledge retrieval results[${position}] must be an object`)\n }\n if (!Number.isSafeInteger(result.rank) || result.rank < 1) {\n throw new TypeError(`knowledge retrieval results[${position}].rank must be positive`)\n }\n if (seenRanks.has(result.rank)) {\n throw new Error(`knowledge retrieval repeats rank ${result.rank}`)\n }\n seenRanks.add(result.rank)\n const origin = validateOrigin(result.origin, `knowledge retrieval results[${position}].origin`)\n validateKnowledgePage(result.page)\n const identity = visibilityIdentity(origin, result.page.path)\n if (seenPages.has(identity)) {\n throw new Error(\n `knowledge retrieval repeats page '${result.page.path}' at origin '${origin}'`,\n )\n }\n seenPages.add(identity)\n const visibleEntry = index.byIdentity.get(identity)\n if (!visibleEntry) {\n throw new Error(\n `knowledge retrieval result '${result.page.path}' at origin '${origin}' was not visible`,\n )\n }\n const pageDigest = knowledgePageDigest(result.page)\n if (visibleEntry.pageId !== result.page.id || visibleEntry.pageDigest !== pageDigest) {\n throw new Error(\n `knowledge retrieval result '${result.page.path}' does not match its visibility snapshot`,\n )\n }\n assertResultScores(result, position)\n return Object.freeze({\n rank: result.rank,\n pageId: result.page.id,\n origin,\n path: result.page.path,\n pageDigest,\n rrfScore: result.rrfScore,\n normalizedScore: result.normalizedScore,\n snippet: typeof result.snippet === 'string' ? result.snippet : '',\n reasons: Object.freeze(\n result.reasons.map((reason: string, reasonIndex: number) =>\n nonEmpty(reason, `knowledge retrieval results[${position}].reasons[${reasonIndex}]`),\n ),\n ),\n })\n })\n normalized.sort((left, right) => left.rank - right.rank)\n assertContiguousRanks(normalized)\n return Object.freeze(normalized)\n}\n\nfunction validateReceiptResultShape(\n results: readonly KnowledgeRetrievalResultReceipt[],\n pageCount: number,\n): void {\n if (!Array.isArray(results)) throw new TypeError('knowledge retrieval results must be an array')\n if (results.length > pageCount) {\n throw new Error(\n `knowledge retrieval returns ${results.length} results from ${pageCount} visible pages`,\n )\n }\n assertContiguousRanks(results)\n const seen = new Set<string>()\n results.forEach((result, position) => {\n if (!result || typeof result !== 'object') {\n throw new TypeError(`knowledge retrieval results[${position}] must be an object`)\n }\n const origin = validateOrigin(result.origin, `knowledge retrieval results[${position}].origin`)\n const identity = visibilityIdentity(\n origin,\n nonEmpty(result.path, `knowledge retrieval results[${position}].path`),\n )\n if (seen.has(identity)) {\n throw new Error(`knowledge retrieval repeats visible page '${result.path}'`)\n }\n seen.add(identity)\n nonEmpty(result.pageId, `knowledge retrieval results[${position}].pageId`)\n digest(result.pageDigest, `knowledge retrieval results[${position}].pageDigest`)\n assertResultScores(result, position)\n if (typeof result.snippet !== 'string') {\n throw new TypeError(`knowledge retrieval results[${position}].snippet must be a string`)\n }\n if (!Array.isArray(result.reasons)) {\n throw new TypeError(`knowledge retrieval results[${position}].reasons must be an array`)\n }\n })\n}\n\n/**\n * Ranks a retriever returned: one-based, unique, and contiguous, so a receipt\n * cannot hide a result by omitting its rank.\n */\nfunction assertContiguousRanks(results: readonly { readonly rank: number }[]): void {\n results.forEach((result, position) => {\n if (result.rank !== position + 1) {\n throw new Error(\n `knowledge retrieval ranks must be contiguous from 1; expected ${position + 1}, observed ${result.rank}`,\n )\n }\n })\n}\n\n/** Scores a receipt may carry: finite, with the normalized score inside [0,1]. */\nfunction assertResultScores(\n result: { readonly rrfScore: number; readonly normalizedScore: number },\n position: number,\n): void {\n finite(result.rrfScore, `knowledge retrieval results[${position}].rrfScore`)\n finite(result.normalizedScore, `knowledge retrieval results[${position}].normalizedScore`)\n if (result.normalizedScore < 0 || result.normalizedScore > 1) {\n throw new TypeError(`knowledge retrieval results[${position}].normalizedScore must be in [0,1]`)\n }\n}\n\nfunction normalizeRetriever(input: KnowledgeRetrieverIdentity): KnowledgeRetrieverIdentity {\n if (!input || typeof input !== 'object') {\n throw new TypeError('knowledge retriever identity is required')\n }\n return Object.freeze({\n id: nonEmpty(input.id, 'knowledge retriever id'),\n version: nonEmpty(input.version, 'knowledge retriever version'),\n configDigest: digest(input.configDigest, 'knowledge retriever configDigest'),\n })\n}\n\nfunction normalizeConsumer(input: KnowledgeConsumerRef): KnowledgeConsumerRef {\n if (!input || typeof input !== 'object') {\n throw new TypeError('knowledge consumer reference is required')\n }\n const kinds: readonly KnowledgeConsumerKind[] = [\n 'decision',\n 'artifact',\n 'experiment',\n 'candidate',\n 'message',\n 'other',\n ]\n if (!kinds.includes(input.kind)) {\n throw new TypeError(`knowledge consumer kind is invalid: ${String(input.kind)}`)\n }\n return Object.freeze({\n kind: input.kind,\n uri: nonEmpty(input.uri, 'knowledge consumer uri'),\n ...(input.digest === undefined\n ? {}\n : { digest: digest(input.digest, 'knowledge consumer digest') }),\n })\n}\n\nfunction normalizeEvidenceRefs(values: readonly EvidenceRef[]): readonly EvidenceRef[] {\n if (!Array.isArray(values)) throw new TypeError('knowledge evidenceRefs must be an array')\n const allowed: readonly EvidenceRef['kind'][] = ['span', 'event', 'artifact', 'finding', 'metric']\n return Object.freeze(\n values.map((value, index) => {\n if (!value || typeof value !== 'object' || !allowed.includes(value.kind)) {\n throw new TypeError(`knowledge evidenceRefs[${index}].kind is invalid`)\n }\n return Object.freeze({\n kind: value.kind,\n uri: nonEmpty(value.uri, `knowledge evidenceRefs[${index}].uri`),\n ...(value.excerpt === undefined\n ? {}\n : { excerpt: nonEmpty(value.excerpt, `knowledge evidenceRefs[${index}].excerpt`) }),\n })\n }),\n )\n}\n\nfunction normalizeAttributes(\n input: Readonly<Record<string, KnowledgeReceiptAttributeValue>>,\n): Readonly<Record<string, KnowledgeReceiptAttributeValue>> {\n if (!input || typeof input !== 'object' || Array.isArray(input)) {\n throw new TypeError('knowledge receipt attributes must be an object')\n }\n const normalized: Record<string, KnowledgeReceiptAttributeValue> = {}\n for (const [key, value] of Object.entries(input)) {\n const name = nonEmpty(key, 'knowledge receipt attribute key')\n if (\n value !== null &&\n typeof value !== 'string' &&\n typeof value !== 'number' &&\n typeof value !== 'boolean'\n ) {\n throw new TypeError(`knowledge receipt attribute '${name}' has an unsupported value`)\n }\n if (typeof value === 'number') finite(value, `knowledge receipt attribute '${name}'`)\n normalized[name] = value\n }\n return Object.freeze(normalized)\n}\n\nfunction validateUseRelation(value: KnowledgeUseRelation): KnowledgeUseRelation {\n const allowed: readonly KnowledgeUseRelation[] = [\n 'supports',\n 'contradicts',\n 'extends',\n 'rederives',\n 'background',\n ]\n if (!allowed.includes(value)) {\n throw new TypeError(`knowledge use relation is invalid: ${String(value)}`)\n }\n return value\n}\n\nfunction optionalDigest(value: unknown, label: string): Sha256Digest | undefined {\n return value === undefined ? undefined : digest(value, label)\n}\n\nfunction optionalText(value: unknown, label: string): string | undefined {\n return value === undefined ? undefined : nonEmpty(value, label)\n}\n\nfunction finite(value: unknown, label: string): asserts value is number {\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n throw new TypeError(`${label} must be a finite number`)\n }\n}\n\nfunction isoTimestamp(value: Date | string | undefined, label: string): string {\n const date = value === undefined ? new Date() : value instanceof Date ? value : new Date(value)\n if (!Number.isFinite(date.getTime())) throw new TypeError(`${label} must be a valid timestamp`)\n return date.toISOString()\n}\n","/**\n * Provider-neutral knowledge tools.\n *\n * Knowledge owns what each tool does; a runtime only transports the definitions\n * and the calls. The shape is `ToolDefinition` from `@tangle-network/agent-interface`,\n * so no provider vocabulary reaches this package and no knowledge behavior\n * reaches a provider adapter.\n *\n * Every search mints a retrieval receipt. Configured receipt capture also\n * persists the exact visibility snapshot before delivering the receipt.\n */\n\nimport { join } from 'node:path'\nimport { pathToFileURL } from 'node:url'\nimport { sha256DigestSchema, type ToolDefinition } from '@tangle-network/agent-interface'\nimport { z } from 'zod'\nimport {\n parseKnowledgeCitationReference,\n resolveKnowledgeCitation,\n resolveRunScopedCitations,\n} from './citation-resolution'\nimport { isMissingFile, readRegularFileWithinRoot, writeFileDurableWithinRoot } from './durable-fs'\nimport { buildKnowledgeBrief, type KnowledgeBriefOptions } from './knowledge-brief'\nimport {\n createKnowledgeRetrievalReceipt,\n createKnowledgeVisibilitySnapshot,\n encodeKnowledgeVisibilitySnapshot,\n type KnowledgeRetrievalReceipt,\n knowledgeVisibilityArtifactRef,\n} from './knowledge-use-receipts'\nimport { knowledgePageDigest } from './knowledge-visibility'\nimport { withKnowledgeMutation } from './mutation-lock'\nimport { normalizePagesDirectory } from './pages-directory'\nimport { applyKnowledgeWriteBlocks, type KnowledgeWriteIntakeRequest } from './proposals'\nimport type { OriginatedPage, RunScopedStores } from './run-scoped'\nimport { parseKnowledgeWriteBlocks } from './write-protocol'\n\nexport interface CreateKnowledgeToolsOptions {\n readonly stores: RunScopedStores\n /** The run whose store is written and whose chain is read. */\n readonly runId: string\n /**\n * Version of this package the host is running. A bundled build cannot read\n * its own manifest, and a receipt that guessed the version would be a\n * receipt that lies about what ranked the results.\n */\n readonly retrieverVersion: string\n readonly actorId?: string\n readonly pagesDirectory?: string\n /** Intake settings for `knowledge_record`. Absent leaves the write ungated. */\n readonly intake?: Omit<KnowledgeWriteIntakeRequest, 'inheritedPages'>\n /** Retain prior and new bytes for every completed knowledge_record transaction. */\n readonly retainHistory?: boolean\n /** Brief settings for `knowledge_search`, overridden per call by the tool input. */\n readonly brief?: Omit<KnowledgeBriefOptions, 'limit'>\n /** Receipt sink. Exact visibility bytes are persisted in the run store before this is called. */\n readonly recordRetrieval?: (receipt: KnowledgeRetrievalReceipt) => Promise<void> | void\n readonly now?: () => Date\n}\n\nconst searchInput = z.object({\n question: z.string().min(1),\n limit: z.int().min(1).max(50).optional(),\n excludeInvalidated: z\n .boolean()\n .optional()\n .describe('False includes refuted pages for historical research.'),\n tags: z.array(z.string()).optional(),\n kinds: z.array(z.string()).optional(),\n})\nconst readInput = z.object({ pageId: z.string().min(1) })\nconst recordInput = z.object({\n expectedPageDigests: z\n .record(z.string().min(1), sha256DigestSchema.nullable())\n .optional()\n .describe(\n 'For each existing page, pass its path and pageDigest from knowledge_read. Null requires a new page. Missing entries permit new pages only.',\n ),\n proposal: z\n .string()\n .min(1)\n .describe(\n 'One or more complete FILE blocks. Each begins with ---FILE: <page-path>--- and ends with ---END FILE---, each on its own line. Put the page content between them. Every block must be valid; malformed or empty proposals write nothing and return an error.',\n ),\n})\nconst resolveInput = z.object({ references: z.array(z.string().min(1)).min(1) })\n\n/**\n * The four tools an agent needs to use a knowledge store: search, read, record,\n * resolve.\n */\nexport function createKnowledgeTools(options: CreateKnowledgeToolsOptions): ToolDefinition[] {\n const { stores, runId } = options\n if (!stores || typeof stores.loadChain !== 'function') {\n throw new TypeError('knowledge tools require run-scoped stores')\n }\n if (typeof runId !== 'string' || runId.trim().length === 0) {\n throw new TypeError('knowledge tools require a runId')\n }\n if (typeof options.retrieverVersion !== 'string' || options.retrieverVersion.trim() === '') {\n throw new TypeError('knowledge tools require the running retrieverVersion')\n }\n const pages =\n options.pagesDirectory === undefined ? {} : { pagesDirectory: options.pagesDirectory }\n const pagesDirectory = normalizePagesDirectory(options.pagesDirectory)\n\n return [\n tool(\n 'knowledge_search',\n 'Search visible knowledge with unambiguous citation handles. Optionally include refuted history or filter tags and kinds.',\n searchInput,\n async (input) => {\n const chain = await stores.loadChain(runId)\n const brief = buildKnowledgeBrief(chain, input.question, {\n ...options.brief,\n ...(input.limit === undefined ? {} : { limit: input.limit }),\n ...(input.excludeInvalidated === undefined\n ? {}\n : { excludeInvalidated: input.excludeInvalidated }),\n ...(input.tags === undefined ? {} : { tags: input.tags }),\n ...(input.kinds === undefined ? {} : { kinds: input.kinds }),\n })\n const visibility = createKnowledgeVisibilitySnapshot(chain)\n const visibilityArtifact = options.recordRetrieval\n ? await persistVisibility(stores.storePath(runId), visibility)\n : undefined\n const receipt = createKnowledgeRetrievalReceipt({\n runId,\n ...(options.actorId === undefined ? {} : { actorId: options.actorId }),\n query: brief.question,\n retriever: {\n id: brief.retrieverId,\n version: options.retrieverVersion,\n configDigest: brief.retrieverConfigDigest,\n },\n visibility,\n ...(visibilityArtifact ? { visibilityArtifact } : {}),\n results: brief.results,\n createdAt: options.now?.(),\n })\n await options.recordRetrieval?.(receipt)\n return {\n text: brief.text,\n citationIds: brief.citationIds,\n retrievalReceiptDigest: receipt.receiptDigest,\n receipt,\n }\n },\n ),\n\n tool(\n 'knowledge_read',\n 'Read one page by its id, optionally qualified with here::, shared:: or inherited:<runId>::.',\n readInput,\n async (input) => {\n const resolution = resolveKnowledgeCitation(\n await stores.loadChain(runId),\n parseKnowledgeCitationReference(input.pageId),\n )\n return {\n status: resolution.status,\n page:\n resolution.resolved === undefined\n ? null\n : {\n pageId: resolution.resolved.page.id,\n origin: resolution.resolved.origin,\n path: resolution.resolved.page.path,\n title: resolution.resolved.page.title,\n pageDigest: knowledgePageDigest(resolution.resolved.page),\n text: resolution.resolved.page.text,\n },\n candidates: resolution.candidates.map((candidate) => ({\n pageId: candidate.pageId,\n origin: candidate.origin,\n path: candidate.page.path,\n })),\n }\n },\n ),\n\n tool(\n 'knowledge_record',\n `Write pages into this run's store. Use complete blocks exactly like:\\n---FILE: ${pagesDirectory}/example.md---\\n# Example\\nPage content.\\n---END FILE---\\nUse paths under ${pagesDirectory}/. Both delimiters must be on their own lines. To update a page, first knowledge_read it and pass expectedPageDigests[path] = pageDigest. Stale edits and malformed, unsafe, or empty proposals are rejected before writing any pages.`,\n recordInput,\n async (input) => {\n const parsed = parseKnowledgeWriteBlocks(input.proposal, [`${pagesDirectory}/`])\n // Tool success must mean the complete proposal was admitted, not a silent partial write.\n if (parsed.blocks.length === 0 || parsed.warnings.length > 0) {\n throw new Error(\n `knowledge_record rejected the proposal without writing any pages. Use ---FILE: ${pagesDirectory}/example.md--- followed by content and ---END FILE---, each delimiter on its own line. ${parsed.warnings.join(' ')}`,\n )\n }\n const intake = options.intake\n return applyKnowledgeWriteBlocks(stores.storePath(runId), input.proposal, {\n ...pages,\n actorId: options.actorId,\n runId,\n expectedPageDigests: input.expectedPageDigests ?? {},\n retainHistory: options.retainHistory ?? true,\n ...(intake === undefined\n ? {}\n : { intake: { ...intake, inheritedPages: await inheritedOf(stores, runId) } }),\n })\n },\n ),\n\n tool(\n 'knowledge_resolve',\n 'Resolve page ids against everything this run can see, without hiding an ambiguity.',\n resolveInput,\n async (input) => ({\n resolutions: (\n await resolveRunScopedCitations(\n stores,\n runId,\n input.references.map((reference) => parseKnowledgeCitationReference(reference)),\n )\n ).map((resolution) => ({\n pageId: resolution.reference.pageId,\n ...(resolution.reference.origin === undefined\n ? {}\n : { origin: resolution.reference.origin }),\n status: resolution.status,\n candidates: resolution.candidates.map((candidate) => ({\n pageId: candidate.pageId,\n origin: candidate.origin,\n path: candidate.page.path,\n })),\n })),\n }),\n ),\n ]\n}\n\n/** Everything the run can see except what it wrote, which the write path reads itself. */\nasync function inheritedOf(\n stores: RunScopedStores,\n runId: string,\n): Promise<readonly OriginatedPage[]> {\n return (await stores.loadChain(runId)).filter((entry) => entry.origin !== 'here')\n}\n\nfunction tool<Schema extends z.ZodType>(\n name: string,\n description: string,\n inputSchema: Schema,\n handler: (input: z.infer<Schema>) => Promise<unknown>,\n): ToolDefinition {\n return {\n name,\n description,\n inputSchema,\n inputSchemaJson: z.toJSONSchema(inputSchema) as Record<string, unknown>,\n handler: (input: unknown) => handler(inputSchema.parse(input)),\n }\n}\n\n/** Snapshot artifacts are immutable evidence, separate from authoritative KB state. */\nasync function persistVisibility(\n root: string,\n snapshot: ReturnType<typeof createKnowledgeVisibilitySnapshot>,\n) {\n const bytes = encodeKnowledgeVisibilitySnapshot(snapshot)\n const path = `.agent-knowledge/retrieval-visibility/${snapshot.snapshotDigest.replace('sha256:', '')}.json`\n await withKnowledgeMutation(root, async () => {\n try {\n const existing = await readRegularFileWithinRoot(root, path)\n if (!Buffer.from(existing.bytes).equals(Buffer.from(bytes))) {\n throw new Error('stored knowledge visibility artifact does not match its content identity')\n }\n } catch (error) {\n if (!isMissingFile(error)) throw error\n await writeFileDurableWithinRoot(root, path, Buffer.from(bytes))\n }\n })\n return knowledgeVisibilityArtifactRef({ uri: pathToFileURL(join(root, path)).href, bytes })\n}\n","/**\n * Run-scope to shared-scope promotion.\n *\n * A run writes only its own store. Knowledge reaches the curated shared store\n * through this call and no other, and every promotion leaves a record naming\n * the source run, the promoted bytes, the support carried with them, the actor,\n * and the reason.\n *\n * A claim's cited support travels with it. Promoting a claim while leaving the\n * run-local pages it cites behind is what turns a resolved citation into a\n * dangling one, so the closure of cited pages is carried and the promotion is\n * refused when any citation would not resolve in the target.\n */\nimport { canonicalCandidateDigest, type Sha256Digest } from '@tangle-network/agent-interface'\nimport {\n assertKnowledgeCitationsResolved,\n parseKnowledgeCitationReference,\n resolveKnowledgeCitation,\n} from './citation-resolution'\nimport { isMissingFile, readRegularFileWithinRoot, writeJsonDurableWithinRoot } from './durable-fs'\nimport { commitKnowledgeFileMutations } from './file-transaction'\nimport { knowledgePageDigest } from './knowledge-use-receipts'\nimport { withKnowledgeMutation } from './mutation-lock'\nimport { type KnowledgePagesOptions, normalizePagesDirectory } from './pages-directory'\nimport {\n type OriginatedPage,\n originatedPages,\n type PageOrigin,\n type RunScopedStores,\n} from './run-scoped'\nimport { initKnowledgeBase, knowledgePageFromMarkdown, loadKnowledgePages } from './store'\nimport type { KnowledgeId, KnowledgePage } from './types'\n\nexport const KNOWLEDGE_PROMOTION_SCHEMA_VERSION = '1.0.0' as const\nexport const KNOWLEDGE_PROMOTION_DIGEST_ALGORITHM = 'rfc8785-sha256' as const\n\n/** Root-relative directory holding one JSON record per promotion. */\nexport const KNOWLEDGE_PROMOTIONS_DIRECTORY = '.agent-knowledge/promotions'\n\nexport type KnowledgePromotionErrorCode =\n | 'unknown-page'\n | 'ambiguous-support'\n | 'id-conflict'\n | 'path-conflict'\n\n/** A promotion that cannot be performed exactly as asked. */\nexport class KnowledgePromotionError extends Error {\n readonly code: KnowledgePromotionErrorCode\n\n constructor(code: KnowledgePromotionErrorCode, message: string) {\n super(message)\n this.name = 'KnowledgePromotionError'\n this.code = code\n }\n}\n\nexport interface KnowledgePromotionEntry {\n readonly pageId: KnowledgeId\n readonly path: string\n /** Where the page was read from in the source run's chain. */\n readonly sourceOrigin: PageOrigin\n readonly pageDigest: Sha256Digest\n /** False when the page travelled only because a promoted page cites it. */\n readonly requested: boolean\n}\n\n/** Immutable record of one promotion into a shared store. */\nexport interface KnowledgePromotionRecord {\n readonly schemaVersion: typeof KNOWLEDGE_PROMOTION_SCHEMA_VERSION\n readonly kind: 'knowledge-promotion'\n readonly digestAlgorithm: typeof KNOWLEDGE_PROMOTION_DIGEST_ALGORITHM\n readonly recordDigest: Sha256Digest\n readonly createdAt: string\n readonly runId: string\n readonly actor: string\n readonly reason: string\n /** Promoted pages first, then carried support, each group in path order. */\n readonly entries: readonly KnowledgePromotionEntry[]\n}\n\nexport interface PromoteRunScopedPagesOptions extends KnowledgePagesOptions {\n /** Stable ids of the pages this run authored and wants in shared scope. */\n readonly pageIds: readonly KnowledgeId[]\n /** The curated store every run reads and no run writes directly. */\n readonly sharedRoot: string\n /** Who decided to promote. */\n readonly actor: string\n /** Why this knowledge belongs in shared scope. */\n readonly reason: string\n readonly now?: () => Date\n}\n\n/**\n * Promote pages a run authored into the shared store, with their cited support.\n *\n * Support keeps its own evidence fields exactly as written, so a promoted claim\n * cannot inherit a confidence its support does not carry. Pages travel as the\n * bytes their store holds.\n *\n * Re-running the same promotion is safe: unchanged pages produce no file\n * mutation and the record is content-addressed, so it lands at the same path\n * with the same bytes.\n */\nexport async function promoteRunScopedPages(\n stores: RunScopedStores,\n runId: string,\n options: PromoteRunScopedPagesOptions,\n): Promise<KnowledgePromotionRecord> {\n const pagesDirectory = normalizePagesDirectory(options.pagesDirectory)\n const sharedRoot = nonEmpty(options.sharedRoot, 'promotion sharedRoot')\n const actor = nonEmpty(options.actor, 'promotion actor')\n const reason = nonEmpty(options.reason, 'promotion reason')\n if (!Array.isArray(options.pageIds) || options.pageIds.length === 0) {\n throw new TypeError('promotion pageIds must name at least one page')\n }\n\n const chain = await stores.loadChain(runId)\n const travellers = collectTravellers(chain, options.pageIds)\n const mutations = await Promise.all(\n travellers.map(async (traveller) => ({\n path: traveller.entry.page.path,\n content: await readPageBytes(stores, runId, traveller.entry, pagesDirectory),\n })),\n )\n\n await initKnowledgeBase(sharedRoot)\n return withKnowledgeMutation(sharedRoot, async (lock) => {\n const existing = await loadKnowledgePages(sharedRoot, { pagesDirectory })\n assertNoIdentityConflict(travellers, existing)\n\n const promotedPaths = new Set(travellers.map((traveller) => traveller.entry.page.path))\n const promotedView = originatedPages(\n [\n ...existing.filter((page) => !promotedPaths.has(page.path)),\n ...travellers.map((traveller) => traveller.entry.page),\n ],\n 'shared',\n )\n assertKnowledgeCitationsResolved(\n promotedView,\n travellers.flatMap((traveller) =>\n (traveller.entry.page.cites ?? []).map((persisted: string) =>\n parseKnowledgeCitationReference(persisted),\n ),\n ),\n )\n\n await commitKnowledgeFileMutations({\n root: sharedRoot,\n transactionRoot: lock.transactionRoot,\n purpose: `knowledge-promotion:${runId}`,\n mutations,\n pagesDirectory,\n assertOwned: lock.assertOwned,\n })\n\n const record = buildRecord({\n runId,\n actor,\n reason,\n travellers,\n createdAt: (options.now ?? (() => new Date()))().toISOString(),\n })\n await writeJsonDurableWithinRoot(\n sharedRoot,\n `${KNOWLEDGE_PROMOTIONS_DIRECTORY}/${record.recordDigest}.json`,\n record,\n )\n return record\n })\n}\n\n/** Read one promotion record written by `promoteRunScopedPages`. */\nexport async function loadKnowledgePromotionRecord(\n sharedRoot: string,\n recordDigest: Sha256Digest,\n): Promise<KnowledgePromotionRecord | null> {\n try {\n const snapshot = await readRegularFileWithinRoot(\n sharedRoot,\n `${KNOWLEDGE_PROMOTIONS_DIRECTORY}/${recordDigest}.json`,\n )\n return JSON.parse(snapshot.bytes.toString('utf8')) as KnowledgePromotionRecord\n } catch (error) {\n if (isMissingFile(error)) return null\n throw error\n }\n}\n\ninterface Traveller {\n readonly entry: OriginatedPage\n requested: boolean\n}\n\n/**\n * The requested pages plus the closure of the run-local pages they cite.\n *\n * A citation into the shared store needs no carrying, and an unresolved\n * citation is left to the target-side check, which reports every one of them\n * together rather than failing on the first.\n */\nfunction collectTravellers(\n chain: readonly OriginatedPage[],\n pageIds: readonly KnowledgeId[],\n): Traveller[] {\n const byId = new Map<KnowledgeId, Traveller>()\n const queue: Array<{ entry: OriginatedPage; requested: boolean }> = []\n\n for (const pageId of pageIds) {\n const authored = chain.filter((entry) => entry.origin === 'here' && entry.page.id === pageId)\n if (authored.length === 0) {\n throw new KnowledgePromotionError(\n 'unknown-page',\n `promotion page \"${pageId}\" was not authored by this run`,\n )\n }\n if (authored.length > 1) {\n throw new KnowledgePromotionError(\n 'ambiguous-support',\n `promotion page \"${pageId}\" names ${authored.length} pages in this run`,\n )\n }\n queue.push({ entry: authored[0]!, requested: true })\n }\n\n while (queue.length > 0) {\n const next = queue.shift()!\n const seen = byId.get(next.entry.page.id)\n if (seen) {\n if (next.requested) seen.requested = true\n if (seen.entry.page.path !== next.entry.page.path) {\n throw new KnowledgePromotionError(\n 'ambiguous-support',\n `promotion support \"${next.entry.page.id}\" names more than one visible page`,\n )\n }\n continue\n }\n byId.set(next.entry.page.id, { entry: next.entry, requested: next.requested })\n for (const persisted of next.entry.page.cites ?? []) {\n const resolution = resolveKnowledgeCitation(chain, parseKnowledgeCitationReference(persisted))\n const target = resolution.resolved\n if (target === undefined || target.origin === 'shared') continue\n queue.push({ entry: { page: target.page, origin: target.origin }, requested: false })\n }\n }\n\n return [...byId.values()].sort(\n (left, right) =>\n Number(right.requested) - Number(left.requested) ||\n left.entry.page.path.localeCompare(right.entry.page.path),\n )\n}\n\nfunction assertNoIdentityConflict(\n travellers: readonly Traveller[],\n existing: readonly KnowledgePage[],\n): void {\n for (const traveller of travellers) {\n const page = traveller.entry.page\n const idClash = existing.find((other) => other.id === page.id && other.path !== page.path)\n if (idClash) {\n throw new KnowledgePromotionError(\n 'id-conflict',\n `shared page \"${idClash.path}\" already holds id \"${page.id}\"; promoting \"${page.path}\" would create two`,\n )\n }\n const pathClash = existing.find((other) => other.path === page.path && other.id !== page.id)\n if (pathClash) {\n throw new KnowledgePromotionError(\n 'path-conflict',\n `shared page \"${page.path}\" holds id \"${pathClash.id}\", not \"${page.id}\"`,\n )\n }\n }\n}\n\n/**\n * The page as its own store holds it. A promoted page must be the same bytes\n * in both scopes, so the record's digest describes what a reader will load.\n */\nasync function readPageBytes(\n stores: RunScopedStores,\n runId: string,\n entry: OriginatedPage,\n pagesDirectory: string,\n): Promise<string> {\n const sourceRunId = sourceRunOf(entry.origin, runId)\n const snapshot = await readRegularFileWithinRoot(stores.storePath(sourceRunId), entry.page.path)\n const content = snapshot.bytes.toString('utf8')\n const page = knowledgePageFromMarkdown(entry.page.path, content, pagesDirectory)\n if (knowledgePageDigest(page) !== knowledgePageDigest(entry.page)) {\n throw new KnowledgePromotionError(\n 'path-conflict',\n `source page \"${entry.page.path}\" in run \"${sourceRunId}\" changed after the promotion snapshot`,\n )\n }\n return content\n}\n\nfunction sourceRunOf(origin: PageOrigin, runId: string): string {\n if (origin === 'here') return runId\n if (origin.startsWith('inherited:')) return origin.slice('inherited:'.length)\n throw new Error(`promotion cannot read the bytes of a ${origin} page`)\n}\n\nfunction buildRecord(input: {\n runId: string\n actor: string\n reason: string\n travellers: readonly Traveller[]\n createdAt: string\n}): KnowledgePromotionRecord {\n const entries: KnowledgePromotionEntry[] = input.travellers.map((traveller) =>\n Object.freeze({\n pageId: traveller.entry.page.id,\n path: traveller.entry.page.path,\n sourceOrigin: traveller.entry.origin,\n pageDigest: knowledgePageDigest(traveller.entry.page),\n requested: traveller.requested,\n }),\n )\n const material = {\n schemaVersion: KNOWLEDGE_PROMOTION_SCHEMA_VERSION,\n kind: 'knowledge-promotion' as const,\n digestAlgorithm: KNOWLEDGE_PROMOTION_DIGEST_ALGORITHM,\n createdAt: input.createdAt,\n runId: input.runId,\n actor: input.actor,\n reason: input.reason,\n entries,\n }\n return Object.freeze({ ...material, recordDigest: canonicalCandidateDigest(material) })\n}\n\nfunction nonEmpty(value: string, label: string): string {\n if (typeof value !== 'string' || value.trim().length === 0) {\n throw new TypeError(`${label} must be a non-empty string`)\n }\n return value.trim()\n}\n","/**\n * Bridge from `AnalystFinding` (agent-eval) to knowledge proposals.\n *\n * Closes the failure → wiki side of the recursive-self-improvement\n * loop: a knowledge-gap or knowledge-poisoning finding produced by an\n * analyst becomes a concrete proposal an operator (or auto-merge bot)\n * can review and apply. The bridge is intentionally lossless on the\n * fail-loud side — a finding the parser can't classify returns a\n * `KnowledgeProposalParseError` rather than a silent skip, so the\n * loop never accepts an underspecified edit.\n *\n * Subject grammar this bridge understands (analyst-side convention,\n * stamped in the kind prompts):\n *\n * agent-knowledge:wiki:<page-slug> create / update page\n * agent-knowledge:wiki:<page-slug>#<heading> insert section under page\n * agent-knowledge:claim:<topic> draft claim row\n * agent-knowledge:raw:<source-id> lift raw → curated\n * agent-knowledge:stale:<page-slug> mark page superseded\n *\n * Anything else (websearch:outdated:*, tool-doc:*, system-prompt:*,\n * memory:*) is NOT a knowledge-base concern and returns `null` so the\n * loop's improvement-applier handles it.\n */\n\nimport type { AnalystFinding, AnalystSeverity } from '@tangle-network/agent-eval'\nimport type { ClaimRef, KnowledgeClaim, KnowledgeWriteBlock } from './types'\n\nexport interface KnowledgeProposal {\n /**\n * Stable id derived from the finding so cross-run diffs share an\n * identity. Re-proposing the same finding produces the same id.\n */\n id: string\n /** The finding that generated this proposal — useful for audit + revert. */\n sourceFindingId: string\n /** What the proposal does. */\n kind:\n | 'create-page'\n | 'update-page'\n | 'append-section'\n | 'create-claim'\n | 'lift-raw'\n | 'mark-stale'\n /** Locus on disk (page slug or claim topic). */\n locus: string\n /**\n * Page write blocks the standard `applyKnowledgeWriteBlocks` consumer\n * accepts. Empty for proposals that don't change page text (e.g.\n * `create-claim` produces a `claim` field instead).\n */\n writeBlocks: KnowledgeWriteBlock[]\n /**\n * Granular claim draft for proposals whose unit-of-change is a claim\n * row rather than a whole page. `status: 'draft'` until reviewed.\n */\n claim?: KnowledgeClaim\n /** Per-proposal metadata: severity, confidence, source span. */\n metadata: {\n severity: AnalystSeverity\n confidence: number\n evidence_uri?: string\n analyst_id: string\n }\n}\n\nexport class KnowledgeProposalParseError extends Error {\n constructor(\n public readonly findingId: string,\n public readonly subject: string,\n message: string,\n ) {\n super(`proposeFromFinding(${findingId}, subject=${subject}): ${message}`)\n this.name = 'KnowledgeProposalParseError'\n }\n}\n\n/**\n * Convert one `AnalystFinding` into a knowledge proposal. Returns\n * `null` when the finding's locus isn't a knowledge-base concern\n * (`websearch:outdated:*`, `tool-doc:*`, `system-prompt:*`,\n * `memory:*`, missing subject). Throws when the locus IS a\n * knowledge-base concern but is malformed — that's a bug in the\n * analyst prompt and should fail loud.\n *\n * Caller convention: feed the function the analyst's full findings\n * list and filter out the `null`s; the orchestrator passes the\n * remaining proposals to the existing review / apply pipeline.\n */\nexport function proposeFromFinding(finding: AnalystFinding): KnowledgeProposal | null {\n if (!finding.subject) return null\n if (!finding.subject.startsWith('agent-knowledge:')) return null\n\n const rest = finding.subject.slice('agent-knowledge:'.length)\n const [kindPart, ...locusParts] = rest.split(':')\n const locus = locusParts.join(':')\n if (!kindPart || !locus) {\n throw new KnowledgeProposalParseError(\n finding.finding_id,\n finding.subject,\n 'expected `agent-knowledge:<kind>:<locus>` shape',\n )\n }\n\n const baseMeta: KnowledgeProposal['metadata'] = {\n severity: finding.severity,\n confidence: finding.confidence,\n evidence_uri: finding.evidence_refs[0]?.uri,\n analyst_id: finding.analyst_id,\n }\n\n switch (kindPart) {\n case 'wiki':\n return wikiProposal(finding, locus, baseMeta)\n case 'claim':\n return claimProposal(finding, locus, baseMeta)\n case 'raw':\n return liftRawProposal(finding, locus, baseMeta)\n case 'stale':\n return markStaleProposal(finding, locus, baseMeta)\n default:\n throw new KnowledgeProposalParseError(\n finding.finding_id,\n finding.subject,\n `unknown kind \"${kindPart}\" (expected one of: wiki | claim | raw | stale)`,\n )\n }\n}\n\nfunction wikiProposal(\n finding: AnalystFinding,\n locus: string,\n metadata: KnowledgeProposal['metadata'],\n): KnowledgeProposal {\n const hashIdx = locus.indexOf('#')\n const pageSlug = hashIdx >= 0 ? locus.slice(0, hashIdx) : locus\n const heading = hashIdx >= 0 ? locus.slice(hashIdx + 1) : null\n const path = `knowledge/${ensureSlug(pageSlug)}.md`\n\n const body = renderWikiBody(finding, pageSlug, heading)\n return {\n id: `prop-${finding.finding_id}`,\n sourceFindingId: finding.finding_id,\n kind: heading ? 'append-section' : 'create-page',\n locus: pageSlug,\n writeBlocks: [{ path, content: body }],\n metadata,\n }\n}\n\nfunction claimProposal(\n finding: AnalystFinding,\n locus: string,\n metadata: KnowledgeProposal['metadata'],\n): KnowledgeProposal {\n const refs: ClaimRef[] = finding.evidence_refs\n .filter((r) => r.uri)\n .map((r) => ({\n sourceId: `analyst-finding:${finding.finding_id}`,\n anchorId: r.uri,\n quote: r.excerpt,\n }))\n const claim: KnowledgeClaim = {\n id: `claim-${finding.finding_id}`,\n text: finding.recommended_action ?? finding.claim,\n refs,\n confidence: finding.confidence,\n status: 'draft',\n metadata: {\n analyst_id: finding.analyst_id,\n source_finding_id: finding.finding_id,\n topic: locus,\n },\n }\n return {\n id: `prop-${finding.finding_id}`,\n sourceFindingId: finding.finding_id,\n kind: 'create-claim',\n locus,\n writeBlocks: [],\n claim,\n metadata,\n }\n}\n\nfunction liftRawProposal(\n finding: AnalystFinding,\n sourceId: string,\n metadata: KnowledgeProposal['metadata'],\n): KnowledgeProposal {\n const path = `knowledge/${ensureSlug(sourceId)}.md`\n const body = [\n '---',\n `title: ${sourceId}`,\n `source: ${sourceId}`,\n `status: draft`,\n `lifted_from_finding: ${finding.finding_id}`,\n '---',\n '',\n '## Why this page exists',\n '',\n finding.claim,\n '',\n ...(finding.rationale ? ['## Rationale', '', finding.rationale, ''] : []),\n ...(finding.recommended_action\n ? ['## Recommended action', '', finding.recommended_action, '']\n : []),\n ].join('\\n')\n return {\n id: `prop-${finding.finding_id}`,\n sourceFindingId: finding.finding_id,\n kind: 'lift-raw',\n locus: sourceId,\n writeBlocks: [{ path, content: body }],\n metadata,\n }\n}\n\nfunction markStaleProposal(\n finding: AnalystFinding,\n pageSlug: string,\n metadata: KnowledgeProposal['metadata'],\n): KnowledgeProposal {\n const path = `knowledge/${ensureSlug(pageSlug)}.stale.md`\n const body = [\n '---',\n `title: ${pageSlug} (marked stale)`,\n `status: superseded`,\n `superseded_by_finding: ${finding.finding_id}`,\n `confidence: ${finding.confidence}`,\n '---',\n '',\n '## Why marked stale',\n '',\n finding.claim,\n '',\n ...(finding.rationale ? ['## Evidence', '', finding.rationale, ''] : []),\n ...(finding.recommended_action ? ['## Action', '', finding.recommended_action, ''] : []),\n ].join('\\n')\n return {\n id: `prop-${finding.finding_id}`,\n sourceFindingId: finding.finding_id,\n kind: 'mark-stale',\n locus: pageSlug,\n writeBlocks: [{ path, content: body }],\n metadata,\n }\n}\n\n/**\n * Plural convenience: filter + map across an entire findings batch\n * with one call. Parse errors collect into `errors[]`; the loop\n * decides per-error whether to abort or continue.\n */\nexport interface ProposeFromFindingsResult {\n proposals: KnowledgeProposal[]\n skipped: number\n errors: KnowledgeProposalParseError[]\n}\n\nexport function proposeFromFindings(\n findings: ReadonlyArray<AnalystFinding>,\n): ProposeFromFindingsResult {\n const proposals: KnowledgeProposal[] = []\n const errors: KnowledgeProposalParseError[] = []\n let skipped = 0\n for (const f of findings) {\n try {\n const p = proposeFromFinding(f)\n if (p) proposals.push(p)\n else skipped += 1\n } catch (err) {\n if (err instanceof KnowledgeProposalParseError) errors.push(err)\n else throw err\n }\n }\n return { proposals, skipped, errors }\n}\n\nfunction ensureSlug(s: string): string {\n return (\n s\n .toLowerCase()\n .replace(/[^a-z0-9-]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 200) || 'untitled'\n )\n}\n\nfunction renderWikiBody(finding: AnalystFinding, slug: string, heading: string | null): string {\n const title = humanize(slug)\n if (heading) {\n return [\n `## ${heading}`,\n '',\n finding.claim,\n '',\n ...(finding.rationale ? ['### Rationale', '', finding.rationale, ''] : []),\n ...(finding.recommended_action ? ['### Action', '', finding.recommended_action, ''] : []),\n `_Drafted from finding ${finding.finding_id} (confidence ${finding.confidence.toFixed(2)})._`,\n ].join('\\n')\n }\n return [\n '---',\n `title: ${title}`,\n `status: draft`,\n `drafted_from_finding: ${finding.finding_id}`,\n `confidence: ${finding.confidence}`,\n '---',\n '',\n `# ${title}`,\n '',\n finding.claim,\n '',\n ...(finding.rationale ? ['## Rationale', '', finding.rationale, ''] : []),\n ...(finding.recommended_action\n ? ['## Recommended action', '', finding.recommended_action, '']\n : []),\n ].join('\\n')\n}\n\nfunction humanize(slug: string): string {\n return (\n slug\n .split('-')\n .filter(Boolean)\n .map((w) => w[0]?.toUpperCase() + w.slice(1))\n .join(' ') || slug\n )\n}\n","import type {\n BuildEvalKnowledgeBundleOptions,\n EvalKnowledgeBundleBuildResult,\n KnowledgeReadinessSpec,\n} from './eval-readiness'\nimport { buildKnowledgeIndex } from './indexer'\nimport {\n type KnowledgeBaseQualityOptions,\n type KnowledgeBaseQualityReport,\n scoreKnowledgeBaseIndex,\n} from './rag-eval'\nimport { readinessFor } from './readiness-helpers'\nimport type { KnowledgeIndex } from './types'\nimport {\n type ValidateKnowledgeOptions,\n type ValidateKnowledgeResult,\n validateKnowledgeIndex,\n} from './validate'\n\nexport interface EvaluateKnowledgeBaseReadinessOptions {\n root: string\n goal: string\n readinessSpecs?: readonly KnowledgeReadinessSpec[]\n readinessTaskId?: string\n readiness?: Omit<BuildEvalKnowledgeBundleOptions, 'taskId' | 'index' | 'specs'>\n strict?: ValidateKnowledgeOptions['strict']\n kbQuality?: KnowledgeBaseQualityOptions\n}\n\nexport interface KnowledgeBaseReadinessEvaluation {\n ready: boolean\n summary: string\n index: KnowledgeIndex\n validation: ValidateKnowledgeResult\n readiness?: EvalKnowledgeBundleBuildResult\n kbQuality: KnowledgeBaseQualityReport\n dimensions: {\n validation: number\n kb_quality: number\n blocking_readiness: number\n }\n}\n\nexport async function evaluateKnowledgeBaseReadiness(\n options: EvaluateKnowledgeBaseReadinessOptions,\n): Promise<KnowledgeBaseReadinessEvaluation> {\n const index = await buildKnowledgeIndex(options.root)\n const validation = validateKnowledgeIndex(index, { strict: options.strict })\n const readiness = readinessFor(\n {\n ...options,\n readinessSpecs: options.readinessSpecs ? [...options.readinessSpecs] : undefined,\n },\n index,\n )\n const kbQuality = scoreKnowledgeBaseIndex(index, {\n strict: options.strict,\n ...options.kbQuality,\n })\n const blockingMissing = readiness?.report.blockingMissingRequirements.length ?? 0\n const blockingTotal =\n options.readinessSpecs?.filter((spec) => spec.importance === 'blocking').length ?? 0\n const blockingReadiness =\n blockingTotal === 0 ? 1 : Math.max(0, blockingTotal - blockingMissing) / blockingTotal\n const ready = validation.ok && kbQuality.ok && blockingMissing === 0\n const failures = [\n validation.ok ? undefined : `${validation.findings.length} validation finding(s)`,\n kbQuality.ok ? undefined : `${kbQuality.findings.length} KB quality finding(s)`,\n blockingMissing === 0\n ? undefined\n : `${blockingMissing}/${blockingTotal} blocking readiness requirement(s) missing`,\n ].filter((failure): failure is string => Boolean(failure))\n\n return {\n ready,\n summary: ready ? 'knowledge base passed readiness checks' : failures.join('; '),\n index,\n validation,\n readiness,\n kbQuality,\n dimensions: {\n validation: validation.ok ? 1 : 0,\n kb_quality: kbQuality.ok ? 1 : 0,\n blocking_readiness: blockingReadiness,\n },\n }\n}\n","import { canonicalCandidateJson } from '@tangle-network/agent-interface'\nimport type {\n KnowledgeId,\n KnowledgeRelation,\n KnowledgeRelationGraph,\n KnowledgeRelationNode,\n} from './types'\n\nexport type KnowledgeRelationGraphErrorCode =\n | 'invalid-node'\n | 'duplicate-node'\n | 'invalid-relation'\n | 'duplicate-relation'\n | 'undeclared-endpoint'\n | 'unknown-node'\n | 'invalid-query'\n\n/** A relation graph input or query that cannot be honored exactly. */\nexport class KnowledgeRelationGraphError extends Error {\n readonly code: KnowledgeRelationGraphErrorCode\n\n constructor(code: KnowledgeRelationGraphErrorCode, message: string) {\n super(message)\n this.name = 'KnowledgeRelationGraphError'\n this.code = code\n }\n}\n\nexport interface BuildKnowledgeRelationGraphInput {\n /**\n * Declared node inventory. When present, every relation endpoint must name\n * one declared node; an undeclared endpoint is refused rather than added.\n * When absent, the graph carries edges only and `nodes` is empty.\n */\n nodes?: readonly KnowledgeRelationNode[]\n relations: readonly KnowledgeRelation[]\n}\n\n/**\n * `out` follows `sourceId -> targetId`, `in` follows `targetId -> sourceId`,\n * `both` follows a relation from either end.\n */\nexport type KnowledgeRelationDirection = 'out' | 'in' | 'both'\n\nexport interface KnowledgeRelationQuery {\n /** Restrict to relations with this predicate. Every predicate when absent. */\n predicate?: string\n direction: KnowledgeRelationDirection\n}\n\nexport interface KnowledgeRelationWalkOptions extends KnowledgeRelationQuery {\n /** Most relations between the start node and a reported node. Unbounded when absent. */\n maxDepth?: number\n}\n\nexport interface KnowledgeRelationNeighbor {\n nodeId: KnowledgeId\n relation: KnowledgeRelation\n}\n\nexport interface KnowledgeRelationWalkStep {\n nodeId: KnowledgeId\n /** Number of relations between the start node and this node. */\n depth: number\n /** The node the search came from when it first reached this node. */\n from: KnowledgeId\n relation: KnowledgeRelation\n}\n\n/**\n * Build a labeled multi-edge graph from caller relations.\n *\n * The graph keeps one edge per `(sourceId, targetId, predicate)`, in first-seen\n * order. A repeated triple is accepted only when its weight and metadata are\n * identical in canonical JSON; any other repeat is a conflict and is refused.\n * Node and relation metadata must be finite, acyclic JSON so the graph\n * round-trips through `KnowledgeRelationGraphSchema` unchanged.\n */\nexport function buildKnowledgeRelationGraph(\n input: BuildKnowledgeRelationGraphInput,\n): KnowledgeRelationGraph {\n const declared =\n input.nodes === undefined ? undefined : new Map<KnowledgeId, KnowledgeRelationNode>()\n const nodes: KnowledgeRelationNode[] = []\n if (declared !== undefined) {\n for (const [position, node] of input.nodes!.entries()) {\n const normalized = normalizeNode(node, position)\n if (declared.has(normalized.id)) {\n throw new KnowledgeRelationGraphError(\n 'duplicate-node',\n `node \"${normalized.id}\" is declared more than once`,\n )\n }\n declared.set(normalized.id, normalized)\n nodes.push(normalized)\n }\n }\n\n const edges: KnowledgeRelation[] = []\n const canonicalByTriple = new Map<string, string>()\n for (const [position, relation] of input.relations.entries()) {\n const normalized = normalizeRelation(relation, position)\n if (declared !== undefined) {\n for (const endpoint of [normalized.sourceId, normalized.targetId]) {\n if (!declared.has(endpoint)) {\n throw new KnowledgeRelationGraphError(\n 'undeclared-endpoint',\n `relation ${describeTriple(normalized)} names undeclared node \"${endpoint}\"`,\n )\n }\n }\n }\n const canonical = canonicalRelationJson(normalized)\n const key = tripleKey(normalized)\n const prior = canonicalByTriple.get(key)\n if (prior !== undefined) {\n if (prior === canonical) continue\n throw new KnowledgeRelationGraphError(\n 'duplicate-relation',\n `relation ${describeTriple(normalized)} is repeated with different weight or metadata`,\n )\n }\n canonicalByTriple.set(key, canonical)\n edges.push(normalized)\n }\n return { nodes, edges }\n}\n\n/** Relations touching `id`, each with the node at the other end, in graph order. */\nexport function neighbors(\n graph: KnowledgeRelationGraph,\n id: KnowledgeId,\n query: KnowledgeRelationQuery,\n): KnowledgeRelationNeighbor[] {\n const index = indexOf(graph)\n validateQuery(query)\n assertKnownNode(index, id)\n return neighborsOf(index, id, query)\n}\n\n/**\n * Breadth-first traversal from `id` over matching relations. Each reachable\n * node is reported once, at the depth where the search first reached it; the\n * start node is never reported, so a cycle back to it adds no step.\n */\nexport function walk(\n graph: KnowledgeRelationGraph,\n id: KnowledgeId,\n options: KnowledgeRelationWalkOptions,\n): KnowledgeRelationWalkStep[] {\n const index = indexOf(graph)\n validateQuery(options)\n validateMaxDepth(options.maxDepth)\n assertKnownNode(index, id)\n const steps: KnowledgeRelationWalkStep[] = []\n for (const step of traverse(index, id, options, options.maxDepth)) steps.push(step)\n return steps\n}\n\n/**\n * Whether `to` is `from` or lies on a path of matching relations out of `from`.\n */\nexport function isReachable(\n graph: KnowledgeRelationGraph,\n from: KnowledgeId,\n to: KnowledgeId,\n query: KnowledgeRelationQuery,\n): boolean {\n const index = indexOf(graph)\n validateQuery(query)\n assertKnownNode(index, from)\n assertKnownNode(index, to)\n if (from === to) return true\n for (const step of traverse(index, from, query, undefined)) {\n if (step.nodeId === to) return true\n }\n return false\n}\n\ninterface RelationIndex {\n readonly outgoing: ReadonlyMap<KnowledgeId, readonly KnowledgeRelation[]>\n readonly incoming: ReadonlyMap<KnowledgeId, readonly KnowledgeRelation[]>\n readonly known: ReadonlySet<KnowledgeId>\n}\n\n// The query index is derived once per graph object. A graph is a value: build\n// a new one instead of mutating `nodes` or `edges` after the first query.\nconst indexes = new WeakMap<KnowledgeRelationGraph, RelationIndex>()\n\nfunction indexOf(graph: KnowledgeRelationGraph): RelationIndex {\n const cached = indexes.get(graph)\n if (cached !== undefined) return cached\n const outgoing = new Map<KnowledgeId, KnowledgeRelation[]>()\n const incoming = new Map<KnowledgeId, KnowledgeRelation[]>()\n const known = new Set<KnowledgeId>()\n for (const node of graph.nodes) known.add(node.id)\n for (const relation of graph.edges) {\n known.add(relation.sourceId)\n known.add(relation.targetId)\n push(outgoing, relation.sourceId, relation)\n push(incoming, relation.targetId, relation)\n }\n const index: RelationIndex = { outgoing, incoming, known }\n indexes.set(graph, index)\n return index\n}\n\nfunction push(\n map: Map<KnowledgeId, KnowledgeRelation[]>,\n key: KnowledgeId,\n relation: KnowledgeRelation,\n): void {\n const list = map.get(key)\n if (list === undefined) map.set(key, [relation])\n else list.push(relation)\n}\n\nfunction neighborsOf(\n index: RelationIndex,\n id: KnowledgeId,\n query: KnowledgeRelationQuery,\n): KnowledgeRelationNeighbor[] {\n const matches = (relation: KnowledgeRelation): boolean =>\n query.predicate === undefined || relation.predicate === query.predicate\n const result: KnowledgeRelationNeighbor[] = []\n if (query.direction !== 'in') {\n for (const relation of index.outgoing.get(id) ?? []) {\n if (matches(relation)) result.push({ nodeId: relation.targetId, relation })\n }\n }\n if (query.direction !== 'out') {\n for (const relation of index.incoming.get(id) ?? []) {\n // A self-loop already appears in the outgoing pass when both ends are followed.\n if (query.direction === 'both' && relation.sourceId === id) continue\n if (matches(relation)) result.push({ nodeId: relation.sourceId, relation })\n }\n }\n return result\n}\n\nfunction* traverse(\n index: RelationIndex,\n start: KnowledgeId,\n query: KnowledgeRelationQuery,\n maxDepth: number | undefined,\n): Generator<KnowledgeRelationWalkStep> {\n const visited = new Set<KnowledgeId>([start])\n const queue: Array<{ nodeId: KnowledgeId; depth: number }> = [{ nodeId: start, depth: 0 }]\n for (let head = 0; head < queue.length; head++) {\n const current = queue[head]!\n if (maxDepth !== undefined && current.depth >= maxDepth) continue\n for (const neighbor of neighborsOf(index, current.nodeId, query)) {\n if (visited.has(neighbor.nodeId)) continue\n visited.add(neighbor.nodeId)\n const depth = current.depth + 1\n yield { nodeId: neighbor.nodeId, depth, from: current.nodeId, relation: neighbor.relation }\n queue.push({ nodeId: neighbor.nodeId, depth })\n }\n }\n}\n\nfunction assertKnownNode(index: RelationIndex, id: KnowledgeId): void {\n if (!index.known.has(id)) {\n throw new KnowledgeRelationGraphError('unknown-node', `node \"${id}\" is not in the graph`)\n }\n}\n\nfunction validateQuery(query: KnowledgeRelationQuery): void {\n if (query.direction !== 'out' && query.direction !== 'in' && query.direction !== 'both') {\n throw new KnowledgeRelationGraphError(\n 'invalid-query',\n `direction must be \"out\", \"in\", or \"both\", got ${JSON.stringify(query.direction)}`,\n )\n }\n if (query.predicate !== undefined && !isNonEmptyString(query.predicate)) {\n throw new KnowledgeRelationGraphError('invalid-query', 'predicate must be a non-empty string')\n }\n}\n\nfunction validateMaxDepth(maxDepth: number | undefined): void {\n if (maxDepth === undefined) return\n if (!Number.isInteger(maxDepth) || maxDepth < 0) {\n throw new KnowledgeRelationGraphError(\n 'invalid-query',\n `maxDepth must be a non-negative integer, got ${JSON.stringify(maxDepth)}`,\n )\n }\n}\n\nfunction normalizeNode(node: KnowledgeRelationNode, position: number): KnowledgeRelationNode {\n if (!isNonEmptyString(node.id)) {\n throw new KnowledgeRelationGraphError('invalid-node', `node at ${position} has no id`)\n }\n if (!isNonEmptyString(node.kind)) {\n throw new KnowledgeRelationGraphError('invalid-node', `node \"${node.id}\" has no kind`)\n }\n if (node.label !== undefined && typeof node.label !== 'string') {\n throw new KnowledgeRelationGraphError('invalid-node', `node \"${node.id}\" label is not a string`)\n }\n if (node.metadata !== undefined)\n assertCanonicalMetadata(node.metadata, `node \"${node.id}\"`, 'invalid-node')\n return {\n id: node.id,\n kind: node.kind,\n ...(node.label !== undefined ? { label: node.label } : {}),\n ...(node.metadata !== undefined ? { metadata: node.metadata } : {}),\n }\n}\n\nfunction normalizeRelation(relation: KnowledgeRelation, position: number): KnowledgeRelation {\n for (const field of ['sourceId', 'targetId', 'predicate'] as const) {\n if (!isNonEmptyString(relation[field])) {\n throw new KnowledgeRelationGraphError(\n 'invalid-relation',\n `relation at ${position} has no ${field}`,\n )\n }\n }\n if (relation.weight !== undefined && !Number.isFinite(relation.weight)) {\n throw new KnowledgeRelationGraphError(\n 'invalid-relation',\n `relation ${describeTriple(relation)} weight must be a finite number`,\n )\n }\n return {\n sourceId: relation.sourceId,\n targetId: relation.targetId,\n predicate: relation.predicate,\n ...(relation.weight !== undefined ? { weight: relation.weight } : {}),\n ...(relation.metadata !== undefined ? { metadata: relation.metadata } : {}),\n }\n}\n\nfunction canonicalRelationJson(relation: KnowledgeRelation): string {\n if (relation.metadata !== undefined) {\n assertCanonicalMetadata(\n relation.metadata,\n `relation ${describeTriple(relation)}`,\n 'invalid-relation',\n )\n }\n return canonicalCandidateJson({\n ...(relation.weight !== undefined ? { weight: relation.weight } : {}),\n ...(relation.metadata !== undefined ? { metadata: relation.metadata } : {}),\n })\n}\n\nfunction assertCanonicalMetadata(\n metadata: Record<string, unknown>,\n subject: string,\n code: 'invalid-node' | 'invalid-relation',\n): void {\n if (metadata === null || typeof metadata !== 'object' || Array.isArray(metadata)) {\n throw new KnowledgeRelationGraphError(code, `${subject} metadata must be an object`)\n }\n try {\n canonicalCandidateJson(metadata)\n } catch (error) {\n throw new KnowledgeRelationGraphError(\n code,\n `${subject} metadata must be finite, acyclic JSON: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n}\n\nfunction tripleKey(relation: KnowledgeRelation): string {\n return JSON.stringify([relation.sourceId, relation.targetId, relation.predicate])\n}\n\nfunction describeTriple(relation: KnowledgeRelation): string {\n return `${relation.sourceId} -[${relation.predicate}]-> ${relation.targetId}`\n}\n\nfunction isNonEmptyString(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0\n}\n","import {\n type DatasetScenario,\n evaluateReleaseConfidence,\n type HeldOutGateDecision,\n type ReleaseConfidenceScorecard,\n type ReleaseTraceEvidence,\n type RunRecord,\n validateRunRecord,\n} from '@tangle-network/agent-eval'\nimport { stableId } from './ids'\nimport type { KnowledgeRelease } from './types'\n\nexport interface KnowledgeReleaseReport {\n release: KnowledgeRelease\n scorecard: ReleaseConfidenceScorecard\n candidateRuns: RunRecord[]\n baselineRuns: RunRecord[]\n}\n\n/**\n * Build a knowledge release report from candidate and baseline run records,\n * optional trace evidence, and an optional decision record.\n */\nexport interface KnowledgeReleaseInput {\n candidateId: string\n baselineId?: string\n candidateRuns: RunRecord[]\n baselineRuns?: RunRecord[]\n traces?: ReleaseTraceEvidence[]\n gateDecision?: HeldOutGateDecision | null\n /** Scenario corpus used to prove train and holdout split coverage. */\n scenarios?: readonly DatasetScenario[]\n /**\n * Require both a holdout scenario and a holdout run.\n * Provide `scenarios` with at least one `split: 'holdout'` item when true.\n */\n hasHoldout?: boolean\n /** Candidate is the search-best variant — a promotion precondition. Default true. */\n promotedIsBest?: boolean\n createdAt?: string\n minScore?: number\n}\n\nexport function knowledgeReleaseReport(input: KnowledgeReleaseInput): KnowledgeReleaseReport {\n const baselineRuns = input.baselineRuns ?? []\n const runRecords = [...input.candidateRuns, ...baselineRuns].map(validateRunRecord)\n const scorecard = evaluateReleaseConfidence({\n target: 'agent-knowledge-base',\n candidateId: input.candidateId,\n baselineId: input.baselineId ?? 'baseline',\n traces: input.traces ?? [],\n runs: runRecords,\n scenarios: input.scenarios,\n gateDecision: input.gateDecision ?? null,\n thresholds: {\n requireCorpus: false,\n // This report has run records but no scenario corpus, so it cannot require\n // a positive scenario count.\n minScenarioCount: 0,\n requireHoldout: input.hasHoldout ?? false,\n minHoldoutRuns: input.hasHoldout ? 1 : 0,\n minSearchRuns: 1,\n minMeanScore: input.minScore ?? 0.7,\n },\n })\n const release: KnowledgeRelease = {\n id: stableId('krel', `${input.candidateId}:${input.createdAt ?? new Date().toISOString()}`),\n candidateId: input.candidateId,\n createdAt: input.createdAt ?? new Date().toISOString(),\n promoted: scorecard.status !== 'fail' && (input.promotedIsBest ?? true),\n scorecard,\n runRecordIds: runRecords.map((record) => record.runId),\n }\n return { release, scorecard, candidateRuns: input.candidateRuns, baselineRuns }\n}\n","/**\n * Research-DRIVING driver for `runVerifiedResearchLoop`.\n *\n * The shipped drivers all FILTER the worker's sources:\n * - `createVerifyingResearchDriver` judges on-topic relevance,\n * - `createAdaptiveResearchDriver` dedups then triages then escalates,\n * - `createClaimGroundingVerifier` rejects misattributed citations.\n *\n * This driver does the OPPOSITE job: instead of narrowing the worker's output,\n * it DRIVES the research DEEPER each round. Its value is not \"fewer sources\" —\n * it is \"more answered, better-corroborated sub-questions\". Concretely, each\n * round it:\n *\n * 1. EXTRACTS the key claims from the worker's new sources (one LLM pass per\n * source, in `verifySource`; falls back to a deterministic sentence-pull\n * when the model is unavailable so a round never silently extracts nothing).\n * 2. TRACKS each claim's support — the set of INDEPENDENT sources (by canonical\n * host) that assert it — and detects CONTRADICTIONS between a new claim and\n * one already on the ledger.\n * 3. GENERATES the next round's DEEP sub-questions from the accumulated claims,\n * in four kinds — comparative (\"how does X's tradeoff differ from Y's?\"),\n * mechanism (\"under what precise condition does X fail?\"), gap (\"what\n * specific result is missing?\"), and contradiction (\"does any source\n * challenge claim Z?\").\n * 4. FLAGS weakly-supported claims (only ONE independent source) and\n * contradicted claims as INVALIDATION targets and demands the worker find\n * corroborating / refuting evidence for them.\n * 5. FOLDS the deep sub-questions + invalidation challenges into the worker's\n * next prompt via the loop's `foldGaps` → `steer` channel — that is the\n * mechanism that drives DEPTH and VALIDATION rather than breadth.\n *\n * COMPLETION (`isComplete` / the `done` judgment the caller gates on) does NOT\n * look at source COUNT. It is done only when every deep sub-question it raised\n * has been addressed AND every key claim is either supported by >= 2 independent\n * sources OR explicitly marked CONTESTED (a contradiction the loop surfaced and\n * could not resolve). A KB with twenty sources all asserting one unchallenged\n * claim is NOT done; a KB whose handful of claims are each corroborated or\n * contested IS.\n *\n * It reuses `runVerifiedResearchLoop` (it is a plain `ResearchDriver`), the web\n * worker, `claim-ledger.ts` (claim identity, independent-source identity, and\n * the merge rule), and the `RouterClient` chat surface; it reinvents none of\n * them.\n */\n\nimport {\n claimEvidenceId,\n claimId,\n deepQuestionId,\n claimSourceHost as hostOf,\n mergeClaimLedgers,\n normalizeClaimText,\n researchSourceVersionKey,\n} from './claim-ledger'\nimport { sha256, textSourceId } from './ids'\nimport { assertClaimLedgerId, type ClaimLedgerStore } from './kb-store'\nimport { snapshotSourceTextInput } from './sources'\nimport type {\n DeepQuestion,\n DeepQuestionKind,\n ResearchClaimEvidence,\n ResearchClaimLedger,\n ResearchClaimRecord,\n ResearchSourceVersion,\n SourceRecord,\n TrackedClaim,\n} from './types'\nimport type {\n KnowledgeGap,\n ResearchDriver,\n ResearchSourceProposal,\n SourceVerdict,\n SourceVerificationContext,\n} from './verified-research-loop'\nimport {\n createTangleRouterClient,\n type RouterClient,\n type TangleRouterOptions,\n} from './web-research-worker'\n\n// The live claim type and its durable ledger records live in `types.ts` with\n// the package's other public shapes. Re-exported here so existing importers\n// keep working.\nexport type {\n DeepQuestion,\n DeepQuestionKind,\n ResearchClaimEvidence,\n ResearchClaimLedger,\n ResearchClaimRecord,\n ResearchSourceVersion,\n TrackedClaim,\n}\n\n/** The driver's accumulated research state — the completion oracle reads this. */\nexport interface ResearchDrivingState {\n /** Every extracted claim backed by a registered source, by id. */\n claims: TrackedClaim[]\n /** Every deep sub-question raised, by id. */\n questions: DeepQuestion[]\n /** Claims with exactly one independent source AND not contested. */\n weaklySupported: TrackedClaim[]\n /** Claims supported by >= 2 independent sources. */\n corroborated: TrackedClaim[]\n /** Claims marked contested (a surfaced, unresolved contradiction). */\n contested: TrackedClaim[]\n /** Deep questions still unaddressed. */\n openQuestions: DeepQuestion[]\n /** How many rounds the driver has folded steer for. */\n rounds: number\n}\n\nexport interface ResearchDrivingDriverOptions {\n /** Router client for claim extraction + deep-question generation. */\n router?: RouterClient\n router_options?: TangleRouterOptions\n /**\n * A claim is CORROBORATED at this many INDEPENDENT supporting sources (distinct\n * canonical hosts). Default 2 — the task's \">= 2 independent sources\" bar.\n */\n minIndependentSources?: number\n /** Max deep sub-questions to fold into one round's steer. Default 6. */\n maxQuestionsPerRound?: number\n /** Max claims to extract from a single source. Default 3. */\n maxClaimsPerSource?: number\n /**\n * When the extractor LLM is unavailable, fall back to a deterministic claim\n * pull (the source's leading sentences) so the driver still drives. Default\n * true. Set false to require the model (claims will be empty without it).\n */\n deterministicFallback?: boolean\n /** Observe each round's generated steer (for instrumentation / the script). */\n onSteer?: (steer: ResearchDrivingSteer) => void\n}\n\n/**\n * Options for the durable driver: the same driver plus a store to keep its\n * belief state in.\n */\nexport interface PersistentResearchDrivingDriverOptions extends ResearchDrivingDriverOptions {\n /** Where the claim ledger is read from and written to. */\n store: ClaimLedgerStore\n /**\n * Names this run's ledger. Stable across resumes (that is what makes a resume\n * a resume) and distinct per run against one knowledge base. Must be a single\n * safe path segment — see `assertClaimLedgerId`.\n */\n ledgerId: string\n}\n\n/** What the driver folded into one round's worker prompt, surfaced for audit. */\nexport interface ResearchDrivingSteer {\n round: number\n deepQuestions: DeepQuestion[]\n /** Claims it demanded corroborating/refuting evidence for this round. */\n invalidationTargets: TrackedClaim[]\n /** The readiness gaps it interleaved (passed through from the loop). */\n gaps: KnowledgeGap[]\n /** The full steer text handed to the worker. */\n text: string\n}\n\n/**\n * The research-driving driver. It is a `ResearchDriver` (drops straight into\n * `runVerifiedResearchLoop`) PLUS a completion oracle and live state, mirroring\n * how `createAdaptiveResearchDriver` exposes `stats()`.\n */\nexport interface ResearchDrivingDriver extends ResearchDriver {\n /** Live snapshot of the claim ledger + deep questions. */\n researchState(): ResearchDrivingState\n /**\n * The completion oracle — gate `done` on THIS, not on source count. True when\n * every deep sub-question is addressed AND every claim is corroborated\n * (>= `minIndependentSources` independent sources) or explicitly contested.\n * False while any claim is weakly-supported or any deep question is open.\n * Returns false before any claim has been seen (nothing researched yet).\n */\n isComplete(): boolean\n /**\n * The last round's generated steer, or undefined before the first fold. Useful\n * to assert the driver produced deeper questions / invalidation challenges.\n */\n lastSteer(): ResearchDrivingSteer | undefined\n /**\n * Write the current belief state to the store. `verifySource` already persists\n * each pending observation; this exists for the state `foldGaps` produces —\n * the deep questions — which is raised by a synchronous hook and would\n * otherwise be lost if the process died before the next source arrived.\n *\n * `runVerifiedResearchLoop` calls this at the end of every round. A driver\n * built without a store has nothing to write and resolves immediately.\n */\n checkpoint(): Promise<void>\n /** Durably announce the next synchronous fold before it begins. */\n prepareFold(): Promise<void>\n /**\n * Confirm exact registered source records.\n * URI equality alone is insufficient: pending evidence is authorized only\n * when its expected content hash matches the registered record.\n */\n commitSources(sources: readonly SourceRecord[]): Promise<void>\n /** The ledger record as it would be written right now. */\n toLedger(): ResearchClaimLedger\n}\n\n/** A claim the extractor returns for one source. */\ninterface ExtractedClaim {\n text: string\n /** A claim id ALREADY on the ledger that this one CONTRADICTS, if the model says so. */\n contradictsExistingId?: string\n}\n\n/**\n * The in-memory driver. Its belief state lives for exactly as long as the\n * process does — use `createPersistentResearchDrivingDriver` when the run must\n * survive a crash or resume.\n */\nexport function createResearchDrivingDriver(\n options: ResearchDrivingDriverOptions = {},\n): ResearchDrivingDriver {\n return buildDriver(options)\n}\n\n/**\n * The durable driver: same behaviour, plus its claim ledger is read from the\n * store at construction and written back after every claim and every round.\n *\n * Construction is asynchronous because loading is I/O, and loading has to happen\n * before the caller can read `researchState()` or `isComplete()` — a driver that\n * loaded lazily would answer \"nothing researched, not complete\" for a run that\n * had already corroborated everything.\n */\nexport async function createPersistentResearchDrivingDriver(\n options: PersistentResearchDrivingDriverOptions,\n): Promise<ResearchDrivingDriver> {\n const ledgerId = assertClaimLedgerId(options.ledgerId)\n const existing = await options.store.getClaimLedger(ledgerId)\n const driver = buildDriver(options, { store: options.store, ledgerId }, existing ?? undefined)\n if (existing && (existing.preparedRounds ?? existing.rounds) > existing.rounds) {\n await driver.checkpoint()\n }\n return driver\n}\n\ninterface DriverPersistence {\n store: ClaimLedgerStore\n ledgerId: string\n}\n\nfunction buildDriver(\n options: ResearchDrivingDriverOptions,\n persistence?: DriverPersistence,\n restored?: ResearchClaimLedger,\n): ResearchDrivingDriver {\n const minIndependentSources = Math.max(2, options.minIndependentSources ?? 2)\n const maxQuestionsPerRound = Math.max(1, options.maxQuestionsPerRound ?? 6)\n const maxClaimsPerSource = Math.max(1, options.maxClaimsPerSource ?? 3)\n const deterministicFallback = options.deterministicFallback ?? true\n\n // The claim ledger, keyed by claim id (sha256 of the normalized claim text).\n const claims = new Map<string, TrackedClaim>(\n (restored?.claims ?? []).map((claim) => [claim.id, fromRecord(claim)]),\n )\n // Claim extraction and source registration are two separate durable writes.\n // Evidence remains inert until its exact source version is confirmed here.\n const claimEvidence = new Map<string, ResearchClaimEvidence>(\n (restored?.claimEvidence ?? []).map((evidence) => [evidence.id, evidence]),\n )\n const registeredSources = new Map<string, ResearchSourceVersion>(\n (restored?.registeredSources ?? []).map((source) => [source.sourceId, source]),\n )\n // Every deep question raised, by id — so we can mark them addressed later.\n const questions = new Map<string, DeepQuestion>(\n (restored?.questions ?? []).map((question) => [question.id, question]),\n )\n let rounds = restored?.rounds ?? 0\n let preparedRounds = Math.max(rounds, restored?.preparedRounds ?? rounds)\n let goal = restored?.goal\n let lastSteer: ResearchDrivingSteer | undefined\n\n // `prepareFold` is persisted before the synchronous fold starts. If the\n // process died during that fold, regenerate its deterministic questions now\n // and advance the in-memory round; `createPersistentResearchDrivingDriver`\n // checkpoints this recovered state before returning it.\n if (preparedRounds > rounds) {\n for (let round = rounds + 1; round <= preparedRounds; round += 1) {\n for (const question of synthesizeDeepQuestions([...claims.values()], round).slice(\n 0,\n maxQuestionsPerRound,\n )) {\n if (!questions.has(question.id)) questions.set(question.id, question)\n }\n }\n rounds = preparedRounds\n }\n\n function toLedger(): ResearchClaimLedger {\n return {\n schemaVersion: 2,\n id: persistence?.ledgerId ?? 'in-memory',\n ...(goal === undefined ? {} : { goal }),\n updatedAt: new Date().toISOString(),\n rounds,\n ...(preparedRounds > rounds ? { preparedRounds } : {}),\n claimEvidence: [...claimEvidence.values()].sort((left, right) =>\n left.id.localeCompare(right.id),\n ),\n registeredSources: [...registeredSources.values()].sort((left, right) =>\n left.sourceId.localeCompare(right.sourceId),\n ),\n claims: [...claims.values()]\n .map((claim) => ({\n ...claim,\n supportingHosts: [...new Set(claim.supportingHosts)].sort(),\n supportingUris: [...new Set(claim.supportingUris)].sort(),\n contradicts: [...new Set(claim.contradicts)].sort(),\n }))\n .sort((a, b) => a.id.localeCompare(b.id)),\n questions: [...questions.values()]\n .map((question) => ({\n ...question,\n claimIds: [...new Set(question.claimIds)].sort(),\n }))\n .sort((a, b) => a.id.localeCompare(b.id)),\n }\n }\n\n /**\n * Write this driver's belief state into the stored ledger and adopt the\n * result.\n *\n * It merges rather than overwrites, and then rehydrates from the merged\n * record, which is the whole of what makes knowledge compound across\n * workers. Two drivers on one ledger id — a resumed run beside a still-live\n * one, or two workers researching one goal in parallel — would otherwise each\n * write a whole record built from what it read before the other wrote, and\n * the later write would erase the earlier writer's claims. Rehydrating means\n * a claim another worker corroborated counts toward THIS driver's completion\n * oracle from the next round onward.\n */\n async function persist(): Promise<void> {\n if (!persistence) return\n const mine = toLedger()\n const merged = await persistence.store.mergeClaimLedger(persistence.ledgerId, (current) =>\n current === null ? mine : mergeClaimLedgers(current, mine),\n )\n claims.clear()\n for (const claim of merged.claims) claims.set(claim.id, fromRecord(claim))\n claimEvidence.clear()\n for (const evidence of merged.claimEvidence) claimEvidence.set(evidence.id, evidence)\n registeredSources.clear()\n for (const source of merged.registeredSources) {\n registeredSources.set(source.sourceId, source)\n }\n questions.clear()\n for (const question of merged.questions) questions.set(question.id, question)\n rounds = Math.max(rounds, merged.rounds)\n preparedRounds = Math.max(rounds, merged.preparedRounds ?? merged.rounds)\n goal = merged.goal ?? goal\n }\n\n async function prepareFold(): Promise<void> {\n if (!persistence) return\n preparedRounds = Math.max(preparedRounds, rounds + 1)\n await persist()\n }\n\n /**\n * A ledger accumulates evidence FOR a goal. Reusing one id across two goals\n * merges two runs' beliefs into one corroboration count, which is worse than\n * losing them, so it fails rather than merging.\n */\n function bindGoal(nextGoal: string): void {\n if (goal === undefined) {\n goal = nextGoal\n return\n }\n if (goal !== nextGoal) {\n throw new Error(\n `claim ledger '${persistence?.ledgerId ?? 'in-memory'}' accumulated evidence for goal ` +\n `'${goal}' and cannot be reused for '${nextGoal}'`,\n )\n }\n }\n\n function resolveRouter(signal?: AbortSignal): RouterClient {\n if (options.router) return options.router\n const configuredSignal = options.router_options?.signal\n const requestSignal =\n configuredSignal && signal\n ? AbortSignal.any([configuredSignal, signal])\n : (configuredSignal ?? signal)\n return createTangleRouterClient({ ...options.router_options, signal: requestSignal })\n }\n\n function throwIfRouterAborted(signal?: AbortSignal): void {\n signal?.throwIfAborted()\n if (!options.router) options.router_options?.signal?.throwIfAborted()\n }\n\n /** Record a claim from a source, growing its independent-source support. */\n function recordClaim(extracted: ExtractedClaim, sourceUri: string, round: number): TrackedClaim {\n const id = claimId(extracted.text)\n const host = hostOf(sourceUri)\n const existing = claims.get(id)\n if (existing) {\n if (host) existing.supportingHosts.add(host)\n addUnique(existing.supportingUris, sourceUri)\n linkContradiction(existing, extracted.contradictsExistingId)\n return existing\n }\n const tracked: TrackedClaim = {\n id,\n text: extracted.text.trim(),\n supportingHosts: new Set(host ? [host] : []),\n supportingUris: [sourceUri],\n contradicts: new Set(),\n contested: false,\n firstSeenRound: round,\n }\n linkContradiction(tracked, extracted.contradictsExistingId)\n claims.set(id, tracked)\n return tracked\n }\n\n /** Persist an extraction observation without treating its source as registered. */\n function recordEvidence(\n extracted: ExtractedClaim,\n sourceVersion: ResearchSourceVersion,\n round: number,\n ): ResearchClaimEvidence {\n const text = extracted.text.trim()\n const observedClaimId = claimId(text)\n const contradictsClaimId =\n extracted.contradictsExistingId === observedClaimId\n ? undefined\n : extracted.contradictsExistingId\n const evidence: ResearchClaimEvidence = {\n id: claimEvidenceId({\n claimId: observedClaimId,\n sourceId: sourceVersion.sourceId,\n sourceUri: sourceVersion.uri,\n sourceContentHash: sourceVersion.contentHash,\n contradictsClaimId,\n }),\n claimId: observedClaimId,\n text,\n sourceId: sourceVersion.sourceId,\n sourceUri: sourceVersion.uri,\n sourceContentHash: sourceVersion.contentHash,\n ...(contradictsClaimId === undefined ? {} : { contradictsClaimId }),\n firstSeenRound: round,\n }\n const existing = claimEvidence.get(evidence.id)\n if (!existing) {\n claimEvidence.set(evidence.id, evidence)\n return evidence\n }\n const earlier =\n evidence.firstSeenRound < existing.firstSeenRound ||\n (evidence.firstSeenRound === existing.firstSeenRound && evidence.text < existing.text)\n ? evidence\n : existing\n const merged = {\n ...earlier,\n firstSeenRound: Math.min(existing.firstSeenRound, evidence.firstSeenRound),\n }\n claimEvidence.set(merged.id, merged)\n return merged\n }\n\n /** Materialize evidence for newly confirmed exact source versions into live claims. */\n function materializeEvidenceFor(sourceVersions: ReadonlySet<string>): string[] {\n const evidence = [...claimEvidence.values()].filter((item) =>\n sourceVersions.has(sourceVersionKeyOfEvidence(item)),\n )\n const texts: string[] = []\n for (const item of evidence) {\n recordClaim(\n { text: item.text, contradictsExistingId: item.contradictsClaimId },\n item.sourceUri,\n item.firstSeenRound,\n )\n texts.push(item.text)\n }\n // A refuter can sort before the original claim, so close edges only after\n // every claim for this confirmation batch exists.\n for (const item of evidence) {\n const claim = claims.get(item.claimId)\n if (claim) linkContradiction(claim, item.contradictsClaimId)\n }\n return texts\n }\n\n async function commitSources(sources: readonly SourceRecord[]): Promise<void> {\n const versions = sources.map(sourceVersionOfRecord)\n const nextRegistered = new Map(registeredSources)\n const newlyRegistered = new Set<string>()\n for (const version of versions) {\n const key = researchSourceVersionKey(version)\n const existing = nextRegistered.get(version.sourceId)\n if (existing && researchSourceVersionKey(existing) !== key) {\n throw new Error(`registered source '${version.sourceId}' has conflicting immutable content`)\n }\n if (existing) continue\n nextRegistered.set(version.sourceId, version)\n newlyRegistered.add(key)\n }\n registeredSources.clear()\n for (const [sourceId, version] of nextRegistered) registeredSources.set(sourceId, version)\n if (newlyRegistered.size > 0) {\n markAddressed(materializeEvidenceFor(newlyRegistered))\n }\n await persist()\n }\n\n /** Wire a bidirectional contradiction edge and mark BOTH claims contested. */\n function linkContradiction(claim: TrackedClaim, otherId: string | undefined): void {\n if (!otherId || otherId === claim.id) return\n const other = claims.get(otherId)\n if (!other) return\n claim.contradicts.add(otherId)\n other.contradicts.add(claim.id)\n claim.contested = true\n other.contested = true\n }\n\n /** A claim's independent-source count = distinct canonical hosts. */\n function independentSupport(claim: TrackedClaim): number {\n return claim.supportingHosts.size\n }\n\n function isCorroborated(claim: TrackedClaim): boolean {\n return independentSupport(claim) >= minIndependentSources\n }\n\n /** Weakly-supported = NOT corroborated AND NOT contested → an invalidation target. */\n function isWeak(claim: TrackedClaim): boolean {\n return !isCorroborated(claim) && !claim.contested\n }\n\n function snapshot(): ResearchDrivingState {\n const all = [...claims.values()]\n const allQuestions = [...questions.values()]\n return {\n claims: all,\n questions: allQuestions,\n weaklySupported: all.filter(isWeak),\n corroborated: all.filter(isCorroborated),\n contested: all.filter((claim) => claim.contested),\n openQuestions: allQuestions.filter((question) => !question.addressed),\n rounds,\n }\n }\n\n /**\n * Mark deep questions addressed when later evidence speaks to them. A question\n * is addressed once a NEW claim's text shares enough content words with the\n * question — i.e. the worker brought back evidence on the thing we asked about.\n * Cheap and deterministic; the LLM is reserved for GENERATING questions, not\n * grading them, so the oracle stays a non-model check.\n */\n function markAddressed(newClaimTexts: string[]): void {\n for (const question of questions.values()) {\n if (question.addressed) continue\n // Contradiction questions resolve when one of their claims becomes\n // corroborated or contested (the disagreement was surfaced/settled).\n if (question.kind === 'contradiction') {\n const settled = question.claimIds.some((id) => {\n const claim = claims.get(id)\n return claim ? isCorroborated(claim) || claim.contested : false\n })\n if (settled) question.addressed = true\n continue\n }\n const qWords = contentWordSet(question.text)\n if (qWords.size === 0) continue\n for (const text of newClaimTexts) {\n const overlap = overlapFraction(qWords, contentWordSet(text))\n if (overlap >= 0.5) {\n question.addressed = true\n break\n }\n }\n }\n }\n\n return {\n /**\n * `verifySource` — the per-source hook. This driver does NOT filter for\n * relevance/dedup (other drivers do that, and the loop already dedups exact\n * uris). Its job here is to EXTRACT the source's claims and grow the ledger.\n * It accepts every source that yields at least one extractable claim; it\n * only rejects a source with NO extractable signal at all (empty/unusable),\n * because such a source cannot drive the research and pollutes the KB.\n */\n async verifySource(\n source: ResearchSourceProposal,\n ctx: SourceVerificationContext,\n ): Promise<SourceVerdict> {\n throwIfRouterAborted(ctx.signal)\n const sourceSnapshot = snapshotSourceTextInput(source)\n const goalSnapshot = ctx.goal\n const roundSnapshot = ctx.round\n const sourceVersion = sourceVersionOfProposal(sourceSnapshot)\n bindGoal(goalSnapshot)\n const extracted = await extractClaims(sourceSnapshot, goalSnapshot, ctx.signal)\n throwIfRouterAborted(ctx.signal)\n if (extracted.length === 0) {\n return {\n accept: false,\n reason: 'no extractable claim: source yields nothing to drive the research deeper',\n }\n }\n for (const claim of extracted) {\n recordEvidence(claim, sourceVersion, roundSnapshot)\n }\n if (!persistence) {\n const key = researchSourceVersionKey(sourceVersion)\n registeredSources.set(sourceVersion.sourceId, sourceVersion)\n markAddressed(materializeEvidenceFor(new Set([key])))\n } else {\n const registered = registeredSources.get(sourceVersion.sourceId)\n if (\n registered &&\n researchSourceVersionKey(registered) === researchSourceVersionKey(sourceVersion)\n ) {\n // Direct callers can verify an exact version already present in the\n // registry. Its newly extracted evidence is safe to materialize now.\n markAddressed(materializeEvidenceFor(new Set([researchSourceVersionKey(sourceVersion)])))\n }\n }\n // Persist the observation BEFORE accepting. It remains pending until the\n // loop confirms source registration through `commitSources`, closing both\n // possible crash directions without a cross-store transaction.\n await persist()\n throwIfRouterAborted(ctx.signal)\n return { accept: true }\n },\n\n /**\n * `foldGaps` — the DEPTH driver. Runs after the worker's contribution is\n * applied each round. It builds the next round's steer from (1) the readiness\n * gaps the loop still reports, (2) freshly generated DEEP sub-questions, and\n * (3) INVALIDATION challenges for weakly-supported / contradicted claims.\n */\n foldGaps(gaps: KnowledgeGap[]): string {\n if (persistence && preparedRounds <= rounds) {\n throw new Error('persistent research driver must prepareFold before foldGaps')\n }\n rounds += 1\n const round = rounds\n const ledger = [...claims.values()]\n\n // Invalidation targets: claims with one source (need corroboration) OR\n // contradicted claims (need a refutation/resolution). These are what the\n // worker is told to go SHORE UP, not new breadth.\n const invalidationTargets = ledger.filter(\n (claim) => isWeak(claim) || claim.contradicts.size > 0,\n )\n\n // Generate this round's deep sub-questions from the actual ledger claims\n // and register them so completion can track whether they get addressed.\n const deepQuestions = synthesizeDeepQuestions(ledger, round).slice(0, maxQuestionsPerRound)\n for (const question of deepQuestions) {\n if (!questions.has(question.id)) questions.set(question.id, question)\n }\n\n const text = buildSteerText(gaps, deepQuestions, invalidationTargets, minIndependentSources)\n lastSteer = { round, deepQuestions, invalidationTargets, gaps, text }\n options.onSteer?.(lastSteer)\n return text\n },\n\n researchState: snapshot,\n\n isComplete(): boolean {\n const all = [...claims.values()]\n if (all.length === 0) return false\n const everyClaimSettled = all.every((claim) => isCorroborated(claim) || claim.contested)\n const everyQuestionAddressed = [...questions.values()].every((question) => question.addressed)\n return everyClaimSettled && everyQuestionAddressed\n },\n\n lastSteer(): ResearchDrivingSteer | undefined {\n return lastSteer\n },\n\n checkpoint: persist,\n\n prepareFold,\n\n commitSources,\n\n toLedger,\n }\n\n // -- claim extraction ------------------------------------------------------\n\n async function extractClaims(\n source: ResearchSourceProposal,\n goal: string,\n signal?: AbortSignal,\n ): Promise<ExtractedClaim[]> {\n const ledger = claimsForExtraction()\n const fromLlm = await extractClaimsWithLlm(source, goal, ledger, signal)\n throwIfRouterAborted(signal)\n if (fromLlm.length > 0) return fromLlm.slice(0, maxClaimsPerSource)\n if (deterministicFallback) return deterministicClaims(source).slice(0, maxClaimsPerSource)\n return []\n }\n\n function claimsForExtraction(): TrackedClaim[] {\n const known = new Map(claims)\n for (const evidence of claimEvidence.values()) {\n if (known.has(evidence.claimId)) continue\n known.set(evidence.claimId, {\n id: evidence.claimId,\n text: evidence.text,\n supportingHosts: new Set(),\n supportingUris: [],\n contradicts: new Set(),\n contested: false,\n firstSeenRound: evidence.firstSeenRound,\n })\n }\n return [...known.values()]\n }\n\n async function extractClaimsWithLlm(\n source: ResearchSourceProposal,\n goal: string,\n ledger: TrackedClaim[],\n signal?: AbortSignal,\n ): Promise<ExtractedClaim[]> {\n let router: RouterClient\n try {\n router = resolveRouter(signal)\n } catch (error) {\n throwIfRouterAborted(signal)\n if ((error as { name?: string } | null)?.name === 'AbortError') throw error\n return []\n }\n const excerpt = source.text.slice(0, 1800)\n const ledgerLines = ledger\n .slice(0, 20)\n .map((claim) => `- [${claim.id}] ${claim.text}`)\n .join('\\n')\n const system =\n 'You extract the KEY factual claims a researcher would cite a page for, and flag ' +\n 'CONTRADICTIONS with claims already on the ledger. ' +\n \"A claim is one concrete, checkable assertion using the page's own terms and numbers. \" +\n 'Return ONLY a JSON array; each item is {\"claim\": string, \"contradicts\": string|null} where ' +\n 'contradicts is the bracketed [id] of a ledger claim this page DIRECTLY contradicts, else null. ' +\n `Return at most ${maxClaimsPerSource} claims. No prose.`\n const user = [\n `Research goal: ${goal}`,\n `Page title: ${source.title ?? '(none)'}`,\n ledgerLines ? `Claims already on the ledger:\\n${ledgerLines}` : 'Ledger is empty.',\n `Page excerpt:\\n${excerpt}`,\n 'Key claims as JSON [{\"claim\": \"...\", \"contradicts\": \"[id]\"|null}]:',\n ].join('\\n\\n')\n\n let raw = ''\n try {\n raw = await router.chat(\n [\n { role: 'system', content: system },\n { role: 'user', content: user },\n ],\n 1200,\n )\n } catch (error) {\n throwIfRouterAborted(signal)\n if ((error as { name?: string } | null)?.name === 'AbortError') throw error\n return []\n }\n throwIfRouterAborted(signal)\n return parseExtractedClaims(raw, ledger)\n }\n\n /**\n * Deterministic fallback: pull the leading sentences as candidate claims. Used\n * only when the model is unavailable, so the driver still drives (and the\n * offline test runs with no creds). Each sentence becomes a checkable claim.\n */\n function deterministicClaims(source: ResearchSourceProposal): ExtractedClaim[] {\n const sentences = source.text\n .split(/(?<=[.!?])\\s+/)\n .map((sentence) => sentence.trim())\n .filter((sentence) => contentWordSet(sentence).size >= 3)\n return sentences.slice(0, maxClaimsPerSource).map((text) => ({ text }))\n }\n\n // -- deep-question synthesis ----------------------------------------------\n\n /**\n * Build the four deep-question kinds from the actual ledger claims. This is\n * intentionally deterministic (not an LLM call): the loop's `foldGaps` contract\n * is synchronous (`foldGaps(gaps): string`), and a template grounded in the\n * real claim text gives a faithful, non-fabricated sub-question every round —\n * comparative, mechanism, gap, and contradiction. Claim EXTRACTION, which runs\n * inside the awaited `verifySource`, is where the model does the open-ended\n * work; question generation just interrogates what was extracted.\n */\n function synthesizeDeepQuestions(ledger: TrackedClaim[], round: number): DeepQuestion[] {\n if (ledger.length === 0) return []\n const out: DeepQuestion[] = []\n\n // CONTRADICTION questions: for every contradiction edge, ask the worker to\n // find evidence that resolves which claim holds.\n for (const claim of ledger) {\n for (const otherId of claim.contradicts) {\n const other = ledger.find((entry) => entry.id === otherId)\n if (!other || other.id < claim.id) continue // emit each pair once\n out.push(\n makeQuestion(\n 'contradiction',\n `Does any independent source resolve the contradiction between \"${truncate(claim.text)}\" and \"${truncate(other.text)}\"? Find evidence that confirms or refutes one of them.`,\n [claim.id, other.id],\n round,\n ),\n )\n }\n }\n\n // GAP questions: for each weakly-supported claim, ask for the specific\n // corroborating result that is missing.\n for (const claim of ledger.filter((entry) => !entry.contested)) {\n if (claim.supportingHosts.size < minIndependentSources) {\n out.push(\n makeQuestion(\n 'gap',\n `Only one independent source supports \"${truncate(claim.text)}\". What specific corroborating result, dataset, or independent measurement is missing to confirm it?`,\n [claim.id],\n round,\n ),\n )\n }\n }\n\n // Probe where the best-supported claims stop holding.\n for (const claim of [...ledger]\n .sort((a, b) => b.supportingHosts.size - a.supportingHosts.size)\n .slice(0, 2)) {\n out.push(\n makeQuestion(\n 'mechanism',\n `Under what precise condition does \"${truncate(claim.text)}\" stop holding? Find a source that states the mechanism, limit, or failure mode.`,\n [claim.id],\n round,\n ),\n )\n }\n\n // Compare tradeoffs between the two best-supported claims.\n const ranked = [...ledger].sort((a, b) => b.supportingHosts.size - a.supportingHosts.size)\n if (ranked.length >= 2 && ranked[0] && ranked[1]) {\n out.push(\n makeQuestion(\n 'comparative',\n `How does the tradeoff in \"${truncate(ranked[0].text)}\" differ from \"${truncate(ranked[1].text)}\"? Find a source that compares them directly.`,\n [ranked[0].id, ranked[1].id],\n round,\n ),\n )\n }\n\n // Stable order: contradiction → gap → mechanism → comparative (most urgent\n // validation work first).\n const priority: Record<DeepQuestionKind, number> = {\n contradiction: 0,\n gap: 1,\n mechanism: 2,\n comparative: 3,\n }\n return out.sort((a, b) => priority[a.kind] - priority[b.kind])\n }\n}\n\n// ---------------------------------------------------------------------------\n// pure helpers\n// ---------------------------------------------------------------------------\n\nfunction sourceVersionOfProposal(source: ResearchSourceProposal): ResearchSourceVersion {\n const contentHash = sha256(source.text)\n return {\n sourceId: textSourceId(source.uri, contentHash),\n uri: source.uri,\n contentHash,\n }\n}\n\nfunction sourceVersionOfRecord(source: SourceRecord): ResearchSourceVersion {\n const originalUri = source.metadata?.originalUri\n if (typeof originalUri !== 'string' || originalUri.length === 0) {\n throw new Error(`registered source '${source.id}' has no originalUri`)\n }\n if (!/^[a-f0-9]{64}$/.test(source.contentHash)) {\n throw new Error(`registered source '${source.id}' contentHash is not a SHA-256 digest`)\n }\n const expectedSourceId = textSourceId(originalUri, source.contentHash)\n if (source.id !== expectedSourceId) {\n throw new Error(\n `registered source '${source.id}' does not match URI-and-content identity '${expectedSourceId}'`,\n )\n }\n return { sourceId: source.id, uri: originalUri, contentHash: source.contentHash }\n}\n\nfunction sourceVersionKeyOfEvidence(evidence: ResearchClaimEvidence): string {\n return researchSourceVersionKey({\n sourceId: evidence.sourceId,\n uri: evidence.sourceUri,\n contentHash: evidence.sourceContentHash,\n })\n}\n\nfunction makeQuestion(\n kind: DeepQuestionKind,\n text: string,\n claimIds: string[],\n raisedRound: number,\n): DeepQuestion {\n return {\n kind,\n text,\n id: deepQuestionId(kind, text),\n claimIds: [...new Set(claimIds)].sort(),\n addressed: false,\n raisedRound,\n }\n}\n\nfunction fromRecord(claim: ResearchClaimRecord): TrackedClaim {\n return {\n ...claim,\n supportingHosts: new Set(claim.supportingHosts),\n supportingUris: [...claim.supportingUris],\n contradicts: new Set(claim.contradicts),\n }\n}\n\n/**\n * Set-like insert into the array form. The ledger's collections are arrays so\n * they survive `JSON.stringify`; dedup is enforced here instead of by the type.\n */\nfunction addUnique(values: string[], value: string): void {\n if (!values.includes(value)) values.push(value)\n}\n\nconst stopwords = new Set([\n 'the',\n 'a',\n 'an',\n 'and',\n 'or',\n 'but',\n 'of',\n 'to',\n 'in',\n 'on',\n 'for',\n 'with',\n 'as',\n 'by',\n 'at',\n 'from',\n 'that',\n 'this',\n 'these',\n 'those',\n 'it',\n 'its',\n 'is',\n 'are',\n 'was',\n 'were',\n 'be',\n 'been',\n 'being',\n 'has',\n 'have',\n 'had',\n 'can',\n 'will',\n 'would',\n 'should',\n 'may',\n 'might',\n 'not',\n 'no',\n 'than',\n 'then',\n 'over',\n 'under',\n 'about',\n 'into',\n 'their',\n 'they',\n 'them',\n])\n\nfunction contentWordSet(text: string): Set<string> {\n return new Set(\n normalizeClaimText(text)\n .split(' ')\n .filter((word) => word.length >= 3 && !stopwords.has(word)),\n )\n}\n\nfunction overlapFraction(a: Set<string>, b: Set<string>): number {\n if (a.size === 0) return 0\n let hits = 0\n for (const word of a) if (b.has(word)) hits += 1\n return hits / a.size\n}\n\nfunction truncate(text: string, max = 140): string {\n const t = text.trim().replace(/\\s+/g, ' ')\n return t.length <= max ? t : `${t.slice(0, max - 1)}…`\n}\n\n/**\n * Parse the extractor's JSON array of `{claim, contradicts}` items, tolerant of\n * code fences / surrounding prose. `contradicts` is mapped from a `[id]` token to\n * a ledger claim id only when that id is actually on the ledger.\n */\nfunction parseExtractedClaims(raw: string, ledger: TrackedClaim[]): ExtractedClaim[] {\n const text = raw.trim()\n if (!text) return []\n const arrayMatch = text.match(/\\[[\\s\\S]*\\]/)\n if (!arrayMatch) return []\n let parsed: unknown\n try {\n parsed = JSON.parse(arrayMatch[0])\n } catch {\n return []\n }\n if (!Array.isArray(parsed)) return []\n const ledgerIds = new Set(ledger.map((claim) => claim.id))\n const out: ExtractedClaim[] = []\n for (const item of parsed) {\n if (!item || typeof item !== 'object') continue\n const record = item as { claim?: unknown; contradicts?: unknown }\n if (typeof record.claim !== 'string' || !record.claim.trim()) continue\n const contradictsId = extractBracketId(record.contradicts)\n out.push({\n text: record.claim.trim(),\n contradictsExistingId:\n contradictsId && ledgerIds.has(contradictsId) ? contradictsId : undefined,\n })\n }\n return out\n}\n\n/** Pull a ledger id out of a `contradicts` field: `\"[c_abc]\"` or `\"c_abc\"`. */\nfunction extractBracketId(value: unknown): string | undefined {\n if (typeof value !== 'string') return undefined\n const trimmed = value.trim()\n if (!trimmed || trimmed.toLowerCase() === 'null') return undefined\n const bracket = trimmed.match(/\\[([^\\]]+)\\]/)\n const id = (bracket?.[1] ?? trimmed).trim()\n return id.startsWith('c_') ? id : undefined\n}\n\n/**\n * Build the steer string handed to the worker's next prompt. Interleaves the\n * readiness gaps the loop still reports with the deep sub-questions and the\n * invalidation challenges — the part that drives DEPTH + VALIDATION.\n */\nfunction buildSteerText(\n gaps: KnowledgeGap[],\n deepQuestions: DeepQuestion[],\n invalidationTargets: TrackedClaim[],\n minIndependentSources: number,\n): string {\n const lines: string[] = []\n lines.push(\n 'Do NOT just add more sources. Go DEEPER and VALIDATE. Address the following before adding breadth:',\n )\n\n if (deepQuestions.length > 0) {\n lines.push('', 'Deep sub-questions to answer this round:')\n for (const question of deepQuestions) {\n lines.push(`- (${question.kind}) ${question.text}`)\n }\n }\n\n if (invalidationTargets.length > 0) {\n lines.push(\n '',\n `Claims needing corroboration or refutation (each must reach >= ${minIndependentSources} INDEPENDENT sources, or be shown contested):`,\n )\n for (const claim of invalidationTargets) {\n const reason =\n claim.contradicts.size > 0\n ? 'CONTRADICTED by another source — find evidence that resolves it'\n : `only ${claim.supportingHosts.size} independent source — find a SECOND, independent corroborating source`\n lines.push(`- \"${truncate(claim.text)}\" — ${reason}`)\n }\n }\n\n if (gaps.length > 0) {\n lines.push('', 'Readiness gaps still open:')\n for (const gap of gaps) {\n lines.push(`- (${gap.blocking ? 'blocking' : 'soft'}) ${gap.description} [${gap.id}]`)\n }\n }\n\n return lines.join('\\n')\n}\n"],"mappings":"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K,KAAK,MAAM,EAAE;AAC/F;AAEA,SAAS,UAAU,MAAyB,OAAmC;CAC7E,OAAO,KAAK,WAAW,MAAM,UAAU,KAAK,OAAO,MAAM,UAAU,SAAS,MAAM,MAAM;AAC1F;;;;;;;;;;;;;;;;ACsCA,MAAa,sBAAyC;CACpD;EACE,QAAQ;EACR,SAAS;EACT,KAAK;EACL,QAAQ;EACR,QAAQ;EACR,cACE;EACF,OAAO;GACL;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MAAC;MAAoB;MAAoB;KAAK;IACvD,GACA;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WAAW;IACX,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;EACF;CACF;CACA;EACE,QAAQ;EACR,SAAS;EACT,KAAK;EACL,QAAQ;EACR,QAAQ;EACR,cAAc;EACd,OAAO;GACL;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UAAU;GACZ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;EACF;CACF;CACA;EACE,QAAQ;EACR,SAAS;EACT,KAAK;EACL,QAAQ;EACR,QAAQ;EACR,cACE;EACF,OAAO;GACL;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UAAU;GACZ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UAAU;GACZ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MAAC;MAAS;MAAe;MAAgB;MAAoB;KAAa;IACnF,CACF;IACA,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UAAU;GACZ;EACF;CACF;CACA;EACE,QAAQ;EACR,SAAS;EACT,KAAK;EACL,QAAQ;EACR,QAAQ;EACR,cACE;EACF,OAAO;GACL;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UAAU;GACZ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UAAU;GACZ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;EACF;CACF;CACA;EACE,QAAQ;EACR,SAAS;EACT,KAAK;EACL,QAAQ;EACR,QAAQ;EACR,cACE;EACF,OAAO;GACL;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KACE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KAOE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KAKE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UAAU;GACZ;GACA;IACE,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU,CACR;KAOE,OAAO;KACP,OAAO;MACL;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF,CACF;IACA,WACE;IACF,UACE;GACJ;EACF;CACF;AACF;;;;;;;AAQA,SAAgB,qBACd,MACA,YACwF;CACxF,MAAM,WAAW,WAAW,YAAY;CACxC,MAAM,QAAQ,KAAK,SAAS,QAAQ,UAClC,MAAM,MAAM,MAAM,aAAa,S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"}