@tangle-network/agent-knowledge 8.0.6 → 8.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/benchmarks/index.d.ts +1 -1
- package/dist/benchmarks/index.js +1 -1
- package/dist/{benchmarks-CPl4AO1k.js → benchmarks-B_07vX0Q.js} +2 -2
- package/dist/{benchmarks-CPl4AO1k.js.map → benchmarks-B_07vX0Q.js.map} +1 -1
- package/dist/cli.js +2 -2
- package/dist/{index-BEVmwlfJ.d.ts → index-BPNsQVSx.d.ts} +3 -3
- package/dist/{index-BEVmwlfJ.d.ts.map → index-BPNsQVSx.d.ts.map} +1 -1
- package/dist/{index-D0wc4GYg.d.ts → index-CLNBGN_f.d.ts} +2 -2
- package/dist/{index-D0wc4GYg.d.ts.map → index-CLNBGN_f.d.ts.map} +1 -1
- package/dist/index.d.ts +214 -23
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +201 -122
- package/dist/index.js.map +1 -1
- package/dist/{inspect-CJQGYuKa.js → inspect-B7AJ7CZS.js} +528 -216
- package/dist/inspect-B7AJ7CZS.js.map +1 -0
- package/dist/memory/index.d.ts +2 -2
- package/dist/memory/index.js +2 -2
- package/dist/{memory-BtZWplh5.js → memory-BPgPIEhj.js} +2 -2
- package/dist/{memory-BtZWplh5.js.map → memory-BPgPIEhj.js.map} +1 -1
- package/dist/{search-CP0QtBJZ.js → search-CtVJ0PKX.js} +24 -5
- package/dist/search-CtVJ0PKX.js.map +1 -0
- package/dist/{types-BOfmvDe-.d.ts → types-CXZS0w00.d.ts} +23 -3
- package/dist/types-CXZS0w00.d.ts.map +1 -0
- package/dist/viz/index.d.ts +1 -1
- package/package.json +4 -4
- package/dist/inspect-CJQGYuKa.js.map +0 -1
- package/dist/search-CP0QtBJZ.js.map +0 -1
- package/dist/types-BOfmvDe-.d.ts.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"inspect-CJQGYuKa.js","names":["mediaTypeFor"],"sources":["../src/adapters.ts","../src/durable-fs.ts","../src/file-transaction.ts","../src/mutation-lock.ts","../src/frontmatter.ts","../src/wikilinks.ts","../src/store.ts","../src/graph.ts","../src/claim-ledger.ts","../src/types.ts","../src/schemas.ts","../src/kb-store.ts","../src/sources.ts","../src/indexer.ts","../src/lint.ts","../src/validate.ts","../src/write-protocol.ts","../src/proposals.ts","../src/metadata.ts","../src/inspect.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 { randomUUID } from 'node:crypto'\nimport { constants } from 'node:fs'\nimport {\n type FileHandle,\n lstat,\n mkdir,\n open,\n readdir,\n realpath,\n rename,\n rm,\n} from 'node:fs/promises'\nimport { basename, dirname, isAbsolute, resolve } from 'node:path'\n\nconst DIRECTORY_FLAGS = constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW\nconst CREATE_FILE_FLAGS =\n constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW\nconst READ_FILE_FLAGS = constants.O_RDONLY | constants.O_NOFOLLOW\n\nexport interface RegularFileSnapshot {\n bytes: Buffer\n mode: number\n}\n\nexport async function writeFileDurable(\n path: string,\n data: string | Buffer,\n options: { encoding?: BufferEncoding; mode?: number } = {},\n): Promise<void> {\n const directory = dirname(path)\n await mkdir(directory, { recursive: true })\n await withDirectoryHandle(directory, async (handle, anchoredDirectory) => {\n const target = resolve(anchoredDirectory, basename(path))\n const existingMode = await regularFileModeOrUndefined(target)\n const requestedMode = options.mode ?? existingMode\n const temporary = resolve(anchoredDirectory, `.${basename(path)}.${randomUUID()}.tmp`)\n let temporaryHandle: FileHandle | undefined\n try {\n temporaryHandle = await open(temporary, CREATE_FILE_FLAGS, requestedMode ?? 0o666)\n await temporaryHandle.writeFile(\n data,\n options.encoding === undefined ? undefined : { encoding: options.encoding },\n )\n if (requestedMode !== undefined) await temporaryHandle.chmod(requestedMode)\n await temporaryHandle.sync()\n await temporaryHandle.close()\n temporaryHandle = undefined\n await rename(temporary, target)\n await syncDirectoryHandle(handle)\n } finally {\n await temporaryHandle?.close().catch(() => undefined)\n await rm(temporary, { force: true }).catch(() => undefined)\n }\n })\n}\n\nexport async function writeJsonDurable(path: string, value: unknown): Promise<void> {\n await writeFileDurable(path, `${JSON.stringify(value, null, 2)}\\n`, { encoding: 'utf8' })\n}\n\nexport async function writeFileDurableWithinRoot(\n root: string,\n relativePath: string,\n data: string | Buffer,\n options: { encoding?: BufferEncoding; mode?: number } = {},\n): Promise<void> {\n await withSafeDescendant(root, relativePath, (path) => writeFileDurable(path, data, options))\n}\n\nexport async function writeJsonDurableWithinRoot(\n root: string,\n relativePath: string,\n value: unknown,\n): Promise<void> {\n await writeFileDurableWithinRoot(root, relativePath, `${JSON.stringify(value, null, 2)}\\n`, {\n encoding: 'utf8',\n })\n}\n\nexport async function renameDurable(source: string, target: string): Promise<void> {\n const sourceDir = dirname(source)\n const targetDir = dirname(target)\n await withDirectoryHandle(sourceDir, async (sourceHandle, anchoredSourceDir) => {\n await withDirectoryHandle(targetDir, async (targetHandle, anchoredTargetDir) => {\n await rename(\n resolve(anchoredSourceDir, basename(source)),\n resolve(anchoredTargetDir, basename(target)),\n )\n await syncDirectoryHandle(sourceHandle)\n if (targetDir !== sourceDir) await syncDirectoryHandle(targetHandle)\n })\n })\n}\n\nexport async function removeDurable(path: string): Promise<void> {\n await withDirectoryHandle(dirname(path), async (handle, anchoredDirectory) => {\n await rm(resolve(anchoredDirectory, basename(path)), { force: true })\n await syncDirectoryHandle(handle)\n })\n}\n\nexport async function syncDirectory(path: string): Promise<void> {\n await withDirectoryHandle(path, syncDirectoryHandle)\n}\n\n/**\n * Keeps the target's parent directory open while the operation runs. On Linux,\n * `/proc/self/fd` anchors every lookup to that directory even if an ancestor is\n * renamed concurrently.\n */\nexport async function withSafeDescendant<T>(\n root: string,\n relativePath: string,\n use: (path: string) => Promise<T> | T,\n): Promise<T> {\n const normalized = normalizeRelativePath(relativePath)\n const parts = normalized.split('/')\n const filename = parts.pop()!\n const directory = await openSafeDirectoryTree(root, parts.join('/'), true)\n try {\n const target = resolve(anchoredDirectoryPath(directory.handle, directory.path), filename)\n await regularFileModeOrUndefined(target)\n return await use(target)\n } finally {\n await directory.handle.close()\n }\n}\n\nexport async function withSafeDirectory<T>(\n root: string,\n relativePath: string,\n create: boolean,\n use: (path: string) => Promise<T> | T,\n): Promise<T> {\n const directory = await openSafeDirectoryTree(root, relativePath, create)\n try {\n return await use(anchoredDirectoryPath(directory.handle, directory.path))\n } finally {\n await directory.handle.close()\n }\n}\n\nexport async function readRegularFileNoFollow(path: string): Promise<RegularFileSnapshot> {\n let handle: FileHandle | undefined\n try {\n handle = await open(path, READ_FILE_FLAGS)\n const entry = await handle.stat()\n if (!entry.isFile()) throw new Error(`knowledge path is not a regular file: ${path}`)\n return { bytes: await handle.readFile(), mode: entry.mode & 0o777 }\n } catch (error) {\n const code = (error as NodeJS.ErrnoException | null)?.code\n if (code === 'ELOOP' || code === 'ENOTDIR') {\n throw new Error(`knowledge path is not a regular file: ${path}`, { cause: error })\n }\n throw error\n } finally {\n await handle?.close().catch(() => undefined)\n }\n}\n\nexport async function readRegularFileWithinRoot(\n root: string,\n relativePath: string,\n): Promise<RegularFileSnapshot> {\n const normalized = normalizeRelativePath(relativePath)\n const parts = normalized.split('/')\n const filename = parts.pop()!\n const directory = await openSafeDirectoryTree(root, parts.join('/'), false)\n try {\n return await readRegularFileNoFollow(\n resolve(anchoredDirectoryPath(directory.handle, directory.path), filename),\n )\n } finally {\n await directory.handle.close()\n }\n}\n\nexport async function listRegularFilesWithinRoot(\n root: string,\n relativeDirectory: string,\n): Promise<Array<RegularFileSnapshot & { path: string }>> {\n const normalized = normalizeRelativePath(relativeDirectory)\n return withSafeDirectory(root, normalized, false, (directory) =>\n listRegularFilesFromOpenDirectory(directory, normalized),\n )\n}\n\nexport function isMissingFile(error: unknown): boolean {\n return (error as NodeJS.ErrnoException | null)?.code === 'ENOENT'\n}\n\nasync function withDirectoryHandle<T>(\n path: string,\n use: (handle: FileHandle, anchoredPath: string) => Promise<T> | T,\n): Promise<T> {\n const handle = await openDirectory(path)\n try {\n return await use(handle, anchoredDirectoryPath(handle, path))\n } finally {\n await handle.close()\n }\n}\n\nasync function listRegularFilesFromOpenDirectory(\n directory: string,\n relativeDirectory: string,\n): Promise<Array<RegularFileSnapshot & { path: string }>> {\n const out: Array<RegularFileSnapshot & { path: string }> = []\n for (const entry of await readdir(directory, { withFileTypes: true })) {\n const relativePath = `${relativeDirectory}/${entry.name}`\n if (entry.isDirectory()) {\n out.push(\n ...(await withSafeDirectory(directory, entry.name, false, (child) =>\n listRegularFilesFromOpenDirectory(child, relativePath),\n )),\n )\n } else if (entry.isFile()) {\n out.push({\n path: relativePath,\n ...(await readRegularFileNoFollow(resolve(directory, entry.name))),\n })\n } else {\n throw new Error(`knowledge tree contains an unsupported filesystem entry: ${relativePath}`)\n }\n }\n return out\n}\n\nasync function openSafeDirectoryTree(\n root: string,\n relativePath: string,\n create: boolean,\n): Promise<{ handle: FileHandle; path: string }> {\n if (create) await mkdir(root, { recursive: true })\n const resolvedRoot = isKernelAnchoredPath(root) ? root : await realpath(root)\n const normalized = relativePath === '' ? '' : normalizeRelativePath(relativePath)\n let currentPath = resolvedRoot\n let currentHandle = await openDirectory(resolvedRoot)\n try {\n for (const part of normalized.split('/').filter(Boolean)) {\n const anchoredParent = anchoredDirectoryPath(currentHandle, currentPath)\n const childPath = resolve(anchoredParent, part)\n let childHandle: FileHandle\n try {\n childHandle = await openDirectory(childPath)\n } catch (error) {\n if (!create || !isMissingFile(error)) throw unsafeDirectoryError(childPath, error)\n let created = false\n try {\n await mkdir(childPath)\n created = true\n } catch (mkdirError) {\n if ((mkdirError as NodeJS.ErrnoException | null)?.code !== 'EEXIST') throw mkdirError\n }\n childHandle = await openDirectory(childPath).catch((openError: unknown) => {\n throw unsafeDirectoryError(childPath, openError)\n })\n if (created) await syncDirectoryHandle(currentHandle)\n }\n await currentHandle.close()\n currentHandle = childHandle\n currentPath = resolve(currentPath, part)\n }\n return { handle: currentHandle, path: currentPath }\n } catch (error) {\n await currentHandle.close().catch(() => undefined)\n throw error\n }\n}\n\nasync function openDirectory(path: string): Promise<FileHandle> {\n const isKernelDescriptor = /^\\/proc\\/self\\/fd\\/\\d+$/.test(path)\n if (!isKernelDescriptor) {\n const entry = await lstat(path)\n if (entry.isSymbolicLink() || !entry.isDirectory()) {\n throw new Error(`knowledge path has an unsafe directory: ${path}`)\n }\n }\n const flags = isKernelDescriptor ? constants.O_RDONLY | constants.O_DIRECTORY : DIRECTORY_FLAGS\n const handle = await open(path, flags)\n const entry = await handle.stat()\n if (!entry.isDirectory()) {\n await handle.close()\n throw new Error(`knowledge path has an unsafe directory: ${path}`)\n }\n return handle\n}\n\nexport function isKernelAnchoredPath(path: string): boolean {\n return process.platform === 'linux' && /^\\/proc\\/self\\/fd\\/\\d+(?:\\/|$)/.test(path)\n}\n\nfunction anchoredDirectoryPath(handle: FileHandle, fallback: string): string {\n return process.platform === 'linux' ? `/proc/self/fd/${handle.fd}` : fallback\n}\n\nasync function regularFileModeOrUndefined(path: string): Promise<number | undefined> {\n try {\n const entry = await lstat(path)\n if (entry.isSymbolicLink() || !entry.isFile()) {\n throw new Error(`knowledge path is not a regular file: ${path}`)\n }\n return entry.mode & 0o777\n } catch (error) {\n if (isMissingFile(error)) return undefined\n throw error\n }\n}\n\nasync function syncDirectoryHandle(handle: FileHandle): Promise<void> {\n if (process.platform === 'win32') return\n await handle.sync()\n}\n\nfunction unsafeDirectoryError(path: string, cause: unknown): Error {\n const code = (cause as NodeJS.ErrnoException | null)?.code\n if (code === 'ELOOP' || code === 'ENOTDIR') {\n return new Error(`knowledge path has an unsafe directory: ${path}`, { cause })\n }\n return cause instanceof Error ? cause : new Error(`could not open knowledge directory: ${path}`)\n}\n\nfunction normalizeRelativePath(path: string): string {\n if (path.length === 0 || isAbsolute(path)) {\n throw new Error(`knowledge path must be a non-empty relative path: ${path}`)\n }\n const normalized = path.replace(/\\\\/g, '/')\n if (normalized.split('/').some((part) => part === '' || part === '.' || part === '..')) {\n throw new Error(`knowledge path contains an unsafe segment: ${path}`)\n }\n return normalized\n}\n","import { createHash, randomUUID } from 'node:crypto'\nimport { mkdtemp, readdir, rm } from 'node:fs/promises'\nimport { join, relative, resolve, sep } from 'node:path'\nimport { contentHash } from '@tangle-network/agent-eval'\nimport { z } from 'zod'\nimport {\n isKernelAnchoredPath,\n isMissingFile,\n readRegularFileNoFollow,\n removeDurable,\n renameDurable,\n syncDirectory,\n withSafeDescendant,\n withSafeDirectory,\n writeFileDurable,\n writeJsonDurable,\n} from './durable-fs'\n\nconst digestSchema = z.string().regex(/^[a-f0-9]{64}$/)\nconst fileModeSchema = z.number().int().min(0).max(0o777)\nconst DEFAULT_FILE_MODE = 0o644\nconst transactionEntrySchema = z\n .object({\n index: z.number().int().nonnegative(),\n path: z.string().min(1),\n beforeHash: digestSchema.nullable(),\n afterHash: digestSchema.nullable(),\n beforeMode: fileModeSchema.optional(),\n afterMode: fileModeSchema.optional(),\n })\n .strict()\nconst transactionSchema = z\n .object({\n kind: z.literal('knowledge-file-transaction'),\n transactionId: z.string().uuid(),\n purpose: z.string().min(1),\n recoveryOwner: z.string().min(1).max(256).optional(),\n createdAt: z.string().min(1),\n entries: z.array(transactionEntrySchema).min(1),\n })\n .strict()\nconst transactionDirectionSchema = z\n .object({\n transactionId: z.string().uuid(),\n direction: z.literal('rollback'),\n })\n .strict()\n\nexport type KnowledgeFileTransaction = z.infer<typeof transactionSchema>\n\nexport interface KnowledgeFileTransactionState {\n transaction: KnowledgeFileTransaction\n direction: 'apply' | 'rollback'\n}\n\nexport interface KnowledgeFileTransactionPlanEntry {\n path: string\n beforeHash: string | null\n afterHash: string | null\n beforeMode?: number\n afterMode?: number\n}\n\nexport function knowledgeFileTransactionPlanHash(\n entries: readonly KnowledgeFileTransactionPlanEntry[],\n): string {\n const normalized = entries\n .map((entry) => normalizePlanEntry(entry))\n .sort((left, right) => left.path.localeCompare(right.path))\n if (new Set(normalized.map((entry) => entry.path)).size !== normalized.length) {\n throw new Error('knowledge transaction plan repeats a path')\n }\n return contentHash(normalized)\n}\n\nexport interface KnowledgeFileMutation {\n path: string\n content: string | Buffer | null\n mode?: number\n}\n\nexport async function prepareKnowledgeFileTransaction(input: {\n root: string\n transactionRoot: string\n purpose: string\n recoveryOwner?: string\n mutations: readonly KnowledgeFileMutation[]\n includeUnchanged?: boolean\n now?: () => Date\n}): Promise<KnowledgeFileTransaction | null> {\n if (input.mutations.length === 0) throw new Error('knowledge file transaction has no mutations')\n return withTransactionRoot(input.root, input.transactionRoot, true, async (transactionRoot) => {\n const activeTransactions = await activeTransactionDirectoryNames(transactionRoot)\n if (activeTransactions.length > 0) {\n throw new Error(\n `knowledge file transaction is already active: ${activeTransactions.join(', ')}`,\n )\n }\n\n const paths = new Set<string>()\n const prepared = await Promise.all(\n input.mutations.map(async (mutation, index) => {\n const path = assertKnowledgeMutationPath(mutation.path)\n if (paths.has(path)) throw new Error(`knowledge file transaction repeats path: ${path}`)\n if (mutation.content === null && mutation.mode !== undefined) {\n throw new Error(`deleted knowledge file cannot declare a mode: ${path}`)\n }\n paths.add(path)\n const before = await withSafeDescendant(input.root, path, readRegularFile)\n const after =\n mutation.content === null\n ? null\n : Buffer.isBuffer(mutation.content)\n ? mutation.content\n : Buffer.from(mutation.content, 'utf8')\n const afterMode = after\n ? fileModeSchema.parse(mutation.mode ?? before?.mode ?? DEFAULT_FILE_MODE)\n : undefined\n if (\n !input.includeUnchanged &&\n sameBytes(before?.bytes ?? null, after) &&\n before?.mode === afterMode\n ) {\n return null\n }\n return {\n entry: {\n index,\n path,\n beforeHash: before ? hashBytes(before.bytes) : null,\n afterHash: after ? hashBytes(after) : null,\n ...(before ? { beforeMode: before.mode } : {}),\n ...(afterMode === undefined ? {} : { afterMode }),\n },\n before: before?.bytes ?? null,\n after,\n }\n }),\n )\n const changed = prepared.filter((entry): entry is NonNullable<typeof entry> => entry !== null)\n if (changed.length === 0) return null\n\n const preparationDir = await mkdtemp(join(transactionRoot, 'prepare-'))\n let activated = false\n try {\n for (const item of changed) {\n if (item.before) {\n await writeFileDurable(\n snapshotPath(preparationDir, 'before', item.entry.index),\n item.before,\n )\n }\n if (item.after) {\n await writeFileDurable(\n snapshotPath(preparationDir, 'after', item.entry.index),\n item.after,\n )\n }\n }\n const transaction = transactionSchema.parse({\n kind: 'knowledge-file-transaction',\n transactionId: randomUUID(),\n purpose: input.purpose,\n ...(input.recoveryOwner ? { recoveryOwner: input.recoveryOwner } : {}),\n createdAt: (input.now ?? (() => new Date()))().toISOString(),\n entries: changed.map((item) => item.entry),\n })\n await writeJsonDurable(join(preparationDir, 'transaction.json'), transaction)\n const activeDir = join(\n transactionRoot,\n activeTransactionDirectoryName(transaction.transactionId),\n )\n await renameDurable(preparationDir, activeDir)\n activated = true\n const competingTransactions = await activeTransactionDirectoryNames(transactionRoot)\n if (competingTransactions.length > 1) {\n await rm(activeDir, { recursive: true, force: true })\n await syncDirectory(transactionRoot)\n throw new Error('multiple knowledge file transactions became active concurrently')\n }\n return transaction\n } finally {\n if (!activated) await rm(preparationDir, { recursive: true, force: true })\n }\n })\n}\n\nexport async function commitKnowledgeFileMutations(input: {\n root: string\n transactionRoot: string\n purpose: string\n mutations: readonly KnowledgeFileMutation[]\n assertOwned?: () => void\n now?: () => Date\n}): Promise<boolean> {\n if (\n await loadKnowledgeFileTransaction({\n root: input.root,\n transactionRoot: input.transactionRoot,\n })\n ) {\n throw new Error('recover the pending knowledge transaction before planning another write')\n }\n const transaction = await prepareKnowledgeFileTransaction({\n root: input.root,\n transactionRoot: input.transactionRoot,\n purpose: input.purpose,\n mutations: input.mutations,\n now: input.now,\n })\n if (!transaction) return false\n input.assertOwned?.()\n await applyKnowledgeFileTransaction({\n root: input.root,\n transactionRoot: input.transactionRoot,\n transaction,\n beforeCommit: input.assertOwned,\n })\n await finishKnowledgeFileTransaction({\n root: input.root,\n transactionRoot: input.transactionRoot,\n transaction,\n assertOwned: input.assertOwned,\n })\n return true\n}\n\nexport async function recoverKnowledgeFileTransaction(input: {\n root: string\n transactionRoot: string\n expectedPurpose: string\n direction?: 'apply' | 'rollback'\n finish?: boolean\n validate?: (transaction: KnowledgeFileTransaction) => void\n assertOwned?: () => void\n}): Promise<boolean> {\n const pending = await inspectKnowledgeFileTransaction({\n root: input.root,\n transactionRoot: input.transactionRoot,\n })\n if (!pending) return false\n const { transaction, direction } = pending\n if (transaction.purpose !== input.expectedPurpose) {\n throw new Error(`knowledge transaction '${transaction.purpose}' requires its owner to resume`)\n }\n input.validate?.(transaction)\n input.assertOwned?.()\n if (input.direction === 'apply' && direction === 'rollback') {\n throw new Error(`knowledge transaction '${transaction.transactionId}' is already rolling back`)\n }\n const requestedDirection = input.direction ?? direction\n if (requestedDirection === 'rollback') {\n await rollbackKnowledgeFileTransaction({\n root: input.root,\n transactionRoot: input.transactionRoot,\n transaction,\n beforeCommit: input.assertOwned,\n })\n } else {\n await applyKnowledgeFileTransaction({\n root: input.root,\n transactionRoot: input.transactionRoot,\n transaction,\n beforeCommit: input.assertOwned,\n })\n }\n if (input.finish !== false) {\n await finishKnowledgeFileTransaction({\n root: input.root,\n transactionRoot: input.transactionRoot,\n transaction,\n assertOwned: input.assertOwned,\n })\n }\n return true\n}\n\nexport async function loadKnowledgeFileTransaction(input: {\n root: string\n transactionRoot: string\n}): Promise<KnowledgeFileTransaction | null> {\n return (await inspectKnowledgeFileTransaction(input))?.transaction ?? null\n}\n\nexport async function inspectKnowledgeFileTransaction(input: {\n root: string\n transactionRoot: string\n}): Promise<KnowledgeFileTransactionState | null> {\n return loadKnowledgeFileTransactionState(input)\n}\n\nexport async function applyKnowledgeFileTransaction(input: {\n root: string\n transactionRoot: string\n transaction: KnowledgeFileTransaction\n beforeCommit?: (entry: KnowledgeFileTransaction['entries'][number]) => Promise<void> | void\n}): Promise<void> {\n const transaction = transactionSchema.parse(input.transaction)\n assertTransactionEntries(transaction)\n await withTransactionDirectory(\n input.root,\n input.transactionRoot,\n transaction,\n async (transactionDir) => {\n await assertActiveTransaction(transactionDir, transaction)\n if ((await readTransactionDirection(transactionDir, transaction)) === 'rollback') {\n throw new Error(`knowledge transaction '${transaction.transactionId}' is rolling back`)\n }\n for (const entry of transaction.entries) {\n await withSafeDescendant(input.root, entry.path, async (target) => {\n const current = await readRegularFile(target)\n if (fileMatches(current, entry.afterHash, entry.afterMode)) return\n if (!fileMatches(current, entry.beforeHash, entry.beforeMode)) {\n throw new Error(`knowledge file changed outside transaction: ${entry.path}`)\n }\n await input.beforeCommit?.(entry)\n if (entry.afterHash === null) {\n await removeDurable(target)\n return\n }\n const after = (\n await readRegularFileNoFollow(snapshotPath(transactionDir, 'after', entry.index))\n ).bytes\n if (hashBytes(after) !== entry.afterHash) {\n throw new Error(`knowledge transaction snapshot changed: ${entry.path}`)\n }\n await writeFileDurable(target, after, { mode: entry.afterMode! })\n })\n }\n await assertKnowledgeFileTransactionApplied(input.root, transaction)\n },\n )\n}\n\nasync function assertKnowledgeFileTransactionApplied(\n root: string,\n transaction: KnowledgeFileTransaction,\n): Promise<void> {\n for (const entry of transaction.entries) {\n await withSafeDescendant(root, entry.path, async (target) => {\n const current = await readRegularFile(target)\n if (!fileMatches(current, entry.afterHash, entry.afterMode)) {\n throw new Error(`knowledge file transaction did not commit: ${entry.path}`)\n }\n })\n }\n}\n\nexport async function finishKnowledgeFileTransaction(input: {\n root: string\n transactionRoot: string\n transaction: KnowledgeFileTransaction\n assertOwned?: () => void\n}): Promise<void> {\n const transaction = transactionSchema.parse(input.transaction)\n assertTransactionEntries(transaction)\n await withTransactionRoot(input.root, input.transactionRoot, false, async (transactionRoot) => {\n const activeName = activeTransactionDirectoryName(transaction.transactionId)\n await withTransactionDirectory(\n input.root,\n input.transactionRoot,\n transaction,\n async (transactionDir) => {\n await assertActiveTransaction(transactionDir, transaction)\n input.assertOwned?.()\n const direction = await readTransactionDirection(transactionDir, transaction)\n await assertKnowledgeFileTransactionTerminal(input.root, transaction, direction)\n await withSafeDirectory(transactionRoot, activeName, false, async (currentDir) => {\n await assertActiveTransaction(currentDir, transaction)\n const currentDirection = await readTransactionDirection(currentDir, transaction)\n if (currentDirection !== direction) {\n throw new Error(\n `knowledge transaction '${transaction.transactionId}' changed direction`,\n )\n }\n await assertKnowledgeFileTransactionTerminal(input.root, transaction, currentDirection)\n })\n },\n )\n await rm(join(transactionRoot, activeName), { recursive: true, force: false })\n await syncDirectory(transactionRoot)\n })\n}\n\nexport async function rollbackKnowledgeFileTransaction(input: {\n root: string\n transactionRoot: string\n transaction: KnowledgeFileTransaction\n beforeCommit?: (entry: KnowledgeFileTransaction['entries'][number]) => Promise<void> | void\n}): Promise<void> {\n await withTransactionDirectory(\n input.root,\n input.transactionRoot,\n input.transaction,\n async (transactionDir) => {\n const transaction = transactionSchema.parse(input.transaction)\n assertTransactionEntries(transaction)\n await assertActiveTransaction(transactionDir, transaction)\n await input.beforeCommit?.(transaction.entries.at(-1)!)\n const direction = await readTransactionDirection(transactionDir, transaction)\n if (direction !== 'rollback') {\n await writeJsonDurable(join(transactionDir, 'direction.json'), {\n transactionId: transaction.transactionId,\n direction: 'rollback',\n })\n }\n for (const entry of [...transaction.entries].reverse()) {\n await withSafeDescendant(input.root, entry.path, async (target) => {\n const current = await readRegularFile(target)\n if (fileMatches(current, entry.beforeHash, entry.beforeMode)) return\n if (!fileMatches(current, entry.afterHash, entry.afterMode)) {\n throw new Error(`knowledge file changed outside rollback: ${entry.path}`)\n }\n await input.beforeCommit?.(entry)\n if (entry.beforeHash === null) {\n await removeDurable(target)\n return\n }\n const before = (\n await readRegularFileNoFollow(snapshotPath(transactionDir, 'before', entry.index))\n ).bytes\n if (hashBytes(before) !== entry.beforeHash) {\n throw new Error(`knowledge rollback snapshot changed: ${entry.path}`)\n }\n await writeFileDurable(target, before, { mode: entry.beforeMode! })\n })\n }\n await input.beforeCommit?.(transaction.entries[0]!)\n for (const entry of transaction.entries) {\n await withSafeDescendant(input.root, entry.path, async (target) => {\n const current = await readRegularFile(target)\n if (!fileMatches(current, entry.beforeHash, entry.beforeMode)) {\n throw new Error(`knowledge file transaction did not roll back: ${entry.path}`)\n }\n })\n }\n },\n )\n}\n\nasync function loadKnowledgeFileTransactionState(input: {\n root: string\n transactionRoot: string\n}): Promise<KnowledgeFileTransactionState | null> {\n try {\n return await withTransactionRoot(input.root, input.transactionRoot, false, async (root) => {\n const activeTransactions = await activeTransactionDirectoryNames(root)\n if (activeTransactions.length === 0) return null\n if (activeTransactions.length > 1) {\n throw new Error('multiple knowledge file transactions are active')\n }\n return withSafeDirectory(root, activeTransactions[0]!, false, async (transactionDir) => {\n const transaction = await readActiveTransaction(transactionDir)\n return {\n transaction,\n direction: await readTransactionDirection(transactionDir, transaction),\n }\n })\n })\n } catch (error) {\n if (isMissingFile(error)) return null\n throw error\n }\n}\n\nasync function readActiveTransaction(transactionDir: string): Promise<KnowledgeFileTransaction> {\n const transaction = transactionSchema.parse(\n JSON.parse(\n (await readRegularFileNoFollow(join(transactionDir, 'transaction.json'))).bytes.toString(\n 'utf8',\n ),\n ),\n )\n assertTransactionEntries(transaction)\n return transaction\n}\n\nasync function assertActiveTransaction(\n transactionDir: string,\n expected: KnowledgeFileTransaction,\n): Promise<void> {\n const active = await readActiveTransaction(transactionDir)\n if (\n active.transactionId !== expected.transactionId ||\n contentHash(active) !== contentHash(transactionSchema.parse(expected))\n ) {\n throw new Error(`active knowledge transaction does not match '${expected.transactionId}'`)\n }\n}\n\nasync function readTransactionDirection(\n transactionDir: string,\n transaction: KnowledgeFileTransaction,\n): Promise<'apply' | 'rollback'> {\n try {\n const direction = transactionDirectionSchema.parse(\n JSON.parse(\n (await readRegularFileNoFollow(join(transactionDir, 'direction.json'))).bytes.toString(\n 'utf8',\n ),\n ),\n )\n if (direction.transactionId !== transaction.transactionId) {\n throw new Error('knowledge transaction direction belongs to another transaction')\n }\n return direction.direction\n } catch (error) {\n if (isMissingFile(error)) return 'apply'\n throw error\n }\n}\n\nfunction snapshotPath(root: string, side: 'before' | 'after', index: number): string {\n return join(root, side, `${index}.bin`)\n}\n\nasync function withTransactionDirectory<T>(\n root: string,\n transactionRoot: string,\n transaction: KnowledgeFileTransaction,\n use: (transactionDir: string) => Promise<T> | T,\n): Promise<T> {\n const parsed = transactionSchema.parse(transaction)\n try {\n return await withTransactionRoot(root, transactionRoot, false, (safeRoot) =>\n withSafeDirectory(safeRoot, activeTransactionDirectoryName(parsed.transactionId), false, use),\n )\n } catch (error) {\n if (isMissingFile(error)) {\n throw new Error(`active knowledge transaction does not match '${parsed.transactionId}'`, {\n cause: error,\n })\n }\n throw error\n }\n}\n\nasync function activeTransactionDirectoryNames(transactionRoot: string): Promise<string[]> {\n const active: string[] = []\n for (const entry of await readdir(transactionRoot, { withFileTypes: true })) {\n if (entry.name === 'active') {\n throw new Error('knowledge transaction store contains an unsupported active journal')\n }\n if (!entry.name.startsWith('active-')) continue\n if (!entry.isDirectory()) {\n throw new Error(`knowledge transaction journal is not a directory: ${entry.name}`)\n }\n activeTransactionDirectoryName(entry.name.slice('active-'.length))\n active.push(entry.name)\n }\n return active.sort()\n}\n\nfunction activeTransactionDirectoryName(transactionId: string): string {\n return `active-${z.string().uuid().parse(transactionId)}`\n}\n\nasync function assertKnowledgeFileTransactionTerminal(\n root: string,\n transaction: KnowledgeFileTransaction,\n direction: 'apply' | 'rollback',\n): Promise<void> {\n if (direction === 'apply') {\n await assertKnowledgeFileTransactionApplied(root, transaction)\n return\n }\n for (const entry of transaction.entries) {\n await withSafeDescendant(root, entry.path, async (target) => {\n const current = await readRegularFile(target)\n if (!fileMatches(current, entry.beforeHash, entry.beforeMode)) {\n throw new Error(`knowledge file transaction did not roll back: ${entry.path}`)\n }\n })\n }\n}\n\nasync function withTransactionRoot<T>(\n root: string,\n transactionRoot: string,\n create: boolean,\n use: (transactionRoot: string) => Promise<T> | T,\n): Promise<T> {\n if (isKernelAnchoredPath(transactionRoot)) {\n const match = transactionRoot.match(/^(\\/proc\\/self\\/fd\\/\\d+)(?:\\/(.*))?$/)\n if (!match?.[1]) throw new Error('knowledge transaction directory has an invalid anchor')\n return withSafeDirectory(match[1], match[2] ?? '', create, use)\n }\n const resolvedRoot = resolve(root)\n const resolvedTransactionRoot = resolve(transactionRoot)\n if (!resolvedTransactionRoot.startsWith(`${resolvedRoot}${sep}`)) {\n throw new Error('knowledge transaction directory escaped its root')\n }\n return withSafeDirectory(\n root,\n relative(resolvedRoot, resolvedTransactionRoot).replace(/\\\\/g, '/'),\n create,\n use,\n )\n}\n\nfunction assertTransactionEntries(transaction: KnowledgeFileTransaction): void {\n const indexes = new Set<number>()\n const paths = new Set<string>()\n for (const entry of transaction.entries) {\n const normalized = assertKnowledgeMutationPath(entry.path)\n if (entry.path !== normalized || indexes.has(entry.index) || paths.has(entry.path)) {\n throw new Error('knowledge file transaction has duplicate or unsafe entries')\n }\n assertHashModePair(entry.path, 'before', entry.beforeHash, entry.beforeMode)\n assertHashModePair(entry.path, 'after', entry.afterHash, entry.afterMode)\n indexes.add(entry.index)\n paths.add(entry.path)\n }\n}\n\nfunction normalizePlanEntry(entry: KnowledgeFileTransactionPlanEntry) {\n const path = assertKnowledgeMutationPath(entry.path)\n assertHashModePair(path, 'before', entry.beforeHash, entry.beforeMode)\n assertHashModePair(path, 'after', entry.afterHash, entry.afterMode)\n return {\n path,\n beforeHash: entry.beforeHash,\n afterHash: entry.afterHash,\n ...(entry.beforeMode === undefined\n ? {}\n : { beforeMode: fileModeSchema.parse(entry.beforeMode) }),\n ...(entry.afterMode === undefined ? {} : { afterMode: fileModeSchema.parse(entry.afterMode) }),\n }\n}\n\nfunction assertHashModePair(\n path: string,\n side: 'before' | 'after',\n hash: string | null,\n mode: number | undefined,\n): void {\n if ((hash === null) !== (mode === undefined)) {\n throw new Error(`knowledge transaction ${side} hash and mode disagree: ${path}`)\n }\n if (mode !== undefined) fileModeSchema.parse(mode)\n}\n\nexport function assertKnowledgeMutationPath(path: string): string {\n const normalized = normalizeTransactionPath(path)\n if (\n normalized === '.agent-knowledge/sources.json' ||\n normalized.startsWith('knowledge/') ||\n normalized.startsWith('raw/')\n ) {\n return normalized\n }\n throw new Error(`knowledge transaction contains an unsupported path: ${path}`)\n}\n\nfunction normalizeTransactionPath(path: string): string {\n const normalized = path.replace(/\\\\/g, '/')\n if (\n normalized.length === 0 ||\n normalized.startsWith('/') ||\n /^[A-Za-z]:/.test(normalized) ||\n normalized.split('/').some((part) => part === '' || part === '.' || part === '..')\n ) {\n throw new Error(`knowledge file transaction has an unsafe path: ${path}`)\n }\n return normalized\n}\n\nasync function readRegularFile(path: string): Promise<{ bytes: Buffer; mode: number } | null> {\n try {\n return await readRegularFileNoFollow(path)\n } catch (error) {\n if (isMissingFile(error)) return null\n throw error\n }\n}\n\nfunction hashBytes(bytes: Buffer): string {\n return createHash('sha256').update(bytes).digest('hex')\n}\n\nfunction sameBytes(left: Buffer | null, right: Buffer | null): boolean {\n if (left === null || right === null) return left === right\n return left.equals(right)\n}\n\nfunction fileMatches(\n file: { bytes: Buffer; mode: number } | null,\n hash: string | null,\n mode: number | undefined,\n): boolean {\n return (file ? hashBytes(file.bytes) : null) === hash && file?.mode === mode\n}\n","import { AsyncLocalStorage } from 'node:async_hooks'\nimport { mkdir, readFile } from 'node:fs/promises'\nimport { dirname, join, resolve } from 'node:path'\nimport type { LockOptions } from 'proper-lockfile'\nimport {\n isMissingFile,\n withSafeDescendant,\n withSafeDirectory,\n writeJsonDurableWithinRoot,\n} from './durable-fs'\nimport {\n inspectKnowledgeFileTransaction,\n type KnowledgeFileTransaction,\n loadKnowledgeFileTransaction,\n recoverKnowledgeFileTransaction,\n} from './file-transaction'\n\nconst DEFAULT_STALE_MS = 15 * 60 * 1000\nconst DEFAULT_READ_RETRIES = 100\nconst DEFAULT_READ_WAIT_MS = 25\n\n// `proper-lockfile` pulls in `graceful-fs`, which patches Node's `fs` at MODULE\n// scope (`fs.close = ...`, `fs.closeSync = ...`). workerd exposes those as\n// getter-only accessors, so a STATIC import makes the assignment throw while\n// Cloudflare runs startup validation on upload — `Cannot set property close of\n// #<Object> which has only a getter [code: 10021]` — rejecting the whole Worker\n// before any request frame exists, uncatchably, even for bundles that never\n// take a lock. Loading it on first use keeps this module importable at the\n// edge. Every consumer below is already async, so nothing else changes.\nlet lockfileModule: Promise<typeof import('proper-lockfile')> | undefined\n\nfunction loadLockfile(): Promise<typeof import('proper-lockfile')> {\n lockfileModule ??= import('proper-lockfile')\n return lockfileModule\n}\n\ninterface KnowledgeMutationScope {\n active: boolean\n lock: KnowledgeMutationLock\n}\n\nconst activeRoots = new AsyncLocalStorage<ReadonlyMap<string, KnowledgeMutationScope>>()\nconst activeReadRoots = new AsyncLocalStorage<ReadonlySet<string>>()\n\nexport interface KnowledgeMutationLock {\n readonly transactionRoot: string\n readonly recovery?: KnowledgeMutationRecovery\n assertOwned(): void\n}\n\ninterface KnowledgeMutationRecovery {\n transactionId: string\n purpose: string\n direction: 'apply' | 'rollback'\n transaction: KnowledgeFileTransaction\n}\n\nexport class KnowledgeLockLostError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options)\n this.name = 'KnowledgeLockLostError'\n }\n}\n\ninterface DurableFileLock {\n assertOwned(): void\n release(): Promise<void>\n}\n\nexport interface KnowledgeMutationOptions {\n staleMs?: number\n resumeTransaction?: {\n purpose: string\n recoveryOwner?: string\n validate?: (transaction: KnowledgeFileTransaction) => void\n direction?: 'apply' | 'rollback'\n deferFinish?: boolean\n }\n retries?: LockOptions['retries']\n}\n\nexport interface PendingKnowledgeMutation {\n transactionId: string\n purpose: string\n recoveryOwner?: string\n createdAt: string\n direction: 'apply' | 'rollback'\n paths: string[]\n}\n\nexport interface RecoverPendingKnowledgeMutationOptions {\n transactionId: string\n action: 'apply' | 'rollback'\n}\n\nexport interface KnowledgeReadOptions {\n staleMs?: number\n retries?: number\n waitMs?: number\n}\n\nexport async function withKnowledgeMutation<T>(\n root: string,\n mutate: (lock: KnowledgeMutationLock) => Promise<T> | T,\n options: KnowledgeMutationOptions = {},\n): Promise<T> {\n const resolvedRoot = resolve(root)\n const active = activeRoots.getStore()\n const existing = active?.get(resolvedRoot)\n if (existing?.active) {\n existing.lock.assertOwned()\n const result = await mutate(existing.lock)\n existing.lock.assertOwned()\n return result\n }\n\n return withSafeDirectory(resolvedRoot, '.agent-knowledge', true, async (cacheDir) => {\n const acquired = await acquireDurableFileLock(resolvedRoot, {\n lockfilePath: join(cacheDir, 'mutation.lock.durable'),\n staleMs: options.staleMs,\n retries:\n options.retries ??\n ({ retries: 100, factor: 1.1, minTimeout: 10, maxTimeout: 200, randomize: true } as const),\n })\n let recovery: KnowledgeMutationRecovery | undefined\n const mutationLock: KnowledgeMutationLock = {\n transactionRoot: join(cacheDir, 'file-transactions'),\n get recovery() {\n return recovery\n },\n assertOwned: acquired.assertOwned,\n }\n const scope: KnowledgeMutationScope = { active: true, lock: mutationLock }\n try {\n const pendingState = await inspectKnowledgeFileTransaction({\n root: resolvedRoot,\n transactionRoot: mutationLock.transactionRoot,\n })\n const pending = pendingState?.transaction ?? null\n const resume = pending\n ? assertKnowledgeTransactionResume(pending, options.resumeTransaction)\n : undefined\n const locks = new Map(active)\n locks.set(resolvedRoot, scope)\n return await activeRoots.run(locks, async () => {\n const epoch = await beginMutationEpoch(cacheDir)\n const finishEpoch = async (completed: boolean) => {\n mutationLock.assertOwned()\n const stillPending = await loadKnowledgeFileTransaction({\n root: resolvedRoot,\n transactionRoot: mutationLock.transactionRoot,\n })\n if (completed && stillPending) {\n throw new Error('knowledge mutation returned with an unfinished transaction')\n }\n if (!stillPending) await finishMutationEpoch(cacheDir, epoch)\n }\n try {\n if (pending) {\n if (!resume)\n throw new Error(\n `knowledge transaction '${pending.purpose}' requires its owner to resume`,\n )\n await recoverKnowledgeFileTransaction({\n root: resolvedRoot,\n transactionRoot: mutationLock.transactionRoot,\n expectedPurpose: resume.purpose,\n direction: resume.direction,\n finish: resume.deferFinish !== true,\n validate: resume.validate,\n assertOwned: acquired.assertOwned,\n })\n recovery = Object.freeze({\n transactionId: pending.transactionId,\n purpose: pending.purpose,\n direction: resume.direction ?? pendingState?.direction ?? 'apply',\n transaction: pending,\n })\n }\n mutationLock.assertOwned()\n const result = await mutate(mutationLock)\n mutationLock.assertOwned()\n await finishEpoch(true)\n return result\n } catch (error) {\n try {\n await finishEpoch(false)\n } catch (finishError) {\n throw new AggregateError(\n [error, finishError],\n 'knowledge mutation failed and its durable state could not be inspected',\n )\n }\n throw error\n }\n })\n } finally {\n scope.active = false\n await acquired.release()\n }\n })\n}\n\nexport async function inspectPendingKnowledgeMutation(\n root: string,\n): Promise<PendingKnowledgeMutation | null> {\n const resolvedRoot = resolve(root)\n const pending = await inspectKnowledgeFileTransaction({\n root: resolvedRoot,\n transactionRoot: join(resolvedRoot, '.agent-knowledge', 'file-transactions'),\n })\n if (!pending) return null\n const { transaction, direction } = pending\n return {\n transactionId: transaction.transactionId,\n purpose: transaction.purpose,\n ...(transaction.recoveryOwner ? { recoveryOwner: transaction.recoveryOwner } : {}),\n createdAt: transaction.createdAt,\n direction,\n paths: transaction.entries.map((entry) => entry.path),\n }\n}\n\nfunction assertKnowledgeTransactionResume(\n pending: KnowledgeFileTransaction,\n resume: KnowledgeMutationOptions['resumeTransaction'],\n): NonNullable<KnowledgeMutationOptions['resumeTransaction']> {\n if (!resume || pending.purpose !== resume.purpose) {\n throw new Error(`knowledge transaction '${pending.purpose}' requires its owner to resume`)\n }\n if (pending.recoveryOwner !== resume.recoveryOwner) {\n if (pending.recoveryOwner) {\n throw new Error(\n `knowledge transaction '${pending.purpose}' must be resumed by '${pending.recoveryOwner}'`,\n )\n }\n throw new Error(`knowledge transaction '${pending.purpose}' has no recovery owner`)\n }\n return resume\n}\n\nexport async function recoverPendingKnowledgeMutation(\n root: string,\n options: RecoverPendingKnowledgeMutationOptions,\n): Promise<void> {\n const pending = await inspectPendingKnowledgeMutation(root)\n if (!pending) throw new Error('knowledge base has no pending mutation')\n\n let matched = false\n await withKnowledgeMutation(\n root,\n () => {\n if (!matched) throw new Error('pending knowledge mutation changed before recovery')\n },\n {\n resumeTransaction: {\n purpose: pending.purpose,\n direction: options.action,\n validate(transaction) {\n if (transaction.transactionId !== options.transactionId) {\n throw new Error(`pending knowledge mutation does not match '${options.transactionId}'`)\n }\n matched = true\n },\n },\n },\n )\n}\n\nexport async function withKnowledgeRead<T>(\n root: string,\n read: () => Promise<T> | T,\n options: KnowledgeReadOptions = {},\n): Promise<T> {\n const resolvedRoot = resolve(root)\n if (activeRoots.getStore()?.get(resolvedRoot)?.active) return await read()\n if (activeReadRoots.getStore()?.has(resolvedRoot)) return await read()\n\n const readRoots = new Set(activeReadRoots.getStore())\n readRoots.add(resolvedRoot)\n return activeReadRoots.run(readRoots, async () => {\n const retries = options.retries ?? DEFAULT_READ_RETRIES\n for (let attempt = 0; attempt <= retries; attempt += 1) {\n const before = await readMutationEpoch(resolvedRoot)\n if (isOdd(before)) {\n await waitForActiveMutationEpoch(resolvedRoot, before, options)\n continue\n }\n\n const result = await read()\n const after = await readMutationEpoch(resolvedRoot)\n if (before === after && !isOdd(after)) return result\n if (isOdd(after)) await waitForActiveMutationEpoch(resolvedRoot, after, options)\n }\n throw new Error('knowledge read could not observe a stable mutation epoch')\n })\n}\n\nexport async function acquireDurableFileLock(\n target: string,\n options: { lockfilePath: string; staleMs?: number; retries?: LockOptions['retries'] },\n): Promise<DurableFileLock> {\n const stale = Math.max(5_000, options.staleMs ?? DEFAULT_STALE_MS)\n const update = Math.max(1_000, Math.floor(stale / 3))\n let compromised: Error | undefined\n let released = false\n const { lock } = await loadLockfile()\n await mkdir(dirname(options.lockfilePath), { recursive: true })\n const release = await lock(target, {\n lockfilePath: options.lockfilePath,\n realpath: false,\n stale,\n update,\n retries: options.retries,\n onCompromised(error) {\n compromised = error\n },\n })\n\n return {\n assertOwned() {\n if (released) throw new KnowledgeLockLostError('knowledge filesystem lock is no longer owned')\n if (compromised)\n throw new KnowledgeLockLostError('knowledge filesystem lock was compromised', {\n cause: compromised,\n })\n },\n async release() {\n if (released) return\n released = true\n let releaseError: unknown\n try {\n await release()\n } catch (error) {\n releaseError = error\n }\n if (releaseError && compromised) {\n throw new AggregateError(\n [releaseError, compromised],\n 'knowledge filesystem lock was compromised and could not be released',\n )\n }\n if (releaseError) throw releaseError\n if (compromised) {\n throw new KnowledgeLockLostError('knowledge filesystem lock was compromised', {\n cause: compromised,\n })\n }\n },\n }\n}\n\nasync function beginMutationEpoch(cacheDir: string): Promise<number> {\n const current = await readMutationEpochFromCache(cacheDir)\n const odd = isOdd(current) ? current : current + 1\n await writeMutationEpoch(cacheDir, odd)\n return odd\n}\n\nasync function finishMutationEpoch(cacheDir: string, odd: number): Promise<void> {\n await writeMutationEpoch(cacheDir, isOdd(odd) ? odd + 1 : odd)\n}\n\nasync function readMutationEpoch(root: string): Promise<number> {\n try {\n return await withSafeDirectory(root, '.agent-knowledge', false, readMutationEpochFromCache)\n } catch (error) {\n if (isMissingFile(error)) return 0\n throw error\n }\n}\n\nasync function readMutationEpochFromCache(cacheDir: string): Promise<number> {\n try {\n const text = await withSafeDescendant(cacheDir, 'mutation-epoch.json', (path) =>\n readFile(path, 'utf8'),\n )\n const parsed = JSON.parse(text) as { epoch?: unknown }\n const epoch = parsed.epoch\n if (typeof epoch !== 'number' || !Number.isSafeInteger(epoch) || epoch < 0) {\n throw new Error('knowledge mutation epoch is invalid')\n }\n return epoch\n } catch (error) {\n if (isMissingFile(error)) return 0\n throw error\n }\n}\n\nasync function writeMutationEpoch(cacheDir: string, epoch: number): Promise<void> {\n await writeJsonDurableWithinRoot(cacheDir, 'mutation-epoch.json', {\n epoch,\n updatedAt: new Date().toISOString(),\n })\n}\n\nasync function waitForActiveMutationEpoch(\n root: string,\n epoch: number,\n options: KnowledgeReadOptions,\n): Promise<void> {\n if (!(await hasActiveMutationLock(root, options)))\n await healAbandonedMutationEpoch(root, epoch, options)\n await new Promise((resolve) => setTimeout(resolve, options.waitMs ?? DEFAULT_READ_WAIT_MS))\n}\n\nasync function healAbandonedMutationEpoch(\n root: string,\n expectedEpoch: number,\n options: KnowledgeReadOptions,\n): Promise<void> {\n await withSafeDirectory(root, '.agent-knowledge', false, async (cacheDir) => {\n let acquired: DurableFileLock\n try {\n acquired = await acquireDurableFileLock(root, {\n lockfilePath: join(cacheDir, 'mutation.lock.durable'),\n staleMs: options.staleMs,\n retries: 0,\n })\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ELOCKED') return\n throw error\n }\n try {\n const currentEpoch = await readMutationEpochFromCache(cacheDir)\n if (currentEpoch !== expectedEpoch || !isOdd(currentEpoch)) return\n const pending = await inspectKnowledgeFileTransaction({\n root,\n transactionRoot: join(cacheDir, 'file-transactions'),\n })\n if (pending) {\n throw new Error(\n `knowledge transaction '${pending.transaction.purpose}' requires its owner to resume`,\n )\n }\n await finishMutationEpoch(cacheDir, currentEpoch)\n } finally {\n await acquired.release()\n }\n })\n}\n\nasync function hasActiveMutationLock(\n root: string,\n options: Pick<KnowledgeReadOptions, 'staleMs'>,\n): Promise<boolean> {\n try {\n const { check } = await loadLockfile()\n return await withSafeDirectory(root, '.agent-knowledge', false, (cacheDir) =>\n check(root, {\n lockfilePath: join(cacheDir, 'mutation.lock.durable'),\n realpath: false,\n stale: Math.max(5_000, options.staleMs ?? DEFAULT_STALE_MS),\n }),\n )\n } catch (error) {\n if (isMissingFile(error)) return false\n throw error\n }\n}\n\nfunction isOdd(value: number): boolean {\n return value % 2 === 1\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 { join } from 'node:path'\nimport {\n isMissingFile,\n listRegularFilesWithinRoot,\n readRegularFileWithinRoot,\n withSafeDirectory,\n writeFileDurableWithinRoot,\n writeJsonDurable,\n} from './durable-fs'\nimport { parseFrontmatter } from './frontmatter'\nimport { slugify } from './ids'\nimport { withKnowledgeMutation, withKnowledgeRead } from './mutation-lock'\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 if (await knowledgeBaseInitialized(layout)) return layout\n return withKnowledgeMutation(root, () => initKnowledgeBaseUnlocked(root))\n}\n\nasync function initKnowledgeBaseUnlocked(root: string): Promise<KnowledgeLayout> {\n const layout = layoutFor(root)\n await withSafeDirectory(root, 'knowledge', true, () => undefined)\n await withSafeDirectory(root, 'raw/sources', true, () => undefined)\n await withSafeDirectory(root, '.agent-knowledge', true, () => undefined)\n await writeIfMissing(root, 'knowledge/index.md', '# Knowledge Index\\n\\n')\n await writeIfMissing(root, 'knowledge/log.md', '# Knowledge Log\\n\\n')\n await writeIfMissing(\n root,\n '.agent-knowledge/sources.json',\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 return withKnowledgeRead(root, () => loadKnowledgePagesUnlocked(root))\n}\n\nasync function loadKnowledgePagesUnlocked(root: string): Promise<KnowledgePage[]> {\n let files: Awaited<ReturnType<typeof listRegularFilesWithinRoot>>\n try {\n files = await listRegularFilesWithinRoot(root, 'knowledge')\n } catch (error) {\n if (isMissingFile(error)) return []\n throw error\n }\n const pages: KnowledgePage[] = []\n for (const file of files) {\n const rel = file.path\n if (!rel.endsWith('.md')) continue\n if (isScaffoldPath(rel)) continue\n const content = file.bytes.toString('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 writeJsonDurable(path, value)\n}\n\nasync function writeIfMissing(root: string, relativePath: string, content: string): Promise<void> {\n try {\n await readRegularFileWithinRoot(root, relativePath)\n } catch (error) {\n if (!isMissingFile(error)) throw error\n await writeFileDurableWithinRoot(root, relativePath, content, { encoding: 'utf8' })\n }\n}\n\nasync function knowledgeBaseInitialized(layout: KnowledgeLayout): Promise<boolean> {\n try {\n await withSafeDirectory(layout.root, 'knowledge', false, () => undefined)\n await withSafeDirectory(layout.root, 'raw/sources', false, () => undefined)\n await withSafeDirectory(layout.root, '.agent-knowledge', false, () => undefined)\n await readRegularFileWithinRoot(layout.root, 'knowledge/index.md')\n await readRegularFileWithinRoot(layout.root, 'knowledge/log.md')\n await readRegularFileWithinRoot(layout.root, '.agent-knowledge/sources.json')\n return true\n } catch (error) {\n if (isMissingFile(error)) return false\n throw error\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 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","/**\n * The algebra of a research claim ledger: claim identity, and how two ledgers\n * that accumulated evidence for the same goal combine into one.\n *\n * This lives apart from `research-driving-driver.ts` because it is no longer\n * that driver's private business. A ledger is a durable record now, and a\n * durable record addressed by id is a record two writers can reach: two rounds\n * of one run resuming from disk, or two workers researching one goal in\n * parallel. `putClaimLedger` writes the whole record, so the second writer's\n * write erases the first writer's claims — the ledger persists and the\n * knowledge still does not compound. Combining is therefore part of what the\n * record MEANS, and it belongs next to the record rather than inside one\n * consumer of it.\n *\n * Every combination here is monotone: support only grows, contradiction edges\n * only accumulate, `contested` only latches on, `firstSeenRound` only moves\n * earlier. That is what makes it safe to apply twice — a retried write cannot\n * produce a different ledger than a single write did.\n */\n\nimport { sha256, textSourceId } from './ids'\nimport type {\n DeepQuestion,\n ResearchClaimEvidence,\n ResearchClaimLedger,\n ResearchClaimRecord,\n ResearchSourceVersion,\n} from './types'\n\n/**\n * Claim identity = sha256 of the normalized claim text, so the same assertion\n * discovered independently by two workers is ONE claim with two supporting\n * sources rather than two claims with one each — which is the difference\n * between corroborated and unsupported.\n */\nexport function claimId(text: string): string {\n return `c_${sha256(normalizeClaimText(text)).slice(0, 16)}`\n}\n\n/** Stable identity for one extracted claim/source/contradiction observation. */\nexport function claimEvidenceId(\n claim: Pick<\n ResearchClaimEvidence,\n 'claimId' | 'sourceId' | 'sourceUri' | 'sourceContentHash' | 'contradictsClaimId'\n >,\n): string {\n return `e_${sha256(\n JSON.stringify([\n claim.claimId,\n claim.sourceId,\n claim.sourceUri,\n claim.sourceContentHash,\n claim.contradictsClaimId ?? null,\n ]),\n ).slice(0, 16)}`\n}\n\n/** Canonical key for one exact registry-id + original-URI + hash source version. */\nexport function researchSourceVersionKey(\n source: Pick<ResearchSourceVersion, 'sourceId' | 'uri' | 'contentHash'>,\n): string {\n return JSON.stringify([source.sourceId, source.uri, source.contentHash])\n}\n\n/** Case-, whitespace-, and stylistic-punctuation-insensitive claim identity form. */\nexport function normalizeClaimText(text: string): string {\n return (\n text\n .normalize('NFKC')\n .toLowerCase()\n // Direction and polarity change scientific meaning. Preserve them as word\n // tokens before removing stylistic punctuation, so `x > y` cannot merge\n // with `x < y`, and `+5%` cannot corroborate `-5%`.\n .replace(/<=|≤/gu, ' symbol_less_than_or_equal ')\n .replace(/>=|≥/gu, ' symbol_greater_than_or_equal ')\n .replace(/!=|≠/gu, ' symbol_not_equal ')\n .replace(/==|=/gu, ' symbol_equal ')\n .replace(/±/gu, ' symbol_plus_or_minus ')\n .replace(/[≈~]/gu, ' symbol_approximately ')\n .replace(/<|←|⇐/gu, ' symbol_less_or_left ')\n .replace(/>|→|⇒/gu, ' symbol_greater_or_right ')\n .replace(/[+]/gu, ' symbol_plus_or_positive ')\n .replace(/[-−]/gu, ' symbol_minus_or_negative ')\n .replace(/[^\\p{L}\\p{N}\\s]+/gu, ' ')\n .replace(/\\s+/g, ' ')\n .trim()\n )\n}\n\n/**\n * The canonical host a source uri counts as, which is what makes two sources\n * INDEPENDENT: corroboration is \"distinct hosts\", so this function is the rule\n * that decides whether a claim is confirmed or merely repeated. Exported so a\n * consumer building a `ResearchClaimRecord` cannot answer it a different way — a\n * consumer that counted raw uris would report two pages of one site as\n * independent confirmation.\n */\nexport function claimSourceHost(uri: string): string {\n try {\n return new URL(uri.trim()).hostname.toLowerCase().replace(/^www\\./, '')\n } catch {\n // Non-URL identifier (offline corpus uris like `web/foo`): canonicalize so\n // distinct identifiers still count as distinct independent sources.\n return uri.trim().toLowerCase()\n }\n}\n\n/** Stable identity for one deep question. */\nexport function deepQuestionId(kind: DeepQuestion['kind'], text: string): string {\n return `q_${sha256(`${kind}:${text}`).slice(0, 16)}`\n}\n\n/**\n * Refuse a claim record whose identity or source count disagrees with its evidence.\n *\n * `supportingHosts` is used as the independent-source count, so accepting hosts\n * that cannot be derived from `supportingUris` would let a malformed record\n * manufacture corroboration. Canonical ordering also makes equal records have\n * equal bytes regardless of which process assembled them.\n */\nexport function assertTrackedClaimIntegrity(claim: ResearchClaimRecord): void {\n if (claim.id !== claimId(claim.text)) {\n throw new Error(`claim '${claim.id}' does not match its text-derived identity`)\n }\n if (claim.text !== claim.text.trim()) {\n throw new Error(`claim '${claim.id}' text must not have surrounding whitespace`)\n }\n if (claim.supportingUris.length === 0) {\n throw new Error(`claim '${claim.id}' must have registered supporting evidence`)\n }\n assertSortedUnique(`claim '${claim.id}' supportingUris`, claim.supportingUris)\n assertSortedUnique(`claim '${claim.id}' supportingHosts`, claim.supportingHosts)\n assertSortedUnique(`claim '${claim.id}' contradicts`, claim.contradicts)\n const expectedHosts = [\n ...new Set(claim.supportingUris.map(claimSourceHost).filter(Boolean)),\n ].sort()\n if (!sameStrings(claim.supportingHosts, expectedHosts)) {\n throw new Error(\n `claim '${claim.id}' supportingHosts must equal the hosts derived from supportingUris`,\n )\n }\n if (claim.contradicts.includes(claim.id)) {\n throw new Error(`claim '${claim.id}' cannot contradict itself`)\n }\n if (claim.contradicts.length > 0 && !claim.contested) {\n throw new Error(`claim '${claim.id}' with a contradiction must be contested`)\n }\n if (claim.contested && claim.contradicts.length === 0) {\n throw new Error(`claim '${claim.id}' cannot be contested without a contradiction`)\n }\n}\n\n/** Refuse a deep question whose stable identity or set fields are malformed. */\nexport function assertDeepQuestionIntegrity(question: DeepQuestion): void {\n if (question.id !== deepQuestionId(question.kind, question.text)) {\n throw new Error(`question '${question.id}' does not match its kind-and-text identity`)\n }\n if (question.text !== question.text.trim()) {\n throw new Error(`question '${question.id}' text must not have surrounding whitespace`)\n }\n assertSortedUnique(`question '${question.id}' claimIds`, question.claimIds)\n}\n\n/** Refuse an extracted observation whose identity or content is malformed. */\nexport function assertResearchClaimEvidenceIntegrity(evidence: ResearchClaimEvidence): void {\n if (evidence.claimId !== claimId(evidence.text)) {\n throw new Error(\n `claim evidence '${evidence.id}' does not match its text-derived claim identity`,\n )\n }\n if (evidence.id !== claimEvidenceId(evidence)) {\n throw new Error(`claim evidence '${evidence.id}' does not match its content-derived identity`)\n }\n if (evidence.text !== evidence.text.trim()) {\n throw new Error(`claim evidence '${evidence.id}' text must not have surrounding whitespace`)\n }\n if (!/^[a-f0-9]{64}$/.test(evidence.sourceContentHash)) {\n throw new Error(`claim evidence '${evidence.id}' sourceContentHash must be a SHA-256 digest`)\n }\n const expectedSourceId = textSourceId(evidence.sourceUri, evidence.sourceContentHash)\n if (evidence.sourceId !== expectedSourceId) {\n throw new Error(\n `claim evidence '${evidence.id}' sourceId does not match URI-and-content identity`,\n )\n }\n if (evidence.contradictsClaimId === evidence.claimId) {\n throw new Error(`claim evidence '${evidence.id}' cannot contradict its own claim`)\n }\n}\n\n/** Refuse a ledger that is not one canonical, internally consistent record. */\nexport function assertResearchClaimLedgerIntegrity(ledger: ResearchClaimLedger): void {\n if (ledger.schemaVersion !== 2) {\n throw new Error(`claim ledger '${ledger.id}' must use schema version 2`)\n }\n if (ledger.preparedRounds !== undefined && ledger.preparedRounds <= ledger.rounds) {\n throw new Error(\n `claim ledger '${ledger.id}' preparedRounds must be greater than completed rounds`,\n )\n }\n assertSortedUnique(\n `claim ledger '${ledger.id}' claimEvidence`,\n ledger.claimEvidence.map((evidence) => evidence.id),\n )\n for (const source of ledger.registeredSources) {\n if (\n source.sourceId.length === 0 ||\n source.uri.length === 0 ||\n !/^[a-f0-9]{64}$/.test(source.contentHash)\n ) {\n throw new Error(`claim ledger '${ledger.id}' contains an invalid registered source version`)\n }\n const expectedSourceId = textSourceId(source.uri, source.contentHash)\n if (source.sourceId !== expectedSourceId) {\n throw new Error(\n `registered source '${source.sourceId}' does not match URI-and-content identity '${expectedSourceId}'`,\n )\n }\n }\n assertSortedUnique(\n `claim ledger '${ledger.id}' registeredSources`,\n ledger.registeredSources.map((source) => source.sourceId),\n )\n assertSortedUnique(\n `claim ledger '${ledger.id}' claims`,\n ledger.claims.map((claim) => claim.id),\n )\n assertSortedUnique(\n `claim ledger '${ledger.id}' questions`,\n ledger.questions.map((question) => question.id),\n )\n for (const evidence of ledger.claimEvidence) assertResearchClaimEvidenceIntegrity(evidence)\n const registeredSources = new Set(ledger.registeredSources.map(researchSourceVersionKey))\n const registeredEvidence = ledger.claimEvidence.filter((evidence) =>\n registeredSources.has(\n researchSourceVersionKey({\n sourceId: evidence.sourceId,\n uri: evidence.sourceUri,\n contentHash: evidence.sourceContentHash,\n }),\n ),\n )\n const materializedClaims = new Map(ledger.claims.map((claim) => [claim.id, claim]))\n for (const claim of ledger.claims) {\n assertTrackedClaimIntegrity(claim)\n for (const sourceUri of claim.supportingUris) {\n if (\n !registeredEvidence.some(\n (evidence) => evidence.claimId === claim.id && evidence.sourceUri === sourceUri,\n )\n ) {\n throw new Error(\n `claim '${claim.id}' counts source '${sourceUri}' without exact registered evidence`,\n )\n }\n }\n for (const contradictedClaimId of claim.contradicts) {\n const contradictedClaim = materializedClaims.get(contradictedClaimId)\n if (!contradictedClaim) {\n throw new Error(\n `claim '${claim.id}' contradicts unmaterialized claim '${contradictedClaimId}'`,\n )\n }\n if (!contradictedClaim.contradicts.includes(claim.id)) {\n throw new Error(\n `claim '${claim.id}' has an asymmetric contradiction with '${contradictedClaimId}'`,\n )\n }\n const hasRegisteredObservation = registeredEvidence.some(\n (evidence) =>\n (evidence.claimId === claim.id && evidence.contradictsClaimId === contradictedClaimId) ||\n (evidence.claimId === contradictedClaimId && evidence.contradictsClaimId === claim.id),\n )\n if (!hasRegisteredObservation) {\n throw new Error(\n `claim '${claim.id}' contradicts '${contradictedClaimId}' without exact registered evidence`,\n )\n }\n }\n }\n const claimsById = materializedClaims\n const claimIds = new Set(claimsById.keys())\n for (const evidence of ledger.claimEvidence) {\n const sourceRegistered = registeredSources.has(\n researchSourceVersionKey({\n sourceId: evidence.sourceId,\n uri: evidence.sourceUri,\n contentHash: evidence.sourceContentHash,\n }),\n )\n if (!sourceRegistered) continue\n const claim = claimsById.get(evidence.claimId)\n if (!claim?.supportingUris.includes(evidence.sourceUri)) {\n throw new Error(\n `registered claim evidence '${evidence.id}' must be materialized in its claim`,\n )\n }\n if (\n evidence.contradictsClaimId !== undefined &&\n claimsById.has(evidence.contradictsClaimId) &&\n !claim.contradicts.includes(evidence.contradictsClaimId)\n ) {\n throw new Error(\n `registered claim evidence '${evidence.id}' must materialize its contradiction`,\n )\n }\n }\n for (const question of ledger.questions) {\n assertDeepQuestionIntegrity(question)\n for (const claimId of question.claimIds) {\n if (!claimIds.has(claimId)) {\n throw new Error(\n `question '${question.id}' references claim '${claimId}' outside its ledger`,\n )\n }\n }\n }\n}\n\n/** A ledger with nothing in it yet. */\nexport function emptyClaimLedger(id: string, goal?: string): ResearchClaimLedger {\n return {\n schemaVersion: 2,\n id,\n ...(goal === undefined ? {} : { goal }),\n updatedAt: new Date(0).toISOString(),\n rounds: 0,\n claimEvidence: [],\n registeredSources: [],\n claims: [],\n questions: [],\n }\n}\n\n/**\n * Turn only evidence backed by a confirmed source registration into support.\n *\n * This is a monotone closure: it never removes claims or evidence, and running\n * it twice is a no-op. Keeping it in the ledger algebra means a source-confirming\n * writer and an evidence-producing writer can arrive in either order.\n */\nexport function materializeRegisteredClaimEvidence(\n ledger: ResearchClaimLedger,\n): ResearchClaimLedger {\n const registered = new Set(ledger.registeredSources.map(researchSourceVersionKey))\n const claims = new Map<string, ResearchClaimRecord>(\n ledger.claims.map((claim) => [claim.id, claim]),\n )\n for (const evidence of ledger.claimEvidence) {\n if (!registered.has(sourceVersionKeyOfEvidence(evidence))) continue\n const host = claimSourceHost(evidence.sourceUri)\n const observed: ResearchClaimRecord = {\n id: evidence.claimId,\n text: evidence.text,\n supportingHosts: host ? [host] : [],\n supportingUris: [evidence.sourceUri],\n contradicts: [],\n contested: false,\n firstSeenRound: evidence.firstSeenRound,\n }\n const existing = claims.get(observed.id)\n claims.set(observed.id, existing ? mergeTrackedClaims(existing, observed) : observed)\n }\n // A contradiction is active only when BOTH claims have registered support.\n // Keep the observation while its counterpart is pending, then close the edge\n // automatically when that counterpart is materialized by a later merge.\n for (const evidence of ledger.claimEvidence) {\n const otherId = evidence.contradictsClaimId\n if (!registered.has(sourceVersionKeyOfEvidence(evidence)) || !otherId || !claims.has(otherId)) {\n continue\n }\n const claim = claims.get(evidence.claimId)\n if (!claim) continue\n claims.set(claim.id, {\n ...claim,\n contradicts: union(claim.contradicts, [otherId]),\n contested: true,\n })\n }\n return linkClaimContradictions({\n ...ledger,\n claims: [...claims.values()].sort((left, right) => left.id.localeCompare(right.id)),\n })\n}\n\nfunction sourceVersionKeyOfEvidence(evidence: ResearchClaimEvidence): string {\n return researchSourceVersionKey({\n sourceId: evidence.sourceId,\n uri: evidence.sourceUri,\n contentHash: evidence.sourceContentHash,\n })\n}\n\n/**\n * Raised when two ledgers that accumulated evidence for DIFFERENT goals are\n * combined. Merging them would pool two questions' evidence into one\n * corroboration count, which reports a claim as independently confirmed when\n * nobody confirmed it — strictly worse than losing the ledger, so this refuses.\n */\nexport class ClaimLedgerGoalConflictError extends Error {\n constructor(\n readonly ledgerId: string,\n readonly existingGoal: string,\n readonly incomingGoal: string,\n ) {\n super(\n `claim ledger '${ledgerId}' accumulated evidence for goal '${existingGoal}' ` +\n `and cannot be merged with evidence for '${incomingGoal}'`,\n )\n this.name = 'ClaimLedgerGoalConflictError'\n }\n}\n\n/**\n * Combine two records of the same claim.\n *\n * Union on every support collection, because a claim asserted by hosts {a} in\n * one writer and {b} in another is asserted by two independent hosts and the\n * whole completion oracle turns on that count. `contested` is OR — one writer\n * seeing a contradiction is enough for the claim to be contested, and no later\n * writer that simply did not see it may clear the flag.\n */\nexport function mergeTrackedClaims(\n base: ResearchClaimRecord,\n incoming: ResearchClaimRecord,\n): ResearchClaimRecord {\n assertTrackedClaimIntegrity(base)\n assertTrackedClaimIntegrity(incoming)\n if (base.id !== incoming.id) {\n throw new Error(`cannot merge claim '${base.id}' with a different claim '${incoming.id}'`)\n }\n const text =\n incoming.firstSeenRound < base.firstSeenRound\n ? incoming.text\n : incoming.firstSeenRound > base.firstSeenRound\n ? base.text\n : incoming.text < base.text\n ? incoming.text\n : base.text\n return {\n id: base.id,\n // The earlier-seen text wins, so the claim's wording is stable across\n // merges rather than flipping with whichever writer wrote last. Equal\n // rounds use a lexical tie-break, preserving commutativity too.\n text,\n supportingHosts: union(base.supportingHosts, incoming.supportingHosts),\n supportingUris: union(base.supportingUris, incoming.supportingUris),\n contradicts: union(base.contradicts, incoming.contradicts),\n contested: base.contested || incoming.contested,\n firstSeenRound: Math.min(base.firstSeenRound, incoming.firstSeenRound),\n }\n}\n\n/**\n * Combine two ledgers for the same run.\n *\n * `addressed` on a question is OR for the same reason `contested` is: a writer\n * that answered a question has answered it, and a writer that never saw the\n * answer must not reopen it. Everything else is a union or an extreme, so this\n * is associative and idempotent — merge order cannot change the result and a\n * replayed merge is a no-op.\n */\nexport function mergeClaimLedgers(\n base: ResearchClaimLedger,\n incoming: ResearchClaimLedger,\n): ResearchClaimLedger {\n assertResearchClaimLedgerIntegrity(base)\n assertResearchClaimLedgerIntegrity(incoming)\n if (base.id !== incoming.id) {\n throw new Error(\n `cannot merge claim ledger '${base.id}' with a different ledger '${incoming.id}'`,\n )\n }\n if (base.goal !== undefined && incoming.goal !== undefined && base.goal !== incoming.goal) {\n throw new ClaimLedgerGoalConflictError(base.id, base.goal, incoming.goal)\n }\n const goal = base.goal ?? incoming.goal\n\n const claimEvidence = new Map<string, ResearchClaimEvidence>(\n base.claimEvidence.map((evidence) => [evidence.id, evidence]),\n )\n for (const evidence of incoming.claimEvidence) {\n const existing = claimEvidence.get(evidence.id)\n claimEvidence.set(evidence.id, existing ? mergeClaimEvidence(existing, evidence) : evidence)\n }\n\n const claims = new Map<string, ResearchClaimRecord>(base.claims.map((claim) => [claim.id, claim]))\n for (const claim of incoming.claims) {\n const existing = claims.get(claim.id)\n claims.set(claim.id, existing ? mergeTrackedClaims(existing, claim) : claim)\n }\n\n const questions = new Map<string, DeepQuestion>(\n base.questions.map((question) => [question.id, question]),\n )\n for (const question of incoming.questions) {\n const existing = questions.get(question.id)\n if (existing && (existing.kind !== question.kind || existing.text !== question.text)) {\n throw new Error(`question '${question.id}' has conflicting immutable content`)\n }\n questions.set(\n question.id,\n existing\n ? {\n ...existing,\n claimIds: union(existing.claimIds, question.claimIds),\n addressed: existing.addressed || question.addressed,\n raisedRound: Math.min(existing.raisedRound, question.raisedRound),\n }\n : question,\n )\n }\n\n const rounds = Math.max(base.rounds, incoming.rounds)\n const preparedRounds = Math.max(\n base.preparedRounds ?? base.rounds,\n incoming.preparedRounds ?? incoming.rounds,\n )\n return materializeRegisteredClaimEvidence({\n schemaVersion: 2,\n id: base.id,\n ...(goal === undefined ? {} : { goal }),\n updatedAt:\n incoming.updatedAt.localeCompare(base.updatedAt) > 0 ? incoming.updatedAt : base.updatedAt,\n rounds,\n ...(preparedRounds > rounds ? { preparedRounds } : {}),\n claimEvidence: [...claimEvidence.values()].sort((left, right) =>\n left.id.localeCompare(right.id),\n ),\n registeredSources: mergeSourceVersions(base.registeredSources, incoming.registeredSources),\n // Sorted by id so the bytes on disk depend on the ledger's content and not\n // on the order two writers happened to arrive in.\n claims: [...claims.values()].sort((a, b) => a.id.localeCompare(b.id)),\n questions: [...questions.values()].sort((a, b) => a.id.localeCompare(b.id)),\n })\n}\n\nfunction mergeClaimEvidence(\n base: ResearchClaimEvidence,\n incoming: ResearchClaimEvidence,\n): ResearchClaimEvidence {\n assertResearchClaimEvidenceIntegrity(base)\n assertResearchClaimEvidenceIntegrity(incoming)\n if (\n base.id !== incoming.id ||\n base.claimId !== incoming.claimId ||\n base.sourceId !== incoming.sourceId ||\n base.sourceUri !== incoming.sourceUri ||\n base.sourceContentHash !== incoming.sourceContentHash ||\n base.contradictsClaimId !== incoming.contradictsClaimId\n ) {\n throw new Error(`claim evidence '${base.id}' has conflicting immutable content`)\n }\n const text =\n incoming.firstSeenRound < base.firstSeenRound\n ? incoming.text\n : incoming.firstSeenRound > base.firstSeenRound\n ? base.text\n : incoming.text < base.text\n ? incoming.text\n : base.text\n return {\n ...base,\n text,\n firstSeenRound: Math.min(base.firstSeenRound, incoming.firstSeenRound),\n }\n}\n\nfunction mergeSourceVersions(\n base: readonly ResearchSourceVersion[],\n incoming: readonly ResearchSourceVersion[],\n): ResearchSourceVersion[] {\n const versions = new Map<string, ResearchSourceVersion>()\n for (const source of [...base, ...incoming]) {\n const existing = versions.get(source.sourceId)\n if (existing && researchSourceVersionKey(existing) !== researchSourceVersionKey(source)) {\n throw new Error(`registered source '${source.sourceId}' has conflicting immutable content`)\n }\n versions.set(source.sourceId, source)\n }\n return [...versions.values()].sort((left, right) => left.sourceId.localeCompare(right.sourceId))\n}\n\n/**\n * Make every contradiction edge symmetric and mark both ends contested.\n *\n * A contradiction is a property of a PAIR, and a writer only ever sees one side\n * of it: the worker that found the refuting source records \"X contradicts Y\" and\n * knows nothing about Y's record. Left one-sided, Y reads as an uncontested\n * claim, and the completion oracle would settle a question two sources disagree\n * about. `createResearchDrivingDriver` does this pairwise as it records; this is\n * the same rule stated over a whole ledger, for writers that assemble one from\n * events rather than from a live loop.\n *\n * One-sided observations stay in `claimEvidence` until both claims are backed\n * by registered source versions. The materialized claim projection contains\n * only closed pairs, so it cannot report a lone weak claim as settled merely\n * because its evidence named a claim that never arrived.\n */\nexport function linkClaimContradictions(ledger: ResearchClaimLedger): ResearchClaimLedger {\n const claimIds = new Set(ledger.claims.map((claim) => claim.id))\n const inbound = new Map<string, string[]>()\n for (const claim of ledger.claims) {\n for (const other of claim.contradicts) {\n if (other === claim.id || !claimIds.has(other)) continue\n const edges = inbound.get(other)\n if (edges) edges.push(claim.id)\n else inbound.set(other, [claim.id])\n }\n }\n return {\n ...ledger,\n claims: ledger.claims\n .map((claim) => {\n const contradicts = union(\n claim.contradicts.filter((other) => other !== claim.id && claimIds.has(other)),\n inbound.get(claim.id) ?? [],\n )\n return { ...claim, contradicts, contested: contradicts.length > 0 }\n })\n .sort((a, b) => a.id.localeCompare(b.id)),\n }\n}\n\n/**\n * Set union, SORTED.\n *\n * Sorted because these collections are sets and merging must be commutative:\n * arrival order is not part of what the ledger says, so two writers arriving in\n * either order have to produce identical bytes. Preserving first-seen order\n * instead made `merge(a, b)` and `merge(b, a)` differ, which the order-\n * independence test caught — and a non-commutative merge under a filesystem\n * lock means the record depends on scheduling.\n */\nfunction union(base: readonly string[], incoming: readonly string[]): string[] {\n return [...new Set([...base, ...incoming])].sort()\n}\n\nfunction assertSortedUnique(label: string, values: readonly string[]): void {\n for (let index = 1; index < values.length; index += 1) {\n if ((values[index - 1] ?? '') >= (values[index] ?? '')) {\n throw new Error(`${label} must be sorted and contain no duplicates`)\n }\n }\n}\n\nfunction sameStrings(left: readonly string[], right: readonly string[]): boolean {\n return left.length === right.length && left.every((value, index) => value === right[index])\n}\n","export type KnowledgeId = string\n\nexport interface SourceAnchor {\n id: string\n sourceId: string\n label?: string\n page?: number\n lineStart?: number\n lineEnd?: number\n charStart?: number\n charEnd?: number\n timestampMs?: number\n metadata?: Record<string, unknown>\n}\n\nexport interface SourceRecord {\n id: KnowledgeId\n uri: string\n title?: string\n mediaType?: string\n contentHash: string\n text?: string\n anchors?: SourceAnchor[]\n /** ISO timestamp after which consumers should treat this source as stale. */\n validUntil?: string\n /** ISO timestamp for the last successful source freshness verification. */\n lastVerifiedAt?: string\n metadata?: Record<string, unknown>\n createdAt: string\n}\n\nexport interface SourceRegistry {\n generatedAt: string\n sources: SourceRecord[]\n}\n\nexport interface ClaimRef {\n sourceId: string\n anchorId?: string\n quote?: string\n}\n\nexport interface KnowledgeClaim {\n id: KnowledgeId\n text: string\n refs: ClaimRef[]\n confidence?: number\n status?: 'draft' | 'active' | 'superseded' | 'rejected'\n metadata?: Record<string, unknown>\n}\n\nexport interface KnowledgeRelation {\n sourceId: KnowledgeId\n targetId: KnowledgeId\n predicate: string\n weight?: number\n metadata?: Record<string, unknown>\n}\n\nexport interface KnowledgeUnit {\n id: KnowledgeId\n title: string\n text: string\n claims?: KnowledgeClaim[]\n relations?: KnowledgeRelation[]\n sourceIds?: string[]\n tags?: string[]\n metadata?: Record<string, unknown>\n updatedAt?: string\n}\n\nexport interface KnowledgePage {\n id: KnowledgeId\n path: string\n title: string\n text: string\n frontmatter: Record<string, unknown>\n sourceIds: string[]\n tags: string[]\n outLinks: string[]\n}\n\nexport interface KnowledgeGraphNode {\n id: KnowledgeId\n title: string\n path: string\n tags: string[]\n sourceIds: string[]\n outDegree: number\n inDegree: number\n}\n\nexport interface KnowledgeGraphEdge {\n source: KnowledgeId\n target: KnowledgeId\n weight: number\n reasons: string[]\n}\n\nexport interface KnowledgeGraph {\n nodes: KnowledgeGraphNode[]\n edges: KnowledgeGraphEdge[]\n}\n\nexport interface KnowledgeIndex {\n root: string\n generatedAt: string\n sources: SourceRecord[]\n pages: KnowledgePage[]\n graph: KnowledgeGraph\n}\n\nexport interface KnowledgeSearchResult {\n page: KnowledgePage\n /**\n * Raw reciprocal rank fusion score. Mathematically meaningful for ordering\n * but not on a [0, 1] confidence scale — typical absolute values are in the\n * 0.01–0.05 range. Equal to `rrfScore`; preserved as `score` for backward\n * compatibility with consumers built against earlier releases.\n */\n score: number\n /** Alias of `score` — the raw RRF value. Use this when intent matters. */\n rrfScore: number\n /**\n * Score linearly normalized to [0, 1] relative to the top hit *in this\n * result set*. The top hit is always 1 (when present); subsequent hits are\n * `score / topScore`. Designed to match human intuition for \"how confident\n * is this match\" — safe to compare against fixed thresholds. Note: this is\n * a within-set ranking, not a cross-query absolute confidence.\n */\n normalizedScore: number\n rank: number\n snippet: string\n reasons: string[]\n}\n\nexport interface KnowledgeLintFinding {\n type:\n | 'broken-link'\n | 'orphan'\n | 'no-outlinks'\n | 'uncited-claim'\n | 'missing-source'\n | 'duplicate-title'\n | 'duplicate-page-id'\n | 'duplicate-source-hash'\n | 'missing-frontmatter'\n severity: 'info' | 'warning' | 'error'\n page?: string\n message: string\n metadata?: Record<string, unknown>\n}\n\nexport interface KnowledgePolicy {\n id: string\n description?: string\n requiredCitationRate?: number\n allowedPathPrefixes?: string[]\n metadata?: Record<string, unknown>\n}\n\nexport interface KnowledgeBaseCandidate {\n id: KnowledgeId\n units: KnowledgeUnit[]\n retrievalPolicy?: string\n synthesisPolicy?: string\n questionPolicy?: string\n updatePolicy?: string\n metadata?: Record<string, unknown>\n}\n\nexport interface KnowledgeWriteBlock {\n path: string\n content: string\n}\n\nexport interface KnowledgeWriteParseResult {\n blocks: KnowledgeWriteBlock[]\n warnings: string[]\n}\n\n/**\n * The event vocabulary, as a value so the runtime schema is DERIVED from it\n * rather than restated. A restated copy in `schemas.ts` drifted: it omitted\n * `research.iteration`, which is the only event `runVerifiedResearchLoop`\n * produces, so every attempt to store one would have been rejected. Nothing\n * caught it because nothing ever stored an event. Add a type here and the\n * schema accepts it in the same edit.\n */\nexport const KNOWLEDGE_EVENT_TYPES = [\n 'source.added',\n 'proposal.applied',\n 'index.built',\n 'lint.run',\n 'research.iteration',\n 'optimization.run',\n 'release.promoted',\n 'release.rejected',\n] as const\n\nexport type KnowledgeEventType = (typeof KNOWLEDGE_EVENT_TYPES)[number]\n\nexport interface KnowledgeEvent {\n id: string\n type: KnowledgeEventType\n createdAt: string\n actor?: string\n target?: string\n metadata?: Record<string, unknown>\n}\n\n/** The four deep sub-question kinds a research driver raises to drive depth. */\nexport type DeepQuestionKind = 'comparative' | 'mechanism' | 'gap' | 'contradiction'\n\n/**\n * A deep sub-question the research driver folds into the worker's next prompt.\n *\n * Lives here, next to the other record types, because it is persisted state:\n * `addressed` is the half of the completion oracle that cannot be recomputed\n * from the claim ledger alone, so a run that loses it reports \"complete\" for\n * questions nobody ever answered.\n */\nexport interface DeepQuestion {\n kind: DeepQuestionKind\n text: string\n /** sha256-derived stable id, so \"addressed\" can be tracked across rounds. */\n id: string\n /** Claim id(s) this question interrogates (for contradiction/mechanism kinds). */\n claimIds: string[]\n /** True once a later round's evidence addressed it. */\n addressed: boolean\n /** The round this question was raised in. */\n raisedRound: number\n}\n\n/** One live tracked claim exposed by the research-driving API. */\nexport interface TrackedClaim {\n id: string\n /** The claim text as first extracted (kept for prompts/audit). */\n text: string\n /** Canonical hosts of the INDEPENDENT sources that assert this claim. */\n supportingHosts: Set<string>\n /** Source URIs that assert this claim (provenance; may share a host). */\n supportingUris: string[]\n /** Claim ids this claim was found to CONTRADICT (and vice versa). */\n contradicts: Set<string>\n /**\n * CONTESTED = a contradiction the loop surfaced but could not resolve to a\n * single supported claim. A contested claim counts as \"settled enough to be\n * done\" (we report the disagreement) even with < 2 independent sources.\n */\n contested: boolean\n firstSeenRound: number\n}\n\n/**\n * JSON-safe form of a tracked claim stored in a research claim ledger.\n *\n * The live `TrackedClaim` contract retains its published `Set` fields.\n * Durable records use sorted arrays because `JSON.stringify` turns a `Set`\n * into `{}`, which would erase every corroboration count and contradiction.\n */\nexport interface ResearchClaimRecord {\n id: string\n text: string\n supportingHosts: string[]\n supportingUris: string[]\n contradicts: string[]\n contested: boolean\n firstSeenRound: number\n}\n\n/** Immutable identity of one exact version of an original source URI. */\nexport interface ResearchSourceVersion {\n /** Canonical source-registry id for this URI and content hash. */\n sourceId: KnowledgeId\n /** The URI supplied before the source was copied into the raw-source store. */\n uri: string\n /** SHA-256 of the exact submitted source text. */\n contentHash: string\n}\n\n/**\n * One immutable claim extraction observed while a source is being verified.\n *\n * An observation is deliberately separate from `ResearchClaimRecord`: source\n * verification happens before source registration, and a process can die in\n * between. The observation is durable immediately, but it contributes support\n * to a claim only after its expected registry id, original URI, and content hash\n * appear together in the ledger's independently confirmed `registeredSources` set.\n */\nexport interface ResearchClaimEvidence {\n /** Stable identity of this claim/source/contradiction observation. */\n id: string\n claimId: string\n text: string\n /** Canonical source-registry id expected for this source version. */\n sourceId: KnowledgeId\n sourceUri: string\n /** SHA-256 of the exact source text from which this observation was extracted. */\n sourceContentHash: string\n /** Existing claim this observation directly contradicts, when reported. */\n contradictsClaimId?: string\n firstSeenRound: number\n}\n\n/**\n * The durable record of one research run's belief state: which claims were\n * extracted, how independently each is supported, which contradict which, and\n * which deep sub-questions are still open.\n *\n * `id` names the run — one knowledge base can host several, and they must not\n * overwrite each other, so the store addresses ledgers by this id.\n */\nexport interface ResearchClaimLedger {\n /** Persistent contract version; version 2 binds evidence to source content. */\n schemaVersion: 2\n id: string\n /** The research goal this ledger accumulated evidence for. */\n goal?: string\n /** ISO timestamp of the last write. */\n updatedAt: string\n /** How many rounds the driver has folded steer for. */\n rounds: number\n /**\n * Highest round durably announced before its synchronous question-generation\n * step began. Greater than `rounds` only while a round needs crash recovery.\n */\n preparedRounds?: number\n /**\n * Extracted evidence, including observations whose source registration has\n * not yet been confirmed. Pending observations never count toward claims.\n */\n claimEvidence: ResearchClaimEvidence[]\n /** Exact source-registry identities confirmed after their raw bytes were stored. */\n registeredSources: ResearchSourceVersion[]\n claims: ResearchClaimRecord[]\n questions: DeepQuestion[]\n}\n\nexport interface KnowledgeRelease {\n id: string\n candidateId: string\n createdAt: string\n promoted: boolean\n scorecard?: unknown\n runRecordIds?: string[]\n metadata?: Record<string, unknown>\n}\n","import { z } from 'zod'\nimport {\n assertDeepQuestionIntegrity,\n assertResearchClaimEvidenceIntegrity,\n assertResearchClaimLedgerIntegrity,\n assertTrackedClaimIntegrity,\n} from './claim-ledger'\nimport { KNOWLEDGE_EVENT_TYPES } from './types'\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 validUntil: z.iso.datetime().optional(),\n lastVerifiedAt: z.iso.datetime().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 // Derived from the type union's own value list — see KNOWLEDGE_EVENT_TYPES.\n // A hand-restated copy of this enum drifted and silently rejected the one\n // event the research loop emits.\n type: z.enum(KNOWLEDGE_EVENT_TYPES),\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 DeepQuestionSchema = z\n .object({\n kind: z.enum(['comparative', 'mechanism', 'gap', 'contradiction']),\n text: z.string().min(1),\n id: z.string().min(1),\n claimIds: z.array(z.string().min(1)),\n addressed: z.boolean(),\n raisedRound: z.number().int().nonnegative(),\n })\n .strict()\n .superRefine((question, context) => {\n reportIntegrityError(context, () => assertDeepQuestionIntegrity(question))\n })\n\nexport const ResearchClaimRecordSchema = z\n .object({\n id: z.string().min(1),\n text: z.string().min(1),\n supportingHosts: z.array(z.string().min(1)),\n supportingUris: z.array(z.string().min(1)),\n contradicts: z.array(z.string().min(1)),\n contested: z.boolean(),\n firstSeenRound: z.number().int().nonnegative(),\n })\n .strict()\n .superRefine((claim, context) => {\n reportIntegrityError(context, () => assertTrackedClaimIntegrity(claim))\n })\n\nexport const ResearchSourceVersionSchema = z\n .object({\n sourceId: z.string().min(1),\n uri: z.string().min(1),\n contentHash: z.string().regex(/^[a-f0-9]{64}$/),\n })\n .strict()\n\nexport const ResearchClaimEvidenceSchema = z\n .object({\n id: z.string().min(1),\n claimId: z.string().min(1),\n text: z.string().min(1),\n sourceId: z.string().min(1),\n sourceUri: z.string().min(1),\n sourceContentHash: z.string().regex(/^[a-f0-9]{64}$/),\n contradictsClaimId: z.string().min(1).optional(),\n firstSeenRound: z.number().int().nonnegative(),\n })\n .strict()\n .superRefine((evidence, context) => {\n reportIntegrityError(context, () => assertResearchClaimEvidenceIntegrity(evidence))\n })\n\nexport const ResearchClaimLedgerSchema = z\n .object({\n schemaVersion: z.literal(2),\n id: z.string().min(1),\n goal: z.string().trim().min(1).optional(),\n updatedAt: z.iso.datetime(),\n rounds: z.number().int().nonnegative(),\n preparedRounds: z.number().int().nonnegative().optional(),\n claimEvidence: z.array(ResearchClaimEvidenceSchema),\n registeredSources: z.array(ResearchSourceVersionSchema),\n claims: z.array(ResearchClaimRecordSchema),\n questions: z.array(DeepQuestionSchema),\n })\n .strict()\n .superRefine((ledger, context) => {\n reportIntegrityError(context, () => assertResearchClaimLedgerIntegrity(ledger))\n })\n\nfunction reportIntegrityError(context: z.core.$RefinementCtx, check: () => void): void {\n try {\n check()\n } catch (error) {\n context.addIssue({\n code: 'custom',\n message: error instanceof Error ? error.message : String(error),\n })\n }\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 { basename, dirname, resolve } from 'node:path'\nimport { z } from 'zod'\nimport {\n isMissingFile,\n listRegularFilesWithinRoot,\n readRegularFileWithinRoot,\n writeJsonDurableWithinRoot,\n} from './durable-fs'\nimport type { KnowledgeEventQuery } from './events'\nimport { buildKnowledgeGraph } from './graph'\nimport { withKnowledgeMutation, withKnowledgeRead } from './mutation-lock'\nimport {\n DeepQuestionSchema,\n KnowledgeEventSchema,\n KnowledgeIndexSchema,\n KnowledgePageSchema,\n ResearchClaimLedgerSchema,\n SourceRecordSchema,\n} from './schemas'\nimport type {\n KnowledgeEvent,\n KnowledgeIndex,\n KnowledgePage,\n ResearchClaimLedger,\n SourceRecord,\n} from './types'\n\n/**\n * Where a filesystem knowledge base keeps its machine-written records, relative\n * to the knowledge-base root.\n *\n * This is the ONE location. `FileSystemKbStore` used to write `<dir>/index.json`\n * while `writeKnowledgeIndex` wrote `<root>/.agent-knowledge/index.json` — two\n * index writers, two files, and only the second one reachable, so a store that\n * had just been written to reported an empty knowledge base. Both now go through\n * `FileSystemKbStore`, anchored on the knowledge-base root, which is also the\n * directory `withKnowledgeMutation` locks: one file, one lock domain.\n */\nexport const KB_STORE_DIR = '.agent-knowledge'\nexport const KB_INDEX_PATH = `${KB_STORE_DIR}/index.json`\nexport const KB_EVENTS_PATH = `${KB_STORE_DIR}/events.json`\nexport const KB_CLAIM_LEDGER_DIR = `${KB_STORE_DIR}/claim-ledgers`\n\n/**\n * A claim-ledger id is used as a filename, so it is restricted to one safe path\n * segment. Rejecting rather than sanitising is deliberate: a sanitised id maps\n * two different runs onto one file and silently merges their belief state.\n */\nconst LEDGER_ID_PATTERN = /^[A-Za-z0-9_-][A-Za-z0-9._-]*$/\n\nexport function assertClaimLedgerId(id: string): string {\n if (!LEDGER_ID_PATTERN.test(id) || id === '.' || id === '..') {\n throw new Error(\n `claim ledger id must match ${LEDGER_ID_PATTERN} and cannot be a path segment: ${id}`,\n )\n }\n return id\n}\n\n/** A URI-only ledger cannot be upgraded without re-verifying its source bytes. */\nexport class ClaimLedgerMigrationRequiredError extends Error {\n constructor(\n readonly ledgerId: string,\n readonly foundSchemaVersion: number | 'unversioned',\n ) {\n super(\n `claim ledger '${ledgerId}' uses source identity schema '${foundSchemaVersion}'; ` +\n 'archive it and re-verify its sources into a new ledger before use',\n )\n this.name = 'ClaimLedgerMigrationRequiredError'\n }\n}\n\nexport interface KbStore {\n putSource(source: SourceRecord): Promise<void>\n getSource(id: string): Promise<SourceRecord | null>\n listSources(): Promise<SourceRecord[]>\n putPage(page: KnowledgePage): Promise<void>\n getPage(idOrPath: string): Promise<KnowledgePage | null>\n listPages(): Promise<KnowledgePage[]>\n putIndex(index: KnowledgeIndex): Promise<void>\n getIndex(): Promise<KnowledgeIndex | null>\n putEvent(event: KnowledgeEvent): Promise<void>\n listEvents(query?: KnowledgeEventQuery): Promise<KnowledgeEvent[]>\n}\n\n/** Optional durable capability for stores that retain per-run research belief. */\nexport interface ClaimLedgerStore {\n /**\n * Persist one research run's claim ledger — the corroboration counts,\n * contradiction edges, and open deep questions that make up its belief state.\n * Addressed by `ledger.id` so two runs against one knowledge base cannot\n * overwrite each other.\n */\n putClaimLedger(ledger: ResearchClaimLedger): Promise<void>\n getClaimLedger(id: string): Promise<ResearchClaimLedger | null>\n listClaimLedgers(): Promise<ResearchClaimLedger[]>\n /**\n * Read one ledger, hand it to `merge`, and write what comes back — with the\n * store's exclusive lock held across all three steps.\n *\n * This is the call a concurrent writer must use, and `putClaimLedger` is the\n * one it must not. `putClaimLedger` writes the whole record, so two writers\n * accumulating into one ledger each write a record built from what they read\n * before the other wrote, and the later write erases the earlier writer's\n * claims. Persisting a ledger that loses half its evidence is not compounding\n * knowledge; it is losing it more slowly.\n *\n * `merge` is SYNCHRONOUS on purpose: it runs inside the critical section, and\n * an `await` in there is a lock held across arbitrary I/O.\n */\n mergeClaimLedger(\n id: string,\n merge: (current: ResearchClaimLedger | null) => ResearchClaimLedger,\n ): Promise<ResearchClaimLedger>\n}\n\nexport class MemoryKbStore implements KbStore, ClaimLedgerStore {\n private readonly sources = new Map<string, SourceRecord>()\n private readonly pages = new Map<string, KnowledgePage>()\n private readonly events: KnowledgeEvent[] = []\n private readonly claimLedgers = new Map<string, ResearchClaimLedger>()\n private index: KnowledgeIndex | null = null\n\n async putSource(source: SourceRecord): Promise<void> {\n this.sources.set(source.id, clone(source))\n }\n\n async getSource(id: string): Promise<SourceRecord | null> {\n return clone(this.sources.get(id) ?? null)\n }\n\n async listSources(): Promise<SourceRecord[]> {\n return [...this.sources.values()].map(clone)\n }\n\n async putPage(page: KnowledgePage): Promise<void> {\n this.pages.set(page.id, clone(page))\n }\n\n async getPage(idOrPath: string): Promise<KnowledgePage | null> {\n return clone(\n this.pages.get(idOrPath) ??\n [...this.pages.values()].find((page) => page.path === idOrPath) ??\n null,\n )\n }\n\n async listPages(): Promise<KnowledgePage[]> {\n return [...this.pages.values()].map(clone)\n }\n\n async putIndex(index: KnowledgeIndex): Promise<void> {\n this.index = clone(index)\n }\n\n async getIndex(): Promise<KnowledgeIndex | null> {\n if (this.index) return clone(this.index)\n const pages = await this.listPages()\n const sources = await this.listSources()\n return {\n root: 'memory',\n generatedAt: new Date().toISOString(),\n sources,\n pages,\n graph: buildKnowledgeGraph(pages),\n }\n }\n\n async putEvent(event: KnowledgeEvent): Promise<void> {\n this.events.push(clone(event))\n }\n\n async listEvents(query: KnowledgeEventQuery = {}): Promise<KnowledgeEvent[]> {\n let out = this.events\n if (query.type) out = out.filter((event) => event.type === query.type)\n if (query.target) out = out.filter((event) => event.target === query.target)\n out = [...out].sort((a, b) => a.createdAt.localeCompare(b.createdAt))\n return out.slice(-(query.limit ?? out.length)).map(clone)\n }\n\n async putClaimLedger(ledger: ResearchClaimLedger): Promise<void> {\n const parsed = parseResearchClaimLedger(ledger)\n this.claimLedgers.set(assertClaimLedgerId(parsed.id), clone(parsed))\n }\n\n async getClaimLedger(id: string): Promise<ResearchClaimLedger | null> {\n return clone(this.claimLedgers.get(assertClaimLedgerId(id)) ?? null)\n }\n\n async listClaimLedgers(): Promise<ResearchClaimLedger[]> {\n return [...this.claimLedgers.values()].map(clone).sort((a, b) => a.id.localeCompare(b.id))\n }\n\n async mergeClaimLedger(\n id: string,\n merge: (current: ResearchClaimLedger | null) => ResearchClaimLedger,\n ): Promise<ResearchClaimLedger> {\n // No lock: `merge` is synchronous and this is one process, so nothing can\n // interleave between the read and the write.\n const key = assertClaimLedgerId(id)\n const next = assertMergedLedgerId(key, merge(clone(this.claimLedgers.get(key) ?? null)))\n await this.putClaimLedger(next)\n return clone(next)\n }\n}\n\nconst knowledgeEventsSchema = z.array(KnowledgeEventSchema)\n\n/**\n * The durable record store for one knowledge base.\n *\n * The object constructor is anchored on the knowledge-base root and keeps its\n * records under `<root>/.agent-knowledge/`, which is the layout used by\n * `writeKnowledgeIndex`. The string constructor preserves the published direct\n * record-directory layout (`<directory>/index.json`).\n */\nexport interface FileSystemKbStoreOptions {\n /** Knowledge-base root; records are stored under `<root>/.agent-knowledge/`. */\n root: string\n}\n\nexport class FileSystemKbStore implements KbStore, ClaimLedgerStore {\n private readonly root: string\n private readonly indexPath: string\n private readonly eventsPath: string\n private readonly claimLedgerDir: string\n\n /**\n * A string retains the published direct-directory contract.\n * The object form explicitly selects a knowledge-base root and the canonical\n * `.agent-knowledge/` layout. A string naming that exact canonical directory\n * keeps its file paths but shares the root form's lock domain.\n */\n constructor(input: string | FileSystemKbStoreOptions) {\n const directDirectory = typeof input === 'string' ? resolve(input) : undefined\n const aliasesCanonicalDirectory =\n directDirectory !== undefined && basename(directDirectory) === KB_STORE_DIR\n this.root = aliasesCanonicalDirectory\n ? dirname(directDirectory)\n : typeof input === 'string'\n ? input\n : input.root\n const canonicalLayout = typeof input !== 'string' || aliasesCanonicalDirectory\n this.indexPath = canonicalLayout ? KB_INDEX_PATH : 'index.json'\n this.eventsPath = canonicalLayout ? KB_EVENTS_PATH : 'events.json'\n this.claimLedgerDir = canonicalLayout ? KB_CLAIM_LEDGER_DIR : 'claim-ledgers'\n }\n\n async putSource(source: SourceRecord): Promise<void> {\n const parsed = SourceRecordSchema.parse(source) as SourceRecord\n await this.updateIndex((index) => ({\n ...index,\n generatedAt: new Date().toISOString(),\n sources: [parsed, ...index.sources.filter((entry) => entry.id !== parsed.id)],\n }))\n }\n\n async getSource(id: string): Promise<SourceRecord | null> {\n return withKnowledgeRead(this.root, async () => {\n const index = await this.readIndex()\n return clone(index?.sources.find((source) => source.id === id) ?? null)\n })\n }\n\n async listSources(): Promise<SourceRecord[]> {\n return withKnowledgeRead(this.root, async () => clone((await this.readIndex())?.sources ?? []))\n }\n\n async putPage(page: KnowledgePage): Promise<void> {\n const parsed = KnowledgePageSchema.parse(page) as KnowledgePage\n await this.updateIndex((index) => {\n const pages = [parsed, ...index.pages.filter((entry) => entry.id !== parsed.id)]\n return {\n ...index,\n generatedAt: new Date().toISOString(),\n pages,\n graph: buildKnowledgeGraph(pages),\n }\n })\n }\n\n async getPage(idOrPath: string): Promise<KnowledgePage | null> {\n return withKnowledgeRead(this.root, async () => {\n const index = await this.readIndex()\n return clone(\n index?.pages.find((page) => page.id === idOrPath || page.path === idOrPath) ?? null,\n )\n })\n }\n\n async listPages(): Promise<KnowledgePage[]> {\n return withKnowledgeRead(this.root, async () => clone((await this.readIndex())?.pages ?? []))\n }\n\n async putIndex(index: KnowledgeIndex): Promise<void> {\n const parsed = KnowledgeIndexSchema.parse(index) as KnowledgeIndex\n await withKnowledgeMutation(this.root, () =>\n writeJsonDurableWithinRoot(this.root, this.indexPath, parsed),\n )\n }\n\n async getIndex(): Promise<KnowledgeIndex | null> {\n return withKnowledgeRead(this.root, () => this.readIndex())\n }\n\n async putEvent(event: KnowledgeEvent): Promise<void> {\n const parsed = KnowledgeEventSchema.parse(event) as KnowledgeEvent\n await withKnowledgeMutation(this.root, async () => {\n const current = await this.readEvents()\n const next = [...current.filter((entry) => entry.id !== parsed.id), parsed].sort((a, b) =>\n a.createdAt.localeCompare(b.createdAt),\n )\n await writeJsonDurableWithinRoot(this.root, this.eventsPath, next)\n })\n }\n\n async listEvents(query: KnowledgeEventQuery = {}): Promise<KnowledgeEvent[]> {\n return withKnowledgeRead(this.root, async () => {\n let events = await this.readEvents()\n if (query.type) events = events.filter((event) => event.type === query.type)\n if (query.target) events = events.filter((event) => event.target === query.target)\n return clone(events.slice(-(query.limit ?? events.length)))\n })\n }\n\n async putClaimLedger(ledger: ResearchClaimLedger): Promise<void> {\n const parsed = parseResearchClaimLedger(ledger)\n const path = this.claimLedgerPath(parsed.id)\n await withKnowledgeMutation(this.root, async () => {\n // Refuse to destroy a legacy ledger whose evidence cannot be bound to\n // exact bytes. Reading through the version-aware parser preserves it for\n // an explicit archive-and-reverify migration.\n await readJsonFile(this.root, path, researchClaimLedgerParser)\n await writeJsonDurableWithinRoot(this.root, path, parsed)\n })\n }\n\n async getClaimLedger(id: string): Promise<ResearchClaimLedger | null> {\n const path = this.claimLedgerPath(id)\n return withKnowledgeRead(\n this.root,\n () =>\n readJsonFile(\n this.root,\n path,\n researchClaimLedgerParser,\n ) as Promise<ResearchClaimLedger | null>,\n )\n }\n\n async listClaimLedgers(): Promise<ResearchClaimLedger[]> {\n return withKnowledgeRead(this.root, async () => {\n let files: Awaited<ReturnType<typeof listRegularFilesWithinRoot>>\n try {\n files = await listRegularFilesWithinRoot(this.root, this.claimLedgerDir)\n } catch (error) {\n if (isMissingFile(error)) return []\n throw error\n }\n const ledgers: ResearchClaimLedger[] = []\n for (const file of files) {\n if (!file.path.endsWith('.json')) continue\n ledgers.push(parseResearchClaimLedger(JSON.parse(file.bytes.toString('utf8'))))\n }\n return ledgers.sort((a, b) => a.id.localeCompare(b.id))\n })\n }\n\n async mergeClaimLedger(\n id: string,\n merge: (current: ResearchClaimLedger | null) => ResearchClaimLedger,\n ): Promise<ResearchClaimLedger> {\n const key = assertClaimLedgerId(id)\n // One mutation scope spans the read AND the write, so a second process\n // cannot read the same `current` this one did. `withKnowledgeMutation` is\n // reentrant, so the nested lock inside `putClaimLedger` joins this scope\n // rather than deadlocking against it.\n return withKnowledgeMutation(this.root, async () => {\n const current = (await readJsonFile(\n this.root,\n this.claimLedgerPath(key),\n researchClaimLedgerParser,\n )) as ResearchClaimLedger | null\n const next = assertMergedLedgerId(key, merge(current))\n await this.putClaimLedger(next)\n return next\n })\n }\n\n private async updateIndex(change: (index: KnowledgeIndex) => KnowledgeIndex): Promise<void> {\n await withKnowledgeMutation(this.root, async () => {\n const current = (await this.readIndex()) ?? emptyIndex(this.root)\n const next = KnowledgeIndexSchema.parse(change(current)) as KnowledgeIndex\n await writeJsonDurableWithinRoot(this.root, this.indexPath, next)\n })\n }\n\n private async readIndex(): Promise<KnowledgeIndex | null> {\n return readJsonFile(\n this.root,\n this.indexPath,\n KnowledgeIndexSchema,\n ) as Promise<KnowledgeIndex | null>\n }\n\n private async readEvents(): Promise<KnowledgeEvent[]> {\n return ((await readJsonFile(this.root, this.eventsPath, knowledgeEventsSchema)) ??\n []) as KnowledgeEvent[]\n }\n\n private claimLedgerPath(id: string): string {\n return `${this.claimLedgerDir}/${assertClaimLedgerId(id)}.json`\n }\n}\n\n/**\n * A merge that returns a ledger under a different id would write that ledger to\n * the file the caller asked to merge, giving one file two identities. Refuse\n * rather than trust the merge function to be well behaved.\n */\nfunction assertMergedLedgerId(id: string, merged: ResearchClaimLedger): ResearchClaimLedger {\n if (merged.id !== id) {\n throw new Error(`merge of claim ledger '${id}' returned a ledger with id '${merged.id}'`)\n }\n return merged\n}\n\nfunction emptyIndex(root: string): KnowledgeIndex {\n return {\n root,\n generatedAt: new Date(0).toISOString(),\n sources: [],\n pages: [],\n graph: { nodes: [], edges: [] },\n }\n}\n\nasync function readJsonFile<T>(\n root: string,\n relativePath: string,\n schema: { parse(value: unknown): T },\n): Promise<T | null> {\n try {\n const file = await readRegularFileWithinRoot(root, relativePath)\n return schema.parse(JSON.parse(file.bytes.toString('utf8')))\n } catch (error) {\n if ((error as NodeJS.ErrnoException | null)?.code === 'ENOENT') return null\n throw error\n }\n}\n\nconst researchClaimLedgerParser = {\n parse: parseResearchClaimLedger,\n}\n\nconst legacyResearchClaimLedgerSchema = z\n .object({\n id: z.string().min(1),\n goal: z.string().trim().min(1).optional(),\n updatedAt: z.iso.datetime(),\n rounds: z.number().int().nonnegative(),\n preparedRounds: z.number().int().nonnegative().optional(),\n claimEvidence: z.array(\n z\n .object({\n id: z.string().min(1),\n claimId: z.string().min(1),\n text: z.string().min(1),\n sourceUri: z.string().min(1),\n contradictsClaimId: z.string().min(1).optional(),\n firstSeenRound: z.number().int().nonnegative(),\n })\n .strict(),\n ),\n registeredSourceUris: z.array(z.string().min(1)),\n claims: z.array(\n z\n .object({\n id: z.string().min(1),\n text: z.string().min(1),\n supportingHosts: z.array(z.string().min(1)),\n supportingUris: z.array(z.string().min(1)),\n contradicts: z.array(z.string().min(1)),\n contested: z.boolean(),\n firstSeenRound: z.number().int().nonnegative(),\n })\n .strict(),\n ),\n questions: z.array(DeepQuestionSchema),\n })\n .strict()\n\nfunction parseResearchClaimLedger(value: unknown): ResearchClaimLedger {\n const legacy = legacyResearchClaimLedgerSchema.safeParse(value)\n if (legacy.success) {\n throw new ClaimLedgerMigrationRequiredError(legacy.data.id, 'unversioned')\n }\n if (isRecord(value) && value.schemaVersion !== 2 && 'registeredSourceUris' in value) {\n throw new ClaimLedgerMigrationRequiredError(\n typeof value.id === 'string' ? value.id : 'unknown',\n typeof value.schemaVersion === 'number' ? value.schemaVersion : 'unversioned',\n )\n }\n return ResearchClaimLedgerSchema.parse(value) as ResearchClaimLedger\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction clone<T>(value: T): T {\n return value == null ? value : (JSON.parse(JSON.stringify(value)) as T)\n}\n","import { lstat, readdir, readFile } from 'node:fs/promises'\nimport { basename, join, relative } from 'node:path'\nimport { z } from 'zod'\nimport { type SourceAdapter, textSourceAdapter } from './adapters'\nimport { readRegularFileWithinRoot, writeJsonDurableWithinRoot } from './durable-fs'\nimport { commitKnowledgeFileMutations, type KnowledgeFileMutation } from './file-transaction'\nimport { sha256, slugify, stableId, textSourceId } from './ids'\nimport { withKnowledgeMutation, withKnowledgeRead } from './mutation-lock'\nimport { SourceRecordSchema } from './schemas'\nimport { layoutFor } from './store'\nimport type { SourceRecord, SourceRegistry } from './types'\n\nconst sourceRegistrySchema = z\n .object({\n generatedAt: z.string().min(1),\n sources: z.array(SourceRecordSchema.passthrough()),\n })\n .strict()\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\n/** Copy and freeze an untrusted source proposal before any asynchronous work. */\nexport function snapshotSourceTextInput(input: AddSourceTextInput): AddSourceTextInput {\n return deepFreeze(structuredClone(input))\n}\n\nexport async function loadSourceRegistry(root: string): Promise<SourceRegistry> {\n return withKnowledgeRead(root, () => loadSourceRegistryUnlocked(root))\n}\n\nasync function loadSourceRegistryUnlocked(root: string): Promise<SourceRegistry> {\n try {\n const file = await readRegularFileWithinRoot(root, '.agent-knowledge/sources.json')\n return sourceRegistrySchema.parse(JSON.parse(file.bytes.toString('utf8'))) as SourceRegistry\n } catch (error) {\n if ((error as NodeJS.ErrnoException | null)?.code === 'ENOENT') {\n return { generatedAt: new Date(0).toISOString(), sources: [] }\n }\n throw error\n }\n}\n\nexport async function writeSourceRegistry(root: string, registry: SourceRegistry): Promise<void> {\n await withKnowledgeMutation(root, async () => {\n await writeJsonDurableWithinRoot(\n root,\n '.agent-knowledge/sources.json',\n sourceRegistrySchema.parse(registry),\n )\n })\n}\n\nexport async function addSourcePath(\n root: string,\n sourcePath: string,\n options: AddSourceOptions = {},\n): Promise<SourceRecord[]> {\n const sourceStat = await lstat(sourcePath)\n if (sourceStat.isDirectory()) {\n const files = await listSourceFiles(sourcePath)\n const prepared = await Promise.all(\n files.map((file) => preparePathSource(root, file.path, file.mode, options)),\n )\n return commitSourceBatch(root, prepared, options)\n }\n if (!sourceStat.isFile()) throw new Error(`unsupported source path: ${sourcePath}`)\n\n return commitSourceBatch(\n root,\n [await preparePathSource(root, sourcePath, sourceStat.mode & 0o777, options)],\n options,\n )\n}\n\nasync function preparePathSource(\n root: string,\n sourcePath: string,\n mode: number,\n options: AddSourceOptions,\n): Promise<PreparedSourceImport> {\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 = rawSourcePath(fileName, contentHash, ext(fileName))\n const copyIntoRaw = options.copyIntoRaw ?? true\n\n return {\n record: {\n id,\n uri: copyIntoRaw ? targetRel : sourcePath,\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 mutation: copyIntoRaw ? { path: targetRel, content: bytes, mode } : null,\n purposeParts: [sourcePath, contentHash, copyIntoRaw, mode],\n }\n}\n\nexport async function addSourceText(\n root: string,\n input: AddSourceTextInput,\n options: Pick<AddSourceOptions, 'adapters' | 'now'> = {},\n): Promise<SourceRecord> {\n const snapshot = snapshotSourceTextInput(input)\n const [record] = await commitSourceBatch(\n root,\n [await prepareTextSource(snapshot, options)],\n options,\n )\n return record!\n}\n\nasync function prepareTextSource(\n input: AddSourceTextInput,\n options: Pick<AddSourceOptions, 'adapters' | 'now'>,\n): Promise<PreparedSourceImport> {\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 = textSourceId(input.uri, contentHash)\n const targetRel = rawSourcePath(fileName, contentHash, '.txt')\n const rawContent = text\n\n return {\n record: {\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 ...(input.validUntil === undefined ? {} : { validUntil: input.validUntil }),\n ...(input.lastVerifiedAt === undefined ? {} : { 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 mutation: { path: targetRel, content: rawContent },\n purposeParts: [input.uri, contentHash],\n }\n}\n\ninterface PreparedSourceImport {\n record: SourceRecord\n mutation: KnowledgeFileMutation | null\n purposeParts: readonly unknown[]\n}\n\nasync function commitSourceBatch(\n root: string,\n prepared: readonly PreparedSourceImport[],\n options: Pick<AddSourceOptions, 'now'>,\n): Promise<SourceRecord[]> {\n if (prepared.length === 0) return []\n const purpose = `source-import:${sha256(JSON.stringify(prepared.map((item) => item.purposeParts)))}`\n return withKnowledgeMutation(\n root,\n async (lock) => {\n const existing = await loadSourceRegistry(root)\n const records = uniqueSources(prepared.map((item) => item.record))\n const next = sourceRegistrySchema.parse({\n generatedAt: (options.now ?? (() => new Date()))().toISOString(),\n sources: [\n ...records,\n ...existing.sources.filter(\n (source) => !records.some((record) => record.id === source.id),\n ),\n ],\n }) as SourceRegistry\n await commitKnowledgeFileMutations({\n root,\n transactionRoot: lock.transactionRoot,\n purpose,\n mutations: [\n ...uniqueMutations(prepared.flatMap((item) => (item.mutation ? [item.mutation] : []))),\n {\n path: relative(root, sourceRegistryPath(root)).replace(/\\\\/g, '/'),\n content: `${JSON.stringify(next, null, 2)}\\n`,\n },\n ],\n assertOwned: lock.assertOwned,\n })\n return records\n },\n { resumeTransaction: { purpose } },\n )\n}\n\nexport function sourceRegistryPath(root: string): string {\n return join(layoutFor(root).cacheDir, 'sources.json')\n}\n\nfunction uniqueSources(records: readonly SourceRecord[]): SourceRecord[] {\n const byId = new Map<string, SourceRecord>()\n for (const record of records) byId.set(record.id, record)\n return [...byId.values()]\n}\n\nfunction uniqueMutations(mutations: readonly KnowledgeFileMutation[]): KnowledgeFileMutation[] {\n const byPath = new Map<string, KnowledgeFileMutation>()\n for (const mutation of mutations) {\n const existing = byPath.get(mutation.path)\n if (existing && !sameMutation(existing, mutation)) {\n throw new Error(`source import produced conflicting raw path: ${mutation.path}`)\n }\n byPath.set(mutation.path, mutation)\n }\n return [...byPath.values()]\n}\n\nfunction sameMutation(left: KnowledgeFileMutation, right: KnowledgeFileMutation): boolean {\n if (left.mode !== right.mode) return false\n if (Buffer.isBuffer(left.content) && Buffer.isBuffer(right.content)) {\n return left.content.equals(right.content)\n }\n return left.content === right.content\n}\n\nfunction deepFreeze<T>(value: T, seen = new WeakSet<object>()): T {\n if (typeof value !== 'object' || value === null || seen.has(value)) return value\n seen.add(value)\n for (const nested of Object.values(value)) deepFreeze(nested, seen)\n return Object.freeze(value)\n}\n\nasync function listSourceFiles(root: string): Promise<Array<{ path: string; mode: number }>> {\n const entries = await readdir(root, { withFileTypes: true })\n const out: Array<{ path: string; mode: number }> = []\n for (const entry of entries) {\n const full = join(root, entry.name)\n const entryStat = await lstat(full)\n if (entryStat.isDirectory()) out.push(...(await listSourceFiles(full)))\n else if (entryStat.isFile()) out.push({ path: full, mode: entryStat.mode & 0o777 })\n else throw new Error(`unsupported directory entry in source import: ${full}`)\n }\n return out\n}\n\nfunction rawSourcePath(fileName: string, contentHash: string, extension: string): string {\n return join(\n 'raw',\n 'sources',\n `${slugify(fileName.replace(/\\.[^.]+$/, ''))}-${contentHash}${extension}`,\n ).replace(/\\\\/g, '/')\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 { buildKnowledgeGraph } from './graph'\nimport { FileSystemKbStore } from './kb-store'\nimport { withKnowledgeMutation, withKnowledgeRead } from './mutation-lock'\nimport { loadSourceRegistry } from './sources'\nimport { loadKnowledgePages } from './store'\nimport type { KnowledgeIndex } from './types'\n\nexport async function buildKnowledgeIndex(root: string): Promise<KnowledgeIndex> {\n return withKnowledgeRead(root, () => buildKnowledgeIndexUnlocked(root))\n}\n\nasync function buildKnowledgeIndexUnlocked(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\n/**\n * Build the index from the knowledge tree and store it.\n *\n * The write goes through `FileSystemKbStore` rather than straight to disk: this\n * function and the store used to write two different index files in two\n * different places, so a knowledge base could hold two disagreeing indexes and\n * a store-based reader saw none of the indexer's work. One writer now, and it\n * validates through `KnowledgeIndexSchema` on the way out.\n */\nexport async function writeKnowledgeIndex(root: string): Promise<KnowledgeIndex> {\n return withKnowledgeMutation(root, async () => {\n const index = await buildKnowledgeIndexUnlocked(root)\n await new FileSystemKbStore({ root }).putIndex(index)\n return index\n })\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","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","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 { readFile } from 'node:fs/promises'\nimport { contentHash } from '@tangle-network/agent-eval'\nimport { commitKnowledgeFileMutations } from './file-transaction'\nimport { withKnowledgeMutation } from './mutation-lock'\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 purpose = `knowledge-proposal:${contentHash(parsed.blocks)}`\n return withKnowledgeMutation(\n root,\n async (lock) => {\n if (parsed.blocks.length > 0) {\n await commitKnowledgeFileMutations({\n root,\n transactionRoot: lock.transactionRoot,\n purpose,\n mutations: parsed.blocks.map((block) => ({\n path: block.path,\n content: block.content.endsWith('\\n') ? block.content : `${block.content}\\n`,\n })),\n assertOwned: lock.assertOwned,\n })\n }\n return { written: parsed.blocks.map((block) => block.path), warnings: parsed.warnings }\n },\n { resumeTransaction: { purpose } },\n )\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","/**\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"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"search-CP0QtBJZ.js","names":[],"sources":["../src/search.ts"],"sourcesContent":["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"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types-BOfmvDe-.d.ts","names":[],"sources":["../src/types.ts"],"mappings":";KAAY;UAEK;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,WAAW;;UAGI;EACf,IAAI;EACJ;EACA;EACA;EACA;EACA;EACA,UAAU;;EAEV;;EAEA;EACA,WAAW;EACX;;UAGe;EACf;EACA,SAAS;;UAGM;EACf;EACA;EACA;;UAGe;EACf,IAAI;EACJ;EACA,MAAM;EACN;EACA;EACA,WAAW;;UAGI;EACf,UAAU;EACV,UAAU;EACV;EACA;EACA,WAAW;;UAGI;EACf,IAAI;EACJ;EACA;EACA,SAAS;EACT,YAAY;EACZ;EACA;EACA,WAAW;EACX;;UAGe;EACf,IAAI;EACJ;EACA;EACA;EACA,aAAa;EACb;EACA;EACA;;UAGe;EACf,IAAI;EACJ;EACA;EACA;EACA;EACA;EACA;;UAGe;EACf,QAAQ;EACR,QAAQ;EACR;EACA;;UAGe;EACf,OAAO;EACP,OAAO;;UAGQ;EACf;EACA;EACA,SAAS;EACT,OAAO;EACP,OAAO;;UAGQ;EACf,MAAM;;;;;;;EAON;;EAEA;;;;;;;;EAQA;EACA;EACA;EACA;;UAGe;EACf;EAUA;EACA;EACA;EACA,WAAW;;UAGI;EACf;EACA;EACA;EACA;EACA,WAAW;;UAGI;EACf,IAAI;EACJ,OAAO;EACP;EACA;EACA;EACA;EACA,WAAW;;UAGI;EACf;EACA;;UAGe;EACf,QAAQ;EACR;;;;;;;;;;cAWW;KAWD,6BAA6B;UAExB;EACf;EACA,MAAM;EACN;EACA;EACA;EACA,WAAW;;;KAID;;;;;;;;;UAUK;EACf,MAAM;EACN;;EAEA;;EAEA;;EAEA;;EAEA;;;UAIe;EACf;;EAEA;;EAEA,iBAAiB;;EAEjB;;EAEA,aAAa;;;;;;EAMb;EACA;;;;;;;;;UAUe;EACf;EACA;EACA;EACA;EACA;EACA;EACA;;;UAIe;;EAEf,UAAU;;EAEV;;EAEA;;;;;;;;;;;UAYe;;EAEf;EACA;EACA;;EAEA,UAAU;EACV;;EAEA;;EAEA;EACA;;;;;;;;;;UAWe;;EAEf;EACA;;EAEA;;EAEA;;EAEA;;;;;EAKA;;;;;EAKA,eAAe;;EAEf,mBAAmB;EACnB,QAAQ;EACR,WAAW;;UAGI;EACf;EACA;EACA;EACA;EACA;EACA;EACA,WAAW"}
|