@tangle-network/agent-knowledge 1.10.0 → 1.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +250 -74
  2. package/dist/benchmarks/index.d.ts +5 -0
  3. package/dist/benchmarks/index.js +52 -0
  4. package/dist/chunk-DQ3PDMDP.js +115 -0
  5. package/dist/chunk-DQ3PDMDP.js.map +1 -0
  6. package/dist/chunk-ULXZI235.js +1855 -0
  7. package/dist/chunk-ULXZI235.js.map +1 -0
  8. package/dist/{chunk-U6KQ4FS3.js → chunk-VN2OGUUP.js} +306 -40
  9. package/dist/chunk-VN2OGUUP.js.map +1 -0
  10. package/dist/{chunk-WWY5FTKQ.js → chunk-W6VWYTNH.js} +10 -115
  11. package/dist/chunk-W6VWYTNH.js.map +1 -0
  12. package/dist/chunk-XVU5FFQA.js +49 -0
  13. package/dist/chunk-XVU5FFQA.js.map +1 -0
  14. package/dist/cli.js +4 -2
  15. package/dist/cli.js.map +1 -1
  16. package/dist/index-Cj5jRXOz.d.ts +426 -0
  17. package/dist/index.d.ts +1036 -169
  18. package/dist/index.js +3372 -558
  19. package/dist/index.js.map +1 -1
  20. package/dist/memory/index.d.ts +5 -70
  21. package/dist/memory/index.js +20 -4
  22. package/dist/types-CjqPcTTK.d.ts +319 -0
  23. package/docs/architecture.md +7 -5
  24. package/docs/eval/investment-material-facts.md +252 -0
  25. package/docs/eval/rag-eval-roadmap.md +119 -0
  26. package/docs/results/investment-thesis.md +306 -0
  27. package/docs/results/research-driving.md +265 -0
  28. package/docs/two-agent-research-ab.md +121 -10
  29. package/package.json +8 -9
  30. package/dist/chunk-MU5CEOGE.js +0 -387
  31. package/dist/chunk-MU5CEOGE.js.map +0 -1
  32. package/dist/chunk-U6KQ4FS3.js.map +0 -1
  33. package/dist/chunk-WWY5FTKQ.js.map +0 -1
  34. package/dist/profiles/index.d.ts +0 -194
  35. package/dist/profiles/index.js +0 -11
  36. package/docs/recursive-research-leaf.md +0 -86
  37. package/docs/supervisor-profiles.md +0 -295
  38. /package/dist/{profiles → benchmarks}/index.js.map +0 -0
