@tangle-network/agent-knowledge 1.6.0 → 1.8.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.
@@ -604,7 +604,7 @@ function lintKnowledgeIndex(index) {
604
604
  const inbound = /* @__PURE__ */ new Map();
605
605
  for (const page of index.pages) inbound.set(page.id, 0);
606
606
  for (const page of index.pages) {
607
- if (page.outLinks.length === 0 && !isStructural(page.path)) {
607
+ if (page.outLinks.length === 0 && !isScaffoldPath(page.path)) {
608
608
  findings.push({
609
609
  type: "no-outlinks",
610
610
  severity: "info",
@@ -626,7 +626,7 @@ function lintKnowledgeIndex(index) {
626
626
  for (const edge of index.graph.edges)
627
627
  inbound.set(edge.target, (inbound.get(edge.target) ?? 0) + 1);
628
628
  for (const page of index.pages) {
629
- if (!isStructural(page.path) && (inbound.get(page.id) ?? 0) === 0) {
629
+ if (!isScaffoldPath(page.path) && (inbound.get(page.id) ?? 0) === 0) {
630
630
  findings.push({
631
631
  type: "orphan",
632
632
  severity: "info",
@@ -705,9 +705,6 @@ function lintKnowledgeIndex(index) {
705
705
  }
706
706
  return findings;
707
707
  }
708
- function isStructural(path) {
709
- return path.endsWith("/index.md") || path.endsWith("/log.md") || path === "knowledge/index.md" || path === "knowledge/log.md";
710
- }
711
708
  function extractSourceRefs(text) {
712
709
  const refs = [];
713
710
  const regex = /\[\^([A-Za-z0-9_-]+)(?:#([A-Za-z0-9_.:-]+))?\]/g;
@@ -718,6 +715,12 @@ function extractSourceRefs(text) {
718
715
  return refs;
719
716
  }
720
717
 
718
+ // src/metadata.ts
719
+ function stringMetadata(metadata, key) {
720
+ const value = metadata?.[key];
721
+ return typeof value === "string" ? value : void 0;
722
+ }
723
+
721
724
  // src/inspect.ts
722
725
  function inspectKnowledgeIndex(index, options = {}) {
723
726
  const now = options.now ?? /* @__PURE__ */ new Date();
@@ -748,10 +751,6 @@ function inspectSourceFreshness(source, now) {
748
751
  const status = validUntil && Number.isFinite(Date.parse(validUntil)) ? Date.parse(validUntil) <= now.getTime() ? "expired" : "fresh" : "unknown";
749
752
  return { id: source.id, title: source.title, uri: source.uri, status, validUntil, lastVerifiedAt };
750
753
  }
751
- function stringMetadata(metadata, key) {
752
- const value = metadata?.[key];
753
- return typeof value === "string" ? value : void 0;
754
- }
755
754
  function explainKnowledgeTarget(index, target) {
756
755
  const page = index.pages.find(
757
756
  (candidate) => candidate.path === target || candidate.id === target || candidate.title.toLowerCase() === target.toLowerCase()
@@ -1004,7 +1003,7 @@ function validateKnowledgeIndex(index, options = {}) {
1004
1003
  }
1005
1004
  if (options.strict) {
1006
1005
  for (const page of index.pages) {
1007
- if (isStructuralPage(page.path)) continue;
1006
+ if (isScaffoldPath(page.path)) continue;
1008
1007
  if (!page.frontmatter.id || !page.frontmatter.title) {
1009
1008
  findings.push({
1010
1009
  type: "missing-frontmatter",
@@ -1017,13 +1016,11 @@ function validateKnowledgeIndex(index, options = {}) {
1017
1016
  }
1018
1017
  return { ok: !findings.some((finding) => finding.severity === "error"), findings };
1019
1018
  }
1020
- function isStructuralPage(path) {
1021
- return path === "knowledge/index.md" || path === "knowledge/log.md" || path.endsWith("/index.md") || path.endsWith("/log.md");
1022
- }
1023
1019
 
1024
1020
  export {
1025
1021
  textSourceAdapter,
1026
1022
  mediaTypeFor,
1023
+ stringMetadata,
1027
1024
  searchKnowledge,
1028
1025
  tokenizeQuery,
1029
1026
  reciprocalRankFusion,
@@ -1063,4 +1060,4 @@ export {
1063
1060
  KnowledgeBaseCandidateSchema,
1064
1061
  validateKnowledgeIndex
1065
1062
  };
1066
- //# sourceMappingURL=chunk-HKYD765Q.js.map
1063
+ //# sourceMappingURL=chunk-WWY5FTKQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters.ts","../src/search.ts","../src/frontmatter.ts","../src/wikilinks.ts","../src/graph.ts","../src/store.ts","../src/sources.ts","../src/indexer.ts","../src/lint.ts","../src/metadata.ts","../src/inspect.ts","../src/write-protocol.ts","../src/proposals.ts","../src/schemas.ts","../src/validate.ts"],"sourcesContent":["import type { SourceRecord } from './types'\n\nexport interface SourceAdapterInput {\n uri: string\n bytes?: Uint8Array\n text?: string\n metadata?: Record<string, unknown>\n}\n\nexport interface SourceAdapterOutput {\n title?: string\n mediaType?: string\n text?: string\n anchors?: SourceRecord['anchors']\n metadata?: Record<string, unknown>\n}\n\nexport interface SourceAdapter {\n id: string\n canLoad(input: SourceAdapterInput): boolean\n load(input: SourceAdapterInput): Promise<SourceAdapterOutput> | SourceAdapterOutput\n}\n\nexport const textSourceAdapter: SourceAdapter = {\n id: 'text',\n canLoad: (input) => Boolean(input.text) || /\\.(md|txt|json|csv)$/i.test(input.uri),\n load: (input) => ({\n title: input.uri.split('/').pop(),\n mediaType: mediaTypeFor(input.uri),\n text: decodeText(input),\n anchors: anchorsForText(input.uri, decodeText(input)),\n metadata: input.metadata,\n }),\n}\n\nexport function mediaTypeFor(uri: string): string {\n const lower = uri.toLowerCase()\n if (lower.endsWith('.md')) return 'text/markdown'\n if (lower.endsWith('.txt')) return 'text/plain'\n if (lower.endsWith('.json')) return 'application/json'\n if (lower.endsWith('.csv')) return 'text/csv'\n if (lower.endsWith('.pdf')) return 'application/pdf'\n return 'application/octet-stream'\n}\n\nfunction decodeText(input: SourceAdapterInput): string | undefined {\n return (\n input.text ??\n (input.bytes ? new TextDecoder().decode(input.bytes).slice(0, 200_000) : undefined)\n )\n}\n\nfunction anchorsForText(uri: string, text: string | undefined): SourceAdapterOutput['anchors'] {\n if (!text) return []\n const lines = text.split('\\n')\n const anchors: NonNullable<SourceAdapterOutput['anchors']> = [\n { id: 'all', sourceId: '', label: 'Full source', lineStart: 1, lineEnd: lines.length },\n ]\n for (let i = 0; i < lines.length; i += 50) {\n anchors.push({\n id: `l${i + 1}`,\n sourceId: '',\n label: `${uri}:${i + 1}`,\n lineStart: i + 1,\n lineEnd: Math.min(lines.length, i + 50),\n })\n }\n return anchors\n}\n","import type { KnowledgeIndex, KnowledgePage, KnowledgeSearchResult } from './types'\n\nconst RRF_K = 60\nconst STOP_WORDS = new Set([\n 'the',\n 'is',\n 'a',\n 'an',\n 'what',\n 'how',\n 'are',\n 'was',\n 'were',\n 'to',\n 'for',\n 'of',\n 'with',\n 'by',\n 'in',\n 'on',\n 'and',\n])\n\nexport function searchKnowledge(\n index: KnowledgeIndex,\n query: string,\n limit = 10,\n): KnowledgeSearchResult[] {\n const trimmed = query.trim()\n if (trimmed === '') return []\n const tokenRanked = rankByTokens(index.pages, trimmed)\n const graphRanked = rankByGraph(index.pages, tokenRanked)\n const scores = reciprocalRankFusion([tokenRanked.map((p) => p.id), graphRanked.map((p) => p.id)])\n const byId = new Map(index.pages.map((page) => [page.id, page]))\n\n const ranked = [...scores.entries()]\n .map(([id, score]) => ({ page: byId.get(id), score }))\n .filter((item): item is { page: KnowledgePage; score: number } => Boolean(item.page))\n .sort((a, b) => b.score - a.score || a.page.path.localeCompare(b.page.path))\n .slice(0, limit)\n\n // Normalize against the top hit so callers can compare against natural\n // [0, 1] thresholds. Raw RRF values are typically ~0.016, which reads as\n // \"no relevance\" to humans even when the result is the best available.\n // The top hit becomes 1 by definition; lower-ranked hits scale linearly.\n const topScore = ranked[0]?.score ?? 0\n\n return ranked.map((item, i) => ({\n page: item.page,\n score: item.score,\n rrfScore: item.score,\n normalizedScore: topScore > 0 ? item.score / topScore : 0,\n rank: i + 1,\n snippet: buildSnippet(item.page.text, trimmed),\n reasons: reasonsFor(item.page, trimmed),\n }))\n}\n\nexport function tokenizeQuery(query: string): string[] {\n const raw = query\n .toLowerCase()\n .split(/[\\s,,。!?、;:\"\"''()()\\-_/\\\\·~~…]+/)\n .filter((token) => token.length > 1 && !STOP_WORDS.has(token))\n const tokens: string[] = []\n for (const token of raw) {\n if (/[\\u4e00-\\u9fff\\u3400-\\u4dbf]/.test(token) && token.length > 2) {\n const chars = [...token]\n for (let i = 0; i < chars.length - 1; i++) tokens.push(chars[i]! + chars[i + 1]!)\n tokens.push(...chars)\n }\n tokens.push(token)\n }\n return [...new Set(tokens)]\n}\n\nexport function reciprocalRankFusion(rankLists: string[][], k = RRF_K): Map<string, number> {\n const scores = new Map<string, number>()\n for (const list of rankLists) {\n list.forEach((id, idx) => {\n scores.set(id, (scores.get(id) ?? 0) + 1 / (k + idx + 1))\n })\n }\n return scores\n}\n\nfunction rankByTokens(pages: KnowledgePage[], query: string): KnowledgePage[] {\n const tokens = tokenizeQuery(query)\n const effective = tokens.length > 0 ? tokens : [query.toLowerCase()]\n return pages\n .map((page) => ({ page, score: tokenScore(page, query, effective) }))\n .filter((item) => item.score > 0)\n .sort((a, b) => b.score - a.score || a.page.path.localeCompare(b.page.path))\n .map((item) => item.page)\n}\n\nfunction rankByGraph(pages: KnowledgePage[], tokenRanked: KnowledgePage[]): KnowledgePage[] {\n if (tokenRanked.length === 0) return []\n const seeds = new Set(tokenRanked.slice(0, 5).map((page) => page.id))\n return pages\n .map((page) => ({\n page,\n score:\n page.outLinks.filter((link) => seeds.has(link)).length +\n page.sourceIds.filter((source) =>\n tokenRanked.some((seed) => seed.sourceIds.includes(source)),\n ).length,\n }))\n .filter((item) => item.score > 0)\n .sort((a, b) => b.score - a.score || a.page.path.localeCompare(b.page.path))\n .map((item) => item.page)\n}\n\nfunction tokenScore(page: KnowledgePage, query: string, tokens: string[]): number {\n const title = page.title.toLowerCase()\n const path = page.path.toLowerCase()\n const body = page.text.toLowerCase()\n const phrase = query.toLowerCase()\n let score = 0\n if (path.endsWith(`${phrase}.md`) || title === phrase) score += 200\n if (title.includes(phrase)) score += 50\n if (body.includes(phrase)) score += 20\n for (const token of tokens) {\n if (title.includes(token)) score += 5\n if (body.includes(token)) score += 1\n if (path.includes(token)) score += 3\n }\n return score\n}\n\nfunction buildSnippet(text: string, query: string): string {\n const compact = text.replace(/\\s+/g, ' ').trim()\n const idx = compact.toLowerCase().indexOf(query.toLowerCase())\n if (idx < 0) return compact.slice(0, 180)\n return compact.slice(Math.max(0, idx - 80), Math.min(compact.length, idx + query.length + 100))\n}\n\nfunction reasonsFor(page: KnowledgePage, query: string): string[] {\n const lower = `${page.title}\\n${page.text}`.toLowerCase()\n const reasons: string[] = []\n if (lower.includes(query.toLowerCase())) reasons.push('phrase')\n if (page.sourceIds.length > 0) reasons.push('sourced')\n if (page.outLinks.length > 0) reasons.push('linked')\n return reasons\n}\n","export interface ParsedFrontmatter {\n frontmatter: Record<string, unknown>\n body: string\n}\n\nexport function parseFrontmatter(content: string): ParsedFrontmatter {\n const normalized = content.replace(/\\r\\n/g, '\\n')\n if (!normalized.startsWith('---\\n')) return { frontmatter: {}, body: normalized }\n const end = normalized.indexOf('\\n---', 4)\n if (end < 0) return { frontmatter: {}, body: normalized }\n const raw = normalized.slice(4, end)\n const after = normalized.slice(end).replace(/^\\n---\\s*\\n?/, '')\n return { frontmatter: parseSimpleYaml(raw), body: after }\n}\n\nexport function formatFrontmatter(frontmatter: Record<string, unknown>, body: string): string {\n const lines = Object.entries(frontmatter)\n .filter(([, value]) => value !== undefined)\n .flatMap(([key, value]) => formatYamlField(key, value))\n if (lines.length === 0) return body\n return `---\\n${lines.join('\\n')}\\n---\\n${body.replace(/^\\n+/, '')}`\n}\n\nfunction parseSimpleYaml(raw: string): Record<string, unknown> {\n const out: Record<string, unknown> = {}\n const lines = raw.split('\\n')\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]!\n const scalar = /^([A-Za-z0-9_-]+):\\s*(.*)$/.exec(line)\n if (!scalar) continue\n const key = scalar[1]!\n const rest = scalar[2]!.trim()\n if (rest === '') {\n const items: string[] = []\n while (i + 1 < lines.length) {\n const item = /^\\s*-\\s*(.+?)\\s*$/.exec(lines[i + 1]!)\n if (!item) break\n items.push(unquote(item[1]!))\n i++\n }\n out[key] = items\n continue\n }\n if (rest.startsWith('[') && rest.endsWith(']')) {\n out[key] = rest\n .slice(1, -1)\n .split(',')\n .map((part) => unquote(part.trim()))\n .filter(Boolean)\n } else if (rest === 'true' || rest === 'false') {\n out[key] = rest === 'true'\n } else if (/^-?\\d+(?:\\.\\d+)?$/.test(rest)) {\n out[key] = Number(rest)\n } else {\n out[key] = unquote(rest)\n }\n }\n return out\n}\n\nfunction formatYamlField(key: string, value: unknown): string[] {\n if (Array.isArray(value)) {\n return [`${key}:`, ...value.map((item) => ` - ${String(item)}`)]\n }\n if (typeof value === 'string') return [`${key}: ${value}`]\n if (typeof value === 'number' || typeof value === 'boolean') return [`${key}: ${String(value)}`]\n return [`${key}: ${JSON.stringify(value)}`]\n}\n\nfunction unquote(value: string): string {\n return value.replace(/^['\"]|['\"]$/g, '')\n}\n","export const WIKILINK_REGEX = /\\[\\[([^\\]|]+?)(?:\\|[^\\]]+?)?\\]\\]/g\n\nexport function extractWikilinks(content: string): string[] {\n const links: string[] = []\n const regex = new RegExp(WIKILINK_REGEX.source, 'g')\n let match: RegExpExecArray | null\n while ((match = regex.exec(content)) !== null) {\n links.push(match[1]!.trim())\n }\n return [...new Set(links)]\n}\n\nexport function normalizeLinkTarget(target: string): string {\n return target.trim().replace(/\\.md$/i, '').toLowerCase().replace(/\\s+/g, '-')\n}\n","import type { KnowledgeGraph, KnowledgeGraphEdge, KnowledgeGraphNode, KnowledgePage } from './types'\nimport { normalizeLinkTarget } from './wikilinks'\n\nexport function buildKnowledgeGraph(pages: KnowledgePage[]): KnowledgeGraph {\n const byId = new Map<string, KnowledgePage>()\n const bySlug = new Map<string, KnowledgePage>()\n for (const page of pages) {\n byId.set(page.id, page)\n bySlug.set(normalizeLinkTarget(page.id), page)\n bySlug.set(normalizeLinkTarget(page.title), page)\n bySlug.set(normalizeLinkTarget(page.path.split('/').pop()!.replace(/\\.md$/, '')), page)\n }\n\n const incoming = new Map<string, number>()\n const outgoing = new Map<string, number>()\n const edgesByKey = new Map<string, KnowledgeGraphEdge>()\n for (const page of pages) {\n outgoing.set(page.id, 0)\n incoming.set(page.id, 0)\n }\n\n for (const page of pages) {\n for (const raw of page.outLinks) {\n const target = bySlug.get(normalizeLinkTarget(raw))\n if (!target || target.id === page.id) continue\n const key = `${page.id}->${target.id}`\n const edge = edgesByKey.get(key)\n if (edge) edge.weight += 1\n else\n edgesByKey.set(key, {\n source: page.id,\n target: target.id,\n weight: 1,\n reasons: ['wikilink'],\n })\n outgoing.set(page.id, (outgoing.get(page.id) ?? 0) + 1)\n incoming.set(target.id, (incoming.get(target.id) ?? 0) + 1)\n }\n }\n\n addSourceOverlapEdges(pages, edgesByKey)\n\n const nodes: KnowledgeGraphNode[] = pages.map((page) => ({\n id: page.id,\n title: page.title,\n path: page.path,\n tags: page.tags,\n sourceIds: page.sourceIds,\n outDegree: outgoing.get(page.id) ?? 0,\n inDegree: incoming.get(page.id) ?? 0,\n }))\n return { nodes, edges: [...edgesByKey.values()].sort((a, b) => b.weight - a.weight) }\n}\n\nfunction addSourceOverlapEdges(\n pages: KnowledgePage[],\n edges: Map<string, KnowledgeGraphEdge>,\n): void {\n for (let i = 0; i < pages.length; i++) {\n for (let j = i + 1; j < pages.length; j++) {\n const a = pages[i]!\n const b = pages[j]!\n const overlap = a.sourceIds.filter((source) => b.sourceIds.includes(source))\n if (overlap.length === 0) continue\n const key = `${a.id}->${b.id}`\n const edge = edges.get(key)\n if (edge) {\n edge.weight += overlap.length * 0.5\n edge.reasons.push('shared-source')\n } else {\n edges.set(key, {\n source: a.id,\n target: b.id,\n weight: overlap.length * 0.5,\n reasons: ['shared-source'],\n })\n }\n }\n }\n}\n","import { mkdir, readdir, readFile, stat, writeFile } from 'node:fs/promises'\nimport { dirname, join, relative } from 'node:path'\nimport { parseFrontmatter } from './frontmatter'\nimport { slugify } from './ids'\nimport type { KnowledgePage } from './types'\nimport { extractWikilinks, normalizeLinkTarget } from './wikilinks'\n\nexport interface KnowledgeLayout {\n root: string\n knowledgeDir: string\n rawSourcesDir: string\n sourceRegistryPath: string\n indexPath: string\n logPath: string\n cacheDir: string\n}\n\nexport function layoutFor(root: string): KnowledgeLayout {\n return {\n root,\n knowledgeDir: join(root, 'knowledge'),\n rawSourcesDir: join(root, 'raw', 'sources'),\n sourceRegistryPath: join(root, '.agent-knowledge', 'sources.json'),\n indexPath: join(root, 'knowledge', 'index.md'),\n logPath: join(root, 'knowledge', 'log.md'),\n cacheDir: join(root, '.agent-knowledge'),\n }\n}\n\n/**\n * Filenames that `initKnowledgeBase` writes as human-navigation scaffolding.\n * These are excluded from the page index — they exist on disk so authors can\n * curate their vault, but they are not searchable content.\n *\n * Add new scaffold filenames here (and only here) to keep lint, validate, viz,\n * and the indexer consistent.\n */\nexport const SCAFFOLD_PAGE_BASENAMES: readonly string[] = ['index.md', 'log.md']\n\n/**\n * True when a knowledge-relative path points at a scaffold file rather than\n * authored content. Accepts both repo-relative paths (`knowledge/index.md`)\n * and any nested `<dir>/index.md` or `<dir>/log.md` (for example\n * `knowledge/concepts/index.md`) so subdirectory README-style scaffolds are\n * also excluded.\n */\nexport function isScaffoldPath(path: string): boolean {\n const normalized = path.replace(/\\\\/g, '/')\n for (const basename of SCAFFOLD_PAGE_BASENAMES) {\n if (normalized === `knowledge/${basename}`) return true\n if (normalized.endsWith(`/${basename}`)) return true\n }\n return false\n}\n\nexport async function initKnowledgeBase(root: string): Promise<KnowledgeLayout> {\n const layout = layoutFor(root)\n await mkdir(layout.knowledgeDir, { recursive: true })\n await mkdir(layout.rawSourcesDir, { recursive: true })\n await mkdir(layout.cacheDir, { recursive: true })\n await writeIfMissing(layout.indexPath, '# Knowledge Index\\n\\n')\n await writeIfMissing(layout.logPath, '# Knowledge Log\\n\\n')\n await writeIfMissing(\n layout.sourceRegistryPath,\n '{\\n \"generatedAt\": \"1970-01-01T00:00:00.000Z\",\\n \"sources\": []\\n}\\n',\n )\n return layout\n}\n\nexport async function loadKnowledgePages(root: string): Promise<KnowledgePage[]> {\n const layout = layoutFor(root)\n const files = await listMarkdownFiles(layout.knowledgeDir)\n const pages: KnowledgePage[] = []\n for (const file of files) {\n const rel = relative(root, file).replace(/\\\\/g, '/')\n if (isScaffoldPath(rel)) continue\n const content = await readFile(file, 'utf8')\n const { frontmatter, body } = parseFrontmatter(content)\n const title =\n stringField(frontmatter.title) ??\n firstHeading(body) ??\n rel.split('/').pop()!.replace(/\\.md$/, '')\n const sourceIds = arrayField(frontmatter.sources)\n const tags = arrayField(frontmatter.tags)\n pages.push({\n id:\n stringField(frontmatter.id) ??\n slugify(rel.replace(/^knowledge\\//, '').replace(/\\.md$/, '')),\n path: rel,\n title,\n text: body,\n frontmatter,\n sourceIds,\n tags,\n outLinks: extractWikilinks(body).map(normalizeLinkTarget),\n })\n }\n pages.sort((a, b) => a.path.localeCompare(b.path))\n return pages\n}\n\nexport async function writeJson(path: string, value: unknown): Promise<void> {\n await mkdir(dirname(path), { recursive: true })\n await writeFile(path, `${JSON.stringify(value, null, 2)}\\n`, 'utf8')\n}\n\nasync function writeIfMissing(path: string, content: string): Promise<void> {\n try {\n await stat(path)\n } catch {\n await mkdir(dirname(path), { recursive: true })\n await writeFile(path, content, 'utf8')\n }\n}\n\nasync function listMarkdownFiles(root: string): Promise<string[]> {\n try {\n const entries = await readdir(root, { withFileTypes: true })\n const out: string[] = []\n for (const entry of entries) {\n const full = join(root, entry.name)\n if (entry.isDirectory()) out.push(...(await listMarkdownFiles(full)))\n else if (entry.isFile() && entry.name.endsWith('.md')) out.push(full)\n }\n return out\n } catch {\n return []\n }\n}\n\nfunction stringField(value: unknown): string | undefined {\n return typeof value === 'string' && value.trim() !== '' ? value.trim() : undefined\n}\n\nfunction arrayField(value: unknown): string[] {\n return Array.isArray(value)\n ? value.filter((item): item is string => typeof item === 'string')\n : []\n}\n\nfunction firstHeading(body: string): string | undefined {\n return /^#\\s+(.+)$/m.exec(body)?.[1]?.trim()\n}\n","import { copyFile, mkdir, readdir, readFile, stat, writeFile } from 'node:fs/promises'\nimport { basename, dirname, join, relative } from 'node:path'\nimport { type SourceAdapter, textSourceAdapter } from './adapters'\nimport { sha256, slugify, stableId } from './ids'\nimport { layoutFor } from './store'\nimport type { SourceRecord, SourceRegistry } from './types'\n\nexport interface AddSourceOptions {\n copyIntoRaw?: boolean\n adapters?: SourceAdapter[]\n now?: () => Date\n}\n\nexport interface AddSourceTextInput {\n uri: string\n text: string\n title?: string\n mediaType?: string\n validUntil?: string\n lastVerifiedAt?: string\n metadata?: Record<string, unknown>\n}\n\nexport async function loadSourceRegistry(root: string): Promise<SourceRegistry> {\n const path = sourceRegistryPath(root)\n try {\n const parsed = JSON.parse(await readFile(path, 'utf8')) as SourceRegistry\n return {\n generatedAt:\n typeof parsed.generatedAt === 'string' ? parsed.generatedAt : new Date(0).toISOString(),\n sources: Array.isArray(parsed.sources) ? parsed.sources : [],\n }\n } catch {\n return { generatedAt: new Date(0).toISOString(), sources: [] }\n }\n}\n\nexport async function writeSourceRegistry(root: string, registry: SourceRegistry): Promise<void> {\n const path = sourceRegistryPath(root)\n await mkdir(dirname(path), { recursive: true })\n await writeFile(path, `${JSON.stringify(registry, null, 2)}\\n`, 'utf8')\n}\n\nexport async function addSourcePath(\n root: string,\n sourcePath: string,\n options: AddSourceOptions = {},\n): Promise<SourceRecord[]> {\n const s = await stat(sourcePath)\n if (s.isDirectory()) {\n const out: SourceRecord[] = []\n for (const file of await listFiles(sourcePath)) {\n out.push(...(await addSourcePath(root, file, options)))\n }\n return out\n }\n\n const layout = layoutFor(root)\n await mkdir(layout.rawSourcesDir, { recursive: true })\n const bytes = await readFile(sourcePath)\n const contentHash = sha256(bytes.toString('base64'))\n const fileName = basename(sourcePath)\n const adapters = options.adapters ?? [textSourceAdapter]\n const adapter = adapters.find((candidate) => candidate.canLoad({ uri: sourcePath, bytes }))\n const loaded = adapter ? await adapter.load({ uri: sourcePath, bytes }) : {}\n const id = stableId('src', `${contentHash}:${fileName}`)\n const targetRel = join(\n 'raw',\n 'sources',\n `${slugify(fileName.replace(/\\.[^.]+$/, ''))}-${contentHash.slice(0, 8)}${ext(fileName)}`,\n ).replace(/\\\\/g, '/')\n const targetAbs = join(root, targetRel)\n\n if (options.copyIntoRaw ?? true) {\n await mkdir(dirname(targetAbs), { recursive: true })\n await copyFile(sourcePath, targetAbs)\n }\n\n const existing = await loadSourceRegistry(root)\n const record: SourceRecord = {\n id,\n uri: targetRel,\n title: loaded.title ?? fileName,\n mediaType: loaded.mediaType ?? mediaTypeFor(fileName),\n contentHash,\n text: loaded.text ?? textPreview(fileName, bytes),\n anchors: (loaded.anchors ?? []).map((anchor) => ({ ...anchor, sourceId: id })),\n createdAt: (options.now ?? (() => new Date()))().toISOString(),\n metadata: {\n ...(loaded.metadata ?? {}),\n originalPath: sourcePath,\n sizeBytes: bytes.length,\n projectRelativePath: relative(root, sourcePath).replace(/\\\\/g, '/'),\n },\n }\n const next: SourceRegistry = {\n generatedAt: new Date().toISOString(),\n sources: [record, ...existing.sources.filter((source) => source.id !== id)],\n }\n await writeSourceRegistry(root, next)\n return [record]\n}\n\nexport async function addSourceText(\n root: string,\n input: AddSourceTextInput,\n options: Pick<AddSourceOptions, 'adapters' | 'now'> = {},\n): Promise<SourceRecord> {\n const text = input.text\n const contentHash = sha256(text)\n const fileName = basename(input.uri) || `${slugify(input.title ?? input.uri)}.txt`\n const adapterInput = { uri: input.uri, text, metadata: input.metadata }\n const adapter = (options.adapters ?? [textSourceAdapter]).find((candidate) =>\n candidate.canLoad(adapterInput),\n )\n const loaded = adapter ? await adapter.load(adapterInput) : {}\n const id = stableId('src', `${contentHash}:${input.uri}`)\n const targetRel = join(\n 'raw',\n 'sources',\n `${slugify(fileName.replace(/\\.[^.]+$/, ''))}-${contentHash.slice(0, 8)}.txt`,\n ).replace(/\\\\/g, '/')\n const targetAbs = join(root, targetRel)\n await mkdir(dirname(targetAbs), { recursive: true })\n await writeFile(targetAbs, text.endsWith('\\n') ? text : `${text}\\n`, 'utf8')\n\n const existing = await loadSourceRegistry(root)\n const record: SourceRecord = {\n id,\n uri: targetRel,\n title: input.title ?? loaded.title ?? fileName,\n mediaType: input.mediaType ?? loaded.mediaType ?? 'text/plain',\n contentHash,\n text: loaded.text ?? text.slice(0, 200_000),\n anchors: (loaded.anchors ?? []).map((anchor) => ({ ...anchor, sourceId: id })),\n validUntil: input.validUntil,\n lastVerifiedAt: input.lastVerifiedAt,\n createdAt: (options.now ?? (() => new Date()))().toISOString(),\n metadata: {\n ...(loaded.metadata ?? {}),\n ...(input.metadata ?? {}),\n originalUri: input.uri,\n sizeBytes: Buffer.byteLength(text, 'utf8'),\n },\n }\n await writeSourceRegistry(root, {\n generatedAt: new Date().toISOString(),\n sources: [record, ...existing.sources.filter((source) => source.id !== id)],\n })\n return record\n}\n\nexport function sourceRegistryPath(root: string): string {\n return join(layoutFor(root).cacheDir, 'sources.json')\n}\n\nasync function listFiles(root: string): Promise<string[]> {\n const entries = await readdir(root, { withFileTypes: true })\n const out: string[] = []\n for (const entry of entries) {\n const full = join(root, entry.name)\n if (entry.isDirectory()) out.push(...(await listFiles(full)))\n else if (entry.isFile()) out.push(full)\n }\n return out\n}\n\nfunction ext(fileName: string): string {\n const idx = fileName.lastIndexOf('.')\n return idx >= 0 ? fileName.slice(idx) : ''\n}\n\nfunction mediaTypeFor(fileName: string): string {\n const lower = fileName.toLowerCase()\n if (lower.endsWith('.md')) return 'text/markdown'\n if (lower.endsWith('.txt')) return 'text/plain'\n if (lower.endsWith('.json')) return 'application/json'\n if (lower.endsWith('.csv')) return 'text/csv'\n if (lower.endsWith('.pdf')) return 'application/pdf'\n return 'application/octet-stream'\n}\n\nfunction textPreview(fileName: string, bytes: Buffer): string | undefined {\n const mediaType = mediaTypeFor(fileName)\n if (!mediaType.startsWith('text/') && mediaType !== 'application/json') return undefined\n return bytes.toString('utf8').slice(0, 200_000)\n}\n","import { join } from 'node:path'\nimport { buildKnowledgeGraph } from './graph'\nimport { loadSourceRegistry } from './sources'\nimport { layoutFor, loadKnowledgePages, writeJson } from './store'\nimport type { KnowledgeIndex } from './types'\n\nexport async function buildKnowledgeIndex(root: string): Promise<KnowledgeIndex> {\n const [pages, sourceRegistry] = await Promise.all([\n loadKnowledgePages(root),\n loadSourceRegistry(root),\n ])\n const index: KnowledgeIndex = {\n root,\n generatedAt: new Date().toISOString(),\n sources: sourceRegistry.sources,\n pages,\n graph: buildKnowledgeGraph(pages),\n }\n return index\n}\n\nexport async function writeKnowledgeIndex(root: string): Promise<KnowledgeIndex> {\n const index = await buildKnowledgeIndex(root)\n await writeJson(join(layoutFor(root).cacheDir, 'index.json'), index)\n return index\n}\n","import { isScaffoldPath } from './store'\nimport type { KnowledgeIndex, KnowledgeLintFinding } from './types'\nimport { normalizeLinkTarget } from './wikilinks'\n\nexport function lintKnowledgeIndex(index: KnowledgeIndex): KnowledgeLintFinding[] {\n const findings: KnowledgeLintFinding[] = []\n const byTarget = new Set<string>()\n const titles = new Map<string, string[]>()\n const sourceIds = new Set(index.sources.map((source) => source.id))\n const anchorIds = new Map(\n index.sources.map((source) => [\n source.id,\n new Set((source.anchors ?? []).map((anchor) => anchor.id)),\n ]),\n )\n const pageIds = new Map<string, string[]>()\n const sourceHashes = new Map<string, string[]>()\n for (const page of index.pages) {\n pageIds.set(page.id, [...(pageIds.get(page.id) ?? []), page.path])\n byTarget.add(normalizeLinkTarget(page.id))\n byTarget.add(normalizeLinkTarget(page.title))\n byTarget.add(normalizeLinkTarget(page.path.split('/').pop()!.replace(/\\.md$/, '')))\n const titleKey = page.title.toLowerCase()\n titles.set(titleKey, [...(titles.get(titleKey) ?? []), page.path])\n }\n for (const source of index.sources) {\n sourceHashes.set(source.contentHash, [\n ...(sourceHashes.get(source.contentHash) ?? []),\n source.id,\n ])\n }\n\n const inbound = new Map<string, number>()\n for (const page of index.pages) inbound.set(page.id, 0)\n for (const page of index.pages) {\n if (page.outLinks.length === 0 && !isScaffoldPath(page.path)) {\n findings.push({\n type: 'no-outlinks',\n severity: 'info',\n page: page.path,\n message: 'Page has no wikilinks to other knowledge pages.',\n })\n }\n for (const link of page.outLinks) {\n if (!byTarget.has(normalizeLinkTarget(link))) {\n findings.push({\n type: 'broken-link',\n severity: 'warning',\n page: page.path,\n message: `Broken wikilink [[${link}]].`,\n })\n }\n }\n }\n\n for (const edge of index.graph.edges)\n inbound.set(edge.target, (inbound.get(edge.target) ?? 0) + 1)\n for (const page of index.pages) {\n if (!isScaffoldPath(page.path) && (inbound.get(page.id) ?? 0) === 0) {\n findings.push({\n type: 'orphan',\n severity: 'info',\n page: page.path,\n message: 'No other page links to this page.',\n })\n }\n if (/\\bclaim\\b/i.test(page.text) && page.sourceIds.length === 0) {\n findings.push({\n type: 'uncited-claim',\n severity: 'warning',\n page: page.path,\n message: 'Page appears to contain claims but has no sources frontmatter.',\n })\n }\n for (const sourceId of page.sourceIds) {\n if (!sourceIds.has(sourceId)) {\n findings.push({\n type: 'missing-source',\n severity: 'error',\n page: page.path,\n message: `Page cites unknown source \"${sourceId}\".`,\n metadata: { sourceId },\n })\n }\n }\n for (const ref of extractSourceRefs(page.text)) {\n if (!sourceIds.has(ref.sourceId)) {\n findings.push({\n type: 'missing-source',\n severity: 'error',\n page: page.path,\n message: `Page cites unknown source \"${ref.sourceId}\".`,\n metadata: ref,\n })\n } else if (ref.anchorId && !anchorIds.get(ref.sourceId)?.has(ref.anchorId)) {\n findings.push({\n type: 'missing-source',\n severity: 'error',\n page: page.path,\n message: `Page cites unknown source anchor \"${ref.sourceId}#${ref.anchorId}\".`,\n metadata: ref,\n })\n }\n }\n }\n\n for (const [title, paths] of titles) {\n if (title && paths.length > 1) {\n findings.push({\n type: 'duplicate-title',\n severity: 'warning',\n message: `Duplicate title \"${title}\" in ${paths.join(', ')}.`,\n metadata: { paths },\n })\n }\n }\n for (const [id, paths] of pageIds) {\n if (id && paths.length > 1) {\n findings.push({\n type: 'duplicate-page-id',\n severity: 'error',\n message: `Duplicate page id \"${id}\" in ${paths.join(', ')}.`,\n metadata: { paths },\n })\n }\n }\n for (const [hash, ids] of sourceHashes) {\n if (hash && ids.length > 1) {\n findings.push({\n type: 'duplicate-source-hash',\n severity: 'warning',\n message: `Duplicate source content hash across ${ids.join(', ')}.`,\n metadata: { sourceIds: ids },\n })\n }\n }\n return findings\n}\n\nfunction extractSourceRefs(text: string): Array<{ sourceId: string; anchorId?: string }> {\n const refs: Array<{ sourceId: string; anchorId?: string }> = []\n const regex = /\\[\\^([A-Za-z0-9_-]+)(?:#([A-Za-z0-9_.:-]+))?\\]/g\n let match: RegExpExecArray | null\n while ((match = regex.exec(text)) !== null) {\n refs.push({ sourceId: match[1]!, anchorId: match[2] })\n }\n return refs\n}\n","/**\n * Read a string value from an optional metadata bag, returning `undefined`\n * when the key is absent or holds a non-string value. Shared by the readiness\n * and inspection paths so the \"string field of an untyped record\" coercion is\n * single-sourced.\n *\n * Internal — not re-exported through the package barrel.\n */\nexport function stringMetadata(\n metadata: Record<string, unknown> | undefined,\n key: string,\n): string | undefined {\n const value = metadata?.[key]\n return typeof value === 'string' ? value : undefined\n}\n","import { lintKnowledgeIndex } from './lint'\nimport { stringMetadata } from './metadata'\nimport { searchKnowledge } from './search'\nimport type { KnowledgeIndex, KnowledgeLintFinding, KnowledgePage } from './types'\n\nexport interface KnowledgeInspection {\n pageCount: number\n sourceCount: number\n expiredSourceCount: number\n staleSourceCount: number\n edgeCount: number\n findingCount: number\n blockingFindingCount: number\n topPages: Array<{ path: string; title: string; degree: number; sources: number }>\n sourceFreshness: SourceFreshnessInspection[]\n findings: KnowledgeLintFinding[]\n}\n\nexport interface SourceFreshnessInspection {\n id: string\n title?: string\n uri: string\n status: 'fresh' | 'expired' | 'unknown'\n validUntil?: string\n lastVerifiedAt?: string\n}\n\nexport function inspectKnowledgeIndex(\n index: KnowledgeIndex,\n options: { now?: Date } = {},\n): KnowledgeInspection {\n const now = options.now ?? new Date()\n const findings = lintKnowledgeIndex(index)\n const degree = new Map(index.graph.nodes.map((node) => [node.id, node.inDegree + node.outDegree]))\n const sourceFreshness = index.sources.map((source) => inspectSourceFreshness(source, now))\n return {\n pageCount: index.pages.length,\n sourceCount: index.sources.length,\n expiredSourceCount: sourceFreshness.filter((source) => source.status === 'expired').length,\n staleSourceCount: sourceFreshness.filter((source) => source.status !== 'fresh').length,\n edgeCount: index.graph.edges.length,\n findingCount: findings.length,\n blockingFindingCount: findings.filter((finding) => finding.severity === 'error').length,\n topPages: [...index.pages]\n .sort((a, b) => (degree.get(b.id) ?? 0) - (degree.get(a.id) ?? 0))\n .slice(0, 10)\n .map((page) => ({\n path: page.path,\n title: page.title,\n degree: degree.get(page.id) ?? 0,\n sources: page.sourceIds.length,\n })),\n sourceFreshness,\n findings,\n }\n}\n\nfunction inspectSourceFreshness(\n source: KnowledgeIndex['sources'][number],\n now: Date,\n): SourceFreshnessInspection {\n const validUntil =\n source.validUntil ??\n stringMetadata(source.metadata, 'validUntil') ??\n stringMetadata(source.metadata, 'expiresAt')\n const lastVerifiedAt = source.lastVerifiedAt ?? stringMetadata(source.metadata, 'lastVerifiedAt')\n const status =\n validUntil && Number.isFinite(Date.parse(validUntil))\n ? Date.parse(validUntil) <= now.getTime()\n ? 'expired'\n : 'fresh'\n : 'unknown'\n return { id: source.id, title: source.title, uri: source.uri, status, validUntil, lastVerifiedAt }\n}\n\nexport interface KnowledgeExplanation {\n target: string\n page?: KnowledgePage\n sources: Array<{ id: string; title?: string; uri: string }>\n links: string[]\n inbound: string[]\n related: Array<{ path: string; title: string; score: number }>\n}\n\nexport function explainKnowledgeTarget(\n index: KnowledgeIndex,\n target: string,\n): KnowledgeExplanation {\n const page = index.pages.find(\n (candidate) =>\n candidate.path === target ||\n candidate.id === target ||\n candidate.title.toLowerCase() === target.toLowerCase(),\n )\n const inbound = page\n ? index.graph.edges\n .filter((edge) => edge.target === page.id)\n .map(\n (edge) =>\n index.pages.find((candidate) => candidate.id === edge.source)?.path ?? edge.source,\n )\n : []\n const related = page\n ? searchKnowledge(index, `${page.title} ${page.tags.join(' ')}`, 6)\n .filter((result) => result.page.id !== page.id)\n .map((result) => ({\n path: result.page.path,\n title: result.page.title,\n score: result.score,\n }))\n : searchKnowledge(index, target, 6).map((result) => ({\n path: result.page.path,\n title: result.page.title,\n score: result.score,\n }))\n return {\n target,\n page,\n sources: page\n ? index.sources\n .filter((source) => page.sourceIds.includes(source.id))\n .map((source) => ({ id: source.id, title: source.title, uri: source.uri }))\n : [],\n links: page?.outLinks ?? [],\n inbound,\n related,\n }\n}\n","import type { KnowledgeWriteParseResult } from './types'\n\nconst OPENER_LINE = /^---\\s*FILE:\\s*(.+?)\\s*---\\s*$/i\nconst CLOSER_LINE = /^---\\s*END\\s+FILE\\s*---\\s*$/i\nconst FENCE_LINE = /^\\s{0,3}(```+|~~~+)/\n\nexport function isSafeKnowledgePath(path: string, allowedPrefixes = ['knowledge/']): boolean {\n if (typeof path !== 'string' || path.trim() === '') return false\n // Path-safety validation must reject any control character that could be used\n // in path-traversal / encoding attacks. Built via String.fromCharCode rather\n // than inline `\\xNN` escapes to keep biome's regex-control-char rule happy.\n const controlRangeRegex = new RegExp(`[${String.fromCharCode(0)}-${String.fromCharCode(0x1f)}]`)\n if (controlRangeRegex.test(path)) return false\n if (path.startsWith('/') || path.startsWith('\\\\')) return false\n if (/^[a-zA-Z]:/.test(path)) return false\n const normalized = path.replace(/\\\\/g, '/')\n if (normalized.split('/').some((part) => part === '..')) return false\n return allowedPrefixes.some((prefix) => normalized.startsWith(prefix))\n}\n\nexport function parseKnowledgeWriteBlocks(\n text: string,\n allowedPrefixes = ['knowledge/'],\n): KnowledgeWriteParseResult {\n const lines = text.replace(/\\r\\n/g, '\\n').split('\\n')\n const blocks: KnowledgeWriteParseResult['blocks'] = []\n const warnings: string[] = []\n let i = 0\n\n while (i < lines.length) {\n const opener = OPENER_LINE.exec(lines[i]!)\n if (!opener) {\n i++\n continue\n }\n const path = opener[1]!.trim()\n i++\n const contentLines: string[] = []\n let fenceMarker: string | null = null\n let fenceLen = 0\n let closed = false\n\n while (i < lines.length) {\n const line = lines[i]!\n const fence = FENCE_LINE.exec(line)\n if (fence) {\n const run = fence[1]!\n const char = run[0]!\n if (fenceMarker === null) {\n fenceMarker = char\n fenceLen = run.length\n } else if (char === fenceMarker && run.length >= fenceLen) {\n fenceMarker = null\n fenceLen = 0\n }\n contentLines.push(line)\n i++\n continue\n }\n if (fenceMarker === null && CLOSER_LINE.test(line)) {\n closed = true\n i++\n break\n }\n contentLines.push(line)\n i++\n }\n\n if (!closed) {\n warnings.push(`FILE block \"${path || '(empty)'}\" was not closed before end of stream.`)\n continue\n }\n if (!isSafeKnowledgePath(path, allowedPrefixes)) {\n warnings.push(`FILE block with unsafe path \"${path}\" rejected.`)\n continue\n }\n blocks.push({ path, content: contentLines.join('\\n') })\n }\n\n return { blocks, warnings }\n}\n","import { mkdir, readFile, writeFile } from 'node:fs/promises'\nimport { dirname, join } from 'node:path'\nimport { parseKnowledgeWriteBlocks } from './write-protocol'\n\nexport interface ApplyWriteBlocksResult {\n written: string[]\n warnings: string[]\n}\n\nexport async function applyKnowledgeWriteBlocks(\n root: string,\n proposalText: string,\n): Promise<ApplyWriteBlocksResult> {\n const parsed = parseKnowledgeWriteBlocks(proposalText)\n const written: string[] = []\n for (const block of parsed.blocks) {\n const path = join(root, block.path)\n await mkdir(dirname(path), { recursive: true })\n await writeFile(\n path,\n block.content.endsWith('\\n') ? block.content : `${block.content}\\n`,\n 'utf8',\n )\n written.push(block.path)\n }\n return { written, warnings: parsed.warnings }\n}\n\nexport async function applyKnowledgeWriteBlocksFile(\n root: string,\n proposalPath: string,\n): Promise<ApplyWriteBlocksResult> {\n return applyKnowledgeWriteBlocks(root, await readFile(proposalPath, 'utf8'))\n}\n","import { z } from 'zod'\n\nexport const SourceAnchorSchema = z.object({\n id: z.string().min(1),\n sourceId: z.string().min(1),\n label: z.string().optional(),\n page: z.number().int().positive().optional(),\n lineStart: z.number().int().positive().optional(),\n lineEnd: z.number().int().positive().optional(),\n charStart: z.number().int().nonnegative().optional(),\n charEnd: z.number().int().nonnegative().optional(),\n timestampMs: z.number().nonnegative().optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n})\n\nexport const SourceRecordSchema = z.object({\n id: z.string().min(1),\n uri: z.string().min(1),\n title: z.string().optional(),\n mediaType: z.string().optional(),\n contentHash: z.string().min(16),\n text: z.string().optional(),\n anchors: z.array(SourceAnchorSchema).optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n createdAt: z.string().min(1),\n})\n\nexport const KnowledgePageSchema = z.object({\n id: z.string().min(1),\n path: z.string().min(1),\n title: z.string().min(1),\n text: z.string(),\n frontmatter: z.record(z.string(), z.unknown()),\n sourceIds: z.array(z.string()),\n tags: z.array(z.string()),\n outLinks: z.array(z.string()),\n})\n\nexport const KnowledgeGraphNodeSchema = z.object({\n id: z.string(),\n title: z.string(),\n path: z.string(),\n tags: z.array(z.string()),\n sourceIds: z.array(z.string()),\n outDegree: z.number().int().nonnegative(),\n inDegree: z.number().int().nonnegative(),\n})\n\nexport const KnowledgeGraphEdgeSchema = z.object({\n source: z.string(),\n target: z.string(),\n weight: z.number(),\n reasons: z.array(z.string()),\n})\n\nexport const KnowledgeIndexSchema = z.object({\n root: z.string(),\n generatedAt: z.string(),\n sources: z.array(SourceRecordSchema),\n pages: z.array(KnowledgePageSchema),\n graph: z.object({\n nodes: z.array(KnowledgeGraphNodeSchema),\n edges: z.array(KnowledgeGraphEdgeSchema),\n }),\n})\n\nexport const KnowledgeEventSchema = z.object({\n id: z.string().min(1),\n type: z.enum([\n 'source.added',\n 'proposal.applied',\n 'index.built',\n 'lint.run',\n 'optimization.run',\n 'release.promoted',\n 'release.rejected',\n ]),\n createdAt: z.string().min(1),\n actor: z.string().optional(),\n target: z.string().optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n})\n\nexport const KnowledgeBaseCandidateSchema = z.object({\n id: z.string().min(1),\n units: z.array(\n z.object({\n id: z.string().min(1),\n title: z.string().min(1),\n text: z.string(),\n claims: z\n .array(\n z.object({\n id: z.string().min(1),\n text: z.string().min(1),\n refs: z.array(\n z.object({\n sourceId: z.string().min(1),\n anchorId: z.string().optional(),\n quote: z.string().optional(),\n }),\n ),\n confidence: z.number().min(0).max(1).optional(),\n status: z.enum(['draft', 'active', 'superseded', 'rejected']).optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n }),\n )\n .optional(),\n relations: z\n .array(\n z.object({\n sourceId: z.string(),\n targetId: z.string(),\n predicate: z.string(),\n weight: z.number().optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n }),\n )\n .optional(),\n sourceIds: z.array(z.string()).optional(),\n tags: z.array(z.string()).optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n updatedAt: z.string().optional(),\n }),\n ),\n retrievalPolicy: z.string().optional(),\n synthesisPolicy: z.string().optional(),\n questionPolicy: z.string().optional(),\n updatePolicy: z.string().optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n})\n","import { lintKnowledgeIndex } from './lint'\nimport { KnowledgeIndexSchema } from './schemas'\nimport { isScaffoldPath } from './store'\nimport type { KnowledgeIndex, KnowledgeLintFinding } from './types'\n\nexport interface ValidateKnowledgeOptions {\n strict?: boolean\n}\n\nexport interface ValidateKnowledgeResult {\n ok: boolean\n findings: KnowledgeLintFinding[]\n}\n\nexport function validateKnowledgeIndex(\n index: KnowledgeIndex,\n options: ValidateKnowledgeOptions = {},\n): ValidateKnowledgeResult {\n const findings = [...lintKnowledgeIndex(index)]\n const parsed = KnowledgeIndexSchema.safeParse(index)\n if (!parsed.success) {\n findings.push({\n type: 'missing-frontmatter',\n severity: 'error',\n message: parsed.error.issues\n .map((issue) => `${issue.path.join('.')}: ${issue.message}`)\n .join('; '),\n })\n }\n if (options.strict) {\n for (const page of index.pages) {\n if (isScaffoldPath(page.path)) continue\n if (!page.frontmatter.id || !page.frontmatter.title) {\n findings.push({\n type: 'missing-frontmatter',\n severity: 'error',\n page: page.path,\n message: 'Strict mode requires id and title frontmatter.',\n })\n }\n }\n }\n return { ok: !findings.some((finding) => finding.severity === 'error'), findings }\n}\n"],"mappings":"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","names":["basename","mkdir","readdir","readFile","stat","writeFile","dirname","join","relative","readFile","mkdir","dirname","writeFile","stat","join","mediaTypeFor","relative","readdir","join","join","mkdir","readFile","writeFile","dirname","join","join","mkdir","dirname","writeFile","readFile"]}
package/dist/cli.js CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  searchKnowledge,
12
12
  validateKnowledgeIndex,
13
13
  writeKnowledgeIndex
14
- } from "./chunk-HKYD765Q.js";
14
+ } from "./chunk-WWY5FTKQ.js";
15
15
  import {
16
16
  detectKnowledgeGaps,
17
17
  findSurprisingConnections,
package/dist/index.d.ts CHANGED
@@ -3,6 +3,8 @@ export { C as ClaimRef, n as KnowledgeBaseCandidate, K as KnowledgeGraphEdge, a
3
3
  import { KnowledgeFragment } from './sources/index.js';
4
4
  export { CornellLiiSelector, CornellLiiSourceOptions, FetchOpts, FragmentProvenance, IRS_DIMENSION_HINTS, IrsPublicationsSourceOptions, KnowledgeSource, MAX_RESPONSE_BYTES, MIN_REQUEST_GAP_MS, POLITE_USER_AGENT, PoliteFetchOptions, PoliteFetchResult, StateSosEntity, StateSosSourceConfig, __resetHttpThrottle, createCornellLiiSource, createIrsPublicationsSource, createStateSosSource, extractLinks, firstMatch, htmlToText, innerHtmlById, looksLikeBlockPage, politeFetch } from './sources/index.js';
5
5
  import { KnowledgeRequirementCategory, KnowledgeAcquisitionMode, KnowledgeImportance, KnowledgeFreshness, KnowledgeSensitivity, KnowledgeRequirement, KnowledgeBundle, KnowledgeReadinessReport, UserQuestion, DataAcquisitionPlan, AnalystSeverity, AnalystFinding, RunRecord, ReleaseTraceEvidence, GateDecision, ReleaseConfidenceScorecard, ControlRuntimeConfig, ControlEvalResult } from '@tangle-network/agent-eval';
6
+ export { AgentMemoryAdapter, AgentMemoryContext, AgentMemoryHit, AgentMemoryHitSchema, AgentMemoryKind, AgentMemoryKindSchema, AgentMemoryScope, AgentMemoryScopeSchema, AgentMemorySearchOptions, AgentMemoryWriteInput, AgentMemoryWriteInputSchema, AgentMemoryWriteResult, Neo4jAgentMemoryAdapterOptions, createNeo4jAgentMemoryAdapter, defaultGetMemoryContext, memoryHitToSourceRecord, memoryWriteResultToSourceRecord, renderMemoryContext } from './memory/index.js';
7
+ import { Budget, ExecutorConfig, SuperviseOptions, DeliverableSpec, SupervisedResult } from '@tangle-network/agent-runtime/loops';
6
8
  import { z } from 'zod';
7
9
 
8
10
  interface SourceAdapterInput {
@@ -585,7 +587,15 @@ interface KnowledgeReleaseInput {
585
587
  baselineRuns?: RunRecord[];
586
588
  traces?: ReleaseTraceEvidence[];
587
589
  gateDecision?: GateDecision | null;
588
- /** True when a held-out split was evaluated (drives the holdout threshold). */
590
+ /**
591
+ * True when a held-out split was evaluated (drives the holdout threshold).
592
+ *
593
+ * Constraint: the substrate gate keys the holdout requirement off a scenario
594
+ * corpus, which this run-only report does not carry. With `hasHoldout: true`
595
+ * the gate fails closed (`missing_holdout_split`) even when holdout RunRecords
596
+ * are supplied. Callers that gate on a real held-out split should drive
597
+ * `evaluateReleaseConfidence` directly with a dataset/scenarios.
598
+ */
589
599
  hasHoldout?: boolean;
590
600
  /** Candidate is the search-best variant — a promotion precondition. Default true. */
591
601
  promotedIsBest?: boolean;
@@ -720,6 +730,67 @@ type KnowledgeControlLoopAdapter = Pick<ControlRuntimeConfig<KnowledgeControlLoo
720
730
  declare function createKnowledgeControlLoopAdapter(options: KnowledgeControlLoopAdapterOptions): KnowledgeControlLoopAdapter;
721
731
  declare function runKnowledgeResearchLoop(options: RunKnowledgeResearchLoopOptions): Promise<KnowledgeResearchLoopResult>;
722
732
 
733
+ /**
734
+ * Default standing instructions for a research supervisor. It does NOT solve the
735
+ * research itself — it DECOMPOSES the goal into sub-topics and spawns one
736
+ * researcher per sub-topic over the live `Scope`, widening/narrowing until the
737
+ * readiness gate (the deliverable check) reports the knowledge base is ready.
738
+ */
739
+ declare const RESEARCH_SUPERVISOR_SYSTEM_PROMPT: string;
740
+ interface ResearchSupervisorOptions {
741
+ /** Where the knowledge base lives. The deliverable check reads readiness here. */
742
+ root: string;
743
+ /** The research goal handed to the supervisor as its task. */
744
+ goal: string;
745
+ /**
746
+ * Readiness specs define DONE: the supervisor's deliverable check passes once
747
+ * `scoreKnowledgeReadiness` reports no blocking gaps over the live KB. Required
748
+ * — without a gate the supervisor would never know when to stop.
749
+ */
750
+ readinessSpecs: KnowledgeReadinessSpec[];
751
+ readinessTaskId?: string;
752
+ readiness?: Omit<BuildEvalKnowledgeBundleOptions, 'taskId' | 'index' | 'specs'>;
753
+ /** The conserved compute pool for the whole supervised run. */
754
+ budget: Budget;
755
+ /**
756
+ * WHERE researcher workers run — the caller's real backend seam (sandbox with
757
+ * a `sandboxClient`, or router/cli/bridge). The supervisor spawns researchers
758
+ * on this backend; assembling the seam (creds, sandbox SDK) is the caller's,
759
+ * so there is no fabricated default.
760
+ */
761
+ backend: ExecutorConfig;
762
+ /** Harness for the researcher worker profile (default `researcherProfile`'s). */
763
+ harness?: string;
764
+ /** The supervisor brain's router model. */
765
+ supervisorModel?: string;
766
+ /** Custom supervisor instructions. Defaults to {@link RESEARCH_SUPERVISOR_SYSTEM_PROMPT}. */
767
+ supervisorSystemPrompt?: string;
768
+ /** Extra `supervise()` knobs (perWorker, maxLiveWorkers, router, allowedModels, …). */
769
+ superviseOptions?: Partial<Omit<SuperviseOptions, 'budget' | 'backend' | 'deliverable'>>;
770
+ }
771
+ /**
772
+ * Build the deliverable (completion oracle) for a research supervisor: "settled
773
+ * ⟺ the knowledge base is ready". It re-reads the KB from disk and runs the
774
+ * readiness gate, so the supervisor stops on the REAL grounded state — not on a
775
+ * worker's self-report.
776
+ */
777
+ declare function knowledgeReadinessDeliverable(options: Pick<ResearchSupervisorOptions, 'root' | 'goal' | 'readinessSpecs' | 'readinessTaskId' | 'readiness'>): DeliverableSpec<unknown>;
778
+ /**
779
+ * A research supervisor: a SUPERVISOR brain creates the topology dynamically —
780
+ * how many researchers, split by sub-topic — over the `Scope`, with the
781
+ * knowledge-readiness gate as its stop condition.
782
+ *
783
+ * This is a thin wrapper over `supervise(profile, goal, opts)`. It composes the
784
+ * existing pieces and builds nothing new: the researcher `AgentProfile` (from
785
+ * `researcherProfile`) is the worker shape the supervisor spawns, and
786
+ * `knowledgeReadinessDeliverable` (over `scoreKnowledgeReadiness`) is the
787
+ * completion oracle that decides when the KB is ready.
788
+ *
789
+ * Needs creds (a real supervisor router brain + a worker backend), so it is the
790
+ * LIVE path. The offline two-agent loop is `runTwoAgentResearchLoop`.
791
+ */
792
+ declare function runResearchSupervisor(options: ResearchSupervisorOptions): Promise<SupervisedResult<unknown>>;
793
+
723
794
  declare const SourceAnchorSchema: z.ZodObject<{
724
795
  id: z.ZodString;
725
796
  sourceId: z.ZodString;
@@ -925,6 +996,198 @@ declare function initKnowledgeBase(root: string): Promise<KnowledgeLayout>;
925
996
  declare function loadKnowledgePages(root: string): Promise<KnowledgePage[]>;
926
997
  declare function writeJson(path: string, value: unknown): Promise<void>;
927
998
 
999
+ /**
1000
+ * A knowledge gap the loop surfaces from `scoreKnowledgeReadiness`. The worker
1001
+ * targets these; the driver folds the unfilled remainder into the worker's next
1002
+ * prompt and runs its own gap-fill pass over them.
1003
+ */
1004
+ interface KnowledgeGap {
1005
+ /** Readiness-spec id this gap belongs to. */
1006
+ id: string;
1007
+ /** Human-readable description of what's missing. */
1008
+ description: string;
1009
+ /** The search query the readiness check ran for this requirement. */
1010
+ query: string;
1011
+ /** True when the gap blocks readiness (vs. a soft, non-blocking gap). */
1012
+ blocking: boolean;
1013
+ }
1014
+ /** A new source the worker (or driver) discovered and wants to add to the KB. */
1015
+ type ResearchSourceProposal = AddSourceTextInput;
1016
+ /**
1017
+ * What a research agent contributes in one round. Both the worker and (when
1018
+ * `driverResearches` is on) the driver produce this shape — the worker ADDS
1019
+ * primary findings, the driver gap-FILLS the ones the worker missed.
1020
+ *
1021
+ * `proposalText` is the safe write-protocol text (`---FILE: knowledge/...---`
1022
+ * blocks). The loop only applies it AFTER the driver has verified the round's
1023
+ * sources, so a rejected source never reaches the curated pages.
1024
+ */
1025
+ interface ResearchContribution {
1026
+ /** Immutable sources to register (the raw evidence). */
1027
+ sources?: ResearchSourceProposal[];
1028
+ /** Safe write-protocol text producing curated `knowledge/*.md` pages. */
1029
+ proposalText?: string;
1030
+ /**
1031
+ * Build the page write-protocol text FROM the sources the driver accepted —
1032
+ * the curated, citing pages the readiness gate searches. Receives the
1033
+ * registered `SourceRecord`s (with their assigned ids, so a page's frontmatter
1034
+ * `sources:` can cite them). Returns `---FILE: knowledge/...---` block text or
1035
+ * `undefined`. Runs after verification, so a page never cites a rejected
1036
+ * source. Concatenated after any static `proposalText`.
1037
+ */
1038
+ buildPages?: (acceptedSources: SourceRecord[]) => string | undefined;
1039
+ /** Free-form research transcript — products can persist this. */
1040
+ notes?: string;
1041
+ metadata?: Record<string, unknown>;
1042
+ }
1043
+ /** Context handed to the worker each round. */
1044
+ interface WorkerResearchContext {
1045
+ root: string;
1046
+ goal: string;
1047
+ round: number;
1048
+ index: KnowledgeIndex;
1049
+ /** Gaps the readiness gate currently reports — what the worker should close. */
1050
+ gaps: KnowledgeGap[];
1051
+ /** Steer text the driver folded in from the previous round's remaining gaps. */
1052
+ steer?: string;
1053
+ readiness: EvalKnowledgeBundleBuildResult;
1054
+ signal?: AbortSignal;
1055
+ }
1056
+ /** Context handed to the driver's verifier for one candidate source. */
1057
+ interface SourceVerificationContext {
1058
+ root: string;
1059
+ goal: string;
1060
+ round: number;
1061
+ index: KnowledgeIndex;
1062
+ gaps: KnowledgeGap[];
1063
+ /** Sources already accepted earlier THIS round (in-round dedup). */
1064
+ acceptedThisRound: ResearchSourceProposal[];
1065
+ signal?: AbortSignal;
1066
+ }
1067
+ /** A single rejected source plus the reason the driver gave. */
1068
+ interface RejectedSource {
1069
+ source: ResearchSourceProposal;
1070
+ reason: string;
1071
+ }
1072
+ /** Context handed to the driver's gap-fill pass (only when `driverResearches`). */
1073
+ interface DriverResearchContext {
1074
+ root: string;
1075
+ goal: string;
1076
+ round: number;
1077
+ index: KnowledgeIndex;
1078
+ /** Gaps STILL open after the worker's accepted contribution applied. */
1079
+ remainingGaps: KnowledgeGap[];
1080
+ readiness: EvalKnowledgeBundleBuildResult;
1081
+ signal?: AbortSignal;
1082
+ }
1083
+ /**
1084
+ * The differentiated driver role.
1085
+ *
1086
+ * - `verifySource` — the gate the worker's additions pass before they commit.
1087
+ * Return `{ accept: true }` to keep a source or `{ accept: false, reason }`
1088
+ * to reject it (not real / not relevant / duplicate). The loop dedups exact
1089
+ * duplicates (same `uri` already in the KB or accepted this round) BEFORE
1090
+ * calling this, so the verifier only sees genuinely-new candidates.
1091
+ * - `research` — the driver's OWN gap-fill pass over the gaps the worker left
1092
+ * open. Only invoked when `driverResearches` is true.
1093
+ * - `foldGaps` — turn the remaining gaps into a steer string for the worker's
1094
+ * next prompt. Defaults to a compact bulleted list when omitted.
1095
+ */
1096
+ interface ResearchDriver {
1097
+ verifySource(source: ResearchSourceProposal, ctx: SourceVerificationContext): Promise<SourceVerdict> | SourceVerdict;
1098
+ research?(ctx: DriverResearchContext): Promise<ResearchContribution> | ResearchContribution;
1099
+ foldGaps?(gaps: KnowledgeGap[]): string;
1100
+ }
1101
+ type SourceVerdict = {
1102
+ accept: true;
1103
+ } | {
1104
+ accept: false;
1105
+ reason: string;
1106
+ };
1107
+ /** The worker: primary research targeting the round's gaps. */
1108
+ type ResearchWorker = (ctx: WorkerResearchContext) => Promise<ResearchContribution> | ResearchContribution;
1109
+ interface TwoAgentResearchLoopOptions {
1110
+ root: string;
1111
+ goal: string;
1112
+ worker: ResearchWorker;
1113
+ driver: ResearchDriver;
1114
+ /**
1115
+ * When false (default), the driver ONLY verifies + gates — a pure coordinator
1116
+ * that contributes no research of its own (the "doesn't participate in the
1117
+ * work" mode). When true, the driver also runs its `research` gap-fill pass
1118
+ * each round over the gaps the worker left open.
1119
+ */
1120
+ driverResearches?: boolean;
1121
+ maxRounds?: number;
1122
+ actor?: string;
1123
+ /** Readiness specs define the gate; an empty list means the loop never gates. */
1124
+ readinessSpecs?: KnowledgeReadinessSpec[];
1125
+ readinessTaskId?: string;
1126
+ readiness?: Omit<BuildEvalKnowledgeBundleOptions, 'taskId' | 'index' | 'specs'>;
1127
+ sourceOptions?: Pick<AddSourceOptions, 'adapters' | 'now'>;
1128
+ signal?: AbortSignal;
1129
+ onRound?: (round: TwoAgentResearchRound) => Promise<void> | void;
1130
+ }
1131
+ interface TwoAgentResearchRound {
1132
+ round: number;
1133
+ /** Gaps reported at the START of the round (what the worker targeted). */
1134
+ gaps: KnowledgeGap[];
1135
+ /** Worker sources accepted by the driver and written to the KB. */
1136
+ acceptedWorkerSources: SourceRecord[];
1137
+ /** Worker sources the driver rejected (with reasons) — never written. */
1138
+ rejectedWorkerSources: RejectedSource[];
1139
+ /** Sources the driver itself added in its gap-fill pass. */
1140
+ driverSources: SourceRecord[];
1141
+ /** Curated pages written this round (worker proposal + driver proposal). */
1142
+ writtenPages: string[];
1143
+ readiness?: EvalKnowledgeBundleBuildResult;
1144
+ /** True once the readiness gate reports no blocking gaps. */
1145
+ ready: boolean;
1146
+ event: KnowledgeEvent;
1147
+ notes: {
1148
+ worker?: string;
1149
+ driver?: string;
1150
+ };
1151
+ }
1152
+ interface TwoAgentResearchLoopResult {
1153
+ root: string;
1154
+ goal: string;
1155
+ rounds: number;
1156
+ ready: boolean;
1157
+ index: KnowledgeIndex;
1158
+ readiness?: EvalKnowledgeBundleBuildResult;
1159
+ steps: TwoAgentResearchRound[];
1160
+ }
1161
+ /**
1162
+ * Two-agent (driver + worker) sibling of `runKnowledgeResearchLoop`.
1163
+ *
1164
+ * Both agents research to grow ONE knowledge base. The roles are differentiated:
1165
+ *
1166
+ * - **WORKER** = primary research. Each round it reads the open gaps, discovers
1167
+ * new sources, and proposes additions (`sources` + `proposalText`). It ADDS.
1168
+ * - **DRIVER** = the verifier / gap-filler / gate. It (1) VERIFIES the worker's
1169
+ * sources before they commit — dedup against the KB, then `verifySource`
1170
+ * rejects ones that aren't real/relevant; (2) GAP-FILLS the gaps the worker
1171
+ * missed with its own research pass (when `driverResearches`); (3) folds the
1172
+ * remaining gaps into the worker's next prompt; and (4) GATES on
1173
+ * `scoreKnowledgeReadiness` — the loop stops as soon as there are no blocking
1174
+ * gaps.
1175
+ *
1176
+ * Set `driverResearches: false` (default) for the pure-coordinator mode: the
1177
+ * driver only verifies + gates and contributes no research itself.
1178
+ *
1179
+ * Composes existing atoms — `initKnowledgeBase`, `addSourceText`,
1180
+ * `applyKnowledgeWriteBlocks`, `buildEvalKnowledgeBundle` (the readiness gate),
1181
+ * and `searchKnowledge` — and reinvents none of them.
1182
+ */
1183
+ declare function runTwoAgentResearchLoop(options: TwoAgentResearchLoopOptions): Promise<TwoAgentResearchLoopResult>;
1184
+ /**
1185
+ * Helper for verifiers: does the candidate source's text/title overlap any page
1186
+ * the readiness search returns for a gap query? A cheap relevance heuristic the
1187
+ * driver can compose into `verifySource` (real verifiers can do more).
1188
+ */
1189
+ declare function sourceMatchesGaps(source: ResearchSourceProposal, index: KnowledgeIndex, gaps: KnowledgeGap[]): KnowledgeSearchResult[];
1190
+
928
1191
  declare const WIKILINK_REGEX: RegExp;
929
1192
  declare function extractWikilinks(content: string): string[];
930
1193
  declare function normalizeLinkTarget(target: string): string;
@@ -932,4 +1195,4 @@ declare function normalizeLinkTarget(target: string): string;
932
1195
  declare function isSafeKnowledgePath(path: string, allowedPrefixes?: string[]): boolean;
933
1196
  declare function parseKnowledgeWriteBlocks(text: string, allowedPrefixes?: string[]): KnowledgeWriteParseResult;
934
1197
 
935
- export { type AddSourceOptions, type AddSourceTextInput, type ApplyWriteBlocksResult, type BuildEvalKnowledgeBundleOptions, type ChunkingOptions, type D1Adapter, type DefineReadinessSpecInput, type DetectChangesOptions, type DetectChangesResult, type DiscoveryResult, type DiscoveryTask, type EvalKnowledgeBundleBuildResult, type FileSystemFreshnessStoreOptions, FileSystemKbStore, type FreshnessKey, type FreshnessMark, type FreshnessRecord, type FreshnessTtl, type KbStore, KnowledgeBaseCandidateSchema, type KnowledgeChange, type KnowledgeChangeKind, type KnowledgeChunk, KnowledgeClaim, type KnowledgeControlLoopAction, type KnowledgeControlLoopActionResult, type KnowledgeControlLoopAdapter, type KnowledgeControlLoopAdapterOptions, type KnowledgeControlLoopState, type KnowledgeDiscoveryDispatcher, type KnowledgeDiscoveryWorker, KnowledgeEvent, type KnowledgeEventQuery, KnowledgeEventSchema, KnowledgeEventType, type KnowledgeExplanation, KnowledgeFragment, type KnowledgeFreshnessStore, KnowledgeGraph, KnowledgeGraphEdgeSchema, KnowledgeGraphNodeSchema, KnowledgeIndex, KnowledgeIndexSchema, type KnowledgeInspection, type KnowledgeLayout, KnowledgeLintFinding, KnowledgePage, KnowledgePageSchema, type KnowledgeProposal, KnowledgeProposalParseError, type KnowledgeReadinessSpec, KnowledgeRelease, type KnowledgeReleaseInput, type KnowledgeReleaseReport, type KnowledgeResearchLoopContext, type KnowledgeResearchLoopDecision, type KnowledgeResearchLoopResult, type KnowledgeResearchLoopStep, KnowledgeSearchResult, KnowledgeWriteBlock, KnowledgeWriteParseResult, MemoryKbStore, type ParsedFrontmatter, type ProposeFromFindingsResult, READINESS_SPEC_DEFAULTS, type RunKnowledgeResearchLoopOptions, SCAFFOLD_PAGE_BASENAMES, type SourceAdapter, type SourceAdapterInput, type SourceAdapterOutput, SourceAnchorSchema, type SourceFreshnessInspection, SourceRecord, SourceRecordSchema, SourceRegistry, type ValidateKnowledgeOptions, type ValidateKnowledgeResult, WIKILINK_REGEX, addSourcePath, addSourceText, applyKnowledgeWriteBlocks, applyKnowledgeWriteBlocksFile, buildEvalKnowledgeBundle, buildKnowledgeGraph, buildKnowledgeIndex, chunkMarkdown, createD1FreshnessStoreStub, createFileSystemFreshnessStore, createKnowledgeControlLoopAdapter, createKnowledgeEvent, createLocalDiscoveryDispatcher, defineReadinessSpec, detectChanges, explainKnowledgeTarget, extractWikilinks, formatFrontmatter, initKnowledgeBase, inspectKnowledgeIndex, isSafeKnowledgePath, isScaffoldPath, knowledgeReleaseReport, layoutFor, lintKnowledgeIndex, loadKnowledgePages, loadSourceRegistry, mediaTypeFor, normalizeLinkTarget, parseFrontmatter, parseKnowledgeWriteBlocks, proposeFromFinding, proposeFromFindings, reciprocalRankFusion, runKnowledgeResearchLoop, searchKnowledge, sha256, slugify, sourceRegistryPath, stableId, stripFrontmatter, textSourceAdapter, tokenizeQuery, validateKnowledgeIndex, writeJson, writeKnowledgeIndex, writeSourceRegistry };
1198
+ export { type AddSourceOptions, type AddSourceTextInput, type ApplyWriteBlocksResult, type BuildEvalKnowledgeBundleOptions, type ChunkingOptions, type D1Adapter, type DefineReadinessSpecInput, type DetectChangesOptions, type DetectChangesResult, type DiscoveryResult, type DiscoveryTask, type DriverResearchContext, type EvalKnowledgeBundleBuildResult, type FileSystemFreshnessStoreOptions, FileSystemKbStore, type FreshnessKey, type FreshnessMark, type FreshnessRecord, type FreshnessTtl, type KbStore, KnowledgeBaseCandidateSchema, type KnowledgeChange, type KnowledgeChangeKind, type KnowledgeChunk, KnowledgeClaim, type KnowledgeControlLoopAction, type KnowledgeControlLoopActionResult, type KnowledgeControlLoopAdapter, type KnowledgeControlLoopAdapterOptions, type KnowledgeControlLoopState, type KnowledgeDiscoveryDispatcher, type KnowledgeDiscoveryWorker, KnowledgeEvent, type KnowledgeEventQuery, KnowledgeEventSchema, KnowledgeEventType, type KnowledgeExplanation, KnowledgeFragment, type KnowledgeFreshnessStore, type KnowledgeGap, KnowledgeGraph, KnowledgeGraphEdgeSchema, KnowledgeGraphNodeSchema, KnowledgeIndex, KnowledgeIndexSchema, type KnowledgeInspection, type KnowledgeLayout, KnowledgeLintFinding, KnowledgePage, KnowledgePageSchema, type KnowledgeProposal, KnowledgeProposalParseError, type KnowledgeReadinessSpec, KnowledgeRelease, type KnowledgeReleaseInput, type KnowledgeReleaseReport, type KnowledgeResearchLoopContext, type KnowledgeResearchLoopDecision, type KnowledgeResearchLoopResult, type KnowledgeResearchLoopStep, KnowledgeSearchResult, KnowledgeWriteBlock, KnowledgeWriteParseResult, MemoryKbStore, type ParsedFrontmatter, type ProposeFromFindingsResult, READINESS_SPEC_DEFAULTS, RESEARCH_SUPERVISOR_SYSTEM_PROMPT, type RejectedSource, type ResearchContribution, type ResearchDriver, type ResearchSourceProposal, type ResearchSupervisorOptions, type ResearchWorker, type RunKnowledgeResearchLoopOptions, SCAFFOLD_PAGE_BASENAMES, type SourceAdapter, type SourceAdapterInput, type SourceAdapterOutput, SourceAnchorSchema, type SourceFreshnessInspection, SourceRecord, SourceRecordSchema, SourceRegistry, type SourceVerdict, type SourceVerificationContext, type TwoAgentResearchLoopOptions, type TwoAgentResearchLoopResult, type TwoAgentResearchRound, type ValidateKnowledgeOptions, type ValidateKnowledgeResult, WIKILINK_REGEX, type WorkerResearchContext, addSourcePath, addSourceText, applyKnowledgeWriteBlocks, applyKnowledgeWriteBlocksFile, buildEvalKnowledgeBundle, buildKnowledgeGraph, buildKnowledgeIndex, chunkMarkdown, createD1FreshnessStoreStub, createFileSystemFreshnessStore, createKnowledgeControlLoopAdapter, createKnowledgeEvent, createLocalDiscoveryDispatcher, defineReadinessSpec, detectChanges, explainKnowledgeTarget, extractWikilinks, formatFrontmatter, initKnowledgeBase, inspectKnowledgeIndex, isSafeKnowledgePath, isScaffoldPath, knowledgeReadinessDeliverable, knowledgeReleaseReport, layoutFor, lintKnowledgeIndex, loadKnowledgePages, loadSourceRegistry, mediaTypeFor, normalizeLinkTarget, parseFrontmatter, parseKnowledgeWriteBlocks, proposeFromFinding, proposeFromFindings, reciprocalRankFusion, runKnowledgeResearchLoop, runResearchSupervisor, runTwoAgentResearchLoop, searchKnowledge, sha256, slugify, sourceMatchesGaps, sourceRegistryPath, stableId, stripFrontmatter, textSourceAdapter, tokenizeQuery, validateKnowledgeIndex, writeJson, writeKnowledgeIndex, writeSourceRegistry };