@tangle-network/agent-knowledge 17.0.1 → 17.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/README.md +8 -1
- package/dist/benchmarks/index.js +1 -1
- package/dist/{benchmarks-BbPJdmHe.js → benchmarks-B3kU-Yxz.js} +2 -2
- package/dist/{benchmarks-BbPJdmHe.js.map → benchmarks-B3kU-Yxz.js.map} +1 -1
- package/dist/cli.js +2 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +62 -21
- package/dist/index.js.map +1 -1
- package/dist/{inspect-Dn7xCZLn.js → inspect-DrJnvx5Z.js} +27 -4
- package/dist/inspect-DrJnvx5Z.js.map +1 -0
- package/dist/memory/index.js +2 -2
- package/dist/{memory-ce9n5O24.js → memory-Bn1Xs1hY.js} +2 -2
- package/dist/{memory-ce9n5O24.js.map → memory-Bn1Xs1hY.js.map} +1 -1
- package/dist/{search-Cw6eYfSd.js → search-Cbyj2shJ.js} +16 -11
- package/dist/search-Cbyj2shJ.js.map +1 -0
- package/docs/run-scoped-citations.md +30 -0
- package/package.json +2 -2
- package/dist/inspect-Dn7xCZLn.js.map +0 -1
- package/dist/search-Cw6eYfSd.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"inspect-Dn7xCZLn.js","names":["mediaTypeFor"],"sources":["../src/adapters.ts","../src/durable-fs.ts","../src/pages-directory.ts","../src/file-transaction.ts","../src/mutation-lock.ts","../src/frontmatter.ts","../src/claim-ledger.ts","../src/types.ts","../src/schemas.ts","../src/wikilinks.ts","../src/store.ts","../src/citation-resolution.ts","../src/graph.ts","../src/kb-store.ts","../src/sources.ts","../src/indexer.ts","../src/claim-evidence.ts","../src/lint.ts","../src/validate.ts","../src/rag-eval/near-duplicates.ts","../src/run-scoped.ts","../src/write-intake.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, join, relative, 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\n/**\n * The path from `root` down to `candidate`, or undefined when `candidate` is not\n * strictly inside `root`.\n *\n * The comparison is lexical, so both arguments must already share one\n * canonicalization basis. Use `canonicalRelativeWithinRoot` when either side can\n * carry a different basis.\n *\n * An empty result means the two paths are equal. A root is not inside itself,\n * and a caller that treats it as a descendant would hand its own root to\n * machinery that may remove the directory it is given.\n */\nexport function relativeWithinRoot(root: string, candidate: string): string | undefined {\n const value = relative(resolve(root), resolve(candidate)).replace(/\\\\/g, '/')\n if (value === '' || value === '..' || value.startsWith('../') || isAbsolute(value)) {\n return undefined\n }\n return value\n}\n\n/**\n * The path from `root` down to `candidate`, with both sides canonicalized before\n * they are compared.\n *\n * `resolve` is lexical: it cannot read a symbolic link, so a path that has been\n * through `realpath` and one that has not describe the same directory with\n * different strings, and comparing the two rejects a directory that genuinely\n * sits inside the root. `openSafeDirectoryTree` canonicalizes the root it opens,\n * so any path that reaches a caller through `withSafeDirectory` carries the\n * canonical form while a path the caller built itself does not.\n *\n * Canonicalizing both sides also tightens the boundary: a candidate that leaves\n * the root through a symbolic link is rejected here, where a lexical comparison\n * admits it.\n *\n * Neither path has to exist. The deepest existing ancestor of each is\n * canonicalized and the remaining segments are appended, so a directory that is\n * about to be created is measured against the same root as one that already is.\n */\nexport async function canonicalRelativeWithinRoot(\n root: string,\n candidate: string,\n): Promise<string | undefined> {\n const canonicalRoot = isKernelAnchoredPath(root) ? root : await canonicalizeThroughMissing(root)\n const canonicalCandidate = isKernelAnchoredPath(candidate)\n ? candidate\n : await canonicalizeThroughMissing(candidate)\n return relativeWithinRoot(canonicalRoot, canonicalCandidate)\n}\n\n/**\n * Whether two paths name the same location, with both sides canonicalized first.\n *\n * A path stored by one caller and a path supplied by another reach this\n * comparison through different routes, so the same location can arrive under two\n * spellings. Comparing the resolved strings reports a mismatch that does not\n * exist.\n */\nexport async function canonicalPathsEqual(left: string, right: string): Promise<boolean> {\n const [canonicalLeft, canonicalRight] = await Promise.all([\n isKernelAnchoredPath(left) ? left : canonicalizeThroughMissing(left),\n isKernelAnchoredPath(right) ? right : canonicalizeThroughMissing(right),\n ])\n return canonicalLeft === canonicalRight\n}\n\n/** The canonical form of a path whose trailing segments may not exist yet. */\nasync function canonicalizeThroughMissing(path: string): Promise<string> {\n const missing: string[] = []\n let current = resolve(path)\n for (;;) {\n try {\n const existing = await realpath(current)\n return missing.length === 0 ? existing : join(existing, ...missing.reverse())\n } catch (error) {\n if (!isMissingFile(error)) throw error\n const parent = dirname(current)\n if (parent === current) throw error\n missing.push(basename(current))\n current = parent\n }\n }\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","/** Root-relative directory that holds Markdown pages when a caller names none. */\nexport const DEFAULT_PAGES_DIRECTORY = 'knowledge'\n\n/**\n * Selects the root-relative directory that holds Markdown pages.\n *\n * The same option drives the reader, the indexer, the search provider, the\n * run-scoped chain, and the write protocol, so a store laid out as\n * `kb/pages/<line>/` is read and written through one value.\n */\nexport interface KnowledgePagesOptions {\n /** Root-relative directory that holds Markdown pages. Defaults to `knowledge`. */\n pagesDirectory?: string\n}\n\n/**\n * Validate a pages directory and return its canonical root-relative form.\n *\n * The result is a write allowlist prefix as well as a read location, so the\n * check refuses every value that could reach outside the pages tree: absolute\n * paths, drive letters, `..` or `.` segments, empty segments, control\n * characters, and the package-owned `.agent-knowledge` and `raw` trees.\n */\nexport function normalizePagesDirectory(value: string = DEFAULT_PAGES_DIRECTORY): string {\n if (typeof value !== 'string') throw new Error('pagesDirectory must be a string')\n const normalized = value.replace(/\\\\/g, '/').replace(/^\\.\\//, '').replace(/\\/+$/, '')\n if (normalized.length === 0 || normalized === '.') {\n throw new Error('pagesDirectory must name a root-relative directory')\n }\n // Built via String.fromCharCode so biome's control-character regex rule\n // does not flag an inline escape.\n const controlRange = new RegExp(`[${String.fromCharCode(0)}-${String.fromCharCode(0x1f)}]`)\n if (controlRange.test(normalized)) {\n throw new Error('pagesDirectory must not contain control characters')\n }\n if (normalized.startsWith('/') || /^[A-Za-z]:/.test(normalized)) {\n throw new Error(`pagesDirectory must be root-relative, not absolute: ${value}`)\n }\n const segments = normalized.split('/')\n if (segments.some((segment) => segment === '' || segment === '.' || segment === '..')) {\n throw new Error(`pagesDirectory must not contain empty or dot segments: ${value}`)\n }\n if (segments[0] === '.agent-knowledge' || segments[0] === 'raw') {\n throw new Error(`pagesDirectory must not name the package-owned ${segments[0]} tree: ${value}`)\n }\n return normalized\n}\n","import { createHash, randomUUID } from 'node:crypto'\nimport { mkdtemp, readdir, rm } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { contentHash } from '@tangle-network/agent-eval'\nimport { z } from 'zod'\nimport {\n canonicalRelativeWithinRoot,\n isKernelAnchoredPath,\n isMissingFile,\n readRegularFileNoFollow,\n removeDurable,\n renameDurable,\n syncDirectory,\n withSafeDescendant,\n withSafeDirectory,\n writeFileDurable,\n writeJsonDurable,\n} from './durable-fs'\nimport { normalizePagesDirectory } from './pages-directory'\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 SOURCE_REGISTRY_PATH = '.agent-knowledge/sources.json'\n/**\n * A journal states the pages directory it was prepared under, already in\n * canonical form, so replay and recovery enforce the same allowlist as the\n * prepare step without any caller-supplied value.\n */\nconst pagesDirectorySchema = z.string().superRefine((value, context) => {\n try {\n if (normalizePagesDirectory(value) !== value) {\n context.addIssue({ code: 'custom', message: 'pagesDirectory is not in canonical form' })\n }\n } catch (error) {\n context.addIssue({\n code: 'custom',\n message: error instanceof Error ? error.message : String(error),\n })\n }\n})\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 pagesDirectory: pagesDirectorySchema.optional(),\n researchState: z.boolean().optional(),\n retainHistory: z.boolean().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 pagesDirectory: string,\n researchState = false,\n): string {\n const normalized = entries\n .map((entry) => normalizePlanEntry(entry, pagesDirectory, researchState))\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 /** Pages directory the mutations may write under; defaults to `knowledge`. */\n pagesDirectory?: string\n /** Explicitly permit authoritative claim-ledger and research-event records. */\n researchState?: boolean\n /** Preserve terminal before/after bytes in the root's write history. */\n retainHistory?: boolean\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 const pagesDirectory =\n input.pagesDirectory === undefined ? undefined : normalizePagesDirectory(input.pagesDirectory)\n // The record keeps the caller's choice, absent when they took the default, so the\n // stored transaction shape is unchanged. Validation always needs a real directory.\n const boundPagesDirectory = normalizePagesDirectory(input.pagesDirectory)\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(\n mutation.path,\n boundPagesDirectory,\n input.researchState,\n )\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 ...(pagesDirectory === undefined ? {} : { pagesDirectory }),\n ...(input.researchState === undefined ? {} : { researchState: input.researchState }),\n ...(input.retainHistory === undefined ? {} : { retainHistory: input.retainHistory }),\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 /** Pages directory the mutations may write under; defaults to `knowledge`. */\n pagesDirectory?: string\n /** Explicitly permit authoritative claim-ledger and research-event records. */\n researchState?: boolean\n retainHistory?: boolean\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 ...(input.researchState === undefined ? {} : { researchState: input.researchState }),\n ...(input.retainHistory === undefined ? {} : { retainHistory: input.retainHistory }),\n ...(input.pagesDirectory === undefined ? {} : { pagesDirectory: input.pagesDirectory }),\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 // A lost acknowledgement after the atomic archive move must not repeat a completed write.\n if (\n transaction.retainHistory === true &&\n !(await activeTransactionDirectoryNames(transactionRoot)).includes(activeName) &&\n (await hasRetainedTransaction(input.root, transaction))\n ) {\n await syncDirectory(transactionRoot)\n return\n }\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 if (transaction.retainHistory === true) {\n // Resolve from the store root: transactionRoot may be an open /proc/self/fd anchor.\n await withSafeDirectory(input.root, '.agent-knowledge/history', true, async (historyRoot) => {\n await renameDurable(\n join(transactionRoot, activeName),\n join(historyRoot, transaction.transactionId),\n )\n })\n } else {\n await rm(join(transactionRoot, activeName), { recursive: true, force: false })\n }\n await syncDirectory(transactionRoot)\n })\n}\n\nasync function hasRetainedTransaction(\n root: string,\n transaction: KnowledgeFileTransaction,\n): Promise<boolean> {\n try {\n return await withSafeDirectory(\n root,\n `.agent-knowledge/history/${transaction.transactionId}`,\n false,\n async (historyDir) => {\n await assertActiveTransaction(historyDir, transaction)\n await readTransactionDirection(historyDir, transaction)\n for (const entry of transaction.entries) {\n for (const side of ['before', 'after'] as const) {\n const expected = side === 'before' ? entry.beforeHash : entry.afterHash\n if (expected === null) continue\n const snapshot = await readRegularFileNoFollow(\n snapshotPath(historyDir, side, entry.index),\n )\n if (hashBytes(snapshot.bytes) !== expected)\n throw new Error(`retained knowledge snapshot changed: ${entry.path}`)\n }\n }\n await syncDirectory(historyDir)\n return true\n },\n )\n } catch (error) {\n if (isMissingFile(error)) return false\n throw error\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 within = await canonicalRelativeWithinRoot(root, transactionRoot)\n if (within === undefined) {\n throw new Error('knowledge transaction directory escaped its root')\n }\n return withSafeDirectory(root, within, create, use)\n}\n\nfunction assertTransactionEntries(transaction: KnowledgeFileTransaction): void {\n const indexes = new Set<number>()\n const paths = new Set<string>()\n const boundPagesDirectory = normalizePagesDirectory(transaction.pagesDirectory)\n for (const entry of transaction.entries) {\n const normalized = assertKnowledgeMutationPath(\n entry.path,\n boundPagesDirectory,\n transaction.researchState,\n )\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(\n entry: KnowledgeFileTransactionPlanEntry,\n pagesDirectory: string,\n researchState: boolean,\n) {\n const path = assertKnowledgeMutationPath(entry.path, pagesDirectory, researchState)\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\n/**\n * Root-relative prefixes a knowledge transaction may write under. The pages\n * directory is the only caller-selected member; the source registry file and\n * the `raw/` evidence tree are package-owned and always present.\n *\n * The pages directory is stated rather than defaulted. A store laid out under\n * `kb/pages/` is checked against a different allowlist from one laid out under\n * `knowledge/`, so a caller that omits it is not asking for a safe default: it\n * is asking for someone else's allowlist. Pass `DEFAULT_PAGES_DIRECTORY` where\n * the default is the deliberate answer.\n */\nexport function knowledgeMutationPathPrefixes(pagesDirectory: string): readonly string[] {\n return [`${normalizePagesDirectory(pagesDirectory)}/`, 'raw/']\n}\n\nexport function assertKnowledgeMutationPath(\n path: string,\n pagesDirectory: string,\n researchState = false,\n): string {\n const normalized = normalizeTransactionPath(path)\n if (\n normalized === SOURCE_REGISTRY_PATH ||\n (researchState &&\n (normalized === '.agent-knowledge/events.json' ||\n /^\\.agent-knowledge\\/claim-ledgers\\/[^/]+\\.json$/.test(normalized))) ||\n knowledgeMutationPathPrefixes(pagesDirectory).some((prefix) => normalized.startsWith(prefix))\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 /**\n * How long a lock may go without a heartbeat before another taker treats it as abandoned.\n * Defaults to 15 minutes, and is floored at 5 seconds. The holder heartbeats at a third of this\n * window, so the window is also the bound on how long a crashed holder wedges every other\n * writer: a process that dies mid-write blocks the next one for up to `staleMs`.\n *\n * The default is sized for a knowledge-improvement run that holds the lock across agent turns.\n * A consumer whose holds are short should say so and take the shorter wedge — measured holds of\n * this lock are 9 ms for one page, 586 ms for a 50-page batch, and about 390 ms for the longest\n * promotion in the largest store, against a 900 s default.\n */\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\n/**\n * A store lock over a knowledge root that a caller took by its own path, and the one question\n * this package asks of it.\n *\n * A consumer that batches its own writes around a read-modify-write takes the lock itself and\n * then needs to call this package inside that window. It supplies the hold; this package supplies\n * the scope, so a nested `withKnowledgeMutation` on the same root runs inline instead of blocking\n * against a lock the caller already owns.\n */\nexport interface KnowledgeMutationHold {\n /**\n * Throw when the lock is no longer owned. Every mutation asks before it begins and again after\n * it returns, so a lock lost to a stale-timeout takeover stops the write rather than letting it\n * land under a lock somebody else now holds.\n */\n assertOwned(): void\n}\n\n/**\n * Whether the current async context already holds the store lock for `root`.\n *\n * A caller that must decide between taking the lock and joining the one it is inside reads this\n * rather than guessing; taking a held lock from inside its own scope would block against itself.\n */\nexport function isKnowledgeMutationHeld(root: string): boolean {\n return activeRoots.getStore()?.get(resolve(root))?.active === true\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 existing = activeRoots.getStore()?.get(resolvedRoot)\n if (existing?.active) return await runInlineMutation(existing.lock, mutate)\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 try {\n return await runOwnedMutation(resolvedRoot, cacheDir, acquired, options, mutate)\n } finally {\n await acquired.release()\n }\n })\n}\n\n/**\n * Run `body` inside this package's mutation scope for `root`, on a lock the caller already holds.\n *\n * The caller owns acquiring and releasing that lock; this package owns the scope, the file\n * transaction it opens, and the epoch a concurrent reader watches. Inside `body`, every\n * lock-taking function in this package sees the root as held and runs inline, which is what makes\n * a consumer's own read-modify-write composable with this package instead of exclusive of it.\n *\n * The hold is asked `assertOwned()` at the same points a lock this package acquired is asked, so\n * an externally held lock carries the same guarantee and not a weaker one. Entering a scope for a\n * lock the caller does not actually hold is the one way to defeat the store's single-writer rule;\n * the hold is required, rather than assumed, so that is a statement the caller has to make.\n */\nexport async function runInKnowledgeMutationScope<T>(\n root: string,\n hold: KnowledgeMutationHold,\n body: (lock: KnowledgeMutationLock) => Promise<T> | T,\n options: KnowledgeMutationOptions = {},\n): Promise<T> {\n const resolvedRoot = resolve(root)\n const existing = activeRoots.getStore()?.get(resolvedRoot)\n if (existing?.active) return await runInlineMutation(existing.lock, body)\n\n return withSafeDirectory(resolvedRoot, '.agent-knowledge', true, (cacheDir) =>\n runOwnedMutation(resolvedRoot, cacheDir, hold, options, body),\n )\n}\n\n/** The reentrant path: the root is already held in this async context, so no lock is taken. */\nasync function runInlineMutation<T>(\n lock: KnowledgeMutationLock,\n mutate: (lock: KnowledgeMutationLock) => Promise<T> | T,\n): Promise<T> {\n lock.assertOwned()\n const result = await mutate(lock)\n lock.assertOwned()\n return result\n}\n\n/** The owning path, shared by a lock this package acquired and a lock the caller supplies. */\nasync function runOwnedMutation<T>(\n resolvedRoot: string,\n cacheDir: string,\n hold: KnowledgeMutationHold,\n options: KnowledgeMutationOptions,\n mutate: (lock: KnowledgeMutationLock) => Promise<T> | T,\n): Promise<T> {\n let recovery: KnowledgeMutationRecovery | undefined\n const mutationLock: KnowledgeMutationLock = {\n transactionRoot: join(cacheDir, 'file-transactions'),\n get recovery() {\n return recovery\n },\n assertOwned: () => hold.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(activeRoots.getStore())\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: mutationLock.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 }\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: unknown[] = []\n while (i + 1 < lines.length) {\n const item = /^\\s*-\\s*(.+?)\\s*$/.exec(lines[i + 1]!)\n if (!item) break\n items.push(parseYamlScalar(item[1]!))\n i++\n }\n out[key] = items\n continue\n }\n out[key] = parseYamlScalar(rest)\n }\n return out\n}\n\nfunction parseYamlScalar(value: string): unknown {\n const trimmed = value.trim()\n if (\n (trimmed.startsWith('\"') && trimmed.endsWith('\"')) ||\n (trimmed.startsWith('[') && trimmed.endsWith(']')) ||\n (trimmed.startsWith('{') && trimmed.endsWith('}'))\n ) {\n try {\n return JSON.parse(trimmed)\n } catch {\n // The accepted frontmatter syntax predates JSON-aware parsing. Keep reading\n // non-JSON quoted and bracketed values with the original scalar rules.\n }\n }\n if (trimmed.startsWith('[') && trimmed.endsWith(']')) {\n return trimmed\n .slice(1, -1)\n .split(',')\n .map((part) => unquote(part.trim()))\n .filter(Boolean)\n }\n if (trimmed === 'true' || trimmed === 'false') return trimmed === 'true'\n if (/^-?\\d+(?:\\.\\d+)?$/.test(trimmed)) return Number(trimmed)\n return unquote(trimmed)\n}\n\nfunction formatYamlField(key: string, value: unknown): string[] {\n if (Array.isArray(value)) {\n return [`${key}:`, ...value.map((item) => ` - ${formatYamlScalar(item)}`)]\n }\n return [`${key}: ${formatYamlScalar(value)}`]\n}\n\nfunction formatYamlScalar(value: unknown): string {\n if (typeof value === 'string') {\n return stringNeedsJsonEncoding(value) ? JSON.stringify(value) : value\n }\n if (typeof value === 'number' || typeof value === 'boolean') return String(value)\n const encoded = JSON.stringify(value)\n if (encoded === undefined) {\n throw new TypeError(`frontmatter value of type ${typeof value} is not JSON-serializable`)\n }\n return encoded\n}\n\nfunction stringNeedsJsonEncoding(value: string): boolean {\n if (value.length === 0 || value !== value.trim()) return true\n if (value.includes('\\n') || value.includes('\\r')) return true\n if (value === 'true' || value === 'false' || /^-?\\d+(?:\\.\\d+)?$/.test(value)) return true\n return /^[[{\"']/.test(value) || /[\"']$/.test(value)\n}\n\n/**\n * Strip a MATCHED surrounding quote pair, and nothing else.\n *\n * The previous rule stripped a leading or a trailing quote independently, so a bare scalar that\n * merely ended in one lost its last character: `check: python3 -c \"print(1)\"` read back as\n * `python3 -c \"print(1)` — an unterminated shell quote that no longer runs. Measured on one\n * corpus, 1,378 of 3,655 pages carried that shape, 1,376 of them in a `check` field.\n *\n * `formatYamlScalar` already refuses to WRITE the shape (`stringNeedsJsonEncoding` returns true\n * for a value matching /[\"']$/), so no page this writer produced was ever affected; the loss fell\n * on frontmatter written by any other hand.\n */\nfunction unquote(value: string): string {\n if (value.length < 2) return value\n const first = value[0]\n if ((first === '\"' || first === \"'\") && value.endsWith(first)) return value.slice(1, -1)\n return value\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\n/** A caller-declared vertex of a labeled relation graph. */\nexport interface KnowledgeRelationNode {\n id: KnowledgeId\n /** Caller vocabulary, such as `run`, `claim`, `page`, or `model`. */\n kind: string\n label?: string\n metadata?: Record<string, unknown>\n}\n\n/** A labeled multi-edge graph with one edge per `(sourceId, targetId, predicate)`. */\nexport interface KnowledgeRelationGraph {\n /** Declared nodes in declaration order; empty when the graph was built from relations alone. */\n nodes: KnowledgeRelationNode[]\n edges: KnowledgeRelation[]\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\n/**\n * A page that its own independently executed evidence has refuted.\n *\n * This is deliberately asymmetric. A competing page can remain live while this\n * page is dead because the check recorded on this page contradicted it. An\n * unresolved disagreement belongs in the claim ledger's symmetric `contested`\n * relation instead and must not be encoded as an invalidation.\n */\nexport interface KnowledgePageInvalidation {\n verdict: 'contradicted'\n observedAt: string\n reason: string\n evidencePath?: string\n grader?: string\n metadata?: Record<string, unknown>\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 /** Stable page ids this page explicitly builds on. */\n cites?: KnowledgeId[]\n /** Page ids this page explicitly refutes. */\n contradicts?: KnowledgeId[]\n /** Present only when this page's own evidence has refuted the page. */\n invalidation?: KnowledgePageInvalidation\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 | 'broken-citation'\n | 'ambiguous-citation'\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 | 'ungradeable-evidence'\n | 'missing-evidence-path'\n | 'nonportable-evidence'\n | 'broken-contradiction'\n | 'invalid-invalidation'\n | 'cites-invalidated'\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 KnowledgePageInvalidationSchema = z\n .object({\n verdict: z.literal('contradicted'),\n observedAt: z.iso.datetime(),\n reason: z.string().trim().min(1),\n evidencePath: z.string().trim().min(1).optional(),\n grader: z.string().trim().min(1).optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n })\n .strict()\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 cites: z.array(z.string().min(1)).optional(),\n contradicts: z.array(z.string().min(1)).optional(),\n invalidation: KnowledgePageInvalidationSchema.optional(),\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 KnowledgeRelationSchema = 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\nexport const KnowledgeRelationNodeSchema = z.object({\n id: z.string(),\n kind: z.string(),\n label: z.string().optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n})\n\nexport const KnowledgeRelationGraphSchema = z.object({\n nodes: z.array(KnowledgeRelationNodeSchema),\n edges: z.array(KnowledgeRelationSchema),\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.array(KnowledgeRelationSchema).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","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 KnowledgePagesOptions, normalizePagesDirectory } from './pages-directory'\nimport { KnowledgePageInvalidationSchema } from './schemas'\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(\n root: string,\n options: KnowledgePagesOptions = {},\n): Promise<KnowledgePage[]> {\n return withKnowledgeRead(root, () => loadKnowledgePagesUnlocked(root, options))\n}\n\nasync function loadKnowledgePagesUnlocked(\n root: string,\n options: KnowledgePagesOptions,\n): Promise<KnowledgePage[]> {\n const pagesDirectory = normalizePagesDirectory(options.pagesDirectory)\n let files: Awaited<ReturnType<typeof listRegularFilesWithinRoot>>\n try {\n files = await listRegularFilesWithinRoot(root, pagesDirectory)\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.replace(/\\\\/g, '/')\n if (!isKnowledgePagePath(rel)) continue\n pages.push(knowledgePageFromMarkdown(rel, file.bytes.toString('utf8'), pagesDirectory))\n }\n pages.sort((a, b) => a.path.localeCompare(b.path))\n return pages\n}\n\n/** True when a root-relative path names authored Markdown rather than scaffolding. */\nexport function isKnowledgePagePath(path: string): boolean {\n const normalized = path.replace(/\\\\/g, '/')\n return normalized.endsWith('.md') && !isScaffoldPath(normalized)\n}\n\n/**\n * Build a page from the bytes of one Markdown file.\n *\n * The reader and every gate that inspects a page before it is written share\n * this constructor, so what a gate judges is exactly what the store loads back.\n */\nexport function knowledgePageFromMarkdown(\n path: string,\n content: string,\n pagesDirectory?: string,\n): KnowledgePage {\n const rel = path.replace(/\\\\/g, '/')\n const pagesPrefix = `${normalizePagesDirectory(pagesDirectory)}/`\n const { frontmatter, body } = parseFrontmatter(content)\n const title =\n stringField(frontmatter.title) ??\n firstHeading(body) ??\n rel.split('/').pop()!.replace(/\\.md$/, '')\n const cites = idListField(frontmatter.cites)\n const contradicts = idListField(frontmatter.contradicts)\n const invalidation = KnowledgePageInvalidationSchema.safeParse(frontmatter.invalidation)\n const pageRelativePath = rel.startsWith(pagesPrefix) ? rel.slice(pagesPrefix.length) : rel\n return {\n id: stringField(frontmatter.id) ?? slugify(pageRelativePath.replace(/\\.md$/, '')),\n path: rel,\n title,\n text: body,\n frontmatter,\n sourceIds: arrayField(frontmatter.sources),\n tags: arrayField(frontmatter.tags),\n outLinks: extractWikilinks(body).map(normalizeLinkTarget),\n ...(cites.length > 0 ? { cites } : {}),\n ...(contradicts.length > 0 ? { contradicts } : {}),\n ...(invalidation.success ? { invalidation: invalidation.data } : {}),\n }\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 idListField(value: unknown): string[] {\n const values = typeof value === 'string' ? [value] : arrayField(value)\n return [...new Set(values.map((item) => item.trim()).filter(Boolean))]\n}\n\nfunction firstHeading(body: string): string | undefined {\n return /^#\\s+(.+)$/m.exec(body)?.[1]?.trim()\n}\n","import type { OriginatedPage, PageOrigin, RunScopedStores } from './run-scoped'\nimport type { KnowledgeId, KnowledgePage } from './types'\n\n/**\n * A citation into the knowledge visible to one run.\n *\n * An unqualified reference is accepted only when exactly one visible page has\n * the requested id. Callers can qualify a reference by origin when a current,\n * inherited, or shared page intentionally reuses the same stable id.\n */\nexport interface KnowledgeCitationReference {\n readonly pageId: KnowledgeId\n readonly origin?: PageOrigin\n}\n\nexport interface KnowledgeCitationCandidate {\n readonly pageId: KnowledgeId\n readonly origin: PageOrigin\n readonly page: KnowledgePage\n}\n\nexport type KnowledgeCitationResolutionStatus = 'resolved' | 'missing' | 'ambiguous'\n\nexport interface KnowledgeCitationResolution {\n readonly reference: KnowledgeCitationReference\n readonly status: KnowledgeCitationResolutionStatus\n readonly candidates: readonly KnowledgeCitationCandidate[]\n readonly resolved?: KnowledgeCitationCandidate\n}\n\nexport type KnowledgeCitationAuditIssueKind = 'self' | 'missing' | 'ambiguous'\n\nexport interface KnowledgeCitationAuditIssue {\n readonly kind: KnowledgeCitationAuditIssueKind\n readonly sourcePageId: KnowledgeId\n readonly sourcePath: string\n readonly sourceOrigin: PageOrigin\n readonly persistedCitation: string\n readonly reference: KnowledgeCitationReference\n readonly candidates: readonly KnowledgeCitationCandidate[]\n}\n\nexport interface KnowledgeCitationAuditReport {\n readonly ok: boolean\n readonly checkedPages: number\n readonly checkedCitations: number\n readonly issues: readonly KnowledgeCitationAuditIssue[]\n}\n\nexport interface AuditKnowledgeCitationsOptions {\n /** Limit audited source pages to these origins. All visible origins are checked by default. */\n readonly sourceOrigins?: readonly PageOrigin[]\n}\n\n/** A batch contains at least one citation that is missing or ambiguous. */\nexport class KnowledgeCitationResolutionError extends Error {\n readonly resolutions: readonly KnowledgeCitationResolution[]\n\n constructor(resolutions: readonly KnowledgeCitationResolution[]) {\n const unresolved = resolutions.filter((resolution) => resolution.status !== 'resolved')\n const missing = unresolved\n .filter((resolution) => resolution.status === 'missing')\n .map((resolution) => formatKnowledgeCitationReference(resolution.reference))\n const ambiguous = unresolved\n .filter((resolution) => resolution.status === 'ambiguous')\n .map(\n (resolution) =>\n `${formatKnowledgeCitationReference(resolution.reference)} (${resolution.candidates.length} matches)`,\n )\n const parts = [\n missing.length > 0 ? `missing: ${missing.join(', ')}` : '',\n ambiguous.length > 0 ? `ambiguous: ${ambiguous.join(', ')}` : '',\n ].filter(Boolean)\n super(`knowledge citation resolution failed: ${parts.join('; ')}`)\n this.name = 'KnowledgeCitationResolutionError'\n this.resolutions = Object.freeze([...unresolved])\n }\n}\n\n/** A persisted page contains a self, missing, or ambiguous citation. */\nexport class KnowledgeCitationAuditError extends Error {\n readonly report: KnowledgeCitationAuditReport\n\n constructor(report: KnowledgeCitationAuditReport) {\n const counts = new Map<KnowledgeCitationAuditIssueKind, number>()\n for (const issue of report.issues) counts.set(issue.kind, (counts.get(issue.kind) ?? 0) + 1)\n const summary = [...counts.entries()].map(([kind, count]) => `${kind}=${count}`).join(', ')\n super(`knowledge citation audit failed: ${summary}`)\n this.name = 'KnowledgeCitationAuditError'\n this.report = report\n }\n}\n\n/**\n * Parse the persisted citation form.\n *\n * `page-id` is unqualified. `here::page-id`, `shared::page-id`, and\n * `inherited:<runId>::page-id` bind an intentional duplicate to one origin.\n */\nexport function parseKnowledgeCitationReference(value: string): KnowledgeCitationReference {\n if (typeof value !== 'string' || value.trim().length === 0) {\n throw new TypeError('persisted knowledge citation must be a non-empty string')\n }\n const normalized = value.trim()\n const separator = normalized.indexOf('::')\n if (separator < 0) return Object.freeze({ pageId: normalized })\n const possibleOrigin = normalized.slice(0, separator)\n const pageId = normalized.slice(separator + 2)\n if (!isPageOrigin(possibleOrigin)) {\n return Object.freeze({ pageId: normalized })\n }\n return normalizeReference({ pageId, origin: possibleOrigin })\n}\n\n/** Serialize one reference into the canonical frontmatter representation. */\nexport function formatKnowledgeCitationReference(reference: KnowledgeCitationReference): string {\n const normalized = normalizeReference(reference)\n return normalized.origin === undefined\n ? normalized.pageId\n : `${normalized.origin}::${normalized.pageId}`\n}\n\n/** Resolve one reference against an already materialized visibility chain. */\nexport function resolveKnowledgeCitation(\n visiblePages: readonly OriginatedPage[],\n reference: KnowledgeCitationReference,\n): KnowledgeCitationResolution {\n const normalized = normalizeReference(reference)\n const candidates = visiblePages\n .filter(\n (entry) =>\n entry.page.id === normalized.pageId &&\n (normalized.origin === undefined || entry.origin === normalized.origin),\n )\n .map((entry) =>\n Object.freeze({\n pageId: entry.page.id,\n origin: entry.origin,\n page: entry.page,\n }),\n )\n const status: KnowledgeCitationResolutionStatus =\n candidates.length === 0 ? 'missing' : candidates.length === 1 ? 'resolved' : 'ambiguous'\n return Object.freeze({\n reference: normalized,\n status,\n candidates: Object.freeze(candidates),\n ...(status === 'resolved' ? { resolved: candidates[0]! } : {}),\n })\n}\n\n/** Resolve a batch without discarding missing or ambiguous rows. */\nexport function resolveKnowledgeCitations(\n visiblePages: readonly OriginatedPage[],\n references: readonly KnowledgeCitationReference[],\n): readonly KnowledgeCitationResolution[] {\n return Object.freeze(\n references.map((reference) => resolveKnowledgeCitation(visiblePages, reference)),\n )\n}\n\n/**\n * Resolve a batch and fail closed unless every reference names exactly one\n * visible page. Returned candidates preserve the caller's reference order.\n */\nexport function assertKnowledgeCitationsResolved(\n visiblePages: readonly OriginatedPage[],\n references: readonly KnowledgeCitationReference[],\n): readonly KnowledgeCitationCandidate[] {\n const resolutions = resolveKnowledgeCitations(visiblePages, references)\n if (resolutions.some((resolution) => resolution.status !== 'resolved')) {\n throw new KnowledgeCitationResolutionError(resolutions)\n }\n return Object.freeze(resolutions.map((resolution) => resolution.resolved!))\n}\n\n/** Audit persisted `cites` relations against one immutable visibility snapshot. */\nexport function auditKnowledgeCitations(\n visiblePages: readonly OriginatedPage[],\n options: AuditKnowledgeCitationsOptions = {},\n): KnowledgeCitationAuditReport {\n const origins = options.sourceOrigins\n ? new Set(options.sourceOrigins.map((origin) => validatePageOrigin(origin)))\n : null\n const sources = visiblePages.filter((entry) => origins === null || origins.has(entry.origin))\n const issues: KnowledgeCitationAuditIssue[] = []\n let checkedCitations = 0\n\n for (const source of sources) {\n for (const persistedCitation of new Set(source.page.cites ?? [])) {\n checkedCitations += 1\n const reference = parseKnowledgeCitationReference(persistedCitation)\n const resolution = resolveKnowledgeCitation(visiblePages, reference)\n const self = resolution.candidates.some(\n (candidate) =>\n candidate.page === source.page ||\n (candidate.origin === source.origin && candidate.page.path === source.page.path),\n )\n const kind: KnowledgeCitationAuditIssueKind | null = self\n ? 'self'\n : resolution.status === 'missing'\n ? 'missing'\n : resolution.status === 'ambiguous'\n ? 'ambiguous'\n : null\n if (kind === null) continue\n issues.push(\n Object.freeze({\n kind,\n sourcePageId: source.page.id,\n sourcePath: source.page.path,\n sourceOrigin: source.origin,\n persistedCitation,\n reference,\n candidates: resolution.candidates,\n }),\n )\n }\n }\n\n return Object.freeze({\n ok: issues.length === 0,\n checkedPages: sources.length,\n checkedCitations,\n issues: Object.freeze(issues),\n })\n}\n\n/** Audit and fail closed when any persisted citation is unresolved. */\nexport function assertKnowledgeCitationAudit(report: KnowledgeCitationAuditReport): void {\n if (!report.ok) throw new KnowledgeCitationAuditError(report)\n}\n\n/** Resolve one citation using a run-scoped store's declared visibility chain. */\nexport async function resolveRunScopedCitation(\n stores: RunScopedStores,\n runId: string,\n reference: KnowledgeCitationReference,\n): Promise<KnowledgeCitationResolution> {\n return resolveKnowledgeCitation(await stores.loadChain(runId), reference)\n}\n\n/** Resolve citations using one chain read so every row sees the same snapshot. */\nexport async function resolveRunScopedCitations(\n stores: RunScopedStores,\n runId: string,\n references: readonly KnowledgeCitationReference[],\n): Promise<readonly KnowledgeCitationResolution[]> {\n return resolveKnowledgeCitations(await stores.loadChain(runId), references)\n}\n\n/** Resolve a run-scoped batch and fail closed on any missing or ambiguous id. */\nexport async function assertRunScopedCitationsResolved(\n stores: RunScopedStores,\n runId: string,\n references: readonly KnowledgeCitationReference[],\n): Promise<readonly KnowledgeCitationCandidate[]> {\n return assertKnowledgeCitationsResolved(await stores.loadChain(runId), references)\n}\n\n/** Audit only pages authored in the current run against the full visible chain. */\nexport async function auditCurrentRunCitations(\n stores: RunScopedStores,\n runId: string,\n): Promise<KnowledgeCitationAuditReport> {\n return auditKnowledgeCitations(await stores.loadChain(runId), { sourceOrigins: ['here'] })\n}\n\n/** Audit current-run citations and fail closed on every unresolved relation. */\nexport async function assertCurrentRunCitationsResolved(\n stores: RunScopedStores,\n runId: string,\n): Promise<KnowledgeCitationAuditReport> {\n const report = await auditCurrentRunCitations(stores, runId)\n assertKnowledgeCitationAudit(report)\n return report\n}\n\nfunction normalizeReference(reference: KnowledgeCitationReference): KnowledgeCitationReference {\n if (!reference || typeof reference !== 'object') {\n throw new TypeError('knowledge citation reference must be an object')\n }\n if (typeof reference.pageId !== 'string' || reference.pageId.trim().length === 0) {\n throw new TypeError('knowledge citation pageId must be a non-empty string')\n }\n if (reference.origin !== undefined) validatePageOrigin(reference.origin)\n return Object.freeze({\n pageId: reference.pageId.trim(),\n ...(reference.origin === undefined ? {} : { origin: reference.origin }),\n })\n}\n\nfunction validatePageOrigin(value: PageOrigin): PageOrigin {\n if (!isPageOrigin(value)) {\n throw new TypeError(`knowledge citation origin is invalid: ${String(value)}`)\n }\n return value\n}\n\nfunction isPageOrigin(value: unknown): value is PageOrigin {\n if (value === 'here' || value === 'shared') return true\n return (\n typeof value === 'string' &&\n value.startsWith('inherited:') &&\n value.slice('inherited:'.length).trim().length > 0\n )\n}\n","import { parseKnowledgeCitationReference } from './citation-resolution'\nimport type {\n KnowledgeGraph,\n KnowledgeGraphEdge,\n KnowledgeGraphNode,\n KnowledgePage,\n KnowledgeRelation,\n} from './types'\nimport { normalizeLinkTarget } from './wikilinks'\n\nexport type KnowledgePageRelationPredicate =\n | 'wikilink'\n | 'citation'\n | 'shared-source'\n | 'contradicts'\n\n/** One labeled relation between two pages; `weight` counts the occurrences that produced it. */\nexport interface KnowledgePageRelation extends KnowledgeRelation {\n predicate: KnowledgePageRelationPredicate\n weight: number\n}\n\n/**\n * The labeled relations between pages, one per `(sourceId, targetId, predicate)`.\n *\n * `wikilink`, `citation`, and `contradicts` follow an authored link, `cites`\n * entry, or `contradicts` entry to the one page it resolves to; a missing,\n * ambiguous, or self-referencing target emits nothing. `shared-source` joins\n * every pair of pages that registers a common source, in page order, weighted\n * 0.5 per shared source id, with the shared ids in `metadata.sourceIds`. It is\n * implicit, so it is listed after the authored relations and never counts\n * toward a page's degree in `buildKnowledgeGraph`.\n */\nexport function knowledgePageRelations(pages: KnowledgePage[]): KnowledgePageRelation[] {\n const bySlug = new Map<string, KnowledgePage>()\n const byId = new Map<string, KnowledgePage[]>()\n for (const page of pages) {\n byId.set(page.id, [...(byId.get(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 authored = new Map<string, KnowledgePageRelation>()\n const count = (\n source: KnowledgePage,\n target: KnowledgePage,\n predicate: KnowledgePageRelationPredicate,\n ): void => {\n const key = JSON.stringify([source.id, target.id, predicate])\n const relation = authored.get(key)\n if (relation) relation.weight += 1\n else authored.set(key, { sourceId: source.id, targetId: target.id, predicate, weight: 1 })\n }\n const uniqueTarget = (id: string): KnowledgePage | undefined => {\n const targets = byId.get(id) ?? []\n return targets.length === 1 ? targets[0] : undefined\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 count(page, target, 'wikilink')\n }\n for (const persisted of page.cites ?? []) {\n const target = uniqueTarget(citedPageId(persisted))\n if (!target || target.id === page.id) continue\n count(page, target, 'citation')\n }\n for (const contradicted of page.contradicts ?? []) {\n const target = uniqueTarget(contradicted)\n if (!target || target.id === page.id) continue\n count(page, target, 'contradicts')\n }\n }\n\n const relations: KnowledgePageRelation[] = [...authored.values()]\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 relations.push({\n sourceId: a.id,\n targetId: b.id,\n predicate: 'shared-source',\n weight: overlap.length * 0.5,\n metadata: { sourceIds: overlap },\n })\n }\n }\n return relations\n}\n\n/**\n * The weighted page graph: `knowledgePageRelations` collapsed to one edge per\n * ordered page pair, with the predicates merged into `reasons` and the weights\n * summed. `contradicts` stays out of this projection; read it from the relation\n * list. Node degrees count the authored `wikilink` and `citation` occurrences.\n */\nexport function buildKnowledgeGraph(pages: KnowledgePage[]): KnowledgeGraph {\n const incoming = new Map<string, number>()\n const outgoing = new Map<string, number>()\n for (const page of pages) {\n outgoing.set(page.id, 0)\n incoming.set(page.id, 0)\n }\n\n const edgesByKey = new Map<string, KnowledgeGraphEdge>()\n for (const relation of knowledgePageRelations(pages)) {\n if (relation.predicate === 'contradicts') continue\n const key = `${relation.sourceId}->${relation.targetId}`\n let edge = edgesByKey.get(key)\n if (!edge) {\n edge = { source: relation.sourceId, target: relation.targetId, weight: 0, reasons: [] }\n edgesByKey.set(key, edge)\n }\n edge.weight += relation.weight\n if (!edge.reasons.includes(relation.predicate)) edge.reasons.push(relation.predicate)\n if (relation.predicate === 'wikilink' || relation.predicate === 'citation') {\n outgoing.set(relation.sourceId, (outgoing.get(relation.sourceId) ?? 0) + relation.weight)\n incoming.set(relation.targetId, (incoming.get(relation.targetId) ?? 0) + relation.weight)\n }\n }\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\n/**\n * An origin-qualified citation (`here::x`, `inherited:<run>::x`, `shared::x`)\n * must keep its graph edge: qualification is the documented remedy for an\n * ambiguous id, so it cannot cost the citation signal. A value the parser\n * rejects stays a literal page id so index builds never fail on stored data.\n */\nfunction citedPageId(persisted: string): string {\n try {\n return parseKnowledgeCitationReference(persisted).pageId\n } catch {\n return persisted\n }\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 type { KnowledgePagesOptions } from './pages-directory'\nimport { loadSourceRegistry } from './sources'\nimport { loadKnowledgePages } from './store'\nimport type { KnowledgeIndex } from './types'\n\nexport async function buildKnowledgeIndex(\n root: string,\n options: KnowledgePagesOptions = {},\n): Promise<KnowledgeIndex> {\n return withKnowledgeRead(root, () => buildKnowledgeIndexUnlocked(root, options))\n}\n\nasync function buildKnowledgeIndexUnlocked(\n root: string,\n options: KnowledgePagesOptions,\n): Promise<KnowledgeIndex> {\n const [pages, sourceRegistry] = await Promise.all([\n loadKnowledgePages(root, options),\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(\n root: string,\n options: KnowledgePagesOptions = {},\n): Promise<KnowledgeIndex> {\n return withKnowledgeMutation(root, async () => {\n const index = await buildKnowledgeIndexUnlocked(root, options)\n await new FileSystemKbStore({ root }).putIndex(index)\n return index\n })\n}\n","/**\n * The evidence contract for claims that machines, not authors, get to grade.\n *\n * Grown in a discovery campaign that learned each rule by paying for it. Self-reported\n * verification is a dead channel: an entire run's twenty-eight true claims scored zero because\n * nothing carried a check a grader could re-execute, and a sibling lab's cells once produced six\n * false certifications in seventeen deliveries without a single agent lying — the format betrayed\n * them. The countermeasure is mechanical: a claim above a threshold must carry the command that\n * re-establishes it, and an independent grader re-runs that command blind.\n *\n * The verdict lattice below is calibrated, not designed: its first contact with real claims\n * graded three TRUE results as refuted, because a silent assert exits zero printing nothing and\n * the expectation could never match empty output. Every distinction here exists because collapsing\n * it blamed the wrong party — a claim for its environment, or an author for their formatting.\n */\n\n/**\n * How far up the ladder a claim's evidence actually reaches. The rungs are five different\n * statements and only the top two are verification:\n *\n * 1 — it parses / exists 3 — its tests pass 5 — independently re-derived\n * 2 — it imports / loads 4 — reproduces a claimed value\n *\n * Reporting a low rung in the vocabulary of a high one is the most expensive error available to a\n * knowledge system: it is indistinguishable from success and propagates as settled provenance.\n */\n\nexport type EvidenceRung = 1 | 2 | 3 | 4 | 5\n\n/** The rung at and above which a claim must be machine-checkable to be recorded at that rung. */\nexport const CHECKABLE_RUNG_THRESHOLD = 4\n\nexport interface ClaimEvidence {\n rung: EvidenceRung\n /**\n * A shell command that re-establishes the claim when run by a grader the author cannot edit,\n * from a working directory the author must not assume. Required at rung 4 and above.\n */\n check?: string\n /**\n * A substring the check's stdout must contain — the decisive value, printed. A check that\n * exits zero but prints nothing cannot confirm a value; authors should print the number.\n * Required at rung 4 and above, where an exit code alone reproduces no value.\n *\n * An expectation naming several values at once is admitted, and is the strongest shape\n * available: a false pass on `GRID OK cells=8 WIN=1 PARETO=6` needs three independent numbers\n * to coincide, where a one-token `OK` is satisfied by any output containing those two letters.\n */\n expect?: string\n /** Where the artifact backing the claim lives, for humans following the trail. */\n evidencePath?: string\n}\n\n/**\n * The refusal vocabulary, shared by both boundaries. Record time and grade time refuse the same\n * static shapes for the same reasons, so they read from one detector and one set of notes. A\n * second definition would let the two boundaries drift, and a claim the recorder admitted but the\n * grader refuses is exactly the gap this section exists to close.\n */\n\n/** The commands that succeed unconditionally, so their exit code carries no information. */\nconst ALWAYS_SUCCEEDS = new Set(['true', ':'])\n\n/** The commands that print their arguments back, so their output carries only their arguments. */\nconst PRINTS_ITS_ARGUMENTS = new Set(['echo', 'printf'])\n\n/**\n * A character that makes an argument depend on something outside the command line: a pipe, a\n * command separator, a redirection from a file, a backtick or `$(` substitution, or a variable\n * reference. `$'` and `$\"` are quoting sigils, not variable references.\n */\nconst READS_SOMETHING_ELSE = /[|;&\\n<`]|\\$(?!['\"])/\n\n/**\n * Whether a check emits a constant, and therefore cannot fail whatever the claim's subject does.\n *\n * The test is deliberately narrow and mechanical. It recognizes exactly two shapes: the whole\n * command is `true` or `:`, or the whole command is one `echo` or `printf` whose arguments read\n * nothing outside the command line. Anything else is treated as a real check.\n *\n * This CANNOT catch every check that cannot fail. A script that prints a hard-coded number, a\n * command whose output an author copied into `expect`, and an `echo` behind a shell alias all look\n * identical to a real check from here. Catching those is not this function's job: it needs an\n * independent party to re-derive the value, which is what rung 5 means. This function refuses only\n * the shapes that carry zero information on their face, where refusing costs the author nothing\n * but a rewrite of the command.\n */\nfunction isConstantEmitter(check: string): boolean {\n const command = check.trim()\n if (ALWAYS_SUCCEEDS.has(command)) return true\n const argumentStart = command.search(/\\s/)\n const head = argumentStart === -1 ? command : command.slice(0, argumentStart)\n if (!PRINTS_ITS_ARGUMENTS.has(head)) return false\n const argumentText = argumentStart === -1 ? '' : command.slice(argumentStart + 1)\n return !READS_SOMETHING_ELSE.test(argumentText)\n}\n\nconst NO_CHECK_NOTE =\n 'a claim at this rung asserts that a command reproduces a value, and no command was recorded ' +\n '— record the command that re-establishes it (evidence.check); without one the claim is a ' +\n 'self-grade, which is rung 3 at most'\n\nconst NO_EXPECTATION_NOTE =\n 'exit code alone cannot verify a claim at this rung — record the value the check must print'\n\nconst CONSTANT_EMITTER_NOTE =\n 'the check is a constant emitter: it prints a fixed string and exits zero whatever the claim ' +\n 'describes, so it can never fail — record a command that reads the artifact the claim is about'\n\nconst MULTILINE_EXPECTATION_NOTE =\n 'the expected value spans multiple lines, but the grader performs one contiguous-substring ' +\n 'comparison — record one decisive single-line value per claim'\n\nconst SELF_CERTIFYING_NOTE =\n 'the check text contains the expected value, so the check carries the answer it is graded ' +\n 'against and prints a value the claim did not have to produce — record a command that reads ' +\n 'the artifact and prints the value it finds there'\n\nconst LONG_FIRST_WORD_NOTE =\n 'the check begins with a shell word longer than 200 characters; this is the escaped-newline ' +\n 'failure shape where \\\\n text was recorded instead of real line breaks — write the script to a file ' +\n 'or record a real heredoc and a short invocation'\n\nconst INVALID_SHELL_SYNTAX_NOTE =\n 'the recorded check does not parse under bash and would fail independently of the claim — ' +\n 'record the exact command only after bash -n accepts it'\n\n/**\n * The evidence recorded for a claim cannot be graded at the rung it was recorded at.\n *\n * One error type for every mechanically refused shape, because the grader reaches one verdict for\n * all of them: `uncheckable`. `note` names which shape was refused and what to record instead, in\n * the same words the grader reports, so an author reads one message wherever the claim is stopped.\n */\nexport class UncheckableClaimError extends Error {\n /** The rung whose evidence rule the recorded claim failed. */\n readonly rung: EvidenceRung\n /** The refused shape and the fix for it, in the grader's vocabulary. */\n readonly note: string\n\n constructor(rung: EvidenceRung, note: string) {\n super(`a claim at rung ${rung} cannot be recorded at that rung: ${note}`)\n this.name = 'UncheckableClaimError'\n this.rung = rung\n this.note = note\n }\n}\n\n/**\n * Refuse the evidence shapes that made self-grading and false refutation possible. Call at record\n * time, not grade time: by grading it is too late — the ungradeable claim has already circulated.\n *\n * At and above `CHECKABLE_RUNG_THRESHOLD` this refuses every statically recognizable shape that\n * `gradeFor` grades `uncheckable`: no check, a check that cannot fail, an unusable expectation,\n * or the escaped-newline command shape. Below the threshold nothing is refused.\n *\n * Three additional rules are calibrated on downstream losses, not taste: four correct claims\n * died from multiline expectations, one campaign recorded an enormous first word made of literal\n * `\\\\n` sequences, and a 299-run fleet autopsy reduced ten reported grader failures to checks that\n * were never executed before their authors disappeared. The dynamic half of that last rule is\n * `verifyGradeableEvidence` below.\n */\nexport function assertGradeableEvidence(evidence: ClaimEvidence): ClaimEvidence {\n if (evidence.rung < CHECKABLE_RUNG_THRESHOLD) return evidence\n const note =\n checkRefusalNote(evidence.check) ??\n selfCertifyingNote(evidence) ??\n expectationRefusalNote(evidence.expect)\n if (note) throw new UncheckableClaimError(evidence.rung, note)\n return evidence\n}\n\n/**\n * What a grader may conclude from re-executing a claim's check.\n *\n * verified exit 0, and the expectation (if any) appears in output\n * silent-check exit 0, expectation given, output empty — the check passed but proves nothing\n * about the expected value; the author should make the check PRINT it\n * contradicted the check ran and refuted the claim: nonzero exit, or non-empty output that\n * lacks the expectation\n * unrunnable the check itself could not execute (missing input, missing module), or its\n * deadline killed it — an environment verdict, never a claim verdict\n * uncheckable the recorded evidence cannot decide the claim at this rung\n */\nexport type ClaimVerdict =\n | 'verified'\n | 'silent-check'\n | 'contradicted'\n | 'unrunnable'\n | 'uncheckable'\n\n/**\n * The output signatures that mean the check never reached what the claim is about.\n *\n * Matched case-insensitively, because a tool that prints its own diagnostic chooses its own case,\n * and read from the OUTPUT rather than from the exit status. A shell pipeline exits with the\n * status of its last stage, so `sha256sum <missing path> | cut -d' ' -f1` prints\n * \"No such file or directory\" and exits 0; reading only the status calls that a refutation of\n * research that was never run. Swept over 272 grade files, 29 of 61 recorded refutations were\n * this shape: 7 a malformed check body, 7 a shell that could not parse the check, 6 a solver that\n * could not open its problem file, 5 `Permission denied`, 4 `cannot create directory`.\n */\nconst UNRUNNABLE_SIGNATURES =\n /No such file|FileNotFoundError|ModuleNotFoundError|command not found|ENOENT|AbortError|timed out|ERR_CHILD_PROCESS_STDIO_MAXBUFFER|Permission denied|EACCES|cannot create directory|cannot open|SyntaxError|unexpected EOF while looking for matching|syntax error near unexpected token/i\n\n/**\n * The exit status a deadline kill reports: `timeout(1)`'s status, and the one a bounded process\n * runner forces so a killed child that closes with 0 cannot read as a pass. A grader that has\n * only an exit status reports this one; a grader that knows it killed the process sets\n * `CheckExecution.timedOut` instead, which is unambiguous.\n */\nexport const DEADLINE_EXIT_CODE = 124\n\nconst DEADLINE_NOTE =\n 'the check was killed at its deadline, so it never tested the claim — a deadline is a budget, ' +\n 'not a verdict; raise the budget or record a check that decides within it'\n\nconst ABORTED_NOTE =\n 'the check was stopped by the caller before it finished, so it never tested the claim — ' +\n 'this is a decision about the run and not a verdict on the claim'\n\nconst TRUNCATED_OUTPUT_NOTE =\n 'the check printed more than the executor kept, so the claim was graded against a fragment — ' +\n 'raise the output ceiling or record a check that prints only the decisive value'\n\nconst UNREACHED_INPUT_NOTE =\n 'the check never reached what the claim is about, so this is a verdict on the environment ' +\n 'and not on the claim'\n\nexport interface CheckExecution {\n exitCode: number\n stdout: string\n stderr: string\n /**\n * True when the executor killed the check at its deadline. The deadline is a budget, not a\n * verdict: a check that ran out of time never tested the claim.\n */\n timedOut?: boolean\n /**\n * True when the caller withdrew the run before it finished. Like a deadline, this is a\n * decision about the budget and not an observation of the claim.\n */\n killedBySignal?: boolean\n /**\n * True when the executor stopped keeping the check's output before the check stopped printing.\n * The kept text is a fragment, so a comparison against it answers about the fragment: an\n * expectation printed in the discarded bytes reads as absent, which would refute a claim the\n * check may well have established.\n */\n outputTruncated?: boolean\n}\n\n/** A verdict with the reason a grader may report to the claim's author. */\nexport interface ClaimGrade {\n verdict: ClaimVerdict\n /** Present when the verdict is a refusal the author can fix, absent otherwise. */\n note?: string\n /**\n * The id of the earlier claim in the same grading pass that carries this claim's check,\n * expectation, title and verdict. Present only on the later claim, and it does not change the\n * verdict: N claims sharing one check are one verification counted N times, which is a\n * check-quality defect for a reader to see rather than a result to drop.\n */\n duplicateOf?: string\n}\n\n/**\n * The calibrated verdict function, pure so every grader shares one semantics. Callers execute the\n * check however their environment requires and pass the observation; this function only judges.\n *\n * Three rules decide a verdict before the expectation is compared, and each one exists because\n * comparing first blamed the claim for something the claim did not do:\n *\n * - a check that carries its own expected value is refused, because its output is authored\n * rather than measured;\n * - a check killed at its deadline is `unrunnable`, because a budget is not a verdict;\n * - a check whose output says it never reached its input is `unrunnable` whatever its exit\n * status, because a pipeline hides the failing stage's status behind its last stage.\n */\nexport function gradeFor(\n evidence: Pick<ClaimEvidence, 'rung' | 'check' | 'expect'>,\n execution: CheckExecution | null,\n): ClaimGrade {\n const mustBeCheckable = evidence.rung >= CHECKABLE_RUNG_THRESHOLD\n if (mustBeCheckable) {\n const note = checkRefusalNote(evidence.check) ?? selfCertifyingNote(evidence)\n if (note) return { verdict: 'uncheckable', note }\n }\n if (!execution) return { verdict: 'unrunnable' }\n const output = `${execution.stdout}\\n${execution.stderr}`.trim()\n if (execution.timedOut || execution.exitCode === DEADLINE_EXIT_CODE) {\n return { verdict: 'unrunnable', note: DEADLINE_NOTE }\n }\n // Both are reports from the EXECUTOR about the run, not observations of the claim, and both\n // are read before the exit status because a killed or half-captured run has no status worth\n // reading. They are fields rather than text in `stderr` on purpose: an executor that reports\n // the condition it caused must not have to spell it in words a regex happens to know.\n if (execution.killedBySignal) return { verdict: 'unrunnable', note: ABORTED_NOTE }\n if (execution.outputTruncated) return { verdict: 'unrunnable', note: TRUNCATED_OUTPUT_NOTE }\n if (execution.exitCode !== 0) {\n // The expectation is the claim's own statement of what settles it, so a nonzero exit does\n // not refute a claim whose promised observation is in the output: a negative control that\n // correctly refuses exits nonzero and prints the refusal it promised, and refuting it for\n // the status made `expect` dead code on every such claim. An unreached-input signature in\n // the output still outranks the substring, and an expectation that itself names a\n // signature keeps the guard's own rule below, so a run that never happened is not rescued.\n if (\n evidence.expect &&\n output.includes(evidence.expect) &&\n !UNRUNNABLE_SIGNATURES.test(evidence.expect) &&\n !UNRUNNABLE_SIGNATURES.test(output)\n ) {\n if (mustBeCheckable) {\n const note = expectationRefusalNote(evidence.expect)\n if (note) return { verdict: 'uncheckable', note }\n }\n return { verdict: 'verified' }\n }\n return refutation(output, evidence.expect)\n }\n if (mustBeCheckable) {\n const note = expectationRefusalNote(evidence.expect)\n if (note) return { verdict: 'uncheckable', note }\n }\n if (evidence.expect && !output.includes(evidence.expect)) {\n if (output === '') return { verdict: 'silent-check' }\n return refutation(output, evidence.expect)\n }\n return { verdict: 'verified' }\n}\n\n/**\n * Decide between a claim verdict and an environment verdict for output that failed to establish\n * the claim. The signature list only ever downgrades a refutation to `unrunnable`: it can turn a\n * measurement that did not happen into an honest \"not measured\", and it can never turn a real\n * failure into a pass.\n *\n * The expectation is consulted first. A claim that PREDICTED the error is genuinely contradicted\n * when the error does not appear, so an expectation naming a signature switches this guard off\n * for that claim rather than letting it hide the one case it would grade backwards.\n */\nfunction refutation(output: string, expect: string | undefined): ClaimGrade {\n if (expect && UNRUNNABLE_SIGNATURES.test(expect)) return { verdict: 'contradicted' }\n const hit = UNRUNNABLE_SIGNATURES.exec(output)\n if (!hit) return { verdict: 'contradicted' }\n return { verdict: 'unrunnable', note: `${UNREACHED_INPUT_NOTE} (${hit[0]})` }\n}\n\n/** A claim and the observation a grader made of it, as one grading pass sees them. */\nexport interface GradeableClaim {\n /** Stable identity a duplicate flag can point back to, such as the page or claim id. */\n id: string\n /** The claim's own sentence. Two claims that share a check but say different things differ. */\n title?: string\n evidence: Pick<ClaimEvidence, 'rung' | 'check' | 'expect'>\n execution: CheckExecution | null\n}\n\n/** A grade with the claim it belongs to, in the order the claims were supplied. */\nexport interface GradedClaim extends ClaimGrade {\n id: string\n}\n\n/**\n * Grade one pass of claims and flag the repeats within it.\n *\n * `gradeFor` judges one claim and cannot see a second claim carrying the same check, so a run\n * that recorded one verification under several titles reports as several independent\n * verifications. This function grades each claim exactly as `gradeFor` does and marks the later\n * claim with `duplicateOf`, leaving the verdict and the count untouched: the flag is for a reader\n * deciding how much evidence a run really produced.\n */\nexport function gradeClaims(claims: readonly GradeableClaim[]): GradedClaim[] {\n const firstSeen = new Map<string, string>()\n return claims.map((claim) => {\n const grade = gradeFor(claim.evidence, claim.execution)\n const key = claimCheckKey({ ...claim.evidence, title: claim.title })\n if (!key) return { id: claim.id, ...grade }\n const seenAt = `${key}\\u0000${grade.verdict}`\n const canonical = firstSeen.get(seenAt)\n if (canonical === undefined) {\n firstSeen.set(seenAt, claim.id)\n return { id: claim.id, ...grade }\n }\n return { id: claim.id, ...grade, duplicateOf: canonical }\n })\n}\n\n/**\n * The identity two claims must share to be one verification counted twice: the same command, the\n * same expectation, and the same sentence. A check shared across claims that say different things\n * is one instrument used several times, which is not a duplicate.\n *\n * Returns `undefined` when the claim cannot be keyed at all — no check, or no title to compare —\n * so an unkeyable claim is never flagged as a repeat of another unkeyable one. The key is JSON\n * rather than a joined string, so no separator can collide with text inside a check.\n */\nexport function claimCheckKey(claim: {\n check?: string\n expect?: string\n title?: string\n}): string | undefined {\n const check = claim.check?.trim()\n if (!check) return undefined\n const title = claim.title?.trim().replace(/\\s+/g, ' ').toLowerCase().replace(/\\.md$/, '')\n if (!title) return undefined\n return JSON.stringify([check, claim.expect?.trim() ?? '', title])\n}\n\n/** The verdict alone, for graders that report a lattice member and not a reason. */\nexport function verdictFor(\n evidence: Pick<ClaimEvidence, 'rung' | 'check' | 'expect'>,\n execution: CheckExecution | null,\n): ClaimVerdict {\n return gradeFor(evidence, execution).verdict\n}\n\nexport interface VerifyGradeableEvidenceOptions {\n /** Directory in which the later grader will execute the command. Required to avoid ambient cwd. */\n cwd: string\n /** Exact environment visible to the command. Omitted variables are genuinely absent. */\n env?: NodeJS.ProcessEnv\n /** Bash-compatible executable. Defaults to `bash`. */\n bashPath?: string\n /** Per syntax or execution process timeout. Defaults to 30 seconds. */\n timeoutMs?: number\n /** Combined stdout/stderr buffer ceiling. Defaults to 1 MiB. */\n maxBufferBytes?: number\n signal?: AbortSignal\n}\n\nexport interface VerifiedGradeableEvidence {\n evidence: ClaimEvidence\n execution: CheckExecution\n grade: ClaimGrade\n}\n\n/**\n * Parse, execute, and grade evidence at intake using the same cwd and environment the blind grader\n * will use later.\n *\n * A check that bash cannot parse raises `UncheckableClaimError`, because a command that cannot run\n * anywhere is a record-time defect the author must fix. A parse the EXECUTOR stopped — its\n * deadline, or the caller's signal — raises nothing and is graded `unrunnable`: nothing was\n * learned about the check's grammar, so there is nothing to refuse it for.\n *\n * This function executes `evidence.check` verbatim. It is intentionally opt-in, Node-only at call\n * time, and dynamically imports `@tangle-network/agent-eval` so edge consumers that never invoke\n * it remain importable. Callers must apply their own sandbox and capability policy before passing\n * untrusted commands here.\n */\nexport async function verifyGradeableEvidence(\n evidence: ClaimEvidence,\n options: VerifyGradeableEvidenceOptions,\n): Promise<VerifiedGradeableEvidence> {\n const accepted = assertGradeableEvidence(evidence)\n const check = accepted.check as string\n const syntax = await runCheckProcess(['-n', '-c', check], options)\n // A parse that the executor stopped is not a reading of the check's grammar. Reporting it as a\n // parse failure would blame the author for a deadline or for the caller's own teardown, which\n // is the shape every other rule in this file exists to refuse. The run is graded instead, and\n // `gradeFor` reports it `unrunnable` from the field that says what stopped it.\n if (syntax.timedOut || syntax.killedBySignal) {\n return { evidence: accepted, execution: syntax, grade: gradeFor(accepted, syntax) }\n }\n if (syntax.exitCode !== 0) {\n const detail = `${syntax.stdout}\\n${syntax.stderr}`.trim()\n const note = detail ? `${INVALID_SHELL_SYNTAX_NOTE}: ${detail}` : INVALID_SHELL_SYNTAX_NOTE\n throw new UncheckableClaimError(accepted.rung, note)\n }\n const execution = await runCheckProcess(['-c', check], options)\n return {\n evidence: accepted,\n execution,\n grade: gradeFor(accepted, execution),\n }\n}\n\nconst WORD_CHARACTER = /[A-Za-z0-9_]/\n\n/**\n * Whether the check text carries the value it is graded against.\n *\n * A check that contains its own expectation prints a value the claim's subject did not have to\n * produce, so the comparison that follows tests the author's typing rather than the artifact.\n * The test is the whole trimmed expectation appearing verbatim in the command, which is narrow\n * on purpose: it costs an author only a rewrite of the command, and it catches the shape\n * `isConstantEmitter` cannot, where a real command's arguments already spell the answer.\n *\n * An occurrence glued to a word character on a side where the expectation is itself a word\n * character does not count. Without that, a short expectation refuses the check that reads it:\n * `expect: 6` appears inside `node report6.mjs`, and refusing a correct claim is the cost this\n * file's rules are calibrated to avoid.\n */\nfunction selfCertifyingNote(evidence: Pick<ClaimEvidence, 'check' | 'expect'>): string | undefined {\n const wanted = evidence.expect?.trim()\n const check = evidence.check\n if (!check || !wanted) return undefined\n const startsInsideWord = WORD_CHARACTER.test(wanted[0] as string)\n const endsInsideWord = WORD_CHARACTER.test(wanted[wanted.length - 1] as string)\n for (let at = check.indexOf(wanted); at !== -1; at = check.indexOf(wanted, at + 1)) {\n const before = check[at - 1]\n const after = check[at + wanted.length]\n if (startsInsideWord && before !== undefined && WORD_CHARACTER.test(before)) continue\n if (endsInsideWord && after !== undefined && WORD_CHARACTER.test(after)) continue\n return SELF_CERTIFYING_NOTE\n }\n return undefined\n}\n\nfunction checkRefusalNote(check: string | undefined): string | undefined {\n if (!check) return NO_CHECK_NOTE\n if (isConstantEmitter(check)) return CONSTANT_EMITTER_NOTE\n const firstWord = check.trimStart().split(/\\s/, 1)[0] ?? ''\n if (firstWord.length > 200) return LONG_FIRST_WORD_NOTE\n return undefined\n}\n\nfunction expectationRefusalNote(expect: string | undefined): string | undefined {\n if (!expect?.trim()) return NO_EXPECTATION_NOTE\n if (expect.includes('\\n') || expect.includes('\\r')) return MULTILINE_EXPECTATION_NOTE\n return undefined\n}\n\nasync function runCheckProcess(\n args: string[],\n options: VerifyGradeableEvidenceOptions,\n): Promise<CheckExecution> {\n const { runBoundedProcess } = await import('@tangle-network/agent-eval')\n const result = await runBoundedProcess({\n command: options.bashPath ?? 'bash',\n args,\n cwd: options.cwd,\n // The exact environment the caller named, and nothing else: a check is graded on what it could\n // read, so an inherited variable would make the grade depend on this process.\n env: options.env ?? {},\n envMode: 'replace',\n timeoutMs: options.timeoutMs ?? 30_000,\n maxOutputBytes: options.maxBufferBytes ?? 1024 * 1024,\n signal: options.signal,\n })\n return {\n exitCode: result.exitCode,\n stdout: result.stdout,\n // `runnerError` is the runner's own text for a run that never started — a missing\n // interpreter, a signal that had already fired. It is appended rather than replacing\n // stderr, because a caller reading a failed check wants both what the check said and why\n // the runner could not run it.\n stderr: result.runnerError ? `${result.stderr}\\n${result.runnerError}`.trim() : result.stderr,\n ...(result.killedByTimeout ? { timedOut: true } : {}),\n ...(result.killedBySignal ? { killedBySignal: true } : {}),\n ...(result.outputTruncated ? { outputTruncated: true } : {}),\n }\n}\n","import { parseKnowledgeCitationReference } from './citation-resolution'\nimport {\n assertGradeableEvidence,\n CHECKABLE_RUNG_THRESHOLD,\n type ClaimEvidence,\n type EvidenceRung,\n UncheckableClaimError,\n} from './claim-evidence'\nimport { KnowledgePageInvalidationSchema } from './schemas'\nimport { isScaffoldPath } from './store'\nimport type { KnowledgeIndex, KnowledgeLintFinding, KnowledgePage } from './types'\nimport { normalizeLinkTarget } from './wikilinks'\n\nconst ABSOLUTE_PATH_TOKEN = /(?:^|[\\s\"'=(])(?:\\/(?!dev\\/null\\b)[^\\s\"'();]+|[A-Za-z]:\\\\[^\\s\"'();]+)/m\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 invalidatedIds = new Set<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 if (page.invalidation !== undefined) invalidatedIds.add(page.id)\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 findings.push(...lintPageEvidence(page))\n findings.push(...lintPageContradictions(page, pageIds))\n findings.push(...lintPageInvalidation(page))\n findings.push(...lintPageInvalidatedCitations(page, pageIds, invalidatedIds))\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 lintPageEvidence(page: KnowledgePage): KnowledgeLintFinding[] {\n if (page.frontmatter.rung === undefined) return []\n const rung = evidenceRung(page.frontmatter.rung)\n if (rung === undefined) {\n return [\n {\n type: 'ungradeable-evidence',\n severity: 'error',\n page: page.path,\n message: 'Evidence rung must be an integer from 1 through 5.',\n metadata: { rung: page.frontmatter.rung },\n },\n ]\n }\n const check = stringValue(page.frontmatter.check)\n const expect = stringValue(page.frontmatter.expect)\n const evidencePath = stringValue(page.frontmatter.evidencePath)\n const evidence: ClaimEvidence = {\n rung,\n ...(check ? { check } : {}),\n ...(expect ? { expect } : {}),\n ...(evidencePath ? { evidencePath } : {}),\n }\n const findings: KnowledgeLintFinding[] = []\n try {\n assertGradeableEvidence(evidence)\n } catch (error) {\n if (!(error instanceof UncheckableClaimError)) throw error\n findings.push({\n type: 'ungradeable-evidence',\n severity: 'error',\n page: page.path,\n message: error.note,\n metadata: { rung: error.rung },\n })\n }\n if (rung >= CHECKABLE_RUNG_THRESHOLD && !evidence.evidencePath) {\n findings.push({\n type: 'missing-evidence-path',\n severity: 'warning',\n page: page.path,\n message: `Rung ${rung} evidence has no evidencePath for a human to inspect.`,\n metadata: { rung },\n })\n }\n for (const [field, value] of [\n ['check', evidence.check],\n ['evidencePath', evidence.evidencePath],\n ] as const) {\n if (value && ABSOLUTE_PATH_TOKEN.test(value)) {\n findings.push({\n type: 'nonportable-evidence',\n severity: 'warning',\n page: page.path,\n message: `${field} contains an absolute path and may not re-run outside the author machine.`,\n metadata: { rung, field },\n })\n }\n }\n return findings\n}\n\nfunction lintPageContradictions(\n page: KnowledgePage,\n pageIds: ReadonlyMap<string, string[]>,\n): KnowledgeLintFinding[] {\n const findings: KnowledgeLintFinding[] = []\n for (const targetId of page.contradicts ?? []) {\n const selfReference = targetId === page.id\n if (selfReference || !pageIds.has(targetId)) {\n findings.push({\n type: 'broken-contradiction',\n severity: 'error',\n page: page.path,\n message: selfReference\n ? `Page \"${page.id}\" cannot contradict itself.`\n : `Page contradicts unknown page id \"${targetId}\".`,\n metadata: { targetId },\n })\n }\n }\n return findings\n}\n\n/**\n * A citation into a page its own evidence refuted.\n *\n * The verdict lives on the cited page, so a reader arriving through the\n * citation never meets it. Ambiguous ids are left to the citation audit, which\n * owns that verdict.\n */\nfunction lintPageInvalidatedCitations(\n page: KnowledgePage,\n pageIds: ReadonlyMap<string, string[]>,\n invalidatedIds: ReadonlySet<string>,\n): KnowledgeLintFinding[] {\n const targetIds = [\n ...new Set(\n (page.cites ?? []).map((persisted) => parseKnowledgeCitationReference(persisted).pageId),\n ),\n ]\n .filter(\n (targetId) =>\n targetId !== page.id && pageIds.get(targetId)?.length === 1 && invalidatedIds.has(targetId),\n )\n .sort()\n if (targetIds.length === 0) return []\n return [\n {\n type: 'cites-invalidated',\n severity: 'warning',\n page: page.path,\n message: `Page cites invalidated ${targetIds.length === 1 ? 'page' : 'pages'} ${targetIds.join(', ')}.`,\n metadata: { targetIds },\n },\n ]\n}\n\nfunction lintPageInvalidation(page: KnowledgePage): KnowledgeLintFinding[] {\n if (page.frontmatter.invalidation === undefined) return []\n const parsed = KnowledgePageInvalidationSchema.safeParse(page.frontmatter.invalidation)\n if (parsed.success) return []\n return [\n {\n type: 'invalid-invalidation',\n severity: 'error',\n page: page.path,\n message:\n 'Page invalidation must record verdict=contradicted, an ISO observedAt timestamp, and a non-empty reason.',\n metadata: { issues: parsed.error.issues },\n },\n ]\n}\n\nfunction evidenceRung(value: unknown): EvidenceRung | undefined {\n const parsed = typeof value === 'string' && /^\\d+$/.test(value) ? Number(value) : value\n return parsed === 1 || parsed === 2 || parsed === 3 || parsed === 4 || parsed === 5\n ? parsed\n : undefined\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === 'string' && value.trim().length > 0 ? value : undefined\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 { KnowledgePage } from '../types'\n\nexport interface NearDuplicateDetectionOptions {\n /** Jaccard similarity at or above which a pair is reported. Defaults to 0.82. */\n threshold?: number\n /** Minimum normalized characters before a page participates. Defaults to 80. */\n minCharacters?: number\n /** Word-shingle width. Defaults to 5. */\n wordShingleSize?: number\n /** Character-shingle width used for text with too few words. Defaults to 16. */\n characterShingleSize?: number\n /** Ignore a shingle occurring in more pages than this. Defaults to 64. */\n maxDocumentFrequency?: number\n /** Stop adding candidate pairs after this many. Defaults to 250,000. */\n maxCandidatePairs?: number\n /** Maximum duplicate pairs retained in the report. Defaults to 1,000. */\n maxReportedPairs?: number\n}\n\nexport interface NearDuplicatePair {\n leftPageId: string\n leftPath: string\n rightPageId: string\n rightPath: string\n similarity: number\n intersectionSize: number\n unionSize: number\n exact: boolean\n}\n\nexport interface NearDuplicateReport {\n algorithm: 'deterministic-shingle-jaccard-v1'\n threshold: number\n pageCount: number\n eligiblePageCount: number\n candidatePairCount: number\n comparedPairCount: number\n duplicatePairCount: number\n duplicatePageCount: number\n duplicatePageRate: number\n truncated: boolean\n pairs: NearDuplicatePair[]\n}\n\ninterface PreparedPage {\n page: KnowledgePage\n normalized: string\n shingles: Set<string>\n}\n\n/**\n * Detect exact and near-duplicate pages without a model, embedding service, or clock.\n *\n * The detector uses word shingles when prose has enough tokens and Unicode\n * character shingles otherwise. An inverted index proposes candidate pairs;\n * high-document-frequency shingles are ignored so common boilerplate cannot\n * make candidate generation quadratic. Exact normalized copies are always\n * proposed before ordinary shingle candidates, even when every shingle is\n * common. Every limit and sort order is explicit so the same corpus produces\n * the same report on every run.\n */\nexport function detectNearDuplicatePages(\n pages: readonly KnowledgePage[],\n options: NearDuplicateDetectionOptions = {},\n): NearDuplicateReport {\n const threshold = finiteUnitInterval(options.threshold ?? 0.82, 'threshold')\n const minCharacters = nonNegativeInteger(options.minCharacters ?? 80, 'minCharacters')\n const wordShingleSize = positiveInteger(options.wordShingleSize ?? 5, 'wordShingleSize')\n const characterShingleSize = positiveInteger(\n options.characterShingleSize ?? 16,\n 'characterShingleSize',\n )\n const maxDocumentFrequency = positiveInteger(\n options.maxDocumentFrequency ?? 64,\n 'maxDocumentFrequency',\n )\n const maxCandidatePairs = positiveInteger(\n options.maxCandidatePairs ?? 250_000,\n 'maxCandidatePairs',\n )\n const maxReportedPairs = nonNegativeInteger(options.maxReportedPairs ?? 1_000, 'maxReportedPairs')\n\n const prepared = pages\n .map((page) => preparePage(page, wordShingleSize, characterShingleSize))\n .filter(\n (item): item is PreparedPage => item !== null && item.normalized.length >= minCharacters,\n )\n .sort((left, right) => left.page.path.localeCompare(right.page.path))\n\n const candidateKeys = new Set<string>()\n const exactGroups = new Map<string, number[]>()\n const byShingle = new Map<string, number[]>()\n for (const [index, item] of prepared.entries()) {\n exactGroups.set(item.normalized, [...(exactGroups.get(item.normalized) ?? []), index])\n for (const shingle of item.shingles) {\n byShingle.set(shingle, [...(byShingle.get(shingle) ?? []), index])\n }\n }\n\n let truncated = false\n const addPair = (left: number, right: number): boolean => {\n if (left === right) return true\n const key = pairKey(Math.min(left, right), Math.max(left, right))\n if (candidateKeys.has(key)) return true\n if (candidateKeys.size >= maxCandidatePairs) {\n truncated = true\n return false\n }\n candidateKeys.add(key)\n return true\n }\n\n for (const normalized of [...exactGroups.keys()].sort()) {\n if (!addGroupPairs(exactGroups.get(normalized)!, addPair)) break\n }\n if (!truncated) {\n for (const shingle of [...byShingle.keys()].sort()) {\n const group = byShingle.get(shingle)!\n if (group.length > maxDocumentFrequency) continue\n if (!addGroupPairs(group, addPair)) break\n }\n }\n\n const duplicatePageIndices = new Set<number>()\n const pairs: NearDuplicatePair[] = []\n let duplicatePairCount = 0\n let comparedPairCount = 0\n for (const key of [...candidateKeys].sort(pairKeyOrder)) {\n const [leftIndex, rightIndex] = parsePairKey(key)\n const left = prepared[leftIndex]!\n const right = prepared[rightIndex]!\n comparedPairCount += 1\n const exact = left.normalized === right.normalized\n const overlap = jaccard(left.shingles, right.shingles)\n if (!exact && overlap.similarity < threshold) continue\n duplicatePairCount += 1\n duplicatePageIndices.add(leftIndex)\n duplicatePageIndices.add(rightIndex)\n if (pairs.length >= maxReportedPairs) {\n truncated = true\n continue\n }\n pairs.push({\n leftPageId: left.page.id,\n leftPath: left.page.path,\n rightPageId: right.page.id,\n rightPath: right.page.path,\n similarity: exact ? 1 : round(overlap.similarity),\n intersectionSize: overlap.intersectionSize,\n unionSize: overlap.unionSize,\n exact,\n })\n }\n\n pairs.sort(\n (left, right) =>\n right.similarity - left.similarity ||\n left.leftPath.localeCompare(right.leftPath) ||\n left.rightPath.localeCompare(right.rightPath),\n )\n\n return {\n algorithm: 'deterministic-shingle-jaccard-v1',\n threshold,\n pageCount: pages.length,\n eligiblePageCount: prepared.length,\n candidatePairCount: candidateKeys.size,\n comparedPairCount,\n duplicatePairCount,\n duplicatePageCount: duplicatePageIndices.size,\n duplicatePageRate:\n prepared.length === 0 ? 0 : round(duplicatePageIndices.size / prepared.length),\n truncated,\n pairs,\n }\n}\n\nfunction preparePage(\n page: KnowledgePage,\n wordShingleSize: number,\n characterShingleSize: number,\n): PreparedPage | null {\n const normalized = normalizePageText(`${page.title}\\n${page.text}`)\n if (normalized.length === 0) return null\n const words = normalized.match(/[\\p{L}\\p{N}]+/gu) ?? []\n const shingles =\n words.length >= wordShingleSize + 2\n ? sequenceShingles(words, wordShingleSize)\n : characterShingles(normalized.replace(/\\s+/g, ''), characterShingleSize)\n if (shingles.size === 0) shingles.add(normalized)\n return { page, normalized, shingles }\n}\n\nexport function normalizePageText(value: string): string {\n return value\n .normalize('NFKC')\n .toLowerCase()\n .replace(/https?:\\/\\/\\S+/g, '<url>')\n .replace(/\\s+/g, ' ')\n .trim()\n}\n\nfunction sequenceShingles(items: readonly string[], width: number): Set<string> {\n const out = new Set<string>()\n if (items.length < width) return out\n for (let index = 0; index <= items.length - width; index += 1) {\n out.add(items.slice(index, index + width).join('\\u001f'))\n }\n return out\n}\n\nfunction characterShingles(value: string, width: number): Set<string> {\n const chars = [...value]\n const out = new Set<string>()\n if (chars.length < width) return out\n for (let index = 0; index <= chars.length - width; index += 1) {\n out.add(chars.slice(index, index + width).join(''))\n }\n return out\n}\n\nfunction addGroupPairs(\n group: readonly number[],\n add: (left: number, right: number) => boolean,\n): boolean {\n for (let left = 0; left < group.length; left += 1) {\n for (let right = left + 1; right < group.length; right += 1) {\n if (!add(group[left]!, group[right]!)) return false\n }\n }\n return true\n}\n\nfunction jaccard(\n left: ReadonlySet<string>,\n right: ReadonlySet<string>,\n): {\n similarity: number\n intersectionSize: number\n unionSize: number\n} {\n const [small, large] = left.size <= right.size ? [left, right] : [right, left]\n let intersectionSize = 0\n for (const item of small) if (large.has(item)) intersectionSize += 1\n const unionSize = left.size + right.size - intersectionSize\n return {\n similarity: unionSize === 0 ? 1 : intersectionSize / unionSize,\n intersectionSize,\n unionSize,\n }\n}\n\nfunction pairKey(left: number, right: number): string {\n return `${left}:${right}`\n}\n\nfunction parsePairKey(value: string): [number, number] {\n const [left, right] = value.split(':')\n return [Number(left), Number(right)]\n}\n\nfunction pairKeyOrder(left: string, right: string): number {\n const [leftA, leftB] = parsePairKey(left)\n const [rightA, rightB] = parsePairKey(right)\n return leftA - rightA || leftB - rightB\n}\n\nfunction finiteUnitInterval(value: number, name: string): number {\n if (!Number.isFinite(value) || value < 0 || value > 1) {\n throw new Error(`${name} must be a finite number in [0, 1]`)\n }\n return value\n}\n\nfunction positiveInteger(value: number, name: string): number {\n if (!Number.isInteger(value) || value < 1) throw new Error(`${name} must be a positive integer`)\n return value\n}\n\nfunction nonNegativeInteger(value: number, name: string): number {\n if (!Number.isInteger(value) || value < 0) {\n throw new Error(`${name} must be a non-negative integer`)\n }\n return value\n}\n\nfunction round(value: number): number {\n return Math.round(value * 1_000_000) / 1_000_000\n}\n","/**\n * Run-scoped knowledge stores with lineage-chain reads.\n *\n * One store exists per run, physically isolated, with inheritance only through\n * declared ancestry. Reads expose the current store, every declared ancestor,\n * and an optional curated shared store with an explicit origin label.\n */\nimport { join } from 'node:path'\nimport { isMissingFile, readRegularFileWithinRoot } from './durable-fs'\nimport { withKnowledgeMutation } from './mutation-lock'\nimport { type KnowledgePagesOptions, normalizePagesDirectory } from './pages-directory'\nimport type { KnowledgeLayout } from './store'\nimport { initKnowledgeBase, loadKnowledgePages, writeJson } from './store'\nimport type { KnowledgePage } from './types'\n\n/** Where a page in a chained read came from. */\nexport type PageOrigin = 'here' | `inherited:${string}` | 'shared'\n\nexport interface OriginatedPage {\n page: KnowledgePage\n origin: PageOrigin\n}\n\n/**\n * Present plain pages as a visibility chain of one origin.\n *\n * A store read directly is the `here` origin of a chain with no ancestry, so\n * the chain-shaped APIs — citation resolution, the write intake gate,\n * invalidation propagation — take one page shape whether or not the caller\n * runs run-scoped stores.\n */\nexport function originatedPages(\n pages: readonly KnowledgePage[],\n origin: PageOrigin = 'here',\n): OriginatedPage[] {\n return pages.map((page) => ({ page, origin }))\n}\n\nexport interface RunLineageRecord {\n runId: string\n parentRunId: string | null\n createdAt: string\n}\n\n/**\n * Durable authority for run ancestry.\n *\n * A product whose run manifest already owns lineage can supply an authority\n * backed by that manifest. `record` is optional for read-only authorities; in\n * that case `init` verifies that the existing authority agrees with the parent\n * requested by the caller before creating any store files.\n */\nexport interface RunLineageAuthority {\n parentOf(runId: string): Promise<string | null>\n record?(record: RunLineageRecord): Promise<void>\n}\n\nexport const RUN_LINEAGE_BASENAME = 'lineage.json'\n\nexport interface RunScopedStoresOptions extends KnowledgePagesOptions {\n /** The root under which per-run stores live. */\n root: string\n /** Store path for a run; defaults to `<root>/<runId>/knowledge-base`. */\n runStorePath?: (runId: string) => string\n /**\n * The curated store every run may read but no run writes. Searched last and\n * labeled `shared`.\n */\n sharedRoot?: string\n /** External owner for run ancestry. Defaults to a record inside each run store. */\n lineageAuthority?: RunLineageAuthority\n /** Optional caller-owned bound on ancestor reads. Omit to read the complete finite chain.\n * Cycles and invalid identities are always refused; long valid history is not corruption. */\n maxAncestors?: number\n}\n\nexport interface RunScopedStores {\n /** Create or open a run store and bind it to one exact parent identity. */\n init(runId: string, options?: { parentRunId?: string | null }): Promise<KnowledgeLayout>\n /**\n * Where one run's store lives. A caller that must read a run's bytes rather\n * than its parsed pages — promotion carries a page unchanged — needs the\n * root the chain read hides.\n */\n storePath(runId: string): string\n /** The ancestor chain of a run, nearest first. */\n lineage(runId: string): Promise<string[]>\n /**\n * Every page visible to a run: current, ancestors, then shared. A repeated\n * page id is retained at every origin so citation resolution can report the\n * ambiguity instead of silently shadowing one page.\n */\n loadChain(runId: string): Promise<OriginatedPage[]>\n}\n\nexport function createRunScopedStores(options: RunScopedStoresOptions): RunScopedStores {\n if (!options || typeof options !== 'object') {\n throw new TypeError('createRunScopedStores options are required')\n }\n if (typeof options.root !== 'string' || options.root.trim().length === 0) {\n throw new TypeError('createRunScopedStores root must be a non-empty string')\n }\n if (options.runStorePath !== undefined && typeof options.runStorePath !== 'function') {\n throw new TypeError('createRunScopedStores runStorePath must be a function when present')\n }\n const maxAncestors = options.maxAncestors\n if (maxAncestors !== undefined && (!Number.isSafeInteger(maxAncestors) || maxAncestors < 0)) {\n throw new TypeError('createRunScopedStores maxAncestors must be a non-negative safe integer')\n }\n if (options.lineageAuthority !== undefined) validateLineageAuthority(options.lineageAuthority)\n const pagesDirectory = normalizePagesDirectory(options.pagesDirectory)\n\n const storePath =\n options.runStorePath ?? ((runId: string) => join(options.root, runId, 'knowledge-base'))\n const internalAuthority = createFileRunLineageAuthority(storePath)\n const authority = options.lineageAuthority ?? internalAuthority\n\n const resolveLineage = async (runId: string): Promise<string[]> => {\n assertRunId(runId)\n const chain: string[] = []\n const seen = new Set<string>([runId])\n let current = runId\n // The terminating null is read even at an explicit bound: an exactly-full chain is valid.\n for (;;) {\n const parent = await authority.parentOf(current)\n if (parent === null) return chain\n assertRunId(parent, `parent of '${current}'`)\n if (seen.has(parent)) {\n throw new Error(`run lineage cycle: ${parent} is its own ancestor (via ${runId})`)\n }\n if (maxAncestors !== undefined && chain.length >= maxAncestors) {\n throw new Error(`run lineage for '${runId}' exceeds caller maxAncestors=${maxAncestors}`)\n }\n seen.add(parent)\n chain.push(parent)\n current = parent\n }\n }\n\n return {\n storePath(runId) {\n assertRunId(runId)\n return storePath(runId)\n },\n\n async init(runId, initOptions = {}) {\n assertRunId(runId)\n const parentRunId = initOptions.parentRunId ?? null\n if (parentRunId !== null) assertRunId(parentRunId, `parent of '${runId}'`)\n\n // A read-only product authority already owns the identity. Verify it\n // before `initKnowledgeBase` creates directories or scaffold files, so a\n // rejected lineage request leaves no partial knowledge store behind.\n if (!authority.record) {\n const existingParent = await authority.parentOf(runId)\n if (existingParent !== parentRunId) {\n throw new Error(\n `external lineage authority disagrees for '${runId}': expected ${renderParent(parentRunId)}, observed ${renderParent(existingParent)}`,\n )\n }\n }\n\n const layout = await initKnowledgeBase(storePath(runId))\n if (authority.record) {\n await authority.record(\n Object.freeze({\n runId,\n parentRunId,\n createdAt: new Date().toISOString(),\n }),\n )\n }\n return layout\n },\n\n lineage: resolveLineage,\n\n async loadChain(runId) {\n assertRunId(runId)\n const out: OriginatedPage[] = []\n const readInto = async (root: string, origin: PageOrigin) => {\n let pages: KnowledgePage[]\n try {\n pages = await loadKnowledgePages(root, { pagesDirectory })\n } catch (error) {\n if (isMissingFile(error)) return\n throw error\n }\n for (const page of pages) out.push({ page, origin })\n }\n await readInto(storePath(runId), 'here')\n for (const ancestor of await resolveLineage(runId)) {\n await readInto(storePath(ancestor), `inherited:${ancestor}`)\n }\n if (options.sharedRoot) await readInto(options.sharedRoot, 'shared')\n return out\n },\n }\n}\n\n/** File-backed authority used when the product has no separate run manifest. */\nexport function createFileRunLineageAuthority(\n runStorePath: (runId: string) => string,\n): RunLineageAuthority {\n if (typeof runStorePath !== 'function') {\n throw new TypeError('createFileRunLineageAuthority requires a runStorePath function')\n }\n\n const readRecord = async (runId: string): Promise<RunLineageRecord | null> => {\n assertRunId(runId)\n const root = runStorePath(runId)\n try {\n const snapshot = await readRegularFileWithinRoot(root, RUN_LINEAGE_BASENAME)\n return parseLineageRecord(snapshot.bytes.toString('utf8'), runId)\n } catch (error) {\n if (isMissingFile(error)) return null\n throw error\n }\n }\n\n return {\n async parentOf(runId) {\n return (await readRecord(runId))?.parentRunId ?? null\n },\n\n async record(record) {\n const validated = validateLineageRecord(record)\n const root = runStorePath(validated.runId)\n await withKnowledgeMutation(root, async () => {\n const existing = await readRecord(validated.runId)\n if (existing) {\n if (existing.parentRunId !== validated.parentRunId) {\n throw new Error(\n `run lineage conflict for '${validated.runId}': existing parent ${renderParent(existing.parentRunId)}, requested ${renderParent(validated.parentRunId)}`,\n )\n }\n return\n }\n await writeJson(join(root, RUN_LINEAGE_BASENAME), validated)\n })\n },\n }\n}\n\nfunction validateLineageAuthority(authority: RunLineageAuthority): void {\n if (!authority || typeof authority !== 'object') {\n throw new TypeError('lineageAuthority must be an object')\n }\n if (typeof authority.parentOf !== 'function') {\n throw new TypeError('lineageAuthority.parentOf must be a function')\n }\n if (authority.record !== undefined && typeof authority.record !== 'function') {\n throw new TypeError('lineageAuthority.record must be a function when present')\n }\n}\n\nfunction parseLineageRecord(text: string, expectedRunId: string): RunLineageRecord {\n let parsed: unknown\n try {\n parsed = JSON.parse(text)\n } catch (cause) {\n throw new Error(`invalid lineage JSON for '${expectedRunId}'`, { cause })\n }\n const record = validateLineageRecord(parsed)\n if (record.runId !== expectedRunId) {\n throw new Error(\n `lineage record identity mismatch: expected '${expectedRunId}', found '${record.runId}'`,\n )\n }\n return record\n}\n\nfunction validateLineageRecord(value: unknown): RunLineageRecord {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new TypeError('run lineage record must be an object')\n }\n const record = value as Record<string, unknown>\n assertRunId(record.runId, 'lineage record runId')\n if (record.parentRunId !== null) {\n assertRunId(record.parentRunId, `parent of '${record.runId}'`)\n }\n if (\n typeof record.createdAt !== 'string' ||\n record.createdAt.trim().length === 0 ||\n !Number.isFinite(Date.parse(record.createdAt))\n ) {\n throw new TypeError('run lineage record createdAt must be an ISO timestamp')\n }\n return {\n runId: record.runId,\n parentRunId: record.parentRunId,\n createdAt: record.createdAt,\n }\n}\n\nfunction assertRunId(value: unknown, label = 'runId'): asserts value is string {\n if (typeof value !== 'string' || value.trim().length === 0) {\n throw new TypeError(`${label} must be a non-empty string`)\n }\n // A run id becomes a path segment under the store root. A separator or dot\n // segment would escape the root and break the physical-isolation promise.\n const trimmed = value.trim()\n if (trimmed === '.' || trimmed === '..' || /[/\\\\\\0]/.test(value)) {\n throw new TypeError(`${label} must not contain path separators or dot segments`)\n }\n}\n\nfunction renderParent(parentRunId: string | null): string {\n return parentRunId === null ? 'none' : `'${parentRunId}'`\n}\n","/**\n * Write-time intake gate.\n *\n * A store degrades in two ways that no post-hoc report reverses: a page lands\n * that restates knowledge already present without relating itself to it, and a\n * page lands citing an id that exists nowhere. Both are cheap to refuse at the\n * moment of the write and expensive to repair afterwards, so the gate runs\n * before bytes are committed.\n */\nimport {\n assertKnowledgeCitationsResolved,\n type KnowledgeCitationCandidate,\n parseKnowledgeCitationReference,\n} from './citation-resolution'\nimport {\n detectNearDuplicatePages,\n type NearDuplicateDetectionOptions,\n} from './rag-eval/near-duplicates'\nimport type { OriginatedPage } from './run-scoped'\nimport type { KnowledgeId, KnowledgePage } from './types'\n\n/** One candidate that duplicates visible knowledge without relating itself to it. */\nexport interface KnowledgeDuplicateIntakePair {\n readonly candidatePageId: KnowledgeId\n readonly candidatePath: string\n readonly matchedPageId: KnowledgeId\n readonly matchedPath: string\n readonly similarity: number\n readonly exact: boolean\n}\n\n/**\n * A write duplicates visible knowledge and declares no relation to it.\n *\n * Every listed pair is cleared by one authoring action: cite the matched page,\n * name it in `contradicts`, or give the candidate the matched page's id so the\n * write is an update of it.\n */\nexport class KnowledgeDuplicateIntakeError extends Error {\n readonly pairs: readonly KnowledgeDuplicateIntakePair[]\n readonly threshold: number\n\n constructor(pairs: readonly KnowledgeDuplicateIntakePair[], threshold: number) {\n const summary = pairs\n .map(\n (pair) =>\n `${pair.candidatePath} ~ ${pair.matchedPath} (${pair.exact ? 'exact copy' : pair.similarity.toFixed(3)})`,\n )\n .join('; ')\n super(\n `knowledge write intake refused ${pairs.length} duplicate ${pairs.length === 1 ? 'pair' : 'pairs'}: ${summary}. Cite the matched page, name it in contradicts, or reuse its id to update it.`,\n )\n this.name = 'KnowledgeDuplicateIntakeError'\n this.pairs = Object.freeze([...pairs])\n this.threshold = threshold\n }\n}\n\nexport interface KnowledgeWriteIntakeOptions {\n /**\n * The chain the write lands in, as `loadChain` reports it. Candidates replace\n * the `here` entries at the same paths; an inherited or shared page at one of\n * those paths stays visible, so a citation into it still reports its true\n * ambiguity.\n */\n readonly visiblePages: readonly OriginatedPage[]\n /** Near-duplicate detector settings. The detector's own defaults apply when absent. */\n readonly nearDuplicates?: NearDuplicateDetectionOptions\n /** Refuse a citation that resolves to no visible page. Defaults to true. */\n readonly citations?: boolean\n}\n\n/**\n * Refuse a write that duplicates visible knowledge or cites a page that exists\n * nowhere.\n *\n * The candidates are part of the corpus both checks see, so a batch may cite a\n * page it writes in the same call, and two candidates that duplicate each other\n * are caught before either lands.\n *\n * Returns the resolved citation candidates in the order the candidates declare\n * them.\n */\nexport function assertKnowledgeWriteIntake(\n candidates: readonly KnowledgePage[],\n options: KnowledgeWriteIntakeOptions,\n): readonly KnowledgeCitationCandidate[] {\n if (!Array.isArray(candidates)) {\n throw new TypeError('knowledge write intake candidates must be an array')\n }\n if (!options || typeof options !== 'object' || !Array.isArray(options.visiblePages)) {\n throw new TypeError('knowledge write intake requires the visible pages of the target chain')\n }\n const candidatePaths = new Set(candidates.map((candidate) => candidate.path))\n const corpus: OriginatedPage[] = [\n ...options.visiblePages.filter(\n (entry) => !(entry.origin === 'here' && candidatePaths.has(entry.page.path)),\n ),\n ...candidates.map((page) => ({ page, origin: 'here' as const })),\n ]\n\n assertNoUnrelatedDuplicate(candidatePaths, corpus, options.nearDuplicates ?? {})\n if (options.citations === false) return Object.freeze([])\n return assertKnowledgeCitationsResolved(\n corpus,\n candidates.flatMap((candidate) =>\n (candidate.cites ?? []).map((persisted: string) =>\n parseKnowledgeCitationReference(persisted),\n ),\n ),\n )\n}\n\nfunction assertNoUnrelatedDuplicate(\n candidatePaths: ReadonlySet<string>,\n corpus: readonly OriginatedPage[],\n nearDuplicates: NearDuplicateDetectionOptions,\n): void {\n if (candidatePaths.size === 0) return\n const report = detectNearDuplicatePages(\n corpus.map((entry) => entry.page),\n nearDuplicates,\n )\n const byIdentity = new Map<string, KnowledgePage>()\n for (const entry of corpus) {\n const key = identityKey(entry.page.path, entry.page.id)\n if (!byIdentity.has(key)) byIdentity.set(key, entry.page)\n }\n\n const offending: KnowledgeDuplicateIntakePair[] = []\n for (const pair of report.pairs) {\n const leftIsCandidate = candidatePaths.has(pair.leftPath)\n if (!leftIsCandidate && !candidatePaths.has(pair.rightPath)) continue\n // Two pages under one stable id are an identity defect, which the\n // `duplicate-page-id` lint owns. Here the same id means the write updates\n // the page it matched, which is the third way to relate the two.\n if (pair.leftPageId === pair.rightPageId) continue\n const left = byIdentity.get(identityKey(pair.leftPath, pair.leftPageId))!\n const right = byIdentity.get(identityKey(pair.rightPath, pair.rightPageId))!\n if (declaresRelation(left, right.id) || declaresRelation(right, left.id)) continue\n const candidate = leftIsCandidate ? left : right\n const matched = leftIsCandidate ? right : left\n offending.push({\n candidatePageId: candidate.id,\n candidatePath: candidate.path,\n matchedPageId: matched.id,\n matchedPath: matched.path,\n similarity: pair.similarity,\n exact: pair.exact,\n })\n }\n if (offending.length > 0) throw new KnowledgeDuplicateIntakeError(offending, report.threshold)\n}\n\nfunction identityKey(path: string, id: KnowledgeId): string {\n return `${path}\\u0000${id}`\n}\n\n/** Whether `page` already relates itself to `targetId` through `cites` or `contradicts`. */\nfunction declaresRelation(page: KnowledgePage, targetId: KnowledgeId): boolean {\n for (const persisted of page.cites ?? []) {\n if (parseKnowledgeCitationReference(persisted).pageId === targetId) return true\n }\n return (page.contradicts ?? []).includes(targetId)\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 { type KnowledgePagesOptions, normalizePagesDirectory } from './pages-directory'\nimport { type OriginatedPage, originatedPages } from './run-scoped'\nimport { isKnowledgePagePath, knowledgePageFromMarkdown, loadKnowledgePages } from './store'\nimport { assertKnowledgeWriteIntake, type KnowledgeWriteIntakeOptions } from './write-intake'\nimport { parseKnowledgeWriteBlocks } from './write-protocol'\n\nexport interface ApplyWriteBlocksResult {\n written: string[]\n warnings: string[]\n}\n\n/** Intake settings for a write, minus the pages the target root supplies itself. */\nexport type KnowledgeWriteIntakeRequest = Omit<KnowledgeWriteIntakeOptions, 'visiblePages'> & {\n /**\n * Pages visible to the write beyond the target root, such as the inherited\n * and shared entries of a run-scoped chain. The target root's own pages are\n * read under the same lock and are always part of the corpus.\n */\n readonly inheritedPages?: readonly OriginatedPage[]\n}\n\nexport interface ApplyKnowledgeWriteBlocksOptions extends KnowledgePagesOptions {\n /** Preserve terminal transactions under .agent-knowledge/history; no automatic deletion. */\n readonly retainHistory?: boolean\n /**\n * Refuse the write when a block duplicates visible knowledge without relating\n * itself to it, or cites a page that exists nowhere. The whole proposal is\n * refused, so a refused batch leaves no partial write behind.\n */\n intake?: KnowledgeWriteIntakeRequest\n}\n\n/**\n * Apply the FILE blocks of a proposal under the pages directory.\n *\n * A block whose path lies outside `<pagesDirectory>/` is refused by the parser\n * and again by the file transaction, so one option value bounds the whole\n * write.\n */\nexport async function applyKnowledgeWriteBlocks(\n root: string,\n proposalText: string,\n options: ApplyKnowledgeWriteBlocksOptions = {},\n): Promise<ApplyWriteBlocksResult> {\n const pagesDirectory = normalizePagesDirectory(options.pagesDirectory)\n const parsed = parseKnowledgeWriteBlocks(proposalText, [`${pagesDirectory}/`])\n const purpose = `knowledge-proposal:${contentHash(parsed.blocks)}`\n const intake = options.intake\n return withKnowledgeMutation(\n root,\n async (lock) => {\n if (parsed.blocks.length > 0) {\n const mutations = parsed.blocks.map((block) => ({\n path: block.path,\n content: block.content.endsWith('\\n') ? block.content : `${block.content}\\n`,\n }))\n if (intake) {\n const { inheritedPages = [], ...settings } = intake\n const here = await loadKnowledgePages(root, { pagesDirectory })\n assertKnowledgeWriteIntake(\n mutations\n .filter((mutation) => isKnowledgePagePath(mutation.path))\n .map((mutation) =>\n knowledgePageFromMarkdown(mutation.path, mutation.content, pagesDirectory),\n ),\n {\n ...settings,\n visiblePages: [...originatedPages(here), ...inheritedPages],\n },\n )\n }\n await commitKnowledgeFileMutations({\n root,\n transactionRoot: lock.transactionRoot,\n purpose,\n mutations,\n pagesDirectory,\n retainHistory: options.retainHistory,\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 options: ApplyKnowledgeWriteBlocksOptions = {},\n): Promise<ApplyWriteBlocksResult> {\n return applyKnowledgeWriteBlocks(root, await readFile(proposalPath, 'utf8'), options)\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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"}
|