@@ -1,3 +1,6 @@
1
+ import {
2
+ searchKnowledge
3
+ } from "./chunk-DQ3PDMDP.js";
1
4
  import {
2
5
  sha256,
3
6
  slugify,
@@ -46,115 +49,6 @@ function anchorsForText(uri, text) {
46
49
  return anchors;
47
50
  }
48
51
 
49
- // src/search.ts
50
- var RRF_K = 60;
51
- var STOP_WORDS = /* @__PURE__ */ new Set([
52
- "the",
53
- "is",
54
- "a",
55
- "an",
56
- "what",
57
- "how",
58
- "are",
59
- "was",
60
- "were",
61
- "to",
62
- "for",
63
- "of",
64
- "with",
65
- "by",
66
- "in",
67
- "on",
68
- "and"
69
- ]);
70
- function searchKnowledge(index, query, limit = 10) {
71
- const trimmed = query.trim();
72
- if (trimmed === "") return [];
73
- const tokenRanked = rankByTokens(index.pages, trimmed);
74
- const graphRanked = rankByGraph(index.pages, tokenRanked);
75
- const scores = reciprocalRankFusion([tokenRanked.map((p) => p.id), graphRanked.map((p) => p.id)]);
76
- const byId = new Map(index.pages.map((page) => [page.id, page]));
77
- const ranked = [...scores.entries()].map(([id, score]) => ({ page: byId.get(id), score })).filter((item) => Boolean(item.page)).sort((a, b) => b.score - a.score || a.page.path.localeCompare(b.page.path)).slice(0, limit);
78
- const topScore = ranked[0]?.score ?? 0;
79
- return ranked.map((item, i) => ({
80
- page: item.page,
81
- score: item.score,
82
- rrfScore: item.score,
83
- normalizedScore: topScore > 0 ? item.score / topScore : 0,
84
- rank: i + 1,
85
- snippet: buildSnippet(item.page.text, trimmed),
86
- reasons: reasonsFor(item.page, trimmed)
87
- }));
88
- }
89
- function tokenizeQuery(query) {
90
- const raw = query.toLowerCase().split(/[\s,,。!?、;:""''()()\-_/\\·~~…]+/).filter((token) => token.length > 1 && !STOP_WORDS.has(token));
91
- const tokens = [];
92
- for (const token of raw) {
93
- if (/[\u4e00-\u9fff\u3400-\u4dbf]/.test(token) && token.length > 2) {
94
- const chars = [...token];
95
- for (let i = 0; i < chars.length - 1; i++) tokens.push(chars[i] + chars[i + 1]);
96
- tokens.push(...chars);
97
- }
98
- tokens.push(token);
99
- }
100
- return [...new Set(tokens)];
101
- }
102
- function reciprocalRankFusion(rankLists, k = RRF_K) {
103
- const scores = /* @__PURE__ */ new Map();
104
- for (const list of rankLists) {
105
- list.forEach((id, idx) => {
106
- scores.set(id, (scores.get(id) ?? 0) + 1 / (k + idx + 1));
107
- });
108
- }
109
- return scores;
110
- }
111
- function rankByTokens(pages, query) {
112
- const tokens = tokenizeQuery(query);
113
- const effective = tokens.length > 0 ? tokens : [query.toLowerCase()];
114
- return pages.map((page) => ({ page, score: tokenScore(page, query, effective) })).filter((item) => item.score > 0).sort((a, b) => b.score - a.score || a.page.path.localeCompare(b.page.path)).map((item) => item.page);
115
- }
116
- function rankByGraph(pages, tokenRanked) {
117
- if (tokenRanked.length === 0) return [];
118
- const seeds = new Set(tokenRanked.slice(0, 5).map((page) => page.id));
119
- return pages.map((page) => ({
120
- page,
121
- score: page.outLinks.filter((link) => seeds.has(link)).length + page.sourceIds.filter(
122
- (source) => tokenRanked.some((seed) => seed.sourceIds.includes(source))
123
- ).length
124
- })).filter((item) => item.score > 0).sort((a, b) => b.score - a.score || a.page.path.localeCompare(b.page.path)).map((item) => item.page);
125
- }
126
- function tokenScore(page, query, tokens) {
127
- const title = page.title.toLowerCase();
128
- const path = page.path.toLowerCase();
129
- const body = page.text.toLowerCase();
130
- const phrase = query.toLowerCase();
131
- let score = 0;
132
- if (path.endsWith(`${phrase}.md`) || title === phrase) score += 200;
133
- if (title.includes(phrase)) score += 50;
134
- if (body.includes(phrase)) score += 20;
135
- for (const token of tokens) {
136
- if (title.includes(token)) score += 5;
137
- if (body.includes(token)) score += 1;
138
- if (path.includes(token)) score += 3;
139
- }
140
- return score;
141
- }
142
- function buildSnippet(text, query) {
143
- const compact = text.replace(/\s+/g, " ").trim();
144
- const idx = compact.toLowerCase().indexOf(query.toLowerCase());
145
- if (idx < 0) return compact.slice(0, 180);
146
- return compact.slice(Math.max(0, idx - 80), Math.min(compact.length, idx + query.length + 100));
147
- }
148
- function reasonsFor(page, query) {
149
- const lower = `${page.title}
150
- ${page.text}`.toLowerCase();
151
- const reasons = [];
152
- if (lower.includes(query.toLowerCase())) reasons.push("phrase");
153
- if (page.sourceIds.length > 0) reasons.push("sourced");
154
- if (page.outLinks.length > 0) reasons.push("linked");
155
- return reasons;
156
- }
157
-
158
52
  // src/frontmatter.ts
159
53
  function parseFrontmatter(content) {
160
54
  const normalized = content.replace(/\r\n/g, "\n");
@@ -223,8 +117,10 @@ function extractWikilinks(content) {
223
117
  const links = [];
224
118
  const regex = new RegExp(WIKILINK_REGEX.source, "g");
225
119
  let match;
226
- while ((match = regex.exec(content)) !== null) {
120
+ match = regex.exec(content);
121
+ while (match !== null) {
227
122
  links.push(match[1].trim());
123
+ match = regex.exec(content);
228
124
  }
229
125
  return [...new Set(links)];
230
126
  }
@@ -709,8 +605,10 @@ function extractSourceRefs(text) {
709
605
  const refs = [];
710
606
  const regex = /\[\^([A-Za-z0-9_-]+)(?:#([A-Za-z0-9_.:-]+))?\]/g;
711
607
  let match;
712
- while ((match = regex.exec(text)) !== null) {
608
+ match = regex.exec(text);
609
+ while (match !== null) {
713
610
  refs.push({ sourceId: match[1], anchorId: match[2] });
611
+ match = regex.exec(text);
714
612
  }
715
613
  return refs;
716
614
  }
@@ -1021,9 +919,6 @@ export {
1021
919
  textSourceAdapter,
1022
920
  mediaTypeFor,
1023
921
  stringMetadata,
1024
- searchKnowledge,
1025
- tokenizeQuery,
1026
- reciprocalRankFusion,
1027
922
  parseFrontmatter,
1028
923
  formatFrontmatter,
1029
924
  WIKILINK_REGEX,
@@ -1060,4 +955,4 @@ export {
1060
955
  KnowledgeBaseCandidateSchema,
1061
956
  validateKnowledgeIndex
1062
957
  };
1063
- //# sourceMappingURL=chunk-WWY5FTKQ.js.map
958
+ //# sourceMappingURL=chunk-W6VWYTNH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters.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","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 match = regex.exec(content)\n while (match !== null) {\n links.push(match[1]!.trim())\n match = regex.exec(content)\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 match = regex.exec(text)\n while (match !== null) {\n refs.push({ sourceId: match[1]!, anchorId: match[2] })\n match = regex.exec(text)\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"]}
@@ -0,0 +1,49 @@
1
+ import {
2
+ sha256,
3
+ stableId
4
+ } from "./chunk-YMKHCTS2.js";
5
+
6
+ // src/memory/source-record.ts
7
+ function memoryHitToSourceRecord(hit, options = {}) {
8
+ const contentHash = sha256(`${hit.uri}
9
+ ${hit.text}`);
10
+ return {
11
+ id: stableId("src", `${hit.uri}:${contentHash}`),
12
+ uri: hit.uri,
13
+ title: hit.title ?? `${hit.kind}:${hit.id}`,
14
+ mediaType: "text/plain",
15
+ contentHash,
16
+ text: hit.text,
17
+ validUntil: hit.validUntil,
18
+ lastVerifiedAt: hit.lastVerifiedAt,
19
+ createdAt: (options.now ?? (() => /* @__PURE__ */ new Date()))().toISOString(),
20
+ metadata: {
21
+ ...hit.metadata ?? {},
22
+ source: "agent-memory",
23
+ memoryId: hit.id,
24
+ memoryKind: hit.kind,
25
+ score: hit.score,
26
+ normalizedScore: hit.normalizedScore,
27
+ confidence: hit.confidence,
28
+ scope: options.scope
29
+ }
30
+ };
31
+ }
32
+ function memoryWriteResultToSourceRecord(result, text, options = {}) {
33
+ return memoryHitToSourceRecord(
34
+ {
35
+ id: result.id,
36
+ uri: result.uri,
37
+ kind: result.kind,
38
+ text,
39
+ metadata: result.metadata
40
+ },
41
+ options
42
+ );
43
+ }
44
+
45
+ export {
46
+ memoryHitToSourceRecord,
47
+ memoryWriteResultToSourceRecord
48
+ };
49
+ //# sourceMappingURL=chunk-XVU5FFQA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/memory/source-record.ts"],"sourcesContent":["import { sha256, stableId } from '../ids'\nimport type { SourceRecord } from '../types'\nimport type { AgentMemoryHit, AgentMemoryScope, AgentMemoryWriteResult } from './types'\n\nexport function memoryHitToSourceRecord(\n hit: AgentMemoryHit,\n options: { now?: () => Date; scope?: AgentMemoryScope } = {},\n): SourceRecord {\n const contentHash = sha256(`${hit.uri}\\n${hit.text}`)\n return {\n id: stableId('src', `${hit.uri}:${contentHash}`),\n uri: hit.uri,\n title: hit.title ?? `${hit.kind}:${hit.id}`,\n mediaType: 'text/plain',\n contentHash,\n text: hit.text,\n validUntil: hit.validUntil,\n lastVerifiedAt: hit.lastVerifiedAt,\n createdAt: (options.now ?? (() => new Date()))().toISOString(),\n metadata: {\n ...(hit.metadata ?? {}),\n source: 'agent-memory',\n memoryId: hit.id,\n memoryKind: hit.kind,\n score: hit.score,\n normalizedScore: hit.normalizedScore,\n confidence: hit.confidence,\n scope: options.scope,\n },\n }\n}\n\nexport function memoryWriteResultToSourceRecord(\n result: AgentMemoryWriteResult,\n text: string,\n options: { now?: () => Date; scope?: AgentMemoryScope } = {},\n): SourceRecord {\n return memoryHitToSourceRecord(\n {\n id: result.id,\n uri: result.uri,\n kind: result.kind,\n text,\n metadata: result.metadata,\n },\n options,\n )\n}\n"],"mappings":";;;;;;AAIO,SAAS,wBACd,KACA,UAA0D,CAAC,GAC7C;AACd,QAAM,cAAc,OAAO,GAAG,IAAI,GAAG;AAAA,EAAK,IAAI,IAAI,EAAE;AACpD,SAAO;AAAA,IACL,IAAI,SAAS,OAAO,GAAG,IAAI,GAAG,IAAI,WAAW,EAAE;AAAA,IAC/C,KAAK,IAAI;AAAA,IACT,OAAO,IAAI,SAAS,GAAG,IAAI,IAAI,IAAI,IAAI,EAAE;AAAA,IACzC,WAAW;AAAA,IACX;AAAA,IACA,MAAM,IAAI;AAAA,IACV,YAAY,IAAI;AAAA,IAChB,gBAAgB,IAAI;AAAA,IACpB,YAAY,QAAQ,QAAQ,MAAM,oBAAI,KAAK,IAAI,EAAE,YAAY;AAAA,IAC7D,UAAU;AAAA,MACR,GAAI,IAAI,YAAY,CAAC;AAAA,MACrB,QAAQ;AAAA,MACR,UAAU,IAAI;AAAA,MACd,YAAY,IAAI;AAAA,MAChB,OAAO,IAAI;AAAA,MACX,iBAAiB,IAAI;AAAA,MACrB,YAAY,IAAI;AAAA,MAChB,OAAO,QAAQ;AAAA,IACjB;AAAA,EACF;AACF;AAEO,SAAS,gCACd,QACA,MACA,UAA0D,CAAC,GAC7C;AACd,SAAO;AAAA,IACL;AAAA,MACE,IAAI,OAAO;AAAA,MACX,KAAK,OAAO;AAAA,MACZ,MAAM,OAAO;AAAA,MACb;AAAA,MACA,UAAU,OAAO;AAAA,IACnB;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
package/dist/cli.js CHANGED
@@ -8,15 +8,17 @@ import {
8
8
  layoutFor,
9
9
  lintKnowledgeIndex,
10
10
  loadSourceRegistry,
11
- searchKnowledge,
12
11
  validateKnowledgeIndex,
13
12
  writeKnowledgeIndex
14
- } from "./chunk-WWY5FTKQ.js";
13
+ } from "./chunk-W6VWYTNH.js";
15
14
  import {
16
15
  detectKnowledgeGaps,
17
16
  findSurprisingConnections,
18
17
  toKnowledgeVizGraph
19
18
  } from "./chunk-4PNXQ2NT.js";
19
+ import {
20
+ searchKnowledge
21
+ } from "./chunk-DQ3PDMDP.js";
20
22
  import "./chunk-YMKHCTS2.js";
21
23
 
22
24
  // src/cli.ts
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { existsSync, readFileSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\n\nimport { type buildKnowledgeIndex, writeKnowledgeIndex } from './indexer'\nimport { explainKnowledgeTarget, inspectKnowledgeIndex } from './inspect'\nimport { lintKnowledgeIndex } from './lint'\nimport { applyKnowledgeWriteBlocksFile } from './proposals'\nimport { searchKnowledge } from './search'\nimport { addSourcePath, loadSourceRegistry } from './sources'\nimport { initKnowledgeBase, layoutFor } from './store'\nimport { validateKnowledgeIndex } from './validate'\nimport { detectKnowledgeGaps, findSurprisingConnections, toKnowledgeVizGraph } from './viz/index'\n\ninterface Args {\n command: string\n positional: string[]\n flags: Record<string, string>\n}\n\nfunction parseArgs(argv: string[]): Args {\n const [command, ...rest] = argv\n const positional: string[] = []\n const flags: Record<string, string> = {}\n for (let i = 0; i < rest.length; i++) {\n const token = rest[i]!\n if (token.startsWith('--')) {\n const key = token.slice(2)\n const next = rest[i + 1]\n if (next && !next.startsWith('--')) {\n flags[key] = next\n i++\n } else {\n flags[key] = 'true'\n }\n } else {\n positional.push(token)\n }\n }\n return { command: command ?? 'help', positional, flags }\n}\n\nconst HELP = `agent-knowledge — source-grounded knowledge graph CLI.\n\nCommands:\n init [--root .]\n Create raw/sources, knowledge, and cache directories.\n index [--root .] [--json]\n Build .agent-knowledge/index.json from knowledge/**/*.md.\n source-add <path> [--root .] [--json]\n Copy a file or directory into raw/sources and register immutable source records.\n sources [--root .] [--json]\n List registered sources.\n apply-write-blocks <proposal-file> [--root .] [--json]\n Apply safe ---FILE: knowledge/...--- blocks emitted by an agent.\n inspect [--root .] [--json]\n Summarize page/source/edge counts, top pages, and lint state.\n explain <page|id|query> [--root .] [--json]\n Explain sources, links, inbound links, and related pages.\n search <query> [--root .] [--limit 10] [--json]\n Fast local token+graph search over the generated knowledge index.\n graph [--root .] [--format summary|json]\n Emit graph summary or JSON.\n lint [--root .] [--json]\n Run deterministic structural lint.\n validate [--root .] [--strict] [--json]\n Run schema + lint validation. Exits non-zero on blocking findings.\n export [--root .] [--format json]\n Export the current index.\n viz [--root .] [--json]\n Emit graph gaps and surprising connections.\n version\n Print package version.\n`\n\nasync function main(): Promise<number> {\n const args = parseArgs(process.argv.slice(2))\n const root = resolve(args.flags.root ?? '.')\n switch (args.command) {\n case 'init': {\n const layout = await initKnowledgeBase(root)\n process.stdout.write(`initialized knowledge base at ${layout.root}\\n`)\n return 0\n }\n case 'index': {\n const index = await writeKnowledgeIndex(root)\n if (args.flags.json === 'true') process.stdout.write(`${JSON.stringify(index, null, 2)}\\n`)\n else\n process.stdout.write(\n `indexed ${index.pages.length} pages, ${index.graph.edges.length} edges\\n`,\n )\n return 0\n }\n case 'source-add': {\n const [path] = args.positional\n if (!path) {\n process.stderr.write('source-add requires a file or directory path\\n')\n return 1\n }\n await initKnowledgeBase(root)\n const sources = await addSourcePath(root, resolve(path))\n if (args.flags.json === 'true') process.stdout.write(`${JSON.stringify(sources, null, 2)}\\n`)\n else for (const source of sources) process.stdout.write(`${source.id} ${source.uri}\\n`)\n return 0\n }\n case 'sources': {\n const registry = await loadSourceRegistry(root)\n if (args.flags.json === 'true')\n process.stdout.write(`${JSON.stringify(registry.sources, null, 2)}\\n`)\n else {\n for (const source of registry.sources)\n process.stdout.write(`${source.id} ${source.title ?? source.uri} ${source.uri}\\n`)\n }\n return 0\n }\n case 'apply-write-blocks': {\n const [proposalPath] = args.positional\n if (!proposalPath) {\n process.stderr.write('apply-write-blocks requires a proposal file\\n')\n return 1\n }\n await initKnowledgeBase(root)\n const result = await applyKnowledgeWriteBlocksFile(root, resolve(proposalPath))\n await writeKnowledgeIndex(root)\n if (args.flags.json === 'true') process.stdout.write(`${JSON.stringify(result, null, 2)}\\n`)\n else {\n for (const path of result.written) process.stdout.write(`wrote ${path}\\n`)\n for (const warning of result.warnings) process.stderr.write(`warning: ${warning}\\n`)\n }\n return result.warnings.length > 0 ? 2 : 0\n }\n case 'inspect': {\n const index = await loadOrBuildIndex(root)\n const inspection = inspectKnowledgeIndex(index)\n if (args.flags.json === 'true')\n process.stdout.write(`${JSON.stringify(inspection, null, 2)}\\n`)\n else {\n process.stdout.write(\n `pages=${inspection.pageCount} sources=${inspection.sourceCount} edges=${inspection.edgeCount} findings=${inspection.findingCount} blocking=${inspection.blockingFindingCount}\\n`,\n )\n for (const page of inspection.topPages.slice(0, 5))\n process.stdout.write(`${page.degree} ${page.path} sources=${page.sources}\\n`)\n }\n return inspection.blockingFindingCount > 0 ? 2 : 0\n }\n case 'explain': {\n const target = args.positional.join(' ')\n if (!target) {\n process.stderr.write('explain requires a page path, id, title, or query\\n')\n return 1\n }\n const explanation = explainKnowledgeTarget(await loadOrBuildIndex(root), target)\n if (args.flags.json === 'true')\n process.stdout.write(`${JSON.stringify(explanation, null, 2)}\\n`)\n else {\n process.stdout.write(`${explanation.page ? explanation.page.title : target}\\n`)\n for (const source of explanation.sources)\n process.stdout.write(`source ${source.id} ${source.title ?? source.uri}\\n`)\n for (const link of explanation.links) process.stdout.write(`out ${link}\\n`)\n for (const inbound of explanation.inbound) process.stdout.write(`in ${inbound}\\n`)\n for (const related of explanation.related.slice(0, 5))\n process.stdout.write(`related ${related.path} score=${related.score.toFixed(5)}\\n`)\n }\n return 0\n }\n case 'search': {\n const query = args.positional.join(' ')\n if (!query) {\n process.stderr.write('search requires a query\\n')\n return 1\n }\n const index = await loadOrBuildIndex(root)\n const results = searchKnowledge(index, query, Number(args.flags.limit ?? 10))\n if (args.flags.json === 'true') {\n process.stdout.write(`${JSON.stringify(results, null, 2)}\\n`)\n } else {\n for (const result of results) {\n process.stdout.write(\n `${result.rank}. ${result.page.title} (${result.page.path}) score=${result.score.toFixed(5)}\\n`,\n )\n if (result.snippet) process.stdout.write(` ${result.snippet}\\n`)\n }\n }\n return 0\n }\n case 'graph': {\n const index = await loadOrBuildIndex(root)\n if ((args.flags.format ?? 'summary') === 'json')\n process.stdout.write(`${JSON.stringify(index.graph, null, 2)}\\n`)\n else\n process.stdout.write(\n `nodes=${index.graph.nodes.length} edges=${index.graph.edges.length}\\n`,\n )\n return 0\n }\n case 'lint': {\n const index = await loadOrBuildIndex(root)\n const findings = lintKnowledgeIndex(index)\n if (args.flags.json === 'true') process.stdout.write(`${JSON.stringify(findings, null, 2)}\\n`)\n else {\n if (findings.length === 0) process.stdout.write('no findings\\n')\n for (const finding of findings) {\n process.stdout.write(\n `${finding.severity.toUpperCase()} ${finding.type}${finding.page ? ` ${finding.page}` : ''}: ${finding.message}\\n`,\n )\n }\n }\n return findings.some((finding) => finding.severity === 'error') ? 2 : 0\n }\n case 'validate': {\n const result = validateKnowledgeIndex(await loadOrBuildIndex(root), {\n strict: args.flags.strict === 'true',\n })\n if (args.flags.json === 'true') process.stdout.write(`${JSON.stringify(result, null, 2)}\\n`)\n else {\n process.stdout.write(result.ok ? 'valid\\n' : 'invalid\\n')\n for (const finding of result.findings)\n process.stdout.write(\n `${finding.severity.toUpperCase()} ${finding.type}${finding.page ? ` ${finding.page}` : ''}: ${finding.message}\\n`,\n )\n }\n return result.ok ? 0 : 2\n }\n case 'export': {\n const index = await loadOrBuildIndex(root)\n const format = args.flags.format ?? 'json'\n if (format !== 'json') {\n process.stderr.write('export currently supports --format json\\n')\n return 1\n }\n process.stdout.write(`${JSON.stringify(index, null, 2)}\\n`)\n return 0\n }\n case 'viz': {\n const index = await loadOrBuildIndex(root)\n const viz = toKnowledgeVizGraph(index.graph)\n const payload = {\n graph: viz,\n gaps: detectKnowledgeGaps(viz),\n surprisingConnections: findSurprisingConnections(viz),\n }\n if (args.flags.json === 'true') process.stdout.write(`${JSON.stringify(payload, null, 2)}\\n`)\n else {\n process.stdout.write(\n `communities=${viz.communities.length} gaps=${payload.gaps.length} surprising=${payload.surprisingConnections.length}\\n`,\n )\n }\n return 0\n }\n case 'version': {\n const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')) as {\n version: string\n }\n process.stdout.write(`${pkg.version}\\n`)\n return 0\n }\n case 'help':\n case '--help':\n case '-h':\n process.stdout.write(HELP)\n return 0\n default:\n process.stderr.write(`unknown command: ${args.command}\\n${HELP}`)\n return 1\n }\n}\n\nasync function loadOrBuildIndex(root: string) {\n const path = join(layoutFor(root).cacheDir, 'index.json')\n if (existsSync(path))\n return JSON.parse(readFileSync(path, 'utf8')) as Awaited<ReturnType<typeof buildKnowledgeIndex>>\n return await writeKnowledgeIndex(root)\n}\n\nmain()\n .then((code) => process.exit(code))\n .catch((err) => {\n process.stderr.write(\n `agent-knowledge error: ${err instanceof Error ? (err.stack ?? err.message) : String(err)}\\n`,\n )\n process.exit(1)\n })\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { existsSync, readFileSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\n\nimport { type buildKnowledgeIndex, writeKnowledgeIndex } from './indexer'\nimport { explainKnowledgeTarget, inspectKnowledgeIndex } from './inspect'\nimport { lintKnowledgeIndex } from './lint'\nimport { applyKnowledgeWriteBlocksFile } from './proposals'\nimport { searchKnowledge } from './search'\nimport { addSourcePath, loadSourceRegistry } from './sources'\nimport { initKnowledgeBase, layoutFor } from './store'\nimport { validateKnowledgeIndex } from './validate'\nimport { detectKnowledgeGaps, findSurprisingConnections, toKnowledgeVizGraph } from './viz/index'\n\ninterface Args {\n command: string\n positional: string[]\n flags: Record<string, string>\n}\n\nfunction parseArgs(argv: string[]): Args {\n const [command, ...rest] = argv\n const positional: string[] = []\n const flags: Record<string, string> = {}\n for (let i = 0; i < rest.length; i++) {\n const token = rest[i]!\n if (token.startsWith('--')) {\n const key = token.slice(2)\n const next = rest[i + 1]\n if (next && !next.startsWith('--')) {\n flags[key] = next\n i++\n } else {\n flags[key] = 'true'\n }\n } else {\n positional.push(token)\n }\n }\n return { command: command ?? 'help', positional, flags }\n}\n\nconst HELP = `agent-knowledge — source-grounded knowledge graph CLI.\n\nCommands:\n init [--root .]\n Create raw/sources, knowledge, and cache directories.\n index [--root .] [--json]\n Build .agent-knowledge/index.json from knowledge/**/*.md.\n source-add <path> [--root .] [--json]\n Copy a file or directory into raw/sources and register immutable source records.\n sources [--root .] [--json]\n List registered sources.\n apply-write-blocks <proposal-file> [--root .] [--json]\n Apply safe ---FILE: knowledge/...--- blocks emitted by an agent.\n inspect [--root .] [--json]\n Summarize page/source/edge counts, top pages, and lint state.\n explain <page|id|query> [--root .] [--json]\n Explain sources, links, inbound links, and related pages.\n search <query> [--root .] [--limit 10] [--json]\n Fast local token+graph search over the generated knowledge index.\n graph [--root .] [--format summary|json]\n Emit graph summary or JSON.\n lint [--root .] [--json]\n Run deterministic structural lint.\n validate [--root .] [--strict] [--json]\n Run schema + lint validation. Exits non-zero on blocking findings.\n export [--root .] [--format json]\n Export the current index.\n viz [--root .] [--json]\n Emit graph gaps and surprising connections.\n version\n Print package version.\n`\n\nasync function main(): Promise<number> {\n const args = parseArgs(process.argv.slice(2))\n const root = resolve(args.flags.root ?? '.')\n switch (args.command) {\n case 'init': {\n const layout = await initKnowledgeBase(root)\n process.stdout.write(`initialized knowledge base at ${layout.root}\\n`)\n return 0\n }\n case 'index': {\n const index = await writeKnowledgeIndex(root)\n if (args.flags.json === 'true') process.stdout.write(`${JSON.stringify(index, null, 2)}\\n`)\n else\n process.stdout.write(\n `indexed ${index.pages.length} pages, ${index.graph.edges.length} edges\\n`,\n )\n return 0\n }\n case 'source-add': {\n const [path] = args.positional\n if (!path) {\n process.stderr.write('source-add requires a file or directory path\\n')\n return 1\n }\n await initKnowledgeBase(root)\n const sources = await addSourcePath(root, resolve(path))\n if (args.flags.json === 'true') process.stdout.write(`${JSON.stringify(sources, null, 2)}\\n`)\n else for (const source of sources) process.stdout.write(`${source.id} ${source.uri}\\n`)\n return 0\n }\n case 'sources': {\n const registry = await loadSourceRegistry(root)\n if (args.flags.json === 'true')\n process.stdout.write(`${JSON.stringify(registry.sources, null, 2)}\\n`)\n else {\n for (const source of registry.sources)\n process.stdout.write(`${source.id} ${source.title ?? source.uri} ${source.uri}\\n`)\n }\n return 0\n }\n case 'apply-write-blocks': {\n const [proposalPath] = args.positional\n if (!proposalPath) {\n process.stderr.write('apply-write-blocks requires a proposal file\\n')\n return 1\n }\n await initKnowledgeBase(root)\n const result = await applyKnowledgeWriteBlocksFile(root, resolve(proposalPath))\n await writeKnowledgeIndex(root)\n if (args.flags.json === 'true') process.stdout.write(`${JSON.stringify(result, null, 2)}\\n`)\n else {\n for (const path of result.written) process.stdout.write(`wrote ${path}\\n`)\n for (const warning of result.warnings) process.stderr.write(`warning: ${warning}\\n`)\n }\n return result.warnings.length > 0 ? 2 : 0\n }\n case 'inspect': {\n const index = await loadOrBuildIndex(root)\n const inspection = inspectKnowledgeIndex(index)\n if (args.flags.json === 'true')\n process.stdout.write(`${JSON.stringify(inspection, null, 2)}\\n`)\n else {\n process.stdout.write(\n `pages=${inspection.pageCount} sources=${inspection.sourceCount} edges=${inspection.edgeCount} findings=${inspection.findingCount} blocking=${inspection.blockingFindingCount}\\n`,\n )\n for (const page of inspection.topPages.slice(0, 5))\n process.stdout.write(`${page.degree} ${page.path} sources=${page.sources}\\n`)\n }\n return inspection.blockingFindingCount > 0 ? 2 : 0\n }\n case 'explain': {\n const target = args.positional.join(' ')\n if (!target) {\n process.stderr.write('explain requires a page path, id, title, or query\\n')\n return 1\n }\n const explanation = explainKnowledgeTarget(await loadOrBuildIndex(root), target)\n if (args.flags.json === 'true')\n process.stdout.write(`${JSON.stringify(explanation, null, 2)}\\n`)\n else {\n process.stdout.write(`${explanation.page ? explanation.page.title : target}\\n`)\n for (const source of explanation.sources)\n process.stdout.write(`source ${source.id} ${source.title ?? source.uri}\\n`)\n for (const link of explanation.links) process.stdout.write(`out ${link}\\n`)\n for (const inbound of explanation.inbound) process.stdout.write(`in ${inbound}\\n`)\n for (const related of explanation.related.slice(0, 5))\n process.stdout.write(`related ${related.path} score=${related.score.toFixed(5)}\\n`)\n }\n return 0\n }\n case 'search': {\n const query = args.positional.join(' ')\n if (!query) {\n process.stderr.write('search requires a query\\n')\n return 1\n }\n const index = await loadOrBuildIndex(root)\n const results = searchKnowledge(index, query, Number(args.flags.limit ?? 10))\n if (args.flags.json === 'true') {\n process.stdout.write(`${JSON.stringify(results, null, 2)}\\n`)\n } else {\n for (const result of results) {\n process.stdout.write(\n `${result.rank}. ${result.page.title} (${result.page.path}) score=${result.score.toFixed(5)}\\n`,\n )\n if (result.snippet) process.stdout.write(` ${result.snippet}\\n`)\n }\n }\n return 0\n }\n case 'graph': {\n const index = await loadOrBuildIndex(root)\n if ((args.flags.format ?? 'summary') === 'json')\n process.stdout.write(`${JSON.stringify(index.graph, null, 2)}\\n`)\n else\n process.stdout.write(\n `nodes=${index.graph.nodes.length} edges=${index.graph.edges.length}\\n`,\n )\n return 0\n }\n case 'lint': {\n const index = await loadOrBuildIndex(root)\n const findings = lintKnowledgeIndex(index)\n if (args.flags.json === 'true') process.stdout.write(`${JSON.stringify(findings, null, 2)}\\n`)\n else {\n if (findings.length === 0) process.stdout.write('no findings\\n')\n for (const finding of findings) {\n process.stdout.write(\n `${finding.severity.toUpperCase()} ${finding.type}${finding.page ? ` ${finding.page}` : ''}: ${finding.message}\\n`,\n )\n }\n }\n return findings.some((finding) => finding.severity === 'error') ? 2 : 0\n }\n case 'validate': {\n const result = validateKnowledgeIndex(await loadOrBuildIndex(root), {\n strict: args.flags.strict === 'true',\n })\n if (args.flags.json === 'true') process.stdout.write(`${JSON.stringify(result, null, 2)}\\n`)\n else {\n process.stdout.write(result.ok ? 'valid\\n' : 'invalid\\n')\n for (const finding of result.findings)\n process.stdout.write(\n `${finding.severity.toUpperCase()} ${finding.type}${finding.page ? ` ${finding.page}` : ''}: ${finding.message}\\n`,\n )\n }\n return result.ok ? 0 : 2\n }\n case 'export': {\n const index = await loadOrBuildIndex(root)\n const format = args.flags.format ?? 'json'\n if (format !== 'json') {\n process.stderr.write('export currently supports --format json\\n')\n return 1\n }\n process.stdout.write(`${JSON.stringify(index, null, 2)}\\n`)\n return 0\n }\n case 'viz': {\n const index = await loadOrBuildIndex(root)\n const viz = toKnowledgeVizGraph(index.graph)\n const payload = {\n graph: viz,\n gaps: detectKnowledgeGaps(viz),\n surprisingConnections: findSurprisingConnections(viz),\n }\n if (args.flags.json === 'true') process.stdout.write(`${JSON.stringify(payload, null, 2)}\\n`)\n else {\n process.stdout.write(\n `communities=${viz.communities.length} gaps=${payload.gaps.length} surprising=${payload.surprisingConnections.length}\\n`,\n )\n }\n return 0\n }\n case 'version': {\n const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')) as {\n version: string\n }\n process.stdout.write(`${pkg.version}\\n`)\n return 0\n }\n case 'help':\n case '--help':\n case '-h':\n process.stdout.write(HELP)\n return 0\n default:\n process.stderr.write(`unknown command: ${args.command}\\n${HELP}`)\n return 1\n }\n}\n\nasync function loadOrBuildIndex(root: string) {\n const path = join(layoutFor(root).cacheDir, 'index.json')\n if (existsSync(path))\n return JSON.parse(readFileSync(path, 'utf8')) as Awaited<ReturnType<typeof buildKnowledgeIndex>>\n return await writeKnowledgeIndex(root)\n}\n\nmain()\n .then((code) => process.exit(code))\n .catch((err) => {\n process.stderr.write(\n `agent-knowledge error: ${err instanceof Error ? (err.stack ?? err.message) : String(err)}\\n`,\n )\n process.exit(1)\n })\n"],"mappings":"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","names":[]}