@saasontools/strauss-kb 0.1.23 → 0.2.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/ARCHITECTURE.md +12 -0
- package/README.md +1 -0
- package/dist/{chunk-5IPQVXCM.js → chunk-7J2BBP67.js} +2 -2
- package/dist/{chunk-3EZ3PAPA.js → chunk-GMZDXWWU.js} +2 -2
- package/dist/{chunk-XENLCPL5.js → chunk-HNPHL6I4.js} +7649 -478
- package/dist/chunk-HNPHL6I4.js.map +1 -0
- package/dist/cli-main.cjs +7707 -541
- package/dist/cli-main.cjs.map +1 -1
- package/dist/cli-main.js +2 -2
- package/dist/index.cjs +7565 -395
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +98 -48
- package/dist/index.d.ts +98 -48
- package/dist/index.js +13 -3
- package/dist/mcp-main.cjs +7701 -535
- package/dist/mcp-main.cjs.map +1 -1
- package/dist/mcp-main.js +2 -2
- package/package.json +2 -1
- package/dist/chunk-XENLCPL5.js.map +0 -1
- /package/dist/{chunk-5IPQVXCM.js.map → chunk-7J2BBP67.js.map} +0 -0
- /package/dist/{chunk-3EZ3PAPA.js.map → chunk-GMZDXWWU.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/anchor-resolver/repo-identity.ts","../src/remote-repo/cache.ts","../src/remote-repo/read.ts","../src/concurrency.ts","../src/remote-repo/git.ts","../src/anchor-resolver/model.ts","../src/remote-repo/model.ts","../src/remote-repo/validate.ts","../src/anchor-resolver/read.ts","../src/grammars/store.ts","../src/grammars/manifest.ts","../src/grammars/model.ts","../src/grammars/index.ts","../src/grammars/fetch.ts","../src/tree-sitter-resolver/languages.ts","../src/tree-sitter-resolver/resolver.ts","../src/tree-sitter-resolver/definitions.ts","../src/tree-sitter-resolver/tokens.ts","../src/anchor-resolver/resolver.ts","../src/drift/git.ts","../src/anchor-resolver/drift.ts","../src/kb-record.schema.ts","../src/errors.ts","../src/anchors/errors.ts","../src/anchors/apply.ts","../src/record-types.ts","../src/compose.ts","../src/decision-record.ts","../src/kb-errors.ts","../src/kb-pins/budgets.ts","../src/kb-pins/errors.ts","../src/kb-pins/model.ts","../src/kb-pins/layers.ts","../src/kb-pins/frozen.ts","../src/kb-pins/list.ts","../src/kb-pins/pin.ts","../src/kb-pins/unpin.ts","../src/commands/anchor-set/model.ts","../src/commands/model.ts","../src/commands/anchor-resolve/command.ts","../src/commands/anchor-resolve/apply.ts","../src/commands/anchor-resolve/sources.ts","../src/commands/anchor-resolve/plan.ts","../src/commands/anchor-set/command.ts","../src/adjudicate.ts","../src/kb-tags.ts","../src/catalog.ts","../src/match-diff.ts","../src/classify/model.ts","../src/classify/rules.ts","../src/classify/classify.ts","../src/drift/moved.ts","../src/drift/classify.ts","../src/drift/diff.ts","../src/drift/packet.ts","../src/kb-index.ts","../src/kb-context.ts","../src/kb-edges.ts","../src/validate.ts","../src/doctor.ts","../src/commands/promote/carry.ts","../src/kb-links/inbound.ts","../src/kb-links/backlinks.ts","../src/kb-links/impact.ts","../src/commands/promote/standing.ts","../src/commands/promote/candidates.ts","../src/commands/promote/model.ts","../src/commands/promote/command.ts","../src/kb-log.ts","../src/json-schema.ts","../src/trace.ts","../src/commands/answer.ts","../src/commands/backlinks.ts","../src/commands/catalog.ts","../src/commands/classify.ts","../src/commands/match/command.ts","../src/commands/match/errors.ts","../src/commands/match/model.ts","../src/commands/match/parse-unified-diff.ts","../src/commands/match/symbol-ranges.ts","../src/commands/context.ts","../src/commands/doctor.ts","../src/commands/reassess.ts","../src/commands/export.ts","../src/commands/impact.ts","../src/commands/list.ts","../src/commands/load.ts","../src/commands/log.ts","../src/commands/no-decision.ts","../src/commands/pack.ts","../src/commands/pin.ts","../src/commands/pins.ts","../src/commands/query.ts","../src/commands/read-index.ts","../src/commands/schema.ts","../src/commands/stamp.ts","../src/commands/status.ts","../src/commands/supersede.ts","../src/commands/sweep.ts","../src/commands/sync-instructions.ts","../src/commands/trace.ts","../src/commands/types.ts","../src/commands/unpin.ts","../src/commands/validate.ts","../src/commands/verify.ts","../src/commands/write.ts","../src/commands/write-decision.ts","../src/commands/index.ts","../src/markdown.ts","../src/search-index.ts","../src/kb-store.ts","../src/kb-stamp.ts","../src/kb-files.ts","../src/kb-gitattributes.ts","../src/pack.ts","../src/version.ts"],"sourcesContent":["import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport type { KbAnchor } from \"../kb-record.schema.js\";\n\nconst execFileAsync = promisify(execFile);\n\n/* -------------------------------------------------------------------------\n * Which repository is this?\n * ---------------------------------------------------------------------- */\n\n/**\n * Repository identity, normalised on both sides and compared rather than\n * parsed; see ARCHITECTURE.\n *\n * Trailing slashes come off in a loop rather than with `/\\/+$/`, which\n * backtracks quadratically on untrusted bundle data.\n */\nexport function normalizeRepoUrl(value: string): string {\n let url = value.trim().replace(/^git\\+/, \"\");\n // scp-style: git@host:org/name\n const scp = /^[\\w.-]+@([\\w.-]+):(.+)$/.exec(url);\n if (scp) url = `https://${scp[1]}/${scp[2]}`;\n url = url.replace(/^ssh:\\/\\/(?:[^@/]+@)?/, \"https://\");\n // Slashes, then `.git`, then slashes again: a remote is written `…/name`,\n // `…/name.git`, and `…/name.git/` interchangeably, and all three name one\n // repository.\n url = trimTrailingSlashes(url);\n if (url.endsWith(\".git\")) url = url.slice(0, -4);\n return trimTrailingSlashes(url).toLowerCase();\n}\n\nfunction trimTrailingSlashes(value: string): string {\n let end = value.length;\n while (end > 0 && value[end - 1] === \"/\") end -= 1;\n return value.slice(0, end);\n}\n\n/**\n * Does this spelling say where the repository lives?\n *\n * Only a full URL can be fetched from. A short form still matches this root's\n * own origin, which is why `validate` warns rather than rejects.\n */\nexport function isCanonicalRepoUrl(value: string): boolean {\n return /^[a-z0-9+.-]+:\\/\\//.test(normalizeRepoUrl(value));\n}\n\n/** `org/name` from a normalized URL, or \"\" when it carries no host. */\nfunction repoPath(normalized: string): string {\n const withoutScheme = normalized.replace(/^[a-z0-9+.-]+:\\/\\//, \"\");\n const segments = withoutScheme.split(\"/\").filter(Boolean);\n return segments.length > 1 ? segments.slice(1).join(\"/\") : \"\";\n}\n\n/**\n * Does `declared` name the repository `originUrl` points at?\n *\n * Three spellings are accepted, narrowest first: the whole URL, the `org/name`\n * path, and the bare repository name. The bare name is the loosest and could\n * in principle collide across organisations; it is accepted because it is what\n * people actually write, and the cost of a false positive here is resolving an\n * anchor that was already meant for a repository of that name.\n */\nexport function repoIdentifies(\n declared: string,\n originUrl: string | null,\n): boolean {\n if (!originUrl) return false;\n const origin = normalizeRepoUrl(originUrl);\n const want = normalizeRepoUrl(declared);\n if (!want || !origin) return false;\n if (want === origin) return true;\n\n const path = repoPath(origin);\n if (!path) return false;\n return want === path || want === (path.split(\"/\").pop() ?? \"\");\n}\n\n/**\n * The `origin` remote of the tree at `repoRoot`, or `null`.\n *\n * `null` for anything that is not a git checkout, has no `origin`, or where\n * git is unavailable — all of which mean the same thing here: this root cannot\n * prove which repository it is. An anchor naming a repository is then treated\n * as foreign rather than resolved hopefully, because a hash that matched by\n * coincidence would be recorded as evidence.\n */\nexport async function repoOriginUrl(repoRoot: string): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"-C\", repoRoot, \"config\", \"--get\", \"remote.origin.url\"],\n { timeout: 5_000 },\n );\n return stdout.trim() || null;\n } catch {\n return null;\n }\n}\n\n/**\n * \"Is this anchor for another repository?\", answered without asking git until\n * an anchor actually declares a `repo`, and only once per run after that.\n */\nexport class LazyOrigin {\n private url: string | null = null;\n private asked = false;\n\n constructor(private readonly repoRoot: string) {}\n\n /** Asks git once, so later `isForeign` calls need no await. */\n async prime(): Promise<void> {\n if (this.asked) return;\n this.url = await repoOriginUrl(this.repoRoot);\n this.asked = true;\n }\n\n /** Only meaningful after `prime`; an unprimed origin identifies nothing. */\n isForeign(anchor: KbAnchor): boolean {\n if (!anchor.repo) return false;\n return !repoIdentifies(anchor.repo, this.url);\n }\n\n async foreign(anchor: KbAnchor): Promise<boolean> {\n if (!anchor.repo) return false;\n await this.prime();\n return this.isForeign(anchor);\n }\n}\n","import { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { normalizeRepoUrl } from \"../anchor-resolver/repo-identity.js\";\n\n/** Where bare mirrors live. Overridable so a test never writes to `$HOME`. */\nexport function repoCacheDir(override?: string): string {\n return (\n override ??\n process.env[\"STRAUSS_KB_REPO_CACHE\"] ??\n join(homedir(), \".strauss\", \"repo-cache\")\n );\n}\n\n/** Fetch timeout in ms; a remote that hangs must not hang the run. */\nexport const DEFAULT_FETCH_TIMEOUT_MS = 30_000;\n\nexport function fetchTimeoutMs(override?: number): number {\n if (override !== undefined) return override;\n const fromEnv = Number(process.env[\"STRAUSS_KB_FETCH_TIMEOUT_MS\"]);\n return Number.isFinite(fromEnv) && fromEnv > 0\n ? fromEnv\n : DEFAULT_FETCH_TIMEOUT_MS;\n}\n\n/**\n * `<cache>/<host>/<org>/<name>.git` for a repository URL.\n *\n * `null` when the declared `repo` carries no path git could fetch — a short\n * form like `org/name` names a repository without saying where it lives.\n */\nexport function cachePathFor(repo: string, cacheDir: string): string | null {\n const normalized = normalizeRepoUrl(repo);\n const scheme = /^[a-z0-9+.-]+:\\/\\//.exec(normalized);\n if (!scheme) return null;\n const segments = normalized\n .slice(scheme[0].length)\n .split(\"/\")\n .filter(Boolean)\n .map((segment: string) => safeSegment(segment));\n if (segments.length < 2 || segments.some((segment) => segment === null)) {\n return null;\n }\n const path = segments as string[];\n return join(cacheDir, ...path.slice(0, -1), `${path[path.length - 1]}.git`);\n}\n\n/**\n * A path segment a repository URL may contribute to a directory name. A\n * Windows `file:///C:/…` contributes its drive as the first one, and `:` is\n * not legal in a directory name there, so it is folded like any other\n * separator rather than special-cased.\n */\nfunction safeSegment(value: string): string | null {\n return value === \".\" || value === \"..\" || value.includes(\"\\0\")\n ? null\n : value.replace(/[/\\\\:]/g, \"-\");\n}\n\n/**\n * A git ref name holding one fetched rev, stable across runs so a second run\n * reads the cache instead of fetching again.\n */\nexport function revRef(rev: string): string {\n // `.` is dropped rather than kept: `v1..2` would be an invalid ref name.\n const safe = rev.replace(/[^A-Za-z0-9_-]/g, \"-\").slice(0, 64);\n let hash = 5381;\n for (let at = 0; at < rev.length; at++) {\n hash = ((hash * 33) ^ rev.charCodeAt(at)) >>> 0;\n }\n return `refs/strauss/${safe}-${hash.toString(16)}`;\n}\n","import { mkdir } from \"node:fs/promises\";\nimport type { AnchorUnresolvedReason } from \"../anchor-resolver/model.js\";\nimport { normalizeRepoUrl } from \"../anchor-resolver/repo-identity.js\";\nimport { DEFAULT_IO_CONCURRENCY, mapLimit } from \"../concurrency.js\";\nimport { cachePathFor, fetchTimeoutMs, repoCacheDir, revRef } from \"./cache.js\";\nimport { git, transportReason } from \"./git.js\";\nimport {\n wantKey,\n type RemoteOptions,\n type RemoteRead,\n type RemoteWant,\n} from \"./model.js\";\nimport {\n filePathIsSafe,\n isShortRepoName,\n protocolArgs,\n refIsWellFormed,\n refShapeIsSafe,\n repoUrlIsSafe,\n} from \"./validate.js\";\n\n/** Repositories fetched at once. Fetches within one repo stay serial. */\nconst DEFAULT_REPO_CONCURRENCY = 4;\n\n/** A full commit sha can never mean different content, so it is fetched once. */\nconst IMMUTABLE_REV = /^[0-9a-f]{40}$/;\n\n/**\n * Reads each wanted (repo, rev, file) out of a bare cache under\n * `~/.strauss/repo-cache`, fetching once per (repo, rev) and never per anchor.\n *\n * Every failure lands as an `unresolved` reason on the wants it affects; no\n * path is read from disk, so containment does not apply here.\n */\nexport async function readRemoteAnchors(\n wants: readonly RemoteWant[],\n options: RemoteOptions = {},\n): Promise<Map<string, RemoteRead>> {\n const out = new Map<string, RemoteRead>();\n if (!wants.length) return out;\n\n const cacheDir = repoCacheDir(options.cacheDir);\n const timeoutMs = fetchTimeoutMs(options.fetchTimeoutMs);\n const byRepo = new Map<string, { url: string; wants: RemoteWant[] }>();\n for (const want of wants) {\n const key = normalizeRepoUrl(want.repo);\n const group = byRepo.get(key) ?? { url: want.repo.trim(), wants: [] };\n group.wants.push(want);\n byRepo.set(key, group);\n }\n\n const groups = [...byRepo.entries()];\n const results = await mapLimit(\n groups,\n Math.max(1, options.concurrency ?? DEFAULT_REPO_CONCURRENCY),\n ([repo, group]) =>\n readOneRepo(repo, group.url, group.wants, {\n cacheDir,\n timeoutMs,\n offline: options.offline === true,\n }),\n );\n for (const result of results) {\n for (const [key, read] of result) out.set(key, read);\n }\n return out;\n}\n\ntype RepoContext = { cacheDir: string; timeoutMs: number; offline: boolean };\n\nasync function readOneRepo(\n repo: string,\n url: string,\n declared: readonly RemoteWant[],\n context: RepoContext,\n): Promise<Map<string, RemoteRead>> {\n let wants: readonly RemoteWant[] = declared;\n const all = (read: RemoteRead) =>\n new Map(wants.map((want) => [wantKey(repo, want.ref, want.file), read]));\n\n // A short `repo` (`org/name`) names a repository without saying where it\n // lives, so there is nothing to fetch from. `validate` warns on the spelling.\n if (isShortRepoName(url)) {\n return all({ ok: false, reason: \"remote-unreachable\" });\n }\n // Anything else that is not a remote we will fetch over is a finding about\n // the record, decided before a single `git` runs.\n if (!repoUrlIsSafe(url)) return all({ ok: false, reason: \"repo-invalid\" });\n\n const cache = cachePathFor(repo, context.cacheDir);\n if (!cache) return all({ ok: false, reason: \"remote-unreachable\" });\n\n // Ref and path shapes are checked with no subprocess, so a want carrying an\n // option-shaped `ref` or `file` never reaches git — not even `git init`.\n const rejected = new Map<string, RemoteRead>();\n const usable: RemoteWant[] = [];\n for (const want of wants) {\n const reason = wantReason(want);\n if (reason)\n rejected.set(wantKey(repo, want.ref, want.file), { ok: false, reason });\n else usable.push(want);\n }\n if (!usable.length) return rejected;\n wants = usable;\n\n const opened = await openCache(cache, url, context);\n if (opened) return new Map([...rejected, ...all(opened)]);\n\n const wantsDefault = wants.some((want) => want.ref === undefined);\n const branch: Branch = wantsDefault\n ? await defaultBranch(cache, context)\n : {};\n\n // One fetch per rev, serial: two `git fetch` in one bare repo race for the\n // same lock.\n const revs = new Map<string, RemoteRead | undefined>();\n for (const rev of distinctRevs(wants, branch.name)) {\n revs.set(\n rev,\n (await refIsWellFormed(rev))\n ? await ensureRev(cache, rev, context)\n : { ok: false, reason: \"ref-invalid\" },\n );\n }\n\n const reads = await mapLimit(\n wants,\n DEFAULT_IO_CONCURRENCY,\n async (want): Promise<RemoteRead> => {\n const rev = want.ref ?? branch.name;\n if (rev === undefined) {\n return {\n ok: false,\n reason: branch.reason ?? \"default-branch-unknown\",\n };\n }\n const failed = revs.get(rev);\n if (failed) return failed;\n return readBlob(cache, rev, want.file, context);\n },\n );\n return new Map([\n ...rejected,\n ...wants.map(\n (want, at) =>\n [wantKey(repo, want.ref, want.file), reads[at] as RemoteRead] as const,\n ),\n ]);\n}\n\n/**\n * Why this want cannot be handed to git, or `undefined`. A ref that would be\n * read as an option (`--upload-pack=…`) or a range (`a..b`) is a finding on the\n * record; a `file` that would be read as an option or climbs out of the tree is\n * the same `outside-repo` a working-tree read reports.\n */\nfunction wantReason(want: RemoteWant): AnchorUnresolvedReason | undefined {\n if (want.ref !== undefined && !refShapeIsSafe(want.ref)) return \"ref-invalid\";\n return filePathIsSafe(want.file) ? undefined : \"outside-repo\";\n}\n\nfunction distinctRevs(\n wants: readonly RemoteWant[],\n branch: string | undefined,\n): string[] {\n const revs = new Set<string>();\n for (const want of wants) {\n if (want.ref !== undefined) revs.add(want.ref);\n else if (branch) revs.add(branch);\n }\n return [...revs];\n}\n\n/** Creates the bare mirror if it is not there and points it at `url`. */\nasync function openCache(\n cache: string,\n url: string,\n context: RepoContext,\n): Promise<RemoteRead | undefined> {\n try {\n await mkdir(cache, { recursive: true });\n } catch {\n return { ok: false, reason: \"remote-unreachable\" };\n }\n const init = await git([\"init\", \"--bare\", \"--quiet\", cache], {\n timeoutMs: context.timeoutMs,\n });\n if (!init.ok) return { ok: false, reason: \"remote-unreachable\" };\n // `config`, not `remote add` or `remote set-url`: the first run has no\n // `origin` to set and the second must not fail because the first added it.\n // The URL is safe to pass unguarded only because the allowlist has already\n // run — nothing starting with `-` reaches here.\n const remote = await git([\"config\", \"remote.origin.url\", url], {\n cwd: cache,\n timeoutMs: context.timeoutMs,\n });\n return remote.ok ? undefined : { ok: false, reason: \"remote-unreachable\" };\n}\n\ntype Branch = { name?: string; reason?: AnchorUnresolvedReason };\n\n/**\n * The remote's default branch: asked once per repo per run, then remembered in\n * the cache so `--offline` and the next run have an answer.\n */\nasync function defaultBranch(\n cache: string,\n context: RepoContext,\n): Promise<Branch> {\n if (!context.offline) {\n const listed = await git(\n [...protocolArgs(), \"ls-remote\", \"--symref\", \"origin\", \"HEAD\"],\n {\n cwd: cache,\n timeoutMs: context.timeoutMs,\n },\n );\n const found = /^ref:\\s+refs\\/heads\\/(\\S+)\\s+HEAD$/m.exec(listed.stdout);\n if (listed.ok && found?.[1]) {\n const name = found[1];\n await git([\"config\", \"strauss.defaultBranch\", name], { cwd: cache });\n return { name };\n }\n if (!listed.ok) {\n const reason = transportReason(listed.stderr);\n if (reason !== \"ref-not-found\") {\n const cached = await cachedBranch(cache);\n return cached ? { name: cached } : { reason };\n }\n }\n }\n const cached = await cachedBranch(cache);\n if (cached) return { name: cached };\n // Offline with nothing cached is not a repository without a HEAD: the cause\n // is that nothing was reached, and that is what the finding should say.\n return {\n reason: context.offline ? \"remote-unreachable\" : \"default-branch-unknown\",\n };\n}\n\nasync function cachedBranch(cache: string): Promise<string | undefined> {\n const stored = await git([\"config\", \"--get\", \"strauss.defaultBranch\"], {\n cwd: cache,\n });\n if (stored.ok && stored.stdout.trim()) return stored.stdout.trim();\n const head = await git(\n [\"symbolic-ref\", \"--short\", \"refs/remotes/origin/HEAD\"],\n {\n cwd: cache,\n },\n );\n const name = head.stdout.trim().replace(/^origin\\//, \"\");\n return head.ok && name ? name : undefined;\n}\n\n/**\n * Fetches `rev` into a stable local ref, or reports why it could not.\n *\n * A full commit sha already in the cache is never refetched — its content\n * cannot change — while a branch is fetched every online run, because \"current\"\n * is exactly what a branch means.\n */\nasync function ensureRev(\n cache: string,\n rev: string,\n context: RepoContext,\n): Promise<RemoteRead | undefined> {\n const ref = revRef(rev);\n const have = await git(\n [\"rev-parse\", \"--verify\", \"--quiet\", `${ref}^{commit}`],\n {\n cwd: cache,\n },\n );\n const cached = have.ok && have.stdout.trim().length > 0;\n if (cached && (context.offline || IMMUTABLE_REV.test(rev))) return undefined;\n if (context.offline) return { ok: false, reason: \"remote-unreachable\" };\n\n // `--end-of-options` is what stops a rev from being parsed as an option; the\n // ref shape already refused one, and this is the layer that does not depend\n // on the shape being right.\n const fetched = await git(\n [\n ...protocolArgs(),\n \"fetch\",\n \"--depth\",\n \"1\",\n \"origin\",\n \"--end-of-options\",\n rev,\n ],\n { cwd: cache, timeoutMs: context.timeoutMs },\n );\n if (!fetched.ok) {\n // A stale cached copy beats no answer when the network is the problem;\n // a rev the remote no longer has is a finding either way.\n const reason = transportReason(fetched.stderr);\n if (cached && reason !== \"ref-not-found\") return undefined;\n return { ok: false, reason };\n }\n const head = await git([\"rev-parse\", \"FETCH_HEAD\"], { cwd: cache });\n const sha = head.stdout.trim();\n if (!head.ok || !sha) return { ok: false, reason: \"remote-unreachable\" };\n const updated = await git([\"update-ref\", ref, sha], { cwd: cache });\n return updated.ok ? undefined : { ok: false, reason: \"remote-unreachable\" };\n}\n\n/** `git cat-file blob <rev>:<file>`, capped at the same 1 MiB as a local read. */\nasync function readBlob(\n cache: string,\n rev: string,\n file: string,\n context: RepoContext,\n): Promise<RemoteRead> {\n const path = file.replace(/^\\.\\//, \"\");\n const blob = await git(\n [\"cat-file\", \"blob\", \"--end-of-options\", `${revRef(rev)}:${path}`],\n {\n cwd: cache,\n timeoutMs: context.timeoutMs,\n },\n );\n if (blob.ok) return { ok: true, source: blob.stdout };\n if (blob.overflowed) return { ok: false, reason: \"file-too-large\" };\n const text = blob.stderr.toLowerCase();\n return text.includes(\"does not exist\") || text.includes(\"not a valid object\")\n ? { ok: false, reason: \"file-missing\" }\n : { ok: false, reason: \"file-unreadable\" };\n}\n","/**\n * Bounded fan-out for the store's I/O paths.\n *\n * Unbounded `Promise.all` over a bundle hits EMFILE on a large base; a serial\n * loop pays full syscall latency per file. One shared pool sits between them.\n */\n\n/** Default in-flight file operations. Bounded so a large base cannot hit EMFILE. */\nexport const DEFAULT_IO_CONCURRENCY = 16;\n\n/**\n * Runs `fn` over `items` with at most `limit` in flight.\n *\n * Results are index-aligned with `items` regardless of completion order. A\n * rejection propagates; a caller wanting per-item isolation catches inside `fn`.\n */\nexport async function mapLimit<T, R>(\n items: readonly T[],\n limit: number,\n fn: (item: T, index: number) => Promise<R>,\n): Promise<R[]> {\n if (!Number.isInteger(limit) || limit < 1) {\n throw new RangeError(\n `mapLimit: \"limit\" must be a positive integer, got ${limit}`,\n );\n }\n const out = new Array<R>(items.length);\n let next = 0;\n let failed = false;\n const runners = Array.from(\n { length: Math.min(limit, items.length) },\n async () => {\n while (!failed && next < items.length) {\n const at = next++;\n try {\n out[at] = await fn(items[at] as T, at);\n } catch (error) {\n failed = true;\n throw error;\n }\n }\n },\n );\n await Promise.all(runners);\n return out;\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport {\n MAX_ANCHOR_FILE_BYTES,\n type AnchorUnresolvedReason,\n} from \"../anchor-resolver/model.js\";\n\nconst execFileAsync = promisify(execFile);\n\nexport type GitRun = {\n ok: boolean;\n stdout: string;\n stderr: string;\n /** Set when the child died because its output passed the blob cap. */\n overflowed: boolean;\n};\n\n/**\n * The environment a `git` child gets. `GIT_TERMINAL_PROMPT` is cleared so a\n * credential helper that decides to prompt cannot block the run forever on a\n * repository the caller has no access to. `GIT_DIR`, `GIT_WORK_TREE`, and\n * `GIT_INDEX_FILE` are stripped because they override `cwd` — a caller's\n * environment must not be able to redirect a cache operation at another\n * repository. The global config stays: it is where the user's own credential\n * helper lives.\n */\nfunction childEnv(): NodeJS.ProcessEnv {\n const env: NodeJS.ProcessEnv = { ...process.env, GIT_TERMINAL_PROMPT: \"0\" };\n for (const name of [\"GIT_DIR\", \"GIT_WORK_TREE\", \"GIT_INDEX_FILE\"]) {\n delete env[name];\n }\n return env;\n}\n\n/**\n * One `git` invocation, argv only — never a shell, because `repo`, `ref`, and\n * `file` are bundle data. A non-zero exit is a result, not a throw.\n */\nexport async function git(\n args: string[],\n options: { cwd?: string; timeoutMs?: number; maxBytes?: number } = {},\n): Promise<GitRun> {\n try {\n const { stdout, stderr } = await execFileAsync(\"git\", args, {\n ...(options.cwd ? { cwd: options.cwd } : {}),\n timeout: options.timeoutMs ?? 30_000,\n maxBuffer: options.maxBytes ?? MAX_ANCHOR_FILE_BYTES,\n encoding: \"utf8\",\n windowsHide: true,\n env: childEnv(),\n });\n return { ok: true, stdout, stderr, overflowed: false };\n } catch (error) {\n const failure = error as {\n stdout?: string;\n stderr?: string;\n code?: string | number;\n };\n return {\n ok: false,\n stdout: failure.stdout ?? \"\",\n stderr: failure.stderr ?? \"\",\n overflowed: failure.code === \"ERR_CHILD_PROCESS_STDIO_MAXBUFFER\",\n };\n }\n}\n\n/**\n * Which failure a git transport error was. Matched on message text because\n * git returns 128 for all of them; an unrecognised failure is unreachable,\n * the reason that never accuses the record of being wrong.\n */\nexport function transportReason(stderr: string): AnchorUnresolvedReason {\n const text = stderr.toLowerCase();\n if (\n text.includes(\"authentication failed\") ||\n text.includes(\"permission denied\") ||\n text.includes(\"could not read username\") ||\n text.includes(\"403 forbidden\") ||\n text.includes(\"access denied\")\n ) {\n return \"repo-unauthorized\";\n }\n if (\n text.includes(\"couldn't find remote ref\") ||\n text.includes(\"unadvertised object\") ||\n text.includes(\"not our ref\")\n ) {\n return \"ref-not-found\";\n }\n return \"remote-unreachable\";\n}\n","/**\n * The vocabulary anchor resolution is reported in.\n *\n * Every failure is a finding with a reason, never a throw: a record pointing\n * at code that moved is information, not a broken run.\n */\n\nexport type ResolvedSymbol = {\n text: string;\n /** 1-based, inclusive. */\n startLine: number;\n endLine: number;\n};\n\n/** Which resolver produced a span. Stamped on the anchor. */\nexport type AnchorResolverName = \"tree-sitter\" | \"regex\" | \"span\";\n\n/**\n * A resolver's verdict. `abstain` (\"not my language\") and `symbol-not-found`\n * (\"nothing I recognize declares this\") pass the symbol down the chain;\n * `symbol-ambiguous` and `resolver-unavailable` end it, because neither may be\n * answered by a looser resolver guessing.\n */\nexport type ResolverAttempt =\n | { kind: \"resolved\"; span: ResolvedSymbol }\n | {\n kind: \"unresolved\";\n reason: \"symbol-not-found\" | \"symbol-ambiguous\" | \"resolver-unavailable\";\n }\n | { kind: \"abstain\" };\n\n/** What the chain already knows when it calls a resolver. */\nexport type ResolverAttemptOptions = {\n /** A resolver that parsed this file already reported `symbol-not-found`. */\n afterParsedMiss?: boolean;\n};\n\nexport interface AnchorResolver {\n name: string;\n /** Loads whatever these files need, before any `resolve` call. Optional. */\n prepare?(files: readonly string[]): Promise<void>;\n /** The richer verdict the chain uses; defaults to `resolve`. */\n attempt?(\n source: string,\n symbol: string,\n file?: string,\n options?: ResolverAttemptOptions,\n ): ResolverAttempt;\n resolve(source: string, symbol: string, file?: string): ResolvedSymbol | null;\n /**\n * The span's normalised token stream — comments dropped, runs of whitespace\n * collapsed — or `null` when this resolver cannot parse the text.\n *\n * Only a resolver that understands the language can offer one, which is why\n * it is optional: a text heuristic normalising by guess would call two\n * different programs equal.\n */\n normalize?(text: string, file?: string): string | null;\n}\n\n/** A resolved span, and which resolver produced it. */\nexport type AnchorResolution =\n | {\n ok: true;\n span: ResolvedSymbol;\n resolver?: AnchorResolverName;\n /** The span's token stream, when the resolver that spanned it can parse. */\n normalized?: string;\n }\n | { ok: false; reason: AnchorUnresolvedReason };\n\n/** Why an anchor could not be compared. Never an error — always a finding. */\nexport type AnchorUnresolvedReason =\n | \"file-missing\"\n | \"symbol-not-found\"\n /** More than one definition carries the name, and guessing is not allowed. */\n | \"symbol-ambiguous\"\n /** The anchor's `span` runs past the end of the file it names. */\n | \"span-out-of-range\"\n /** `side: \"old\"` with no usable `ref`, or no such path at the rev. */\n | \"ref-unreadable\"\n /** The `ref` is not in this clone — a shallow checkout, not deleted code. */\n | \"ref-unavailable\"\n /** The extension has a grammar, but it would not load. Never a throw. */\n | \"resolver-unavailable\"\n | \"outside-repo\"\n | \"file-too-large\"\n | \"file-unreadable\"\n /** The remote could not be fetched, or `--offline` found nothing cached. */\n | \"remote-unreachable\"\n /** The anchor's `ref` is not on the remote any more. */\n | \"ref-not-found\"\n | \"repo-unauthorized\"\n /** No default branch, so there is no \"current\" to compare against. */\n | \"default-branch-unknown\"\n /** The anchor's `ref` is not a name git may safely be handed. */\n | \"ref-invalid\"\n /** The anchor's `repo` is not a remote we will fetch from. */\n | \"repo-invalid\";\n\n/**\n * A hash that changed because a more precise resolver took over, not because\n * the code did. Reported as drift so nothing is restamped silently, and\n * accepted by `--rebaseline` like any other.\n */\nexport type AnchorDriftReason = \"resolver-changed\";\n\n/**\n * How a ref-pinned foreign anchor stands. `drifted-on-default` is the one a\n * working-tree anchor has no equivalent of: the evidence is still true at the\n * commit it was taken from, and the code has moved since.\n */\nexport type RemoteAnchorState =\n \"matches-ref\" | \"drifted-from-ref\" | \"drifted-on-default\";\n\n/** Big enough for any hand-written source file, small enough to read eagerly. */\nexport const MAX_ANCHOR_FILE_BYTES = 1_048_576;\n\n/** What `hash` was taken over. Absent on an anchor means `raw`. */\nexport type AnchorHashKind = \"raw\" | \"ast\";\n\n/**\n * How an anchor's code changed, once the bytes are known to differ.\n *\n * The classes a machine can settle, so a reader only sees the ones it cannot:\n * `moved` and `cosmetic` are answered and closed, `gone` and `changed` are\n * handed on. Deliberately shallow — whether the record's *claim* still holds\n * is a reading, and no hash can stand in for one.\n */\nexport const KB_DRIFT_CLASSES = [\n \"moved\",\n \"cosmetic\",\n \"gone\",\n \"changed\",\n] as const;\n\nexport type KbDriftClass = (typeof KB_DRIFT_CLASSES)[number];\n\n/** Where a `moved` anchor's stored hash turned up. */\nexport type KbDriftMovedTo = {\n file: string;\n symbol?: string;\n startLine: number;\n endLine: number;\n};\n\nexport type KbAnchorDriftEntry = {\n file: string;\n symbol?: string;\n /** Set only for `side: \"old\"`: read at `ref`, never from the working tree. */\n side?: \"old\";\n state: \"match\" | \"drifted\" | \"unresolved\";\n storedHash: string;\n currentHash?: string;\n /** `null` when the anchor recorded no `lines` — size unknown, not zero. */\n diffSize: number | null;\n reason?: AnchorUnresolvedReason | AnchorDriftReason;\n /** Which resolver produced `currentHash`. Absent for a whole-file anchor. */\n resolver?: AnchorResolverName;\n /** Set only when the anchor was resolved against another repository. */\n repo?: string;\n remoteState?: RemoteAnchorState;\n /** What the compared hashes were taken over. */\n hashKind?: AnchorHashKind;\n /**\n * Provisional: `gone` or `changed`, the two a hash comparison alone can\n * settle. `moved` and `cosmetic` cost a repository search and a git read, so\n * `classifyDrift` refines this on the reassessment path rather than on every\n * `load`.\n */\n class?: KbDriftClass;\n /** Set by `classifyDrift` when the class is `moved`. */\n movedTo?: KbDriftMovedTo;\n};\n\nexport type AnchorRead =\n { ok: true; source: string } | { ok: false; reason: AnchorUnresolvedReason };\n\nexport type AnchorFileReader = (file: string) => Promise<AnchorRead>;\n","import type {\n AnchorDriftReason,\n AnchorUnresolvedReason,\n} from \"../anchor-resolver/model.js\";\n\n/**\n * A foreign anchor's file at one rev. `ref` absent means the remote's default\n * branch — the \"current\" side of a ref-pinned comparison.\n */\nexport type RemoteWant = { repo: string; ref?: string; file: string };\n\nexport type RemoteRead =\n { ok: true; source: string } | { ok: false; reason: AnchorUnresolvedReason };\n\nexport type RemoteOptions = {\n /** Cache only: no `fetch`, no `ls-remote`. */\n offline?: boolean;\n cacheDir?: string;\n fetchTimeoutMs?: number;\n /** Repositories worked on at once; fetches within one repo stay serial. */\n concurrency?: number;\n};\n\n/** Reasons that mean \"not checked\", as opposed to evidence that moved. */\nexport const UNCHECKED_REASONS: readonly AnchorUnresolvedReason[] = [\n \"remote-unreachable\",\n \"repo-unauthorized\",\n \"default-branch-unknown\",\n /** Local, but the same finding: a shallow clone has no rev to read. */\n \"ref-unavailable\",\n];\n\nexport function isUncheckedReason(\n reason: AnchorUnresolvedReason | AnchorDriftReason | undefined,\n): boolean {\n return (\n reason !== undefined &&\n UNCHECKED_REASONS.includes(reason as AnchorUnresolvedReason)\n );\n}\n\n/** One key per (repo, rev, file); `ref` absent is the default branch. */\nexport function wantKey(\n repo: string,\n ref: string | undefined,\n file: string,\n): string {\n return `${repo}\\u0000${ref ?? \"\"}\\u0000${file}`;\n}\n","import { git } from \"./git.js\";\n\n/**\n * `repo`, `ref`, and `file` are bundle data — a `.md` file the reader did not\n * write — and every one of them reaches `git` argv. An argv array stops the\n * shell, not git's own option parsing: `git fetch origin --upload-pack=<cmd>`\n * runs `<cmd>`, `ext::sh -c <cmd>` is a transport that does the same, and\n * `file:///` reads any repository the process can see. So each value is checked\n * against a shape before git ever sees it, and a value that fails is a finding\n * on the record rather than a command.\n */\n\n/** Long enough for any real branch, short enough to bound the argv. */\nconst MAX_REF_LENGTH = 200;\n\n/**\n * The shape a `ref` must have to reach git at all. The leading character class\n * excludes `-`, so no ref can be read as an option; `@`, `{`, `\\`, spaces, and\n * control characters are outside the class entirely.\n */\nconst REF_SHAPE = /^[A-Za-z0-9][A-Za-z0-9._/-]*$/;\n\n/** Checked with no subprocess, so an invalid ref never spawns git. */\nexport function refShapeIsSafe(ref: string): boolean {\n if (!ref || ref.length > MAX_REF_LENGTH) return false;\n // `a..b` is a range, not a rev, and `git fetch` would resolve it as one.\n if (ref.includes(\"..\")) return false;\n return REF_SHAPE.test(ref);\n}\n\n/** Wider than `refShapeIsSafe` (`~`, `^`) for a local read; never guards a fetch. */\nexport function localRevShapeIsSafe(rev: string): boolean {\n if (!rev || rev.length > MAX_REF_LENGTH) return false;\n if (rev.includes(\"..\")) return false;\n return /^[A-Za-z0-9][A-Za-z0-9._/^~-]*$/.test(rev);\n}\n\n/**\n * git's own opinion of the name, asked only once the shape has made it safe to\n * pass. `--allow-onelevel` because `main` and a bare sha are both legal here.\n */\nexport async function refIsWellFormed(ref: string): Promise<boolean> {\n if (!refShapeIsSafe(ref)) return false;\n const checked = await git([\"check-ref-format\", \"--allow-onelevel\", ref]);\n return checked.ok;\n}\n\n/**\n * A `file` that may become the path half of `<rev>:<path>`. A leading `-` would\n * be an option; `..` would climb out of the tree the anchor describes.\n */\nexport function filePathIsSafe(file: string): boolean {\n const path = file.replace(/^\\.\\//, \"\");\n if (!path || path.startsWith(\"-\") || path.includes(\"\\0\")) return false;\n return !path.split(\"/\").includes(\"..\");\n}\n\n/** Transports a remote may be fetched over. Plaintext `http` is not one. */\nconst DEFAULT_PROTOCOLS = [\"https\", \"ssh\", \"git\"] as const;\n\n/**\n * `STRAUSS_KB_REPO_PROTOCOLS` widens the set — a comma list. It exists so the\n * test suite can serve `file://` remotes off disk; it is not a production knob,\n * because every protocol it can add is one that reads or runs something local.\n */\nexport function allowedProtocols(): string[] {\n const raw = process.env[\"STRAUSS_KB_REPO_PROTOCOLS\"];\n if (raw === undefined) return [...DEFAULT_PROTOCOLS];\n const listed = raw\n .split(\",\")\n .map((entry) => entry.trim().toLowerCase())\n .filter(Boolean);\n return listed.length ? listed : [...DEFAULT_PROTOCOLS];\n}\n\n/**\n * A `repo` naming a repository without saying where it lives (`org/name`).\n * There is nothing to fetch from, which is not the same finding as a `repo`\n * spelled in a transport we refuse to use.\n */\nexport function isShortRepoName(repo: string): boolean {\n return /^[A-Za-z0-9._-]+(?:\\/[A-Za-z0-9._-]+)*$/.test(repo.trim());\n}\n\n/** scp-style `git@host:org/name`, which git reads as ssh. */\nconst SCP_LIKE = /^[\\w.-]+@[\\w.-]+:(?!\\/)\\S+$/;\n\nconst URL_SCHEME = /^([A-Za-z0-9+.-]+):\\/\\//;\n\n// eslint-disable-next-line no-control-regex -- refusing control bytes is the point\nconst CONTROL_CHARS = /[\\u0000-\\u001f\\u007f]/;\n\n/** Checked with no subprocess, so a rejected URL never reaches a git remote. */\nexport function repoUrlIsSafe(repo: string): boolean {\n const url = repo.trim();\n if (!url || url.startsWith(\"-\") || CONTROL_CHARS.test(url)) return false;\n\n const allowed = allowedProtocols();\n if (SCP_LIKE.test(url)) return allowed.includes(\"ssh\");\n\n const scheme = URL_SCHEME.exec(url);\n // No `://` means no transport we recognise — `ext::sh -c …` lands here.\n if (!scheme?.[1]) return false;\n if (!allowed.includes(scheme[1].toLowerCase())) return false;\n\n // `https://user:password@host/…` puts a secret in a URL a bundle wrote; a\n // credential belongs in git's own helper, not in a record.\n const authority = url.slice(scheme[0].length).split(\"/\")[0] ?? \"\";\n const at = authority.lastIndexOf(\"@\");\n return at < 0 || !authority.slice(0, at).includes(\":\");\n}\n\n/**\n * Defence in depth behind the allowlist: even if a URL slipped past it, git\n * itself refuses the two transports that run or read something local.\n */\nexport function protocolArgs(): string[] {\n const allowed = allowedProtocols();\n return [\n \"-c\",\n \"protocol.ext.allow=never\",\n \"-c\",\n `protocol.file.allow=${allowed.includes(\"file\") ? \"user\" : \"never\"}`,\n ];\n}\n","import { readFile, realpath, stat } from \"node:fs/promises\";\nimport { isAbsolute, relative, resolve, sep } from \"node:path\";\nimport { DEFAULT_IO_CONCURRENCY, mapLimit } from \"../concurrency.js\";\nimport {\n MAX_ANCHOR_FILE_BYTES,\n type AnchorFileReader,\n type AnchorRead,\n type KbAnchorDriftEntry,\n} from \"./model.js\";\n\n/**\n * An anchor's `file` must stay inside the repository root — a record points\n * at code, not at arbitrary files on the machine reading it. Bundles are\n * data, so a traversal or absolute path here is untrusted input, not a bug\n * in the caller. Returns the resolved path, or `null` when it escapes.\n *\n * Lexical only, and therefore not the whole containment check: see\n * `readAnchorFile`, which re-tests the real path after following symlinks.\n */\nexport function anchorFilePath(repoRoot: string, file: string): string | null {\n // Anchors are repo-relative, hand-written often enough that `./` shows up.\n const path = resolve(repoRoot, file.replace(/^\\.\\//, \"\"));\n const rel = relative(resolve(repoRoot), path);\n if (\n rel === \"\" ||\n rel === \"..\" ||\n rel.startsWith(`..${sep}`) ||\n isAbsolute(rel)\n ) {\n return null;\n }\n return path;\n}\n\nfunction contains(root: string, path: string): boolean {\n const rel = relative(root, path);\n return (\n rel !== \"\" &&\n rel !== \"..\" &&\n !rel.startsWith(`..${sep}`) &&\n !isAbsolute(rel)\n );\n}\n\nfunction errorCode(error: unknown): string | undefined {\n return typeof error === \"object\" && error !== null && \"code\" in error\n ? String((error as { code: unknown }).code)\n : undefined;\n}\n\n/** Resolves the repo root once, then reads anchor files against it. */\nexport function anchorFileReader(repoRoot: string): AnchorFileReader {\n let rootOnce: Promise<string> | undefined;\n const realRoot = (): Promise<string> => {\n rootOnce ??= realpath(resolve(repoRoot)).catch((error: unknown) => {\n // A rejected promise stays cached forever if left as-is — clear it so\n // the next read retries realpath instead of replaying one transient\n // failure for the rest of the run. This read still reports its own\n // file-missing/file-unreadable result via the catch below.\n rootOnce = undefined;\n throw error;\n });\n return rootOnce;\n };\n return (file) => readAnchorFileWithRoot(repoRoot, file, realRoot);\n}\n\n/** Convenience wrapper: resolves the repo root fresh on every call. */\nexport async function readAnchorFile(\n repoRoot: string,\n file: string,\n): Promise<AnchorRead> {\n return readAnchorFileWithRoot(repoRoot, file, () =>\n realpath(resolve(repoRoot)),\n );\n}\n\n/**\n * Containment is checked twice: lexically, then again against the realpath'd\n * path — a symlink inside the repo pointing out must not leak reads. Only\n * ENOENT/ENOTDIR is `file-missing`; other read errors are `file-unreadable`.\n */\nasync function readAnchorFileWithRoot(\n repoRoot: string,\n file: string,\n realRoot: () => Promise<string>,\n): Promise<AnchorRead> {\n const lexical = anchorFilePath(repoRoot, file);\n if (lexical === null) return { ok: false, reason: \"outside-repo\" };\n\n let root: string;\n let path: string;\n try {\n root = await realRoot();\n path = await realpath(lexical);\n } catch (error) {\n const code = errorCode(error);\n if (code === \"ENOENT\" || code === \"ENOTDIR\") {\n return { ok: false, reason: \"file-missing\" };\n }\n return { ok: false, reason: \"file-unreadable\" };\n }\n if (!contains(root, path)) return { ok: false, reason: \"outside-repo\" };\n\n try {\n const stats = await stat(path);\n if (!stats.isFile()) return { ok: false, reason: \"file-unreadable\" };\n // Anchors point at source. Reading a bundled artefact or a checked-in\n // binary into memory on a read path is a cost with no finding behind it.\n if (stats.size > MAX_ANCHOR_FILE_BYTES) {\n return { ok: false, reason: \"file-too-large\" };\n }\n return { ok: true, source: await readFile(path, \"utf8\") };\n } catch (error) {\n const code = errorCode(error);\n if (code === \"ENOENT\" || code === \"ENOTDIR\") {\n return { ok: false, reason: \"file-missing\" };\n }\n return { ok: false, reason: \"file-unreadable\" };\n }\n}\n\n/**\n * Every checked anchor failed to find its file at all.\n *\n * The signature of a repo root that was never given rather than of code that\n * moved: a bundle read from somewhere other than the tree it describes misses\n * every file, and reporting that as base-wide drift would train a reader to\n * ignore the warning. One file found anywhere makes the root plausible, and\n * the misses become real findings again.\n */\nexport function looksLikeWrongRepoRoot(\n drift: Map<string, KbAnchorDriftEntry[]>,\n): boolean {\n let checked = 0;\n for (const entries of drift.values()) {\n for (const entry of entries) {\n // An anchor read from another repository's remote says nothing about\n // this root. Counting it either way would be wrong: as a miss it would\n // make a correct root look wrong, and as a hit it would keep a\n // genuinely wrong root from being spotted.\n if (entry.repo !== undefined) continue;\n // An old-side anchor is read from git, not from this root's files, so it\n // can neither vouch for the root nor argue against it.\n if (entry.side === \"old\") continue;\n checked += 1;\n if (entry.state !== \"unresolved\" || entry.reason !== \"file-missing\") {\n return false;\n }\n }\n }\n return checked > 0;\n}\n\n/**\n * Reads each distinct file once with at most `concurrency` in flight.\n *\n * A reader that throws is one unreadable file, not a failed run.\n */\nexport async function readAnchorFiles(\n files: readonly string[],\n read: AnchorFileReader,\n concurrency: number = DEFAULT_IO_CONCURRENCY,\n): Promise<Map<string, AnchorRead>> {\n if (!Number.isInteger(concurrency) || concurrency < 1) {\n throw new RangeError(\n `readAnchorFiles: option \"concurrency\" must be a positive integer, got ${concurrency}`,\n );\n }\n const wanted = [...new Set(files)];\n const results = await mapLimit(wanted, concurrency, async (file) => {\n try {\n return await read(file);\n } catch {\n return { ok: false, reason: \"file-unreadable\" } as AnchorRead;\n }\n });\n return new Map(wanted.map((file, at) => [file, results[at] as AnchorRead]));\n}\n","import { createHash, randomBytes } from \"node:crypto\";\nimport { mkdir, readFile, rename, rm, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport type { Pinned } from \"./model.js\";\n\n/** Where downloaded grammars live. Overridable so a test never writes to `$HOME`. */\nexport function grammarsCacheRoot(override?: string): string {\n return (\n override ??\n process.env[\"STRAUSS_KB_GRAMMARS_DIR\"] ??\n join(homedir(), \".strauss\", \"grammars\")\n );\n}\n\n/**\n * Named by the hash the manifest pins, so a re-pin downloads beside the old\n * file instead of over it and a rollback finds its own still there. Both parts\n * of a pack share the layout: `<root>/<language>/<sha12>.wasm|.scm`.\n */\nexport function grammarCachePath(\n root: string,\n language: string,\n sha256: string,\n extension: \"wasm\" | \"scm\" = \"wasm\",\n): string {\n return join(root, language, `${sha256.slice(0, 12)}.${extension}`);\n}\n\nexport function sha256(bytes: Uint8Array): string {\n return createHash(\"sha256\").update(bytes).digest(\"hex\");\n}\n\nexport function matches(bytes: Uint8Array, entry: Pinned): boolean {\n if (entry.bytes !== undefined && bytes.byteLength !== entry.bytes)\n return false;\n return sha256(bytes) === entry.sha256;\n}\n\n/**\n * `true` when the cached file hashes as the manifest says. Checked on every\n * load, not only on download: `$HOME` is writable by anything the user runs\n * and a grammar is code the parser executes. A failing file is deleted.\n */\nexport async function verifyCached(\n path: string,\n entry: Pinned,\n): Promise<boolean> {\n let bytes: Uint8Array;\n try {\n bytes = await readFile(path);\n } catch {\n return false;\n }\n if (matches(bytes, entry)) return true;\n await rm(path, { force: true });\n return false;\n}\n\n/**\n * Write then `rename`, which is atomic within a filesystem: a second process\n * either sees the old file or the whole new one, never a half-written parser.\n */\nexport async function writeCached(\n path: string,\n bytes: Uint8Array,\n): Promise<void> {\n await mkdir(dirname(path), { recursive: true });\n const temporary = `${path}.${process.pid}.${randomBytes(4).toString(\"hex\")}.tmp`;\n try {\n await writeFile(temporary, bytes);\n await rename(temporary, path);\n } catch (error) {\n await rm(temporary, { force: true });\n throw error;\n }\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { grammarManifestSchema, type GrammarManifest } from \"./model.js\";\n\nlet cached: GrammarManifest | undefined;\n\n/**\n * The shipped `grammars/manifest.json`: the URL, hash and extensions of every\n * language pack. Read once per process.\n */\nexport function grammarManifest(): GrammarManifest {\n cached ??= grammarManifestSchema.parse(\n JSON.parse(readFileSync(grammarsDataPath(\"manifest.json\"), \"utf8\")),\n );\n return cached;\n}\n\n/**\n * Test seam: stands a lock of the test's own in for the shipped one, so a\n * suite can pin a part the shipped lock does not carry. `undefined` restores.\n */\nexport function setGrammarManifest(manifest?: GrammarManifest): void {\n cached = manifest;\n}\n\n/**\n * A path under the package's shipped `grammars/` directory.\n *\n * Source and bundle sit at different depths under the package root — `src/\n * grammars/` and `dist/` — so the directory is found by walking up rather than\n * by a fixed `..`.\n */\nexport function grammarsDataPath(...segments: string[]): string {\n let dir = dirname(fileURLToPath(import.meta.url));\n for (let up = 0; up < 5; up++) {\n const candidate = join(dir, \"grammars\");\n if (existsSync(join(candidate, \"manifest.json\")))\n return join(candidate, ...segments);\n dir = dirname(dir);\n }\n throw new Error(\"grammars/manifest.json is missing from the package\");\n}\n","import { z } from \"zod\";\n\nconst sha256 = z.string().regex(/^[0-9a-f]{64}$/);\n\n/**\n * The WASM half of a pack as the lock records it: the URL it was pinned from\n * and what it hashed to. `bytes` is checked before the hash so a truncated\n * response is rejected without hashing megabytes.\n */\nexport const grammarWasmSchema = z.object({\n url: z.string().min(1),\n sha256,\n bytes: z.number().int().positive(),\n});\n\n/**\n * One part of the tags query. A query is kilobytes, so the hash alone settles\n * it and the lock carries no byte count.\n */\nexport const grammarTagsSchema = z.object({ url: z.string().min(1), sha256 });\n\n/**\n * A language pack: a grammar and the definitions query that runs over it,\n * pinned together at one `package@version`. `tags` is empty where upstream\n * ships no query — that language parses but resolves nothing.\n */\nexport const grammarPackSchema = z.object({\n package: z.string().min(1),\n wasm: grammarWasmSchema,\n tags: z.array(grammarTagsSchema),\n license: z.string().min(1),\n extensions: z.array(z.string().min(1)),\n});\n\nexport const grammarManifestSchema = z.object({\n /** The runtime the packs were proved against. */\n webTreeSitter: z.string().min(1),\n linguist: z.object({ tag: z.string().min(1), commit: z.string().min(1) }),\n packs: z.record(z.string().min(1), grammarPackSchema),\n});\n\nexport type GrammarWasm = z.infer<typeof grammarWasmSchema>;\nexport type GrammarTags = z.infer<typeof grammarTagsSchema>;\n/** What a cached file is checked against: a hash, and a size where one is known. */\nexport type Pinned = { sha256: string; bytes?: number };\nexport type GrammarPack = z.infer<typeof grammarPackSchema>;\nexport type GrammarManifest = z.infer<typeof grammarManifestSchema>;\n\n/** A grammar and the query that runs over it, both verified, both on disk. */\nexport type Grammar = {\n /** Path to the cached WASM. */\n wasm: string;\n /** The pack's tags parts as one query, or `undefined` where it declares none. */\n query: string | undefined;\n};\n\n/** Where a grammar comes from and whether it may be fetched at all. */\nexport type GrammarOptions = {\n /** Cache root; defaults to `STRAUSS_KB_GRAMMARS_DIR` then `~/.strauss/grammars`. */\n cacheRoot?: string;\n /** Replaces the scheme and host of every manifest URL. For tests and mirrors. */\n baseUrl?: string;\n /** Cache only, never the network — what `--offline` passes down. */\n offline?: boolean;\n fetchTimeoutMs?: number;\n /** Where the download lines go. Defaults to stderr, never stdout. */\n log?: (line: string) => void;\n};\n","import { readFile } from \"node:fs/promises\";\nimport { downloadPart, grammarsBaseUrl, grammarUrl } from \"./fetch.js\";\nimport { grammarManifest } from \"./manifest.js\";\nimport type { Grammar, GrammarOptions, Pinned } from \"./model.js\";\nimport {\n grammarCachePath,\n grammarsCacheRoot,\n verifyCached,\n writeCached,\n} from \"./store.js\";\n\nexport { grammarsBaseUrl, grammarUrl } from \"./fetch.js\";\nexport {\n grammarManifest,\n grammarsDataPath,\n setGrammarManifest,\n} from \"./manifest.js\";\nexport {\n grammarManifestSchema,\n type Grammar,\n type GrammarManifest,\n type GrammarPack,\n type GrammarOptions,\n} from \"./model.js\";\nexport { grammarCachePath, grammarsCacheRoot } from \"./store.js\";\n\n/** One download per pack per process, however many callers ask at once. */\nconst inFlight = new Map<string, Promise<Grammar | null>>();\n\n/** Packs this process wanted and could not get, and why, for the hint. */\nconst missing = new Map<string, { subject: string; cause?: string }>();\n\n/** Languages whose pinned tags query would not compile, and why. */\nconst uncompilable = new Map<string, string>();\n\n/** Languages whose pinned grammar this runtime refused to load, and why. */\nconst rejected = new Map<string, string>();\n\n/** `STRAUSS_KB_GRAMMARS=off` keeps a run off the wire; the cache still counts. */\nexport function grammarsDownloadDisabled(): boolean {\n return process.env[\"STRAUSS_KB_GRAMMARS\"] === \"off\";\n}\n\n/**\n * Both halves of a verified pack (cached WASM path, tags query text), each\n * downloaded once. `null` on any refused, disabled or mismatched part is what\n * the resolver reports as `resolver-unavailable`; a miss is not remembered.\n */\nexport async function ensureGrammar(\n language: string,\n options: GrammarOptions = {},\n): Promise<Grammar | null> {\n const pack = grammarManifest().packs[language];\n if (!pack) return null;\n\n const root = grammarsCacheRoot(options.cacheRoot);\n const wasm = grammarCachePath(root, language, pack.wasm.sha256);\n // Keyed on the pack rather than the part, so a pack downloads once however\n // many parts it has.\n const key = `${wasm} ${grammarsBaseUrl(options.baseUrl) ?? \"\"}`;\n const existing = inFlight.get(key);\n if (existing) return existing;\n\n const pending = (async () => {\n const grammar = await ensurePart(\n wasm,\n `tree-sitter-${language}`,\n pack.wasm,\n options,\n );\n if (grammar !== true)\n return miss(language, `grammar tree-sitter-${language}`, grammar);\n\n const parts: string[] = [];\n const total = pack.tags.length;\n for (const [at, part] of pack.tags.entries()) {\n const name = `${language} tags${total > 1 ? ` part ${at + 1}/${total}` : \"\"}`;\n const path = grammarCachePath(root, language, part.sha256, \"scm\");\n const held = await ensurePart(path, name, part, options);\n if (held !== true) return miss(language, name, held);\n parts.push(`; ${part.url}\\n${lf(await readFile(path, \"utf8\"))}`);\n }\n\n missing.delete(language);\n return { wasm, query: total ? parts.join(\"\\n\") : undefined };\n })();\n inFlight.set(key, pending);\n const result = await pending;\n if (result === null) inFlight.delete(key);\n return result;\n}\n\n/** `true` once the part is cached and hashes as the lock says, else why not. */\nasync function ensurePart(\n path: string,\n name: string,\n entry: Pinned & { url: string },\n options: GrammarOptions,\n): Promise<true | { cause?: string }> {\n if (await verifyCached(path, entry)) return true;\n if (options.offline === true || grammarsDownloadDisabled()) return {};\n const download = await downloadPart(\n grammarUrl(entry.url, options.baseUrl),\n name,\n entry,\n options,\n );\n if (\"cause\" in download) return { cause: download.cause };\n await writeCached(path, download.bytes).catch(() => null);\n return true;\n}\n\n/** Records which part of the pack this run could not get, for the hint. */\nfunction miss(\n language: string,\n subject: string,\n failure: { cause?: string },\n): null {\n missing.set(language, { subject, ...failure });\n return null;\n}\n\n/** The pin concatenates parts LF-normalised; the runtime must compile the same. */\nfunction lf(body: string): string {\n return body.replace(/\\r\\n/g, \"\\n\");\n}\n\n/**\n * A tags query that will not compile against the grammar release it is pinned\n * to. The resolver reports the language unavailable; the repair is a re-pin.\n */\nexport function noteUncompilableQuery(language: string, cause: string): void {\n uncompilable.set(language, cause);\n}\n\n/**\n * A grammar the runtime will not load — a WASM built at an ABI outside the\n * range this `web-tree-sitter` accepts. The resolver reports the language\n * unavailable; the repair is a re-pin against the installed runtime.\n */\nexport function noteRejectedGrammar(language: string, cause: string): void {\n rejected.set(language, cause);\n}\n\n/**\n * One line per grammar this process could not use, for the doctor and\n * anchor-resolve reports. The only place a repair is spelled out.\n */\nexport function grammarHints(): string[] {\n const manifest = grammarManifest();\n const packs = manifest.packs;\n const lines = new Map<string, string>();\n for (const [language, { subject, cause }] of missing)\n lines.set(\n language,\n `${subject} not cached${cause ? ` (${cause})` : \"\"}; run online once, or set STRAUSS_KB_GRAMMARS_DIR`,\n );\n for (const [language, cause] of rejected)\n lines.set(\n language,\n `${packs[language]?.package ?? `tree-sitter-${language}`} rejected by web-tree-sitter ${manifest.webTreeSitter}${cause ? `: ${cause}` : \"\"}; re-pin with pnpm grammars pin ${language}`,\n );\n for (const [language, cause] of uncompilable)\n lines.set(\n language,\n `tags query for ${language} does not compile against ${packs[language]?.package ?? `tree-sitter-${language}`}: ${cause}; re-pin with pnpm grammars pin ${language}`,\n );\n return [...lines]\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([, line]) => line);\n}\n\n/** Test seam: forgets this process's downloads, misses and query failures. */\nexport function resetGrammarState(): void {\n inFlight.clear();\n missing.clear();\n uncompilable.clear();\n rejected.clear();\n}\n","import { fetchTimeoutMs } from \"../remote-repo/index.js\";\nimport type { GrammarOptions, Pinned } from \"./model.js\";\nimport { matches } from \"./store.js\";\n\n/** Attempts per grammar, and the pause after attempt `n`. */\nconst ATTEMPTS = 3;\nconst BACKOFF_MS = 250;\n\n/**\n * The manifest pins a fully resolved URL per pack. An override — a mirror, or\n * the suite's own server — replaces its scheme and host and nothing else, so\n * one setting redirects every pack whatever CDN it was pinned from.\n */\nexport function grammarUrl(url: string, override?: string): string {\n const base = grammarsBaseUrl(override);\n if (!base) return url;\n let root = base;\n while (root.endsWith(\"/\")) root = root.slice(0, -1);\n const pinned = new URL(url);\n return `${root}${pinned.pathname}${pinned.search}`;\n}\n\nexport function grammarsBaseUrl(override?: string): string | undefined {\n return override ?? process.env[\"STRAUSS_KB_GRAMMARS_URL\"];\n}\n\n/** Bytes, or why the last attempt failed — for the log line and the hint. */\nexport type Download = { bytes: Uint8Array } | { cause: string };\n\n/**\n * A pinned part's bytes, or a cause — never a throw. Grammar and tags query\n * take the same path: a hash mismatch is not retried (the CDN will serve the\n * same file again; the manifest is the safety), while timeouts, dropped\n * connections, 5xx and 429 get `ATTEMPTS` tries.\n */\nexport async function downloadPart(\n url: string,\n name: string,\n entry: Pinned,\n options: GrammarOptions = {},\n): Promise<Download> {\n const log =\n options.log ?? ((line: string) => void process.stderr.write(line));\n const weight =\n entry.bytes === undefined ? \"\" : ` (${size(entry.bytes)} from manifest)`;\n log(`strauss-kb: downloading ${name}${weight} from ${url}\\n`);\n\n let cause = \"\";\n for (let attempt = 1; attempt <= ATTEMPTS; attempt++) {\n const outcome = await attemptDownload(url, entry, options.fetchTimeoutMs);\n if (\"bytes\" in outcome) return outcome;\n cause = outcome.cause;\n log(\n `strauss-kb: ${name} attempt ${attempt}/${ATTEMPTS} failed: ${cause}\\n`,\n );\n if (!outcome.retry) break;\n if (attempt < ATTEMPTS) await pause(BACKOFF_MS * attempt);\n }\n log(`strauss-kb: ${name} not downloaded: ${cause}\\n`);\n return { cause };\n}\n\nasync function attemptDownload(\n url: string,\n entry: Pinned,\n timeoutMs: number | undefined,\n): Promise<{ bytes: Uint8Array } | { cause: string; retry: boolean }> {\n try {\n const response = await fetch(url, {\n signal: AbortSignal.timeout(fetchTimeoutMs(timeoutMs)),\n });\n if (!response.ok) {\n return {\n cause: `HTTP ${response.status}`,\n retry: response.status >= 500 || response.status === 429,\n };\n }\n const bytes = new Uint8Array(await response.arrayBuffer());\n if (!matches(bytes, entry))\n return { cause: \"sha256 mismatch\", retry: false };\n return { bytes };\n } catch (error) {\n const timedOut =\n error instanceof Error &&\n (error.name === \"TimeoutError\" || error.name === \"AbortError\");\n return { cause: timedOut ? \"timeout\" : \"network error\", retry: true };\n }\n}\n\n/** What the manifest says the file weighs, for the download line. */\nfunction size(bytes: number): string {\n return bytes >= 1024 * 1024\n ? `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n : `${Math.round(bytes / 1024)} KB`;\n}\n\nfunction pause(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import { extname } from \"node:path\";\nimport { grammarManifest, type GrammarManifest } from \"../grammars/index.js\";\n\n/**\n * Which grammar a file extension is parsed with, and whether a definitions\n * query runs over it. Both are generated — `pnpm grammars pin` — from GitHub\n * Linguist and from each pack's own tags query, so adding a language is a pin\n * run rather than a hand-written query.\n */\n\n/** Inverted once per lock — the lock a test stands in is a different object. */\nlet table:\n { of: GrammarManifest; extensions: Record<string, string> } | undefined;\n\nfunction extensionTable(): Record<string, string> {\n const manifest = grammarManifest();\n if (table?.of !== manifest)\n table = {\n of: manifest,\n extensions: Object.fromEntries(\n Object.entries(manifest.packs).flatMap(([language, pack]) =>\n pack.extensions.map((extension) => [extension, language]),\n ),\n ),\n };\n return table.extensions;\n}\n\n/** Does the lock pin a tags query for this language? The query itself downloads. */\nfunction hasQuery(language: string): boolean {\n return (grammarManifest().packs[language]?.tags.length ?? 0) > 0;\n}\n\n/**\n * Grammar for a path, or `undefined` when the extension has none — or when the\n * pinned grammar release ships no tags query for it, so the regex heuristic\n * keeps those files, as before the resolver existed.\n */\nexport function languageForFile(file: string): string | undefined {\n const language = extensionTable()[extname(file).toLowerCase()];\n return language && hasQuery(language) ? language : undefined;\n}\n\n/** Every language the resolver can resolve in: a grammar and a tags query. */\nexport function treeSitterLanguages(): string[] {\n return [...new Set(Object.values(extensionTable()))].filter(hasQuery).sort();\n}\n","import { createHash } from \"node:crypto\";\nimport { Language, Parser, Query, type Tree } from \"web-tree-sitter\";\nimport type {\n AnchorResolver,\n ResolvedSymbol,\n ResolverAttempt,\n} from \"../anchor-resolver/index.js\";\nimport { DEFAULT_IO_CONCURRENCY, mapLimit } from \"../concurrency.js\";\nimport {\n ensureGrammar,\n noteRejectedGrammar,\n noteUncompilableQuery,\n type Grammar,\n type GrammarOptions,\n} from \"../grammars/index.js\";\nimport {\n chainOf,\n index,\n select,\n spanOf,\n type Definition,\n type ParsedFile,\n} from \"./definitions.js\";\nimport { languageForFile } from \"./languages.js\";\nimport { tokens } from \"./tokens.js\";\n\n/**\n * AST-backed anchor resolution: a symbol resolves to the byte range of the\n * definition node that declares it, or to nothing.\n *\n * `resolve` stays synchronous because the read path resolves inside a loop;\n * grammar loading is the async part and happens once, in `prepare`.\n */\n\n/** How many parsed trees to keep. Trees are large; anchors cluster in few files. */\nconst TREE_CACHE_LIMIT = 32;\n\ntype Loaded = { language: Language; query: Query };\n\nexport type TreeSitterStats = { parses: number; cacheHits: number };\n\n/** Where both halves of a pack come from, and whether they may be fetched. */\nexport type TreeSitterOptions = GrammarOptions;\n\nexport class TreeSitterResolver implements AnchorResolver {\n readonly name = \"tree-sitter\";\n\n private readonly grammars: GrammarOptions;\n private readonly loaded = new Map<string, Loaded | null>();\n private readonly trees = new Map<string, ParsedFile>();\n private parser: Parser | undefined;\n private initialized = false;\n\n /** Cache effectiveness, for tests and for the latency numbers. */\n readonly stats: TreeSitterStats = { parses: 0, cacheHits: 0 };\n\n constructor(options: TreeSitterOptions = {}) {\n this.grammars = options;\n }\n\n /**\n * Loads the grammars these files need, once per language per process,\n * downloading each one on first use.\n *\n * A grammar that will not load is remembered as unavailable rather than\n * retried per anchor, and never throws: an unobtainable WASM is a finding.\n */\n async prepare(files: readonly string[]): Promise<void> {\n const wanted = new Set<string>();\n for (const file of files) {\n const language = languageForFile(file);\n if (language && !this.loaded.has(language)) wanted.add(language);\n }\n if (!wanted.size) return;\n\n if (!this.initialized) {\n try {\n await Parser.init();\n this.parser = new Parser();\n this.initialized = true;\n } catch {\n for (const language of wanted) this.loaded.set(language, null);\n return;\n }\n }\n\n // Downloads dominate a cold first run, so the languages a bundle needs\n // are fetched together rather than one after another.\n const languages = [...wanted];\n const loaded = await mapLimit(\n languages,\n Math.min(DEFAULT_IO_CONCURRENCY, languages.length),\n (language) => this.load(language),\n );\n languages.forEach((language, at) =>\n this.loaded.set(language, loaded[at] ?? null),\n );\n }\n\n /**\n * An unobtainable grammar, one this runtime refuses, and a query that will\n * not compile are three faults with three repairs; all are reported through\n * the grammars module so every hint has one home.\n */\n private async load(language: string): Promise<Loaded | null> {\n let pack: Grammar | null;\n try {\n pack = await ensureGrammar(language, this.grammars);\n } catch {\n return null;\n }\n if (!pack?.query) return null;\n\n let grammar: Language;\n try {\n grammar = await Language.load(pack.wasm);\n } catch (error) {\n noteRejectedGrammar(language, why(error));\n return null;\n }\n try {\n return { language: grammar, query: new Query(grammar, pack.query) };\n } catch (error) {\n noteUncompilableQuery(language, why(error));\n return null;\n }\n }\n\n /**\n * Abstains on an extension with no grammar so the regex resolver gets a\n * turn; reports `resolver-unavailable` when the grammar exists in principle\n * but could not be loaded, because falling back there would silently trade a\n * precise span for a guessed one.\n */\n attempt(source: string, symbol: string, file?: string): ResolverAttempt {\n const language = file ? languageForFile(file) : undefined;\n if (!language) return { kind: \"abstain\" };\n if (!this.loaded.has(language)) return { kind: \"abstain\" };\n const loaded = this.loaded.get(language);\n if (!loaded) return { kind: \"unresolved\", reason: \"resolver-unavailable\" };\n\n const parsed = this.parse(language, loaded, source);\n if (!parsed) return { kind: \"unresolved\", reason: \"resolver-unavailable\" };\n\n const wanted = symbol.split(\".\").filter(Boolean);\n if (!wanted.length)\n return { kind: \"unresolved\", reason: \"symbol-not-found\" };\n\n const matches = select(parsed, wanted);\n if (!matches.length)\n return { kind: \"unresolved\", reason: \"symbol-not-found\" };\n if (matches.length > 1)\n return { kind: \"unresolved\", reason: \"symbol-ambiguous\" };\n return { kind: \"resolved\", span: spanOf(matches[0] as Definition, source) };\n }\n\n resolve(\n source: string,\n symbol: string,\n file?: string,\n ): ResolvedSymbol | null {\n const attempt = this.attempt(source, symbol, file);\n return attempt.kind === \"resolved\" ? attempt.span : null;\n }\n\n /** Parsed trees are keyed by content hash, so an unchanged file parses once. */\n private parse(\n language: string,\n loaded: Loaded,\n source: string,\n ): ParsedFile | null {\n const key = `${language}:${createHash(\"sha256\").update(source).digest(\"hex\")}`;\n const cached = this.trees.get(key);\n if (cached) {\n this.stats.cacheHits += 1;\n return cached;\n }\n\n const parser = this.parser;\n if (!parser) return null;\n let parsed: ParsedFile;\n try {\n parser.setLanguage(loaded.language);\n const tree = parser.parse(source);\n if (!tree) return null;\n parsed = index(tree, loaded.query);\n } catch {\n return null;\n }\n this.stats.parses += 1;\n\n if (this.trees.size >= TREE_CACHE_LIMIT) {\n const oldest = this.trees.keys().next();\n if (!oldest.done) {\n this.trees.get(oldest.value)?.tree.delete();\n this.trees.delete(oldest.value);\n }\n }\n this.trees.set(key, parsed);\n return parsed;\n }\n\n /**\n * Every definition this file declares, as dotted symbol and span.\n *\n * The inverse of `attempt`: that asks \"where is this name\", this asks \"what\n * names are here\". `moved` needs the second — the stored hash has to be\n * looked for at every definition in the repository, and there is no name to\n * ask about, since the whole question is which name now carries that code.\n */\n spans(\n source: string,\n file: string,\n ): { symbol: string; span: ResolvedSymbol }[] {\n const language = languageForFile(file);\n if (!language) return [];\n const loaded = this.loaded.get(language);\n if (!loaded) return [];\n const parsed = this.parse(language, loaded, source);\n if (!parsed) return [];\n\n return parsed.definitions\n .filter((definition) => definition.target)\n .map((definition) => ({\n symbol: chainOf(definition, parsed.byNodeId).join(\".\"),\n span: spanOf(definition, source),\n }));\n }\n\n /**\n * The token stream of a span: every leaf the parser sees, comments dropped,\n * joined by single spaces.\n *\n * This is what makes a reformat not be drift. Hashing it rather than the raw\n * text means indentation, line breaks, trailing commas the formatter moved,\n * and every comment above or inside the definition are outside the hash —\n * and a renamed identifier or a changed literal is still inside it, because\n * those are leaves.\n *\n * `null` when the file has no grammar, the grammar would not load, or the\n * text will not parse: no normalisation is better than a guessed one.\n */\n normalize(text: string, file?: string): string | null {\n const language = file ? languageForFile(file) : undefined;\n if (!language) return null;\n const loaded = this.loaded.get(language);\n if (!loaded) return null;\n\n const parser = this.parser;\n if (!parser) return null;\n let tree: Tree | null;\n try {\n parser.setLanguage(loaded.language);\n tree = parser.parse(text);\n } catch {\n return null;\n }\n if (!tree) return null;\n try {\n return tokens(tree.rootNode).join(\" \");\n } finally {\n tree.delete();\n }\n }\n\n /** Drops cached trees. Grammars stay loaded — they are immutable. */\n reset(): void {\n for (const parsed of this.trees.values()) parsed.tree.delete();\n this.trees.clear();\n this.stats.parses = 0;\n this.stats.cacheHits = 0;\n }\n}\n\n/** web-tree-sitter throws bare Errors for a rejected module; say so. */\nfunction why(error: unknown): string {\n const text = error instanceof Error ? error.message : String(error);\n return text || \"no reason given\";\n}\n","import type { Node, Query, Tree } from \"web-tree-sitter\";\nimport type { ResolvedSymbol } from \"../anchor-resolver/index.js\";\n\n/**\n * Upstream `tags.scm` vocabulary: `@name` is the symbol, `@definition.*` the\n * node a reader points at, `@reference.*` a use. `@reference.implementation`\n * (a Rust `impl Foo`) scopes the chain without being a target.\n */\n\nconst SCOPE_ONLY = \"reference.implementation\";\n\n/** A definition site, with the node whose range becomes the anchor span. */\nexport type Definition = {\n node: Node;\n name: string;\n /** `false` for chain-only scopes such as a Rust `impl` block. */\n target: boolean;\n};\n\nexport type ParsedFile = {\n tree: Tree;\n /** Definitions by node id, for walking a node's enclosing chain. */\n byNodeId: Map<number, Definition>;\n definitions: Definition[];\n};\n\n/**\n * One definition per name site, innermost node wins — a query that captures\n * the same name twice (upstream Rust makes every `fn` both a function and,\n * inside its `impl` block's `declaration_list`, a method) means the tightest\n * node around the name, never the block that holds its siblings too.\n */\nexport function index(tree: Tree, query: Query): ParsedFile {\n const byName = new Map<number, Definition>();\n\n for (const match of query.matches(tree.rootNode)) {\n const nameNode = match.captures.find((capture) => capture.name === \"name\");\n const defNode = match.captures.find(\n (capture) =>\n capture.name.startsWith(\"definition.\") || capture.name === SCOPE_ONLY,\n );\n if (!nameNode || !defNode) continue;\n\n const candidate: Definition = {\n node: defNode.node,\n name: nameNode.node.text,\n target: defNode.name !== SCOPE_ONLY,\n };\n const existing = byName.get(nameNode.node.id);\n if (existing && width(existing.node) <= width(candidate.node)) continue;\n byName.set(nameNode.node.id, candidate);\n }\n\n const definitions = [...byName.values()];\n return {\n tree,\n byNodeId: new Map(\n definitions.map((definition) => [definition.node.id, definition]),\n ),\n definitions,\n };\n}\n\n/**\n * Definitions whose chain ends with `wanted`. When several match, the ones\n * with a body win: an overload signature declares the same chain as the\n * implementation, and the implementation is what a reader means.\n */\nexport function select(\n parsed: ParsedFile,\n wanted: readonly string[],\n): Definition[] {\n const matches = parsed.definitions.filter(\n (definition) =>\n definition.target &&\n endsWith(chainOf(definition, parsed.byNodeId), wanted),\n );\n if (matches.length < 2) return matches;\n const bodied = matches.filter(\n (definition) => definition.node.childForFieldName(\"body\") !== null,\n );\n return bodied.length === 1 ? bodied : matches;\n}\n\n/**\n * The definition's enclosing chain, outermost first: `[\"OrderService\",\n * \"cancel\"]` for a method of that class.\n *\n * A receiver stands in for an ancestor where a grammar has one — Go's\n * `func (s *Server) Cancel` chains as `Server.Cancel`.\n */\nexport function chainOf(\n definition: Definition,\n byNodeId: Map<number, Definition>,\n): string[] {\n const chain = [definition.name];\n\n const receiver = definition.node.childForFieldName(\"receiver\");\n const type = receiver && typeNameIn(receiver);\n if (type) chain.unshift(type);\n\n for (let node = definition.node.parent; node; node = node.parent) {\n const enclosing = byNodeId.get(node.id);\n if (enclosing && enclosing.node !== definition.node)\n chain.unshift(enclosing.name);\n }\n return chain;\n}\n\n/** `(s *Server)` and `(s Server)` both name `Server`. */\nfunction typeNameIn(receiver: Node): string | undefined {\n const stack: Node[] = [receiver];\n while (stack.length) {\n const node = stack.pop() as Node;\n if (node.type === \"type_identifier\") return node.text;\n for (let at = 0; at < node.childCount; at++) {\n const child = node.child(at);\n if (child) stack.push(child);\n }\n }\n return undefined;\n}\n\n/** Does `chain` end with every segment of `wanted`, in order? */\nfunction endsWith(chain: string[], wanted: readonly string[]): boolean {\n if (wanted.length > chain.length) return false;\n const offset = chain.length - wanted.length;\n return wanted.every((segment, at) => chain[offset + at] === segment);\n}\n\nfunction width(node: Node): number {\n return node.endIndex - node.startIndex;\n}\n\n/**\n * The definition node's lines, widened to what a reader would call the\n * declaration: preceding decorators, and the `export` that fronts it.\n */\nexport function spanOf(definition: Definition, source: string): ResolvedSymbol {\n let start = definition.node;\n let end = definition.node;\n\n for (\n let sibling = start.previousSibling;\n sibling?.type === \"decorator\";\n sibling = sibling.previousSibling\n ) {\n start = sibling;\n }\n\n const parent = end.parent;\n if (\n parent?.type === \"export_statement\" &&\n parent.childForFieldName(\"declaration\")?.id === end.id\n ) {\n start = parent;\n end = parent;\n }\n\n const lines = source.split(\"\\n\");\n const startLine = start.startPosition.row;\n // A node ending at column 0 ends on the previous line's newline.\n const endLine =\n end.endPosition.column === 0 && end.endPosition.row > startLine\n ? end.endPosition.row - 1\n : end.endPosition.row;\n\n return {\n text: lines.slice(startLine, endLine + 1).join(\"\\n\"),\n startLine: startLine + 1,\n endLine: endLine + 1,\n };\n}\n","import type { Node } from \"web-tree-sitter\";\n\n/**\n * Leaf text in source order, comments skipped whole.\n *\n * Iterative rather than recursive: a span is bounded by `MAX_ANCHOR_FILE_BYTES`\n * but its nesting depth is not, and a deeply nested literal must not be able to\n * overflow the stack on a read path.\n */\nexport function tokens(root: Node): string[] {\n const out: string[] = [];\n const stack: Node[] = [root];\n while (stack.length) {\n const node = stack.pop() as Node;\n if (node.type.includes(\"comment\")) continue;\n if (node.childCount === 0) {\n const text = node.text.trim();\n if (text) out.push(text);\n continue;\n }\n for (let at = node.childCount - 1; at >= 0; at--) {\n const child = node.child(at);\n if (child) stack.push(child);\n }\n }\n return out;\n}\n","import { createHash } from \"node:crypto\";\nimport type { KbAnchor, KbAnchorSpan } from \"../kb-record.schema.js\";\nimport type { GrammarOptions } from \"../grammars/index.js\";\nimport { TreeSitterResolver } from \"../tree-sitter-resolver/index.js\";\nimport type {\n AnchorHashKind,\n AnchorResolution,\n AnchorResolverName,\n AnchorResolver,\n ResolvedSymbol,\n ResolverAttempt,\n} from \"./model.js\";\n\n/**\n * Symbol → text, and text → hash.\n *\n * Resolvers are pure: source string in, range out. Any shape the lexer cannot\n * handle confidently returns `null` and is reported `unresolved`, never guessed.\n */\n\n/**\n * How far above a candidate the parent of a dotted symbol may sit and still\n * be taken as scoping it. Crude on purpose: a real parser owns this question,\n * and until one takes the seat a fixed window is at least predictable.\n */\nconst PARENT_SCOPE_LINES = 50;\n\n/* -------------------------------------------------------------------------\n * A crude lexer, sufficient for counting braces\n * ---------------------------------------------------------------------- */\n\ntype ScanState = { blockComment: boolean; template: boolean };\n\nconst CLEAN_STATE: ScanState = { blockComment: false, template: false };\n\n/**\n * Strips comments and string literals from one line, carrying block-comment\n * and template-literal state across lines.\n *\n * Brace counting over raw text is wrong in both directions: a `}` inside a\n * string or a comment ends a block early — the truncation that hashes as\n * stable — and a `{` inside one opens a block that never closes. This is not\n * a tokenizer: a regex literal containing a brace (`/}/`) still fools it, and\n * `#` is left alone because TypeScript spells private fields with it. Both\n * limits are documented in the README.\n */\nfunction stripLine(\n line: string,\n state: ScanState,\n): { code: string; state: ScanState } {\n let out = \"\";\n let index = 0;\n let { blockComment, template } = state;\n\n while (index < line.length) {\n const char = line[index];\n const next = line[index + 1];\n\n if (blockComment) {\n if (char === \"*\" && next === \"/\") {\n blockComment = false;\n index += 2;\n continue;\n }\n index += 1;\n continue;\n }\n\n // Braces inside `${...}` are balanced by construction, so ignoring the\n // whole template rather than re-entering code inside it is safe here.\n if (template) {\n if (char === \"\\\\\") {\n index += 2;\n continue;\n }\n if (char === \"`\") template = false;\n index += 1;\n continue;\n }\n\n if (char === \"/\" && next === \"*\") {\n blockComment = true;\n index += 2;\n continue;\n }\n if (char === \"/\" && next === \"/\") break;\n if (char === \"`\") {\n template = true;\n index += 1;\n continue;\n }\n if (char === \"'\" || char === '\"') {\n const quote = char;\n index += 1;\n while (index < line.length) {\n if (line[index] === \"\\\\\") {\n index += 2;\n continue;\n }\n if (line[index] === quote) {\n index += 1;\n break;\n }\n index += 1;\n }\n continue;\n }\n\n out += char;\n index += 1;\n }\n\n return { code: out, state: { blockComment, template } };\n}\n\n/* -------------------------------------------------------------------------\n * Span capture\n * ---------------------------------------------------------------------- */\n\nfunction span(lines: string[], from: number, to: number): ResolvedSymbol {\n return {\n text: lines.slice(from, to + 1).join(\"\\n\"),\n startLine: from + 1,\n endLine: to + 1,\n };\n}\n\n/**\n * From the matched line to the line where brace depth returns to zero.\n *\n * Depth is tested at end of line, never mid-line, so a destructured signature\n * (`function f({ a, b }) {`) does not end the span. A top-level `;` before any\n * brace opens is a braceless declaration and the matched line alone is the\n * span. Everything else is `null`.\n */\nfunction captureBraceBlock(\n lines: string[],\n matchLine: number,\n): ResolvedSymbol | null {\n let depth = 0;\n let opened = false;\n let state = CLEAN_STATE;\n\n for (let index = matchLine; index < lines.length; index++) {\n const stripped = stripLine(lines[index] ?? \"\", state);\n state = stripped.state;\n\n for (const char of stripped.code) {\n if (char === \"{\") {\n depth += 1;\n opened = true;\n } else if (char === \"}\") {\n depth = Math.max(0, depth - 1);\n } else if (char === \";\" && !opened) {\n return span(lines, matchLine, index);\n }\n }\n\n if (opened && depth === 0) return span(lines, matchLine, index);\n }\n\n return null;\n}\n\n/** `def f(...)` / `class C:` — a header ending in a colon, body by indent. */\nconst PYTHON_HEADER = /^\\s*(?:async\\s+)?(?:def|class)\\s+[A-Za-z_]\\w*\\s*[(:]/;\n\n/**\n * A Python block: the header, however many lines its signature runs to, plus\n * every following line that is blank or indented past the header.\n *\n * Brace counting would capture a `def` line and nothing else — a signature\n * hash that never sees a body change, which is worse than no anchor at all.\n * A header whose body never arrives is `null` for the same reason.\n */\nfunction captureIndentedBlock(\n lines: string[],\n matchLine: number,\n): ResolvedSymbol | null {\n const header = lines[matchLine] ?? \"\";\n const indent = header.length - header.trimStart().length;\n\n let headerEnd = -1;\n for (\n let index = matchLine;\n index < lines.length && index <= matchLine + 20;\n index++\n ) {\n const code = stripLine(lines[index] ?? \"\", CLEAN_STATE).code.trimEnd();\n if (code.endsWith(\":\")) {\n headerEnd = index;\n break;\n }\n // `def f(): pass` — the body is on the header line, so the line is the span.\n if (code.includes(\":\")) return span(lines, matchLine, index);\n }\n if (headerEnd === -1) return null;\n\n let end = headerEnd;\n for (let index = headerEnd + 1; index < lines.length; index++) {\n const line = lines[index] ?? \"\";\n if (line.trim() === \"\") continue;\n const lineIndent = line.length - line.trimStart().length;\n if (lineIndent <= indent) break;\n end = index;\n }\n\n // A signature with no body under it is the false-stability case again.\n return end === headerEnd ? null : span(lines, matchLine, end);\n}\n\n/* -------------------------------------------------------------------------\n * The v1 resolver\n * ---------------------------------------------------------------------- */\n\ntype Tier = (name: string) => RegExp;\n\nconst declarationTier: Tier = (name) =>\n new RegExp(\n `(?:function|class|interface|type|enum|const|let|var|def)\\\\s+${name}\\\\b`,\n );\n\n/** `name:` or `name =` anywhere on the line. */\nconst assignmentTier: Tier = (name) => new RegExp(`\\\\b${name}\\\\s*[:=]`);\n\n// Anchored to line start, past any modifiers: mid-line, `name:` is as likely\n// a parameter annotation or a destructuring rename as a definition.\nconst anchoredAssignmentTier: Tier = (name) =>\n new RegExp(\n `^\\\\s*(?:export\\\\s+|readonly\\\\s+|pub\\\\s+|static\\\\s+|private\\\\s+|public\\\\s+|protected\\\\s+)*${name}\\\\s*[:=]`,\n );\n\n/** A line that declares or assigns the name. */\nconst DEFINITION_TIERS: Tier[] = [declarationTier, anchoredAssignmentTier];\n\n/** Never an answer after a parsed miss. */\nconst MENTION_TIERS: Tier[] = [\n (name) => new RegExp(`\\\\b${name}\\\\s*\\\\(`),\n (name) => new RegExp(`\\\\b${name}\\\\b`),\n];\n\n/**\n * Candidate lines, best shape first. A declaration outranks an assignment,\n * which outranks a call-shaped line, which outranks a bare mention — so an\n * anchor lands on where a symbol is defined rather than the first place it is\n * used, which `findIndex` over one loose pattern used to do.\n */\nconst TIERS: Tier[] = [declarationTier, assignmentTier, ...MENTION_TIERS];\n\nfunction resolveWith(\n tiers: readonly Tier[],\n source: string,\n symbol: string,\n): ResolvedSymbol | null {\n const segments = symbol.split(\".\");\n const name = segments[segments.length - 1];\n if (!name) return null;\n const parent =\n segments.length > 1 ? segments[segments.length - 2] : undefined;\n\n const escaped = escapeRegExp(name);\n const parentPattern = parent\n ? new RegExp(`\\\\b${escapeRegExp(parent)}\\\\b`)\n : null;\n const lines = source.split(\"\\n\");\n\n for (const tier of tiers) {\n const pattern = tier(escaped);\n let candidates = lines\n .map((line, index) => ({ line, index }))\n .filter((entry) => pattern.test(entry.line))\n .map((entry) => entry.index);\n if (!candidates.length) continue;\n\n // Nearest enclosing parent wins, not merely a parent somewhere above:\n // two classes in one file each declaring `cancel` both see the first\n // class's name in the window, and only distance tells them apart.\n if (parentPattern && candidates.length > 1) {\n const distances = candidates.map((index) =>\n distanceToParent(lines, index, parentPattern),\n );\n const nearest = Math.min(...distances);\n if (Number.isFinite(nearest)) {\n candidates = candidates.filter((_, at) => distances[at] === nearest);\n }\n }\n\n // Two lines of the same shape: which one the record meant is a guess,\n // and a guessed anchor hashes as evidence.\n if (candidates.length !== 1) return null;\n\n const matchLine = candidates[0] as number;\n return PYTHON_HEADER.test(lines[matchLine] ?? \"\")\n ? captureIndentedBlock(lines, matchLine)\n : captureBraceBlock(lines, matchLine);\n }\n\n return null;\n}\n\n/**\n * v1 heuristic resolver. A dotted symbol like `OrderService.cancel` matches on\n * its last segment, with the parent used to scope the search: a candidate\n * counts only if the parent name appears in the fifty lines above it, when any\n * candidate satisfies that at all.\n *\n * Deterministic, and ambiguity is not resolved by guessing — two lines of\n * equally good shape mean the resolver cannot tell which one the record meant,\n * and it says so by returning `null`.\n */\nexport const regexResolver: AnchorResolver = {\n name: \"regex\",\n resolve(source, symbol) {\n return resolveWith(TIERS, source, symbol);\n },\n attempt(source, symbol, _file, options) {\n const tiers = options?.afterParsedMiss ? DEFINITION_TIERS : TIERS;\n const span = resolveWith(tiers, source, symbol);\n return span\n ? { kind: \"resolved\", span }\n : { kind: \"unresolved\", reason: \"symbol-not-found\" };\n },\n};\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n/** Lines from the nearest parent mention at or above `index`, or Infinity. */\nfunction distanceToParent(\n lines: string[],\n index: number,\n parent: RegExp,\n): number {\n const floor = Math.max(0, index - PARENT_SCOPE_LINES);\n for (let at = index; at >= floor; at--) {\n if (parent.test(lines[at] ?? \"\")) return index - at;\n }\n return Number.POSITIVE_INFINITY;\n}\n\n/** CRLF normalized to LF before hashing, so checkout style cannot read as drift. */\nexport function hashAnchorText(text: string): string {\n return `sha256:${createHash(\"sha256\")\n .update(text.replace(/\\r\\n/g, \"\\n\"))\n .digest(\"hex\")}`;\n}\n\n/**\n * An anchor without a symbol is about the whole file; with one, the resolver\n * decides. Source newlines are normalized first so line counts and hashes\n * agree with `hashAnchorText`.\n *\n * A file's last line is the last line with content: a trailing newline is a\n * terminator, not an empty line, and counting it would have made every\n * whole-file anchor's `lines` one larger than the file.\n */\nexport function resolveAnchor(\n source: string,\n anchor: KbAnchor,\n resolver: AnchorResolver = regexResolver,\n): ResolvedSymbol | null {\n const outcome = resolveAnchorSpan(source, anchor, [resolver]);\n return outcome.ok ? outcome.span : null;\n}\n\n/**\n * Walks the resolver chain: tree-sitter, then regex, then a whole-file span\n * when the anchor names no symbol.\n *\n * `symbol-not-found` falls through (a tags query defines functions and types,\n * not constants or fields), but a resolver that parsed the file and missed\n * narrows what follows to definition-shaped candidates: never a call site or a\n * bare mention. `symbol-ambiguous` and `resolver-unavailable` end the chain.\n */\nexport function resolveAnchorSpan(\n source: string,\n anchor: KbAnchor,\n resolvers: readonly AnchorResolver[] = [regexResolver],\n): AnchorResolution {\n const normalized = source.replace(/\\r\\n/g, \"\\n\");\n // An explicit range outranks a symbol: the two are alternatives, and only a\n // hand-edit puts both on one anchor. `kb_validate` faults that; here the\n // author's literal line numbers win over a search.\n if (anchor.span) return sliceSpan(normalized, anchor.span);\n if (!anchor.symbol) {\n const lines = normalized.split(\"\\n\");\n if (lines.length > 1 && lines[lines.length - 1] === \"\") lines.pop();\n return {\n ok: true,\n span: {\n text: normalized,\n startLine: 1,\n endLine: Math.max(1, lines.length),\n },\n };\n }\n\n let afterParsedMiss = false;\n for (const resolver of resolvers) {\n const attempt = resolver.attempt\n ? resolver.attempt(normalized, anchor.symbol, anchor.file, {\n afterParsedMiss,\n })\n : fromResolve(resolver, normalized, anchor.symbol, anchor.file);\n if (attempt.kind === \"abstain\") continue;\n if (attempt.kind === \"unresolved\") {\n if (attempt.reason === \"symbol-not-found\") {\n // Only a resolver that parsed the file narrows the ones below it; the\n // same reason manufactured for a `resolve`-only resolver proves nothing.\n if (resolver.attempt) afterParsedMiss = true;\n continue;\n }\n return { ok: false, reason: attempt.reason };\n }\n const tokens = resolver.normalize?.(attempt.span.text, anchor.file);\n return {\n ok: true,\n span: attempt.span,\n ...(isResolverName(resolver.name) ? { resolver: resolver.name } : {}),\n ...(tokens ? { normalized: tokens } : {}),\n };\n }\n return { ok: false, reason: \"symbol-not-found\" };\n}\n\n/**\n * An author-given line range, taken exactly as written and hashed raw.\n *\n * No token stream is offered: a span is a slice, not a syntactic unit, so a\n * parser handed half a statement would normalise an error tree. Lines past the\n * end of the file are `span-out-of-range` — the described code is not there.\n */\nfunction sliceSpan(source: string, range: KbAnchorSpan): AnchorResolution {\n const lines = source.split(\"\\n\");\n if (lines.length > 1 && lines[lines.length - 1] === \"\") lines.pop();\n if (range.end > lines.length) {\n return { ok: false, reason: \"span-out-of-range\" };\n }\n return {\n ok: true,\n span: {\n text: lines.slice(range.start - 1, range.end).join(\"\\n\"),\n startLine: range.start,\n endLine: range.end,\n },\n resolver: \"span\",\n };\n}\n\n/** A resolver with no `attempt`: a span or a plain miss, never an abstain. */\nfunction fromResolve(\n resolver: AnchorResolver,\n source: string,\n symbol: string,\n file: string,\n): ResolverAttempt {\n const span = resolver.resolve(source, symbol, file);\n return span\n ? { kind: \"resolved\", span }\n : { kind: \"unresolved\", reason: \"symbol-not-found\" };\n}\n\nfunction isResolverName(name: string): name is AnchorResolverName {\n return name === \"tree-sitter\" || name === \"regex\" || name === \"span\";\n}\n\n/** Loads every chained resolver's per-language assets, once. */\nexport async function prepareResolvers(\n resolvers: readonly AnchorResolver[],\n files: readonly string[],\n): Promise<void> {\n for (const resolver of resolvers) await resolver.prepare?.(files);\n}\n\n/**\n * The read-path chain. A fresh tree-sitter resolver per call, so its parse\n * cache lives exactly as long as the run that owns it. `offline` rides down to\n * grammar loading: a run that may not reach the network uses the cache or\n * reports `resolver-unavailable`.\n */\nexport function defaultAnchorResolvers(\n grammars: GrammarOptions = {},\n): AnchorResolver[] {\n return [new TreeSitterResolver(grammars), regexResolver];\n}\n\n/**\n * Was the swap the whole story?\n *\n * Only when the resolver that stamped the anchor still reproduces the stored\n * hash against this very source. Otherwise the code moved too, and calling it\n * a resolver change would hide the edit behind a bookkeeping note.\n */\nexport function resolverChanged(\n source: string,\n anchor: KbAnchor,\n produced: AnchorResolverName | undefined,\n): boolean {\n const previous = anchor.resolver ?? \"regex\";\n if (!produced || !anchor.symbol || previous === produced) return false;\n if (previous !== \"regex\") return false;\n const before = regexResolver.resolve(\n source.replace(/\\r\\n/g, \"\\n\"),\n anchor.symbol,\n );\n return before !== null && hashAnchorText(before.text) === anchor.hash;\n}\n\n/**\n * Which hash to compare, and over what.\n *\n * A stored hash is only ever compared against a hash of the same kind — an\n * `ast` hash and a `raw` hash of the same code differ by construction, and\n * treating that as drift would report every anchor once. An anchor with no\n * hash yet takes the strongest kind the resolver can offer, so newly stamped\n * anchors stop drifting on reformatting.\n */\nexport function anchorHashOf(\n anchor: KbAnchor,\n outcome: {\n span: ResolvedSymbol;\n normalized?: string;\n resolver?: AnchorResolverName;\n },\n): { hash: string; kind: AnchorHashKind } {\n // A span is raw whatever the anchor stored: honouring a hand-written\n // `hash_kind: \"ast\"` would compare a raw hash against a token stream for\n // ever. `kb_validate` reports the anchor; this keeps it comparable.\n if (outcome.resolver === \"span\") {\n return { hash: hashAnchorText(outcome.span.text), kind: \"raw\" };\n }\n const stored = anchor.hash ? (anchor.hash_kind ?? \"raw\") : undefined;\n const wanted = stored ?? (outcome.normalized ? \"ast\" : \"raw\");\n return wanted === \"ast\" && outcome.normalized\n ? { hash: hashAnchorText(outcome.normalized), kind: \"ast\" }\n : { hash: hashAnchorText(outcome.span.text), kind: \"raw\" };\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport type { AnchorRead } from \"../anchor-resolver/model.js\";\nimport {\n filePathIsSafe,\n localRevShapeIsSafe,\n refShapeIsSafe,\n} from \"../remote-repo/validate.js\";\n\nconst execFileAsync = promisify(execFile);\n\n/**\n * Reading a committed file, for the one thing a working tree cannot answer:\n * what the anchored code looked like when the record was written.\n *\n * `ref` and `file` come off an anchor, which is a `.md` file the reader did not\n * write. An argv array stops a shell; it does not stop git's own option\n * parsing, so every positional that derives from bundle data goes after\n * `--end-of-options` and is shape-checked before a subprocess exists. Nothing\n * here fetches — a rev this checkout does not have is a finding, never a\n * network call.\n *\n * The shape checks themselves are `remote-repo/validate.ts`'s: one definition\n * of what a `ref` and a `file` may be, whichever read path asks.\n */\n\n/** Output cap. A recovered file is source, and source this large is not. */\nexport const MAX_GIT_OUTPUT_BYTES = 1_048_576;\n\n/** A range diff is a whole change rather than one file, so it gets its own. */\nexport const MAX_RANGE_DIFF_BYTES = 8 * 1_048_576;\n\nconst GIT_TIMEOUT_MS = 5_000;\nconst RANGE_DIFF_TIMEOUT_MS = 20_000;\n\n/** `failed` is git's own non-zero exit; the other three are the run itself. */\ntype GitFailure = \"failed\" | \"too-large\" | \"timeout\" | \"git-missing\";\n\ntype GitResult =\n { ok: true; stdout: string } | { ok: false; reason: GitFailure };\n\ntype GitLimits = { maxBytes?: number; timeoutMs?: number };\n\n/**\n * `GIT_DIR`, `GIT_WORK_TREE` and `GIT_INDEX_FILE` are stripped from the child:\n * a caller's environment must not be able to redirect a read that `-C` already\n * addressed.\n */\nasync function git(\n cwd: string,\n args: string[],\n limits: GitLimits = {},\n): Promise<GitResult> {\n const env = { ...process.env };\n delete env[\"GIT_DIR\"];\n delete env[\"GIT_WORK_TREE\"];\n delete env[\"GIT_INDEX_FILE\"];\n try {\n const { stdout } = await execFileAsync(\"git\", [\"-C\", cwd, ...args], {\n timeout: limits.timeoutMs ?? GIT_TIMEOUT_MS,\n maxBuffer: limits.maxBytes ?? MAX_GIT_OUTPUT_BYTES,\n env,\n });\n return { ok: true, stdout };\n } catch (error) {\n return { ok: false, reason: failureOf(error) };\n }\n}\n\n/** A killed child is over the cap before it is over time: the cap kills too. */\nfunction failureOf(error: unknown): GitFailure {\n const { code, killed } = error as { code?: unknown; killed?: boolean };\n if (code === \"ENOENT\") return \"git-missing\";\n if (code === \"ERR_CHILD_PROCESS_STDIO_MAXBUFFER\") return \"too-large\";\n if (killed === true) return \"timeout\";\n return \"failed\";\n}\n\n/**\n * The committed file an old-side anchor names, at its own `ref` and nowhere\n * else. No history fallback: `side: \"old\"` asserts one exact tree, so guessing\n * a nearby commit would answer a question the anchor did not ask.\n *\n * A rev this clone does not carry is `ref-unavailable` — unchecked, not\n * `gone`: a shallow checkout is no evidence the code went away.\n */\nexport async function readFileAtRef(\n repoRoot: string,\n anchor: { file: string; ref?: string },\n): Promise<AnchorRead> {\n if (!filePathIsSafe(anchor.file))\n return { ok: false, reason: \"outside-repo\" };\n if (!anchor.ref || !refShapeIsSafe(anchor.ref)) {\n return { ok: false, reason: \"ref-unreadable\" };\n }\n const blob = await catBlob(repoRoot, anchor.ref, anchor.file);\n if (blob !== null) return { ok: true, source: blob };\n return {\n ok: false,\n reason: (await hasCommit(repoRoot, anchor.ref))\n ? \"ref-unreadable\"\n : \"ref-unavailable\",\n };\n}\n\n/** Whether the rev resolves to a commit here. `^{commit}` is ours, not bundle data. */\nasync function hasCommit(repoRoot: string, ref: string): Promise<boolean> {\n const found = await git(repoRoot, [\n \"cat-file\",\n \"-e\",\n \"--end-of-options\",\n `${ref}^{commit}`,\n ]);\n return found.ok;\n}\n\n/** Repository-relative paths, for the `moved` search. Empty when git fails. */\nexport async function listRepoFiles(repoRoot: string): Promise<string[]> {\n const result = await git(repoRoot, [\"ls-files\", \"-z\", \"--cached\"]);\n if (!result.ok) return [];\n return result.stdout.split(\"\\0\").filter(Boolean);\n}\n\n/**\n * `<base>..<head>` or `<base>...<head>`, both halves spelled out. git reads\n * `..head` and `base..` as ranges against `HEAD`; a shape-checked half is the\n * only kind that reaches argv, so the omitted one is refused instead.\n */\nconst DIFF_RANGE = /^(.+?)(\\.{2,3})(.+)$/;\n\n/**\n * A commit range as a zero-context patch, for a caller turning a change into\n * hunks.\n *\n * The reason travels with the refusal: a range git would not take, a patch past\n * the cap, a run that timed out, and no git at all are four different things to\n * tell a caller. External diff drivers and textconv filters are off — both run\n * a command the repository configured — and the prefixes and `core.quotePath`\n * are pinned so the parser reads one spelling rather than the repo's.\n */\nexport type RangeDiff =\n | { ok: true; text: string }\n | {\n ok: false;\n reason: \"bad-range\" | \"too-large\" | \"timeout\" | \"git-missing\";\n };\n\nexport async function readRangeDiff(\n repoRoot: string,\n range: string,\n maxBytes: number = MAX_RANGE_DIFF_BYTES,\n): Promise<RangeDiff> {\n const parts = DIFF_RANGE.exec(range);\n if (!parts) return { ok: false, reason: \"bad-range\" };\n const [, base = \"\", dots = \"\", head = \"\"] = parts;\n if (!localRevShapeIsSafe(base) || !localRevShapeIsSafe(head)) {\n return { ok: false, reason: \"bad-range\" };\n }\n\n const result = await git(\n repoRoot,\n [\n \"-c\",\n \"core.quotePath=false\",\n \"diff\",\n \"--unified=0\",\n \"--no-color\",\n \"--no-ext-diff\",\n \"--no-textconv\",\n \"--find-renames\",\n \"--src-prefix=a/\",\n \"--dst-prefix=b/\",\n \"--end-of-options\",\n `${base}${dots}${head}`,\n \"--\",\n ],\n { maxBytes, timeoutMs: RANGE_DIFF_TIMEOUT_MS },\n );\n if (result.ok) return { ok: true, text: result.stdout };\n return {\n ok: false,\n reason: result.reason === \"failed\" ? \"bad-range\" : result.reason,\n };\n}\n\n/** Where a recovered file came from, so a packet can say how far back it looked. */\nexport type OldSourceOrigin =\n /** `git cat-file blob <anchor.ref>:<file>` — the rev the record named. */\n | { kind: \"ref\"; ref: string }\n /** The last commit touching the path before `resolved_at`. */\n | { kind: \"history\"; ref: string };\n\nexport type OldSource =\n | { ok: true; source: string; origin: OldSourceOrigin }\n /**\n * No committed text to diff against: no usable `ref`, no history before\n * `resolved_at`, or the path did not exist at the rev that was found.\n */\n | { ok: false; reason: \"unrecoverable\" };\n\n/**\n * The anchored file as it was, `ref` first and the record's own timestamp\n * second.\n *\n * `ref` is what the record asserted the evidence was taken at, so it is tried\n * before anything inferred. Falling back to `git log --before=<resolved_at>`\n * recovers the far commoner case of an anchor that was stamped but never\n * pinned; it is weaker — the last commit before a timestamp is a guess about\n * which tree the reader had — which is why the origin travels with the text.\n */\nexport async function readOldSource(\n repoRoot: string,\n anchor: { file: string; ref?: string; resolved_at?: string },\n): Promise<OldSource> {\n if (!filePathIsSafe(anchor.file))\n return { ok: false, reason: \"unrecoverable\" };\n\n if (anchor.ref && refShapeIsSafe(anchor.ref)) {\n const shown = await catBlob(repoRoot, anchor.ref, anchor.file);\n if (shown !== null) {\n return {\n ok: true,\n source: shown,\n origin: { kind: \"ref\", ref: anchor.ref },\n };\n }\n }\n\n const at = anchor.resolved_at;\n if (!at || Number.isNaN(Date.parse(at))) {\n return { ok: false, reason: \"unrecoverable\" };\n }\n // `--before` is a git-parsed value, not a path or a rev, and it is passed as\n // one `--before=<date>` token so it can never be read as two arguments.\n const found = await git(repoRoot, [\n \"log\",\n \"-1\",\n \"--format=%H\",\n `--before=${at}`,\n \"--end-of-options\",\n \"HEAD\",\n \"--\",\n anchor.file,\n ]);\n const sha = found.ok ? found.stdout.trim() : \"\";\n if (!sha || !refShapeIsSafe(sha))\n return { ok: false, reason: \"unrecoverable\" };\n\n const shown = await catBlob(repoRoot, sha, anchor.file);\n if (shown === null) return { ok: false, reason: \"unrecoverable\" };\n return { ok: true, source: shown, origin: { kind: \"history\", ref: sha } };\n}\n\n/**\n * `<rev>:<path>` is one positional, so both halves are validated together.\n * `cat-file blob` rather than `show`: a path naming a directory must fail, and\n * `show` would hand back a tree listing to be hashed as if it were source.\n */\nasync function catBlob(\n repoRoot: string,\n ref: string,\n file: string,\n): Promise<string | null> {\n const path = file.replace(/^\\.\\//, \"\");\n const result = await git(repoRoot, [\n \"cat-file\",\n \"blob\",\n \"--end-of-options\",\n `${ref}:${path}`,\n ]);\n return result.ok ? result.stdout : null;\n}\n","import { DEFAULT_IO_CONCURRENCY, mapLimit } from \"../concurrency.js\";\nimport { readFileAtRef } from \"../drift/git.js\";\nimport type { KbAnchor, KbRecord } from \"../kb-record.schema.js\";\nimport {\n readRemoteAnchors,\n wantKey,\n type RemoteOptions,\n type RemoteRead,\n type RemoteWant,\n} from \"../remote-repo/index.js\";\nimport type {\n AnchorFileReader,\n AnchorHashKind,\n AnchorRead,\n AnchorResolver,\n AnchorResolverName,\n KbAnchorDriftEntry,\n KbDriftClass,\n} from \"./model.js\";\nimport { anchorFileReader, readAnchorFiles } from \"./read.js\";\nimport { LazyOrigin, normalizeRepoUrl } from \"./repo-identity.js\";\nimport {\n anchorHashOf,\n defaultAnchorResolvers,\n prepareResolvers,\n resolveAnchorSpan,\n resolverChanged,\n} from \"./resolver.js\";\n\nexport type AnchorDriftOptions = {\n repoRoot?: string;\n /** Single resolver, no chain. Convenience for tests. */\n resolver?: AnchorResolver;\n /** The chain, tried in order. Defaults to tree-sitter then regex. */\n resolvers?: readonly AnchorResolver[];\n concurrency?: number;\n /** Test seam: replaces the disk reader. */\n reader?: AnchorFileReader;\n /** Test seam: replaces the committed-side git read. */\n readAtRef?: typeof readFileAtRef;\n /** Remote resolution of foreign anchors; `offline` keeps a run off the wire. */\n remote?: RemoteOptions;\n /** Test seam: replaces the remote blob reader. */\n readRemote?: typeof readRemoteAnchors;\n};\n\ntype Planned = { anchor: KbAnchor; foreign: boolean };\n\n/**\n * Re-resolves every hash-carrying anchor and compares against the stored hash.\n *\n * An anchor naming another repository is read from that repository's remote\n * through a bare cache; everything else is read from the working tree. A\n * missing file, an unreachable remote, or an unresolvable symbol is a finding\n * (`unresolved`), never a throw.\n *\n * Four phases: collect the checkable anchors, read the working tree's distinct\n * files and the remotes' distinct (repo, rev, file) blobs, then resolve and\n * hash in record order — so the output never depends on which read finished\n * first.\n */\nexport async function detectAnchorDrift(\n records: KbRecord[],\n options: AnchorDriftOptions = {},\n): Promise<Map<string, KbAnchorDriftEntry[]>> {\n const repoRoot = options.repoRoot ?? process.cwd();\n const resolvers =\n options.resolvers ??\n (options.resolver\n ? [options.resolver]\n : defaultAnchorResolvers({\n offline: options.remote?.offline === true,\n }));\n const origin = new LazyOrigin(repoRoot);\n\n const planned = new Map<string, Planned[]>();\n let declaresRepo = false;\n for (const record of records) {\n const anchors = (record.frontmatter.strauss_anchors ?? []).filter(\n (anchor) => anchor.hash,\n );\n if (!anchors.length) continue;\n if (anchors.some((anchor) => anchor.repo)) declaresRepo = true;\n planned.set(\n record.conceptId,\n anchors.map((anchor) => ({ anchor, foreign: false })),\n );\n }\n if (declaresRepo) {\n await origin.prime();\n for (const entries of planned.values()) {\n for (const entry of entries)\n entry.foreign = origin.isForeign(entry.anchor);\n }\n }\n\n const files: string[] = [];\n const committedWants: KbAnchor[] = [];\n const wants: RemoteWant[] = [];\n for (const entries of planned.values()) {\n for (const { anchor, foreign } of entries) {\n if (foreign) wants.push(...remoteWants(anchor));\n else if (anchor.side === \"old\") committedWants.push(anchor);\n else files.push(anchor.file);\n }\n }\n\n // Disk, git and network are independent; none waits for another.\n const [reads, committed, remote] = await Promise.all([\n readAnchorFiles(\n files,\n options.reader ?? anchorFileReader(repoRoot),\n options.concurrency ?? DEFAULT_IO_CONCURRENCY,\n ),\n readCommitted(repoRoot, committedWants, options),\n (options.readRemote ?? readRemoteAnchors)(wants, options.remote ?? {}),\n ]);\n await prepareResolvers(resolvers, [\n ...files,\n ...committedWants.map((anchor) => anchor.file),\n ...wants.map((want) => want.file),\n ]);\n\n const drift = new Map<string, KbAnchorDriftEntry[]>();\n for (const record of records) {\n const entries: KbAnchorDriftEntry[] = [];\n for (const { anchor, foreign } of planned.get(record.conceptId) ?? []) {\n if (foreign) {\n entries.push(remoteEntry(anchor, remote, resolvers));\n continue;\n }\n const read = (\n anchor.side === \"old\"\n ? committed.get(atRefKey(anchor))\n : reads.get(anchor.file)\n ) as AnchorRead;\n entries.push(localEntry(anchor, read, resolvers));\n }\n if (entries.length) drift.set(record.conceptId, entries);\n }\n return drift;\n}\n\n/** One key per (ref, file): an old-side anchor is read once per pair, not per anchor. */\nexport function atRefKey(anchor: KbAnchor): string {\n return `${anchor.ref ?? \"\"}\\u0000${anchor.file}`;\n}\n\n/**\n * The committed side, through the guarded git runner. `readAtRef` is a test\n * seam only; nothing else may spawn git from here. Keyed by `atRefKey`, so\n * every read path dedupes the same way and bounds its own concurrency.\n */\nexport async function readCommitted(\n repoRoot: string,\n anchors: readonly KbAnchor[],\n options: { readAtRef?: typeof readFileAtRef; concurrency?: number } = {},\n): Promise<Map<string, AnchorRead>> {\n if (!anchors.length) return new Map();\n const read = options.readAtRef ?? readFileAtRef;\n const byKey = new Map<string, KbAnchor>();\n for (const anchor of anchors) byKey.set(atRefKey(anchor), anchor);\n const keys = [...byKey.keys()];\n const results = await mapLimit(\n keys,\n options.concurrency ?? DEFAULT_IO_CONCURRENCY,\n (key) => read(repoRoot, byKey.get(key) as KbAnchor),\n );\n return new Map(keys.map((key, at) => [key, results[at] as AnchorRead]));\n}\n\n/**\n * What must be read for one foreign anchor: the pinned commit, plus the\n * default branch it is \"current\" against when the anchor pins one at all.\n */\nexport function remoteWants(anchor: KbAnchor): RemoteWant[] {\n const repo = anchor.repo as string;\n const wants: RemoteWant[] = [{ repo, file: anchor.file }];\n if (anchor.ref) wants.unshift({ repo, ref: anchor.ref, file: anchor.file });\n return wants;\n}\n\nfunction base(\n anchor: KbAnchor,\n): Pick<KbAnchorDriftEntry, \"file\" | \"symbol\" | \"side\" | \"storedHash\"> {\n return {\n file: anchor.file,\n ...(anchor.symbol ? { symbol: anchor.symbol } : {}),\n ...(anchor.side === \"old\" ? { side: \"old\" as const } : {}),\n storedHash: anchor.hash as string,\n };\n}\n\nfunction unresolved(\n anchor: KbAnchor,\n reason: KbAnchorDriftEntry[\"reason\"],\n repo?: string,\n): KbAnchorDriftEntry {\n return {\n ...base(anchor),\n state: \"unresolved\",\n diffSize: null,\n ...(reason ? { reason } : {}),\n ...(repo ? { repo } : {}),\n ...classOf(reason),\n };\n}\n\n/** Every way of saying \"the described code is not there to be re-read\". */\nconst GONE_REASONS = new Set<KbAnchorDriftEntry[\"reason\"]>([\n \"file-missing\",\n \"symbol-not-found\",\n \"span-out-of-range\",\n \"ref-unreadable\",\n]);\n\n/**\n * The class a hash comparison alone can settle.\n *\n * A vanished file, an undefined symbol, a span past the end of its file or a\n * `ref` that will not read is `gone` — the strongest signal there is. Anything\n * that resolved and hashed differently is `changed` until a search proves it\n * only moved.\n */\nexport function provisionalDriftClass(\n entry: Pick<KbAnchorDriftEntry, \"state\" | \"reason\">,\n): KbDriftClass | undefined {\n if (entry.state === \"unresolved\") {\n return GONE_REASONS.has(entry.reason) ? \"gone\" : undefined;\n }\n return entry.state === \"drifted\" ? \"changed\" : undefined;\n}\n\n/** `class` for an unresolved reason, or nothing to spread. */\nfunction classOf(reason: KbAnchorDriftEntry[\"reason\"]): {\n class?: KbDriftClass;\n} {\n const settled = provisionalDriftClass({ state: \"unresolved\", reason });\n return settled ? { class: settled } : {};\n}\n\ntype Current = {\n hash: string;\n kind: AnchorHashKind;\n lines: number;\n resolver?: AnchorResolverName;\n};\n\n/** The hash of an anchor's text in one source, or the reason it has none. */\nfunction hashIn(\n source: string,\n anchor: KbAnchor,\n resolvers: readonly AnchorResolver[],\n):\n | { ok: true; current: Current }\n | { ok: false; reason: KbAnchorDriftEntry[\"reason\"] } {\n const outcome = resolveAnchorSpan(source, anchor, resolvers);\n if (!outcome.ok) return { ok: false, reason: outcome.reason };\n const { hash, kind } = anchorHashOf(anchor, outcome);\n return {\n ok: true,\n current: {\n hash,\n kind,\n lines: outcome.span.endLine - outcome.span.startLine + 1,\n ...(outcome.resolver ? { resolver: outcome.resolver } : {}),\n },\n };\n}\n\n/**\n * Which resolver produced the hash, and — when it differs from the stored one\n * — whether that swap is the whole difference. A regex-stamped anchor re-read\n * by tree-sitter drifts because the resolver changed, not because the code\n * did; named so a reader can tell the two apart before reaching for\n * `--rebaseline`.\n */\nfunction resolverExtras(\n source: string,\n anchor: KbAnchor,\n current: Current,\n): Partial<KbAnchorDriftEntry> {\n return {\n ...(current.resolver ? { resolver: current.resolver } : {}),\n ...(current.hash !== anchor.hash &&\n resolverChanged(source, anchor, current.resolver)\n ? { reason: \"resolver-changed\" as const }\n : {}),\n };\n}\n\nfunction compared(\n anchor: KbAnchor,\n current: Current,\n extra: Partial<KbAnchorDriftEntry> = {},\n): KbAnchorDriftEntry {\n const matched = current.hash === anchor.hash;\n return {\n ...base(anchor),\n state: matched ? \"match\" : \"drifted\",\n currentHash: current.hash,\n hashKind: current.kind,\n diffSize:\n anchor.lines === undefined\n ? null\n : Math.abs(current.lines - anchor.lines),\n ...(matched ? {} : { class: \"changed\" as const }),\n ...extra,\n };\n}\n\nfunction localEntry(\n anchor: KbAnchor,\n read: AnchorRead,\n resolvers: readonly AnchorResolver[],\n): KbAnchorDriftEntry {\n if (!read.ok) return unresolved(anchor, read.reason);\n const found = hashIn(read.source, anchor, resolvers);\n if (!found.ok) return unresolved(anchor, found.reason);\n return compared(\n anchor,\n found.current,\n resolverExtras(read.source, anchor, found.current),\n );\n}\n\n/**\n * A foreign anchor's three states.\n *\n * The pinned commit decides whether the evidence still holds; the default\n * branch only adds `drifted-on-default` on top of a ref that still matches. A\n * default branch that could not be read therefore never downgrades a `ref` hit\n * — offline, a pinned anchor still verifies.\n */\nfunction remoteEntry(\n anchor: KbAnchor,\n remote: Map<string, RemoteRead>,\n resolvers: readonly AnchorResolver[],\n): KbAnchorDriftEntry {\n const repo = anchor.repo as string;\n const key = normalizeRepoUrl(repo);\n const atDefault = remote.get(wantKey(key, undefined, anchor.file));\n const primary = anchor.ref\n ? remote.get(wantKey(key, anchor.ref, anchor.file))\n : atDefault;\n\n if (!primary) return unresolved(anchor, \"remote-unreachable\", repo);\n if (!primary.ok) return unresolved(anchor, primary.reason, repo);\n\n const found = hashIn(primary.source, anchor, resolvers);\n if (!found.ok) return unresolved(anchor, found.reason, repo);\n const current = found.current;\n const extras = resolverExtras(primary.source, anchor, current);\n if (!anchor.ref) return compared(anchor, current, { repo, ...extras });\n if (current.hash !== anchor.hash) {\n return compared(anchor, current, {\n repo,\n ...extras,\n remoteState: \"drifted-from-ref\",\n });\n }\n // `side: \"old\"` is a claim about the pinned commit alone, so the default\n // branch has nothing to add: having moved on is what the anchor already says.\n if (anchor.side === \"old\") {\n return compared(anchor, current, {\n repo,\n ...extras,\n remoteState: \"matches-ref\",\n });\n }\n\n const head = atDefault?.ok\n ? hashIn(atDefault.source, anchor, resolvers)\n : null;\n return head?.ok && head.current.hash !== anchor.hash\n ? {\n ...compared(anchor, head.current, {\n repo,\n ...(head.current.resolver ? { resolver: head.current.resolver } : {}),\n }),\n state: \"drifted\",\n remoteState: \"drifted-on-default\",\n }\n : compared(anchor, current, {\n repo,\n ...extras,\n remoteState: \"matches-ref\",\n });\n}\n","import { z } from \"zod\";\n\n/**\n * Knowledge records, shaped as OKF v0.2 concepts.\n *\n * OKF (Google Cloud `knowledge-catalog`) requires exactly one key — `type` —\n * and explicitly permits extension: \"Producers MAY include any additional keys.\n * Consumers SHOULD preserve unknown keys when round-tripping and MUST NOT\n * reject documents with unrecognized fields.\"\n *\n * A record's identity is its `concept_id`: the file path within the bundle with\n * `.md` removed. `<type>.<slug>.md` therefore yields `decision.some-slug`.\n *\n * Keys prefixed `strauss_` are this package's extensions rather than\n * conformance, and are namespaced so a later OKF version defining the same\n * names cannot collide: OKF names files through path-valued `resource` fields\n * and has no notion of a span, so anchoring a concept to a range of code has no\n * standard spelling, and standing has none either.\n */\n\n/** A source the record draws on. Footnotes in the body key to `id`. */\nexport const kbSourceSchema = z\n .object({\n id: z.string().min(1),\n resource: z.string().min(1),\n title: z.string().min(1).optional(),\n author: z.string().min(1).optional(),\n last_modified: z.string().min(1).optional(),\n })\n .passthrough();\n\n/** An actor/time pair — OKF's shape for both `generated` and `verified[]`. */\nexport const kbActorStampSchema = z\n .object({\n by: z.string().min(1),\n at: z.string().min(1),\n })\n .passthrough();\n\n/**\n * A `verified[]` event as this package writes one: the actor stamp plus a\n * required note saying what the check found. Write-side only — the frontmatter\n * keeps reading `verified` with `kbActorStampSchema`, because OKF-native\n * entries carry no note and a consumer must not reject conformant records.\n */\nexport const kbVerifiedEventSchema = kbActorStampSchema.extend({\n note: z.string().refine((s) => s.trim().length > 0, {\n message: \"note must say what the check found\",\n }),\n});\n\n/**\n * Where a record attaches in the code.\n *\n * Symbolic on purpose. These are written while the code is still moving: a\n * `line: 379` recorded at minute five is wrong by minute forty, but\n * `OrderService.cancel` survives every edit that does not rename it. Once the\n * change settles, a resolution pass (`anchor-resolver/`) stamps `hash`,\n * `resolved_at`, and `lines`; drift detection later re-resolves and compares.\n *\n * `hash` is prefixed with the algorithm so a future one can coexist with\n * stored values. `lines` exists because the anchor keeps a hash, not the text:\n * without the line count at hash time, a drift report could say \"changed\" but\n * never how much.\n *\n * `repo` and `ref` say *which* code, for bases that describe more than one\n * repository. They are author-owned identity: a resolver stamps `hash`,\n * `lines`, and `resolved_at`, and never writes these two. Both are optional and\n * independent of each other, so every anchor written before they existed stays\n * valid.\n */\n\n/**\n * An explicit line range, 1-based and inclusive. Author-owned: a resolver\n * hashes it but never moves it.\n */\nexport const kbAnchorSpanSchema = z\n .object({\n start: z.number().int().positive(),\n end: z.number().int().positive(),\n })\n .strict();\n\nexport const kbAnchorSchema = z\n .object({\n file: z.string().min(1),\n symbol: z.string().min(1).optional(),\n /**\n * The lines the concept names, when no symbol covers them — deleted code,\n * YAML, SQL, Markdown. Alternative to `symbol`, never a refinement of it.\n */\n span: kbAnchorSpanSchema.optional(),\n /**\n * Which side of the change the anchor describes. `old` is code as it was\n * committed at `ref`, which is the only way to anchor something deleted;\n * absent means the working tree.\n */\n side: z.enum([\"old\", \"new\"]).optional(),\n /**\n * Which repository the file lives in — a remote URL\n * (`https://github.com/org/name`) or a short name. Absent means the base's\n * own repository, which is what nearly every anchor means.\n *\n * Unvalidated beyond not-blank: one repository has many spellings, matched\n * after normalisation. Only a full URL can be fetched from, so `validate`\n * warns on a short one; see ARCHITECTURE.\n */\n repo: z.string().trim().min(1).optional(),\n /**\n * The git rev the evidence was taken at. Prefer a commit SHA: a branch\n * name is a moving pointer, so an anchor pinned to one says the evidence\n * came from wherever that branch happens to be now, which is not a\n * baseline. A foreign anchor is checked at this rev, and compared against\n * the remote's default branch on top of it.\n */\n ref: z.string().trim().min(1).optional(),\n hash: z\n .string()\n .regex(/^sha256:[0-9a-f]{64}$/, {\n message: \"hash must be sha256:<64 hex chars>\",\n })\n .optional(),\n /**\n * What `hash` was taken over: the span's raw text, or the normalised token\n * stream a parser sees (`ast`). Absent means `raw`, which is what every\n * anchor stamped before this field carries, so old hashes keep comparing\n * the way they were written. An `ast` hash is blind to whitespace and\n * comments, so reformatting the anchored code is not drift.\n */\n hash_kind: z.enum([\"raw\", \"ast\"]).optional(),\n /** ISO 8601 timestamp of the last successful resolution. */\n resolved_at: z.string().min(1).optional(),\n /** Line count of the text the hash was taken over. */\n lines: z.number().int().positive().optional(),\n /**\n * Which resolver produced the hashed span. Absent means an anchor stamped\n * before resolvers were named, which is read as `regex` — the only one\n * there was. A hash from a different resolver is drift, not a match.\n */\n resolver: z.enum([\"tree-sitter\", \"regex\", \"span\"]).optional(),\n })\n .strict();\n\n/**\n * The anchor rules a resolver cannot settle for itself.\n *\n * Write-side only, like `kbVerifiedEventSchema`: the frontmatter keeps parsing\n * with `kbAnchorSchema`, so a hand-edited defect is a `kb_validate` finding\n * rather than a record that silently vanishes from `list()`.\n */\nexport const kbAnchorWriteSchema = kbAnchorSchema.superRefine((anchor, ctx) => {\n if (anchor.span && anchor.symbol) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [\"span\"],\n message: \"an anchor names a symbol or a span, not both\",\n });\n }\n if (anchor.span && anchor.span.end < anchor.span.start) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [\"span\", \"end\"],\n message: \"span end must not precede start\",\n });\n }\n // A span is hashed raw, so an `ast` kind on one would compare a raw hash\n // against a token-stream hash and report drift for ever.\n if (anchor.span && anchor.hash_kind === \"ast\") {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [\"hash_kind\"],\n message: \"a span is hashed raw, never ast\",\n });\n }\n if (anchor.side === \"old\" && !anchor.ref) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [\"ref\"],\n message: 'side: \"old\" needs a ref — committed code has no other address',\n });\n }\n});\n\n/**\n * An anchor's address, with none of the baseline a resolver stamps: a `hash`\n * under a locator is an unknown key. Picked rather than respelled, so a new\n * locator field on the anchor is one here too. See\n * `contract.anchor-locator-is-the-address-half-of-an-anchor`.\n */\nexport const kbAnchorLocatorSchema = kbAnchorSchema.pick({\n file: true,\n symbol: true,\n span: true,\n side: true,\n repo: true,\n ref: true,\n});\n\n/**\n * One typed causal edge, as the frontmatter stores it.\n *\n * Read-side, and therefore tolerant: `rel` is a plain string here even though\n * the vocabulary is closed, for the same reason `type` is. Rejecting an unknown\n * rel at parse time would make the file vanish from `list()`, and a bundle\n * cannot report a defect in a record it refuses to load. `kb_validate` turns an\n * unknown rel into an error; `composeRecord` stops one being written.\n *\n * `target` is likewise not required to resolve — a dangling target is a\n * validation warning rather than a parse failure.\n */\nexport const kbLinkSchema = z\n .object({\n target: z.string().min(1),\n rel: z.string().min(1),\n })\n .passthrough();\n\nexport const KB_RECORD_TYPES = [\n \"fact\",\n \"requirement\",\n \"constraint\",\n \"decision\",\n \"assumption\",\n \"open-question\",\n \"risk\",\n \"contract\",\n \"flow\",\n \"affected-system\",\n \"test-obligation\",\n \"source-note\",\n] as const;\n\nexport type KbRecordType = (typeof KB_RECORD_TYPES)[number];\n\n/** Both halves of `<type>.<slug>` are kebab-case, and neither may be empty. */\nexport const KB_SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\nexport const KB_CONCEPT_ID_PATTERN =\n /^[a-z0-9]+(?:-[a-z0-9]+)*\\.[a-z0-9]+(?:-[a-z0-9]+)*$/;\n\n/**\n * Concept ids are rendered into markdown links unescaped, so an id carrying a\n * `]` or `)` would emit a broken edge rather than fail. Validating at the entry\n * point keeps the renderer from having to care.\n */\nexport const kbConceptIdSchema = z.string().regex(KB_CONCEPT_ID_PATTERN, {\n message: \"concept id must be <type>.<slug>, both kebab-case\",\n});\n\n/**\n * Standing, not freshness.\n *\n * OKF's `verified[]` and `stale_after` answer \"is this still true?\"; nothing in\n * the spec answers \"is this settled, and does it still apply?\". A base\n * supersedes its own conclusions as work proceeds, so that second question\n * needs an answer, and it is this package's to define — hence `strauss_`.\n */\nexport const KB_RECORD_STATUSES = [\n \"draft\",\n \"proposed\",\n \"accepted\",\n \"open\",\n \"resolved\",\n \"rejected\",\n \"superseded\",\n] as const;\n\nexport type KbRecordStatus = (typeof KB_RECORD_STATUSES)[number];\n\nexport const KB_MATERIALITIES = [\n \"blocking\",\n \"important\",\n \"non-blocking\",\n] as const;\nexport const KB_CONFIDENCES = [\"low\", \"medium\", \"high\"] as const;\n\nexport const kbRecordFrontmatterSchema = z\n .object({\n // OKF: the only always-required key. A concept carrying just `type` is\n // fully conformant, so everything below stays optional.\n type: z.string().min(1),\n\n // OKF recommended.\n title: z.string().min(1).optional(),\n description: z.string().min(1).optional(),\n resource: z.string().min(1).optional(),\n tags: z.array(z.string()).optional(),\n\n // OKF optional: provenance and freshness.\n sources: z.array(kbSourceSchema).optional(),\n generated: kbActorStampSchema.optional(),\n verified: z.array(kbActorStampSchema).optional(),\n stale_after: z.string().min(1).optional(),\n\n // strauss extensions — see the module comment.\n strauss_anchors: z.array(kbAnchorSchema).optional(),\n strauss_verify: z.array(z.string().min(1)).optional(),\n\n // Typed causal edges, source → target, living on the source. `A depends_on\n // B` means A needs B, so `kb_impact` walks these inbound: what breaks if B\n // changes is whatever declared a dependence on it.\n strauss_links: z.array(kbLinkSchema).optional(),\n\n // Total after parsing, tolerant before it. Our producers must supply a\n // status — an absent one would leave every reader inventing its own default\n // — but OKF calls a concept carrying only `type` fully conformant, so\n // rejecting a foreign record for the lack of one would put us outside the\n // spec. The default resolves it in the single place that can: here.\n strauss_status: z.enum(KB_RECORD_STATUSES).default(\"draft\"),\n strauss_supersedes: z.array(z.string().min(1)).optional(),\n strauss_superseded_by: z.string().min(1).optional(),\n strauss_answered: kbActorStampSchema.optional(),\n strauss_materiality: z.enum(KB_MATERIALITIES).optional(),\n strauss_confidence: z.enum(KB_CONFIDENCES).optional(),\n strauss_owner: z.string().min(1).optional(),\n\n // \"No source exists\" as a field rather than a sentinel entry inside\n // `sources`. A sentinel in a reference list is a value doing work a field\n // should do; as a field, `sources` may be legitimately empty.\n strauss_assumption: z.boolean().optional(),\n })\n // Unknown keys are kept rather than stripped: OKF requires consumers to\n // preserve them when round-tripping, and a producer we don't know about may\n // be writing into the same bundle.\n .passthrough();\n\nexport type KbSource = z.infer<typeof kbSourceSchema>;\nexport type KbActorStamp = z.infer<typeof kbActorStampSchema>;\nexport type KbVerifiedEvent = z.infer<typeof kbVerifiedEventSchema>;\nexport type KbAnchorSpan = z.infer<typeof kbAnchorSpanSchema>;\nexport type KbAnchor = z.infer<typeof kbAnchorSchema>;\nexport type KbAnchorLocator = z.infer<typeof kbAnchorLocatorSchema>;\nexport type KbLink = z.infer<typeof kbLinkSchema>;\nexport type KbRecordFrontmatter = z.infer<typeof kbRecordFrontmatterSchema>;\n\nexport type KbRecord = {\n /** Path minus `.md`, relative to the bundle root. OKF's concept identity. */\n conceptId: string;\n frontmatter: KbRecordFrontmatter;\n body: string;\n};\n","/**\n * The error shape the store throws.\n *\n * Every caller here is an agent, reached through a CLI or a stdio MCP server,\n * so a bare `Error` arrives as an opaque string. What a caller has to act on is\n * carried as fields instead: `code` separates \"pick a different slug and retry\"\n * from \"this input was never going to work\", and `retriable` says whether\n * re-running the same call could succeed.\n *\n * No dependency, deliberately. This is four fields and a constructor; an error\n * library would be a runtime dependency in aid of that.\n */\nexport enum Fault {\n /** The environment is wrong — a path, a permission, a missing directory. */\n Configuration = \"Configuration\",\n /** Nothing the caller did; retrying may work. */\n System = \"System\",\n /** The call was malformed or asked for something impossible. */\n User = \"User\",\n}\n\n/** Machine-readable discriminant, stable across message rewording. */\nexport enum ErrorTypes {\n KbRecordAlreadyExists = \"KbRecordAlreadyExists\",\n KbAnchorSetDuplicate = \"KbAnchorSetDuplicate\",\n KbClassifyInput = \"KbClassifyInput\",\n KbFlagConflict = \"KbFlagConflict\",\n KbInvalidActor = \"KbInvalidActor\",\n KbInvalidConceptId = \"KbInvalidConceptId\",\n KbMatchInput = \"KbMatchInput\",\n KbMissingFlagValue = \"KbMissingFlagValue\",\n KbPackBudgetExceeded = \"KbPackBudgetExceeded\",\n KbPromoteCollision = \"KbPromoteCollision\",\n KbPromoteSelf = \"KbPromoteSelf\",\n KbPromoteStanding = \"KbPromoteStanding\",\n KbPromoteStopped = \"KbPromoteStopped\",\n KbRecordNotFound = \"KbRecordNotFound\",\n KbSelfVerification = \"KbSelfVerification\",\n KbStampBaselineUnreadable = \"KbStampBaselineUnreadable\",\n KbStampDigestBaselineAmbiguous = \"KbStampDigestBaselineAmbiguous\",\n KbUnknownLinkRel = \"KbUnknownLinkRel\",\n KbWriteConflict = \"KbWriteConflict\",\n}\n\nexport type ErrorDetails = Record<\n string,\n string | boolean | number | string[] | boolean[] | number[]\n>;\n\nexport interface ErrorProps {\n message: string;\n errorType?: ErrorTypes;\n details?: ErrorDetails;\n name?: string;\n code?: number;\n fault?: Fault;\n retriable?: boolean;\n reportToUser?: boolean;\n}\n\nexport class BaseError extends Error {\n code: number;\n errorType?: ErrorTypes;\n fault?: Fault;\n retriable: boolean;\n reportToUser: boolean;\n details?: ErrorDetails;\n\n constructor(props: ErrorProps) {\n super(props.message);\n this.name = props.name ?? this.constructor.name;\n this.code = props.code ?? 500;\n this.errorType = props.errorType;\n this.fault = props.fault;\n this.retriable = props.retriable ?? true;\n this.reportToUser = props.reportToUser ?? false;\n this.details = props.details;\n }\n}\n","import { BaseError, ErrorTypes, Fault } from \"../errors.js\";\nimport type { KbAnchorLocator } from \"../kb-record.schema.js\";\n\n/**\n * A locator in the terms the caller wrote it, for an error message. Each field\n * is capped: `file` and `symbol` have no maximum length, and this text goes\n * into a tool result the caller pays for by the token.\n */\nexport function locatorText(locator: KbAnchorLocator): string {\n const span = locator.span ? `:${locator.span.start}-${locator.span.end}` : \"\";\n const symbol = locator.symbol ? `:${cap(locator.symbol)}` : \"\";\n const repo = locator.repo ? `${cap(locator.repo)}@` : \"\";\n const ref = locator.ref ? `@${cap(locator.ref)}` : \"\";\n return `${repo}${cap(locator.file)}${symbol}${span}${ref}`;\n}\n\nconst FIELD_CAP = 120;\n\nfunction cap(value: string): string {\n return value.length > FIELD_CAP ? `${value.slice(0, FIELD_CAP - 1)}…` : value;\n}\n\n/** Two anchors at one address: they would drift and rebaseline as a pair. */\nexport class KbAnchorSetDuplicateError extends BaseError {\n constructor(readonly locator: string) {\n super({\n message: `kb: ${locator} appears twice in this set — a record holds each pointer once`,\n errorType: ErrorTypes.KbAnchorSetDuplicate,\n code: 400,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { locator, action: \"refused\" },\n });\n }\n}\n","import { normalizeRepoUrl } from \"../anchor-resolver/index.js\";\nimport {\n kbAnchorLocatorSchema,\n type KbAnchor,\n type KbAnchorLocator,\n} from \"../kb-record.schema.js\";\nimport { KbAnchorSetDuplicateError, locatorText } from \"./errors.js\";\n\n/** One change the write made, as the result and the log entry report it. */\nexport type KbAnchorChange = {\n /** `move` keeps a baseline under a new address; `add` and `drop` are plain. */\n op: \"move\" | \"add\" | \"drop\";\n from?: KbAnchorLocator;\n to?: KbAnchorLocator;\n};\n\nconst LOCATOR_FIELDS = [\n \"file\",\n \"symbol\",\n \"span\",\n \"side\",\n \"repo\",\n \"ref\",\n] as const;\n\nexport type KbAnchorSetOutcome = {\n anchors: KbAnchor[];\n changes: KbAnchorChange[];\n};\n\n/**\n * Checks a proposed anchor set and says what changed against the current one.\n * Accepted as given — whether the code behind a pointer was read is the\n * caller's claim, recorded in the log, not something this can check. Refuses\n * only two anchors at one address.\n */\nexport function applyAnchorSet(\n current: KbAnchor[],\n incoming: KbAnchor[],\n): KbAnchorSetOutcome {\n const anchors = incoming.map((anchor) => ({ ...anchor }));\n const seen = new Set<string>();\n for (const anchor of anchors) {\n const key = locatorKey(anchor);\n if (seen.has(key)) {\n throw new KbAnchorSetDuplicateError(locatorText(locatorOf(anchor)));\n }\n seen.add(key);\n }\n return { anchors, changes: diff(current, anchors) };\n}\n\n/**\n * What the write did, in the reader's terms: a baseline that changed address\n * moved, an anchor the set no longer holds was dropped, the rest were added.\n * Derived from before and after rather than declared by the caller, so the log\n * records what happened.\n */\nfunction diff(current: KbAnchor[], next: KbAnchor[]): KbAnchorChange[] {\n const before = new Map(\n current.filter((anchor) => anchor.hash).map((a) => [a.hash as string, a]),\n );\n const beforeLocators = new Map(current.map((a) => [locatorKey(a), a]));\n const afterLocators = new Set(next.map((anchor) => locatorKey(anchor)));\n const moved = new Set<string>();\n const changes: KbAnchorChange[] = [];\n\n for (const anchor of next) {\n const source = anchor.hash ? before.get(anchor.hash) : undefined;\n if (source) {\n if (locatorKey(source) === locatorKey(anchor)) continue;\n moved.add(locatorKey(source));\n changes.push({\n op: \"move\",\n from: locatorOf(source),\n to: locatorOf(anchor),\n });\n continue;\n }\n if (beforeLocators.has(locatorKey(anchor))) continue;\n changes.push({ op: \"add\", to: locatorOf(anchor) });\n }\n\n for (const anchor of current) {\n const key = locatorKey(anchor);\n if (afterLocators.has(key) || moved.has(key)) continue;\n changes.push({ op: \"drop\", from: locatorOf(anchor) });\n }\n return changes;\n}\n\n/** An anchor's address, without the baseline a resolver stamped onto it. */\nexport function locatorOf(anchor: KbAnchor): KbAnchorLocator {\n return kbAnchorLocatorSchema.parse(\n Object.fromEntries(\n LOCATOR_FIELDS.flatMap((field) =>\n anchor[field] === undefined ? [] : [[field, anchor[field]]],\n ),\n ),\n );\n}\n\n/**\n * One address as a comparable string. `repo` goes through the resolver's own\n * normalisation, so two spellings of one remote are one place; an absent\n * `side` reads as `new`, which is what it means.\n */\nfunction locatorKey(anchor: KbAnchor): string {\n return JSON.stringify([\n anchor.file,\n anchor.symbol ?? \"\",\n anchor.span ? `${anchor.span.start}-${anchor.span.end}` : \"\",\n anchor.side ?? \"new\",\n anchor.repo === undefined ? \"\" : normalizeRepoUrl(anchor.repo),\n anchor.ref ?? \"\",\n ]);\n}\n","import type { KbRecordStatus, KbRecordType } from \"./kb-record.schema.js\";\n\n/**\n * What each record type is for, and the shape of its body.\n *\n * A table rather than twelve composer modules. The types differ only in which\n * questions their body answers and where they start in the lifecycle; encoding\n * that as data keeps the one composer honest and makes adding a type an edit\n * rather than a file.\n *\n * `sections` are ordered. A section the caller leaves empty is omitted rather\n * than rendered with a placeholder — an empty \"## Evidence\" reads as evidence\n * that was looked for and not found.\n */\nexport type KbRecordTypeSpec = {\n /** One line, for `INDEX.md` legends and CLI help. */\n purpose: string;\n /** Ordered body headings. The first is the record's central claim. */\n sections: readonly string[];\n /** Where a freshly written record of this type starts. */\n initialStatus: KbRecordStatus;\n};\n\nexport const RECORD_TYPES: Readonly<Record<KbRecordType, KbRecordTypeSpec>> = {\n fact: {\n purpose: \"Observed or sourced fact\",\n sections: [\"Claim\", \"Evidence\", \"Implication\"],\n initialStatus: \"accepted\",\n },\n requirement: {\n purpose: \"Required behavior or outcome\",\n sections: [\"Claim\", \"Evidence\", \"Implication\"],\n initialStatus: \"proposed\",\n },\n constraint: {\n purpose: \"Limitation, compatibility boundary, policy, or restriction\",\n sections: [\"Claim\", \"Evidence\", \"Implication\"],\n initialStatus: \"accepted\",\n },\n decision: {\n purpose: \"Chosen or proposed direction\",\n sections: [\"Decision\", \"Rationale\", \"Rejected\", \"Impact\"],\n initialStatus: \"accepted\",\n },\n assumption: {\n purpose: \"Unsourced or not-yet-confirmed working assumption\",\n sections: [\"Claim\", \"Why we think so\", \"What would falsify it\"],\n initialStatus: \"draft\",\n },\n \"open-question\": {\n purpose: \"Question needing resolution\",\n sections: [\"Question\", \"Why it matters\", \"Default assumption\"],\n initialStatus: \"open\",\n },\n risk: {\n purpose: \"Something that can go wrong\",\n sections: [\"Risk\", \"Why it matters\", \"Mitigation\", \"Verification\"],\n initialStatus: \"open\",\n },\n contract: {\n purpose: \"API, data, event, schema, or permission contract\",\n sections: [\"Contract\", \"Producer\", \"Consumer\", \"Compatibility\"],\n initialStatus: \"proposed\",\n },\n flow: {\n purpose: \"Sequence, lifecycle, or state behavior\",\n sections: [\"Flow\", \"Trigger\", \"Steps\", \"Failure modes\"],\n initialStatus: \"accepted\",\n },\n \"affected-system\": {\n purpose: \"Component, service, package, integration, or external system\",\n sections: [\"System\", \"How it is affected\", \"Blast radius\"],\n initialStatus: \"accepted\",\n },\n \"test-obligation\": {\n purpose: \"Behavior or contract that must be verified\",\n sections: [\"Obligation\", \"Why it matters\", \"How to verify\"],\n initialStatus: \"open\",\n },\n \"source-note\": {\n purpose: \"Extracted note from source material\",\n sections: [\"Note\", \"Where it came from\"],\n initialStatus: \"accepted\",\n },\n};\n\nexport function isKbRecordType(value: string): value is KbRecordType {\n return Object.prototype.hasOwnProperty.call(RECORD_TYPES, value);\n}\n\n/**\n * The closed vocabulary of typed causal edges — `strauss_links[].rel` — which a\n * producer may not extend. `related_to` is the non-dependence escape hatch and\n * the one rel `kb_impact` does not follow. Every edge lives on the source's\n * frontmatter, source → target; `phrase` is the template compose.ts renders.\n */\nexport type KbLinkRelSpec = {\n /** One line, for schema output and CLI help. */\n purpose: string;\n /** Sentence stem: `<phrase> [target](target.md).` */\n phrase: string;\n /**\n * Which end of the edge breaks when the other end changes.\n *\n * The rel's *direction of dependence*, which does not follow the edge's own\n * direction. `A depends_on B` puts the dependant at the source: A breaks when\n * B moves. `A informs B` puts it at the target. A walk that treated both as\n * \"inbound\" would report the blast radius of `informs`, `blocks`,\n * `invalidates` and `constrains` backwards.\n *\n * `null` means the rel asserts no dependence either way, so nothing\n * propagates along it. `related_to` is the only such rel.\n */\n dependant: \"source\" | \"target\" | null;\n};\n\nexport const KB_LINK_RELS = [\n \"depends_on\",\n \"constrains\",\n \"informs\",\n \"blocks\",\n \"invalidates\",\n \"verified_by\",\n \"satisfies\",\n \"related_to\",\n] as const;\n\nexport type KbLinkRel = (typeof KB_LINK_RELS)[number];\n\nexport const LINK_RELS: Readonly<Record<KbLinkRel, KbLinkRelSpec>> = {\n depends_on: {\n purpose:\n \"The source needs the target to hold; the source breaks if the target changes\",\n phrase: \"Depends on\",\n dependant: \"source\",\n },\n constrains: {\n purpose:\n \"The source bounds what the target may do; the target breaks if the constraint changes\",\n phrase: \"Constrains\",\n dependant: \"target\",\n },\n informs: {\n purpose:\n \"The source shaped the target without binding it; the target is what needs revisiting\",\n phrase: \"Informs\",\n dependant: \"target\",\n },\n blocks: {\n purpose:\n \"The target cannot proceed until the source is settled; the target is what waits\",\n phrase: \"Blocks\",\n dependant: \"target\",\n },\n invalidates: {\n purpose:\n \"The source makes the target no longer hold; the target is what stops holding\",\n phrase: \"Invalidates\",\n dependant: \"target\",\n },\n verified_by: {\n purpose:\n \"The target is the check that confirms the source; the source's confirmation moves with it\",\n phrase: \"Verified by\",\n dependant: \"source\",\n },\n satisfies: {\n purpose:\n \"The source discharges the target's requirement; the source must change if the requirement does\",\n phrase: \"Satisfies\",\n dependant: \"source\",\n },\n related_to: {\n purpose: \"A pointer worth following, with no claim of dependence\",\n phrase: \"Relates to\",\n dependant: null,\n },\n};\n\n/**\n * The rels that carry a direction of dependence, and therefore the only ones\n * anything can propagate along. `kb_impact`'s default edge set, and what\n * `trace` follows.\n *\n * Derived from the table rather than restated, so a rel cannot be causal in one\n * place and inert in another. The cast is a non-emptiness assertion for\n * `z.enum`.\n */\nexport const KB_CAUSAL_LINK_RELS = KB_LINK_RELS.filter(\n (rel) => LINK_RELS[rel].dependant !== null,\n) as [KbLinkRel, ...KbLinkRel[]];\n\nexport function isKbLinkRel(value: string): value is KbLinkRel {\n return Object.prototype.hasOwnProperty.call(LINK_RELS, value);\n}\n","import { z } from \"zod\";\nimport { applyAnchorSet } from \"./anchors/index.js\";\nimport {\n kbAnchorWriteSchema,\n kbConceptIdSchema,\n kbSourceSchema,\n KB_CONFIDENCES,\n KB_MATERIALITIES,\n type KbRecordFrontmatter,\n type KbRecordType,\n} from \"./kb-record.schema.js\";\nimport { KB_LINK_RELS, LINK_RELS, RECORD_TYPES } from \"./record-types.js\";\n\n/**\n * One typed causal edge, as a producer states it.\n *\n * Strict where `kbLinkSchema` is tolerant, the same split\n * `kbVerifiedEventSchema` makes against `kbActorStampSchema`: what this package\n * writes must be inside the closed vocabulary, what it reads may not be, since\n * a foreign record has to stay loadable for `kb_validate` to fault it.\n */\nexport const composeLinkSchema = z\n .object({\n target: kbConceptIdSchema,\n rel: z.enum(KB_LINK_RELS),\n })\n .strict();\n\nexport type ComposeLink = z.infer<typeof composeLinkSchema>;\n\nexport const composeInputSchema = z\n .object({\n slug: z.string().min(1),\n /** One line, in the reader's terms. Becomes OKF `title`. */\n title: z.string().min(1),\n /** The consequence — what breaks if this is wrong. Becomes `description`. */\n why: z.string().min(1),\n /** Keyed by section heading from the type's spec. Unknown keys rejected. */\n sections: z.record(z.string(), z.string().min(1)).optional(),\n anchors: z.array(kbAnchorWriteSchema).optional(),\n sources: z.array(kbSourceSchema).optional(),\n /** No source exists, as a claim rather than a sentinel in `sources`. */\n assumption: z.boolean().optional(),\n /**\n * OKF `stale_after`: the absolute date this record stops being trusted.\n * Anything the outside world can change — pricing, quotas, versions,\n * reception counts — should carry one.\n */\n stale_after: z\n .string()\n .regex(/^\\d{4}-\\d{2}-\\d{2}$/, {\n message: \"stale_after must be YYYY-MM-DD\",\n })\n .refine((date) => !Number.isNaN(Date.parse(date)), {\n message: \"stale_after must be a real date\",\n })\n .optional(),\n verify: z.array(z.string().min(1)).optional(),\n tags: z.array(z.string().min(1)).optional(),\n /** Concept ids this record relates to; rendered as body links. */\n relatedConceptIds: z.array(kbConceptIdSchema).optional(),\n /**\n * Typed causal edges, source → target: `{ target: \"fact.b\", rel:\n * \"depends_on\" }` on record A says A needs B. Stored in frontmatter and\n * also rendered as one prose sentence each, so the meaning survives a\n * reader that knows only OKF. The vocabulary goes into the description from\n * the same table the walk uses, so `kb_schema` emits it.\n */\n links: z\n .array(composeLinkSchema)\n .max(64)\n .optional()\n .describe(\n `Typed causal edges, source → target — a link on this record says this record <rel> the target. ${KB_LINK_RELS.map(\n (rel) => `${rel}: ${LINK_RELS[rel].purpose}`,\n ).join(\"; \")}.`,\n ),\n /** Concept ids this record replaces. The store settles the backlinks. */\n supersedes: z.array(kbConceptIdSchema).max(32).optional(),\n materiality: z.enum(KB_MATERIALITIES).optional(),\n confidence: z.enum(KB_CONFIDENCES).optional(),\n owner: z.string().min(1).optional(),\n })\n .strict();\n\nexport type ComposeInput = z.infer<typeof composeInputSchema>;\n\nexport type ComposedRecord = {\n type: string;\n slug: string;\n frontmatter: Omit<KbRecordFrontmatter, \"type\">;\n body: string;\n};\n\n/**\n * Builds one record's frontmatter and body from its type's spec.\n *\n * Edges go in the body rather than frontmatter because that is where OKF puts\n * them: consumers read markdown links as directed but untyped relationships,\n * with \"the specific kind conveyed by the surrounding prose, not by the link\n * itself\". Broken links are explicitly legal, which matters here — records are\n * routinely written before the ones they point at exist.\n */\nexport function composeRecord(\n type: KbRecordType,\n input: ComposeInput,\n writtenBy: string,\n writtenAt: string,\n): ComposedRecord {\n // Parsed here rather than trusted from the caller: the CLI validates its own\n // stdin, but a library caller has no such gate, and `relatedConceptIds` is\n // interpolated into a markdown link unescaped a few lines down.\n const parsed = composeInputSchema.parse(input);\n const spec = RECORD_TYPES[type];\n const sections = parsed.sections ?? {};\n\n const unknown = Object.keys(sections).filter(\n (heading) => !spec.sections.includes(heading),\n );\n if (unknown.length) {\n throw new Error(\n `kb: ${type} has no section ${unknown.join(\", \")} — expected one of ${spec.sections.join(\", \")}`,\n );\n }\n\n const frontmatter: Omit<KbRecordFrontmatter, \"type\"> = {\n title: parsed.title,\n description: parsed.why,\n generated: { by: writtenBy, at: writtenAt },\n // Empty rather than absent: a later verification pass appends here, and an\n // empty list says \"not yet verified\" where a missing key would only say\n // \"this producer didn't think about it\".\n verified: [],\n strauss_status: spec.initialStatus,\n };\n if (parsed.stale_after) frontmatter.stale_after = parsed.stale_after;\n // The same check `anchor-set` runs: no two anchors at one address.\n if (parsed.anchors?.length) {\n frontmatter.strauss_anchors = applyAnchorSet([], parsed.anchors).anchors;\n }\n if (parsed.verify?.length) frontmatter.strauss_verify = parsed.verify;\n if (parsed.tags?.length) frontmatter.tags = parsed.tags;\n if (parsed.sources?.length) frontmatter.sources = parsed.sources;\n if (parsed.assumption) frontmatter.strauss_assumption = true;\n if (parsed.materiality) frontmatter.strauss_materiality = parsed.materiality;\n if (parsed.confidence) frontmatter.strauss_confidence = parsed.confidence;\n if (parsed.owner) frontmatter.strauss_owner = parsed.owner;\n if (parsed.supersedes?.length)\n frontmatter.strauss_supersedes = parsed.supersedes;\n // Refused on the write path, where the caller can still fix it: a self-link\n // asserts a record depends on itself, which every walk skips. `kb_validate`\n // keeps it a warning, since by then the choice is between reporting it and\n // refusing to load the file.\n const selfLink = parsed.links?.find(\n (link) => link.target === `${type}.${parsed.slug}`,\n );\n if (selfLink) {\n throw new Error(\n `kb: ${type}.${parsed.slug} cannot ${selfLink.rel} itself — a link must name another record`,\n );\n }\n if (parsed.links?.length) frontmatter.strauss_links = parsed.links;\n\n const blocks: string[] = [];\n for (const heading of spec.sections) {\n const text = sections[heading];\n // Omitted rather than stubbed: an empty \"## Evidence\" reads as evidence\n // that was sought and not found.\n if (text) blocks.push(`## ${heading}\\n\\n${text}`);\n }\n if (!blocks.length) blocks.push(parsed.why);\n\n for (const related of parsed.relatedConceptIds ?? []) {\n blocks.push(`Relates to [${related}](${related}.md).`);\n }\n\n // One sentence per typed link, from a fixed template per rel. A walk reads\n // the edge from frontmatter, but a plain-OKF consumer ignores frontmatter it\n // does not recognise, so the claim is also stated as prose around a markdown\n // link — OKF's own spelling for a typed relationship. Fixed rather than free\n // text so the sentence cannot say something the rel does not.\n for (const link of parsed.links ?? []) {\n blocks.push(\n `${LINK_RELS[link.rel].phrase} [${link.target}](${link.target}.md).`,\n );\n }\n\n if (parsed.sources?.length) {\n blocks.push(\n parsed.sources\n .map((source) => `[^${source.id}]: ${source.title ?? source.resource}`)\n .join(\"\\n\"),\n );\n }\n\n return {\n type,\n slug: parsed.slug,\n frontmatter,\n body: `${blocks.join(\"\\n\\n\")}\\n`,\n };\n}\n","import { z } from \"zod\";\nimport {\n composeInputSchema,\n composeRecord,\n type ComposedRecord,\n} from \"./compose.js\";\nimport type { KbRecord } from \"./kb-record.schema.js\";\n\n/**\n * The record written while a change is being made: why it is shaped the way it\n * is, anchored to the symbols it touches.\n *\n * A decision is the one thing a later pass cannot recover. The diff shows what\n * changed; nothing in it says which alternative was rejected, or which\n * constraint a future reader would otherwise \"simplify\" away. Everything else a\n * review needs — categories, moves, formatting — is derivable from the finished\n * diff and does not belong here.\n */\nexport const DECISION_TYPE = \"decision\";\n\n/**\n * Slug for the explicit \"nothing to record here\" answer.\n *\n * Gating on \"did you write a decision?\" rewards writing a junk decision. Gating\n * on \"did you answer?\" does not, so silence has to be expressible as a claim:\n * one record, one sentence, auditable after the fact. Work that genuinely\n * needed no decision says so; work that says nothing at all is the case worth\n * surfacing.\n */\nexport const NO_DECISION_SLUG = \"none\";\n\n/**\n * Decisions keep a typed input of their own where the generic composer takes a\n * section map. `alternative` is not a nicety here — \"what was rejected\" is the\n * part of a decision that a later reader cannot reconstruct, so it gets a field\n * rather than a heading a writer may forget to fill.\n */\nexport const decisionInputSchema = composeInputSchema\n .omit({ sections: true })\n .extend({\n alternative: z.string().min(1).optional(),\n impact: z.string().min(1).optional(),\n })\n .strict();\n\nexport type DecisionInput = z.infer<typeof decisionInputSchema>;\n\nexport function composeDecisionRecord(\n input: DecisionInput,\n writtenBy: string,\n writtenAt: string,\n): ComposedRecord {\n const { alternative, impact, ...rest } = input;\n return composeRecord(\n DECISION_TYPE,\n {\n ...rest,\n sections: {\n Decision: input.title,\n Rationale: input.why,\n ...(alternative ? { Rejected: alternative } : {}),\n ...(impact ? { Impact: impact } : {}),\n },\n },\n writtenBy,\n writtenAt,\n );\n}\n\n/** The explicit no-decision claim, so an absence and an answer stay distinct. */\nexport function composeNoDecisionRecord(\n reason: string,\n writtenBy: string,\n writtenAt: string,\n): ComposedRecord {\n return composeRecord(\n DECISION_TYPE,\n {\n slug: NO_DECISION_SLUG,\n title: \"No decision to record\",\n why: reason,\n sections: { Decision: reason },\n },\n writtenBy,\n writtenAt,\n );\n}\n\n/** Whether a record is the explicit no-decision claim rather than a decision. */\nexport function isNoDecisionRecord(record: KbRecord): boolean {\n return record.conceptId === `${DECISION_TYPE}.${NO_DECISION_SLUG}`;\n}\n\n/**\n * Decisions in the bundle, excluding the no-decision claim.\n *\n * Callers asking \"what was decided\" must not be handed the record that exists\n * precisely to say nothing was.\n */\nexport function selectDecisions(records: KbRecord[]): KbRecord[] {\n return records.filter(\n (record) =>\n record.conceptId.startsWith(`${DECISION_TYPE}.`) &&\n !isNoDecisionRecord(record),\n );\n}\n","import { BaseError, ErrorTypes, Fault } from \"./errors.js\";\n\n/**\n * Every caller of this store is an agent, reached through a CLI or a stdio MCP\n * server, so a bare `Error` reaches it as an opaque string. The `code` carries\n * the distinction the caller has to act on: 409 means pick a different slug and\n * retry, 400 means the input was never going to work.\n */\nexport class KbRecordAlreadyExistsError extends BaseError {\n constructor(readonly conceptId: string) {\n super({\n message: `kb: ${conceptId} already exists — choose a more specific slug, or write with overwrite`,\n errorType: ErrorTypes.KbRecordAlreadyExists,\n code: 409,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { conceptId, action: \"refused\" },\n });\n }\n}\n\nexport class KbRecordNotFoundError extends BaseError {\n constructor(readonly conceptId: string) {\n super({\n message: `kb: ${conceptId} does not exist`,\n errorType: ErrorTypes.KbRecordNotFound,\n code: 404,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { conceptId },\n });\n }\n}\n\n/** Retriable, unlike the others: re-reading and re-applying usually succeeds. */\nexport class KbWriteConflictError extends BaseError {\n constructor(readonly conceptId: string) {\n super({\n message: `kb: ${conceptId} changed while it was being updated — re-read and retry`,\n errorType: ErrorTypes.KbWriteConflict,\n code: 409,\n fault: Fault.System,\n retriable: true,\n reportToUser: true,\n details: { conceptId },\n });\n }\n}\n\n/** A generator confirming its own record adds no independent check. */\nexport class KbSelfVerificationError extends BaseError {\n constructor(\n readonly conceptId: string,\n readonly actor: string,\n readonly generatedBy: string,\n ) {\n super({\n message: `kb: ${conceptId} was generated by ${generatedBy}, and a record's generator cannot verify it — only a human or a different actor can`,\n errorType: ErrorTypes.KbSelfVerification,\n code: 400,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { conceptId, actor, generatedBy, action: \"refused\" },\n });\n }\n}\n\n/** An actor a write cannot carry: malformed, or `unknown` on a `verify`. */\nexport class KbInvalidActorError extends BaseError {\n constructor(\n readonly actor: string,\n readonly reason: string,\n ) {\n super({\n message: `kb: actor ${JSON.stringify(actor)} ${reason} — set STRAUSS_KB_ACTOR, e.g. human:alice or agent:reviewer`,\n errorType: ErrorTypes.KbInvalidActor,\n code: 400,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { actor, reason, action: \"refused\" },\n });\n }\n}\n\n/** Two flags that ask for opposite things in one run. */\nexport class KbFlagConflictError extends BaseError {\n constructor(readonly flags: string[]) {\n super({\n message: `kb: ${flags.join(\" and \")} cannot be combined`,\n errorType: ErrorTypes.KbFlagConflict,\n code: 400,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { flags },\n });\n }\n}\n\n/**\n * A pack that will not fit its token budget. Refusal, not truncation: a\n * partial pack is indistinguishable from a complete one, so the caller gets\n * the full picture — how many records, how many tokens, and every id the\n * walk's own limits already cut — and decides whether to raise the budget or\n * tighten the walk.\n */\nexport class KbPackBudgetExceededError extends BaseError {\n constructor(\n readonly recordCount: number,\n readonly approxTokens: number,\n readonly budgetTokens: number,\n readonly excluded: string[],\n ) {\n super({\n message: `kb: a pack of ${recordCount} records is ~${approxTokens} tokens against a budget of ${budgetTokens} — lower hops or maxNodes, or raise the budget`,\n errorType: ErrorTypes.KbPackBudgetExceeded,\n code: 400,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { recordCount, approxTokens, budgetTokens, excluded },\n });\n }\n}\n\n/**\n * A `rels` option naming something the walk can never follow.\n *\n * Refused rather than ignored: dropping an unrecognised rel would return an\n * empty impact set — \"nothing breaks\" — indistinguishable from a genuine\n * result. `related_to` is refused here too, since it asserts no dependence and\n * following it can only produce that same empty set.\n */\nexport class KbUnknownLinkRelError extends BaseError {\n constructor(\n readonly rel: string,\n readonly expected: readonly string[],\n ) {\n super({\n message: `kb: ${rel} is not a rel a walk can follow — expected one of ${expected.join(\", \")}`,\n errorType: ErrorTypes.KbUnknownLinkRel,\n code: 400,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { rel, expected: expected.join(\", \") },\n });\n }\n}\n\n/**\n * A flag that takes a value, given none.\n *\n * `strauss-kb load --budget` used to read the next argv entry, find\n * nothing, and quietly fall back to the default — so a caller who meant to\n * raise a ceiling got the ceiling they were trying to move, and a typo looked\n * exactly like success. Refusing is the only way that stays visible.\n */\nexport class KbMissingFlagValueError extends BaseError {\n constructor(readonly flag: string) {\n super({\n message: `kb: ${flag} needs a value — pass ${flag} <value> or ${flag}=<value>`,\n errorType: ErrorTypes.KbMissingFlagValue,\n code: 400,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { flag },\n });\n }\n}\n\n/** `classify` invoked with no diff it could read, or one it could not parse. */\nexport class KbClassifyInputError extends BaseError {\n constructor(readonly reason: string) {\n super({\n message: `classify: ${reason}`,\n errorType: ErrorTypes.KbClassifyInput,\n code: 400,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { reason },\n });\n }\n}\n\n/** The target base already holds one of the records. Refused for the whole run. */\nexport class KbPromoteCollisionError extends BaseError {\n constructor(\n readonly conceptId: string,\n readonly to: string,\n ) {\n super({\n message: `kb: ${to} already holds ${conceptId} — re-run with force to overwrite it`,\n errorType: ErrorTypes.KbPromoteCollision,\n code: 409,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { conceptId, to, action: \"refused\" },\n });\n }\n}\n\n/** Promotion carries a record's standing, so a withdrawn one may not be copied. */\nexport class KbPromoteStandingError extends BaseError {\n constructor(\n readonly conceptId: string,\n readonly standing: string,\n ) {\n super({\n message: `kb: ${conceptId} is ${standing} — only a record that still stands can be promoted`,\n errorType: ErrorTypes.KbPromoteStanding,\n code: 409,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { conceptId, standing, action: \"refused\" },\n });\n }\n}\n\n/** Source and target are the same base: the run would rewrite its own records. */\nexport class KbPromoteSelfError extends BaseError {\n constructor(readonly to: string) {\n super({\n message: `kb: ${to} is the base being promoted from — name a different target`,\n errorType: ErrorTypes.KbPromoteSelf,\n code: 400,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { to, action: \"refused\" },\n });\n }\n}\n\n/** A write failed after earlier ones landed; `landed` is what the target now holds. */\nexport class KbPromoteStoppedError extends BaseError {\n constructor(\n readonly conceptId: string,\n readonly landed: string[],\n readonly reason: string,\n ) {\n super({\n message: `kb: promotion stopped at ${conceptId} (${reason}) — landed: ${\n landed.length ? landed.join(\", \") : \"nothing\"\n }`,\n errorType: ErrorTypes.KbPromoteStopped,\n code: 500,\n fault: Fault.System,\n retriable: false,\n reportToUser: true,\n details: { conceptId, landed, reason, action: \"stopped\" },\n });\n }\n}\n\nexport class KbInvalidConceptIdError extends BaseError {\n constructor(message: string, details: Record<string, string>) {\n super({\n message: `kb: ${message}`,\n errorType: ErrorTypes.KbInvalidConceptId,\n code: 400,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details,\n });\n }\n}\n\n/** `--since` named a baseline that is neither a digest nor a readable stamp. */\nexport class KbStampBaselineError extends BaseError {\n constructor(readonly since: string) {\n super({\n message: `kb: --since ${since} is neither a 64-character digest nor a readable stamp file`,\n errorType: ErrorTypes.KbStampBaselineUnreadable,\n code: 400,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { since },\n });\n }\n}\n\n/** `--since` named a digest while more than one base is being stamped. */\nexport class KbStampDigestBaselineError extends BaseError {\n constructor(readonly since: string) {\n super({\n message: `kb: --since ${since} is a digest, which needs --bundle (one base) — a file baseline works for many`,\n errorType: ErrorTypes.KbStampDigestBaselineAmbiguous,\n code: 400,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { since },\n });\n }\n}\n","import type {\n KbContextBudgets,\n KbMergedPins,\n KbPinsManifest,\n} from \"./model.js\";\n\n/** Sane integers only; anything else is ignored, not an error. */\nfunction asBudgets(value: unknown): KbContextBudgets {\n if (value === null || typeof value !== \"object\") return {};\n const table = value as Record<string, unknown>;\n const pick = (key: string, min: number) => {\n const raw = table[key];\n return typeof raw === \"number\" && Number.isInteger(raw) && raw >= min\n ? raw\n : undefined;\n };\n const budgetTokens = pick(\"budgetTokens\", 1);\n // 0 is meaningful — \"full-under off\", overriding a `default` that set it.\n const fullUnderTokens = pick(\"fullUnderTokens\", 0);\n // An empty array is meaningful too: it lifts a `default`'s exclusions.\n const raw = table[\"excludeTags\"];\n const excludeTags = Array.isArray(raw)\n ? raw.filter((tag): tag is string => typeof tag === \"string\" && tag !== \"\")\n : undefined;\n return {\n ...(budgetTokens ? { budgetTokens } : {}),\n ...(fullUnderTokens !== undefined ? { fullUnderTokens } : {}),\n ...(excludeTags ? { excludeTags } : {}),\n };\n}\n\n/**\n * One manifest's budgets for one profile: the named profile's values over the\n * manifest's `\"default\"` entry. What is absent here falls through to the\n * caller's built-ins — a manifest narrows, it never has to be complete.\n */\nexport function contextProfileBudgets(\n manifest: KbPinsManifest,\n profile?: string,\n): KbContextBudgets {\n const table = manifest.context;\n if (table === null || typeof table !== \"object\") return {};\n const entries = table as Record<string, unknown>;\n return {\n ...asBudgets(entries[\"default\"]),\n ...(profile ? asBudgets(entries[profile]) : {}),\n };\n}\n\n/**\n * Budgets across the layers: user underneath, local over it, project on top —\n * the committed file is the workspace's word — and explicit flags above all\n * of this, applied by the caller.\n */\nexport function mergedContextBudgets(\n merged: KbMergedPins,\n profile?: string,\n): KbContextBudgets {\n const layered = ([\"user\", \"local\", \"project\"] as const).map((layer) => {\n const manifest = merged.manifests[layer];\n return manifest ? contextProfileBudgets(manifest, profile) : {};\n });\n return { ...layered[0], ...layered[1], ...layered[2] };\n}\n","import type { KbPinLayer } from \"./model.js\";\n\nexport class KbPinsMalformedError extends Error {\n constructor(file: string, cause: string) {\n super(`pin manifest ${file} is not readable (${cause}) — fix or remove it`);\n this.name = \"KbPinsMalformedError\";\n }\n}\n\nexport class KbBaseFrozenError extends Error {\n constructor(bundlePath: string, layer: KbPinLayer) {\n super(\n `${bundlePath} is frozen (read-only) by this workspace's ${layer} pin manifest — re-pin with --unfreeze, or unpin, to change it`,\n );\n this.name = \"KbBaseFrozenError\";\n }\n}\n","import { join } from \"node:path\";\nimport { z } from \"zod\";\n\n/**\n * Pin manifests, in three layers.\n *\n * Pins are workspace state, not base state: they record which bases a session\n * should be shown at every context birth. The pinned base is never touched —\n * not even its log — because a base must remain copyable without knowing who\n * pins it.\n *\n * The layers, nearest wins when the same base appears in more than one:\n *\n * | layer | file | for |\n * | ------- | --------------------------------------- | -------------------------- |\n * | project | <workspace>/.strauss/kb-pins.json | committed, the team's pins |\n * | local | <workspace>/.strauss/kb-pins.local.json | personal, gitignored |\n * | user | ~/.strauss/kb-pins.json | personal, every workspace |\n *\n * Every manifest's paths resolve against its own root — the workspace for\n * project and local, the home directory for user — so each file is portable\n * with the tree it belongs to. `STRAUSS_KB_USER_ROOT` overrides the user root\n * (tests, unusual homes).\n */\nexport const PINS_FILE = join(\".strauss\", \"kb-pins.json\");\nexport const PINS_LOCAL_FILE = join(\".strauss\", \"kb-pins.local.json\");\n\nexport const PIN_LAYERS = [\"project\", \"local\", \"user\"] as const;\nexport type KbPinLayer = (typeof PIN_LAYERS)[number];\n\n/**\n * Primary state — it records an intent nothing else holds — but trivially\n * rewritable, so a full rewrite on change is fine and no append log is needed.\n * Unknown keys are preserved on rewrite, the same tolerance the record reader\n * extends to frontmatter it did not write.\n */\nexport const pinSchema = z\n .object({\n /** Relative to the manifest's root, so the file is committable. */\n path: z.string().min(1),\n pinnedAt: z.string().min(1).optional(),\n /**\n * How `context` renders this base. `full` preloads the whole base into\n * the block regardless of the full-under threshold — for a base whose\n * contents should simply be present, the way an ADR base should be —\n * still answering to the block budget, with an index fallback that says\n * so when it cannot fit. `index` never upgrades, whatever the threshold.\n * Absent: the profile's full-under threshold decides. Invalid values\n * degrade to absent rather than failing the manifest.\n */\n mode: z.enum([\"full\", \"index\"]).optional().catch(undefined),\n /**\n * Context profiles this pin surfaces in (e.g. only at session-start,\n * not per turn). Absent: every profile. A run without a profile sees\n * every pin. A base that only matters to one skill is better loaded by\n * that skill at point of use than pinned at all — pins are what every\n * session should see.\n */\n profiles: z.array(z.string()).optional().catch(undefined),\n /**\n * The base is concluded — a finished piece of research, a frozen ADR\n * set. Write commands against it refuse while this workspace holds the\n * pin, and `context` labels it read-only. Workspace policy, not base\n * state: the base itself stays copyable and writable elsewhere.\n */\n frozen: z.boolean().optional().catch(undefined),\n })\n .passthrough();\n\nexport const pinsManifestSchema = z\n .object({\n pins: z.array(pinSchema).default([]),\n /**\n * Per-repo budgets for the `context` command, keyed by profile —\n * `\"session-start\"`, `\"compact\"`, `\"turn\"`, or `\"default\"` for all of\n * them. Deliberately untyped here: a typo'd budget must degrade to the\n * built-in default, not make the whole manifest unreadable and silence\n * the index at every session start. `contextProfileBudgets` does the\n * tolerant read.\n */\n context: z.unknown().optional(),\n })\n .passthrough();\n\nexport type KbPin = z.infer<typeof pinSchema>;\nexport type KbPinsManifest = z.infer<typeof pinsManifestSchema>;\n\n/** One profile's `context` settings, from the manifest or the built-ins. */\nexport type KbContextBudgets = {\n budgetTokens?: number;\n fullUnderTokens?: number;\n /**\n * Frontmatter tags whose records this profile leaves out of the block —\n * `review`, say, kept out of session-start without unpinning the base.\n */\n excludeTags?: string[];\n};\n\n/** A pin as the merged view hands it back: entry + where it came from. */\nexport type KbMergedPin = KbPin & {\n layer: KbPinLayer;\n absolutePath: string;\n};\n\nexport type KbMergedPins = {\n /** Effective pins after dedup — nearest layer wins per resolved path. */\n pins: KbMergedPin[];\n /** Per-layer manifests that parsed, for budget merging. */\n manifests: Partial<Record<KbPinLayer, KbPinsManifest>>;\n};\n\n/** One pinned base, with whether it currently resolves to anything readable. */\nexport type KbPinStatus = {\n /** As stored — relative to its layer's root. */\n path: string;\n layer: KbPinLayer;\n pinnedAt: string | null;\n absolutePath: string;\n /** The directory exists and yielded at least one parseable record. */\n valid: boolean;\n recordCount: number;\n mode: \"full\" | \"index\" | null;\n profiles: string[] | null;\n frozen: boolean;\n};\n\nexport type KbPinResult = {\n path: string;\n layer: KbPinLayer;\n pinnedAt: string;\n alreadyPinned: boolean;\n mode?: \"full\" | \"index\";\n profiles?: string[];\n frozen?: boolean;\n /** Set when the path holds no readable records — pinned anyway. */\n warning?: string;\n};\n\nexport type KbPinOptions = {\n mode?: \"full\" | \"index\";\n profiles?: string[];\n frozen?: boolean;\n /** Which manifest to write. Defaults to the committed project layer. */\n layer?: KbPinLayer;\n};\n","import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { dirname, isAbsolute, join, relative, resolve, sep } from \"node:path\";\nimport { KbPinsMalformedError } from \"./errors.js\";\nimport {\n PIN_LAYERS,\n PINS_FILE,\n PINS_LOCAL_FILE,\n pinsManifestSchema,\n type KbMergedPin,\n type KbMergedPins,\n type KbPinLayer,\n type KbPinsManifest,\n} from \"./model.js\";\n\nfunction userRoot(): string {\n return process.env.STRAUSS_KB_USER_ROOT || homedir();\n}\n\n/** The directory a layer's stored paths resolve against. */\nexport function layerRoot(workspaceDir: string, layer: KbPinLayer): string {\n return layer === \"user\" ? userRoot() : resolve(workspaceDir);\n}\n\nfunction layerFile(workspaceDir: string, layer: KbPinLayer): string {\n return join(\n layerRoot(workspaceDir, layer),\n layer === \"local\" ? PINS_LOCAL_FILE : PINS_FILE,\n );\n}\n\n/**\n * One layer's manifest, or an empty one when the file is missing.\n *\n * A malformed file throws rather than being treated as empty: every write path\n * does a full rewrite, and rewriting over content we could not read would\n * destroy the one copy of it. Read-only consumers that must stay silent\n * (`context` from a session hook, the merged reader) skip malformed layers\n * themselves.\n */\nexport async function readPinsLayer(\n workspaceDir: string,\n layer: KbPinLayer,\n): Promise<KbPinsManifest> {\n const file = layerFile(workspaceDir, layer);\n let raw: string;\n try {\n raw = await readFile(file, \"utf8\");\n } catch {\n return { pins: [] };\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (error) {\n throw new KbPinsMalformedError(\n file,\n error instanceof Error ? error.message : \"invalid JSON\",\n );\n }\n const manifest = pinsManifestSchema.safeParse(parsed);\n if (!manifest.success) {\n throw new KbPinsMalformedError(\n file,\n manifest.error.issues[0]?.message ?? \"invalid shape\",\n );\n }\n return manifest.data;\n}\n\nexport async function writePinsLayer(\n workspaceDir: string,\n layer: KbPinLayer,\n manifest: KbPinsManifest,\n): Promise<void> {\n const file = layerFile(workspaceDir, layer);\n await mkdir(dirname(file), { recursive: true });\n await writeFile(file, `${JSON.stringify(manifest, null, 2)}\\n`, \"utf8\");\n}\n\n/** Where a stored pin points, resolved against its layer's root. */\nexport function resolvePinPath(rootDir: string, path: string): string {\n return isAbsolute(path)\n ? resolve(path)\n : resolve(rootDir, path.split(\"/\").join(sep));\n}\n\n/** How a base is spelled in a manifest: relative to the layer root, forward slashes. */\nexport function storablePath(rootDir: string, bundlePath: string): string {\n const rel = relative(resolve(rootDir), resolve(bundlePath));\n return (rel === \"\" ? \".\" : rel).split(sep).join(\"/\");\n}\n\n/**\n * All three layers, merged. A malformed layer is skipped rather than thrown:\n * this feeds hooks at every session start, and one broken personal file must\n * not silence the team's pins — `pin`/`unpin` against the broken layer still\n * refuse loudly.\n */\nexport async function readMergedPins(\n workspaceDir: string,\n): Promise<KbMergedPins> {\n const manifests: Partial<Record<KbPinLayer, KbPinsManifest>> = {};\n const pins: KbMergedPin[] = [];\n const seen = new Set<string>();\n\n for (const layer of PIN_LAYERS) {\n let manifest: KbPinsManifest;\n try {\n manifest = await readPinsLayer(workspaceDir, layer);\n } catch {\n continue;\n }\n manifests[layer] = manifest;\n const root = layerRoot(workspaceDir, layer);\n for (const entry of manifest.pins) {\n const absolutePath = resolvePinPath(root, entry.path);\n if (seen.has(absolutePath)) continue;\n seen.add(absolutePath);\n pins.push({ ...entry, layer, absolutePath });\n }\n }\n return { pins, manifests };\n}\n","import { resolve } from \"node:path\";\nimport { KbBaseFrozenError } from \"./errors.js\";\nimport { readMergedPins } from \"./layers.js\";\n\n/**\n * Refuses when a write would land in a base this workspace froze. Called by\n * every mutating command; a workspace that pinned a base `--frozen` said the\n * base is concluded, and a quiet write past that would be exactly the silent\n * drift the pin was meant to stop.\n */\nexport async function assertBaseNotFrozen(\n workspaceDir: string,\n bundlePath: string,\n): Promise<void> {\n const merged = await readMergedPins(workspaceDir);\n const absolute = resolve(bundlePath);\n const pin = merged.pins.find((entry) => entry.absolutePath === absolute);\n if (pin?.frozen === true) {\n throw new KbBaseFrozenError(pin.path, pin.layer);\n }\n}\n","import type { KbStore } from \"../kb-store.js\";\nimport { readMergedPins } from \"./layers.js\";\nimport type { KbPinStatus } from \"./model.js\";\n\n/** Every effective pin across the layers, with whether it points at records. */\nexport async function listPins(\n store: KbStore,\n workspaceDir: string,\n): Promise<KbPinStatus[]> {\n const merged = await readMergedPins(workspaceDir);\n return Promise.all(\n merged.pins.map(async (entry) => {\n const records = await store.list(entry.absolutePath);\n return {\n path: entry.path,\n layer: entry.layer,\n pinnedAt: entry.pinnedAt ?? null,\n absolutePath: entry.absolutePath,\n valid: records.length > 0,\n recordCount: records.length,\n mode: entry.mode ?? null,\n profiles: entry.profiles ?? null,\n frozen: entry.frozen === true,\n };\n }),\n );\n}\n","import type { KbStore } from \"../kb-store.js\";\nimport {\n layerRoot,\n readPinsLayer,\n resolvePinPath,\n storablePath,\n writePinsLayer,\n} from \"./layers.js\";\nimport type { KbPin, KbPinOptions, KbPinResult } from \"./model.js\";\n\n/**\n * Adds a base to one layer's manifest. Idempotent — re-pinning a pinned path\n * with no options returns the existing entry untouched, and re-pinning with\n * `mode`, `profiles`, or `frozen` updates just those fields, which is how a\n * pin's rendering or writability is changed. A path that is not (yet) a valid\n * base succeeds with a warning: bases are routinely pinned before they are\n * populated, the same way records link to records that do not exist yet.\n */\nexport async function pinBase(\n store: KbStore,\n workspaceDir: string,\n bundlePath: string,\n at: string,\n options: KbPinOptions = {},\n): Promise<KbPinResult> {\n const layer = options.layer ?? \"project\";\n const root = layerRoot(workspaceDir, layer);\n const manifest = await readPinsLayer(workspaceDir, layer);\n const absolute = resolvePinPath(root, storablePath(root, bundlePath));\n\n const existing = manifest.pins.find(\n (entry) => resolvePinPath(root, entry.path) === absolute,\n );\n const records = await store.list(absolute);\n const warning =\n records.length === 0\n ? `no records found at ${absolute} — pinned anyway; bases are routinely pinned before they are populated`\n : undefined;\n\n const fields = {\n ...(options.mode ? { mode: options.mode } : {}),\n ...(options.profiles?.length ? { profiles: options.profiles } : {}),\n ...(options.frozen !== undefined ? { frozen: options.frozen } : {}),\n };\n\n if (existing) {\n const updated: KbPin = { ...existing, ...fields };\n if (Object.keys(fields).length) {\n await writePinsLayer(workspaceDir, layer, {\n ...manifest,\n pins: manifest.pins.map((entry) =>\n entry === existing ? updated : entry,\n ),\n });\n }\n return {\n path: existing.path,\n layer,\n pinnedAt: existing.pinnedAt ?? at,\n alreadyPinned: true,\n ...(updated.mode ? { mode: updated.mode } : {}),\n ...(updated.profiles ? { profiles: updated.profiles } : {}),\n ...(updated.frozen !== undefined ? { frozen: updated.frozen } : {}),\n ...(warning ? { warning } : {}),\n };\n }\n\n const entry: KbPin = {\n path: storablePath(root, bundlePath),\n pinnedAt: at,\n ...fields,\n };\n await writePinsLayer(workspaceDir, layer, {\n ...manifest,\n pins: [...manifest.pins, entry],\n });\n return {\n path: entry.path,\n layer,\n pinnedAt: at,\n alreadyPinned: false,\n ...fields,\n ...(warning ? { warning } : {}),\n };\n}\n","import { resolve } from \"node:path\";\nimport {\n layerRoot,\n readPinsLayer,\n resolvePinPath,\n storablePath,\n writePinsLayer,\n} from \"./layers.js\";\nimport { PIN_LAYERS, type KbPinLayer, type KbPinsManifest } from \"./model.js\";\n\n/**\n * Removes a base from every layer that holds it — unpinned means gone, not\n * \"gone from one file and still injected from another\". A malformed layer is\n * skipped (it cannot be rewritten safely); the layers actually touched are\n * reported.\n */\nexport async function unpinBase(\n workspaceDir: string,\n bundlePath: string,\n): Promise<{ path: string; removed: boolean; layers: KbPinLayer[] }> {\n const layers: KbPinLayer[] = [];\n for (const layer of PIN_LAYERS) {\n const root = layerRoot(workspaceDir, layer);\n let manifest: KbPinsManifest;\n try {\n manifest = await readPinsLayer(workspaceDir, layer);\n } catch {\n continue;\n }\n const absolute = resolvePinPath(root, storablePath(root, bundlePath));\n const kept = manifest.pins.filter(\n (entry) => resolvePinPath(root, entry.path) !== absolute,\n );\n if (kept.length !== manifest.pins.length) {\n await writePinsLayer(workspaceDir, layer, { ...manifest, pins: kept });\n layers.push(layer);\n }\n }\n return {\n path: storablePath(resolve(workspaceDir), bundlePath),\n removed: layers.length > 0,\n layers,\n };\n}\n","import { z } from \"zod\";\nimport type { AnchorResolveResult } from \"../anchor-resolve/index.js\";\nimport { bundlePath, conceptId } from \"../model.js\";\nimport type { KbAnchorChange } from \"../../anchors/index.js\";\nimport { kbAnchorWriteSchema, type KbAnchor } from \"../../kb-record.schema.js\";\n\n/**\n * The record's anchors, as the caller means them to end up.\n *\n * A whole set rather than a patch: the caller has just read the record, so it\n * holds every anchor including its baseline, and carrying one forward under a\n * new symbol is a field edit rather than an operation to name.\n */\nexport const anchorSetInputSchema = z\n .object({\n reason: z\n .string()\n .refine((text) => text.trim().length > 0, {\n message: \"reason must say what was reviewed\",\n })\n .describe(\n \"What the reviewer read that makes these the right pointers. Recorded in the log.\",\n ),\n anchors: z\n .array(kbAnchorWriteSchema)\n .min(1)\n .describe(\n \"The complete new anchor set. Carry an anchor's hash forward to keep drift visible until the new code is read.\",\n ),\n })\n .strict();\n\nexport type AnchorSetInput = z.infer<typeof anchorSetInputSchema>;\n\nexport const anchorSetCommandInput = z.object({\n bundlePath,\n conceptId,\n input: anchorSetInputSchema,\n resolve: z\n .boolean()\n .optional()\n .describe(\n \"Also resolve and stamp every anchor against the current code, as anchor-resolve --rebaseline does.\",\n ),\n repoRoot: z\n .string()\n .min(1)\n .optional()\n .describe(\n \"Where the anchored source lives, for resolve. Defaults to the working directory.\",\n ),\n offline: z\n .boolean()\n .optional()\n .describe(\"With resolve, read foreign anchors from the repo cache only.\"),\n});\n\nexport type KbAnchorSetResult = {\n conceptId: string;\n reason: string;\n /** Unchanged anchors are not listed; a no-op write reports nothing. */\n changes: KbAnchorChange[];\n anchors: KbAnchor[];\n /**\n * `unchanged` without `resolve`; with it, `stamped` only when every anchor\n * matched or its write was `applied`, else `incomplete`.\n */\n baseline: \"unchanged\" | \"stamped\" | \"incomplete\";\n /** anchor-resolve's per-anchor results, when `resolve` ran. */\n resolved?: AnchorResolveResult[];\n note: string;\n};\n","import { z } from \"zod\";\nimport { KbMissingFlagValueError } from \"../kb-errors.js\";\nimport type { KbStore } from \"../kb-store.js\";\n\n/**\n * Every operation a knowledge base exposes, defined once.\n *\n * The CLI and the MCP server are both projections of this table. Kept apart\n * they drift within a day — fourteen commands against six tools — which is the\n * same failure as a schema restated in prose beside the code that enforces it,\n * one level up. A command added to the table appears in both surfaces or in\n * neither, and a test asserts exactly that.\n *\n * The two differ only in how arguments arrive: MCP passes an object matching\n * `input`, while the CLI has to turn positional argv into the same object.\n * `fromArgv` is that adapter and is the only per-surface code a command needs.\n *\n * One file per command in this folder; `index.ts` assembles the table.\n */\nexport type KbCommandContext = {\n store: KbStore;\n actor: string;\n now: () => string;\n};\n\nexport type KbCommand<Shape extends z.ZodRawShape = z.ZodRawShape> = {\n /** CLI verb. */\n name: string;\n /**\n * MCP tool name. Absent only for CLI-only plumbing (`sync-instructions`),\n * which exists to edit files for hooks and instruction blocks rather than to\n * give an agent a capability — the capability, \"get the pinned context\n * block\", is `kb_context`.\n */\n tool?: string;\n /** Argument spelling for CLI usage output. */\n usage: string;\n /** Shown to an agent choosing a tool, so it carries the judgment too. */\n description: string;\n input: z.ZodObject<Shape>;\n /**\n * Positional argv → the same object MCP receives. `bundleExplicit` says\n * whether `--bundle` was actually passed, for the one command whose meaning\n * turns on it: `stamp` with no bundle stamps every pinned base.\n */\n fromArgv(\n argv: string[],\n bundlePath: string,\n stdin: () => Promise<string>,\n bundleExplicit?: boolean,\n ): Promise<unknown> | unknown;\n run(\n ctx: KbCommandContext,\n input: z.infer<z.ZodObject<Shape>>,\n ): Promise<unknown>;\n /**\n * A human-readable form of the result, for the CLI. Where it exists the CLI\n * prints it and `--json` asks for the machine shape instead; MCP always gets\n * the machine shape, since a tool result is parsed rather than read.\n *\n * Separate from `run` rather than rendered inside it — as `pack` does, whose\n * result *is* a document — because a command whose result is a report needs\n * both forms: the table for a person, and the object for `failsWhen` and for\n * anything downstream.\n */\n render?(result: unknown): string;\n /**\n * Turns a result into a non-zero exit for the CLI. A check that reports a\n * problem has succeeded as a command and failed as a check, and a shell\n * caller can only see the difference through the exit code.\n *\n * The input comes too, so a command can make the exit conditional on a flag\n * the caller passed rather than on the result alone.\n */\n failsWhen?(result: unknown, input: z.infer<z.ZodObject<Shape>>): boolean;\n};\n\nexport const bundlePath = z\n .string()\n .min(1)\n .describe(\"Absolute path to the knowledge base directory.\");\n\nexport const conceptId = z.string().min(1).describe(\"e.g. decision.cursor-v2\");\n\n/**\n * The tag filter every read surface shares. AND, and no vocabulary: `tags` is\n * free text in frontmatter, so matching is exact and an unknown tag is empty.\n */\nexport const TAGS = z\n .array(z.string().min(1))\n .optional()\n .describe(\n \"Keep only records carrying every one of these frontmatter tags. Matched exactly.\",\n );\n\n/**\n * Where the code an anchor points at lives, for the drift check.\n *\n * Pass it whenever the base is not inside the tree it describes: the default is\n * the working directory, where a bundle read from elsewhere finds none of its\n * anchored files. `KbStore.detectDrift` suppresses that case rather than\n * reporting the whole base as drifted.\n */\nexport const REPO_ROOT = z\n .string()\n .min(1)\n .optional()\n .describe(\n \"Where the anchored source lives, for the drift check. Defaults to the working directory.\",\n );\n\nexport function define<Shape extends z.ZodRawShape>(\n command: KbCommand<Shape>,\n): KbCommand<z.ZodRawShape> {\n return command as unknown as KbCommand<z.ZodRawShape>;\n}\n\n/**\n * The value of `--name`, in either spelling, or undefined when it is absent.\n *\n * Both `--name value` and `--name=value` are accepted, because a caller who\n * writes the second and is silently given the default has been told the\n * opposite of what happened.\n *\n * A flag present with no value is an error rather than an absent flag, for the\n * same reason. `strauss-kb load --budget` reading past the end of argv and\n * falling back to the default would hand the caller the exact ceiling they were\n * trying to move, and a trailing typo would be indistinguishable from success.\n * Note\n * that a following token starting with `--` counts as no value: `--budget\n * --all` is a missing value, not a budget of \"--all\".\n */\nexport function argvFlag(argv: string[], name: string): string | undefined {\n const joined = argv.find((arg) => arg.startsWith(`${name}=`));\n if (joined !== undefined) {\n const value = joined.slice(name.length + 1);\n if (!value) throw new KbMissingFlagValueError(name);\n return value;\n }\n\n const at = argv.indexOf(name);\n if (at === -1) return undefined;\n\n const value = argv[at + 1];\n if (value === undefined || value.startsWith(\"--\")) {\n throw new KbMissingFlagValueError(name);\n }\n return value;\n}\n\n/**\n * Every value of a repeatable `--name`, in both spellings, in argv order.\n * Empty when the flag is absent; a flag with no value is an error, as above.\n */\nexport function argvFlags(argv: string[], name: string): string[] {\n const values: string[] = [];\n for (const [at, arg] of argv.entries()) {\n if (arg.startsWith(`${name}=`)) {\n const value = arg.slice(name.length + 1);\n if (!value) throw new KbMissingFlagValueError(name);\n values.push(value);\n } else if (arg === name) {\n const value = argv[at + 1];\n if (value === undefined || value.startsWith(\"--\")) {\n throw new KbMissingFlagValueError(name);\n }\n values.push(value);\n }\n }\n return values;\n}\n\n/**\n * argv with every occurrence of the named flags, and their values, removed —\n * for the verbs whose remaining words are free prose rather than positionals.\n */\nexport function argvWithout(argv: string[], ...names: string[]): string[] {\n const kept: string[] = [];\n for (let at = 0; at < argv.length; at += 1) {\n const arg = argv[at] as string;\n if (names.some((name) => arg.startsWith(`${name}=`))) continue;\n if (names.includes(arg)) {\n at += 1;\n continue;\n }\n kept.push(arg);\n }\n return kept;\n}\n\n/**\n * The first positional after the verb, once the named value-taking flags are\n * out of the way — so `list --tag review decision` still sees the type. Read\n * at a fixed index it would be dropped whenever a flag came first.\n */\nexport function argvPositional(\n argv: string[],\n ...names: string[]\n): string | undefined {\n return argvWithout(argv.slice(1), ...names).find(\n (arg) => !arg.startsWith(\"--\"),\n );\n}\n","import { z } from \"zod\";\nimport { grammarHints } from \"../../grammars/index.js\";\nimport { KbFlagConflictError, KbRecordNotFoundError } from \"../../kb-errors.js\";\nimport { isUncheckedReason } from \"../../remote-repo/index.js\";\nimport { argvFlag, bundlePath, conceptId, define } from \"../model.js\";\nimport { applyPlan, baseFrozen } from \"./apply.js\";\nimport type { AnchorResolveResult } from \"./model.js\";\nimport { planAnchors } from \"./plan.js\";\n\nexport const anchorResolveCommand = define({\n name: \"anchor-resolve\",\n tool: \"kb_anchor_resolve\",\n usage:\n \"anchor-resolve <concept-id> [--repo-root <path>] [--offline] [--rebaseline] [--restamp] [--check]\",\n description:\n \"Resolve a record's anchors: stamp a hash onto anchors that lack one, report drift where the code moved. An anchor naming another repository is read from that remote through a bare cache; --offline uses the cache only. Never writes verified[]; a judgment is kb_verify. Each result says what it compared and whether the write applied.\",\n input: z.object({\n bundlePath,\n conceptId,\n repoRoot: z.string().min(1).optional(),\n offline: z\n .boolean()\n .optional()\n .describe(\n \"Resolve foreign anchors from the local repo cache only, never fetching.\",\n ),\n rebaseline: z\n .boolean()\n .optional()\n .describe(\n \"Accept the current code as the new baseline for anchors that drifted.\",\n ),\n restamp: z\n .boolean()\n .optional()\n .describe(\n \"Refresh `resolved_at` on anchors that already match. Off by default, so a green run writes nothing.\",\n ),\n check: z\n .boolean()\n .optional()\n .describe(\n \"Resolve and report only: no hash, no `resolved_at`, no log entry.\",\n ),\n }),\n fromArgv: (argv, path) => ({\n bundlePath: path,\n conceptId: argv[1],\n repoRoot: argvFlag(argv, \"--repo-root\"),\n offline: argv.includes(\"--offline\"),\n rebaseline: argv.includes(\"--rebaseline\"),\n restamp: argv.includes(\"--restamp\"),\n check: argv.includes(\"--check\"),\n }),\n run: async (\n { store, actor, now },\n {\n bundlePath: path,\n conceptId: id,\n repoRoot,\n offline,\n rebaseline,\n restamp,\n check,\n },\n ) => {\n if (check && (rebaseline || restamp)) {\n throw new KbFlagConflictError([\n \"check\",\n rebaseline ? \"rebaseline\" : \"restamp\",\n ]);\n }\n const root = repoRoot ?? process.cwd();\n const record = await store.read(path, id);\n if (!record) throw new KbRecordNotFoundError(id);\n\n const anchors = record.frontmatter.strauss_anchors ?? [];\n if (!anchors.length) {\n return {\n conceptId: id,\n results: [] as AnchorResolveResult[],\n note: \"record has no anchors\",\n };\n }\n\n // Two passes: what the code says, then what the base took. A report that\n // claimed a baseline while preparing one would call a refused write a\n // completed rebaseline.\n const frozen = check ? false : await baseFrozen(process.cwd(), path);\n const plans = await planAnchors(anchors, {\n root,\n offline: offline === true,\n rebaseline: rebaseline === true,\n restamp: restamp === true,\n check: check === true,\n frozen,\n now,\n });\n const applied = await applyPlan(plans, {\n store,\n actor,\n bundlePath: path,\n conceptId: id,\n frozen,\n });\n const results = applied.results;\n\n // A freeze is only news where it cost something: a base that owed no\n // write is not \"nothing was stamped\".\n const refused = frozen && plans.some((plan) => plan.write);\n // What to do about a grammar this run could not obtain. Written once, in\n // the grammars module, so doctor and this command say the same thing.\n const hints = grammarHints();\n const hintNote = hints.length ? { hints } : {};\n\n // Never `verified[]`: that trail holds judgments, and the hash above is\n // the mechanical evidence. An anchor nothing could reach stays outside the\n // denominator — \"could not look\" is not \"matches\".\n const unreachable = results.filter((entry) =>\n isUncheckedReason(entry.reason),\n ).length;\n const matches = results.filter((entry) => entry.state === \"match\").length;\n // One `note`, so a refused write never costs the caller the count it was\n // reading.\n const note = [\n unreachable\n ? `${matches}/${results.length - unreachable} anchors match, ${unreachable} unreachable`\n : \"\",\n refused ? \"base is frozen: nothing was stamped\" : \"\",\n applied.error ? `nothing was written: ${applied.error}` : \"\",\n ]\n .filter(Boolean)\n .join(\"; \");\n\n return {\n conceptId: id,\n results,\n ...(note ? { note } : {}),\n ...(refused ? { frozen: true } : {}),\n ...hintNote,\n };\n },\n // Drift is a finding until a write settles it: a rebaseline the base took is\n // the answer to the drift it reports, while one refused, skipped, or never\n // asked for leaves the gate exactly what it was meant to catch.\n //\n // A stored hash that no longer resolves is a broken anchor, not an absence:\n // the file was deleted or the symbol renamed. An anchor nobody ever stamped\n // is still just unstamped, and one whose remote nothing could reach was\n // never checked — failing CI on either would gate on work this command did\n // not do.\n failsWhen: (result) =>\n (result as { results: AnchorResolveResult[] }).results.some(\n (entry) =>\n entry.outcome === \"failed\" ||\n entry.outcome === \"skipped\" ||\n (entry.state === \"drifted\" && entry.outcome !== \"applied\") ||\n (entry.state === \"unresolved\" &&\n entry.storedHash !== undefined &&\n !isUncheckedReason(entry.reason)),\n ),\n});\n","import { z } from \"zod\";\nimport { BaseError } from \"../../errors.js\";\nimport { assertBaseNotFrozen, KbBaseFrozenError } from \"../../kb-pins/index.js\";\nimport type { KbStore } from \"../../kb-store.js\";\nimport type {\n AnchorPlan,\n AnchorResolveResult,\n AnchorUpdateReason,\n} from \"./model.js\";\n\nexport type ApplyTarget = {\n store: KbStore;\n actor: string;\n bundlePath: string;\n conceptId: string;\n /** What the freeze check found, before anything was planned. */\n frozen: boolean;\n};\n\nexport type AppliedPlan = {\n results: AnchorResolveResult[];\n /** The store's message when it refused the write. */\n error?: string;\n};\n\n/**\n * Whether the base refuses writes. Asked before the plan is built, so a run\n * plans only what the base would accept — a freeze is policy, like `--check`,\n * not a failure discovered halfway.\n */\nexport async function baseFrozen(\n cwd: string,\n bundlePath: string,\n): Promise<boolean> {\n try {\n await assertBaseNotFrozen(cwd, bundlePath);\n return false;\n } catch (caught) {\n if (!(caught instanceof KbBaseFrozenError)) throw caught;\n return true;\n }\n}\n\n/**\n * Persists the plan's writes, then says per anchor what became of each. One\n * record, one write: every pending anchor is applied together or none is, so\n * an outcome of `applied` is a hash the base now holds.\n */\nexport async function applyPlan(\n plans: readonly AnchorPlan[],\n target: ApplyTarget,\n): Promise<AppliedPlan> {\n if (!plans.some((plan) => plan.write)) {\n return { results: plans.map((plan) => plan.finding) };\n }\n\n // Frozen bases refuse writes, not reads: pure drift reporting is legitimate\n // on a concluded base, so the report is computed either way and the freeze\n // only costs the mutation. Reported rather than thrown — a caller asking a\n // concluded base whether its code moved deserves the answer.\n let failure: AnchorUpdateReason | undefined = target.frozen\n ? \"frozen\"\n : undefined;\n let error: string | undefined;\n if (!failure) {\n try {\n await target.store.updateAnchors(\n target.bundlePath,\n target.conceptId,\n plans.map((plan) => plan.anchor),\n target.actor,\n );\n } catch (caught) {\n // A typed error is the caller's to act on — a write conflict says this\n // whole comparison was computed from a record that has since moved, a\n // refused actor says the call was wrong, a schema error says this\n // command built the anchor badly — so it propagates, and MCP still\n // marks the call an error. What is left is the environment failing,\n // which the report can carry.\n if (caught instanceof BaseError || caught instanceof z.ZodError) {\n throw caught;\n }\n failure = \"write-failed\";\n error = clamp(caught instanceof Error ? caught.message : String(caught));\n }\n }\n\n return {\n results: plans.map((plan) => settle(plan, failure)),\n ...(error ? { error } : {}),\n };\n}\n\n/** The finding plus what the write did, for the anchors a write was due on. */\nfunction settle(\n plan: AnchorPlan,\n failure: AnchorUpdateReason | undefined,\n): AnchorResolveResult {\n if (!plan.write) return plan.finding;\n // A refused write says so whatever it was for. A `resolved_at` refresh that\n // landed moves no baseline, so it stays quiet.\n if (failure) {\n return { ...plan.finding, outcome: \"failed\", outcomeReason: failure };\n }\n if (plan.write === \"refresh\") return plan.finding;\n return plan.write === \"stamp\"\n ? { ...plan.finding, state: \"stamped\", outcome: \"applied\" }\n : { ...plan.finding, outcome: \"applied\", rebaselined: true };\n}\n\n/** A store message goes in a report a person reads; its length is not news. */\nfunction clamp(message: string): string {\n const line = message.split(\"\\n\")[0] ?? \"\";\n return line.length > 200 ? `${line.slice(0, 199)}…` : line;\n}\n","import {\n anchorFileReader,\n atRefKey,\n LazyOrigin,\n normalizeRepoUrl,\n readAnchorFiles,\n readCommitted,\n remoteWants,\n type AnchorRead,\n} from \"../../anchor-resolver/index.js\";\nimport type { KbAnchor } from \"../../kb-record.schema.js\";\nimport { readRemoteAnchors, wantKey } from \"../../remote-repo/index.js\";\nimport type { AnchorSource } from \"./model.js\";\n\n/**\n * What each anchor is read from: the working tree for this repository's own,\n * the committed tree at `ref` for an old-side one, a bare remote cache for\n * every other. Each set is collected first, so git is spawned once per\n * (repo, rev) and never inside the loop.\n */\nexport async function readSources(\n anchors: readonly KbAnchor[],\n root: string,\n offline: boolean,\n): Promise<Map<KbAnchor, AnchorSource>> {\n const origin = new LazyOrigin(root);\n if (anchors.some((anchor) => anchor.repo)) await origin.prime();\n const foreign = new Map(\n anchors.map((anchor) => [anchor, origin.isForeign(anchor)] as const),\n );\n\n const local = anchors.filter(\n (anchor) => !foreign.get(anchor) && anchor.side !== \"old\",\n );\n // The committed side never comes from the working tree: `side: \"old\"` is\n // about code that may not be there any more.\n const committed = anchors.filter(\n (anchor) => !foreign.get(anchor) && anchor.side === \"old\",\n );\n const remote = anchors.filter((anchor) => foreign.get(anchor));\n const reads = await readAnchorFiles(\n local.map((anchor) => anchor.file),\n anchorFileReader(root),\n );\n const atRef = await readCommitted(root, committed);\n const blobs = await readRemoteAnchors(remote.flatMap(remoteWants), {\n offline,\n });\n\n const sources = new Map<KbAnchor, AnchorSource>();\n for (const anchor of local) {\n const read = reads.get(anchor.file) as AnchorRead;\n sources.set(\n anchor,\n read.ok\n ? { ok: true, source: read.source }\n : { ok: false, reason: read.reason },\n );\n }\n for (const anchor of committed) {\n const read = atRef.get(atRefKey(anchor)) as AnchorRead;\n sources.set(\n anchor,\n read.ok\n ? { ok: true, source: read.source }\n : { ok: false, reason: read.reason },\n );\n }\n for (const anchor of remote) {\n const repo = anchor.repo as string;\n const key = normalizeRepoUrl(repo);\n const atDefault = blobs.get(wantKey(key, undefined, anchor.file));\n const primary = anchor.ref\n ? blobs.get(wantKey(key, anchor.ref, anchor.file))\n : atDefault;\n if (!primary?.ok) {\n sources.set(anchor, {\n ok: false,\n reason: primary?.ok === false ? primary.reason : \"remote-unreachable\",\n repo,\n });\n continue;\n }\n sources.set(anchor, {\n ok: true,\n source: primary.source,\n repo,\n ...(anchor.ref && atDefault?.ok ? { head: atDefault.source } : {}),\n });\n }\n return sources;\n}\n","import {\n anchorHashOf,\n defaultAnchorResolvers,\n hashAnchorText,\n prepareResolvers,\n resolveAnchorSpan,\n resolverChanged,\n type AnchorResolver,\n} from \"../../anchor-resolver/index.js\";\nimport type { KbAnchor } from \"../../kb-record.schema.js\";\nimport type { AnchorPlan, AnchorResolveResult, AnchorSource } from \"./model.js\";\nimport { readSources } from \"./sources.js\";\n\nexport type PlanOptions = {\n root: string;\n offline: boolean;\n rebaseline: boolean;\n restamp: boolean;\n check: boolean;\n /** A base that refuses writes: plan only what it would accept. */\n frozen?: boolean;\n now: () => string;\n};\n\n/**\n * The comparison pass: what each anchor's code looks like now, and which write\n * that earns. Nothing here persists, so no finding it produces says a baseline\n * moved — `apply` is what turns a pending write into an outcome.\n */\nexport async function planAnchors(\n anchors: readonly KbAnchor[],\n options: PlanOptions,\n): Promise<AnchorPlan[]> {\n const { root, offline, rebaseline, restamp, check, frozen, now } = options;\n const sources = await readSources(anchors, root, offline);\n const resolvers = defaultAnchorResolvers({ offline });\n await prepareResolvers(\n resolvers,\n anchors.map((anchor) => anchor.file),\n );\n\n const plans: AnchorPlan[] = [];\n for (const anchor of anchors) {\n const base: Pick<\n AnchorResolveResult,\n \"file\" | \"symbol\" | \"side\" | \"storedHash\" | \"repo\"\n > = {\n file: anchor.file,\n ...(anchor.symbol ? { symbol: anchor.symbol } : {}),\n ...(anchor.side === \"old\" ? { side: \"old\" as const } : {}),\n // Carried onto unresolved findings too: an anchor that once hashed\n // and now resolves to nothing is a broken anchor, and the exit code\n // has to be able to tell it from one nobody ever stamped.\n ...(anchor.hash ? { storedHash: anchor.hash } : {}),\n };\n const source = sources.get(anchor) as AnchorSource;\n if (source.repo) base.repo = source.repo;\n\n if (!source.ok) {\n plans.push({\n finding: { ...base, state: \"unresolved\", reason: source.reason },\n anchor,\n });\n continue;\n }\n\n const outcome = resolveAnchorSpan(source.source, anchor, resolvers);\n if (!outcome.ok) {\n plans.push({\n finding: { ...base, state: \"unresolved\", reason: outcome.reason },\n anchor,\n });\n continue;\n }\n\n const resolved = outcome.span;\n const producedBy = outcome.resolver;\n const { hash: currentHash, kind } = anchorHashOf(anchor, outcome);\n const currentLines = resolved.endLine - resolved.startLine + 1;\n // A fresh or rebaselined stamp takes the strongest hash the resolver can\n // offer: `hash_kind: \"ast\"` is over the parsed token stream, so\n // reformatting the anchored code stops registering as drift. An anchor\n // already carrying a raw hash keeps comparing raw until it is\n // rebaselined — see `anchorHashOf`.\n const stampedKind = outcome.normalized ? \"ast\" : \"raw\";\n const stampedHash = outcome.normalized\n ? anchorHashOf({ ...anchor, hash: undefined }, outcome).hash\n : currentHash;\n // `resolver` records which resolver the stored hash came from, so a\n // later run can tell a precise span from a heuristic one.\n const stamped: KbAnchor = {\n ...anchor,\n hash: stampedHash,\n hash_kind: stampedKind,\n lines: currentLines,\n resolved_at: now(),\n ...(producedBy ? { resolver: producedBy } : {}),\n };\n const pinned = anchor.ref !== undefined && source.repo !== undefined;\n\n if (!anchor.hash) {\n // The write path for hashes: kb_write callers record symbols, not\n // digests, and this pass fills them in once the code settles. The\n // finding says `unstamped` until the record is written.\n plans.push({\n finding: {\n ...base,\n state: \"unstamped\",\n currentHash: stampedHash,\n hashKind: stampedKind,\n ...(producedBy ? { resolver: producedBy } : {}),\n },\n anchor: check ? anchor : stamped,\n ...(check ? {} : { write: \"stamp\" as const }),\n });\n continue;\n }\n\n if (anchor.hash !== currentHash) {\n plans.push({\n finding: {\n ...base,\n state: \"drifted\",\n currentHash,\n hashKind: kind,\n diffSize: lineDelta(anchor, currentLines),\n ...(producedBy ? { resolver: producedBy } : {}),\n // A regex-stamped anchor re-read by tree-sitter drifts because the\n // resolver changed, not because the code did.\n ...(resolverChanged(source.source, anchor, producedBy)\n ? { reason: \"resolver-changed\" as const }\n : {}),\n ...(pinned ? { remoteState: \"drifted-from-ref\" as const } : {}),\n },\n anchor: rebaseline && !check ? stamped : anchor,\n ...(rebaseline && !check ? { write: \"rebaseline\" as const } : {}),\n });\n continue;\n }\n\n // The evidence still holds at the pinned commit and the default branch\n // has moved past it. Never rebaselined: the repair is to move `ref`,\n // which is the author's field, not this command's.\n const onDefault = pinned ? headHash(source, anchor, resolvers) : undefined;\n if (onDefault && onDefault.hash !== anchor.hash) {\n plans.push({\n finding: {\n ...base,\n state: \"drifted\",\n currentHash: onDefault.hash,\n diffSize: lineDelta(anchor, onDefault.lines),\n remoteState: \"drifted-on-default\",\n ...(rebaseline\n ? {\n outcome: \"skipped\" as const,\n outcomeReason: \"pinned-ref\" as const,\n }\n : {}),\n },\n anchor,\n });\n continue;\n }\n\n // Nothing changed, so nothing is written: a re-dated record on every\n // green CI run would be a mutation, a log line, and a git diff saying\n // only that a check ran. `resolved_at` is filled in when it is absent\n // (the anchor predates hashing), or on request. Only `--restamp` asks,\n // so a frozen base keeps the backfill rather than failing forever on a\n // date nobody wanted.\n const backfill = anchor.resolved_at === undefined && !frozen;\n const refresh = !check && (restamp || backfill);\n plans.push({\n finding: {\n ...base,\n state: \"match\",\n currentHash,\n hashKind: kind,\n ...(producedBy ? { resolver: producedBy } : {}),\n ...(pinned ? { remoteState: \"matches-ref\" as const } : {}),\n },\n anchor: refresh ? { ...anchor, resolved_at: now() } : anchor,\n ...(refresh ? { write: \"refresh\" as const } : {}),\n });\n }\n return plans;\n}\n\nfunction lineDelta(anchor: KbAnchor, current: number): number | null {\n return anchor.lines === undefined ? null : Math.abs(current - anchor.lines);\n}\n\n/** The anchor's hash on the remote's default branch, when one was read. */\nfunction headHash(\n source: { head?: string },\n anchor: KbAnchor,\n resolvers: readonly AnchorResolver[],\n): { hash: string; lines: number } | undefined {\n if (source.head === undefined) return undefined;\n const outcome = resolveAnchorSpan(source.head, anchor, resolvers);\n if (!outcome.ok) return undefined;\n return {\n hash: hashAnchorText(outcome.span.text),\n lines: outcome.span.endLine - outcome.span.startLine + 1,\n };\n}\n","import { assertBaseNotFrozen } from \"../../kb-pins/index.js\";\nimport { isUncheckedReason } from \"../../remote-repo/index.js\";\nimport {\n anchorResolveCommand,\n type AnchorResolveResult,\n} from \"../anchor-resolve/index.js\";\nimport { argvFlag, define } from \"../model.js\";\nimport {\n applyAnchorSet,\n type KbAnchorSetOutcome,\n} from \"../../anchors/index.js\";\nimport { anchorSetCommandInput, type KbAnchorSetResult } from \"./model.js\";\n\n/** Said in the result, because the caller's next step depends on knowing it. */\nconst NOTE =\n \"pointers only: nothing was resolved or verified. Run anchor-resolve to check the new pointers, --rebaseline to accept the code, or pass resolve to do both here.\";\nconst STAMPED_NOTE =\n \"pointers set and stamped against the current code. Not verification: run verify separately if someone reviewed it.\";\nconst INCOMPLETE_NOTE =\n \"pointers set, but not every anchor was stamped: see each resolved entry's state and outcome.\";\n\nexport const anchorSetCommand = define({\n name: \"anchor-set\",\n tool: \"kb_anchor_set\",\n usage:\n \"anchor-set <concept-id> [--resolve] [--repo-root <path>] [--offline] < anchors.json\",\n description:\n \"Set a record's code anchors after a reviewed refactor, with a reason. The array is the whole set. With resolve, every anchor is stamped against the current code in the same call; without it, run kb_anchor_resolve next. Recorded in the log, never verification.\",\n input: anchorSetCommandInput,\n fromArgv: async (argv, path, stdin) => ({\n bundlePath: path,\n conceptId: argv[1],\n input: JSON.parse(await stdin()) as unknown,\n resolve: argv.includes(\"--resolve\"),\n repoRoot: argvFlag(argv, \"--repo-root\"),\n offline: argv.includes(\"--offline\"),\n }),\n run: async (\n ctx,\n { bundlePath: path, conceptId: id, input, resolve, repoRoot, offline },\n ): Promise<KbAnchorSetResult> => {\n const { store, actor } = ctx;\n await assertBaseNotFrozen(process.cwd(), path);\n\n // Inside the mutation, so the logged changes are against the record as it\n // stands, not as the caller last read it.\n let applied: KbAnchorSetOutcome | undefined;\n const record = await store.updateAnchors(\n path,\n id,\n (current) => {\n applied = applyAnchorSet(current, input.anchors);\n return {\n anchors: applied.anchors,\n log: {\n operation: \"anchor-set\",\n reason: input.reason,\n anchors: applied.changes,\n },\n };\n },\n actor,\n );\n\n const changes = applied?.changes ?? [];\n if (!resolve) {\n return {\n conceptId: id,\n reason: input.reason,\n changes,\n anchors: record.frontmatter.strauss_anchors ?? [],\n baseline: \"unchanged\",\n note: NOTE,\n };\n }\n\n // Choosing the pointer is the reading, so the current code is the\n // baseline. Reuses anchor-resolve rather than restating it.\n const resolved = (await anchorResolveCommand.run(\n ctx,\n anchorResolveCommand.input.parse({\n bundlePath: path,\n conceptId: id,\n rebaseline: true,\n ...(repoRoot ? { repoRoot } : {}),\n ...(offline ? { offline } : {}),\n }),\n )) as { results: AnchorResolveResult[] };\n const after = await store.read(path, id);\n // Stamped is what the base holds, not what was asked: a refused or\n // skipped write, or an anchor nothing resolved, leaves the set incomplete.\n const stamped = resolved.results.every(\n (entry) => entry.state === \"match\" || entry.outcome === \"applied\",\n );\n return {\n conceptId: id,\n reason: input.reason,\n changes,\n anchors: after?.frontmatter.strauss_anchors ?? [],\n baseline: stamped ? \"stamped\" : \"incomplete\",\n resolved: resolved.results,\n note: stamped ? STAMPED_NOTE : INCOMPLETE_NOTE,\n };\n },\n // With `resolve`, a pointer that names nothing is a failed set, not a\n // finding to read later, and a stamp that did not land fails as it does in\n // anchor-resolve. A remote nothing could reach was never checked, so it does\n // not fail — the same line anchor-resolve draws.\n failsWhen: (result, input) => {\n const resolved = (result as KbAnchorSetResult).resolved ?? [];\n return (\n resolved.some(\n (entry) =>\n entry.state === \"unresolved\" && !isUncheckedReason(entry.reason),\n ) ||\n anchorResolveCommand.failsWhen?.({ results: resolved }, input) === true\n );\n },\n});\n","import type {\n KbAnchorDriftEntry,\n KbDriftClass,\n} from \"./anchor-resolver/index.js\";\nimport { isUncheckedReason } from \"./remote-repo/index.js\";\nimport type { KbRecord, KbRecordStatus } from \"./kb-record.schema.js\";\n\n/**\n * Why a matched record must not be read as a plain answer.\n *\n * Relevance and standing are different questions, and ranking answers only the\n * first. A superseded record is usually the older, longer, more general one and\n * its replacement is usually a narrowing, so any similarity measure favours the\n * record that is no longer true. Every hit therefore carries its standing, and\n * the caller is never handed a bare match.\n */\nexport type KbWarning =\n /** Explicitly not adopted. The most dangerous status to return unmarked: a\n * well-formed assertion of what someone decided *not* to do. */\n | { kind: \"rejected\" }\n | { kind: \"superseded\"; by: string[] }\n /** Not settled. Acting on a proposal as though it were a decision is a defect. */\n | { kind: \"unsettled\"; status: KbRecordStatus }\n /** Says a matter is unresolved. Valuable as a result, never as an answer. */\n | { kind: \"unresolved-question\" }\n /** `strauss_superseded_by` names a record that is not in the bundle. */\n | { kind: \"broken-chain\"; missing: string }\n | { kind: \"chain-cycle\"; through: string[] }\n /** Two records claim to replace this one; picking either would be a guess. */\n | { kind: \"forked-chain\"; heads: string[] }\n | { kind: \"stale\"; staleAfter: string }\n | { kind: \"unverified\" }\n /** The code this record anchors to has changed since its hash was recorded —\n * the record may describe code that no longer exists in that form. */\n | { kind: \"drifted\"; anchors: KbWarningAnchor[] }\n /** A foreign anchor nothing could check: the remote was unreachable, refused,\n * or the run was offline. Neither drift nor a clean match. */\n | { kind: \"unchecked\"; anchors: KbWarningAnchor[] };\n\nexport type KbWarningAnchor = {\n file: string;\n symbol?: string;\n /** `null` when the anchor recorded no line count — size unknown. */\n diffSize: number | null;\n reason?: string;\n /** Set only for an anchor resolved against another repository. */\n repo?: string;\n remoteState?: string;\n /**\n * `gone` or `changed` — what a hash comparison alone can settle. `moved` and\n * `cosmetic` cost a repository search and a git read, so they are\n * `kb_reassess`'s answer, not a read path's.\n */\n class?: KbDriftClass;\n};\n\nexport type KbStanding =\n \"current\" | \"superseded\" | \"rejected\" | \"unsettled\" | \"open\";\n\nexport type KbAdjudicated = {\n record: KbRecord;\n standing: KbStanding;\n /** Where the supersession chain ends. Empty when it is broken or cyclic. */\n heads: KbRecord[];\n warnings: KbWarning[];\n};\n\nconst STANDING: Record<KbRecordStatus, KbStanding> = {\n accepted: \"current\",\n resolved: \"current\",\n draft: \"unsettled\",\n proposed: \"unsettled\",\n open: \"open\",\n rejected: \"rejected\",\n superseded: \"superseded\",\n};\n\n/**\n * Attaches standing to records a search returned.\n *\n * Adjudicating rather than filtering, deliberately. A filtered result set is\n * invisible: the caller cannot tell it missed anything, so a dropped record is\n * worse than a flagged one — it turns a knowable gap into an unknowable one.\n */\nexport function adjudicate(\n hits: KbRecord[],\n bundle: KbRecord[],\n now = new Date(),\n // Precomputed by the caller: this function stays pure and sync, and the fs\n // work of re-resolving anchors lives in detectAnchorDrift.\n anchorDrift?: Map<string, KbAnchorDriftEntry[]>,\n): KbAdjudicated[] {\n const byId = new Map(bundle.map((record) => [record.conceptId, record]));\n return hits.map((record) => {\n const status = record.frontmatter.strauss_status;\n const warnings: KbWarning[] = [];\n let heads: KbRecord[] = [];\n\n if (status === \"superseded\") {\n const resolved = resolveHeads(record, byId);\n heads = resolved.heads;\n warnings.push(...resolved.warnings);\n if (heads.length) {\n warnings.push({\n kind: \"superseded\",\n by: heads.map((head) => head.conceptId),\n });\n }\n } else if (status === \"rejected\") {\n warnings.push({ kind: \"rejected\" });\n } else if (status === \"draft\" || status === \"proposed\") {\n warnings.push({ kind: \"unsettled\", status });\n } else if (status === \"open\") {\n warnings.push({ kind: \"unresolved-question\" });\n }\n\n const staleAfter = record.frontmatter.stale_after;\n if (staleAfter && Date.parse(staleAfter) < now.getTime()) {\n warnings.push({ kind: \"stale\", staleAfter });\n }\n if (!record.frontmatter.verified?.length) {\n warnings.push({ kind: \"unverified\" });\n }\n\n // Split at the one point every read path and `doctor` share, so none of\n // them can report \"no drift\" for an anchor nobody could reach.\n const found = (anchorDrift?.get(record.conceptId) ?? []).filter(\n (entry) => entry.state !== \"match\",\n );\n const unchecked = found.filter((entry) => isUncheckedReason(entry.reason));\n const moved = found.filter((entry) => !isUncheckedReason(entry.reason));\n if (moved.length) {\n warnings.push({ kind: \"drifted\", anchors: moved.map(warningAnchor) });\n }\n if (unchecked.length) {\n warnings.push({\n kind: \"unchecked\",\n anchors: unchecked.map(warningAnchor),\n });\n }\n\n return { record, standing: STANDING[status], heads, warnings };\n });\n}\n\nfunction warningAnchor(entry: KbAnchorDriftEntry): KbWarningAnchor {\n const { file, symbol, diffSize, reason, repo, remoteState } = entry;\n return {\n file,\n ...(symbol !== undefined ? { symbol } : {}),\n diffSize,\n ...(reason !== undefined ? { reason } : {}),\n ...(repo !== undefined ? { repo } : {}),\n ...(remoteState !== undefined ? { remoteState } : {}),\n ...(entry.class !== undefined ? { class: entry.class } : {}),\n };\n}\n\n/**\n * Walks a supersession chain to whatever currently stands in its place.\n *\n * Both directions are followed, not just `strauss_superseded_by`. `supersede()`\n * writes the pair, but a hand-edit can leave one side behind, and a walk that\n * trusts only the forward pointer would silently return a record that something\n * in the bundle openly claims to replace.\n *\n * Resolution happens here rather than being denormalised onto records at write\n * time: a stored head would have to be rewritten on every ancestor whenever a\n * chain grows, which is derived state that goes stale — the failure this design\n * keeps avoiding elsewhere.\n */\nexport function resolveHeads(\n from: KbRecord,\n byId: Map<string, KbRecord>,\n): { heads: KbRecord[]; warnings: KbWarning[] } {\n const warnings: KbWarning[] = [];\n const heads = new Map<string, KbRecord>();\n const seen = new Set<string>([from.conceptId]);\n const queue: KbRecord[] = [from];\n\n while (queue.length) {\n const current = queue.shift() as KbRecord;\n const next = successors(current, byId);\n\n for (const missing of next.missing) {\n warnings.push({ kind: \"broken-chain\", missing });\n }\n if (!next.records.length) {\n if (current.conceptId !== from.conceptId)\n heads.set(current.conceptId, current);\n continue;\n }\n for (const record of next.records) {\n if (seen.has(record.conceptId)) {\n warnings.push({ kind: \"chain-cycle\", through: [...seen] });\n continue;\n }\n seen.add(record.conceptId);\n queue.push(record);\n }\n }\n\n if (heads.size > 1) {\n warnings.push({ kind: \"forked-chain\", heads: [...heads.keys()] });\n }\n return { heads: [...heads.values()], warnings };\n}\n\nfunction successors(\n record: KbRecord,\n byId: Map<string, KbRecord>,\n): { records: KbRecord[]; missing: string[] } {\n const ids = new Set<string>();\n const forward = record.frontmatter.strauss_superseded_by;\n if (forward) ids.add(forward);\n for (const [id, candidate] of byId) {\n if (candidate.frontmatter.strauss_supersedes?.includes(record.conceptId)) {\n ids.add(id);\n }\n }\n\n const records: KbRecord[] = [];\n const missing: string[] = [];\n for (const id of ids) {\n const found = byId.get(id);\n if (found) records.push(found);\n else missing.push(id);\n }\n return { records, missing };\n}\n","import type { KbRecord } from \"./kb-record.schema.js\";\n\n/**\n * Selection by frontmatter `tags`. Matching is exact and no vocabulary is\n * enforced — a tag is whatever a writer put there.\n */\nexport type KbTagFilter = {\n /** AND: a record matches only when it carries every one of these. */\n tags?: string[];\n /** A record carrying any one of these is dropped, even if `tags` matched. */\n excludeTags?: string[];\n};\n\n/**\n * Whether one record survives the filter. An empty filter keeps everything,\n * so every caller can pass one unconditionally.\n */\nexport function matchesTags(record: KbRecord, filter: KbTagFilter): boolean {\n if (!filter.tags?.length && !filter.excludeTags?.length) return true;\n const carried = new Set(record.frontmatter.tags ?? []);\n return (\n (filter.tags ?? []).every((tag) => carried.has(tag)) &&\n !(filter.excludeTags ?? []).some((tag) => carried.has(tag))\n );\n}\n","import { adjudicate, type KbStanding } from \"./adjudicate.js\";\nimport type { KbRecord } from \"./kb-record.schema.js\";\nimport { matchesTags, type KbTagFilter } from \"./kb-tags.js\";\n\n/** One record as the catalog names it — no body, no description, one line. */\nexport type KbCatalogEntry = {\n conceptId: string;\n type: string;\n title: string | null;\n standing: KbStanding;\n /** Where the supersession chain ends. Empty when broken, cyclic, or n/a. */\n supersededBy: string[];\n /** `stale_after` is in the past. The one freshness signal a line can carry. */\n stale: boolean;\n};\n\nexport type KbCatalogResult = {\n entries: KbCatalogEntry[];\n /** Every record the catalog names, filter applied. */\n recordCount: number;\n /**\n * How many records hold each standing. Sums to `recordCount` — every record\n * has exactly one standing, so the reader can see that nothing went missing.\n */\n standings: Record<KbStanding, number>;\n /** Shorthand for `standings.current` — records that simply hold. */\n currentCount: number;\n /** Shorthand for `standings.superseded`. */\n supersededCount: number;\n /**\n * Records whose `stale_after` has passed. A flag over the standings rather\n * than one of them — a current record can be stale — so this deliberately\n * does not participate in the sum.\n */\n staleCount: number;\n};\n\nconst EMPTY_STANDINGS: Record<KbStanding, number> = {\n current: 0,\n superseded: 0,\n rejected: 0,\n unsettled: 0,\n open: 0,\n};\n\n/**\n * The tier-one listing: every record named, nothing spelled out.\n *\n * `load` hands over bodies and `pack` hands over a neighbourhood; both have to\n * decide what the reader can afford. The catalog is the rung below either — one\n * line per record at roughly thirty tokens, so a base far past `load`'s gate\n * still fits in a single call. What it buys is the ability to choose: a reader\n * that can see every id, type, title and standing knows which record to `pack`\n * and knows when no record covers the question at all, which is the conclusion\n * a truncated read can never support.\n *\n * Standing travels on the line for the same reason it travels with every other\n * result here: a title is a claim, and a superseded claim reads exactly like a\n * live one. A superseded entry names its replacement, so the line the reader\n * should follow instead is already in front of them.\n *\n * Unbounded, alone among the read paths. `load` and `pack` refuse past a\n * ceiling because a partial body set reads as a complete one; a catalog has no\n * such failure — it is the rung a caller lands on *because* something else\n * refused, and a second refusal there would leave nowhere to go. The cost is\n * linear and cheap: roughly thirty tokens a record, so a thousand-record base\n * is about 30k and five thousand about 150k. Past that the `type` filter\n * narrows it, and no ceiling is needed to make that available.\n *\n * Deterministic given a fixed `now`: no timestamp is emitted, and the ordering\n * is total down to the concept id, so two catalogs of an unchanged base within\n * one `stale_after` window are byte-identical and diff to nothing. The default\n * clock is the wall clock, so a line can still flip to stale as a date passes —\n * pass `now` when byte-equality has to hold across that boundary.\n */\nexport function catalog(\n bundle: KbRecord[],\n options: { type?: string; now?: Date } & KbTagFilter = {},\n): KbCatalogResult {\n const wanted = options.type\n ? bundle.filter((record) => record.frontmatter.type === options.type)\n : bundle;\n\n // Adjudicated against the whole base, not the filtered slice: a record's\n // replacement may be of another type, and a filter must not turn a\n // superseded record into a current-looking one.\n const entries = adjudicate(wanted, bundle, options.now ?? new Date())\n // Tags cut after adjudication, for the same reason: a tag narrows what the\n // catalog names, never the standing it names it with.\n .filter((hit) => matchesTags(hit.record, options))\n .map((hit) => ({\n conceptId: hit.record.conceptId,\n type: hit.record.frontmatter.type,\n title: hit.record.frontmatter.title ?? null,\n standing: hit.standing,\n supersededBy: hit.heads.map((head) => head.conceptId),\n stale: hit.warnings.some((warning) => warning.kind === \"stale\"),\n }))\n .sort(byTypeThenTitle);\n\n const standings = { ...EMPTY_STANDINGS };\n for (const entry of entries) standings[entry.standing] += 1;\n\n return {\n entries,\n recordCount: entries.length,\n standings,\n currentCount: standings.current,\n supersededCount: standings.superseded,\n staleCount: entries.filter((entry) => entry.stale).length,\n };\n}\n\n/** Concept id is the tiebreak, so the order is total and therefore stable. */\nfunction byTypeThenTitle(left: KbCatalogEntry, right: KbCatalogEntry): number {\n return (\n byCodeUnit(left.type, right.type) ||\n byCodeUnit(left.title ?? \"\", right.title ?? \"\") ||\n byCodeUnit(left.conceptId, right.conceptId)\n );\n}\n\n/**\n * Code-unit order, not `localeCompare`.\n *\n * `localeCompare` without an explicit locale reads the host's, so the same\n * base sorts differently on two machines — and this output's whole contract is\n * that two catalogs of an unchanged base diff to nothing. A collation nobody\n * configured is not worth a determinism claim that quietly does not hold.\n */\nfunction byCodeUnit(left: string, right: string): number {\n return left < right ? -1 : left > right ? 1 : 0;\n}\n\n/**\n * One entry, as one line.\n *\n * ` · `-separated rather than a table: a table pays for column alignment on\n * every row, and nothing downstream parses these.\n */\nexport function renderCatalogLine(entry: KbCatalogEntry): string {\n const parts = [\n entry.conceptId,\n entry.type,\n entry.title ?? \"(untitled)\",\n entry.standing === \"superseded\"\n ? `superseded → ${entry.supersededBy.join(\", \") || \"(no surviving head)\"}`\n : entry.standing,\n ];\n if (entry.stale) parts.push(\"stale\");\n return `- ${parts.join(\" · \")}`;\n}\n","import { adjudicate, type KbAdjudicated } from \"./adjudicate.js\";\nimport type { KbAnchor, KbRecord } from \"./kb-record.schema.js\";\n\n/**\n * Which records apply to which part of a change.\n *\n * Takes a structural description of a diff rather than a patch, so this package\n * carries no diff parser: callers already have one, and a knowledge base has no\n * business preferring a particular flavour of unified diff.\n *\n * Deterministic on purpose. Every step here is mechanical — the one judgment,\n * whether a matched record is worth showing a reviewer, is deliberately absent.\n * A model placed here would sit between the reviewer and their diff on every\n * review, to answer a question nobody has yet shown needs asking.\n *\n * Distinct from `load()`, which hands a reader the whole base. That answers\n * \"does anything address this question\"; this answers \"what is attached to this\n * code\", and an anchor is the author's own statement rather than an inference\n * from one. A reader guessing which record relates to a hunk would be guessing\n * at something already written down — and a diff has dozens of hunks, which is\n * dozens of reader calls against microseconds of matching. Where they compose:\n * this narrows a hunk to a few records, and a reader asked to explain them gets\n * those, not the base.\n */\nexport type DiffHunk = {\n /** 1-based, inclusive, in the numbering of this hunk's `side`. */\n startLine: number;\n endLine: number;\n /**\n * Which half of the change these lines number; absent means `new`. An\n * old-side anchor lands here on the caller's word that its `ref` is this\n * diff's base rev — nothing compares the two.\n */\n side?: \"old\" | \"new\";\n /**\n * This hunk's own changed lines, markers stripped, where a parser kept them.\n * Nothing here reads them; a caller classifying content does.\n */\n lines?: string[];\n};\n\nexport type DiffFile = {\n /** Repo-relative, matching how anchors are written. */\n filePath: string;\n hunks: DiffHunk[];\n /** Where `git diff -M` says this path came from, and how alike the two are. */\n renamedFrom?: string;\n similarity?: number;\n};\n\n/**\n * A symbol resolved to lines. Supplied by whatever the caller uses to index\n * symbols; absence is tolerated — see `place()`.\n */\nexport type SymbolRange = {\n file: string;\n symbol: string;\n startLine: number;\n endLine: number;\n /** Which side these lines number; absent means `new`, as on a hunk. */\n side?: \"old\" | \"new\";\n};\n\nexport type DiffMatch = {\n filePath: string;\n hunk: DiffHunk;\n /** Current records first — what still holds should be read before what does not. */\n records: KbAdjudicated[];\n /**\n * `symbol` when every record here was placed by a resolved symbol range,\n * `file` when at least one fell back to the whole file. Reported rather than\n * hidden: a caller showing a file-level match as though it were pinned to\n * these lines is claiming a precision it does not have.\n */\n precision: \"symbol\" | \"file\";\n};\n\nexport type MatchOptions = {\n /** Without these, symbol anchors degrade to file level rather than vanishing. */\n symbolRanges?: SymbolRange[];\n now?: Date;\n};\n\nexport function matchToDiff(\n files: DiffFile[],\n records: KbRecord[],\n options: MatchOptions = {},\n): DiffMatch[] {\n const ranges = symbolRangeIndex(options.symbolRanges ?? []);\n const anchored = records.filter(\n (record) => (record.frontmatter.strauss_anchors ?? []).length > 0,\n );\n const matches: DiffMatch[] = [];\n\n for (const file of files) {\n const candidates = anchored\n .map((record) => ({\n record,\n anchors: (record.frontmatter.strauss_anchors ?? []).filter(\n (anchor) => normalize(anchor.file) === normalize(file.filePath),\n ),\n }))\n .filter(({ anchors }) => anchors.length > 0);\n if (!candidates.length) continue;\n\n for (const hunk of file.hunks) {\n const hits: KbRecord[] = [];\n let precision: DiffMatch[\"precision\"] = \"symbol\";\n\n for (const { record, anchors } of candidates) {\n const placement = place(anchors, file.filePath, hunk, ranges);\n if (placement.kind === \"miss\") continue;\n if (placement.kind === \"file\") precision = \"file\";\n hits.push(record);\n }\n\n if (!hits.length) continue;\n matches.push({\n filePath: file.filePath,\n hunk,\n records: order(adjudicate(hits, records, options.now)),\n precision,\n });\n }\n }\n\n return matches;\n}\n\n/**\n * How one record landed on one hunk, and through which anchor.\n *\n * `matchToDiff` reports the precision of a whole hunk, so a caller naming the\n * record that matched has no way back to the anchor that did it.\n */\nexport type HunkPlacement = {\n kind: \"symbol\" | \"file\" | \"miss\";\n anchor?: KbAnchor;\n};\n\nexport function placeOnHunk(\n record: KbRecord,\n filePath: string,\n hunk: DiffHunk,\n symbolRanges: readonly SymbolRange[] | SymbolRangeIndex = [],\n): HunkPlacement {\n const anchors = (record.frontmatter.strauss_anchors ?? []).filter(\n (anchor) => normalize(anchor.file) === normalize(filePath),\n );\n return place(anchors, filePath, hunk, asIndex(symbolRanges));\n}\n\n/** Ranges arrive as a list, or as the index a caller built once for a diff. */\nfunction asIndex(\n ranges: readonly SymbolRange[] | SymbolRangeIndex,\n): SymbolRangeIndex {\n return isIndex(ranges) ? ranges : symbolRangeIndex(ranges);\n}\n\nfunction isIndex(\n ranges: readonly SymbolRange[] | SymbolRangeIndex,\n): ranges is SymbolRangeIndex {\n return !Array.isArray(ranges);\n}\n\n/** The anchor alone, for a caller that already knows the hunk matched. */\nexport function anchorOnHunk(\n record: KbRecord,\n filePath: string,\n hunk: DiffHunk,\n symbolRanges: readonly SymbolRange[] | SymbolRangeIndex = [],\n): KbAnchor | undefined {\n return placeOnHunk(record, filePath, hunk, symbolRanges).anchor;\n}\n\n/**\n * Whether any of a record's anchors puts it on this hunk.\n *\n * An anchor naming only a file is about the whole file, so it lands on every\n * hunk in it. One naming a symbol lands only where that symbol's lines overlap\n * — unless nothing resolved the symbol, in which case it falls back to the file\n * rather than disappearing. A record silently absent because a resolver was\n * unavailable is worse than one shown imprecisely and labelled as such.\n *\n * A span is already the resolved range, so it needs no `symbolRanges` and is\n * symbol-precision by construction. Sides never cross: an anchor's line\n * numbers only mean anything in its own half of the change, and a symbol\n * indexed on the new tree cannot place an old-side anchor.\n */\nfunction place(\n anchors: KbAnchor[],\n filePath: string,\n hunk: DiffHunk,\n ranges: SymbolRangeIndex,\n): HunkPlacement {\n let fallback: HunkPlacement = { kind: \"miss\" };\n\n for (const anchor of anchors) {\n if (side(anchor.side) !== side(hunk.side)) continue;\n\n if (anchor.span) {\n if (\n overlaps(\n { startLine: anchor.span.start, endLine: anchor.span.end },\n hunk,\n )\n ) {\n return { kind: \"symbol\", anchor };\n }\n continue;\n }\n if (!anchor.symbol) return { kind: \"file\", anchor };\n\n const resolved = ranges.get(\n key(filePath, anchor.symbol, side(anchor.side)),\n );\n if (!resolved?.length) {\n if (fallback.kind === \"miss\") fallback = { kind: \"file\", anchor };\n continue;\n }\n if (resolved.some((range) => overlaps(range, hunk))) {\n return { kind: \"symbol\", anchor };\n }\n }\n\n return fallback;\n}\n\n/** Absent means the post-change side, on an anchor and on a hunk alike. */\nfunction side(value: \"old\" | \"new\" | undefined): \"old\" | \"new\" {\n return value ?? \"new\";\n}\n\nfunction overlaps(\n range: { startLine: number; endLine: number },\n hunk: DiffHunk,\n): boolean {\n return range.startLine <= hunk.endLine && hunk.startLine <= range.endLine;\n}\n\n/** Current before superseded, then oldest first, so an arc reads in order. */\nfunction order(records: KbAdjudicated[]): KbAdjudicated[] {\n const rank: Record<string, number> = {\n current: 0,\n unsettled: 1,\n open: 2,\n superseded: 3,\n rejected: 4,\n };\n return [...records].sort(\n (left, right) =>\n (rank[left.standing] ?? 9) - (rank[right.standing] ?? 9) ||\n (left.record.frontmatter.generated?.at ?? \"\").localeCompare(\n right.record.frontmatter.generated?.at ?? \"\",\n ),\n );\n}\n\n/** Built once by a caller placing many records on many hunks of one diff. */\nexport type SymbolRangeIndex = ReadonlyMap<string, SymbolRange[]>;\n\nexport function symbolRangeIndex(\n ranges: readonly SymbolRange[],\n): SymbolRangeIndex {\n const byKey = new Map<string, SymbolRange[]>();\n for (const range of ranges) {\n const id = key(range.file, range.symbol, side(range.side));\n byKey.set(id, [...(byKey.get(id) ?? []), range]);\n }\n return byKey;\n}\n\nfunction key(file: string, symbol: string, at: \"old\" | \"new\"): string {\n return `${normalize(file)}#${symbol}#${at}`;\n}\n\n/** Anchors are written by hand often enough that `./` shows up. */\nfunction normalize(path: string): string {\n return path.replace(/^\\.\\//, \"\");\n}\n","import type { KbRecord } from \"../kb-record.schema.js\";\nimport type { DiffFile, SymbolRange } from \"../match-diff.js\";\n\n/**\n * What a reviewer can skim and what they must read, derived from the diff.\n *\n * A closed set: a consumer branches on these nine, and a tenth would arrive\n * unhandled. `source` is the residue — everything no rule claimed.\n */\nexport const KB_CLASSES = [\n \"test\",\n \"config\",\n \"ci\",\n \"docs\",\n \"lockfile\",\n \"generated\",\n \"boilerplate\",\n \"rename\",\n \"source\",\n] as const;\n\nexport type KbClass = (typeof KB_CLASSES)[number];\n\n/** A diff file, plus the head lines a caller could read for it. */\nexport type KbClassifyFile = DiffFile & {\n /** The file's first lines at head. Absent falls back to the diff's own. */\n header?: string[];\n};\n\nexport type KbClassifyThresholds = {\n /** Share of a file's changed lines that must match a boilerplate shape. */\n boilerplate?: number;\n /** The `git diff -M` similarity a rename needs before it is called one. */\n rename?: number;\n};\n\nexport const DEFAULT_THRESHOLDS: Required<KbClassifyThresholds> = {\n boilerplate: 0.8,\n rename: 90,\n};\n\nexport type KbClassifyOptions = {\n /** The base, for the `review:*` overrides. Adjudicated: only current wins. */\n records?: KbRecord[];\n /** Without these a symbol anchor covers its whole file rather than a hunk. */\n symbolRanges?: readonly SymbolRange[];\n now?: Date;\n thresholds?: KbClassifyThresholds;\n};\n\n/** The class and the name of the rule that produced it. */\nexport type KbVerdict = { class: KbClass; reason: string };\n\nexport type KbClassifiedHunk = KbVerdict & {\n startLine: number;\n endLine: number;\n};\n\nexport type KbClassifiedFile = KbVerdict & {\n filePath: string;\n renamedFrom?: string;\n /** Present only where some hunk's class differs from the file's. */\n hunks?: KbClassifiedHunk[];\n};\n\nexport type KbClassifyResult = { files: KbClassifiedFile[] };\n","import type { KbClass } from \"./model.js\";\n\n/**\n * The rules, as data. A rule is added by adding a row, so the table is what a\n * reader checks against a path rather than a chain of branches.\n */\nexport type KbPathRule = { name: string; class: KbClass; test: RegExp };\n\n/**\n * Path patterns, first match wins. `lockfile` sits above `config` because a\n * lock file is also a `.yaml`, and `ci` above it because a workflow is a\n * `.yml`.\n */\nexport const PATH_RULES: readonly KbPathRule[] = [\n {\n name: \"test-path\",\n class: \"test\",\n test: /(^|\\/)(__tests__|__mocks__|tests?)\\/|\\.(spec|test)\\.[^/]+$/,\n },\n {\n name: \"ci-path\",\n class: \"ci\",\n test: /(^|\\/)\\.github\\/|(^|\\/)(\\.circleci|\\.buildkite|\\.gitlab|ci)\\/[^/]*\\.ya?ml$|(^|\\/)Dockerfile(\\.[^/]*)?$|\\.tf$/,\n },\n {\n name: \"docs-path\",\n class: \"docs\",\n test: /\\.md$|(^|\\/)docs\\/|(^|\\/)LICENSE(\\.(md|txt|rst))?$/,\n },\n {\n name: \"lockfile-path\",\n class: \"lockfile\",\n test: /(^|\\/)(pnpm-lock\\.yaml|package-lock\\.json|yarn\\.lock|Cargo\\.lock|go\\.sum)$/,\n },\n {\n name: \"config-path\",\n class: \"config\",\n // `.jsonl` rides with `.json`: an append-only log of JSON is configuration\n // data too, and calling it source would send a reviewer to read it. Every\n // arm is anchored at both ends: `src/tsconfig-loader.ts` and `report.env.ts`\n // are source, not config.\n test: /\\.(jsonc?|jsonl|ya?ml|toml|ini)$|(^|\\/)\\.env(?![^/]*\\.[cm]?[jt]sx?$)([.-][^/]*)?$|[^/]+\\.env$|(^|\\/)tsconfig[^/]*\\.json$|\\.config\\.[^/]+$|(^|\\/)\\.(eslintrc|prettierrc)[^/]*$/,\n },\n];\n\n/** How far into a file a generator's banner counts as one. */\nexport const HEADER_LINES = 20;\n\n/**\n * Banners a generator writes. Matched case-insensitively: the convention is\n * shouted in some ecosystems and not in others.\n */\nexport const GENERATED_MARKERS: readonly RegExp[] = [\n /@generated\\b/i,\n /\\bdo not edit\\b/i,\n /\\bcode generated by\\b/i,\n /\\bthis file was automatically generated\\b/i,\n];\n\n/**\n * Line shapes carrying no decision: a moved import, a barrel's re-exports, the\n * punctuation around them, and a class whose body is empty on the same line —\n * an opening brace with code behind it is a class someone has to read.\n */\nexport const BOILERPLATE_SHAPES: readonly { name: string; test: RegExp }[] = [\n { name: \"import\", test: /^import\\b|^\\}\\s*from\\s+[\"']/ },\n { name: \"re-export\", test: /^export\\s+(\\*|\\{|type\\s*[{*])/ },\n {\n name: \"class-shell\",\n test: /^(export\\s+)?(default\\s+)?(abstract\\s+)?class\\s+[\\w$]+[^{]*\\{\\s*\\}$/,\n },\n { name: \"punctuation\", test: /^[{}()[\\],;]+$/ },\n];\n\nexport function generatedMarker(lines: readonly string[]): string | undefined {\n for (const line of lines.slice(0, HEADER_LINES)) {\n const hit = GENERATED_MARKERS.find((marker) => marker.test(line));\n if (hit) return hit.source.replaceAll(\"\\\\b\", \"\");\n }\n return undefined;\n}\n\nexport function isBoilerplateLine(line: string): boolean {\n return BOILERPLATE_SHAPES.some((shape) => shape.test.test(line));\n}\n","import { adjudicate } from \"../adjudicate.js\";\nimport type { KbRecord } from \"../kb-record.schema.js\";\nimport {\n placeOnHunk,\n symbolRangeIndex,\n type DiffHunk,\n type SymbolRangeIndex,\n} from \"../match-diff.js\";\nimport {\n DEFAULT_THRESHOLDS,\n type KbClass,\n type KbClassifiedFile,\n type KbClassifyFile,\n type KbClassifyOptions,\n type KbClassifyThresholds,\n type KbVerdict,\n} from \"./model.js\";\nimport {\n generatedMarker,\n isBoilerplateLine,\n HEADER_LINES,\n PATH_RULES,\n} from \"./rules.js\";\n\n/**\n * What kind of change each file carries.\n *\n * Every input is in the diff, so nothing here is written down: a class the KB\n * stored would be a second copy of an answer the patch already gives, and the\n * two would disagree the first time a rule changed. The one thing a script\n * cannot derive — \"this output is generated, read its input instead\" — is a\n * record, and it wins over the heuristic.\n */\nexport function classifyDiff(\n files: readonly KbClassifyFile[],\n options: KbClassifyOptions = {},\n): KbClassifiedFile[] {\n const overrides = currentOverrides(options.records ?? [], options.now);\n const ranges = symbolRangeIndex(options.symbolRanges ?? []);\n const thresholds = { ...DEFAULT_THRESHOLDS, ...options.thresholds };\n return files.map((file) => classifyFile(file, overrides, ranges, thresholds));\n}\n\n/** A `review:*` fact and the class it asserts. */\ntype Override = { record: KbRecord; class: KbClass };\n\nconst OVERRIDE_CLASS = new Map<string, KbClass>([\n [\"review:generated\", \"generated\"],\n [\"review:boilerplate\", \"boilerplate\"],\n [\"review:move\", \"rename\"],\n]);\n\n/** Wide enough that a file-only anchor lands on it whatever the file's size. */\nconst WHOLE_FILE: DiffHunk = {\n startLine: 1,\n endLine: Number.MAX_SAFE_INTEGER,\n};\n\nfunction classifyFile(\n file: KbClassifyFile,\n overrides: readonly Override[],\n ranges: SymbolRangeIndex,\n thresholds: Required<KbClassifyThresholds>,\n): KbClassifiedFile {\n // An anchor naming no symbol — or one nothing resolved — covers the file, so\n // its record settles every hunk and the heuristic never runs. Probed on the\n // new side only: an override written `side: \"old\"` is not read as one.\n const whole = overrides.find(\n ({ record }) =>\n placeOnHunk(record, file.filePath, WHOLE_FILE, ranges).kind === \"file\",\n );\n const verdict = whole ? verdictOf(whole) : heuristic(file, thresholds);\n\n const hunks = file.hunks.map((hunk) => {\n const hit =\n whole ??\n overrides.find(\n ({ record }) =>\n placeOnHunk(record, file.filePath, hunk, ranges).kind !== \"miss\",\n );\n return {\n startLine: hunk.startLine,\n endLine: hunk.endLine,\n ...(hit ? verdictOf(hit) : verdict),\n };\n });\n\n return {\n filePath: file.filePath,\n ...verdict,\n ...(file.renamedFrom ? { renamedFrom: file.renamedFrom } : {}),\n ...(hunks.some((hunk) => hunk.class !== verdict.class) ? { hunks } : {}),\n };\n}\n\nfunction verdictOf(override: Override): KbVerdict {\n return {\n class: override.class,\n reason: `kb-override ${override.record.conceptId}`,\n };\n}\n\n/** Precedence: a generator's banner, then the path table, then content. */\nfunction heuristic(\n file: KbClassifyFile,\n thresholds: Required<KbClassifyThresholds>,\n): KbVerdict {\n const marker = generatedMarker(file.header ?? headOfDiff(file));\n if (marker)\n return { class: \"generated\", reason: `generated-header ${marker}` };\n\n const rule = PATH_RULES.find((entry) => entry.test.test(file.filePath));\n if (rule) return { class: rule.class, reason: rule.name };\n\n if (\n file.renamedFrom &&\n !file.hunks.length &&\n (file.similarity ?? 100) >= thresholds.rename\n ) {\n return { class: \"rename\", reason: `rename ${file.renamedFrom}` };\n }\n\n const share = boilerplateShare(file);\n if (share !== undefined && share >= thresholds.boilerplate) {\n return {\n class: \"boilerplate\",\n reason: `boilerplate ${Math.round(share * 100)}%`,\n };\n }\n return { class: \"source\", reason: \"default\" };\n}\n\n/**\n * The head of the file as the diff shows it — every added line numbered inside\n * the banner window. All a caller that read no working tree can offer.\n *\n * The window is `--unified=0` numbering: a `--stdin` patch carrying context\n * lines numbers its hunk from the context, so a banner can be misattributed.\n */\nfunction headOfDiff(file: KbClassifyFile): string[] {\n return file.hunks.flatMap((hunk) =>\n (hunk.side ?? \"new\") === \"new\" && hunk.startLine <= HEADER_LINES\n ? (hunk.lines ?? []).slice(0, HEADER_LINES - hunk.startLine + 1)\n : [],\n );\n}\n\n/** Undefined when no parser kept the lines: the rule cannot fire on nothing. */\nfunction boilerplateShare(file: KbClassifyFile): number | undefined {\n const lines = file.hunks\n .flatMap((hunk) => hunk.lines ?? [])\n .map((line) => line.trim())\n .filter(Boolean);\n if (!lines.length) return undefined;\n return lines.filter(isBoilerplateLine).length / lines.length;\n}\n\n/**\n * The `review:*` facts that still hold, by concept id so two on one file\n * resolve the same way twice. Superseded and rejected ones are dropped: an\n * override is an assertion, and a withdrawn assertion is not one.\n */\nfunction currentOverrides(records: KbRecord[], now?: Date): Override[] {\n const tagged = records.flatMap((record) => {\n if (record.frontmatter.type !== \"fact\") return [];\n const tag = (record.frontmatter.tags ?? []).find((entry) =>\n OVERRIDE_CLASS.has(entry),\n );\n const asserted = tag && OVERRIDE_CLASS.get(tag);\n return asserted ? [{ record, class: asserted }] : [];\n });\n\n const current = new Set(\n adjudicate(\n tagged.map(({ record }) => record),\n records,\n now,\n )\n .filter((entry) => entry.standing === \"current\")\n .map((entry) => entry.record.conceptId),\n );\n\n return tagged\n .filter(({ record }) => current.has(record.conceptId))\n .sort((left, right) =>\n left.record.conceptId.localeCompare(right.record.conceptId),\n );\n}\n","import { stat } from \"node:fs/promises\";\nimport {\n anchorFilePath,\n anchorFileReader,\n hashAnchorText,\n type AnchorFileReader,\n type KbDriftMovedTo,\n} from \"../anchor-resolver/index.js\";\nimport { DEFAULT_IO_CONCURRENCY, mapLimit } from \"../concurrency.js\";\nimport type { KbAnchor } from \"../kb-record.schema.js\";\nimport {\n languageForFile,\n TreeSitterResolver,\n} from \"../tree-sitter-resolver/index.js\";\nimport { listRepoFiles } from \"./git.js\";\n\n/**\n * Did this exact code turn up somewhere else?\n *\n * The one drift question a machine can close on its own. A file renamed, a\n * function lifted into a new module, a block reordered — the bytes are\n * identical, so the record still describes them, and asking a reader to\n * re-read what they already read would train them to skip the ones that\n * matter.\n *\n * Identity is the stored hash, never a similarity score: \"nearly the same\n * code\" is exactly the case a reader has to judge.\n */\n\n/**\n * How many repository files one search may parse.\n *\n * The search runs on a reassessment path a person is waiting on, and a\n * repository is not bounded. Past the cap the answer is \"not found\", which is\n * the same answer the reader gets today.\n */\nexport const MAX_MOVED_SEARCH_FILES = 2_000;\n\n/**\n * How many candidates are dispatched before the result is checked.\n *\n * The batch is the unit of wasted work: a hit in the first file still costs a\n * whole batch of reads, and a miss in the whole repository costs one round of\n * latency per batch. Large enough that the pool stays fed, small enough that\n * an early hit does not read a repository to find it.\n */\nconst SEARCH_BATCH = 64;\n\nexport type MovedSearch = {\n /**\n * Where this anchor's stored hash turned up, or `undefined`.\n *\n * Shared across every anchor of a run: one `git ls-files`, one parse cache,\n * one set of loaded grammars. A `doctor --drifted` sweep over a base whose\n * records anchor into the same few languages parses each candidate once, not\n * once per drifted anchor.\n */\n find(anchor: KbAnchor): Promise<KbDriftMovedTo | undefined>;\n};\n\nexport type MovedSearchOptions = {\n /** Test seam: replaces the disk reader. */\n reader?: AnchorFileReader;\n /** Test seam: a candidate's byte size, or `null` when it cannot be known. */\n sizeOf?: (file: string) => Promise<number | null>;\n};\n\n/**\n * Repository-wide through tree-sitter, same-file-only without it.\n *\n * The fallback is narrow on purpose. Without a parser there are no definition\n * boundaries, so the only honest search is a sliding window of the recorded\n * line count over one file — which finds a block that moved within its file\n * and nothing else. Widening that to the repository would be a hash collision\n * hunt across every line offset of every file, for an answer no more certain.\n */\nexport function movedSearch(\n repoRoot: string,\n options: MovedSearchOptions = {},\n): MovedSearch {\n const read = options.reader ?? anchorFileReader(repoRoot);\n const sizeOf = options.sizeOf ?? diskSize(repoRoot);\n const resolver = new TreeSitterResolver();\n let repoFiles: Promise<string[]> | undefined;\n const prepared = new Set<string>();\n\n const filesForLanguage = async (language: string): Promise<string[]> => {\n repoFiles ??= listRepoFiles(repoRoot);\n return (await repoFiles)\n .filter((file) => languageForFile(file) === language)\n .slice(0, MAX_MOVED_SEARCH_FILES);\n };\n\n return {\n async find(anchor) {\n const stored = anchor.hash;\n if (!stored) return undefined;\n\n // A span is an arbitrary range, not a definition, so the definition\n // search has nothing to compare it against — only the window can find it.\n if (anchor.span) return sameFileWindow(anchor, read, stored);\n\n const language = languageForFile(anchor.file);\n // No grammar means no token stream, and an `ast` hash can only be\n // compared against one. Comparing it to a raw hash would be comparing\n // two different measurements and calling a mismatch a move.\n if (!language) return sameFileWindow(anchor, read, stored);\n\n const candidates = await filesForLanguage(language);\n if (!prepared.has(language)) {\n await resolver.prepare(candidates.length ? candidates : [anchor.file]);\n prepared.add(language);\n }\n // A file smaller than the span cannot contain it. One `stat` is far\n // cheaper than a read and a parse, and in a repository of small modules\n // it is most of the candidates.\n const floor = anchor.lines ?? 0;\n\n for (let at = 0; at < candidates.length; at += SEARCH_BATCH) {\n const batch = candidates.slice(at, at + SEARCH_BATCH);\n const hits = await mapLimit(\n batch,\n DEFAULT_IO_CONCURRENCY,\n async (file) => {\n const size = await sizeOf(file);\n // One byte per line is the floor a file of that many lines cannot\n // go under. `null` is \"unknown\", which reads rather than skips.\n if (size !== null && size < floor) return undefined;\n return matchIn(resolver, read, anchor, stored, file);\n },\n );\n // Index order, not completion order: the same repository must always\n // report the same destination.\n const found = hits.find((hit) => hit !== undefined);\n if (found) return found;\n }\n return undefined;\n },\n };\n}\n\n/** The stored hash at some definition in `file`, or `undefined`. */\nasync function matchIn(\n resolver: TreeSitterResolver,\n read: AnchorFileReader,\n anchor: KbAnchor,\n stored: string,\n file: string,\n): Promise<KbDriftMovedTo | undefined> {\n const source = await read(file);\n if (!source.ok) return undefined;\n const normalized = source.source.replace(/\\r\\n/g, \"\\n\");\n\n for (const found of resolver.spans(normalized, file)) {\n // Hashed the way the anchor was stamped: an `ast` hash is only ever\n // compared against a token stream, a raw hash only against raw text.\n const text =\n anchor.hash_kind === \"ast\"\n ? resolver.normalize(found.span.text, file)\n : found.span.text;\n if (text === null || hashAnchorText(text) !== stored) continue;\n // The anchor's own place is where it already looked; finding the hash\n // there would mean it never drifted.\n if (file === anchor.file && found.symbol === anchor.symbol) continue;\n return {\n file,\n symbol: found.symbol,\n startLine: found.span.startLine,\n endLine: found.span.endLine,\n };\n }\n return undefined;\n}\n\n/** `stat` under the repository root; `null` for anything it cannot size. */\nfunction diskSize(repoRoot: string): (file: string) => Promise<number | null> {\n return async (file) => {\n const path = anchorFilePath(repoRoot, file);\n if (path === null) return null;\n try {\n return (await stat(path)).size;\n } catch {\n return null;\n }\n };\n}\n\n/** A block of the recorded line count, at some other offset in the same file. */\nasync function sameFileWindow(\n anchor: KbAnchor,\n read: AnchorFileReader,\n stored: string,\n): Promise<KbDriftMovedTo | undefined> {\n const height = anchor.lines;\n // Without a recorded line count there is no window to slide, and guessing\n // one would make the search's negative answer meaningless. An `ast` hash is\n // over a token stream, which has no line offsets to slide over at all.\n if (!height || anchor.hash_kind === \"ast\") return undefined;\n\n const source = await read(anchor.file);\n if (!source.ok) return undefined;\n const lines = source.source.replace(/\\r\\n/g, \"\\n\").split(\"\\n\");\n\n for (let at = 0; at + height <= lines.length; at++) {\n if (hashAnchorText(lines.slice(at, at + height).join(\"\\n\")) !== stored) {\n continue;\n }\n return {\n file: anchor.file,\n ...(anchor.symbol ? { symbol: anchor.symbol } : {}),\n startLine: at + 1,\n endLine: at + height,\n };\n }\n return undefined;\n}\n","import {\n anchorFileReader,\n prepareResolvers,\n regexResolver,\n resolveAnchorSpan,\n type AnchorFileReader,\n type AnchorResolver,\n type KbAnchorDriftEntry,\n type KbDriftClass,\n} from \"../anchor-resolver/index.js\";\nimport type { KbAnchor, KbRecord } from \"../kb-record.schema.js\";\nimport { isUncheckedReason } from \"../remote-repo/index.js\";\nimport { TreeSitterResolver } from \"../tree-sitter-resolver/index.js\";\nimport { readOldSource, type OldSourceOrigin } from \"./git.js\";\nimport { movedSearch, type MovedSearch } from \"./moved.js\";\n\n/**\n * Turning \"the bytes changed\" into one of four answers, two of which end the\n * matter.\n *\n * The order is not arbitrary: `moved` is asked first because it is the only\n * class that needs no history at all, and `cosmetic` second because it is the\n * only one that needs the old text. What survives both is what a reader has to\n * read — and the whole point of asking the cheap questions first is that most\n * drift never reaches them.\n *\n * Everything here is read-only. Rebaselining a `moved` anchor is a write, and\n * writes belong to the verb the caller named.\n */\n\nexport type ClassifiedAnchor = {\n anchor: KbAnchor;\n entry: KbAnchorDriftEntry;\n /** Resolved class. Never `undefined` — every reported anchor gets one. */\n class: KbDriftClass;\n /** The anchored text as it stands now. Absent when the class is `gone`. */\n newText?: string;\n /** The anchored text as it was, when history could produce it. */\n oldText?: string;\n oldOrigin?: OldSourceOrigin;\n};\n\nexport type ClassifyOptions = {\n /** Test seam: replaces the disk reader. */\n reader?: AnchorFileReader;\n /** Skip the history read. `cosmetic` cannot be reached without it. */\n withHistory?: boolean;\n /**\n * The run's shared `moved` search. A sweep classifying many records passes\n * one, so the repository is listed once and each candidate file is parsed\n * once for the whole sweep rather than once per record.\n */\n search?: MovedSearch;\n};\n\n/**\n * Refines one record's drift entries. Anchors that matched, or that name\n * another repository, are not drift and never appear.\n */\nexport async function classifyDrift(\n repoRoot: string,\n record: KbRecord,\n entries: readonly KbAnchorDriftEntry[],\n options: ClassifyOptions = {},\n): Promise<ClassifiedAnchor[]> {\n // `detectAnchorDrift` walks the hash-carrying anchors in frontmatter order\n // and emits one entry each, so index is identity here.\n const anchors = (record.frontmatter.strauss_anchors ?? []).filter(\n (anchor) => anchor.hash,\n );\n const reader = options.reader ?? anchorFileReader(repoRoot);\n const treeSitter = new TreeSitterResolver();\n const resolvers: AnchorResolver[] = [treeSitter, regexResolver];\n const search =\n options.search ??\n movedSearch(repoRoot, { ...(options.reader ? { reader } : {}) });\n\n const wanted: { anchor: KbAnchor; entry: KbAnchorDriftEntry }[] = [];\n entries.forEach((entry, at) => {\n const anchor = anchors[at];\n if (!anchor) return;\n if (entry.state === \"match\" || isUncheckedReason(entry.reason)) return;\n wanted.push({ anchor, entry });\n });\n if (!wanted.length) return [];\n\n await prepareResolvers(\n resolvers,\n wanted.map(({ anchor }) => anchor.file),\n );\n\n const out: ClassifiedAnchor[] = [];\n for (const { anchor, entry } of wanted) {\n // Both passes read the working tree — `search.find` for a move, and the\n // cosmetic check for the current text — which is not the tree an old-side\n // anchor names, so the provisional class stands.\n if (anchor.side === \"old\") {\n const settled = entry.class ?? \"changed\";\n out.push({ anchor, entry: { ...entry, class: settled }, class: settled });\n continue;\n }\n\n const movedTo = await search.find(anchor);\n if (movedTo) {\n out.push({\n anchor,\n entry: { ...entry, class: \"moved\", movedTo },\n class: \"moved\",\n });\n continue;\n }\n\n const newText = await currentText(reader, anchor, resolvers);\n const old =\n options.withHistory === false\n ? { ok: false as const, reason: \"unrecoverable\" as const }\n : await readOldSource(repoRoot, anchor);\n const oldText = old.ok ? spanIn(old.source, anchor, resolvers) : undefined;\n\n const settled: KbDriftClass =\n newText !== undefined &&\n oldText !== undefined &&\n sameTokens(treeSitter, anchor.file, oldText, newText)\n ? \"cosmetic\"\n : (entry.class ?? \"changed\");\n\n out.push({\n anchor,\n entry: { ...entry, class: settled },\n class: settled,\n ...(newText !== undefined ? { newText } : {}),\n ...(oldText !== undefined ? { oldText } : {}),\n ...(old.ok ? { oldOrigin: old.origin } : {}),\n });\n }\n return out;\n}\n\n/**\n * Only a parser can say two spellings are one program. Without one — a file\n * with no grammar, or text that will not parse — the answer is no, which\n * leaves the class where it was rather than inventing a reassurance.\n */\nfunction sameTokens(\n resolver: TreeSitterResolver,\n file: string,\n before: string,\n after: string,\n): boolean {\n if (before === after) return false;\n const left = resolver.normalize(before, file);\n const right = resolver.normalize(after, file);\n return left !== null && left === right;\n}\n\nasync function currentText(\n reader: AnchorFileReader,\n anchor: KbAnchor,\n resolvers: readonly AnchorResolver[],\n): Promise<string | undefined> {\n const read = await reader(anchor.file);\n if (!read.ok) return undefined;\n return spanIn(read.source, anchor, resolvers);\n}\n\n/** The anchor's span within some version of its file, current or committed. */\nfunction spanIn(\n source: string,\n anchor: KbAnchor,\n resolvers: readonly AnchorResolver[],\n): string | undefined {\n const outcome = resolveAnchorSpan(source, anchor, resolvers);\n return outcome.ok ? outcome.span.text : undefined;\n}\n","/**\n * A unified diff of two spans, bounded on purpose.\n *\n * The packet exists so a reader can judge without opening the repository, and\n * a diff that has to be scrolled past defeats that as surely as no diff at all.\n * Both caps below are line counts rather than bytes, because what a reader\n * runs out of is attention.\n */\n\n/** Never more than this from one anchor, whatever the record's shape. */\nexport const MAX_ANCHOR_DIFF_LINES = 200;\n\n/**\n * Shared across a record's anchors, so a ten-anchor record stays as readable as\n * a one-anchor record is. `kb_reassess`'s size ceiling is a whole-packet\n * number, and only a whole-packet budget can hold it.\n */\nexport const PACKET_DIFF_LINE_BUDGET = 200;\n\n/** Below this an anchor is better dropped than shown as a stub. */\nexport const MIN_ANCHOR_DIFF_LINES = 12;\n\n/** Each anchor's share of the budget, never above the per-anchor cap. */\nexport function diffBudget(anchors: number): number {\n if (anchors <= 0) return MAX_ANCHOR_DIFF_LINES;\n return Math.min(\n MAX_ANCHOR_DIFF_LINES,\n Math.max(\n MIN_ANCHOR_DIFF_LINES,\n Math.floor(PACKET_DIFF_LINE_BUDGET / anchors),\n ),\n );\n}\n\nexport type UnifiedDiff = {\n /** `-`/`+`/` ` prefixed lines, with a `@@` header. */\n text: string;\n added: number;\n removed: number;\n /** Whether the cap cut it short. */\n truncated: boolean;\n};\n\n/**\n * One hunk, no context trimming: the two sides are already a symbol's span,\n * so the whole of both is the context a reader wants.\n *\n * The common subsequence is computed over line *hashes* through a simple\n * O(n·m) table. Spans are bounded by the anchor file cap, and a smarter\n * algorithm would be a second thing to be wrong about for a saving nobody can\n * measure at this size.\n */\nexport function unifiedDiff(\n before: string,\n after: string,\n options: { maxLines?: number; oldLabel?: string; newLabel?: string } = {},\n): UnifiedDiff {\n const max = options.maxLines ?? MAX_ANCHOR_DIFF_LINES;\n const left = before.replace(/\\r\\n/g, \"\\n\").split(\"\\n\");\n const right = after.replace(/\\r\\n/g, \"\\n\").split(\"\\n\");\n\n const body: string[] = [];\n let added = 0;\n let removed = 0;\n for (const edit of edits(left, right)) {\n if (edit.kind === \"same\") body.push(` ${edit.line}`);\n else if (edit.kind === \"remove\") {\n body.push(`-${edit.line}`);\n removed += 1;\n } else {\n body.push(`+${edit.line}`);\n added += 1;\n }\n }\n\n const truncated = body.length > max;\n const shown = truncated ? body.slice(0, max) : body;\n const header = `@@ -1,${left.length} +1,${right.length} @@${\n options.oldLabel\n ? ` ${options.oldLabel} → ${options.newLabel ?? \"\"}`.trimEnd()\n : \"\"\n }`;\n const lines = [header, ...shown];\n if (truncated) lines.push(`… ${body.length - max} more diff lines`);\n\n return { text: lines.join(\"\\n\"), added, removed, truncated };\n}\n\ntype Edit = { kind: \"same\" | \"remove\" | \"add\"; line: string };\n\n/** Longest-common-subsequence backtrack, emitted in source order. */\nfunction edits(left: string[], right: string[]): Edit[] {\n const rows = left.length;\n const cols = right.length;\n const table: number[][] = Array.from({ length: rows + 1 }, () =>\n new Array<number>(cols + 1).fill(0),\n );\n for (let row = rows - 1; row >= 0; row--) {\n for (let col = cols - 1; col >= 0; col--) {\n (table[row] as number[])[col] =\n left[row] === right[col]\n ? ((table[row + 1] as number[])[col + 1] as number) + 1\n : Math.max(\n (table[row + 1] as number[])[col] as number,\n (table[row] as number[])[col + 1] as number,\n );\n }\n }\n\n const out: Edit[] = [];\n let row = 0;\n let col = 0;\n while (row < rows && col < cols) {\n if (left[row] === right[col]) {\n out.push({ kind: \"same\", line: left[row] as string });\n row += 1;\n col += 1;\n } else if (\n ((table[row + 1] as number[])[col] as number) >=\n ((table[row] as number[])[col + 1] as number)\n ) {\n out.push({ kind: \"remove\", line: left[row] as string });\n row += 1;\n } else {\n out.push({ kind: \"add\", line: right[col] as string });\n col += 1;\n }\n }\n for (; row < rows; row++)\n out.push({ kind: \"remove\", line: left[row] as string });\n for (; col < cols; col++)\n out.push({ kind: \"add\", line: right[col] as string });\n return out;\n}\n","import type { KbStanding } from \"../adjudicate.js\";\nimport type {\n KbAnchorDriftEntry,\n KbDriftClass,\n KbDriftMovedTo,\n} from \"../anchor-resolver/index.js\";\nimport type { KbRecord, KbRecordType } from \"../kb-record.schema.js\";\nimport type { KbImpactResult } from \"../kb-links/index.js\";\nimport { isKbRecordType, RECORD_TYPES } from \"../record-types.js\";\nimport {\n classifyDrift,\n type ClassifiedAnchor,\n type ClassifyOptions,\n} from \"./classify.js\";\nimport { diffBudget, unifiedDiff } from \"./diff.js\";\n\n/**\n * What a reader needs in order to decide whether a record still holds, without\n * opening the repository.\n *\n * A drift finding today says two hashes disagree, which is not a thing anyone\n * can judge. The packet is the same finding with the three pieces judgment\n * actually takes: what the record claims, what the code did, and what depends\n * on the answer. It stops there — the reading itself is the reader's, and\n * every default below is a starting point the protocol expects to be argued\n * with.\n */\n\nexport type KbReassessDiff =\n | {\n status: \"ok\";\n /** `ref` when the anchor pinned one, `history` when it was inferred. */\n source: \"ref\" | \"history\";\n /** The rev the old side was read at. */\n ref: string;\n unified: string;\n added: number;\n removed: number;\n truncated: boolean;\n }\n /** No committed text to diff against; see `readOldSource`. */\n | { status: \"unrecoverable\" };\n\nexport type KbReassessAnchor = {\n file: string;\n symbol?: string;\n class: KbDriftClass;\n reason?: string;\n storedHash: string;\n currentHash?: string;\n diffSize: number | null;\n movedTo?: KbDriftMovedTo;\n diff?: KbReassessDiff;\n};\n\n/**\n * What the type says about a record whose code changed under it.\n *\n * A `fact` is a claim about the world that the code was the evidence for, so\n * changed evidence presumptively unmakes it. A `decision` is a claim about a\n * choice, and the reasoning for a choice routinely outlives the code that\n * implemented it. Neither is a verdict — they are which way to lean while\n * reading, and naming the lean is what keeps it arguable.\n */\nexport type KbReassessDefault =\n \"presumed-invalidated\" | \"rationale-may-survive\" | \"review\";\n\nconst PRESUMED_INVALID: readonly KbRecordType[] = [\n \"fact\",\n \"constraint\",\n \"contract\",\n];\nconst RATIONALE_SURVIVES: readonly KbRecordType[] = [\"decision\", \"risk\"];\n\nconst DEFAULT_NOTES: Record<KbReassessDefault, string> = {\n \"presumed-invalidated\":\n \"the code this claim was taken from changed; presume it no longer holds until re-read\",\n \"rationale-may-survive\":\n \"the reasoning may outlive the code that implemented it; check whether it does\",\n review: \"re-read the record against the new code\",\n};\n\nexport type KbReassessPacket = {\n conceptId: string;\n title: string | null;\n type: string;\n standing: KbStanding;\n /** What breaks if this record is wrong — the record's `why`, stored as `description`. */\n why: string | null;\n /** The type's claim section — the sentence being reassessed. */\n claim: { section: string; text: string } | null;\n anchors: KbReassessAnchor[];\n /**\n * The record's dependants. A fact that stopped holding did not stop holding\n * alone, and a reader deciding about it is deciding about these too.\n */\n impact: {\n conceptId: string;\n title: string | null;\n standing: KbStanding;\n depth: number;\n }[];\n impactTruncated: boolean;\n default: KbReassessDefault;\n defaultNote: string;\n};\n\nexport type PacketOptions = ClassifyOptions & {\n /** Recover and render the old-vs-new span diff. Off by default: it reads git. */\n withDiff?: boolean;\n impact?: KbImpactResult;\n standing?: KbStanding;\n};\n\n/**\n * One record's packet, or `null` when nothing survived classification.\n *\n * A record whose every drifted anchor turned out to be `moved` or `cosmetic`\n * is a record with no reassessment work, and emitting an empty packet for it\n * would put it back in front of the reader the classification just cleared it\n * from.\n */\nexport async function reassessPacket(\n repoRoot: string,\n record: KbRecord,\n entries: readonly KbAnchorDriftEntry[],\n options: PacketOptions = {},\n): Promise<{\n packet: KbReassessPacket | null;\n classified: ClassifiedAnchor[];\n}> {\n const classified = await classifyDrift(repoRoot, record, entries, {\n ...(options.reader ? { reader: options.reader } : {}),\n ...(options.search ? { search: options.search } : {}),\n withHistory: options.withDiff !== false,\n });\n\n const open = classified.filter(\n (found) => found.class === \"changed\" || found.class === \"gone\",\n );\n if (!open.length) return { packet: null, classified };\n\n const budget = diffBudget(open.length);\n const anchors = open.map((found) =>\n anchorPacket(found, options.withDiff === true, budget),\n );\n\n const type = record.frontmatter.type;\n const fallback: KbReassessDefault = isKbRecordType(type)\n ? PRESUMED_INVALID.includes(type)\n ? \"presumed-invalidated\"\n : RATIONALE_SURVIVES.includes(type)\n ? \"rationale-may-survive\"\n : \"review\"\n : \"review\";\n\n return {\n classified,\n packet: {\n conceptId: record.conceptId,\n title: record.frontmatter.title ?? null,\n type,\n standing: options.standing ?? \"unsettled\",\n why: record.frontmatter.description ?? null,\n claim: claimOf(record),\n anchors,\n impact: (options.impact?.impacted ?? []).map((entry) => ({\n conceptId: entry.conceptId,\n title: entry.title,\n standing: entry.standing,\n depth: entry.depth,\n })),\n impactTruncated: options.impact?.truncated ?? false,\n default: fallback,\n defaultNote: DEFAULT_NOTES[fallback],\n },\n };\n}\n\nfunction anchorPacket(\n found: ClassifiedAnchor,\n withDiff: boolean,\n maxLines: number,\n): KbReassessAnchor {\n const { entry } = found;\n const base: KbReassessAnchor = {\n file: entry.file,\n ...(entry.symbol ? { symbol: entry.symbol } : {}),\n class: found.class,\n ...(entry.reason ? { reason: entry.reason } : {}),\n storedHash: entry.storedHash,\n ...(entry.currentHash ? { currentHash: entry.currentHash } : {}),\n diffSize: entry.diffSize,\n ...(entry.movedTo ? { movedTo: entry.movedTo } : {}),\n };\n if (!withDiff) return base;\n\n if (found.oldText === undefined || !found.oldOrigin) {\n return { ...base, diff: { status: \"unrecoverable\" } };\n }\n // A `gone` anchor has no new side; the diff is the whole old span removed,\n // which is exactly what the reader has to weigh.\n const rendered = unifiedDiff(found.oldText, found.newText ?? \"\", {\n maxLines,\n });\n return {\n ...base,\n diff: {\n status: \"ok\",\n source: found.oldOrigin.kind,\n ref: found.oldOrigin.ref,\n unified: rendered.text,\n added: rendered.added,\n removed: rendered.removed,\n truncated: rendered.truncated,\n },\n };\n}\n\n/**\n * The first section of the record's type — its central claim, per the type\n * table — pulled out of the body so the packet carries the sentence being\n * judged rather than the whole record.\n */\nfunction claimOf(record: KbRecord): { section: string; text: string } | null {\n const type = record.frontmatter.type;\n const section = isKbRecordType(type)\n ? RECORD_TYPES[type].sections[0]\n : undefined;\n if (!section) return null;\n\n const lines = record.body.replace(/\\r\\n/g, \"\\n\").split(\"\\n\");\n const start = lines.findIndex(\n (line) => line.trim().toLowerCase() === `## ${section}`.toLowerCase(),\n );\n if (start < 0) return null;\n const rest = lines.slice(start + 1);\n const end = rest.findIndex((line) => line.startsWith(\"## \"));\n const text = (end < 0 ? rest : rest.slice(0, end)).join(\"\\n\").trim();\n return text ? { section, text } : null;\n}\n","import type { KbRecord } from \"./kb-record.schema.js\";\n\nexport const INDEX_FILE = \"INDEX.md\";\n\nconst HEADING = \"# KB Index\";\n\n/**\n * `INDEX.md` is a projection — every byte recomputable from record frontmatter.\n *\n * That is what lets parallel writers regenerate it without a lock: they compute\n * the same function of the same records, so two concurrent regenerations differ\n * only in how recent each writer's scan was, and the next read settles it. The\n * file is therefore eventually correct rather than always correct, which is the\n * right trade for something nothing reads transactionally.\n *\n * Lines carry `description`, not just a title. A reader consults the index to\n * decide what is worth opening, and a list of titles does not answer that.\n */\nexport function renderIndex(records: KbRecord[]): string {\n const lines = [...records]\n .sort((left, right) => left.conceptId.localeCompare(right.conceptId))\n .map(renderIndexLine);\n\n return `${HEADING}\\n\\n${lines.join(\"\\n\")}\\n`;\n}\n\n/**\n * One record's index line. The single writer of this shape — `context` emits\n * the same line rather than growing a second index renderer that would drift\n * from this one.\n */\nexport function renderIndexLine(record: KbRecord): string {\n const { frontmatter: fm } = record;\n const parts = [fm.type, fm.strauss_status];\n if (fm.tags?.length) parts.push(`tags: ${fm.tags.join(\", \")}`);\n if (fm.description) parts.push(fm.description);\n return `- [${fm.title ?? record.conceptId}](${record.conceptId}.md) — ${parts.join(\" · \")}`;\n}\n\n/** Whether the stored projection still matches the records it claims to index. */\nexport function indexIsStale(stored: string | null, expected: string): boolean {\n return stored !== expected;\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { adjudicate } from \"./adjudicate.js\";\nimport { renderIndexLine } from \"./kb-index.js\";\nimport {\n mergedContextBudgets,\n readMergedPins,\n type KbContextBudgets,\n} from \"./kb-pins/index.js\";\nimport type { KbStore } from \"./kb-store.js\";\nimport { matchesTags } from \"./kb-tags.js\";\n\n/**\n * The context block: an index of every pinned base, emitted at context birth.\n *\n * Two failure modes lose a knowledge base to a long session — attention decay,\n * and compaction, which summarises away both loaded records and the early\n * instruction that said to consult them. This block is the layer against both:\n * small enough to re-inject at every session start, and self-instructing, so a\n * re-injection after compaction reads as a refresh rather than a contradiction.\n *\n * It is an index, not the content: concept ids, titles and standing. The\n * bodies stay behind the tools, loaded at the point of use.\n */\n\n/** A stable heading, so re-injection reads as a refresh. */\nconst HEADING = \"## Knowledge bases (pinned)\";\n\n/**\n * Small by design — this block is paid at every context birth, and on some\n * runtimes on every turn. A base wanting more space is `--full-under`'s job.\n */\nconst DEFAULT_CONTEXT_BUDGET = 4_000;\n\n/**\n * What the hooks ask for by name, so the numbers live in one place and a repo\n * can override them in its pin manifest rather than editing hook commands.\n * `session-start` is a fresh window — room for tiny bases to arrive whole.\n * `compact` competes with a summary for a smaller window — index only.\n * `turn` is per-turn injection (Antigravity) — same tight stance as compact.\n */\nexport const CONTEXT_PROFILES: Record<string, KbContextBudgets> = {\n \"session-start\": { fullUnderTokens: 1_500 },\n compact: { budgetTokens: 2_500 },\n turn: { budgetTokens: 2_500 },\n};\n\nexport type KbContextOptions = {\n /** Refuse past this. Defaults to 4000 tokens. */\n budgetTokens?: number;\n /** Emit bases whose full `load` fits under this as records, not index. 0 = off. */\n fullUnderTokens?: number;\n /**\n * A named budget set. Resolution, most specific wins: explicit options,\n * then the manifest's `context[profile]` over its `context.default`, then\n * the built-in profile, then the package defaults. An unknown profile is\n * not an error — it simply falls through; hooks must never break over a\n * name.\n */\n profile?: string;\n /**\n * Frontmatter tags whose records stay out of the block. Resolved like the\n * budgets, and a profile setting rather than a pin's: it says what this\n * context birth wants, so a base stays pinned and stays readable by tool.\n */\n excludeTags?: string[];\n /**\n * Where budget pressure is reported outside the block itself: a full pin\n * that had to degrade to an index, a block that refused. The block already\n * says both to the agent; this says them to the operator's log.\n */\n warn?: (entry: Record<string, unknown>) => void;\n};\n\nexport type KbContextResult = {\n /** The markdown block. Empty when there are no pins — silence, not a stub. */\n block: string;\n /** Refused: over budget. The block then lists the bases instead of the index. */\n refused: boolean;\n approxTokens: number;\n budgetTokens: number;\n bases: { path: string; absolutePath: string; approxTokens: number }[];\n};\n\n/** The crude estimator everything here shares — see kb-store.ts on why. */\nfunction approxTokens(text: string): number {\n return Math.ceil(text.length / 4);\n}\n\nfunction preamble(): string {\n return [\n HEADING,\n \"\",\n \"What follows is an index of this workspace's pinned knowledge bases —\",\n \"concept ids, titles and standing only. The record bodies are NOT in this\",\n \"context.\",\n \"\",\n \"Consult records only through the strauss-kb MCP tools: `kb_load` (the\",\n \"preferred first call), `kb_query`, and `kb_trace`, passing the\",\n \"`bundlePath` listed with each base. Do not read record files directly:\",\n \"a raw file read bypasses supersession resolution, and a superseded or\",\n \"rejected record file reads exactly like a current one — only the store\",\n \"resolves chains and standing.\",\n \"\",\n \"KB content loaded earlier in a long session may have been compacted\",\n \"away. Before answering a question one of these bases governs, load it\",\n \"again at the point of use — reloading a small base costs a few thousand\",\n \"tokens.\",\n ].join(\"\\n\");\n}\n\ntype BaseSection = {\n path: string;\n absolutePath: string;\n body: string;\n mode: \"index\" | \"full\" | \"empty\";\n /**\n * A `mode: full` pin whose bodies exceeded the block budget, emitted as an\n * index instead. Flagged in the section label, never silent — the reader\n * asked for the whole base and must know it is not looking at it.\n */\n degradedFrom?: { approxTokens: number };\n};\n\nasync function renderBase(\n store: KbStore,\n path: string,\n absolutePath: string,\n fullUnderTokens: number,\n pinMode: \"full\" | \"index\" | undefined,\n budgetTokens: number,\n excludeTags: string[],\n): Promise<BaseSection> {\n const bundle = await store.list(absolutePath);\n if (bundle.length === 0) {\n return {\n path,\n absolutePath,\n mode: \"empty\",\n body: \"No readable records yet — pinned ahead of being populated.\",\n };\n }\n\n // A pin's own mode outranks the threshold. `full` preloads the base whole —\n // capped only by the block budget, because past that the whole block\n // refuses anyway; when even that fails, the base degrades to an index and\n // the label says so, never silently. `index` never upgrades.\n const fullCap =\n pinMode === \"full\"\n ? budgetTokens\n : pinMode === \"index\"\n ? 0\n : fullUnderTokens;\n\n let degradedFrom: { approxTokens: number } | undefined;\n if (fullCap > 0) {\n const full = await store.load(absolutePath, {\n budgetTokens: fullCap,\n excludeTags,\n });\n if (!full.loaded && pinMode === \"full\") {\n degradedFrom = { approxTokens: full.approxTokens };\n }\n if (full.loaded) {\n const records = full.records.map((hit) =>\n [\n `#### ${hit.record.conceptId} — ${hit.record.frontmatter.title ?? \"(untitled)\"} (${hit.standing})`,\n \"\",\n hit.record.body.trim(),\n ].join(\"\\n\"),\n );\n const superseded = full.superseded.map(\n (entry) =>\n `- \\`${entry.conceptId}\\` → superseded by ${entry.supersededBy.map((id) => `\\`${id}\\``).join(\", \") || \"(missing replacement)\"}`,\n );\n return {\n path,\n absolutePath,\n mode: \"full\",\n body: [\n ...records,\n ...(superseded.length\n ? [\n \"#### Superseded (bodies withheld — kb_trace reaches them)\",\n ...superseded,\n ]\n : []),\n ].join(\"\\n\\n\"),\n };\n }\n }\n\n // Adjudicated against the whole base, excluded only after: a record kept out\n // of the block still supersedes, so the replacement it names stays right.\n const adjudicated = adjudicate(bundle, bundle).filter((hit) =>\n matchesTags(hit.record, { excludeTags }),\n );\n const lines = adjudicated\n .filter((hit) => hit.standing !== \"superseded\")\n .map((hit) => renderIndexLine(hit.record));\n const superseded = adjudicated\n .filter((hit) => hit.standing === \"superseded\")\n .map(\n (hit) =>\n `- \\`${hit.record.conceptId}\\` → superseded by ${hit.heads.map((head) => `\\`${head.conceptId}\\``).join(\", \") || \"(missing replacement)\"}`,\n );\n return {\n path,\n absolutePath,\n mode: \"index\",\n body: [...lines, ...superseded].join(\"\\n\"),\n ...(degradedFrom ? { degradedFrom } : {}),\n };\n}\n\n/**\n * Builds the block, or a refusal that lists the bases — never a truncation. A\n * truncated index is indistinguishable from a complete one, so a reader would\n * take a slice for the whole, which is `load`'s argument one layer up.\n */\nexport async function buildContext(\n store: KbStore,\n workspaceDir: string,\n options: KbContextOptions = {},\n): Promise<KbContextResult> {\n const builtin = options.profile\n ? (CONTEXT_PROFILES[options.profile] ?? {})\n : {};\n let budgetTokens =\n options.budgetTokens ?? builtin.budgetTokens ?? DEFAULT_CONTEXT_BUDGET;\n let fullUnderTokens = options.fullUnderTokens ?? builtin.fullUnderTokens ?? 0;\n\n // All three manifest layers, merged — nearest wins. The reader skips a\n // malformed layer rather than throwing: this runs from hooks at every\n // session start, and one broken personal file must not silence the team's\n // pins. `pin`/`unpin` are what surface the broken layer, loudly.\n const merged = await readMergedPins(workspaceDir);\n\n // The workspace's own numbers, from the manifests — above the built-ins,\n // below anything passed explicitly.\n const fromManifest = mergedContextBudgets(merged, options.profile);\n budgetTokens =\n options.budgetTokens ??\n fromManifest.budgetTokens ??\n builtin.budgetTokens ??\n DEFAULT_CONTEXT_BUDGET;\n fullUnderTokens =\n options.fullUnderTokens ??\n fromManifest.fullUnderTokens ??\n builtin.fullUnderTokens ??\n 0;\n const excludeTags =\n options.excludeTags ??\n fromManifest.excludeTags ??\n builtin.excludeTags ??\n [];\n\n // A pin scoped to named profiles surfaces only in those; unscoped pins\n // surface everywhere, and a run without a profile sees everything — the\n // explicit full view.\n const pins = merged.pins.filter(\n (pin) =>\n !pin.profiles?.length ||\n !options.profile ||\n pin.profiles.includes(options.profile),\n );\n if (pins.length === 0) {\n return {\n block: \"\",\n refused: false,\n approxTokens: 0,\n budgetTokens,\n bases: [],\n };\n }\n\n const sections = await Promise.all(\n pins.map(async (pin) => ({\n section: await renderBase(\n store,\n pin.path,\n pin.absolutePath,\n fullUnderTokens,\n pin.mode,\n budgetTokens,\n excludeTags,\n ),\n frozen: pin.frozen === true,\n })),\n );\n\n const modeLabel = {\n index: \"index only — record bodies are not here\",\n full: \"full records — this base arrives whole\",\n empty: \"empty\",\n } as const;\n\n // A full pin that could not fit is loudly labelled, in the block and in the\n // log: the reader asked for the whole base and must know it is not looking\n // at it, and the operator must see the budget pressure without reading\n // injected context.\n for (const { section } of sections) {\n if (section.degradedFrom) {\n options.warn?.({\n operation: \"kb.context.full-pin-degraded\",\n path: section.path,\n approxTokens: section.degradedFrom.approxTokens,\n budgetTokens,\n });\n }\n }\n\n const rendered = sections.map(({ section, frozen }) => {\n const label = section.degradedFrom\n ? `index only — pinned \\`mode: full\\`, but its ~${section.degradedFrom.approxTokens} tokens exceed this block's ${budgetTokens}-token budget; kb_load it directly (load's budget is separate), or raise this profile's budget`\n : modeLabel[section.mode];\n return [\n `### ${section.path} (${label}${frozen ? \" · frozen, read-only\" : \"\"})`,\n \"\",\n `bundlePath: \\`${section.absolutePath}\\``,\n \"\",\n section.body,\n ].join(\"\\n\");\n });\n\n const block = [preamble(), \"\", rendered.join(\"\\n\\n\"), \"\"].join(\"\\n\");\n const bases = sections.map(({ section }) => ({\n path: section.path,\n absolutePath: section.absolutePath,\n approxTokens: approxTokens(section.body),\n }));\n const total = approxTokens(block);\n\n if (total > budgetTokens) {\n options.warn?.({\n operation: \"kb.context.refused\",\n approxTokens: total,\n budgetTokens,\n bases: bases.map((base) => base.path),\n });\n // A refusal, not a lock: the budget guards what is injected at every\n // context birth, never a deliberate read. So the refusal carries both\n // moves — read what the question needs right now, and shrink the\n // recurring block so the next session does not land here.\n const refusal = [\n HEADING,\n \"\",\n `The pinned index runs to ~${total} tokens, past the ${budgetTokens}-token`,\n \"budget, and was not emitted — a truncated index is indistinguishable\",\n \"from a complete one. The pinned bases:\",\n \"\",\n ...bases.map(\n (base) =>\n `- ${base.path} — ~${base.approxTokens} tokens (bundlePath: \\`${base.absolutePath}\\`)`,\n ),\n \"\",\n \"For the question at hand, read what you need now — `kb_load` a base\",\n \"(its own budget is separate), or `kb_index` for one base's shape.\",\n \"\",\n \"To bring this block back under budget, in order of preference:\",\n \"- supersede or resolve stale records — the base shrinks, the knowledge keeps\",\n \"- force a large base to index lines: `strauss-kb pin <path> --mode index`\",\n \"- scope a pin to the profiles that need it: `strauss-kb pin <path> --profiles session-start`\",\n \"- raise this profile's budget under `context` in .strauss/kb-pins.json\",\n \"- unpin what no session actually needs\",\n \"\",\n ].join(\"\\n\");\n return {\n block: refusal,\n refused: true,\n approxTokens: total,\n budgetTokens,\n bases,\n };\n }\n\n return { block, refused: false, approxTokens: total, budgetTokens, bases };\n}\n\n/**\n * The same block in the envelope hook protocols that demand strict JSON on\n * stdout require:\n * those protocols treat non-JSON stdout as a violation, where Claude Code and\n * Codex take plain text. One canonical writer for the block; this is wrapping.\n */\nexport function toHookJson(block: string, event: string): string {\n return JSON.stringify({\n hookSpecificOutput: {\n hookEventName: event,\n additionalContext: block,\n },\n });\n}\n\nexport const CONTEXT_BEGIN = \"<!-- strauss-kb:begin -->\";\nexport const CONTEXT_END = \"<!-- strauss-kb:end -->\";\n\nexport type KbSyncResult = {\n file: string;\n action: \"created\" | \"replaced\" | \"appended\" | \"removed\" | \"unchanged\";\n};\n\n/**\n * Idempotently plants the block between sentinels in an instruction file\n * (AGENTS.md, CLAUDE.md). This is how a runtime without a reliable\n * post-compact hook keeps a refreshable index: the file is re-read where the\n * conversation is not. Everything outside the sentinels is left alone.\n */\nexport async function syncInstructions(\n file: string,\n block: string,\n): Promise<KbSyncResult> {\n const existing = await readFile(file, \"utf8\").catch(() => null);\n const region = block\n ? `${CONTEXT_BEGIN}\\n${block.trim()}\\n${CONTEXT_END}`\n : null;\n\n if (existing === null) {\n if (!region) return { file, action: \"unchanged\" };\n await writeFile(file, `${region}\\n`, \"utf8\");\n return { file, action: \"created\" };\n }\n\n const begin = existing.indexOf(CONTEXT_BEGIN);\n const end = existing.indexOf(CONTEXT_END);\n if (begin !== -1 && end !== -1 && end >= begin) {\n const before = existing.slice(0, begin);\n const after = existing.slice(end + CONTEXT_END.length);\n const next = region\n ? `${before}${region}${after}`\n : `${before.replace(/\\n+$/, \"\\n\")}${after.replace(/^\\n+/, \"\\n\")}`;\n if (next === existing) return { file, action: \"unchanged\" };\n await writeFile(file, next, \"utf8\");\n return { file, action: region ? \"replaced\" : \"removed\" };\n }\n\n if (!region) return { file, action: \"unchanged\" };\n await writeFile(\n file,\n `${existing.replace(/\\n*$/, \"\\n\\n\")}${region}\\n`,\n \"utf8\",\n );\n return { file, action: \"appended\" };\n}\n","import { KB_CONCEPT_ID_PATTERN, type KbRecord } from \"./kb-record.schema.js\";\nimport { KB_LINK_RELS } from \"./record-types.js\";\n\n/**\n * The edges between records in one bundle, defined once.\n *\n * Both walks — `trace` and `pack` — consume this module, so they cannot drift\n * into disagreeing about what makes two records neighbours, and a diagnostic\n * pass over the graph can reuse the same definition.\n *\n * There is no separate `related` kind: compose.ts renders `relatedConceptIds`\n * as body links (`Relates to [id](id.md).`), so in stored form a related edge\n * IS a body link, and a distinct kind would count the same markdown twice.\n *\n * `typed-link` is not that case, despite compose.ts also rendering a sentence\n * per link. The edge is `strauss_links` in the frontmatter — the authoritative,\n * typed form — and the sentence is its rendering for a reader that only knows\n * OKF. A record can carry the frontmatter without the prose (hand-written, or\n * from a producer we did not write), so reading only the body would miss it.\n * A pair connected both ways comes back with both kinds in `via`, which is the\n * honest answer: it was declared, and it was written about.\n *\n * `body-link` and `typed-link` are DIRECTED — the edges a record itself makes,\n * read off its own body or frontmatter. `supersession`, `anchor` and `source`\n * are symmetric: they hold between two records because both name the same\n * thing, so either end sees the other. Callers wanting the inbound half of a\n * typed edge use `kb-links/` (`kb_backlinks`, `kb_impact`) rather than this\n * module, which answers \"what does this record point at\".\n */\nexport const KB_EDGE_KINDS = [\n \"body-link\",\n \"typed-link\",\n \"supersession\",\n \"anchor\",\n \"source\",\n] as const;\n\nexport type KbEdgeKind = (typeof KB_EDGE_KINDS)[number];\n\nexport type KbNeighbour = {\n record: KbRecord;\n /** Every edge kind that connects it to the record asked about. */\n via: KbEdgeKind[];\n};\n\n// The target of any markdown link whose href is a record filename:\n// `](<concept-id>.md)`. Built from the id pattern with its anchors stripped so\n// the id can be matched mid-body.\nconst BODY_LINK_TARGET = new RegExp(\n `\\\\]\\\\((${KB_CONCEPT_ID_PATTERN.source.replace(/^\\^|\\$$/g, \"\")})\\\\.md\\\\)`,\n \"g\",\n);\n\n/**\n * Which rels a `typed-link` walk may follow.\n *\n * Defaults to the whole known vocabulary — including `related_to`, since a\n * neighbourhood is the one place a bibliography belongs. It never includes an\n * unknown rel: a rel outside the vocabulary is not a claim any walk can\n * interpret, so no walk traverses it anywhere, and `kb_validate` reports it as\n * an error rather than a walk quietly acting on it.\n */\nexport const DEFAULT_TYPED_LINK_RELS: readonly string[] = KB_LINK_RELS;\n\n/**\n * Every record `from` touches, each carrying the full set of edge kinds that\n * connect the pair. Order is deterministic: bundle order per kind, kinds in\n * the order given.\n */\nexport function neighbours(\n from: KbRecord,\n bundle: KbRecord[],\n kinds: readonly KbEdgeKind[] = KB_EDGE_KINDS,\n linkRels: readonly string[] = DEFAULT_TYPED_LINK_RELS,\n): KbNeighbour[] {\n const found = new Map<string, KbNeighbour>();\n for (const kind of kinds) {\n for (const record of edgeNeighbours(from, bundle, kind, linkRels)) {\n const existing = found.get(record.conceptId);\n if (existing) {\n if (!existing.via.includes(kind)) existing.via.push(kind);\n continue;\n }\n found.set(record.conceptId, { record, via: [kind] });\n }\n }\n return [...found.values()];\n}\n\n/**\n * The records one edge kind connects `from` to, in bundle order.\n *\n * `linkRels` narrows the `typed-link` kind and is ignored by the others —\n * `trace` passes the causal rels, `pack` takes the default.\n */\nexport function edgeNeighbours(\n from: KbRecord,\n bundle: KbRecord[],\n kind: KbEdgeKind,\n linkRels: readonly string[] = DEFAULT_TYPED_LINK_RELS,\n): KbRecord[] {\n switch (kind) {\n // A link whose target is not in the bundle is legal per compose.ts —\n // records are routinely written before the ones they point at exist — so\n // missing targets are skipped, never an error.\n case \"body-link\": {\n const targets = new Set(\n [...from.body.matchAll(BODY_LINK_TARGET)].map((match) => match[1]),\n );\n if (!targets.size) return [];\n return bundle.filter(\n (candidate) =>\n candidate.conceptId !== from.conceptId &&\n targets.has(candidate.conceptId),\n );\n }\n\n // Outbound only, like `body-link`, and for the same reason: this is what\n // the record declares about itself. A missing target is legal — the walk\n // skips it, and `kb_validate` is what reports it as a warning. A rel\n // outside `linkRels` is skipped too, which is how an unknown rel stays\n // untraversable everywhere rather than one walk at a time.\n case \"typed-link\": {\n const allowed = new Set(linkRels);\n const targets = new Set(\n (from.frontmatter.strauss_links ?? [])\n .filter((link) => allowed.has(link.rel))\n .map((link) => link.target),\n );\n if (!targets.size) return [];\n return bundle.filter(\n (candidate) =>\n candidate.conceptId !== from.conceptId &&\n targets.has(candidate.conceptId),\n );\n }\n\n // Both directions and both pointers: `supersede()` writes the pair, but a\n // hand-edit can leave one side behind, and a walk trusting one pointer\n // would miss a replacement the bundle openly declares.\n case \"supersession\":\n return bundle.filter(\n (candidate) =>\n candidate.conceptId !== from.conceptId &&\n (candidate.conceptId === from.frontmatter.strauss_superseded_by ||\n from.frontmatter.strauss_supersedes?.includes(\n candidate.conceptId,\n ) ||\n candidate.frontmatter.strauss_superseded_by === from.conceptId ||\n candidate.frontmatter.strauss_supersedes?.includes(from.conceptId)),\n );\n\n // The edge that answers \"why is this code shaped this way\": every record\n // attached to the same file or symbol, whatever its standing.\n case \"anchor\": {\n const mine = from.frontmatter.strauss_anchors ?? [];\n if (!mine.length) return [];\n return bundle.filter(\n (candidate) =>\n candidate.conceptId !== from.conceptId &&\n (candidate.frontmatter.strauss_anchors ?? []).some((theirs) =>\n mine.some((ours) => anchorsTouch(ours, theirs)),\n ),\n );\n }\n\n case \"source\": {\n const mine = new Set((from.frontmatter.sources ?? []).map((s) => s.id));\n if (!mine.size) return [];\n return bundle.filter(\n (candidate) =>\n candidate.conceptId !== from.conceptId &&\n (candidate.frontmatter.sources ?? []).some((source) =>\n mine.has(source.id),\n ),\n );\n }\n }\n}\n\n/**\n * Two anchors touch when they name the same file and do not name different\n * symbols within it.\n *\n * An anchor without a symbol means \"this record is about this file\", so it\n * relates to everything anchored inside it. Requiring an exact match instead\n * would hide the file-level record from every symbol-level walk, which is the\n * direction a reviewer actually reads.\n */\nfunction anchorsTouch(\n left: { file: string; symbol?: string },\n right: { file: string; symbol?: string },\n): boolean {\n if (left.file !== right.file) return false;\n if (!left.symbol || !right.symbol) return true;\n return left.symbol === right.symbol;\n}\n","import { isCanonicalRepoUrl } from \"./anchor-resolver/index.js\";\nimport { KB_CONCEPT_ID_PATTERN, type KbRecord } from \"./kb-record.schema.js\";\nimport { isKbLinkRel, isKbRecordType, KB_LINK_RELS } from \"./record-types.js\";\n\n/** `error` fails the check; `warning` does not. */\nexport type KbValidationSeverity = \"error\" | \"warning\";\n\nexport type KbValidationProblem = {\n check: string;\n conceptId: string;\n note: string;\n severity: KbValidationSeverity;\n};\n\n/**\n * Checks that only hold across the whole bundle: whether one record's pointers\n * agree with another's. Per-record shape is the schema's job, enforced on every\n * read, so nothing here re-states it.\n */\nexport function validateBundle(records: KbRecord[]): KbValidationProblem[] {\n const byId = new Map(records.map((record) => [record.conceptId, record]));\n const problems: KbValidationProblem[] = [];\n const report = (\n check: string,\n conceptId: string,\n note: string,\n severity: KbValidationSeverity = \"error\",\n ) => problems.push({ check, conceptId, note, severity });\n\n for (const record of records) {\n const { conceptId, frontmatter: fm } = record;\n\n // OKF permits any `type`, so an unrecognised one is a note, not a failure:\n // another producer may legitimately be writing into this bundle.\n if (!isKbRecordType(fm.type)) {\n report(\"type\", conceptId, `unrecognised type \"${fm.type}\"`);\n }\n\n if (fm.strauss_status === \"superseded\") {\n const by = fm.strauss_superseded_by;\n if (!by) {\n report(\"superseded_by\", conceptId, \"superseded with no replacement\");\n } else if (!byId.has(by)) {\n report(\"superseded_by\", conceptId, `replacement ${by} is missing`);\n } else if (\n !byId.get(by)?.frontmatter.strauss_supersedes?.includes(conceptId)\n ) {\n report(\"backlink\", by, `does not list ${conceptId} in supersedes`);\n }\n }\n\n for (const old of fm.strauss_supersedes ?? []) {\n const previous = byId.get(old);\n if (!previous) {\n report(\"supersedes\", conceptId, `target ${old} is missing`);\n } else if (previous.frontmatter.strauss_status !== \"superseded\") {\n report(\"supersedes\", conceptId, `${old} is not marked superseded`);\n }\n }\n\n for (const link of fm.strauss_links ?? []) {\n // The vocabulary is closed, and this is where that is enforced. An\n // unknown rel is not a record another producer wrote in good faith the\n // way an unknown `type` is — `rel` is this package's own extension, so\n // there is no spec under which a foreign spelling is legitimate, and\n // every walk over the graph would silently skip it.\n if (!isKbLinkRel(link.rel)) {\n report(\n \"link_rel\",\n conceptId,\n `unknown rel \"${link.rel}\" on link to ${link.target} — expected one of ${KB_LINK_RELS.join(\", \")}`,\n );\n }\n\n // A target is an error or a warning depending on whether time can fix\n // it. An id that does not match the concept-id pattern can never name a\n // record — no write could produce that filename — so it is a defect\n // now and forever. A well-formed id that is simply absent is the\n // ordinary state of a base being written, and the same tolerance body\n // links already have.\n if (!KB_CONCEPT_ID_PATTERN.test(link.target)) {\n report(\n \"link_target\",\n conceptId,\n `target \"${link.target}\" is not a valid concept id — expected <type>.<slug>, both kebab-case`,\n );\n } else if (link.target === conceptId) {\n // The composer refuses this outright; reaching it means a hand-edit,\n // and a self-link is inert rather than wrong — nothing traverses it.\n report(\n \"link_target\",\n conceptId,\n `links to itself (${link.rel})`,\n \"warning\",\n );\n } else if (!byId.has(link.target)) {\n report(\n \"link_target\",\n conceptId,\n `target ${link.target} is not in the bundle`,\n \"warning\",\n );\n }\n }\n\n // A short `repo` names a repository without saying where it lives, so a\n // foreign anchor carrying one can never be fetched. A warning, not an\n // error: it still matches this root's own origin, and records are never\n // rewritten under an author.\n for (const anchor of fm.strauss_anchors ?? []) {\n // A symbol and a span are two ways to name one range, and a resolver\n // handed both has to pick — which is a guess about what the author meant.\n if (anchor.span && anchor.symbol) {\n report(\n \"anchor_span\",\n conceptId,\n `anchor ${anchor.file} names both a symbol and a span — one or the other`,\n );\n }\n\n // A backwards range resolves to nothing, and an `ast` hash over a span\n // is compared against a raw one for ever. Both only reach a bundle by\n // hand: the write schema refuses them.\n if (anchor.span && anchor.span.end < anchor.span.start) {\n report(\n \"anchor_span\",\n conceptId,\n `anchor ${anchor.file} span ${anchor.span.start}-${anchor.span.end} ends before it starts`,\n );\n }\n\n if (anchor.span && anchor.hash_kind === \"ast\") {\n report(\n \"anchor_span\",\n conceptId,\n `anchor ${anchor.file} is a span with hash_kind: \"ast\" — a span is hashed raw`,\n );\n }\n\n // Committed code has no address but a rev: without one there is nothing\n // to read the old side from, and the working tree is the wrong answer.\n if (anchor.side === \"old\" && !anchor.ref) {\n report(\n \"anchor_side\",\n conceptId,\n `anchor ${anchor.file} is side: \"old\" with no ref`,\n );\n }\n\n if (anchor.repo && !isCanonicalRepoUrl(anchor.repo)) {\n report(\n \"anchor_repo\",\n conceptId,\n `anchor repo \"${anchor.repo}\" is not a full remote URL, so it cannot be resolved against a remote`,\n \"warning\",\n );\n }\n }\n\n // An assumption with sources is a fact that forgot to change its mind.\n if (fm.strauss_assumption && fm.sources?.length) {\n report(\"assumption\", conceptId, \"marked an assumption but cites sources\");\n }\n }\n\n return problems;\n}\n","import {\n adjudicate,\n type KbStanding,\n type KbWarning,\n type KbWarningAnchor,\n} from \"./adjudicate.js\";\nimport type { KbAnchorDriftEntry } from \"./anchor-resolver/index.js\";\nimport { edgeNeighbours } from \"./kb-edges.js\";\nimport type { KbRecord, KbRecordStatus } from \"./kb-record.schema.js\";\nimport { validateBundle } from \"./validate.js\";\n\n/**\n * A health sweep over a whole base — read-only, and never a mutation.\n *\n * Every other read answers a question a caller already had. This one asks the\n * questions nobody thinks to: which records the calendar has already retired,\n * which nobody ever confirmed, which have been open long enough that \"open\" is\n * now the answer, and which the graph has quietly dropped on the floor. Those\n * decay silently, because a stale record reads exactly like a live one and a\n * question nobody answered reads exactly like one nobody asked.\n *\n * Grouped and counted rather than merged into one list: the eight checks are\n * eight different repairs — re-verify, re-date, answer, link, supersede, or\n * re-anchor — and a flat list of \"problems\" would leave the reader sorting\n * them again.\n *\n * Every group is emitted even when empty. A check that found nothing and a\n * check that never ran look identical in a report that only lists findings,\n * and the difference is the whole value of a sweep.\n */\n\nexport const DEFAULT_EXPIRING_DAYS = 30;\nexport const DEFAULT_UNVERIFIED_DAYS = 90;\nexport const DEFAULT_AGING_DAYS = 90;\n\nexport const KB_DOCTOR_CHECKS = [\n \"expired\",\n \"expiring\",\n \"unverified\",\n \"aging\",\n \"orphaned\",\n \"broken-supersession\",\n \"superseded-but-cited\",\n \"drifted\",\n \"unchecked\",\n] as const;\n\nexport type KbDoctorCheck = (typeof KB_DOCTOR_CHECKS)[number];\n\n/** What each check looks for, in the words the report prints. */\nconst CHECK_HEADLINES: Record<KbDoctorCheck, string> = {\n expired: \"past its stale_after date\",\n expiring: \"stale_after falls within the window\",\n unverified: \"nobody has ever confirmed it, and it is old enough to matter\",\n aging: \"still open or still proposed long after it was written\",\n orphaned: \"no other record links to it\",\n \"broken-supersession\": \"the supersession pointers do not resolve\",\n \"superseded-but-cited\":\n \"a live record's body links to one that no longer holds\",\n drifted: \"the code an anchor points at moved out from under its hash\",\n unchecked: \"an anchor in another repository nothing could reach\",\n};\n\nexport type KbDoctorFinding = {\n conceptId: string;\n title: string | null;\n status: KbRecordStatus;\n /** Why this record is in this group, in one phrase a reader can act on. */\n note: string;\n};\n\nexport type KbDoctorGroup = {\n check: KbDoctorCheck;\n /** What the check looks for, so a zero count still says something. */\n headline: string;\n count: number;\n findings: KbDoctorFinding[];\n};\n\nexport type KbDoctorThresholds = {\n expiringDays: number;\n unverifiedDays: number;\n agingDays: number;\n};\n\nexport type KbDoctorReport = {\n recordCount: number;\n thresholds: KbDoctorThresholds;\n counts: Record<KbDoctorCheck, number>;\n /** All eight, in `KB_DOCTOR_CHECKS` order, empty ones included. */\n groups: KbDoctorGroup[];\n findingCount: number;\n healthy: boolean;\n /**\n * Anchors carrying a hash, by the resolver that produced it. A heuristic\n * span is weaker evidence than a parsed one, so a base still leaning on the\n * regex resolver is worth re-resolving. Not a finding: a regex-stamped\n * anchor is not broken.\n */\n anchorResolvers: KbAnchorResolverCounts;\n};\n\nexport type KbAnchorResolverCounts = {\n total: number;\n treeSitter: number;\n /** Includes anchors stamped before resolvers were named. */\n regex: number;\n /** Author-given line ranges, hashed exactly as written. */\n span: number;\n /**\n * Hashed anchors read at their `ref` rather than the working tree. Counted\n * beside the resolver buckets and outside `total`: `side` is not a resolver,\n * and one of these may name a whole file.\n */\n oldSide: number;\n};\n\nexport type KbDoctorOptions = {\n /** How far ahead `expiring` looks. */\n expiringDays?: number;\n /** How old an unconfirmed record must be before `unverified` reports it. */\n unverifiedDays?: number;\n /** How long `open` or `proposed` may stand before `aging` reports it. */\n agingDays?: number;\n now?: Date;\n /**\n * Anchor drift, precomputed by the caller. `doctor` stays pure and sync for\n * the same reason `adjudicate` does — the filesystem work of re-resolving\n * anchors belongs to `detectAnchorDrift`, and a sweep with no map simply\n * reports the `drifted` check as clean rather than half-running it.\n */\n anchorDrift?: Map<string, KbAnchorDriftEntry[]>;\n};\n\nconst DAY_MS = 86_400_000;\n\n/**\n * A whole-file anchor names no resolver, so only symbol and span anchors are\n * bucketed. `oldSide` is counted beside those buckets over every hashed anchor\n * read at a `ref`, whole-file ones included — a deleted file is exactly what\n * one of those anchors is for.\n */\nfunction anchorResolverCounts(bundle: KbRecord[]): KbAnchorResolverCounts {\n let treeSitter = 0;\n let regex = 0;\n let span = 0;\n let oldSide = 0;\n for (const record of bundle) {\n for (const anchor of record.frontmatter.strauss_anchors ?? []) {\n if (!anchor.hash) continue;\n if (anchor.side === \"old\") oldSide += 1;\n if (anchor.span) span += 1;\n else if (!anchor.symbol) continue;\n else if (anchor.resolver === \"tree-sitter\") treeSitter += 1;\n else regex += 1;\n }\n }\n return { total: treeSitter + regex + span, treeSitter, regex, span, oldSide };\n}\n\nexport function doctor(\n bundle: KbRecord[],\n options: KbDoctorOptions = {},\n): KbDoctorReport {\n const thresholds: KbDoctorThresholds = {\n expiringDays: options.expiringDays ?? DEFAULT_EXPIRING_DAYS,\n unverifiedDays: options.unverifiedDays ?? DEFAULT_UNVERIFIED_DAYS,\n agingDays: options.agingDays ?? DEFAULT_AGING_DAYS,\n };\n const now = options.now ?? new Date();\n\n const adjudicated = adjudicate(bundle, bundle, now, options.anchorDrift);\n const standings = new Map<string, KbStanding>(\n adjudicated.map((hit) => [hit.record.conceptId, hit.standing]),\n );\n // Superseded and rejected records are already out of force: a replaced\n // record whose date has passed needs no repair, and reporting one would\n // bury the records that do.\n const inForce = adjudicated.filter(\n (hit) => hit.standing !== \"superseded\" && hit.standing !== \"rejected\",\n );\n\n const groups: KbDoctorGroup[] = [\n group(\"expired\", expired(inForce, now)),\n group(\"expiring\", expiring(inForce, now, thresholds.expiringDays)),\n group(\"unverified\", unverified(inForce, now, thresholds.unverifiedDays)),\n group(\"aging\", aging(inForce, now, thresholds.agingDays)),\n group(\"orphaned\", orphaned(bundle)),\n group(\"broken-supersession\", brokenSupersession(bundle, adjudicated)),\n group(\"superseded-but-cited\", supersededButCited(bundle, standings)),\n group(\"drifted\", drifted(inForce)),\n group(\"unchecked\", unchecked(inForce)),\n ];\n\n const counts = Object.fromEntries(\n groups.map((entry) => [entry.check, entry.count]),\n ) as Record<KbDoctorCheck, number>;\n const findingCount = groups.reduce((total, entry) => total + entry.count, 0);\n\n return {\n recordCount: bundle.length,\n thresholds,\n counts,\n groups,\n findingCount,\n anchorResolvers: anchorResolverCounts(bundle),\n healthy: findingCount === 0,\n };\n}\n\nfunction group(\n check: KbDoctorCheck,\n findings: KbDoctorFinding[],\n): KbDoctorGroup {\n return {\n check,\n headline: CHECK_HEADLINES[check],\n count: findings.length,\n findings,\n };\n}\n\n/**\n * An unreadable `stale_after` counts as expired rather than being skipped.\n * A date nobody can parse is a date nobody can trust, and treating it as\n * absent would silently exempt the record from the only check that ages it.\n *\n * `stale_after` is written date-only, which `Date.parse` reads as UTC\n * midnight — so a record goes stale at the start of its date, and a sweep run\n * at 00:00:00Z on that very date still counts it as expiring rather than\n * expired. That is `adjudicate`'s comparison, not a second one: two readings\n * of the same field disagreeing about the day would be worse than either.\n */\nfunction expired(\n hits: ReturnType<typeof adjudicate>,\n now: Date,\n): KbDoctorFinding[] {\n const findings: KbDoctorFinding[] = [];\n for (const hit of hits) {\n const raw = hit.record.frontmatter.stale_after;\n if (!raw) continue;\n const at = Date.parse(raw);\n if (Number.isNaN(at)) {\n findings.push(\n finding(hit.record, `stale_after \"${raw}\" is not a readable date`),\n );\n continue;\n }\n if (at < now.getTime()) {\n findings.push(\n finding(\n hit.record,\n `stale since ${raw} (${daysBetween(at, now.getTime())} days ago)`,\n ),\n );\n }\n }\n return findings;\n}\n\nfunction expiring(\n hits: ReturnType<typeof adjudicate>,\n now: Date,\n withinDays: number,\n): KbDoctorFinding[] {\n const horizon = now.getTime() + withinDays * DAY_MS;\n const findings: KbDoctorFinding[] = [];\n for (const hit of hits) {\n const raw = hit.record.frontmatter.stale_after;\n if (!raw) continue;\n const at = Date.parse(raw);\n if (Number.isNaN(at) || at < now.getTime() || at > horizon) continue;\n findings.push(\n finding(\n hit.record,\n `goes stale ${raw} (in ${daysBetween(now.getTime(), at)} days)`,\n ),\n );\n }\n return findings;\n}\n\n/**\n * Age is read from `generated.at`, so a record carrying no timestamp is not\n * reported: this check is about how long something has gone unconfirmed, and\n * without a start there is no duration. `kb_query` still warns `unverified` on\n * every such record at read time, which is where the timeless case belongs.\n */\nfunction unverified(\n hits: ReturnType<typeof adjudicate>,\n now: Date,\n olderThanDays: number,\n): KbDoctorFinding[] {\n const findings: KbDoctorFinding[] = [];\n for (const hit of hits) {\n if (hit.record.frontmatter.verified?.length) continue;\n const age = ageInDays(hit.record, now);\n if (age === null || age <= olderThanDays) continue;\n findings.push(\n finding(hit.record, `never verified, written ${age} days ago`),\n );\n }\n return findings;\n}\n\n/**\n * One group for both spellings of the same decay. An `open` question and a\n * `proposed` decision are the same debt — something was raised and never\n * settled — and splitting them would make the reader check two places for one\n * repair.\n */\nfunction aging(\n hits: ReturnType<typeof adjudicate>,\n now: Date,\n olderThanDays: number,\n): KbDoctorFinding[] {\n const findings: KbDoctorFinding[] = [];\n for (const hit of hits) {\n const status = hit.record.frontmatter.strauss_status;\n if (status !== \"open\" && status !== \"proposed\") continue;\n const age = ageInDays(hit.record, now);\n if (age === null || age <= olderThanDays) continue;\n findings.push(\n finding(\n hit.record,\n status === \"open\"\n ? `open for ${age} days`\n : `proposed ${age} days ago and still unsettled`,\n ),\n );\n }\n return findings.sort((left, right) =>\n left.conceptId.localeCompare(right.conceptId),\n );\n}\n\n/**\n * Incoming edges only, and over every record whatever its standing.\n *\n * \"Links to\" is directional: a record that cites five others and is cited by\n * none is precisely the island this names — reachable if you already know it\n * exists, which is the thing nobody does. Standing is not a filter here\n * because the question is about the graph, not about force: a rejected record\n * nothing points at is as lost as a current one.\n *\n * Supersession is read in one direction only — the replacement references what\n * it replaced, never the other way. `kb-edges` deliberately reports the pair\n * symmetrically, which is right for a walk and wrong here: taken symmetrically,\n * a dead record vouches for its own replacement, so an old→new pair nothing\n * else touches would rescue itself and never report. Read one way, the\n * replaced record stays reachable through its history and the replacement has\n * to earn its own inbound link.\n */\nfunction orphaned(bundle: KbRecord[]): KbDoctorFinding[] {\n const present = new Set(bundle.map((record) => record.conceptId));\n const referenced = new Set<string>();\n for (const record of bundle) {\n for (const neighbour of edgeNeighbours(record, bundle, \"body-link\")) {\n referenced.add(neighbour.conceptId);\n }\n // Both spellings of one statement — \"X replaced R\" — whichever side of the\n // pair stores it. Either way it is X that references R.\n for (const replaced of record.frontmatter.strauss_supersedes ?? []) {\n referenced.add(replaced);\n }\n const replacement = record.frontmatter.strauss_superseded_by;\n if (replacement && present.has(replacement)) {\n referenced.add(record.conceptId);\n }\n }\n return bundle\n .filter((record) => !referenced.has(record.conceptId))\n .map((record) => finding(record, \"no other record links to it\"));\n}\n\n/**\n * The cross-record supersession checks `validate` already owns, plus the two\n * shapes only a chain walk can see: a cycle, and a fork where two records both\n * claim to replace one. Re-deriving the first set here would give the two\n * commands room to disagree about what a broken chain is.\n *\n * \"Superseded with nothing surviving\" is not a third clause: a chain ends\n * empty only when a pointer is absent, missing, or cyclic, and all three are\n * already reported above — a second phrasing of the same defect would read as\n * two problems to repair.\n */\nconst SUPERSESSION_CHECKS = new Set([\n \"superseded_by\",\n \"supersedes\",\n \"backlink\",\n]);\n\nfunction brokenSupersession(\n bundle: KbRecord[],\n adjudicated: ReturnType<typeof adjudicate>,\n): KbDoctorFinding[] {\n const byId = new Map(bundle.map((record) => [record.conceptId, record]));\n const findings: KbDoctorFinding[] = [];\n const seen = new Set<string>();\n const add = (record: KbRecord, note: string) => {\n const key = `${record.conceptId}\\u0000${note}`;\n if (seen.has(key)) return;\n seen.add(key);\n findings.push(finding(record, note));\n };\n\n for (const problem of validateBundle(bundle)) {\n if (!SUPERSESSION_CHECKS.has(problem.check)) continue;\n const record = byId.get(problem.conceptId);\n if (record) add(record, problem.note);\n }\n\n // Both `validate` and the chain walk below reach a `strauss_superseded_by`\n // only through a record whose status is already `superseded` — so a record\n // left `accepted` while pointing at a replacement is invisible to both, and\n // adjudication reads it as current no matter what the pointer says. That is\n // precisely the hand-edit this check exists for: the store writes the status\n // and the pointer in one mutation, so the two can only disagree off-tool.\n for (const record of bundle) {\n const replacement = record.frontmatter.strauss_superseded_by;\n if (!replacement) continue;\n if (!byId.has(replacement)) {\n add(record, `replacement ${replacement} is missing`);\n } else if (record.frontmatter.strauss_status !== \"superseded\") {\n add(\n record,\n `names ${replacement} as its replacement but is not marked superseded`,\n );\n }\n }\n\n for (const hit of adjudicated) {\n for (const warning of hit.warnings) {\n if (warning.kind === \"broken-chain\") {\n add(hit.record, `replacement ${warning.missing} is missing`);\n } else if (warning.kind === \"chain-cycle\") {\n add(\n hit.record,\n `supersession chain cycles through ${warning.through.join(\" → \")}`,\n );\n } else if (warning.kind === \"forked-chain\") {\n add(\n hit.record,\n `two records claim to replace it: ${warning.heads.join(\", \")}`,\n );\n }\n }\n }\n\n return findings.sort((left, right) =>\n left.conceptId.localeCompare(right.conceptId),\n );\n}\n\n/**\n * A live record whose body points at a record that no longer holds.\n *\n * The most quietly wrong state in a base: the citing record is current, so a\n * reader trusts it, and the link reads as support for a claim its target has\n * already stopped making. One finding per pair, because each is its own edit.\n *\n * Rejected targets count as well as superseded ones. The check's name is for\n * the common case, but the failure is \"cites something that no longer holds\",\n * and a live record citing a rejected one is the worse half — a superseded\n * record at least names its replacement, while a rejected one is a well-formed\n * assertion of what someone decided *not* to do.\n *\n * A record citing the very record it replaced is exempt. That link is the\n * history working as designed — `relatedConceptIds` on a superseding write\n * renders as exactly this edge — and reporting it would put a finding on every\n * correctly performed supersession.\n */\nfunction supersededButCited(\n bundle: KbRecord[],\n standings: Map<string, KbStanding>,\n): KbDoctorFinding[] {\n const byId = new Map(bundle.map((record) => [record.conceptId, record]));\n const findings: KbDoctorFinding[] = [];\n for (const record of bundle) {\n const standing = standings.get(record.conceptId);\n if (standing === \"superseded\" || standing === \"rejected\") continue;\n for (const target of edgeNeighbours(record, bundle, \"body-link\")) {\n const targetStanding = standings.get(target.conceptId);\n if (targetStanding !== \"superseded\" && targetStanding !== \"rejected\") {\n continue;\n }\n if (replaces(record, target)) continue;\n const replacement = target.frontmatter.strauss_superseded_by;\n findings.push(\n finding(\n record,\n `cites ${targetStanding} ${target.conceptId}${\n targetStanding === \"superseded\" &&\n replacement &&\n byId.has(replacement)\n ? ` — replaced by ${replacement}`\n : \"\"\n }`,\n ),\n );\n }\n }\n return findings;\n}\n\n/**\n * Records whose anchors no longer resolve to the code they were hashed\n * against — read off the `drifted` warning `adjudicate` already attaches, so\n * the sweep and every read path agree about what drift is. Recomputing the\n * comparison here would give the two room to disagree.\n *\n * In-force records only. A superseded record anchoring code that has since\n * moved is the expected outcome of it being replaced, not a repair.\n *\n * Unresolvable anchors ride in this group rather than a check of their own:\n * the repair is the same edit, and the note says which happened.\n */\nfunction drifted(hits: ReturnType<typeof adjudicate>): KbDoctorFinding[] {\n return anchorFindings(hits, \"drifted\", (count) =>\n count === 1 ? \"anchor no longer matches\" : \"anchors no longer match\",\n );\n}\n\n/**\n * Anchors in another repository that nothing could read — unreachable, refused,\n * or offline. Its own group because the repair is not an edit to the record:\n * a reader who cannot tell \"unchecked\" from \"clean\" trusts a base nobody\n * checked.\n */\nfunction unchecked(hits: ReturnType<typeof adjudicate>): KbDoctorFinding[] {\n return anchorFindings(hits, \"unchecked\", (count) =>\n count === 1 ? \"anchor was not checked\" : \"anchors were not checked\",\n );\n}\n\n/** Anchor findings grouped by repository, so one unreachable remote reads as one cause. */\nfunction anchorFindings(\n hits: ReturnType<typeof adjudicate>,\n kind: \"drifted\" | \"unchecked\",\n headline: (count: number) => string,\n): KbDoctorFinding[] {\n const findings: KbDoctorFinding[] = [];\n for (const hit of hits) {\n const warning = hit.warnings.find(\n (entry): entry is Extract<KbWarning, { anchors: KbWarningAnchor[] }> =>\n entry.kind === kind,\n );\n if (!warning) continue;\n const byRepo = new Map<string, string[]>();\n for (const anchor of warning.anchors) {\n const repo = anchor.repo ?? \"\";\n byRepo.set(repo, [...(byRepo.get(repo) ?? []), describeAnchor(anchor)]);\n }\n const detail = [...byRepo.entries()].map(([repo, entries]) =>\n repo ? `${repo}: ${entries.join(\", \")}` : entries.join(\", \"),\n );\n findings.push(\n finding(\n hit.record,\n `${warning.anchors.length} ${headline(warning.anchors.length)}: ${detail.join(\"; \")}`,\n ),\n );\n }\n return findings.sort((left, right) =>\n left.conceptId.localeCompare(right.conceptId),\n );\n}\n\nfunction describeAnchor(anchor: KbWarningAnchor): string {\n const at = anchor.symbol ? `${anchor.file}:${anchor.symbol}` : anchor.file;\n if (anchor.class === \"gone\") {\n return `${at} gone${anchor.reason ? ` (${anchor.reason})` : \"\"}`;\n }\n if (anchor.reason) return `${at} (${anchor.reason})`;\n if (anchor.remoteState === \"drifted-on-default\") {\n return `${at} (matches ref, moved on the default branch)`;\n }\n if (anchor.diffSize === null) return `${at} (changed, size unrecorded)`;\n // A same-size rewrite is the drift most worth naming plainly:\n // \"0 lines apart\" reads as \"nothing happened\".\n return anchor.diffSize === 0\n ? `${at} (content changed, same line count)`\n : `${at} (${anchor.diffSize} line${anchor.diffSize === 1 ? \"\" : \"s\"} apart)`;\n}\n\n/** Either pointer saying `later` is what stands in `earlier`'s place. */\nfunction replaces(later: KbRecord, earlier: KbRecord): boolean {\n return (\n (later.frontmatter.strauss_supersedes ?? []).includes(earlier.conceptId) ||\n earlier.frontmatter.strauss_superseded_by === later.conceptId\n );\n}\n\nfunction finding(record: KbRecord, note: string): KbDoctorFinding {\n return {\n conceptId: record.conceptId,\n title: record.frontmatter.title ?? null,\n status: record.frontmatter.strauss_status,\n note,\n };\n}\n\n/** Whole days between two instants, never negative. */\nfunction daysBetween(from: number, to: number): number {\n return Math.max(0, Math.floor((to - from) / DAY_MS));\n}\n\nfunction ageInDays(record: KbRecord, now: Date): number | null {\n const at = record.frontmatter.generated?.at;\n if (!at) return null;\n const written = Date.parse(at);\n if (Number.isNaN(written)) return null;\n return daysBetween(written, now.getTime());\n}\n","import type {\n KbLink,\n KbRecord,\n KbRecordFrontmatter,\n KbRecordStatus,\n} from \"../../kb-record.schema.js\";\nimport { isKbLinkRel, LINK_RELS } from \"../../record-types.js\";\nimport type { KbDroppedLink } from \"./model.js\";\n\n/** The source entry a promotion adds, replaced rather than repeated on re-promote. */\nexport const PROMOTION_SOURCE_ID = \"promoted\";\n\n/**\n * The status a copy is written under: settling is what promotion means, so the\n * unsettled statuses land `accepted` while `open` and `resolved` carry\n * unchanged. `rejected` and `superseded` never reach here — `promote` refuses\n * them.\n */\nconst CARRIED_STATUS: Record<KbRecordStatus, KbRecordStatus> = {\n draft: \"accepted\",\n proposed: \"accepted\",\n accepted: \"accepted\",\n open: \"open\",\n resolved: \"resolved\",\n rejected: \"rejected\",\n superseded: \"superseded\",\n};\n\nexport type KbCarriedRecord = {\n frontmatter: Omit<KbRecordFrontmatter, \"type\">;\n body: string;\n droppedLinks: KbDroppedLink[];\n};\n\n/**\n * One record as the target base should hold it.\n *\n * Frontmatter is carried rather than recomposed: OKF requires a consumer to\n * preserve keys it does not recognise when round-tripping, and a record written\n * by another producer would lose them to a rebuild from known fields.\n */\nexport function carry(\n record: KbRecord,\n promoted: ReadonlySet<string>,\n source?: string,\n): KbCarriedRecord {\n const {\n type: _type,\n // Both name records in the source base, and supersession in the target is\n // a separate question from whether this record belongs there at all.\n strauss_supersedes: _supersedes,\n strauss_superseded_by: _supersededBy,\n // A check run against the source repository, which the target never saw.\n verified: _verified,\n ...rest\n } = record.frontmatter;\n\n const links = rest.strauss_links ?? [];\n const kept = links.filter((link) => promoted.has(link.target));\n const dropped = links.filter((link) => !promoted.has(link.target));\n const tags = (rest.tags ?? []).filter((tag) => !isReviewTag(tag));\n\n const frontmatter: Omit<KbRecordFrontmatter, \"type\"> = {\n ...rest,\n strauss_status: CARRIED_STATUS[rest.strauss_status],\n };\n setOrDrop(frontmatter, \"tags\", tags);\n setOrDrop(frontmatter, \"strauss_links\", kept);\n\n let body = withoutLinkSentences(record.body, dropped);\n if (source) {\n frontmatter.sources = [\n ...(rest.sources ?? []).filter(\n (entry) => entry.id !== PROMOTION_SOURCE_ID,\n ),\n { id: PROMOTION_SOURCE_ID, resource: source },\n ];\n body = `${stripFootnote(body).trimEnd()}\\n\\n[^${PROMOTION_SOURCE_ID}]: ${source}\\n`;\n }\n\n return {\n frontmatter,\n body,\n droppedLinks: dropped.map(({ target, rel }) => ({ target, rel })),\n };\n}\n\n/**\n * `review` and the `review:<id>` family alike: the target base is not a review\n * base, so a tag saying which review wrote the record no longer selects\n * anything there.\n */\nexport function isReviewTag(tag: string): boolean {\n return tag === \"review\" || tag.startsWith(\"review:\");\n}\n\n/**\n * Removes the prose `compose.ts` renders for a link, alongside the link itself.\n * A body claiming an edge the frontmatter dropped is the one inconsistency the\n * two-place spelling of an edge can produce.\n */\nfunction withoutLinkSentences(body: string, dropped: KbLink[]): string {\n const sentences = new Set(\n dropped\n .filter((link) => isKbLinkRel(link.rel))\n .map(\n (link) =>\n `${LINK_RELS[link.rel as keyof typeof LINK_RELS].phrase} [${link.target}](${link.target}.md).`,\n ),\n );\n if (!sentences.size) return body;\n return body\n .split(\"\\n\\n\")\n .filter((block) => !sentences.has(block.trim()))\n .join(\"\\n\\n\");\n}\n\n/** The footnote a previous promotion left, so re-promoting does not stack them. */\nfunction stripFootnote(body: string): string {\n return body\n .split(\"\\n\")\n .filter((line) => !line.startsWith(`[^${PROMOTION_SOURCE_ID}]: `))\n .join(\"\\n\");\n}\n\nfunction setOrDrop<Key extends \"tags\" | \"strauss_links\">(\n frontmatter: Omit<KbRecordFrontmatter, \"type\">,\n key: Key,\n value: NonNullable<KbRecordFrontmatter[Key]>,\n): void {\n if (value.length) frontmatter[key] = value;\n else delete frontmatter[key];\n}\n","import type { KbRecord } from \"../kb-record.schema.js\";\nimport type { KbInboundEdge } from \"./model.js\";\n\n/**\n * The whole bundle's typed edges, indexed by target — built once per call, so a\n * walk stays linear in the bundle rather than quadratic. Order is `list()`'s\n * own, then each record's declared link order, so repeated runs agree.\n */\nexport function inboundIndex(bundle: KbRecord[]): Map<string, KbInboundEdge[]> {\n const byTarget = new Map<string, KbInboundEdge[]>();\n\n for (const record of bundle) {\n for (const link of record.frontmatter.strauss_links ?? []) {\n // A record naming itself is a no-op, not an error, for the same reason\n // `supersedes` treats it that way: the claim is already true.\n if (link.target === record.conceptId) continue;\n\n const edges = byTarget.get(link.target) ?? [];\n // The same pair stated twice says nothing twice.\n if (\n edges.some(\n (edge) => edge.from === record.conceptId && edge.rel === link.rel,\n )\n ) {\n continue;\n }\n edges.push({ from: record.conceptId, rel: link.rel });\n byTarget.set(link.target, edges);\n }\n }\n\n return byTarget;\n}\n","import { adjudicate } from \"../adjudicate.js\";\nimport { KbRecordNotFoundError } from \"../kb-errors.js\";\nimport type { KbRecord } from \"../kb-record.schema.js\";\nimport { inboundIndex } from \"./inbound.js\";\nimport type { KbBacklink, KbBacklinksResult } from \"./model.js\";\n\n/**\n * Every edge the bundle holds against this id: one hop, every rel including\n * `related_to`, each row carrying the standing of the record that made it.\n * Flat and factual, where `impact` answers the causal, transitive question.\n */\nexport function backlinks(\n targetId: string,\n bundle: KbRecord[],\n): KbBacklinksResult {\n const byId = new Map(bundle.map((record) => [record.conceptId, record]));\n if (!byId.has(targetId)) throw new KbRecordNotFoundError(targetId);\n\n const standingOf = new Map(\n adjudicate(bundle, bundle).map((hit) => [hit.record.conceptId, hit]),\n );\n\n const rows: KbBacklink[] = [];\n for (const edge of inboundIndex(bundle).get(targetId) ?? []) {\n const record = byId.get(edge.from);\n if (!record) continue;\n const hit = standingOf.get(edge.from);\n rows.push({\n ...edge,\n title: record.frontmatter.title ?? null,\n standing: hit?.standing ?? \"unsettled\",\n warnings: hit?.warnings ?? [],\n });\n }\n\n return {\n target: targetId,\n backlinks: rows.sort(\n (left, right) =>\n left.from.localeCompare(right.from) ||\n left.rel.localeCompare(right.rel),\n ),\n };\n}\n","import { adjudicate, type KbAdjudicated } from \"../adjudicate.js\";\nimport { KbRecordNotFoundError, KbUnknownLinkRelError } from \"../kb-errors.js\";\nimport type { KbRecord } from \"../kb-record.schema.js\";\nimport {\n isKbLinkRel,\n KB_CAUSAL_LINK_RELS,\n LINK_RELS,\n} from \"../record-types.js\";\nimport { inboundIndex } from \"./inbound.js\";\nimport type {\n KbImpactOptions,\n KbImpactResult,\n KbImpactedRecord,\n KbLinkEdge,\n} from \"./model.js\";\n\n/**\n * The transitive set of *dependants*, not the set of inbound edges: each rel is\n * followed in its own direction of dependence. `related_to` and unknown rels\n * propagate nothing. A superseded or rejected record is reported, then not\n * walked through. A record expands once, so cycles terminate.\n */\nexport function impact(\n targetId: string,\n bundle: KbRecord[],\n options: KbImpactOptions = {},\n): KbImpactResult {\n const byId = new Map(bundle.map((record) => [record.conceptId, record]));\n if (!byId.has(targetId)) throw new KbRecordNotFoundError(targetId);\n\n const rels = resolveRels(options.rels);\n const maxDepth = options.depth ?? Number.POSITIVE_INFINITY;\n const inbound = inboundIndex(bundle);\n\n // Adjudicated once over the whole bundle: standing must not depend on\n // whether a record's replacement happened to be within the walk.\n const standingOf = new Map<string, KbAdjudicated>(\n adjudicate(bundle, bundle).map((hit) => [hit.record.conceptId, hit]),\n );\n\n const reached = new Map<string, KbImpactedRecord>();\n const stopped: string[] = [];\n let frontier = [targetId];\n let depth = 0;\n\n while (frontier.length && depth < maxDepth) {\n depth += 1;\n const next: string[] = [];\n\n const consider = (dependantId: string, edge: KbLinkEdge) => {\n // The root is the question, not an answer to it.\n if (dependantId === targetId) return;\n\n const existing = reached.get(dependantId);\n if (existing) {\n if (!hasEdge(existing.via, edge)) existing.via.push(edge);\n return;\n }\n\n const record = byId.get(dependantId);\n // An edge naming a record that is not in the bundle is routine — records\n // are written before the ones they point at — and `kb_validate` is what\n // reports it. Nothing to report as impacted, so nothing is invented.\n if (!record) return;\n\n const hit = standingOf.get(dependantId);\n const entry: KbImpactedRecord = {\n conceptId: dependantId,\n title: record.frontmatter.title ?? null,\n standing: hit?.standing ?? \"unsettled\",\n warnings: hit?.warnings ?? [],\n depth,\n via: [edge],\n };\n reached.set(dependantId, entry);\n\n if (entry.standing === \"superseded\" || entry.standing === \"rejected\") {\n stopped.push(dependantId);\n return;\n }\n next.push(dependantId);\n };\n\n for (const id of frontier) {\n // Inbound: someone points at me with a rel whose dependant is the source.\n for (const edge of inbound.get(id) ?? []) {\n if (!rels.has(edge.rel)) continue;\n if (dependantEnd(edge.rel) !== \"source\") continue;\n consider(edge.from, { source: edge.from, target: id, rel: edge.rel });\n }\n\n // Outbound: I point at someone with a rel whose dependant is the target.\n for (const link of byId.get(id)?.frontmatter.strauss_links ?? []) {\n if (!rels.has(link.rel)) continue;\n if (dependantEnd(link.rel) !== \"target\") continue;\n if (link.target === id) continue;\n consider(link.target, {\n source: id,\n target: link.target,\n rel: link.rel,\n });\n }\n }\n\n frontier = next;\n }\n\n return {\n root: targetId,\n impacted: [...reached.values()].sort(\n (left, right) =>\n left.depth - right.depth ||\n left.conceptId.localeCompare(right.conceptId),\n ),\n stopped: stopped.sort(),\n truncated: frontier.length > 0,\n unexpanded: [...frontier].sort(),\n };\n}\n\n/**\n * The caller's `rels`, checked at the library boundary.\n *\n * A rel the walk cannot follow is an error, not an empty result: the two are\n * indistinguishable to a caller, and \"nothing breaks\" is the most dangerous\n * answer this function can return.\n */\nfunction resolveRels(rels: readonly string[] | undefined): Set<string> {\n if (!rels?.length) return new Set<string>(KB_CAUSAL_LINK_RELS);\n for (const rel of rels) {\n if (!isKbLinkRel(rel) || LINK_RELS[rel].dependant === null) {\n throw new KbUnknownLinkRelError(rel, KB_CAUSAL_LINK_RELS);\n }\n }\n return new Set(rels);\n}\n\n/** Which end of a stored rel depends on the other. `null` for anything inert. */\nfunction dependantEnd(rel: string): \"source\" | \"target\" | null {\n return isKbLinkRel(rel) ? LINK_RELS[rel].dependant : null;\n}\n\nfunction hasEdge(edges: KbLinkEdge[], edge: KbLinkEdge): boolean {\n return edges.some(\n (existing) =>\n existing.source === edge.source &&\n existing.target === edge.target &&\n existing.rel === edge.rel,\n );\n}\n","import { adjudicate, type KbStanding } from \"../../adjudicate.js\";\nimport type { KbRecord } from \"../../kb-record.schema.js\";\n\n/**\n * Standings a promotion neither lists nor carries: the record has been withdrawn\n * where it was written, and the target base holds no chain that says so.\n */\nconst WITHDRAWN: readonly KbStanding[] = [\"superseded\", \"rejected\"];\n\n/** Adjudicated standing per concept id, over the whole source base. */\nexport function standings(bundle: KbRecord[]): Map<string, KbStanding> {\n return new Map(\n adjudicate(bundle, bundle).map((hit) => [\n hit.record.conceptId,\n hit.standing,\n ]),\n );\n}\n\nexport function isWithdrawn(standing: KbStanding | undefined): boolean {\n return standing !== undefined && WITHDRAWN.includes(standing);\n}\n","import { isNoDecisionRecord } from \"../../decision-record.js\";\nimport { inboundIndex } from \"../../kb-links/index.js\";\nimport type { KbInboundEdge } from \"../../kb-links/index.js\";\nimport type { KbRecord, KbRecordStatus } from \"../../kb-record.schema.js\";\nimport type { KbPromoteCandidate } from \"./model.js\";\nimport { isWithdrawn, standings } from \"./standing.js\";\n\n/**\n * The bare tag, not the `review:<id>` family. `review` says the record is still\n * under review; `review:pr-59` only says which review wrote it, and every\n * record in a review base carries one.\n */\nconst REVIEW_TAG = \"review\";\n\n/** A risk nobody has to carry forward. */\nconst SETTLED: readonly KbRecordStatus[] = [\"resolved\"];\n\n/**\n * What in a review base is worth keeping once the change merges. Heuristics over\n * what a reviewer usually wants; a record they cut is still nameable by hand.\n * A withdrawn record is not among them — `promote` refuses those outright.\n */\nexport function promoteCandidates(bundle: KbRecord[]): KbPromoteCandidate[] {\n const inbound = inboundIndex(bundle);\n const standing = standings(bundle);\n const rows: KbPromoteCandidate[] = [];\n\n for (const record of bundle) {\n if (isWithdrawn(standing.get(record.conceptId))) continue;\n const why = candidateReason(record, inbound.get(record.conceptId) ?? []);\n if (!why) continue;\n rows.push({\n conceptId: record.conceptId,\n type: recordType(record.conceptId),\n title: record.frontmatter.title ?? null,\n why,\n });\n }\n return rows;\n}\n\nfunction candidateReason(\n record: KbRecord,\n inbound: KbInboundEdge[],\n): string | null {\n const { strauss_status: status, tags } = record.frontmatter;\n\n switch (recordType(record.conceptId)) {\n case \"decision\":\n if (isNoDecisionRecord(record)) return null;\n return tags?.includes(REVIEW_TAG)\n ? null\n : \"decision no longer under review\";\n case \"constraint\":\n return status === \"proposed\"\n ? \"constraint still proposed — the target base is where it settles\"\n : null;\n case \"contract\":\n return \"contract — it outlives the change that introduced it\";\n case \"requirement\":\n return inbound.some((edge) => edge.rel === \"satisfies\")\n ? \"requirement something in the base satisfies\"\n : null;\n case \"risk\":\n return record.frontmatter.strauss_materiality === \"blocking\" &&\n !SETTLED.includes(status)\n ? \"blocking risk still open\"\n : null;\n default:\n return null;\n }\n}\n\nfunction recordType(conceptId: string): string {\n return conceptId.slice(0, conceptId.indexOf(\".\"));\n}\n","import { z } from \"zod\";\nimport { bundlePath, conceptId } from \"../model.js\";\n\n/**\n * Listing candidates and promoting share one input, and the two need different\n * arguments. The rule lives here rather than in `run` so both surfaces refuse\n * the same call: the CLI before it dispatches, MCP before the tool runs.\n */\nexport const promoteInputSchema = z\n .object({\n bundlePath,\n conceptIds: z\n .array(conceptId)\n .max(64)\n .optional()\n .describe(\"Records to copy into the target base. Omit with `list`.\"),\n to: z\n .string()\n .min(1)\n .optional()\n .describe(\"Absolute path to the base being promoted into.\"),\n source: z\n .string()\n .min(1)\n .optional()\n .describe(\n \"Where the promotion came from, usually the pull request URL. Recorded on each copy as a source.\",\n ),\n force: z\n .boolean()\n .optional()\n .describe(\"Overwrite a record the target base already holds.\"),\n list: z\n .boolean()\n .optional()\n .describe(\"List the source base's candidates instead of promoting.\"),\n })\n .refine((input) => input.list === true || input.to !== undefined, {\n message: \"promote needs a target base — pass --to <bundle>, or --list\",\n path: [\"to\"],\n })\n .refine(\n (input) => input.list === true || (input.conceptIds?.length ?? 0) > 0,\n {\n message: \"name at least one concept id to promote, or pass --list\",\n path: [\"conceptIds\"],\n },\n );\n\n/** A typed link the copy does not carry, because its target stayed behind. */\nexport type KbDroppedLink = { target: string; rel: string };\n\nexport type KbPromotedRecord = {\n conceptId: string;\n droppedLinks: KbDroppedLink[];\n};\n\nexport type KbPromoteCandidate = {\n conceptId: string;\n type: string;\n title: string | null;\n /** The rule that made it a candidate, in the reader's terms. */\n why: string;\n};\n\nexport type KbPromoteResult =\n | { mode: \"list\"; candidates: KbPromoteCandidate[] }\n | { mode: \"promote\"; to: string; promoted: KbPromotedRecord[] };\n","import { resolve } from \"node:path\";\nimport {\n KbInvalidConceptIdError,\n KbPromoteCollisionError,\n KbPromoteSelfError,\n KbPromoteStandingError,\n KbPromoteStoppedError,\n KbRecordNotFoundError,\n} from \"../../kb-errors.js\";\nimport { assertBaseNotFrozen } from \"../../kb-pins/index.js\";\nimport { KB_SLUG_PATTERN } from \"../../kb-record.schema.js\";\nimport { argvFlag, define } from \"../model.js\";\nimport { carry } from \"./carry.js\";\nimport { promoteCandidates } from \"./candidates.js\";\nimport {\n promoteInputSchema,\n type KbPromoteResult,\n type KbPromotedRecord,\n} from \"./model.js\";\nimport { isWithdrawn, standings } from \"./standing.js\";\n\nexport const promoteCommand = define({\n name: \"promote\",\n tool: \"kb_promote\",\n usage:\n \"promote <concept-id...> --to <bundle> [--source <url>] [--force] | --list\",\n description:\n \"Copy records into another base at the same slug, with the review tags dropped and a source naming where the promotion came from. Use at merge, to lift what a review base settled into the base that outlives it. `list` names the candidates instead. The originals stay put.\",\n input: promoteInputSchema,\n fromArgv: (argv, path) => {\n const to = argvFlag(argv, \"--to\");\n const source = argvFlag(argv, \"--source\");\n // Flag values sit in argv where the concept ids do, so a run that did not\n // strip them would try to promote a record named after a URL.\n const words = argv.slice(1);\n for (const flag of [\"--to\", \"--source\"]) {\n const at = words.indexOf(flag);\n if (at !== -1) words.splice(at, 2);\n }\n const conceptIds = words.filter((word) => !word.startsWith(\"--\"));\n\n return {\n bundlePath: path,\n ...(conceptIds.length ? { conceptIds } : {}),\n ...(to !== undefined ? { to } : {}),\n ...(source !== undefined ? { source } : {}),\n ...(argv.includes(\"--force\") ? { force: true } : {}),\n ...(argv.includes(\"--list\") ? { list: true } : {}),\n };\n },\n run: async (\n { store, actor },\n { bundlePath: path, conceptIds, to, source, force, list },\n ): Promise<KbPromoteResult> => {\n // Both bases are logged and compared, so both are resolved before either is\n // written to or named in a log line.\n const from = resolve(path);\n const bundle = await store.list(from);\n if (list) {\n return { mode: \"list\", candidates: promoteCandidates(bundle) };\n }\n\n // Narrowed here rather than in the signature: the schema already refuses\n // the absent case, and the two modes share one input object.\n const target = resolve(to as string);\n if (target === from) throw new KbPromoteSelfError(target);\n\n // Every refusal happens here, before the first write: a run that stopped at\n // its own pre-flight would leave the target holding part of a change.\n const named = (conceptIds ?? []).map(namedRecord);\n const wanted = named.map(({ conceptId, type, slug }) => {\n const record = bundle.find((entry) => entry.conceptId === conceptId);\n if (!record) throw new KbRecordNotFoundError(conceptId);\n return { record, type, slug };\n });\n\n // The source takes `promote-out` lines and possibly a `.gitattributes`, so\n // a frozen source base refuses the run as surely as a frozen target.\n await assertBaseNotFrozen(process.cwd(), from);\n await assertBaseNotFrozen(process.cwd(), target);\n\n const standing = standings(bundle);\n for (const { record } of wanted) {\n const where = standing.get(record.conceptId);\n if (isWithdrawn(where)) {\n throw new KbPromoteStandingError(record.conceptId, where as string);\n }\n if (!force && (await store.read(target, record.conceptId))) {\n throw new KbPromoteCollisionError(record.conceptId, target);\n }\n }\n\n const promotedIds = new Set(wanted.map(({ record }) => record.conceptId));\n const promoted: KbPromotedRecord[] = [];\n for (const { record, type, slug } of wanted) {\n const { frontmatter, body, droppedLinks } = carry(\n record,\n promotedIds,\n source,\n );\n try {\n await store.write(\n target,\n { type, slug, frontmatter, body, overwrite: force === true },\n actor,\n );\n } catch (error) {\n throw new KbPromoteStoppedError(\n record.conceptId,\n promoted.map((entry) => entry.conceptId),\n error instanceof Error ? error.message : \"unknown\",\n );\n }\n // Both bases, because neither can answer on its own: the source keeps no\n // trace of a copy, and the target keeps no trace of where it came from.\n await store.note(target, {\n by: actor,\n operation: \"promote-in\",\n conceptId: record.conceptId,\n target: from,\n });\n await store.note(from, {\n by: actor,\n operation: \"promote-out\",\n conceptId: record.conceptId,\n target,\n });\n promoted.push({ conceptId: record.conceptId, droppedLinks });\n }\n\n return { mode: \"promote\", to: target, promoted };\n },\n render: (result) => renderPromote(result as KbPromoteResult),\n});\n\n/**\n * The `<type>.<slug>` split `KbStore.write` will accept, checked here so a\n * malformed id in the list fails the run before the earlier ids are written.\n */\nfunction namedRecord(conceptId: string): {\n conceptId: string;\n type: string;\n slug: string;\n} {\n const at = conceptId.indexOf(\".\");\n const type = at === -1 ? conceptId : conceptId.slice(0, at);\n const slug = at === -1 ? \"\" : conceptId.slice(at + 1);\n if (!KB_SLUG_PATTERN.test(type) || !KB_SLUG_PATTERN.test(slug)) {\n throw new KbInvalidConceptIdError(\n \"concept id must be <type>.<slug>, both kebab-case\",\n { conceptId },\n );\n }\n return { conceptId, type, slug };\n}\n\nexport function renderPromote(result: KbPromoteResult): string {\n if (result.mode === \"list\") {\n if (!result.candidates.length) return \"No promotion candidates.\";\n return result.candidates\n .flatMap((candidate) => [\n `${candidate.conceptId} [${candidate.type}]${\n candidate.title ? ` — ${candidate.title}` : \"\"\n }`,\n ` ${candidate.why}`,\n ])\n .join(\"\\n\");\n }\n\n const lines = [\n `Promoted ${result.promoted.length} record${\n result.promoted.length === 1 ? \"\" : \"s\"\n } into ${result.to}.`,\n ];\n for (const entry of result.promoted) {\n lines.push(`- ${entry.conceptId}`);\n for (const link of entry.droppedLinks) {\n lines.push(\n ` dropped ${link.rel} → ${link.target} (not promoted in this run)`,\n );\n }\n }\n return lines.join(\"\\n\");\n}\n","import { z } from \"zod\";\nimport { kbAnchorLocatorSchema } from \"./kb-record.schema.js\";\n\nexport const LOG_FILE = \"log.jsonl\";\n\n/**\n * One pointer change, as an `anchor-set` entry records it: `from` for a move or\n * a drop, `to` for a move or an addition. Locators only — the log says which\n * pointer moved, never what it was hashed against. Derived from the record\n * before and after, so it reports what happened rather than what was asked.\n */\nexport const kbLogAnchorChangeSchema = z\n .object({\n op: z.enum([\"move\", \"add\", \"drop\"]),\n from: kbAnchorLocatorSchema.optional(),\n to: kbAnchorLocatorSchema.optional(),\n })\n .strict();\n\nconst kbLogEntryFields = z.object({\n // Validated, not just `min(1)`: `at` is a sort key (see `parseLog`\n // below), and a value that isn't actually chronological — a Unix\n // timestamp, a human-typed date, garbage — would sort wrong without\n // ever failing to parse. `z.iso.datetime()` accepts exactly what\n // `record()` writes (`Date#toISOString()`: full precision, `Z` offset)\n // and rejects everything else, including a non-`Z` offset — so a\n // malformed `at` is reported the same way a malformed line already is,\n // rather than silently sorting into the wrong place.\n at: z.iso.datetime(),\n by: z.string().min(1),\n operation: z.string().min(1),\n conceptId: z.string().min(1),\n /**\n * The operation's other end, where it has one: a second concept id for\n * supersession, the other base's path for promotion.\n */\n target: z.string().min(1).optional(),\n /**\n * Why the operation was performed, where the operation demands one.\n * `anchor-set` does: a pointer moved by a reader is only auditable if\n * the reading is recorded beside it.\n */\n reason: z.string().min(1).optional(),\n /** What `anchor-set` changed, derived from the record before and after. */\n anchors: z.array(kbLogAnchorChangeSchema).optional(),\n});\n\n/**\n * Read-side, and tolerant of a key it has never heard of: one base is read by\n * every version that touches the repository, so a log has to read *forward*.\n * Under `.strict()` the first version to add a field turned its own entries\n * into `malformed` for every older reader — the entries an audit most needs\n * were the only ones that vanished. A line missing a required field, or\n * carrying an `at` that is not an ISO datetime, is still malformed.\n */\nexport const kbLogEntrySchema = kbLogEntryFields.passthrough();\n\n/** Write-side: this package controls exactly what it appends. */\nexport const kbLogEntryWriteSchema = kbLogEntryFields.strict();\n\nexport type KbLogEntry = z.infer<typeof kbLogEntryFields>;\nexport type KbLogAnchorChange = z.infer<typeof kbLogAnchorChangeSchema>;\n\n/**\n * The log is the bundle's only primary artifact, and the reason it is handled\n * unlike `INDEX.md`.\n *\n * The index is derived: lose it and the records rebuild it. The log records\n * events — which agent wrote what, and when — that leave no trace in the record\n * set, so it cannot be regenerated from anything. Repair therefore means detect\n * and report, never rewrite: rewriting an append-only log destroys the only\n * copy of what it holds.\n *\n * JSONL rather than a markdown list. An earlier version rendered entries as\n * `- <at> · <by> · <op> · <id>` and parsed them by splitting on the separator —\n * a hand-written parser for a format invented here, which fails the first time\n * a value contains the separator. JSON needs no parser and the schema below\n * needs no separator to be unambiguous. Humans read the log through\n * `strauss-kb log`, as they read everything else.\n *\n * One line per entry, appended with `O_APPEND`: POSIX makes the offset update\n * atomic, and writes this size do not interleave on a local filesystem.\n */\nexport function renderLogEntry(entry: KbLogEntry): string {\n return `${JSON.stringify(kbLogEntryWriteSchema.parse(entry))}\\n`;\n}\n\nexport type KbLogReadResult = {\n entries: KbLogEntry[];\n /** Lines that did not parse, with their 1-based position. Never rewritten. */\n malformed: { line: number; text: string }[];\n /** Whether the file still carried merge conflict markers. */\n conflicted: boolean;\n};\n\n/**\n * GitHub's merge button ignores `.gitattributes`, so a pull request that\n * touches the log from both sides lands conflict markers in it. Both sides'\n * entries are real; the markers are not, and reading past them keeps `kb_log`\n * working on a file nobody has resolved yet. `|||||||` is diff3's base\n * section, which `merge.conflictStyle` adds to the other three.\n */\nconst CONFLICT_MARKER = /^(<{7}|\\|{7}|={7}|>{7})/;\n\nexport function parseLog(raw: string): KbLogReadResult {\n const entries: KbLogEntry[] = [];\n const malformed: { line: number; text: string }[] = [];\n const seen = new Set<string>();\n let conflicted = false;\n\n raw.split(\"\\n\").forEach((text, index) => {\n if (!text.trim()) return;\n if (CONFLICT_MARKER.test(text)) {\n conflicted = true;\n return;\n }\n let value: unknown;\n try {\n value = JSON.parse(text) as unknown;\n } catch {\n malformed.push({ line: index + 1, text });\n return;\n }\n const parsed = kbLogEntrySchema.safeParse(value);\n if (!parsed.success) {\n malformed.push({ line: index + 1, text });\n return;\n }\n\n // A union merge keeps both sides' lines even when a line appears on\n // both — a cherry-pick or rebase that carried one worktree's entry into\n // the other's history before the merge produces two byte-identical\n // lines for what was genuinely one event. Dropping the repeat is the\n // right read here: two writers independently logging the *same*\n // `at`/`by`/`operation`/`conceptId`/`target` is not a real scenario\n // `record()` can produce (each call mints its own `at`), so an exact\n // duplicate is merge residue, not two events that happen to coincide.\n // A near-duplicate (same fields but a different `at`) is left alone —\n // that is two genuine events and both stay.\n const key = JSON.stringify(parsed.data);\n if (seen.has(key)) return;\n seen.add(key);\n\n entries.push(parsed.data);\n });\n\n // A union merge (see `kb-gitattributes.ts`) interleaves two worktrees'\n // appends by whatever order git's merge happened to visit them in, not by\n // when each entry was actually written. Sorting on `at` here means line\n // order in the file is never load-bearing — only the timestamp is. `at` is\n // `Date#toISOString`, so lexicographic order is chronological order; the\n // sort is stable, so entries that share a timestamp keep their file order.\n entries.sort((left, right) =>\n left.at < right.at ? -1 : left.at > right.at ? 1 : 0,\n );\n\n return { entries, malformed, conflicted };\n}\n","import { z } from \"zod\";\nimport { composeInputSchema } from \"./compose.js\";\nimport { kbLogEntrySchema } from \"./kb-log.js\";\nimport { kbRecordFrontmatterSchema } from \"./kb-record.schema.js\";\n\n/**\n * The frontmatter contract, emitted rather than restated.\n *\n * Prose describing a schema drifts from the code that enforces it; a generated\n * artifact cannot. Documentation points at this, a YAML language server\n * validates hand-edited records against it, and a consumer that is not\n * TypeScript has something to check.\n *\n * `io: 'input'` on purpose. `strauss_status` carries a default, so the output\n * type marks it required while the *document* may legitimately omit it — and\n * the document is what this schema is used to validate.\n */\nexport function kbJsonSchemas(): Record<string, unknown> {\n return {\n recordFrontmatter: z.toJSONSchema(kbRecordFrontmatterSchema, {\n io: \"input\",\n }),\n composeInput: z.toJSONSchema(composeInputSchema, { io: \"input\" }),\n logEntry: z.toJSONSchema(kbLogEntrySchema, { io: \"input\" }),\n };\n}\n","import { edgeNeighbours } from \"./kb-edges.js\";\nimport type { KbRecord } from \"./kb-record.schema.js\";\nimport { KB_CAUSAL_LINK_RELS } from \"./record-types.js\";\n\n/**\n * Edges a trace may follow — the shared kb-edges.ts definitions, minus\n * `body-link`: body links can reach most of a bundle from anywhere, which\n * suits a bounded pack but floods a timeline. Also absent by design:\n * `strauss_answered` carries no target id, so a question's resolution lives\n * in its own body rather than in another record.\n *\n * `typed-link` is in, where `body-link` is out, because the two differ in how\n * cheaply they are made. A body link is any markdown a writer happened to\n * type; a `strauss_links` entry is a deliberate claim from a closed vocabulary\n * about what this record depends on. That is exactly the kind of edge a\n * timeline should follow — \"we chose this because of that\" is the history.\n *\n * Only the causal rels, though. `related_to` asserts no dependence and reaches\n * whatever a writer thought worth mentioning, which is the same flooding\n * `body-link` is excluded for; a bibliography is a neighbourhood's business\n * (`pack`), not a history's.\n */\nexport const TRACE_EDGES = [\n \"typed-link\",\n \"supersession\",\n \"anchor\",\n \"source\",\n] as const;\nexport type KbTraceEdge = (typeof TRACE_EDGES)[number];\n\nexport type KbTraceStep = {\n record: KbRecord;\n /** Hops from the seed. 0 is the seed itself. */\n depth: number;\n /** Why this record was reached. Empty for the seed. */\n via: KbTraceEdge[];\n};\n\nexport type KbTraceOptions = {\n edges?: readonly KbTraceEdge[];\n /** Body links alone can reach the whole bundle, so a trace is always bounded. */\n depth?: number;\n};\n\n/**\n * How a position was arrived at, as a timeline.\n *\n * The inverse of a point query, and the reason the two cannot be one call with\n * a flag: there, a `rejected` record is the most dangerous thing retrievable —\n * here it is the content. A trace that drops the rejected alternatives and the\n * superseded earlier understanding has removed the answer and kept the\n * conclusion, which is what reading a diff already gives you.\n *\n * Ordered by `generated.at` rather than by relevance. Ranking a history is\n * meaningless when the sequence is the point.\n */\nexport function trace(\n seedId: string,\n bundle: KbRecord[],\n options: KbTraceOptions = {},\n): KbTraceStep[] {\n const edges = options.edges?.length ? options.edges : TRACE_EDGES;\n const maxDepth = options.depth ?? 3;\n const byId = new Map(bundle.map((record) => [record.conceptId, record]));\n const seed = byId.get(seedId);\n if (!seed) return [];\n\n const reached = new Map<string, KbTraceStep>([\n [seedId, { record: seed, depth: 0, via: [] }],\n ]);\n let frontier: KbRecord[] = [seed];\n\n for (let depth = 1; depth <= maxDepth && frontier.length; depth += 1) {\n const next: KbRecord[] = [];\n for (const from of frontier) {\n for (const edge of edges) {\n for (const record of edgeNeighbours(\n from,\n bundle,\n edge,\n KB_CAUSAL_LINK_RELS,\n )) {\n const existing = reached.get(record.conceptId);\n if (existing) {\n // Reached twice by different edges: keep the shorter path, but\n // record both reasons — \"shares an anchor and replaces it\" is more\n // informative than either alone. The seed keeps an empty `via`,\n // since it was not reached by anything.\n if (existing.depth > 0 && !existing.via.includes(edge)) {\n existing.via.push(edge);\n }\n continue;\n }\n reached.set(record.conceptId, { record, depth, via: [edge] });\n next.push(record);\n }\n }\n }\n frontier = next;\n }\n\n return [...reached.values()].sort(byGeneratedAt);\n}\n\nfunction byGeneratedAt(left: KbTraceStep, right: KbTraceStep): number {\n const at = (step: KbTraceStep) => step.record.frontmatter.generated?.at ?? \"\";\n return at(left).localeCompare(at(right)) || left.depth - right.depth;\n}\n","import { z } from \"zod\";\nimport { assertBaseNotFrozen } from \"../kb-pins/index.js\";\nimport { bundlePath, conceptId, define } from \"./model.js\";\n\nexport const answerCommand = define({\n name: \"answer\",\n tool: \"kb_answer\",\n usage: \"answer <concept-id> <answer...>\",\n description:\n \"Resolve an open question: set status, stamp who and when, append an Answer section. If the answer overturns a decision or assumption, supersede that record explicitly.\",\n input: z.object({ bundlePath, conceptId, answer: z.string().min(1) }),\n fromArgv: (argv, path) => ({\n bundlePath: path,\n conceptId: argv[1],\n answer: argv.slice(2).join(\" \").trim(),\n }),\n run: async (\n { store, actor },\n { bundlePath: path, conceptId: id, answer },\n ) => {\n await assertBaseNotFrozen(process.cwd(), path);\n const record = await store.answer(path, id, answer, actor);\n return { conceptId: record.conceptId };\n },\n});\n","import { z } from \"zod\";\nimport { bundlePath, conceptId, define } from \"./model.js\";\n\nexport const backlinksCommand = define({\n name: \"backlinks\",\n tool: \"kb_backlinks\",\n usage: \"backlinks <concept-id>\",\n description:\n \"Who points at this record: every inbound typed causal link (`strauss_links`), one hop, every rel including `related_to`, each with its rel and the standing of the record that made it. Use it when you need the exact edges — reviewing or renaming a record.\",\n input: z.object({ bundlePath, conceptId }),\n fromArgv: (argv, path) => ({ bundlePath: path, conceptId: argv[1] }),\n run: async ({ store }, { bundlePath: path, conceptId: id }) =>\n store.backlinks(path, id),\n});\n","import { z } from \"zod\";\nimport type { KbStanding } from \"../adjudicate.js\";\nimport { renderCatalogLine, type KbCatalogResult } from \"../catalog.js\";\nimport { KB_RECORD_TYPES } from \"../kb-record.schema.js\";\nimport {\n argvFlags,\n argvPositional,\n bundlePath,\n define,\n TAGS,\n} from \"./model.js\";\n\nexport const catalogCommand = define({\n name: \"catalog\",\n tool: \"kb_catalog\",\n usage: \"catalog [type] [--tag T]...\",\n description:\n \"Lists every record as one line — concept id, type, title, standing, and a stale flag — at roughly thirty tokens each. Pick this over kb_load once kb_load refuses: kb_catalog never refuses. Superseded records show only their replacement; fetch bodies with kb_load, kb_pack, kb_query, or kb_trace.\",\n input: z.object({\n bundlePath,\n type: z.enum(KB_RECORD_TYPES).optional(),\n tags: TAGS,\n }),\n fromArgv: (argv, path) => {\n const tags = argvFlags(argv, \"--tag\");\n // The type is the first positional, in either order: a flag in the slot is\n // a flag, and `catalog --tag review decision` still narrows by type.\n const type = argvPositional(argv, \"--tag\");\n return {\n bundlePath: path,\n ...(type ? { type } : {}),\n ...(tags.length ? { tags } : {}),\n };\n },\n run: async ({ store }, { bundlePath: path, type, tags }) =>\n render(\n await store.catalog(path, {\n ...(type ? { type } : {}),\n ...(tags ? { tags } : {}),\n }),\n path,\n type,\n tags,\n ),\n});\n\n/**\n * Markdown, like `index` and `pack`, because the value is one line per record\n * and JSON would spend a third of the tokens on repeated key names.\n */\nfunction render(\n result: KbCatalogResult,\n bundle: string,\n type?: string,\n tags?: string[],\n): string {\n // The filter is named in the heading: an empty catalog otherwise reads as an\n // empty base. Tags carry a prefix so a tag cannot read as a type.\n const narrowed = [\n ...(type ? [type] : []),\n ...(tags?.length ? [`tags: ${tags.join(\", \")}`] : []),\n ].join(\" · \");\n const lines = [\n `# KB Catalog${narrowed ? ` — ${narrowed}` : \"\"}`,\n `bundle: ${bundle}`,\n `${count(result.recordCount, \"record\")}: ${standingCounts(result)}`,\n ];\n\n // Staleness is a flag over a standing, not a standing — a current record can\n // be stale. Adding it to the run above would make the counts stop summing to\n // the record count, which is the one thing that line is for.\n if (result.staleCount) {\n lines.push(\n `${result.staleCount} stale — a flag over the standings above, not one of them`,\n );\n }\n\n lines.push(\"\");\n\n if (!result.entries.length) {\n lines.push(\n narrowed\n ? `(no records matching ${narrowed})`\n : \"(no records — this base is empty)\",\n );\n } else {\n for (const entry of result.entries) lines.push(renderCatalogLine(entry));\n }\n\n lines.push(\n \"\",\n \"Bodies are not here: kb_pack <conceptId> for the neighbourhood around one record, kb_load for the whole base when it fits the budget, kb_query for a lookup by wording, kb_trace <conceptId> for how a position was arrived at.\",\n );\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Every standing that has a record, in order of how live it is. Zero counts are\n * dropped as noise, and what remains sums to the record count — a reader can\n * add the line up and see that nothing went missing.\n */\nfunction standingCounts(result: KbCatalogResult): string {\n const ORDER: readonly KbStanding[] = [\n \"current\",\n \"open\",\n \"unsettled\",\n \"rejected\",\n \"superseded\",\n ];\n const parts = ORDER.filter((standing) => result.standings[standing]).map(\n (standing) => `${result.standings[standing]} ${standing}`,\n );\n return parts.length ? parts.join(\" · \") : \"none\";\n}\n\nfunction count(value: number, noun: string): string {\n return `${value} ${value === 1 ? noun : `${noun}s`}`;\n}\n","import { Buffer } from \"node:buffer\";\nimport { open, type FileHandle } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { z } from \"zod\";\nimport {\n classifyDiff,\n HEADER_LINES,\n type KbClassifiedFile,\n type KbClassifyFile,\n type KbClassifyResult,\n} from \"../classify/index.js\";\nimport { readRangeDiff, type RangeDiff } from \"../drift/index.js\";\nimport { KbClassifyInputError } from \"../kb-errors.js\";\nimport { filePathIsSafe } from \"../remote-repo/validate.js\";\nimport {\n diffFileSchema,\n diffHunkSchema,\n parseUnifiedDiff,\n resolveSymbolRanges,\n} from \"./match/index.js\";\nimport { argvFlag, bundlePath, define, REPO_ROOT } from \"./model.js\";\n\nconst classifyFileSchema = diffFileSchema.extend({\n hunks: z.array(\n diffHunkSchema.extend({ lines: z.array(z.string()).optional() }),\n ),\n renamedFrom: z\n .string()\n .min(1)\n .optional()\n .describe(\"Where `git diff -M` says the path came from.\"),\n similarity: z.number().min(0).max(100).optional(),\n});\n\nexport const classifyCommand = define({\n name: \"classify\",\n tool: \"kb_classify\",\n usage:\n \"classify --git <base>..<head> | --stdin [--repo-root <path>] [--offline]\",\n description:\n \"What kind of change each file carries: test, config, ci, docs, lockfile, generated, boilerplate, rename or source, with the rule that decided it. Derived from the diff and never stored; a `review:generated`, `review:boilerplate` or `review:move` fact anchored on a file overrides the heuristic. kb_match says what sits on a hunk; this says whether to read it.\",\n input: z.object({\n bundlePath,\n files: z\n .array(classifyFileSchema)\n .describe(\"The changed files, each with its line ranges.\"),\n repoRoot: REPO_ROOT,\n offline: z\n .boolean()\n .optional()\n .describe(\n \"Resolve symbol ranges from what is already on disk, never fetching a grammar.\",\n ),\n }),\n fromArgv: async (argv, path, stdin) => {\n const repoRoot = argvFlag(argv, \"--repo-root\");\n const range = argvFlag(argv, \"--git\");\n const base = {\n bundlePath: path,\n ...(repoRoot !== undefined ? { repoRoot } : {}),\n ...(argv.includes(\"--offline\") ? { offline: true } : {}),\n };\n\n if (range !== undefined) {\n const diff = await readRangeDiff(repoRoot ?? process.cwd(), range);\n if (!diff.ok) {\n throw new KbClassifyInputError(\n `--git ${range} ${REFUSED[diff.reason]}`,\n );\n }\n return {\n ...base,\n files: parseUnifiedDiff(diff.text, {\n keepEmpty: true,\n withLines: true,\n }),\n };\n }\n\n if (!argv.includes(\"--stdin\")) {\n throw new KbClassifyInputError(\n \"pass --git <base>..<head>, or --stdin with { files } as JSON\",\n );\n }\n return { ...base, files: fromStdin(await stdin()) };\n },\n run: async (\n { store },\n { bundlePath: path, files, repoRoot, offline },\n ): Promise<KbClassifyResult> => {\n const records = await store.list(path);\n const root = repoRoot ?? process.cwd();\n const withHeaders = await mapLimit(files, READERS, async (file) => ({\n ...file,\n header: await header(root, file),\n }));\n // Resolved as `match` resolves them, over the files the diff names and no\n // others: without them a symbol-scoped override would cover the file.\n const symbolRanges = await resolveSymbolRanges(\n root,\n files,\n records,\n offline === true,\n );\n return { files: classifyDiff(withHeaders, { records, symbolRanges }) };\n },\n render: (result) => renderClassify(result as KbClassifyResult),\n});\n\n/** More than the banner window can need, and less than a lockfile costs. */\nconst HEADER_BYTES = 65_536;\n\n/** How many files are open at once, whatever the diff's size. */\nconst READERS = 16;\n\n/**\n * The file's banner from the working tree, which `--git <base>..<head>` reads\n * at head. Absent when it is not there — a deletion, or a tree parked\n * elsewhere — and the diff's own added lines answer instead.\n */\nasync function header(\n root: string,\n file: KbClassifyFile,\n): Promise<string[] | undefined> {\n // Lexical only: a committed symlink can still point outside the root, and\n // what leaks is one bit — whether the target's head carries a banner.\n if (!filePathIsSafe(file.filePath)) return undefined;\n let handle: FileHandle | undefined;\n try {\n handle = await open(join(root, file.filePath), \"r\");\n const buffer = Buffer.alloc(HEADER_BYTES);\n const { bytesRead } = await handle.read(buffer, 0, HEADER_BYTES, 0);\n return buffer\n .toString(\"utf8\", 0, bytesRead)\n .split(\"\\n\")\n .slice(0, HEADER_LINES);\n } catch {\n return undefined;\n } finally {\n await handle?.close();\n }\n}\n\n/** Runs at most `limit` at a time, keeping each result in its input's place. */\nasync function mapLimit<T, R>(\n items: readonly T[],\n limit: number,\n run: (item: T) => Promise<R>,\n): Promise<R[]> {\n const out: R[] = Array.from({ length: items.length });\n let next = 0;\n const worker = async (): Promise<void> => {\n while (next < items.length) {\n const at = next;\n next += 1;\n out[at] = await run(items[at] as T);\n }\n };\n await Promise.all(\n Array.from({ length: Math.min(limit, items.length) }, () => worker()),\n );\n return out;\n}\n\n/** What each refusal from `readRangeDiff` reads as, so the CLI names it. */\nconst REFUSED: Record<Extract<RangeDiff, { ok: false }>[\"reason\"], string> = {\n \"bad-range\":\n \"is not a range git could read here — both halves of <base>..<head> are required\",\n \"too-large\": \"diffs to a patch past the output cap — narrow the range\",\n timeout: \"took longer to diff than the runner allows — narrow the range\",\n \"git-missing\": \"needs git on PATH, and there is none\",\n};\n\n/** The MCP input's `files`, for a caller holding a patch of its own. */\nfunction fromStdin(text: string): unknown {\n let payload: { files?: unknown };\n try {\n payload = JSON.parse(text) as typeof payload;\n } catch {\n throw new KbClassifyInputError(\"stdin is not JSON\");\n }\n if (!Array.isArray(payload?.files)) {\n throw new KbClassifyInputError(\"stdin needs a files array\");\n }\n return payload.files;\n}\n\n/** One line per file: the class, the path, and the rule that decided it. */\nexport function renderClassify(result: KbClassifyResult): string {\n const width = Math.max(\n 0,\n ...result.files.map((file: KbClassifiedFile) => file.class.length),\n );\n return result.files\n .map(\n (file) =>\n `${file.class.padEnd(width)} ${file.filePath} (${file.reason})`,\n )\n .join(\"\\n\");\n}\n","import { z } from \"zod\";\nimport { readRangeDiff, type RangeDiff } from \"../../drift/index.js\";\nimport {\n matchToDiff,\n placeOnHunk,\n symbolRangeIndex,\n type DiffMatch,\n type SymbolRangeIndex,\n} from \"../../match-diff.js\";\nimport { argvFlag, bundlePath, define, REPO_ROOT } from \"../model.js\";\nimport { KbMatchInputError } from \"./errors.js\";\nimport {\n diffFileSchema,\n symbolRangeSchema,\n type KbMatch,\n type KbMatchRecord,\n} from \"./model.js\";\nimport { parseUnifiedDiff } from \"./parse-unified-diff.js\";\nimport { resolveSymbolRanges } from \"./symbol-ranges.js\";\n\nexport const matchCommand = define({\n name: \"match\",\n tool: \"kb_match\",\n usage:\n \"match --git <base>..<head> | --stdin [--repo-root <path>] [--offline] [--include-non-current]\",\n description:\n \"Which records sit on each changed hunk: the anchored records per file range, current first, each with its standing and the anchor that matched. kb_load hands over a whole base; this narrows a diff. Symbol ranges resolve from repoRoot when omitted; non-current records need includeNonCurrent.\",\n input: z.object({\n bundlePath,\n files: z\n .array(diffFileSchema)\n .describe(\"The changed files, each with its post-change line ranges.\"),\n symbolRanges: z\n .array(symbolRangeSchema)\n .optional()\n .describe(\n \"Symbol spans the caller already has. Resolved from repoRoot when omitted.\",\n ),\n repoRoot: REPO_ROOT,\n offline: z\n .boolean()\n .optional()\n .describe(\n \"Resolve symbol ranges from what is already on disk, never fetching a grammar.\",\n ),\n includeNonCurrent: z\n .boolean()\n .optional()\n .describe(\n \"Return superseded, rejected and unsettled records too, each carrying its standing.\",\n ),\n }),\n fromArgv: async (argv, path, stdin) => {\n const repoRoot = argvFlag(argv, \"--repo-root\");\n const range = argvFlag(argv, \"--git\");\n const base = {\n bundlePath: path,\n ...(repoRoot !== undefined ? { repoRoot } : {}),\n ...(argv.includes(\"--offline\") ? { offline: true } : {}),\n ...(argv.includes(\"--include-non-current\")\n ? { includeNonCurrent: true }\n : {}),\n };\n\n if (range !== undefined) {\n const diff = await readRangeDiff(repoRoot ?? process.cwd(), range);\n if (!diff.ok) {\n throw new KbMatchInputError(`--git ${range} ${REFUSED[diff.reason]}`);\n }\n return { ...base, files: parseUnifiedDiff(diff.text) };\n }\n\n if (!argv.includes(\"--stdin\")) {\n throw new KbMatchInputError(\n \"pass --git <base>..<head>, or --stdin with { files } as JSON\",\n );\n }\n return { ...base, ...fromStdin(await stdin()) };\n },\n run: async (\n { store },\n {\n bundlePath: path,\n files,\n symbolRanges,\n repoRoot,\n offline,\n includeNonCurrent,\n },\n ): Promise<KbMatch[]> => {\n const records = await store.list(path);\n const ranges =\n symbolRanges ??\n (await resolveSymbolRanges(\n repoRoot ?? process.cwd(),\n files,\n records,\n offline === true,\n ));\n // One index for the whole diff: `project` places every kept record again.\n const index = symbolRangeIndex(ranges);\n\n return matchToDiff(files, records, { symbolRanges: ranges }).flatMap(\n (match) => project(match, index, includeNonCurrent === true),\n );\n },\n});\n\n/** What each refusal from `readRangeDiff` reads as, so the CLI names it. */\nconst REFUSED: Record<Extract<RangeDiff, { ok: false }>[\"reason\"], string> = {\n \"bad-range\":\n \"is not a range git could read here — both halves of <base>..<head> are required\",\n \"too-large\": \"diffs to a patch past the output cap — narrow the range\",\n timeout: \"took longer to diff than the runner allows — narrow the range\",\n \"git-missing\": \"needs git on PATH, and there is none\",\n};\n\n/** The MCP input's `files` and `symbolRanges`, for a caller with no MCP. */\nfunction fromStdin(text: string): {\n files: unknown;\n symbolRanges?: unknown;\n} {\n let payload: { files?: unknown; symbolRanges?: unknown };\n try {\n payload = JSON.parse(text) as typeof payload;\n } catch {\n throw new KbMatchInputError(\"stdin is not JSON\");\n }\n if (!Array.isArray(payload?.files)) {\n throw new KbMatchInputError(\"stdin needs a files array\");\n }\n return {\n files: payload.files,\n ...(payload.symbolRanges !== undefined\n ? { symbolRanges: payload.symbolRanges }\n : {}),\n };\n}\n\n/**\n * One match as a caller reads it: no bodies, and superseded or rejected\n * records only where they were asked for. A hunk left with nothing drops out\n * rather than coming back empty.\n */\nfunction project(\n match: DiffMatch,\n ranges: SymbolRangeIndex,\n all: boolean,\n): KbMatch[] {\n const kept = all\n ? match.records\n : match.records.filter((hit) => hit.standing === \"current\");\n if (!kept.length) return [];\n\n const placed = kept.map((hit) => ({\n hit,\n at: placeOnHunk(hit.record, match.filePath, match.hunk, ranges),\n }));\n\n return [\n {\n filePath: match.filePath,\n hunk: match.hunk,\n // Over the records returned, not the ones matched: a hunk holding only\n // symbol-placed records is not `file` because a dropped one was.\n precision: placed.every(({ at }) => at.kind === \"symbol\")\n ? \"symbol\"\n : \"file\",\n records: placed.map(({ hit, at: { anchor } }): KbMatchRecord => {\n const { frontmatter } = hit.record;\n return {\n conceptId: hit.record.conceptId,\n type: frontmatter.type,\n title: frontmatter.title ?? null,\n standing: hit.standing,\n status: frontmatter.strauss_status,\n supersededBy: hit.heads.map((head) => head.conceptId),\n ...(frontmatter.strauss_materiality\n ? { materiality: frontmatter.strauss_materiality }\n : {}),\n ...(frontmatter.strauss_confidence\n ? { confidence: frontmatter.strauss_confidence }\n : {}),\n ...(frontmatter.tags?.length ? { tags: frontmatter.tags } : {}),\n ...(anchor ? { anchor } : {}),\n };\n }),\n },\n ];\n}\n","import { BaseError, ErrorTypes, Fault } from \"../../errors.js\";\n\n/** `match` invoked with no diff it could read, or one it could not parse. */\nexport class KbMatchInputError extends BaseError {\n constructor(readonly reason: string) {\n super({\n message: `match: ${reason}`,\n errorType: ErrorTypes.KbMatchInput,\n code: 400,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { reason },\n });\n }\n}\n","import { z } from \"zod\";\nimport type { KbStanding } from \"../../adjudicate.js\";\nimport type { DiffHunk } from \"../../match-diff.js\";\nimport type {\n KbAnchor,\n KbRecordFrontmatter,\n KbRecordStatus,\n} from \"../../kb-record.schema.js\";\n\n/**\n * One changed range, 1-based and inclusive, in the numbering of its `side`;\n * absent means the post-change side. Open: a field added here later comes back\n * on the hunk an older build echoes.\n */\nexport const diffHunkSchema = z\n .object({\n startLine: z.number().int().positive(),\n endLine: z.number().int().positive(),\n side: z.enum([\"old\", \"new\"]).optional(),\n })\n .passthrough();\n\nexport const diffFileSchema = z.object({\n filePath: z\n .string()\n .min(1)\n .describe(\"Repo-relative, spelled the way anchors are.\"),\n hunks: z.array(diffHunkSchema),\n});\n\nexport const symbolRangeSchema = z.object({\n file: z.string().min(1),\n symbol: z.string().min(1),\n startLine: z.number().int().positive(),\n endLine: z.number().int().positive(),\n});\n\n/** One record on a hunk: enough to decide whether to read it, and no body. */\nexport type KbMatchRecord = {\n conceptId: string;\n type: string;\n title: string | null;\n /** Carried on every entry, so a hit is never handed over as a bare match. */\n standing: KbStanding;\n status: KbRecordStatus;\n /** Where the supersession chain ends. Empty while the record still holds. */\n supersededBy: string[];\n materiality?: KbRecordFrontmatter[\"strauss_materiality\"];\n confidence?: KbRecordFrontmatter[\"strauss_confidence\"];\n tags?: string[];\n /** The anchor that put this record on this hunk. */\n anchor?: KbAnchor;\n};\n\nexport type KbMatch = {\n filePath: string;\n hunk: DiffHunk;\n /** `symbol` when every record here was placed by a resolved symbol range. */\n precision: \"symbol\" | \"file\";\n records: KbMatchRecord[];\n};\n","import type { DiffFile, DiffHunk } from \"../../match-diff.js\";\n\n/**\n * `git diff --unified=0` → the structure `matchToDiff` takes.\n *\n * CLI-side, not library: a caller holding a patch already has a parser for it,\n * and the library stays free of a flavour of unified diff.\n */\n\nconst FILE_HEADER = /^diff --git (.+)$/;\nconst HUNK = /^@@ -(\\d+)(?:,(\\d+))? \\+(\\d+)(?:,(\\d+))? @@/;\nconst SIMILARITY = /^similarity index (\\d+)%$/;\n/** What `readRangeDiff` pins. A patch from elsewhere may spell it otherwise. */\nconst KNOWN_PREFIX = /^[ab]\\//;\n\nexport type ParseDiffOptions = {\n /**\n * Keep a file the patch names but gives no hunk — a rename `-M` matched\n * whole, a binary change, a mode-only change. Off by default: a hunkless\n * file has no line for a record to sit on.\n */\n keepEmpty?: boolean;\n /** Carry each hunk's changed lines, for a caller that reads content. */\n withLines?: boolean;\n};\n\n/**\n * Files with at least one hunk, unless `keepEmpty` asks for the rest. A binary\n * file, a mode-only change and a rename that changed nothing carry no hunks,\n * so by default they appear nowhere: there is no line for a record to sit on.\n *\n * `rename from`/`similarity index` are always read onto the file; they are two\n * header lines, and a caller that ignores them pays nothing.\n */\nexport function parseUnifiedDiff(\n patch: string,\n options: ParseDiffOptions = {},\n): DiffFile[] {\n const files: DiffFile[] = [];\n let current: DiffFile | undefined;\n let listed = false;\n let shared: string | undefined;\n let oldPath: string | undefined;\n let rename: Pick<DiffFile, \"renamedFrom\" | \"similarity\"> = {};\n // Only between `diff --git` and the first hunk is a `---`/`+++` line a\n // header; past it, an added or removed line of source can spell one.\n let inHeader = false;\n // The two hunks one header can emit, so a `+`/`-` line lands on its own side.\n let added: DiffHunk | undefined;\n let removed: DiffHunk | undefined;\n\n const list = (): void => {\n if (!current || listed) return;\n files.push(current);\n listed = true;\n };\n const open = (filePath: string): void => {\n current = { filePath, hunks: [], ...rename };\n listed = false;\n };\n /** Rename headers follow the `diff --git` line the file was opened on. */\n const amend = (): void => {\n if (current) Object.assign(current, rename);\n };\n const close = (): void => {\n if (options.keepEmpty) list();\n current = undefined;\n listed = false;\n added = undefined;\n removed = undefined;\n };\n\n for (const raw of patch.split(\"\\n\")) {\n const line = raw.endsWith(\"\\r\") ? raw.slice(0, -1) : raw;\n\n const start = FILE_HEADER.exec(line);\n if (start) {\n close();\n oldPath = undefined;\n rename = {};\n shared = sharedHeaderPath(start[1] as string);\n inHeader = true;\n // Opened here rather than on `+++`: a binary or mode-only change has no\n // `+++` line at all, and `keepEmpty` is what asks for those files.\n if (shared) open(shared);\n continue;\n }\n if (inHeader) {\n const similarity = SIMILARITY.exec(line);\n if (similarity) {\n rename.similarity = Number(similarity[1]);\n amend();\n continue;\n }\n if (line.startsWith(\"rename from \")) {\n rename.renamedFrom = unquote(line.slice(12).trim());\n amend();\n continue;\n }\n // The only header naming the new path when the rename changed no line.\n if (line.startsWith(\"rename to \")) {\n open(unquote(line.slice(10).trim()));\n continue;\n }\n if (line.startsWith(\"--- \")) {\n oldPath = sidePath(line.slice(4), shared);\n continue;\n }\n if (line.startsWith(\"+++ \")) {\n // A deletion names `/dev/null` on the new side; the record still points\n // at the path that was removed.\n const path = sidePath(line.slice(4), shared) ?? oldPath;\n if (path) open(path);\n else current = undefined;\n continue;\n }\n }\n\n const hunk = HUNK.exec(line);\n if (!hunk) {\n if (!options.withLines || inHeader) continue;\n if (line.startsWith(\"+\")) added?.lines?.push(line.slice(1));\n else if (line.startsWith(\"-\")) removed?.lines?.push(line.slice(1));\n continue;\n }\n inHeader = false;\n added = undefined;\n removed = undefined;\n if (!current) continue;\n const [next, before] = hunksOf(hunk, options.withLines === true);\n added = next;\n removed = before;\n list();\n current.hunks.push(...(before ? [next, before] : [next]));\n }\n\n close();\n return files;\n}\n\n/**\n * Both halves of one hunk header. An omitted count is one line.\n *\n * The post-change side is always emitted: a count of zero there is a removal,\n * which git addresses by the line it happened after, so the hunk is that\n * single line, clamped to 1 for a removal at the top of a file or a file\n * deleted outright. The pre-change side is emitted only where the hunk\n * actually removed lines, carrying `side: \"old\"` so a record anchored to the\n * base rev lands on the code that went away rather than on whatever replaced\n * it.\n */\nfunction hunksOf(\n hunk: RegExpExecArray,\n withLines: boolean,\n): [DiffHunk, DiffHunk?] {\n const oldStart = Number(hunk[1]);\n const oldCount = hunk[2] === undefined ? 1 : Number(hunk[2]);\n const newStart = Number(hunk[3]);\n const newCount = hunk[4] === undefined ? 1 : Number(hunk[4]);\n\n const lines = withLines ? { lines: [] as string[] } : {};\n const added: DiffHunk =\n newCount === 0\n ? { ...point(newStart), ...lines }\n : { startLine: newStart, endLine: newStart + newCount - 1, ...lines };\n if (oldCount === 0) return [added];\n return [\n added,\n {\n startLine: oldStart,\n endLine: oldStart + oldCount - 1,\n side: \"old\",\n ...(withLines ? { lines: [] } : {}),\n },\n ];\n}\n\nfunction point(start: number): DiffHunk {\n const at = Math.max(1, start);\n return { startLine: at, endLine: at };\n}\n\n/**\n * `a/src/x.ts` → `src/x.ts`; `/dev/null` → nothing to attribute a hunk to. A\n * prefix this does not know is left to the `diff --git` line, which carries\n * the same two and so says what they wrap.\n */\nfunction sidePath(raw: string, shared: string | undefined): string | undefined {\n const text = unquote(raw.replace(/\\t.*$/, \"\").trim());\n if (text === \"/dev/null\") return undefined;\n if (KNOWN_PREFIX.test(text)) return text.slice(2);\n return shared ?? text;\n}\n\n/**\n * The repo-relative path both operands of a `diff --git` line wrap, whatever\n * prefixes they carry. Nothing when the two are equal — `--no-prefix` — or for\n * a rename, whose paths differ; there the `---`/`+++` lines are all there is.\n */\nfunction sharedHeaderPath(rest: string): string | undefined {\n const pair = splitHeaderPair(rest);\n if (!pair || pair[0] === pair[1]) return undefined;\n const from = unquote(pair[0]).split(\"/\");\n const to = unquote(pair[1]).split(\"/\");\n const shared: string[] = [];\n while (from.length > 1 && to.length > 1 && from.at(-1) === to.at(-1)) {\n shared.unshift(from.pop() as string);\n to.pop();\n }\n return shared.length ? shared.join(\"/\") : undefined;\n}\n\n/** `<old> <new>`. Equal-length operands are the rule, so the middle splits. */\nfunction splitHeaderPair(rest: string): [string, string] | undefined {\n if (rest.startsWith('\"')) {\n const end = endOfQuoted(rest);\n if (end < 0 || rest[end + 1] !== \" \") return undefined;\n return [rest.slice(0, end + 1), rest.slice(end + 2)];\n }\n const mid = (rest.length - 1) / 2;\n if (Number.isInteger(mid) && rest[mid] === \" \") {\n return [rest.slice(0, mid), rest.slice(mid + 1)];\n }\n const at = rest.indexOf(\" \");\n return at === -1 ? undefined : [rest.slice(0, at), rest.slice(at + 1)];\n}\n\n/** The closing quote of a C-style token, past any the body escaped. */\nfunction endOfQuoted(text: string): number {\n for (let at = 1; at < text.length; at += 1) {\n if (text[at] === \"\\\\\") {\n at += 1;\n continue;\n }\n if (text[at] === '\"') return at;\n }\n return -1;\n}\n\nconst ESCAPES: Record<string, number> = {\n a: 0x07,\n b: 0x08,\n f: 0x0c,\n n: 0x0a,\n r: 0x0d,\n t: 0x09,\n v: 0x0b,\n '\"': 0x22,\n \"\\\\\": 0x5c,\n};\n\nconst OCTAL = /^[0-7]{3}/;\nconst utf8 = new TextEncoder();\n\n/**\n * git quotes a path holding a space, a quote, or a byte outside ASCII, and\n * escapes it C-style. A non-ASCII character is three octal escapes — one per\n * UTF-8 byte — so the bytes are decoded together rather than one at a time.\n */\nfunction unquote(text: string): string {\n if (text.length < 2 || !text.startsWith('\"') || !text.endsWith('\"')) {\n return text;\n }\n const body = text.slice(1, -1);\n const bytes: number[] = [];\n\n for (let at = 0; at < body.length;) {\n const slash = body.indexOf(\"\\\\\", at);\n if (slash < 0) {\n bytes.push(...utf8.encode(body.slice(at)));\n break;\n }\n if (slash > at) bytes.push(...utf8.encode(body.slice(at, slash)));\n\n const octal = OCTAL.exec(body.slice(slash + 1, slash + 4));\n if (octal) {\n bytes.push(Number.parseInt(octal[0], 8));\n at = slash + 4;\n continue;\n }\n const next = body[slash + 1];\n if (next === undefined) {\n bytes.push(ESCAPES[\"\\\\\"] as number);\n break;\n }\n const mapped = ESCAPES[next];\n if (mapped === undefined) bytes.push(...utf8.encode(next));\n else bytes.push(mapped);\n at = slash + 2;\n }\n\n return new TextDecoder().decode(Uint8Array.from(bytes));\n}\n","import {\n anchorFileReader,\n defaultAnchorResolvers,\n prepareResolvers,\n readAnchorFiles,\n resolveAnchorSpan,\n} from \"../../anchor-resolver/index.js\";\nimport type { KbAnchor, KbRecord } from \"../../kb-record.schema.js\";\nimport type { DiffFile, SymbolRange } from \"../../match-diff.js\";\n\n/**\n * The symbol anchors that land in a diff, resolved to line ranges through the\n * package's own chain — tree-sitter, then the regex heuristic.\n *\n * Only the files the diff names are read. A base describes a repository, and\n * resolving all of it to place a handful of hunks is work with no match behind\n * it. An anchor naming another repository is skipped: the diff is this one's.\n * `offline` keeps the resolvers off the network, as `anchor-resolve` does.\n */\nexport async function resolveSymbolRanges(\n repoRoot: string,\n files: readonly DiffFile[],\n records: readonly KbRecord[],\n offline = false,\n): Promise<SymbolRange[]> {\n const changed = new Set(files.map((file) => strip(file.filePath)));\n const wanted: KbAnchor[] = [];\n const seen = new Set<string>();\n\n for (const record of records) {\n for (const anchor of record.frontmatter.strauss_anchors ?? []) {\n if (!anchor.symbol || anchor.repo) continue;\n if (!changed.has(strip(anchor.file))) continue;\n const key = `${strip(anchor.file)}#${anchor.symbol}`;\n if (seen.has(key)) continue;\n seen.add(key);\n wanted.push(anchor);\n }\n }\n if (!wanted.length) return [];\n\n const paths = [...new Set(wanted.map((anchor) => anchor.file))];\n const sources = await readAnchorFiles(paths, anchorFileReader(repoRoot));\n const resolvers = defaultAnchorResolvers({ offline });\n await prepareResolvers(resolvers, paths);\n\n const ranges: SymbolRange[] = [];\n for (const anchor of wanted) {\n const read = sources.get(anchor.file);\n if (!read?.ok) continue;\n const outcome = resolveAnchorSpan(read.source, anchor, resolvers);\n // A symbol nothing could resolve is simply left out: `matchToDiff` then\n // degrades it to the file rather than dropping the record.\n if (!outcome.ok) continue;\n ranges.push({\n file: anchor.file,\n symbol: anchor.symbol as string,\n startLine: outcome.span.startLine,\n endLine: outcome.span.endLine,\n });\n }\n return ranges;\n}\n\n/** Anchors are written by hand often enough that `./` shows up. */\nfunction strip(path: string): string {\n return path.replace(/^\\.\\//, \"\");\n}\n","import { z } from \"zod\";\nimport { buildContext, toHookJson } from \"../kb-context.js\";\nimport { argvFlag, argvFlags, define } from \"./model.js\";\n\nexport const contextCommand = define({\n name: \"context\",\n tool: \"kb_context\",\n usage:\n \"context [--profile NAME] [--budget N] [--full-under N] [--exclude-tag T]... [--format json] [--event NAME]\",\n description:\n \"Index block of pinned bases (ids, titles, standing) for injection at context birth. Takes no bundlePath — reads the workspace pin manifests. Empty when nothing is pinned; refuses over budget rather than truncating. Budget precedence: flags, then the manifest `context[profile]` over `context.default`, then the built-in profile, then package defaults.\",\n input: z.object({\n budgetTokens: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\n \"Ceiling on the whole emitted block; past it the command refuses with a list of bases rather than truncating. Defaults to 4000.\",\n ),\n fullUnderTokens: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\n \"Per-base rendering threshold, applied before the budget: a base whose complete load fits under this arrives as full records instead of index lines, and the whole block still answers to budgetTokens. Off by default — index-only is the safe default at a context birth, because injected bodies outlive the qualifiers on them; the session-start profile opts tiny bases in at 1500.\",\n ),\n profile: z\n .string()\n .optional()\n .describe(\n \"Named budget set: built-ins are session-start (full-under 1500), compact and turn (budget 2500); the manifests' `context` tables override per repo. Unknown names fall through to defaults rather than failing.\",\n ),\n excludeTags: z\n .array(z.string().min(1))\n .optional()\n .describe(\n \"Frontmatter tags whose records stay out of the block. The base stays pinned and stays readable by tool; resolved like the budgets.\",\n ),\n format: z\n .enum([\"markdown\", \"json\"])\n .optional()\n .describe(\n \"CLI envelope for hook protocols that require strict JSON on stdout. MCP callers omit this — the block itself is identical.\",\n ),\n event: z\n .string()\n .optional()\n .describe(\n \"hookEventName stamped into the JSON envelope. Only meaningful with format=json.\",\n ),\n }),\n fromArgv: (argv) => {\n const budget = argvFlag(argv, \"--budget\");\n const fullUnder = argvFlag(argv, \"--full-under\");\n const profile = argvFlag(argv, \"--profile\");\n const format = argvFlag(argv, \"--format\");\n const event = argvFlag(argv, \"--event\");\n const excludeTags = argvFlags(argv, \"--exclude-tag\");\n return {\n ...(budget ? { budgetTokens: Number(budget) } : {}),\n ...(fullUnder ? { fullUnderTokens: Number(fullUnder) } : {}),\n ...(profile ? { profile } : {}),\n ...(excludeTags.length ? { excludeTags } : {}),\n ...(format ? { format } : {}),\n ...(event ? { event } : {}),\n };\n },\n run: async (\n { store },\n { budgetTokens, fullUnderTokens, profile, excludeTags, format, event },\n ) => {\n const result = await buildContext(store, process.cwd(), {\n ...(budgetTokens ? { budgetTokens } : {}),\n ...(fullUnderTokens ? { fullUnderTokens } : {}),\n ...(profile ? { profile } : {}),\n ...(excludeTags ? { excludeTags } : {}),\n // Degradations — a full pin that could not fit, a refused block — go\n // to stderr as well as into the block itself: stderr is diagnostics on\n // both surfaces (hooks discard it, MCP logs it), so an operator can\n // see budget pressure without reading injected context.\n warn: (entry) => process.stderr.write(`${JSON.stringify(entry)}\\n`),\n });\n // Empty means empty in both formats: this runs from hooks at every\n // session start and must be silent when there is nothing to say.\n if (!result.block) return \"\";\n return format === \"json\"\n ? toHookJson(result.block, event ?? \"SessionStart\")\n : result.block;\n },\n});\n","import { z } from \"zod\";\nimport { adjudicate } from \"../adjudicate.js\";\nimport {\n movedSearch,\n reassessPacket,\n type KbReassessPacket,\n} from \"../drift/index.js\";\nimport {\n doctor,\n DEFAULT_AGING_DAYS,\n DEFAULT_EXPIRING_DAYS,\n DEFAULT_UNVERIFIED_DAYS,\n type KbAnchorResolverCounts,\n type KbDoctorReport,\n} from \"../doctor.js\";\nimport { renderReassess } from \"./reassess.js\";\nimport { grammarHints } from \"../grammars/index.js\";\nimport { argvFlag, bundlePath, define, REPO_ROOT } from \"./model.js\";\n\nexport type KbDoctorCommandResult = KbDoctorReport & {\n bundlePath: string;\n checkedAt: string;\n /**\n * One per drifted record that still needs a reading, present only under\n * `--drifted`. Records whose every drifted anchor was `moved` or `cosmetic`\n * produce no packet — that is the classification earning its keep.\n */\n packets?: KbReassessPacket[];\n /**\n * Records carrying an anchor whose code turned up unchanged elsewhere.\n * `doctor` never writes, so it names them and stops; `kb_reassess <id>` is\n * the verb that moves the anchor.\n */\n rebaselinable?: string[];\n /** What to do about a grammar this run could not obtain. */\n hints?: string[];\n};\n\nconst days = (what: string, fallback: number) =>\n z\n .number()\n .int()\n .positive()\n .optional()\n .describe(`${what} Defaults to ${fallback}.`);\n\nexport const doctorCommand = define({\n name: \"doctor\",\n tool: \"kb_doctor\",\n usage:\n \"doctor [--expiring-days N] [--unverified-days N] [--aging-days N] [--repo-root PATH] [--offline] [--strict] [--drifted [--with-diff]]\",\n description:\n \"Read-only health sweep: expired, expiring, unverified, aging, orphaned, broken-supersession, superseded-but-cited, drifted and unchecked anchors. Every group is reported even when empty; nothing is written or re-stamped. `drifted` narrows it to a reassessment packet per drifted record, `with_diff` adding each anchor's old-vs-new span.\",\n input: z.object({\n bundlePath,\n repoRoot: REPO_ROOT,\n expiringDays: days(\n \"How far ahead `expiring` looks, in days.\",\n DEFAULT_EXPIRING_DAYS,\n ),\n unverifiedDays: days(\n \"How old an unconfirmed record must be before `unverified` reports it, in days.\",\n DEFAULT_UNVERIFIED_DAYS,\n ),\n agingDays: days(\n \"How long a record may stay `open` or `proposed` before `aging` reports it, in days.\",\n DEFAULT_AGING_DAYS,\n ),\n offline: z\n .boolean()\n .optional()\n .describe(\n \"Read foreign anchors from the local repo cache only, never fetching.\",\n ),\n strict: z\n .boolean()\n .optional()\n .describe(\n \"Turn an expired record into a non-zero exit for the CLI. No effect on the report itself.\",\n ),\n drifted: z\n .boolean()\n .optional()\n .describe(\n \"Report only drift, as a reassessment packet per record: claim, per-anchor class, and what depends on it.\",\n ),\n withDiff: z\n .boolean()\n .optional()\n .describe(\n \"With `drifted`: recover each anchor's committed span and render the old-vs-new diff. Reads git history.\",\n ),\n }),\n // Presence, not truthiness: `--expiring-days \"\"` is a caller who meant\n // something and mistyped it, and a falsy test would answer by quietly\n // sweeping at the default. Passed through as given, the schema rejects it\n // and says which field.\n fromArgv: (argv, path) => {\n const expiring = argvFlag(argv, \"--expiring-days\");\n const unverified = argvFlag(argv, \"--unverified-days\");\n const agingDays = argvFlag(argv, \"--aging-days\");\n const repoRoot = argvFlag(argv, \"--repo-root\");\n return {\n bundlePath: path,\n ...(repoRoot !== undefined ? { repoRoot } : {}),\n ...(expiring !== undefined ? { expiringDays: Number(expiring) } : {}),\n ...(unverified !== undefined\n ? { unverifiedDays: Number(unverified) }\n : {}),\n ...(agingDays !== undefined ? { agingDays: Number(agingDays) } : {}),\n ...(argv.includes(\"--offline\") ? { offline: true } : {}),\n ...(argv.includes(\"--strict\") ? { strict: true } : {}),\n ...(argv.includes(\"--drifted\") ? { drifted: true } : {}),\n ...(argv.includes(\"--with-diff\") ? { withDiff: true } : {}),\n };\n },\n run: async (\n { store, now },\n {\n bundlePath: path,\n expiringDays,\n unverifiedDays,\n agingDays,\n repoRoot,\n offline,\n drifted,\n withDiff,\n },\n ) => {\n const checkedAt = now();\n const records = await store.list(path);\n // Read-only, like every other check here: the sweep names the drifted\n // anchors and leaves the re-stamp to `anchor-resolve`, which is the verb\n // that writes.\n const anchorDrift = await store.detectDrift(records, repoRoot, {\n offline: offline === true,\n });\n const report = doctor(records, {\n ...(expiringDays !== undefined ? { expiringDays } : {}),\n ...(unverifiedDays !== undefined ? { unverifiedDays } : {}),\n ...(agingDays !== undefined ? { agingDays } : {}),\n ...(anchorDrift !== undefined ? { anchorDrift } : {}),\n now: new Date(checkedAt),\n });\n const hints = grammarHints();\n if (!drifted) {\n return {\n bundlePath: path,\n checkedAt,\n ...report,\n ...(hints.length ? { hints } : {}),\n };\n }\n\n // Read-only, like the rest of the sweep: packets are built, `moved`\n // anchors are named, and not one anchor is rewritten.\n const standings = new Map(\n adjudicate(records, records, new Date(checkedAt)).map((hit) => [\n hit.record.conceptId,\n hit.standing,\n ]),\n );\n const packets: KbReassessPacket[] = [];\n const rebaselinable: string[] = [];\n // One search for the whole sweep: the repository is listed once, and a\n // candidate file is parsed once however many records anchor into it.\n const search = movedSearch(repoRoot ?? process.cwd());\n for (const found of report.groups.find((g) => g.check === \"drifted\")\n ?.findings ?? []) {\n const record = records.find(\n (entry) => entry.conceptId === found.conceptId,\n );\n if (!record) continue;\n const standing = standings.get(record.conceptId);\n const built = await reassessPacket(\n repoRoot ?? process.cwd(),\n record,\n anchorDrift?.get(record.conceptId) ?? [],\n {\n ...(withDiff ? { withDiff: true } : {}),\n impact: await store.impact(path, record.conceptId),\n ...(standing ? { standing } : {}),\n search,\n },\n );\n if (built.packet) packets.push(built.packet);\n if (built.classified.some((entry) => entry.class === \"moved\")) {\n rebaselinable.push(record.conceptId);\n }\n }\n return {\n bundlePath: path,\n checkedAt,\n ...report,\n packets,\n rebaselinable,\n ...(hints.length ? { hints } : {}),\n };\n },\n render: (result) => render(result as KbDoctorCommandResult),\n // Only expiry, and only under --strict. The other seven checks report debt a\n // reader decides about; an expired record is the base asserting something it\n // already said it would stop standing behind, which is the one finding a\n // pipeline can act on without a judgment call. Drift has its own gate —\n // `anchor-resolve` exits non-zero on it, against a repo root the caller\n // named, which is the run a CI pipeline should be making anyway.\n failsWhen: (result, input) =>\n input.strict === true &&\n (result as KbDoctorCommandResult).counts.expired > 0,\n});\n\n/**\n * The summary table first, then only the groups that found something.\n *\n * The table carries every check including the empty ones — that is what makes\n * \"checked and clean\" legible — while the detail below stays as short as the\n * base's actual health.\n */\nfunction render(result: KbDoctorCommandResult): string {\n if (result.packets) return renderPackets(result);\n const { thresholds, anchorResolvers: counts } = result;\n const lines = [\n `# KB Doctor — ${result.bundlePath}`,\n `records: ${result.recordCount}`,\n `thresholds: expiring within ${thresholds.expiringDays}d, unverified over ${thresholds.unverifiedDays}d, aging over ${thresholds.agingDays}d`,\n `checked: ${result.checkedAt}`,\n ...(counts.total ? [anchorLine(counts)] : []),\n // Its own line: an old-side anchor may name a whole file, which no\n // resolver bucket and no `total` counts.\n ...(counts.oldSide ? [`old-side anchors: ${counts.oldSide}`] : []),\n \"\",\n ];\n\n const width = Math.max(...result.groups.map((group) => group.check.length));\n for (const group of result.groups) {\n lines.push(\n ` ${group.check.padEnd(width)} ${String(group.count).padStart(3)} ${group.headline}`,\n );\n }\n\n for (const group of result.groups) {\n if (!group.count) continue;\n lines.push(\"\", `## ${group.check} (${group.count})`);\n for (const found of group.findings) {\n lines.push(\n `- ${found.conceptId}${found.title ? ` — ${found.title}` : \"\"}: ${found.note}`,\n );\n }\n }\n\n for (const hint of result.hints ?? []) lines.push(\"\", hint);\n\n lines.push(\n \"\",\n result.healthy\n ? \"Nothing to repair.\"\n : `${result.findingCount} finding${result.findingCount === 1 ? \"\" : \"s\"} across ${\n result.groups.filter((group) => group.count).length\n } of ${result.groups.length} checks.`,\n );\n\n return lines.join(\"\\n\");\n}\n\n/** Zero buckets are left off: the line is a summary, not a schema. */\nfunction anchorLine(counts: KbAnchorResolverCounts): string {\n const parts = [\n `${counts.treeSitter} tree-sitter`,\n `${counts.regex} regex`,\n ...(counts.span ? [`${counts.span} span`] : []),\n ];\n return `anchors: ${counts.total} hashed — ${parts.join(\", \")}`;\n}\n\n/**\n * `--drifted` answers a different question from the sweep, so it prints a\n * different report: not \"what is wrong with this base\" but \"here is what to\n * read, and what the code did\".\n */\nfunction renderPackets(result: KbDoctorCommandResult): string {\n const packets = result.packets ?? [];\n const lines = [\n `# KB Drift — ${result.bundlePath}`,\n `checked: ${result.checkedAt}`,\n `${packets.length} record${packets.length === 1 ? \"\" : \"s\"} need a reading; ${\n result.counts.drifted\n } drifted in all.`,\n ];\n if (result.rebaselinable?.length) {\n lines.push(\n `moved, rebaseline with \\`kb_reassess\\`: ${result.rebaselinable.join(\", \")}`,\n );\n }\n for (const packet of packets) {\n lines.push(\n renderReassess({\n conceptId: packet.conceptId,\n packet,\n rebaselined: [],\n cosmetic: 0,\n }),\n );\n }\n return lines.join(\"\\n\");\n}\n","import { z } from \"zod\";\nimport { adjudicate } from \"../adjudicate.js\";\nimport { reassessPacket, type KbReassessPacket } from \"../drift/index.js\";\nimport { KbRecordNotFoundError } from \"../kb-errors.js\";\nimport { assertBaseNotFrozen, KbBaseFrozenError } from \"../kb-pins/index.js\";\nimport type { KbAnchor } from \"../kb-record.schema.js\";\nimport { argvFlag, bundlePath, conceptId, define, REPO_ROOT } from \"./model.js\";\n\n/** One anchor whose code turned up unchanged elsewhere, and where. */\nexport type KbRebaselinedAnchor = {\n file: string;\n symbol?: string;\n toFile: string;\n toSymbol?: string;\n};\n\nexport type KbReassessResult = {\n conceptId: string;\n /** `null` when nothing survived classification — the record needs no reading. */\n packet: KbReassessPacket | null;\n rebaselined: KbRebaselinedAnchor[];\n /** Anchors whose only change was formatting. Reported, never read. */\n cosmetic: number;\n frozen?: true;\n note?: string;\n};\n\nexport const reassessCommand = define({\n name: \"reassess\",\n tool: \"kb_reassess\",\n usage: \"reassess <concept-id> [--repo-root <path>] [--with-diff]\",\n description:\n \"One drifted record, as something to judge: its claim, each anchor's drift class, the old-vs-new span diff, and the records that depend on it. Formatting-only drift is dropped. Empty when there is nothing to reassess. Writes: relocates moved anchors, keeping their hash; never verifies, supersedes, or changes standing.\",\n input: z.object({\n bundlePath,\n conceptId,\n repoRoot: REPO_ROOT,\n withDiff: z\n .boolean()\n .optional()\n .describe(\n \"Recover each anchor's committed span and render the diff. Reads git history.\",\n ),\n }),\n fromArgv: (argv, path) => {\n const repoRoot = argvFlag(argv, \"--repo-root\");\n return {\n bundlePath: path,\n conceptId: argv[1],\n ...(repoRoot !== undefined ? { repoRoot } : {}),\n ...(argv.includes(\"--with-diff\") ? { withDiff: true } : {}),\n };\n },\n run: async (\n { store, actor },\n { bundlePath: path, conceptId: id, repoRoot, withDiff },\n ): Promise<KbReassessResult> => {\n const root = repoRoot ?? process.cwd();\n const bundle = await store.list(path);\n const record = bundle.find((entry) => entry.conceptId === id);\n if (!record) throw new KbRecordNotFoundError(id);\n\n const drift = await store.detectDrift([record], repoRoot);\n const entries = drift?.get(id) ?? [];\n if (!entries.some((entry) => entry.state !== \"match\")) {\n return { conceptId: id, packet: null, rebaselined: [], cosmetic: 0 };\n }\n\n const standing = adjudicate(bundle, bundle).find(\n (hit) => hit.record.conceptId === id,\n )?.standing;\n // Only asked for once there is drift: the dependants of a record that\n // still holds are not part of this question.\n const impact = await store.impact(path, id);\n\n const { packet, classified } = await reassessPacket(root, record, entries, {\n ...(withDiff ? { withDiff: true } : {}),\n impact,\n ...(standing ? { standing } : {}),\n });\n\n // `moved` is the one class this command settles rather than reports: the\n // bytes are identical, so the record still describes them and only the\n // address was wrong. The hash is kept exactly as it was — nothing here\n // re-baselines *content*, which would be accepting an edit nobody read.\n const moves = classified.filter((found) => found.class === \"moved\");\n let frozen = false;\n const rebaselined: KbRebaselinedAnchor[] = [];\n if (moves.length) {\n const relocated = new Map<KbAnchor, KbAnchor>();\n for (const found of moves) {\n const to = found.entry.movedTo;\n if (!to) continue;\n relocated.set(found.anchor, {\n ...found.anchor,\n file: to.file,\n ...(to.symbol ? { symbol: to.symbol } : {}),\n // A span is the anchor's whole address, so relocating it means\n // moving the line range the same code now occupies.\n ...(found.anchor.span\n ? { span: { start: to.startLine, end: to.endLine } }\n : {}),\n });\n rebaselined.push({\n file: found.anchor.file,\n ...(found.anchor.symbol ? { symbol: found.anchor.symbol } : {}),\n toFile: to.file,\n ...(to.symbol ? { toSymbol: to.symbol } : {}),\n });\n }\n try {\n await assertBaseNotFrozen(process.cwd(), path);\n } catch (error) {\n if (!(error instanceof KbBaseFrozenError)) throw error;\n frozen = true;\n }\n if (!frozen) {\n await store.updateAnchors(\n path,\n id,\n (record.frontmatter.strauss_anchors ?? []).map(\n (anchor) => relocated.get(anchor) ?? anchor,\n ),\n actor,\n );\n }\n }\n\n return {\n conceptId: id,\n packet,\n rebaselined: frozen ? [] : rebaselined,\n cosmetic: classified.filter((found) => found.class === \"cosmetic\").length,\n ...(frozen\n ? {\n frozen: true as const,\n note: \"base is frozen: nothing was rebaselined\",\n }\n : {}),\n };\n },\n render: (result) => renderReassess(result as KbReassessResult),\n});\n\n/**\n * The packet as prose, because it is read rather than parsed. `--json` is the\n * machine shape; everything below exists so a reader can answer without\n * opening the repository.\n */\nexport function renderReassess(result: KbReassessResult): string {\n const lines: string[] = [];\n for (const move of result.rebaselined) {\n lines.push(\n `rebaselined: ${at(move.file, move.symbol)} → ${at(move.toFile, move.toSymbol)} (same code, new address)`,\n );\n }\n if (result.cosmetic) {\n lines.push(\n `${result.cosmetic} anchor${result.cosmetic === 1 ? \"\" : \"s\"} changed formatting only.`,\n );\n }\n if (result.note) lines.push(result.note);\n\n const packet = result.packet;\n if (!packet) {\n lines.push(`${result.conceptId}: nothing to reassess.`);\n return lines.join(\"\\n\");\n }\n\n lines.push(\n \"\",\n `# ${packet.conceptId}${packet.title ? ` — ${packet.title}` : \"\"}`,\n `type: ${packet.type} standing: ${packet.standing}`,\n ...(packet.why ? [`why: ${packet.why}`] : []),\n ...(packet.claim\n ? [\"\", `## ${packet.claim.section}`, packet.claim.text]\n : []),\n \"\",\n `## Anchors (${packet.anchors.length})`,\n );\n\n for (const anchor of packet.anchors) {\n lines.push(\n `- ${at(anchor.file, anchor.symbol)} — ${anchor.class}${anchor.reason ? ` (${anchor.reason})` : \"\"}`,\n );\n if (!anchor.diff) continue;\n if (anchor.diff.status === \"unrecoverable\") {\n lines.push(\n \" diff: unrecoverable — no committed span to compare against\",\n );\n continue;\n }\n lines.push(\n ` diff vs ${anchor.diff.ref} (${anchor.diff.source}): +${anchor.diff.added} −${anchor.diff.removed}`,\n ...anchor.diff.unified.split(\"\\n\").map((line) => ` ${line}`),\n );\n }\n\n if (packet.impact.length) {\n lines.push(\"\", `## Impact (${packet.impact.length})`);\n for (const entry of packet.impact) {\n lines.push(\n `- ${entry.conceptId} [${entry.standing}]${entry.title ? ` — ${entry.title}` : \"\"}`,\n );\n }\n if (packet.impactTruncated) lines.push(\"- … walk truncated\");\n }\n\n lines.push(\"\", `Default: ${packet.default} — ${packet.defaultNote}.`);\n return lines.join(\"\\n\");\n}\n\nfunction at(file: string, symbol?: string): string {\n return symbol ? `${file}:${symbol}` : file;\n}\n","import {\n mkdir,\n readFile,\n readdir,\n rename,\n unlink,\n writeFile,\n} from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { z } from \"zod\";\nimport { adjudicate, type KbAdjudicated } from \"../adjudicate.js\";\nimport { selectDecisions } from \"../decision-record.js\";\nimport type { KbRecord } from \"../kb-record.schema.js\";\nimport { LINK_RELS } from \"../record-types.js\";\nimport { argvFlag, bundlePath, define } from \"./model.js\";\n\nexport type KbExportedDecision = {\n conceptId: string;\n /** File name within the target directory, `NNNN-<slug>.md`. */\n file: string;\n /** The ADR's Status line, as adjudication settled it. */\n status: string;\n};\n\n/** A file this exporter did not write, holding the name a decision needs. */\nexport type KbExportForeignFile = {\n conceptId: string;\n file: string;\n};\n\nexport type KbExportResult = {\n to: string;\n format: \"madr\";\n exported: KbExportedDecision[];\n /** Decisions left unwritten because a foreign file already holds their name. */\n foreign: KbExportForeignFile[];\n};\n\n/** `NNNN-<slug>.md` — an ADR file already in the target directory. */\nconst NUMBERED = /^(\\d{4})-(.+)\\.md$/;\n\n/** Last line of every file this exporter writes, and how it recognises its own. */\nconst MARKER = \"<!-- strauss-kb export: \";\n\nexport const exportCommand = define({\n name: \"export\",\n tool: \"kb_export\",\n usage: \"export --format madr --to <dir>\",\n description:\n \"Write the base's decisions out as numbered MADR files, one per decision, for a repository that keeps ADRs of its own. Numbering is by slug, so a re-run rewrites its own files in place. A superseded decision is exported with what replaced it.\",\n input: z.object({\n bundlePath,\n format: z\n .enum([\"madr\"])\n .describe(\"Output layout. `madr` is the only one so far.\"),\n to: z.string().min(1).describe(\"Directory the ADR files are written into.\"),\n }),\n fromArgv: (argv, path) => ({\n bundlePath: path,\n format: argvFlag(argv, \"--format\"),\n to: argvFlag(argv, \"--to\"),\n }),\n run: async ({ store }, { bundlePath: path, to }): Promise<KbExportResult> => {\n const bundle = await store.list(path);\n const decisions = selectDecisions(bundle).sort((left, right) =>\n left.conceptId.localeCompare(right.conceptId),\n );\n const adjudicated = new Map(\n adjudicate(decisions, bundle).map((hit) => [hit.record.conceptId, hit]),\n );\n\n // Written outside any base, so this is the one path that does not go\n // through KbStore: the target is a repository's own ADR directory.\n await mkdir(to, { recursive: true });\n const taken = await existingFiles(to);\n let next = Math.max(0, ...[...taken.values()].map((row) => row.number)) + 1;\n\n const exported: KbExportedDecision[] = [];\n const foreign: KbExportForeignFile[] = [];\n for (const record of decisions) {\n const slug = record.conceptId.slice(record.conceptId.indexOf(\".\") + 1);\n const held = taken.get(slug);\n if (held && !held.ours) {\n foreign.push({ conceptId: record.conceptId, file: held.file });\n continue;\n }\n const number = held?.number ?? next++;\n const file = `${String(number).padStart(4, \"0\")}-${slug}.md`;\n const status = statusLine(adjudicated.get(record.conceptId));\n await publish(join(to, file), renderMadr(record, status));\n exported.push({ conceptId: record.conceptId, file, status });\n }\n\n return { to, format: \"madr\", exported, foreign };\n },\n render: (result) => {\n const { exported, foreign, to } = result as KbExportResult;\n return [\n `Wrote ${exported.length} MADR file${exported.length === 1 ? \"\" : \"s\"} to ${to}.`,\n ...exported.map(\n (entry) => `- ${entry.file} ${entry.conceptId} [${entry.status}]`,\n ),\n ...foreign.map(\n (entry) =>\n `- skipped ${entry.conceptId}: ${entry.file} was not written by export`,\n ),\n ].join(\"\\n\");\n },\n});\n\n/** Staged and renamed, so a reader never sees half an ADR. */\nasync function publish(target: string, contents: string): Promise<void> {\n const staging = `${target}.${process.pid}.tmp`;\n await writeFile(staging, contents, \"utf8\");\n try {\n await rename(staging, target);\n } catch (error) {\n await unlink(staging).catch(() => undefined);\n throw error;\n }\n}\n\n/**\n * Names already taken, keyed by slug, and whether this exporter wrote each one.\n * A decision keeps the number it was first exported under: an ADR is cited by\n * number, so renumbering rewrites history elsewhere.\n */\nasync function existingFiles(\n to: string,\n): Promise<Map<string, { file: string; number: number; ours: boolean }>> {\n const names = await readdir(to).catch(() => [] as string[]);\n const taken = new Map<\n string,\n { file: string; number: number; ours: boolean }\n >();\n for (const name of names.sort()) {\n const [, number, slug] = NUMBERED.exec(name) ?? [];\n if (!number || !slug) continue;\n const text = await readFile(join(to, name), \"utf8\").catch(() => \"\");\n taken.set(slug, {\n file: name,\n number: Number(number),\n ours: text.includes(MARKER),\n });\n }\n return taken;\n}\n\nfunction statusLine(hit: KbAdjudicated | undefined): string {\n const status = hit?.record.frontmatter.strauss_status ?? \"draft\";\n if (status !== \"superseded\") return status;\n const by = (hit?.heads ?? []).map((head) => head.conceptId);\n return by.length ? `superseded by ${by.join(\", \")}` : \"superseded\";\n}\n\nfunction renderMadr(record: KbRecord, status: string): string {\n const sections = bodySections(record.body);\n const blocks = [\n `# ${record.frontmatter.title ?? record.conceptId}`,\n \"## Status\",\n status,\n ];\n // A heading with nothing under it reads as a question that was asked and left\n // unanswered, so an absent field is an absent heading — as in the record.\n push(blocks, \"Context and Problem Statement\", record.frontmatter.description);\n push(blocks, \"Considered Options\", sections.get(\"Rejected\"));\n push(blocks, \"Decision Outcome\", sections.get(\"Decision\"));\n push(blocks, \"Consequences\", sections.get(\"Impact\"));\n blocks.push(`${MARKER}${record.conceptId} -->`);\n return `${blocks.join(\"\\n\\n\")}\\n`;\n}\n\nfunction push(blocks: string[], heading: string, text?: string): void {\n if (text?.trim()) blocks.push(`## ${heading}`, text.trim());\n}\n\n/**\n * The body's `## Heading` blocks, without the sentences `compose.ts` renders\n * after them — those state edges and sources, which an ADR carries nowhere.\n */\nfunction bodySections(body: string): Map<string, string> {\n const generated = new RegExp(\n `^(?:(?:${Object.values(LINK_RELS)\n .map((spec) => spec.phrase)\n .join(\"|\")}) \\\\[[^\\\\]]+\\\\]\\\\([^)]+\\\\.md\\\\)\\\\.|\\\\[\\\\^[^\\\\]]+\\\\]: .*)$`,\n );\n\n const sections = new Map<string, string>();\n let heading: string | null = null;\n let lines: string[] = [];\n const flush = () => {\n if (heading) sections.set(heading, lines.join(\"\\n\").trim());\n };\n\n for (const line of body.split(\"\\n\")) {\n const match = /^## (.+?)\\s*$/.exec(line);\n if (match) {\n flush();\n heading = match[1] ?? null;\n lines = [];\n } else if (heading && !generated.test(line)) {\n lines.push(line);\n }\n }\n flush();\n return sections;\n}\n","import { z } from \"zod\";\nimport { KB_CAUSAL_LINK_RELS } from \"../record-types.js\";\nimport { argvFlag, bundlePath, conceptId, define } from \"./model.js\";\n\nexport const impactCommand = define({\n name: \"impact\",\n tool: \"kb_impact\",\n usage: \"impact <concept-id> [--depth N] [--rels a,b]\",\n description:\n \"What breaks if this record changes: its transitive set of dependants, each with its standing. Each rel declares which of its ends depends on the other, and the walk follows each rel in its own direction. Naming `related_to` or an unknown rel in `rels` is an error. kb_backlinks gives one flat hop.\",\n input: z.object({\n bundlePath,\n conceptId,\n depth: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\n \"Hops out from the record. Unbounded when omitted; a walk this cuts reports truncated: true.\",\n ),\n rels: z\n .array(z.enum(KB_CAUSAL_LINK_RELS))\n .optional()\n .describe(\n \"Narrow which rels the walk follows. Defaults to every rel that carries a dependence — all but related_to.\",\n ),\n }),\n fromArgv: (argv, path) => {\n const depth = argvFlag(argv, \"--depth\");\n const rels = argvFlag(argv, \"--rels\");\n return {\n bundlePath: path,\n conceptId: argv[1],\n ...(depth ? { depth: Number(depth) } : {}),\n ...(rels ? { rels: rels.split(\",\").filter(Boolean) } : {}),\n };\n },\n run: async ({ store }, { bundlePath: path, conceptId: id, depth, rels }) =>\n store.impact(path, id, {\n ...(depth !== undefined ? { depth } : {}),\n ...(rels?.length ? { rels } : {}),\n }),\n});\n","import { z } from \"zod\";\nimport { KB_RECORD_TYPES } from \"../kb-record.schema.js\";\nimport {\n argvFlags,\n argvPositional,\n bundlePath,\n define,\n TAGS,\n} from \"./model.js\";\n\nexport const listCommand = define({\n name: \"list\",\n tool: \"kb_list\",\n usage: \"list [type] [--tag T]...\",\n description:\n \"Every record, optionally one type or tag. For enumerating; use kb_query for a question.\",\n input: z.object({\n bundlePath,\n type: z.enum(KB_RECORD_TYPES).optional(),\n tags: TAGS,\n }),\n fromArgv: (argv, path) => {\n const tags = argvFlags(argv, \"--tag\");\n // The type is the first positional, in either order: a flag in the slot is\n // a flag, and `list --tag review decision` still narrows by type.\n const type = argvPositional(argv, \"--tag\");\n return {\n bundlePath: path,\n ...(type ? { type } : {}),\n ...(tags.length ? { tags } : {}),\n };\n },\n run: async ({ store }, { bundlePath: path, type, tags }) =>\n (await store.list(path, type, { ...(tags ? { tags } : {}) })).map(\n (record) => ({\n conceptId: record.conceptId,\n title: record.frontmatter.title ?? null,\n description: record.frontmatter.description ?? null,\n status: record.frontmatter.strauss_status,\n anchors: record.frontmatter.strauss_anchors ?? [],\n }),\n ),\n});\n","import { z } from \"zod\";\nimport { KB_RECORD_TYPES } from \"../kb-record.schema.js\";\nimport { argvFlag, bundlePath, define, REPO_ROOT } from \"./model.js\";\n\nexport const loadCommand = define({\n name: \"load\",\n tool: \"kb_load\",\n usage: \"load [type] [--budget N | --all] [--repo-root PATH]\",\n description:\n \"Load the whole base, each record with its standing — call it first, at the point of use, since compaction drops it. Superseded records arrive as stubs; kb_trace has the history. Over budget it refuses: kb_catalog, then kb_pack, or narrow with `type`; `all` bypasses. Never read record files directly — only kb_* tools resolve supersession. `digest` stamps the base's content, so hooks know when to reload.\",\n input: z\n .object({\n bundlePath,\n type: z.enum(KB_RECORD_TYPES).optional(),\n budgetTokens: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\"Approximate token ceiling. Defaults to 25000.\"),\n all: z\n .boolean()\n .optional()\n .describe(\n \"Loads the entire base regardless of size, bypassing the token budget; mutually exclusive with budgetTokens.\",\n ),\n repoRoot: REPO_ROOT,\n })\n .refine((value) => !(value.all && value.budgetTokens !== undefined), {\n message:\n \"all is mutually exclusive with budgetTokens: pass a ceiling or none, not both.\",\n }),\n fromArgv: (argv, path) => {\n const budget = argvFlag(argv, \"--budget\");\n const repoRoot = argvFlag(argv, \"--repo-root\");\n return {\n bundlePath: path,\n ...(argv[1] && !argv[1].startsWith(\"--\") ? { type: argv[1] } : {}),\n ...(budget ? { budgetTokens: Number(budget) } : {}),\n ...(argv.includes(\"--all\") ? { all: true } : {}),\n ...(repoRoot !== undefined ? { repoRoot } : {}),\n };\n },\n run: async (\n { store },\n { bundlePath: path, type, budgetTokens, all, repoRoot },\n ) => {\n const result = await store.load(path, {\n ...(type ? { type } : {}),\n ...(budgetTokens ? { budgetTokens } : {}),\n ...(all ? { all } : {}),\n ...(repoRoot !== undefined ? { repoRoot } : {}),\n });\n if (!result.loaded) return result;\n return {\n ...result,\n records: result.records.map((hit) => ({\n conceptId: hit.record.conceptId,\n title: hit.record.frontmatter.title ?? null,\n standing: hit.standing,\n supersededBy: hit.heads.map((head) => head.conceptId),\n warnings: hit.warnings,\n anchors: hit.record.frontmatter.strauss_anchors ?? [],\n body: hit.record.body,\n })),\n };\n },\n});\n","import { z } from \"zod\";\nimport { bundlePath, define } from \"./model.js\";\n\nexport const logCommand = define({\n name: \"log\",\n tool: \"kb_log\",\n usage: \"log\",\n description:\n \"Who touched what, and when. Append-only; malformed lines are reported, never repaired.\",\n input: z.object({ bundlePath }),\n fromArgv: (_argv, path) => ({ bundlePath: path }),\n run: ({ store }, { bundlePath: path }) => store.readLog(path),\n});\n","import { z } from \"zod\";\nimport { composeNoDecisionRecord } from \"../decision-record.js\";\nimport { assertBaseNotFrozen } from \"../kb-pins/index.js\";\nimport { bundlePath, define } from \"./model.js\";\n\nexport const noDecisionCommand = define({\n name: \"no-decision\",\n tool: \"kb_no_decision\",\n usage: \"no-decision <reason...>\",\n description:\n \"Record in one sentence that a piece of work had nothing to decide. Idempotent.\",\n input: z.object({ bundlePath, reason: z.string().min(1) }),\n fromArgv: (argv, path) => ({\n bundlePath: path,\n reason: argv.slice(1).join(\" \").trim(),\n }),\n run: async ({ store, actor, now }, { bundlePath: path, reason }) => {\n await assertBaseNotFrozen(process.cwd(), path);\n const record = await store.write(\n path,\n { ...composeNoDecisionRecord(reason, actor, now()), overwrite: true },\n actor,\n );\n return { conceptId: record.conceptId };\n },\n});\n","import { z } from \"zod\";\nimport type { KbWarning } from \"../adjudicate.js\";\nimport type { KbPackResult } from \"../pack.js\";\nimport { argvFlag, bundlePath, conceptId, define } from \"./model.js\";\n\nexport const packCommand = define({\n name: \"pack\",\n tool: \"kb_pack\",\n usage: \"pack <conceptId> [--hops N] [--max-nodes N] [--budget N]\",\n description:\n \"Bounded neighbourhood around one record: within `hops`, ranked, cut to `maxNodes`, with every cut record named under Excluded. Use when the base is over kb_load's budget and the work centres on a record you can name. Refuses over budget rather than truncating. Everything below the header is byte-stable across runs. Resolves supersession like kb_load.\",\n input: z.object({\n bundlePath,\n conceptId,\n hops: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\"How far from the root the walk may reach. Defaults to 2.\"),\n maxNodes: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\n \"How many records the pack may hold, root included. Defaults to 20.\",\n ),\n budgetTokens: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\n \"Approximate token ceiling over what is actually emitted. Defaults to 25000.\",\n ),\n }),\n fromArgv: (argv, path) => {\n const hops = argvFlag(argv, \"--hops\");\n const maxNodes = argvFlag(argv, \"--max-nodes\");\n const budget = argvFlag(argv, \"--budget\");\n return {\n bundlePath: path,\n conceptId: argv[1],\n ...(hops ? { hops: Number(hops) } : {}),\n ...(maxNodes ? { maxNodes: Number(maxNodes) } : {}),\n ...(budget ? { budgetTokens: Number(budget) } : {}),\n };\n },\n run: async (\n { store, now },\n { bundlePath: path, conceptId: root, hops, maxNodes, budgetTokens },\n ) => {\n const result = await store.pack(path, root, {\n ...(hops !== undefined ? { hops } : {}),\n ...(maxNodes !== undefined ? { maxNodes } : {}),\n ...(budgetTokens !== undefined ? { budgetTokens } : {}),\n });\n return render(result, path, now());\n },\n});\n\n/**\n * The timestamp is the header's last line and appears nowhere else, so a\n * caller can drop everything through that line and diff two packs of the same\n * base byte for byte.\n */\nfunction render(result: KbPackResult, bundle: string, at: string): string {\n const lines = [\n `# KB Pack — ${result.root}`,\n `bundle: ${bundle}`,\n `budget: ~${result.tokensLoaded} of ${result.budgetTokens} tokens, ${result.recordCount} records`,\n `packed: ${at}`,\n \"\",\n `## Records (${result.records.length})`,\n ];\n\n for (const record of result.records) {\n lines.push(\n \"\",\n `### ${record.conceptId}${record.title ? ` — ${record.title}` : \"\"} [${record.standing}]`,\n );\n if (record.warnings.length) {\n lines.push(`warnings: ${record.warnings.map(warningLabel).join(\"; \")}`);\n }\n if (record.anchors.length) {\n lines.push(\n `anchors: ${record.anchors\n .map((anchor) =>\n anchor.symbol ? `${anchor.file}#${anchor.symbol}` : anchor.file,\n )\n .join(\", \")}`,\n );\n }\n lines.push(\"\", record.body.trimEnd());\n }\n\n if (result.superseded.length) {\n lines.push(\"\", `## Superseded (${result.superseded.length})`);\n for (const entry of result.superseded) {\n lines.push(\n `- ${entry.conceptId} → ${\n entry.supersededBy.join(\", \") || \"(no surviving head)\"\n }${entry.at ? ` (${entry.at})` : \"\"}`,\n );\n }\n }\n\n if (result.excluded.length) {\n lines.push(\"\", `## Excluded (${result.excluded.length})`);\n for (const cut of result.excluded) lines.push(`- ${cut}`);\n }\n\n return lines.join(\"\\n\");\n}\n\nfunction warningLabel(warning: KbWarning): string {\n switch (warning.kind) {\n case \"superseded\":\n return `superseded by ${warning.by.join(\", \")}`;\n case \"unsettled\":\n return `unsettled (${warning.status})`;\n case \"broken-chain\":\n return `broken chain — ${warning.missing} is not in the bundle`;\n case \"chain-cycle\":\n return `chain cycle through ${warning.through.join(\" → \")}`;\n case \"forked-chain\":\n return `forked chain — heads ${warning.heads.join(\", \")}`;\n case \"stale\":\n return `stale since ${warning.staleAfter}`;\n case \"unresolved-question\":\n return \"unresolved question\";\n default:\n return warning.kind;\n }\n}\n","import { z } from \"zod\";\nimport { pinBase } from \"../kb-pins/index.js\";\nimport { argvFlag, bundlePath, define } from \"./model.js\";\n\nexport const pinCommand = define({\n name: \"pin\",\n tool: \"kb_pin\",\n usage:\n \"pin [bundle-path] [--mode full|index] [--profiles a,b] [--local|--user] [--frozen|--unfreeze]\",\n description:\n \"Pin a base into a workspace manifest so kb_context surfaces it. Layers, nearest wins: project `.strauss/kb-pins.json` (default), `--local` (personal, gitignored), `--user` (`~/.strauss`). Idempotent; `--mode full|index`, `--profiles`, `--frozen`/`--unfreeze` update only those fields. A path with no records pins with a warning. Never touches the base itself.\",\n input: z.object({\n bundlePath,\n mode: z\n .enum([\"full\", \"index\"])\n .optional()\n .describe(\n \"full: always emit this base's records whole (still under the block budget); index: never upgrade. Absent: the profile's full-under threshold decides.\",\n ),\n profiles: z\n .array(z.string())\n .optional()\n .describe(\"Context profiles this pin surfaces in. Absent: all of them.\"),\n layer: z\n .enum([\"project\", \"local\", \"user\"])\n .optional()\n .describe(\n \"Which manifest to write: project (committed, default), local (personal, gitignored), user (~/.strauss, every workspace).\",\n ),\n frozen: z\n .boolean()\n .optional()\n .describe(\n \"true: the base is concluded — writes against it refuse while pinned. false: lift a freeze.\",\n ),\n }),\n fromArgv: (argv, path) => {\n const positional = argv[1] && !argv[1].startsWith(\"--\") ? argv[1] : path;\n const mode = argvFlag(argv, \"--mode\");\n const profiles = argvFlag(argv, \"--profiles\");\n const layer = argv.includes(\"--user\")\n ? \"user\"\n : argv.includes(\"--local\")\n ? \"local\"\n : undefined;\n const frozen = argv.includes(\"--frozen\")\n ? true\n : argv.includes(\"--unfreeze\")\n ? false\n : undefined;\n return {\n bundlePath: positional,\n ...(mode ? { mode } : {}),\n ...(profiles\n ? {\n profiles: profiles\n .split(\",\")\n .map((p) => p.trim())\n .filter(Boolean),\n }\n : {}),\n ...(layer ? { layer } : {}),\n ...(frozen !== undefined ? { frozen } : {}),\n };\n },\n run: ({ store, now }, { bundlePath: path, mode, profiles, layer, frozen }) =>\n pinBase(store, process.cwd(), path, now(), {\n ...(mode ? { mode } : {}),\n ...(profiles ? { profiles } : {}),\n ...(layer ? { layer } : {}),\n ...(frozen !== undefined ? { frozen } : {}),\n }),\n});\n","import { z } from \"zod\";\nimport { listPins } from \"../kb-pins/index.js\";\nimport { define } from \"./model.js\";\n\nexport const pinsCommand = define({\n name: \"pins\",\n tool: \"kb_pins\",\n usage: \"pins\",\n description:\n \"Every pinned base across the manifest layers, with its layer and whether it resolves to records. Takes no bundlePath.\",\n input: z.object({}),\n fromArgv: () => ({}),\n run: ({ store }) => listPins(store, process.cwd()),\n});\n","import { z } from \"zod\";\nimport { KB_RECORD_TYPES } from \"../kb-record.schema.js\";\nimport {\n argvFlag,\n argvFlags,\n argvWithout,\n bundlePath,\n define,\n REPO_ROOT,\n TAGS,\n} from \"./model.js\";\n\nexport const queryCommand = define({\n name: \"query\",\n tool: \"kb_query\",\n usage: \"query <text...> [--tag T]... [--repo-root PATH]\",\n description:\n \"Search; every hit carries its standing. Flagged, never filtered: a superseded hit returns with its replacement, a rejected one is marked. Prefer kb_load when the base fits its budget — a full read beats search. Results are volatile: place them at the tail, not the cached prefix. Never read record files directly.\",\n input: z.object({\n bundlePath,\n text: z.string().optional(),\n type: z.enum(KB_RECORD_TYPES).optional(),\n includeNonCurrent: z.boolean().optional(),\n tags: TAGS,\n repoRoot: REPO_ROOT,\n }),\n // Both are flags, so neither's value may fall into the search text.\n fromArgv: (argv, path) => {\n const repoRoot = argvFlag(argv, \"--repo-root\");\n const tags = argvFlags(argv, \"--tag\");\n const words = argvWithout(argv.slice(1), \"--repo-root\", \"--tag\");\n return {\n bundlePath: path,\n text: words.join(\" \").trim(),\n includeNonCurrent: true,\n ...(tags.length ? { tags } : {}),\n ...(repoRoot !== undefined ? { repoRoot } : {}),\n };\n },\n run: async (\n { store },\n { bundlePath: path, text, type, includeNonCurrent, tags, repoRoot },\n ) =>\n (\n await store.query(path, text ?? \"\", {\n ...(type ? { type } : {}),\n includeNonCurrent: includeNonCurrent === true,\n ...(tags ? { tags } : {}),\n ...(repoRoot !== undefined ? { repoRoot } : {}),\n })\n ).map((hit) => ({\n conceptId: hit.record.conceptId,\n title: hit.record.frontmatter.title ?? null,\n description: hit.record.frontmatter.description ?? null,\n standing: hit.standing,\n supersededBy: hit.heads.map((head) => head.conceptId),\n warnings: hit.warnings,\n body: hit.record.body,\n })),\n});\n","import { z } from \"zod\";\nimport { bundlePath, define } from \"./model.js\";\n\nexport const readIndexCommand = define({\n name: \"index\",\n tool: \"kb_index\",\n usage: \"index\",\n description:\n \"The index — title, type, status, description per record — rebuilt if stale. Cheapest re-orientation after compaction: call it (or kb_context) first, then kb_load or fetch by id.\",\n input: z.object({ bundlePath }),\n fromArgv: (_argv, path) => ({ bundlePath: path }),\n run: ({ store }, { bundlePath: path }) => store.readIndex(path),\n});\n","import { z } from \"zod\";\nimport { kbJsonSchemas } from \"../json-schema.js\";\nimport { define } from \"./model.js\";\n\nexport const schemaCommand = define({\n name: \"schema\",\n tool: \"kb_schema\",\n usage: \"schema\",\n description:\n \"JSON Schema for frontmatter, write input, and log entries, generated from the enforcing code.\",\n input: z.object({}),\n fromArgv: () => ({}),\n run: () => Promise.resolve(kbJsonSchemas()),\n});\n","import { readFile } from \"node:fs/promises\";\nimport { z } from \"zod\";\nimport {\n KbStampBaselineError,\n KbStampDigestBaselineError,\n} from \"../kb-errors.js\";\nimport { readMergedPins } from \"../kb-pins/index.js\";\nimport type { KbStampResult } from \"../kb-store.js\";\nimport { argvFlag, define } from \"./model.js\";\n\n/** One base's stamp, plus which records moved when a baseline was given. */\ntype KbStampReport = KbStampResult & {\n /** Changed, added or removed ids; null when the baseline was a digest. */\n changed: string[] | null;\n};\n\nconst DIGEST = /^[0-9a-f]{64}$/;\n\nexport const stampCommand = define({\n name: \"stamp\",\n tool: \"kb_stamp\",\n usage: \"stamp [--bundle PATH] [--since DIGEST|FILE]\",\n description:\n \"Content stamp of a base — `load`'s digest, record counts, per-record digests, how many records have drifted anchors — without any bodies. Takes no bundlePath to stamp every pinned base. With `since`, reports only the bases that moved, naming the changed ids. Reads, never writes.\",\n input: z.object({\n bundlePath: z\n .string()\n .min(1)\n .optional()\n .describe(\n \"Absolute path to one knowledge base. Omit to stamp every pinned base.\",\n ),\n since: z\n .string()\n .min(1)\n .optional()\n .describe(\n \"Prior digest, or path to a prior `stamp --json`; only moved bases return, with changed ids when the baseline is a file.\",\n ),\n }),\n fromArgv: (argv, path, _stdin, bundleExplicit) => {\n const since = argvFlag(argv, \"--since\");\n return {\n ...(bundleExplicit ? { bundlePath: path } : {}),\n ...(since !== undefined ? { since } : {}),\n };\n },\n run: async ({ store }, { bundlePath, since }) => {\n const targets = bundlePath\n ? [bundlePath]\n : (await readMergedPins(process.cwd())).pins.map(\n (pin) => pin.absolutePath,\n );\n\n // A digest baseline only answers equality, and equality against which\n // base is ambiguous once more than one is in play — a file baseline\n // carries a digest per base and has no such limit.\n if (since !== undefined && DIGEST.test(since) && targets.length > 1) {\n throw new KbStampDigestBaselineError(since);\n }\n\n const stamps = await Promise.all(\n targets.map((target) => store.stamp(target)),\n );\n if (since === undefined) {\n return stamps.map((stamp) => ({ ...stamp, changed: null }));\n }\n\n const baseline = await readBaseline(since);\n const reports: KbStampReport[] = [];\n for (const stamp of stamps) {\n const before = baseline.byPath.get(stamp.path);\n if (baseline.digest !== null) {\n if (baseline.digest === stamp.digest) continue;\n reports.push({ ...stamp, changed: null });\n continue;\n }\n // A base absent from the baseline was never injected — reported whole,\n // the same as a base whose every record is new.\n if (before && before.digest === stamp.digest) continue;\n reports.push({ ...stamp, changed: changedIds(before?.records, stamp) });\n }\n return reports;\n },\n render: (result) =>\n (result as KbStampReport[])\n .map((report) => {\n const counts = `${report.recordCount} record(s), ${report.superseded} superseded${\n report.drifted ? `, ${report.drifted} drifted` : \"\"\n }`;\n const head = `${report.path} ${report.digest} ${counts}${\n report.newestAt ? ` newest ${report.newestAt}` : \"\"\n }`;\n return report.changed?.length\n ? `${head}\\n changed: ${report.changed.join(\", \")}`\n : head;\n })\n .join(\"\\n\"),\n});\n\nfunction changedIds(\n before: Map<string, string> | undefined,\n stamp: KbStampResult,\n): string[] {\n const now = new Map(\n stamp.records.map((record) => [record.conceptId, record.digest]),\n );\n const ids = new Set<string>();\n for (const [conceptId, digest] of now) {\n if (before?.get(conceptId) !== digest) ids.add(conceptId);\n }\n for (const conceptId of before?.keys() ?? []) {\n if (!now.has(conceptId)) ids.add(conceptId);\n }\n return [...ids].sort();\n}\n\n/**\n * `--since` is either a digest — an equality answer, no ids to name — or a\n * path to a prior `stamp --json` (equally, a hook's session state file), which\n * carries the per-record digests a changed-id list needs.\n */\nasync function readBaseline(since: string): Promise<{\n digest: string | null;\n byPath: Map<string, { digest: string; records: Map<string, string> }>;\n}> {\n if (DIGEST.test(since)) return { digest: since, byPath: new Map() };\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(await readFile(since, \"utf8\"));\n } catch {\n throw new KbStampBaselineError(since);\n }\n\n // Either a `stamp --json` array, or a hook's session state file, which\n // carries the same entries under `stamps` beside the git head it saw.\n const entries = Array.isArray(parsed)\n ? parsed\n : ((parsed as { stamps?: unknown[] })?.stamps ?? []);\n const byPath = new Map<\n string,\n { digest: string; records: Map<string, string> }\n >();\n for (const entry of entries as {\n path?: string;\n digest?: string;\n records?: { conceptId: string; digest: string }[];\n }[]) {\n if (typeof entry?.path !== \"string\" || typeof entry?.digest !== \"string\") {\n continue;\n }\n byPath.set(entry.path, {\n digest: entry.digest,\n records: new Map(\n (entry.records ?? []).map((record) => [\n record.conceptId,\n record.digest,\n ]),\n ),\n });\n }\n return { digest: null, byPath };\n}\n","import { z } from \"zod\";\nimport { assertBaseNotFrozen } from \"../kb-pins/index.js\";\nimport { KB_RECORD_STATUSES } from \"../kb-record.schema.js\";\nimport { bundlePath, conceptId, define } from \"./model.js\";\n\nexport const statusCommand = define({\n name: \"status\",\n tool: \"kb_status\",\n usage: \"status <concept-id> <status>\",\n description:\n \"Move a record's status. Compare-and-swap: a concurrent change fails instead of being overwritten.\",\n input: z.object({\n bundlePath,\n conceptId,\n status: z.enum(KB_RECORD_STATUSES),\n }),\n fromArgv: (argv, path) => ({\n bundlePath: path,\n conceptId: argv[1],\n status: argv[2],\n }),\n run: async (\n { store, actor },\n { bundlePath: path, conceptId: id, status },\n ) => {\n await assertBaseNotFrozen(process.cwd(), path);\n const record = await store.setStatus(path, id, status, actor);\n return { conceptId: record.conceptId, status };\n },\n});\n","import { z } from \"zod\";\nimport { assertBaseNotFrozen } from \"../kb-pins/index.js\";\nimport { bundlePath, conceptId, define } from \"./model.js\";\n\nexport const supersedeCommand = define({\n name: \"supersede\",\n tool: \"kb_supersede\",\n usage: \"supersede <concept-id> <replacement-id>\",\n description:\n \"Mark a record superseded by another, linked in both directions. Use instead of editing a record whose meaning changed.\",\n input: z.object({ bundlePath, conceptId, replacementId: conceptId }),\n fromArgv: (argv, path) => ({\n bundlePath: path,\n conceptId: argv[1],\n replacementId: argv[2],\n }),\n run: async (\n { store, actor },\n { bundlePath: path, conceptId: id, replacementId },\n ) => {\n await assertBaseNotFrozen(process.cwd(), path);\n await store.supersede(path, id, replacementId, actor);\n return { superseded: id, replacedBy: replacementId };\n },\n});\n","import { z } from \"zod\";\nimport { adjudicate, type KbAdjudicated } from \"../adjudicate.js\";\nimport { assertBaseNotFrozen } from \"../kb-pins/index.js\";\nimport { inboundIndex } from \"../kb-links/index.js\";\nimport type { KbRecord, KbRecordStatus } from \"../kb-record.schema.js\";\nimport { argvFlag, bundlePath, define } from \"./model.js\";\n\n/**\n * The statuses a record can be swept from: it is settled, so nothing later\n * reads it for an answer.\n */\nconst TERMINAL: readonly KbRecordStatus[] = [\n \"resolved\",\n \"rejected\",\n \"superseded\",\n];\n\n/** One record kept back, and the surviving records still pointing at it. */\nexport type KbSweptSkip = {\n conceptId: string;\n heldBy: string[];\n};\n\n/** One candidate a real run did not remove, and why. */\nexport type KbSweepFailure = {\n conceptId: string;\n reason: string;\n};\n\nexport type KbSweepResult = {\n tag: string;\n dryRun: boolean;\n /** Ids removed — empty under `--dry-run`, where `candidates` says what would go. */\n deleted: string[];\n /** Ids a real run would delete. Equals `deleted` once one has, minus `failed`. */\n candidates: string[];\n skipped: KbSweptSkip[];\n /** Candidates a real run could not remove. Empty under `--dry-run`. */\n failed: KbSweepFailure[];\n};\n\nexport const sweepCommand = define({\n name: \"sweep\",\n tool: \"kb_sweep\",\n usage: \"sweep --tag <tag> --terminal [--dry-run]\",\n description:\n \"Delete tagged records that are resolved, rejected or superseded. Refuses without --tag, keeps any record a surviving record still points at, and logs each deletion.\",\n input: z.object({\n bundlePath,\n tag: z\n .string({ error: \"sweep needs --tag: it never sweeps a whole base\" })\n .min(1)\n .describe(\"Only records carrying this tag are considered.\"),\n terminal: z\n .literal(true, {\n error: \"sweep needs --terminal: it deletes only settled records\",\n })\n .describe(\n \"Required. Names the only scope sweep deletes: resolved, rejected and superseded records.\",\n ),\n dryRun: z\n .boolean()\n .optional()\n .describe(\"Report what would go, and delete nothing.\"),\n }),\n fromArgv: (argv, path) => ({\n bundlePath: path,\n tag: argvFlag(argv, \"--tag\"),\n ...(argv.includes(\"--terminal\") ? { terminal: true as const } : {}),\n ...(argv.includes(\"--dry-run\") ? { dryRun: true } : {}),\n }),\n run: async (\n { store, actor },\n { bundlePath: path, tag, dryRun },\n ): Promise<KbSweepResult> => {\n const bundle = await store.list(path);\n const held = holderIndex(bundle);\n const candidates = adjudicate(bundle, bundle).filter((hit) =>\n sweepable(hit, tag),\n );\n\n // A record only goes if nothing that stays points at it, and whether a\n // holder stays is itself the question — so shrink the doomed set until it\n // stops shrinking rather than judging every candidate against the first\n // guess.\n const doomed = new Set(candidates.map((hit) => hit.record.conceptId));\n let changed = true;\n while (changed) {\n changed = false;\n for (const conceptId of [...doomed]) {\n if (survivorsHolding(conceptId, held, doomed).length === 0) continue;\n doomed.delete(conceptId);\n changed = true;\n }\n }\n\n const skipped = candidates\n .filter((hit) => !doomed.has(hit.record.conceptId))\n .map((hit) => ({\n conceptId: hit.record.conceptId,\n heldBy: survivorsHolding(hit.record.conceptId, held, doomed),\n }));\n const ordered = [...doomed].sort();\n\n if (dryRun) {\n return {\n tag,\n dryRun: true,\n deleted: [],\n candidates: ordered,\n skipped,\n failed: [],\n };\n }\n\n // Guarded here rather than at the top: a dry run writes nothing, and a\n // frozen base is exactly where a reader wants to see what a sweep would do.\n await assertBaseNotFrozen(process.cwd(), path);\n\n const deleted: string[] = [];\n const failed: KbSweepFailure[] = [];\n try {\n for (const conceptId of ordered) {\n try {\n const outcome = await store.deleteRecord(\n path,\n conceptId,\n { tag, statuses: TERMINAL },\n actor,\n );\n if (outcome === \"deleted\") deleted.push(conceptId);\n else failed.push({ conceptId, reason: outcome });\n } catch (error) {\n // One id failing is not the run failing: the rest still go, and the\n // caller is told which did not rather than being handed a throw\n // after an unknown number of deletions.\n failed.push({\n conceptId,\n reason: error instanceof Error ? error.message : \"unknown\",\n });\n }\n }\n } finally {\n // Both projections are derived, and a partial run leaves both wrong.\n await store.readIndex(path);\n await store.dropSearchIndex(path);\n }\n\n return {\n tag,\n dryRun: false,\n deleted,\n candidates: ordered,\n skipped,\n failed,\n };\n },\n render: (result) => renderSweep(result as KbSweepResult),\n});\n\nfunction sweepable(hit: KbAdjudicated, tag: string): boolean {\n const { tags, strauss_status } = hit.record.frontmatter;\n return (\n (tags ?? []).includes(tag) &&\n // Supersession is a standing, settled against the whole base; the other\n // two are the record's own word for itself.\n (hit.standing === \"superseded\" ||\n strauss_status === \"resolved\" ||\n strauss_status === \"rejected\")\n );\n}\n\n/**\n * Everything pointing at a record, by target: typed links plus both\n * supersession pointers. A pointer is not an edge, but a survivor left holding\n * one at a swept record has a dangling id `validate` faults.\n */\nfunction holderIndex(bundle: KbRecord[]): Map<string, Set<string>> {\n const byTarget = new Map<string, Set<string>>();\n const hold = (target: string, from: string) => {\n if (target === from) return;\n const holders = byTarget.get(target) ?? new Set<string>();\n holders.add(from);\n byTarget.set(target, holders);\n };\n\n for (const [target, edges] of inboundIndex(bundle)) {\n for (const edge of edges) hold(target, edge.from);\n }\n for (const record of bundle) {\n const { strauss_supersedes, strauss_superseded_by } = record.frontmatter;\n for (const old of strauss_supersedes ?? []) hold(old, record.conceptId);\n if (strauss_superseded_by) hold(strauss_superseded_by, record.conceptId);\n }\n return byTarget;\n}\n\n/** Records outside `doomed` that point at `conceptId`. */\nfunction survivorsHolding(\n conceptId: string,\n held: Map<string, Set<string>>,\n doomed: Set<string>,\n): string[] {\n return [...(held.get(conceptId) ?? [])]\n .filter((from) => !doomed.has(from))\n .sort();\n}\n\nexport function renderSweep(result: KbSweepResult): string {\n const shown = result.dryRun ? result.candidates : result.deleted;\n const verb = result.dryRun ? \"would delete\" : \"deleted\";\n const lines = [`${verb} ${shown.length} (tag: ${result.tag})`];\n for (const conceptId of shown) lines.push(`- ${conceptId}`);\n for (const skip of result.skipped) {\n lines.push(`kept ${skip.conceptId} — held by ${skip.heldBy.join(\", \")}`);\n }\n for (const failure of result.failed) {\n lines.push(`failed ${failure.conceptId} — ${failure.reason}`);\n }\n return lines.join(\"\\n\");\n}\n","import { z } from \"zod\";\nimport { buildContext, syncInstructions } from \"../kb-context.js\";\nimport { argvFlag, define } from \"./model.js\";\n\nexport const syncInstructionsCommand = define({\n name: \"sync-instructions\",\n usage:\n \"sync-instructions <file> [--profile NAME] [--budget N] [--full-under N]\",\n description:\n \"CLI-only: plant the kb_context block between sentinel comments in AGENTS.md or CLAUDE.md, idempotently.\",\n input: z.object({\n file: z.string().min(1).describe(\"The instruction file to edit in place.\"),\n budgetTokens: z.number().int().positive().optional(),\n fullUnderTokens: z.number().int().positive().optional(),\n profile: z.string().optional(),\n }),\n fromArgv: (argv) => {\n const budget = argvFlag(argv, \"--budget\");\n const fullUnder = argvFlag(argv, \"--full-under\");\n const profile = argvFlag(argv, \"--profile\");\n return {\n file: argv[1],\n ...(budget ? { budgetTokens: Number(budget) } : {}),\n ...(fullUnder ? { fullUnderTokens: Number(fullUnder) } : {}),\n ...(profile ? { profile } : {}),\n };\n },\n run: async ({ store }, { file, budgetTokens, fullUnderTokens, profile }) => {\n const result = await buildContext(store, process.cwd(), {\n ...(budgetTokens ? { budgetTokens } : {}),\n ...(fullUnderTokens ? { fullUnderTokens } : {}),\n ...(profile ? { profile } : {}),\n warn: (entry) => process.stderr.write(`${JSON.stringify(entry)}\\n`),\n });\n return syncInstructions(file, result.block);\n },\n});\n","import { z } from \"zod\";\nimport { TRACE_EDGES } from \"../trace.js\";\nimport { bundlePath, conceptId, define } from \"./model.js\";\n\nexport const traceCommand = define({\n name: \"trace\",\n tool: \"kb_trace\",\n usage: \"trace <concept-id> [edges...]\",\n description:\n 'Timeline of how a position was reached, ordered by write time, following supersession, shared anchors and shared sources. Includes rejected, draft and superseded records — in a history they are the content. For \"why is it like this\"; kb_load answers \"what holds now\".',\n input: z.object({\n bundlePath,\n conceptId,\n edges: z.array(z.enum(TRACE_EDGES)).optional(),\n depth: z.number().int().positive().optional(),\n }),\n fromArgv: (argv, path) => ({\n bundlePath: path,\n conceptId: argv[1],\n edges: argv\n .slice(2)\n .filter((edge) => (TRACE_EDGES as readonly string[]).includes(edge)),\n }),\n run: async ({ store }, { bundlePath: path, conceptId: id, edges, depth }) =>\n (\n await store.trace(path, id, {\n ...(edges?.length ? { edges } : {}),\n ...(depth ? { depth } : {}),\n })\n ).map((step) => ({\n conceptId: step.record.conceptId,\n at: step.record.frontmatter.generated?.at ?? null,\n status: step.record.frontmatter.strauss_status,\n title: step.record.frontmatter.title ?? null,\n depth: step.depth,\n via: step.via,\n body: step.record.body,\n })),\n});\n","import { z } from \"zod\";\nimport { RECORD_TYPES } from \"../record-types.js\";\nimport { define } from \"./model.js\";\n\nexport const typesCommand = define({\n name: \"types\",\n tool: \"kb_types\",\n usage: \"types\",\n description:\n \"The twelve record types with their purpose, body sections, and starting status. Read this before writing rather than guessing headings — a section the type does not define is rejected.\",\n input: z.object({}),\n fromArgv: () => ({}),\n run: () => Promise.resolve(RECORD_TYPES),\n});\n","import { z } from \"zod\";\nimport { unpinBase } from \"../kb-pins/index.js\";\nimport { bundlePath, define } from \"./model.js\";\n\nexport const unpinCommand = define({\n name: \"unpin\",\n tool: \"kb_unpin\",\n usage: \"unpin [bundle-path]\",\n description:\n \"Remove a base from every manifest layer that holds it. Reports the layers touched.\",\n input: z.object({ bundlePath }),\n fromArgv: (argv, path) => ({ bundlePath: argv[1] ?? path }),\n run: (_ctx, { bundlePath: path }) => unpinBase(process.cwd(), path),\n});\n","import { z } from \"zod\";\nimport { validateBundle, type KbValidationProblem } from \"../validate.js\";\nimport { bundlePath, define } from \"./model.js\";\n\nexport const validateCommand = define({\n name: \"validate\",\n tool: \"kb_validate\",\n usage: \"validate\",\n description:\n \"Check pointers no single record can see: supersession links that disagree between the two records, typed causal links, and assumptions that cite sources. Each finding carries a severity: errors fail the exit code, warnings do not.\",\n input: z.object({ bundlePath }),\n fromArgv: (_argv, path) => ({ bundlePath: path }),\n run: async ({ store }, { bundlePath: path }) =>\n validateBundle(await store.list(path)),\n // Warnings never fail the exit code; every other severity does.\n failsWhen: (result) =>\n Array.isArray(result) &&\n (result as KbValidationProblem[]).some(\n (problem) => problem.severity !== \"warning\",\n ),\n});\n","import { z } from \"zod\";\nimport { assertBaseNotFrozen } from \"../kb-pins/index.js\";\nimport { argvFlag, bundlePath, conceptId, define } from \"./model.js\";\n\nexport const verifyCommand = define({\n name: \"verify\",\n tool: \"kb_verify\",\n usage: \"verify <concept-id> --note <text>\",\n description:\n \"Append a verified[] event: who checked, when, and what was found. Append-only. A record's own generator is refused unless the actor is `human:`-prefixed.\",\n input: z.object({\n bundlePath,\n conceptId,\n note: z.string().refine((s) => s.trim().length > 0, {\n message: \"note must say what the check found\",\n }),\n }),\n fromArgv: (argv, path) => ({\n bundlePath: path,\n conceptId: argv[1],\n note: argvFlag(argv, \"--note\"),\n }),\n run: async (\n { store, actor, now },\n { bundlePath: path, conceptId: id, note },\n ) => {\n await assertBaseNotFrozen(process.cwd(), path);\n const record = await store.verify(path, id, note, actor, now());\n return {\n conceptId: record.conceptId,\n verified: record.frontmatter.verified?.length ?? 0,\n };\n },\n});\n","import { z } from \"zod\";\nimport { composeInputSchema, composeRecord } from \"../compose.js\";\nimport { assertBaseNotFrozen } from \"../kb-pins/index.js\";\nimport { KB_RECORD_TYPES, type KbRecordType } from \"../kb-record.schema.js\";\nimport { bundlePath, define } from \"./model.js\";\n\nexport const writeCommand = define({\n name: \"write\",\n tool: \"kb_write\",\n usage: \"write <type> < record.json\",\n description:\n \"Write one record. Search first — a duplicate concept id is rejected, not overwritten; kb_types lists each type's sections. An unsourced claim is an `assumption` with assumption: true, never a vague `fact`. Conflicting records get a `risk`, `open-question`, or superseding `decision`. Prefer a new short record over overloading one. Never delete; supersede.\",\n input: z.object({\n bundlePath,\n type: z.enum(KB_RECORD_TYPES),\n input: composeInputSchema,\n }),\n fromArgv: async (argv, path, stdin) => ({\n bundlePath: path,\n type: argv[1],\n input: JSON.parse(await stdin()) as unknown,\n }),\n run: async ({ store, actor, now }, { bundlePath: path, type, input }) => {\n await assertBaseNotFrozen(process.cwd(), path);\n const record = await store.write(\n path,\n composeRecord(type as KbRecordType, input, actor, now()),\n actor,\n );\n return {\n conceptId: record.conceptId,\n action: record.action,\n supersededIds: record.supersededIds,\n };\n },\n});\n","import { z } from \"zod\";\nimport {\n composeDecisionRecord,\n decisionInputSchema,\n} from \"../decision-record.js\";\nimport { assertBaseNotFrozen } from \"../kb-pins/index.js\";\nimport { bundlePath, define } from \"./model.js\";\n\nexport const writeDecisionCommand = define({\n name: \"write-decision\",\n tool: \"kb_write_decision\",\n usage: \"write-decision < decision.json\",\n description:\n \"Write a decision, with `alternative` (what was rejected and why) and `impact` as fields. Record one when a later reader would otherwise simplify the constraint away; skip when the diff already answers it. `sources` for material read, `anchors` for code, `relatedConceptIds` for records.\",\n input: z.object({ bundlePath, input: decisionInputSchema }),\n fromArgv: async (_argv, path, stdin) => ({\n bundlePath: path,\n input: JSON.parse(await stdin()) as unknown,\n }),\n run: async ({ store, actor, now }, { bundlePath: path, input }) => {\n await assertBaseNotFrozen(process.cwd(), path);\n const record = await store.write(\n path,\n composeDecisionRecord(input, actor, now()),\n actor,\n );\n return {\n conceptId: record.conceptId,\n action: record.action,\n supersededIds: record.supersededIds,\n };\n },\n});\n","/**\n * The command table, assembled from one file per command.\n *\n * Order is the CLI usage listing's order: the write path, the read path,\n * base housekeeping, the format, and the workspace pin verbs.\n */\nimport { DECISION_TYPE } from \"../decision-record.js\";\nimport { anchorResolveCommand } from \"./anchor-resolve/index.js\";\nimport { anchorSetCommand } from \"./anchor-set/index.js\";\nimport { answerCommand } from \"./answer.js\";\nimport { backlinksCommand } from \"./backlinks.js\";\nimport { catalogCommand } from \"./catalog.js\";\nimport { classifyCommand } from \"./classify.js\";\nimport { contextCommand } from \"./context.js\";\nimport { doctorCommand } from \"./doctor.js\";\nimport { exportCommand } from \"./export.js\";\nimport { impactCommand } from \"./impact.js\";\nimport { listCommand } from \"./list.js\";\nimport { loadCommand } from \"./load.js\";\nimport { logCommand } from \"./log.js\";\nimport { matchCommand } from \"./match/index.js\";\nimport { noDecisionCommand } from \"./no-decision.js\";\nimport { packCommand } from \"./pack.js\";\nimport { pinCommand } from \"./pin.js\";\nimport { pinsCommand } from \"./pins.js\";\nimport { promoteCommand } from \"./promote/index.js\";\nimport { queryCommand } from \"./query.js\";\nimport { readIndexCommand } from \"./read-index.js\";\nimport { reassessCommand } from \"./reassess.js\";\nimport { schemaCommand } from \"./schema.js\";\nimport { stampCommand } from \"./stamp.js\";\nimport { statusCommand } from \"./status.js\";\nimport { supersedeCommand } from \"./supersede.js\";\nimport { sweepCommand } from \"./sweep.js\";\nimport { syncInstructionsCommand } from \"./sync-instructions.js\";\nimport { traceCommand } from \"./trace.js\";\nimport { typesCommand } from \"./types.js\";\nimport { unpinCommand } from \"./unpin.js\";\nimport { validateCommand } from \"./validate.js\";\nimport { verifyCommand } from \"./verify.js\";\nimport { writeCommand } from \"./write.js\";\nimport { writeDecisionCommand } from \"./write-decision.js\";\nimport type { KbCommand } from \"./model.js\";\n\nexport const KB_COMMANDS: KbCommand[] = [\n writeCommand,\n writeDecisionCommand,\n noDecisionCommand,\n statusCommand,\n supersedeCommand,\n answerCommand,\n verifyCommand,\n anchorResolveCommand,\n anchorSetCommand,\n reassessCommand,\n promoteCommand,\n loadCommand,\n catalogCommand,\n packCommand,\n exportCommand,\n queryCommand,\n traceCommand,\n impactCommand,\n backlinksCommand,\n matchCommand,\n classifyCommand,\n listCommand,\n readIndexCommand,\n logCommand,\n stampCommand,\n validateCommand,\n doctorCommand,\n sweepCommand,\n schemaCommand,\n pinCommand,\n unpinCommand,\n pinsCommand,\n contextCommand,\n syncInstructionsCommand,\n typesCommand,\n];\n\nexport const KB_COMMANDS_BY_NAME = new Map(\n KB_COMMANDS.map((command) => [command.name, command]),\n);\n\nexport { DECISION_TYPE };\nexport type { KbCommand, KbCommandContext } from \"./model.js\";\n","import matter from \"gray-matter\";\nimport type { z } from \"zod\";\n\n/**\n * Frontmatter round-tripping, thin over gray-matter.\n *\n * Thin on purpose. A record is a YAML block and a markdown body, and every\n * hand-rolled reader of that shape eventually meets a nested map — an OKF\n * `generated`, a `sources[]`, a `verified[]` — and misreads it. The parser is\n * therefore borrowed and the only thing added is the schema gate below.\n */\nexport function stringifyMarkdownWithFrontmatter(\n content: string,\n frontmatter: Record<string, unknown>,\n): string {\n return matter.stringify(content, frontmatter);\n}\n\nexport function splitMarkdownFrontmatter(text: string): {\n content: string;\n prefix: string;\n raw: Record<string, unknown>;\n} {\n const file = matter(text);\n\n return {\n content: file.content,\n // Everything gray-matter consumed: the fences, the YAML, and the blank line\n // after them. Kept so a caller can rewrite a body without touching the head.\n prefix: text.slice(0, text.length - file.content.length),\n raw: file.data as Record<string, unknown>,\n };\n}\n\n/**\n * Splits, then validates the frontmatter against a schema.\n *\n * The result is a `safeParse` outcome rather than a throw: one malformed record\n * must not make a whole directory unreadable, so the caller decides whether to\n * skip it or fail.\n */\nexport function parseMarkdownWithFrontmatter<S extends z.ZodType>(\n text: string,\n schema: S,\n): {\n content: string;\n prefix: string;\n raw: Record<string, unknown>;\n frontmatter: ReturnType<S[\"safeParse\"]>;\n} {\n const { content, prefix, raw } = splitMarkdownFrontmatter(text);\n\n return {\n content,\n prefix,\n raw,\n frontmatter: schema.safeParse(raw) as ReturnType<S[\"safeParse\"]>,\n };\n}\n","import { stat } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { DEFAULT_IO_CONCURRENCY, mapLimit } from \"./concurrency.js\";\nimport { INDEX_FILE } from \"./kb-index.js\";\nimport { LOG_FILE } from \"./kb-log.js\";\n\nexport const SEARCH_INDEX_FILE = \".index.sqlite\";\n\nconst COLLECTION = \"kb\";\n\n/**\n * BM25 over one knowledge base, via qmd's SDK.\n *\n * Reached only when a base is too large to hand over whole — see `load()`,\n * which is the first thing a reader should try.\n *\n * Lexical only. `searchLex` is BM25 and needs no model. Measured against the\n * substring scan it replaces it wins on word forms and little else: `pages`\n * finds a record saying only `page`, and eight of nine probe queries returned\n * exactly what substring returned.\n *\n * The vector tier does close the semantic gap — \"why not just use a mutex\"\n * finds the record about compare-and-swap, which no lexical match can. It stays\n * off because its scores do not separate right from wrong: a wrong hit scored\n * 0.318 against a correct one at 0.295, and a query about a subject absent from\n * the base still returns its nearest record rather than nothing.\n *\n * The index is derived and disposable — one file per base, gitignored, deleted\n * and rebuilt at will. That is only true because a base is self-contained: an\n * index covering exactly one directory can always be rebuilt from it.\n *\n * qmd is used as a **library**, and is an optional peer dependency: with it\n * absent every path here still answers, `searchBase` returns null, and the\n * store falls back to a substring scan. Its own MCP server would let an agent\n * reach a base without passing the store, and its default markdown glob would\n * return `INDEX.md` as a search hit — the case `list()` already excludes,\n * reintroduced by a reader this package does not control. Hence the explicit\n * `ignore` below.\n */\n/**\n * A hit as qmd reports it — by its own normalised path, not by our identity.\n *\n * qmd rewrites `decision.cursor-keyset.md` to `decision-cursor-keyset.md`,\n * which destroys the separator between a record's type and its slug and cannot\n * be undone from the string alone: `decision-cursor-keyset` could be the type\n * `decision` or a type `decision-cursor`. The caller maps these back through\n * the records it already holds rather than parsing them.\n */\nexport type SearchHit = { displayPath: string; score: number };\n\ntype QmdStore = {\n searchLex(\n query: string,\n options?: { limit?: number; collection?: string },\n ): Promise<{ displayPath?: string; filepath?: string; score?: number }[]>;\n addCollection(\n name: string,\n opts: { path: string; pattern?: string; ignore?: string[] },\n ): Promise<void>;\n listCollections(): Promise<unknown[]>;\n update(options?: { collections?: string[] }): Promise<unknown>;\n close(): Promise<void>;\n};\n\nexport type KbSearchLogger = {\n warn?(entry: Record<string, unknown>): void;\n};\n\n/** What this module needs of qmd, which is all it is allowed to assume. */\nexport type QmdModule = { createStore(options: unknown): Promise<unknown> };\n\nexport type SearchOptions = {\n limit?: number;\n logger?: KbSearchLogger;\n /**\n * The backend, supplied rather than imported. Production passes nothing and\n * gets the dynamic import below; a caller that already holds qmd — or a test\n * covering the present-backend branch on a machine where the optional peer is\n * not installed — passes it here.\n */\n qmd?: QmdModule;\n};\n\n/**\n * Opens (or creates) the base's index and answers a query against it.\n *\n * Re-indexes when the index is older than the newest record rather than on a\n * schedule or a write hook: the same repair-on-read rule `INDEX.md` follows,\n * and for the same reason — a derived artifact that can rebuild itself does not\n * need anyone to remember to rebuild it.\n */\nexport async function searchBase(\n bundlePath: string,\n query: string,\n options: SearchOptions = {},\n): Promise<SearchHit[] | null> {\n const qmd = options.qmd ?? (await loadQmd(options.logger));\n if (!qmd) return null;\n\n let store: QmdStore | null = null;\n try {\n store = (await qmd.createStore({\n dbPath: join(bundlePath, SEARCH_INDEX_FILE),\n config: {\n collections: {\n [COLLECTION]: {\n path: bundlePath,\n pattern: \"**/*.md\",\n // Both store-owned files are markdown and neither is a record.\n ignore: [INDEX_FILE, LOG_FILE],\n },\n },\n },\n })) as QmdStore;\n\n if (await isStale(bundlePath)) {\n await store.update({ collections: [COLLECTION] });\n }\n\n const hits = await store.searchLex(query, {\n collection: COLLECTION,\n ...(options.limit ? { limit: options.limit } : {}),\n });\n return hits\n .map((hit) => ({\n displayPath: hit.displayPath ?? hit.filepath ?? \"\",\n score: hit.score ?? 0,\n }))\n .filter((hit) => hit.displayPath.length > 0);\n } catch (error) {\n // A search index is an optimisation. Losing it must degrade recall, never\n // the answer — `query()` falls back to substring rather than failing.\n options.logger?.warn?.({\n operation: \"kb.search\",\n outcome: \"unavailable\",\n error: error instanceof Error ? error.message : \"unknown\",\n });\n return null;\n } finally {\n await store?.close().catch(() => undefined);\n }\n}\n\n/**\n * Whether any record is newer than the index.\n *\n * Stats run through a bounded pool rather than one at a time; once one record\n * has answered \"newer\", the workers still queued skip their `stat` entirely.\n */\nasync function isStale(bundlePath: string): Promise<boolean> {\n const indexAt = await stat(join(bundlePath, SEARCH_INDEX_FILE))\n .then((s) => s.mtimeMs)\n .catch(() => 0);\n if (!indexAt) return true;\n\n const { readdir } = await import(\"node:fs/promises\");\n const names = (await readdir(bundlePath).catch(() => [] as string[])).filter(\n (name) => name.endsWith(\".md\") && name !== INDEX_FILE,\n );\n\n let stale = false;\n await mapLimit(names, DEFAULT_IO_CONCURRENCY, async (name) => {\n if (stale) return;\n const at = await stat(join(bundlePath, name))\n .then((s) => s.mtimeMs)\n .catch(() => 0);\n if (at > indexAt) stale = true;\n });\n return stale;\n}\n\n/**\n * Maps qmd's normalised paths back onto real records.\n *\n * Comparing on the same normalisation rather than trying to invert it: a dot in\n * a concept id and a dash in a slug are indistinguishable once qmd has rewritten\n * the name, so the only reliable direction is forwards, from ids we hold.\n */\nexport function resolveHits<T extends { conceptId: string }>(\n hits: SearchHit[],\n records: T[],\n): T[] {\n const byName = new Map<string, T>();\n for (const record of records) {\n const name = flatten(record.conceptId);\n // A collision would make the mapping a guess; drop both rather than pick.\n if (byName.has(name)) byName.delete(name);\n else byName.set(name, record);\n }\n\n const resolved: T[] = [];\n for (const hit of hits) {\n const file = hit.displayPath.split(\"/\").pop() ?? \"\";\n const name = file.endsWith(\".md\") ? file.slice(0, -\".md\".length) : file;\n const record = byName.get(flatten(name));\n if (record) resolved.push(record);\n }\n return resolved;\n}\n\nfunction flatten(value: string): string {\n return value.replace(/[.]/g, \"-\").toLowerCase();\n}\n\n/**\n * Held in a variable rather than written inline. qmd is not a dependency of\n * this package, so a literal specifier sends the compiler looking for types\n * that are not installed; the indirection keeps the import dynamic at runtime\n * and invisible at build time, which is what an optional engine needs.\n */\nconst QMD_MODULE = \"@tobilu/qmd\";\n\n/**\n * Loaded on demand so a caller that never searches pays nothing for a\n * dependency that pulls in native SQLite bindings and a llama runtime — and\n * returns null rather than throwing when it is not installed at all, which is\n * the normal case for an optional peer.\n */\nexport async function loadQmd(\n logger?: KbSearchLogger,\n): Promise<QmdModule | null> {\n try {\n return (await import(QMD_MODULE)) as unknown as QmdModule;\n } catch {\n logger?.warn?.({ operation: \"kb.search\", outcome: \"qmd-unavailable\" });\n return null;\n }\n}\n","import {\n appendFile,\n link,\n mkdir,\n readdir,\n readFile,\n rename,\n unlink,\n writeFile,\n} from \"node:fs/promises\";\nimport { join, resolve, sep } from \"node:path\";\nimport { DEFAULT_IO_CONCURRENCY, mapLimit } from \"./concurrency.js\";\nimport {\n parseMarkdownWithFrontmatter,\n stringifyMarkdownWithFrontmatter,\n} from \"./markdown.js\";\nimport {\n kbAnchorWriteSchema,\n kbRecordFrontmatterSchema,\n kbVerifiedEventSchema,\n KB_SLUG_PATTERN,\n type KbAnchor,\n type KbRecord,\n type KbRecordFrontmatter,\n type KbRecordStatus,\n} from \"./kb-record.schema.js\";\nimport {\n KbInvalidActorError,\n KbInvalidConceptIdError,\n KbRecordAlreadyExistsError,\n KbRecordNotFoundError,\n KbSelfVerificationError,\n KbWriteConflictError,\n} from \"./kb-errors.js\";\nimport { INDEX_FILE, indexIsStale, renderIndex } from \"./kb-index.js\";\nimport { adjudicate, type KbAdjudicated } from \"./adjudicate.js\";\nimport {\n bundleDigest,\n bundleStamp,\n sha256 as digest,\n type KbRecordStamp,\n} from \"./kb-stamp.js\";\nimport {\n detectAnchorDrift,\n looksLikeWrongRepoRoot,\n type KbAnchorDriftEntry,\n} from \"./anchor-resolver/index.js\";\nimport { isUncheckedReason } from \"./remote-repo/index.js\";\nimport { resolveHits, searchBase, SEARCH_INDEX_FILE } from \"./search-index.js\";\nimport { trace, type KbTraceOptions, type KbTraceStep } from \"./trace.js\";\nimport { pack, type KbPackOptions, type KbPackResult } from \"./pack.js\";\nimport { catalog, type KbCatalogResult } from \"./catalog.js\";\nimport { matchesTags, type KbTagFilter } from \"./kb-tags.js\";\nimport {\n backlinks,\n impact,\n type KbBacklinksResult,\n type KbImpactOptions,\n type KbImpactResult,\n} from \"./kb-links/index.js\";\nimport {\n LOG_FILE,\n parseLog,\n renderLogEntry,\n type KbLogEntry,\n} from \"./kb-log.js\";\nimport {\n appendGitattributesLines,\n GITATTRIBUTES_FILE,\n} from \"./kb-gitattributes.js\";\nimport { STORE_OWNED_FILES } from \"./kb-files.js\";\n\n/**\n * Default bundle, relative to the working directory. A scratch base lives here\n * and is meant to be gitignored; a base worth keeping is written to a committed\n * path instead, passed explicitly. Nothing promotes one to the other.\n */\nexport const KB_DIR = join(\".strauss\", \"kb\");\n\nconst STORE_OWNED = new Set(STORE_OWNED_FILES);\n\nexport type KbLogger = {\n info?(entry: Record<string, unknown>): void;\n warn?(entry: Record<string, unknown>): void;\n};\n\n/** Roughly an eighth of a large context window — generous, and overridable. */\nexport const DEFAULT_LOAD_BUDGET = 25_000;\n\n/**\n * A superseded record, named but not spelled out.\n *\n * Standing is a qualifier on a body, and over a long session the body outlives\n * the qualifier — the reader keeps what the record said and loses that it no\n * longer holds. A stub has nothing left to act on, so the failure cannot occur,\n * and `trace` still reaches the content through the id.\n */\nexport type KbSupersededStub = {\n conceptId: string;\n title: string | null;\n supersededBy: string[];\n at: string | null;\n};\n\nexport type KbLoadResult =\n | {\n loaded: true;\n records: KbAdjudicated[];\n /** Named only. Their bodies are reachable through `trace`. */\n superseded: KbSupersededStub[];\n recordCount: number;\n tokensLoaded: number;\n /** `null` when loaded via `all`: no ceiling was applied. */\n budgetTokens: number | null;\n /**\n * Sha256 over every record's content and standing, sorted by concept\n * id. Flips when a body, frontmatter, or standing changes; it's the\n * base's content stamp, compared by hooks and `kb_stamp` (SAA-719).\n */\n digest: string;\n }\n | {\n loaded: false;\n recordCount: number;\n approxTokens: number;\n budgetTokens: number;\n /** The refusal in words, naming the budget and what to call next. */\n message: string;\n /**\n * Same digest a successful load would carry, computed over what would\n * have been handed back. Cheap here — adjudication already ran before\n * the refusal — and it lets a caller notice a refused bundle's content\n * changed (say, after a narrower `type` filter) without loading it.\n */\n digest: string;\n };\n\n/** What `stamp` reports for one base. See `kb-stamp.ts`. */\nexport type KbStampResult = {\n path: string;\n digest: string;\n recordCount: number;\n superseded: number;\n /** Newest `generated.at` across the base, or null when none carries one. */\n newestAt: string | null;\n records: KbRecordStamp[];\n /**\n * Records with at least one anchor whose code no longer matches its hash.\n *\n * Outside the digest, and deliberately: drift is a fact about the working\n * tree, not about the base's content, and folding it in would make a stamp\n * change every time someone checked out a branch. `null` when the drift pass\n * could not run — an unknown count, which is not zero.\n */\n drifted: number | null;\n};\n\nexport type KbWriteInput = {\n type: string;\n slug: string;\n frontmatter: Omit<KbRecordFrontmatter, \"type\">;\n body: string;\n /** Replace an existing record rather than failing on the collision. */\n overwrite?: boolean;\n};\n\n/**\n * What a patching caller hands `updateAnchors`. Omitting `log` keeps the\n * default `anchor-resolve` entry.\n */\nexport type KbAnchorWrite = {\n anchors: KbAnchor[];\n log?: Omit<KbLogEntry, \"at\" | \"conceptId\" | \"by\">;\n};\n\n/** What a record had to still be for `deleteRecord` to remove it. */\nexport type KbDeleteExpectation = {\n tag: string;\n statuses: readonly KbRecordStatus[];\n};\n\n/** Whether the delete landed, or the record left that scope first. */\nexport type KbDeleteOutcome = \"deleted\" | \"changed-since-listing\";\n\nexport type KbWriteResult = KbRecord & {\n /** Whether this write also marked prior records superseded. */\n action: \"created\" | \"superseded-prior\";\n /** `frontmatter.strauss_supersedes` ids that were actually marked. */\n supersededIds: string[];\n};\n\n/**\n * Reads and writes a knowledge bundle.\n *\n * One record per file, deliberately. Several agents run in parallel against the\n * same bundle, and a shared file would need merging — a file-per-record store\n * has no write conflict to resolve, only distinct filenames to choose.\n *\n * The bundle is addressed by path rather than fixed to one directory. A base\n * belongs to whatever prompted it — a worktree, an investigation, a document —\n * and one hardcoded location cannot be all of those.\n *\n * Framework-free on purpose. The consumers are a library caller, a CLI an agent\n * shells out to, and an MCP server; the store takes a logger rather than\n * reaching for one, because only some of those have anything to reach into.\n */\nexport class KbStore {\n constructor(private readonly logger: KbLogger = {}) {}\n\n /**\n * Writes one record. `type` and `slug` compose both the filename and the\n * concept id, so a caller cannot produce a file whose identity disagrees with\n * its contents.\n */\n async write(\n bundlePath: string,\n input: KbWriteInput,\n actor = \"unknown\",\n ): Promise<KbWriteResult> {\n assertActor(actor);\n if (!KB_SLUG_PATTERN.test(input.slug)) {\n throw new KbInvalidConceptIdError(\"slug must be kebab-case\", {\n slug: input.slug,\n });\n }\n if (!KB_SLUG_PATTERN.test(input.type)) {\n throw new KbInvalidConceptIdError(\"type must be kebab-case\", {\n type: input.type,\n });\n }\n\n const frontmatter = kbRecordFrontmatterSchema.parse({\n ...input.frontmatter,\n type: input.type,\n });\n const conceptId = `${input.type}.${input.slug}`;\n const root = this.root(bundlePath);\n const target = this.recordPath(bundlePath, conceptId);\n\n await mkdir(root, { recursive: true });\n await this.publish(\n target,\n stringifyMarkdownWithFrontmatter(input.body, frontmatter),\n input.overwrite ?? false,\n conceptId,\n );\n\n await this.record(root, {\n operation: input.overwrite ? \"overwrite\" : \"write\",\n conceptId,\n by: actor,\n });\n\n // The new record is published and logged first, then each prior record it\n // supersedes is marked. A crash between the two leaves an old\n // record with no backlink — exactly what kb_validate already reports as\n // \"<old> is not marked superseded\", never a silent drift.\n //\n // Naming itself is a no-op, not an error — the record is already itself.\n // Duplicates collapse through the Set, so a repeated id marks once.\n const targets = new Set(frontmatter.strauss_supersedes ?? []);\n targets.delete(conceptId);\n\n // Targets are marked sequentially, in order: targets are 1-3 in practice,\n // and marking them concurrently made log.jsonl entry order depend on\n // which retry finished first rather than on strauss_supersedes order.\n const supersededIds: string[] = [];\n for (const old of targets) {\n if (\n await this.markSupersededRetrying(bundlePath, old, conceptId, actor)\n ) {\n supersededIds.push(old);\n }\n }\n\n this.logger.info?.({\n operation: \"kb.write\",\n bundlePath: root,\n conceptId,\n anchors: frontmatter.strauss_anchors?.length ?? 0,\n });\n\n return {\n conceptId,\n frontmatter,\n body: input.body,\n action: supersededIds.length ? \"superseded-prior\" : \"created\",\n supersededIds,\n };\n }\n\n /** One record by concept id, or null when it does not exist. */\n async read(bundlePath: string, conceptId: string): Promise<KbRecord | null> {\n // Resolved outside the try: the `catch` exists to turn a missing file into\n // `null`, and must not also swallow the concept-id validation below it.\n const target = this.recordPath(bundlePath, conceptId);\n let raw: string;\n try {\n raw = await readFile(target, \"utf8\");\n } catch {\n return null;\n }\n return this.parse(conceptId, raw);\n }\n\n /**\n * Every record in the bundle, optionally narrowed to one type and to the\n * records carrying every tag in `filter.tags`. Selection only — `excludeTags`\n * is not taken here, because `query`, `catalog` and `load` read through this\n * and must adjudicate over the whole base.\n *\n * A file that fails to parse is skipped and logged rather than thrown: one\n * malformed record — hand-edited, or written by a producer we don't know —\n * must not make the whole bundle unreadable.\n */\n async list(\n bundlePath: string,\n type?: string,\n filter: { tags?: string[] } = {},\n ): Promise<KbRecord[]> {\n const root = this.root(bundlePath);\n let names: string[];\n try {\n names = await readdir(root);\n } catch {\n return [];\n }\n\n // The type filter runs on the filename, so a narrowed list never opens a\n // record it is going to discard. What remains is read concurrently: the\n // cost here is per-file syscall latency, not CPU.\n const wanted = names\n .sort()\n // Both store-owned files are markdown and neither is a record; without\n // this they parse to null and are dropped, but not before logging a\n // warning that says the bundle contains a malformed record.\n .filter((name) => name.endsWith(\".md\") && !STORE_OWNED.has(name))\n .map((name) => ({ name, conceptId: name.slice(0, -\".md\".length) }))\n .filter(({ conceptId }) => !type || conceptId.startsWith(`${type}.`));\n\n const records = await mapLimit(\n wanted,\n DEFAULT_IO_CONCURRENCY,\n async ({ name, conceptId }) =>\n this.parse(conceptId, await readFile(join(root, name), \"utf8\")),\n );\n return records.filter(\n (record): record is KbRecord =>\n record !== null && matchesTags(record, filter),\n );\n }\n\n /**\n * Moves a record's status, preserving everything else.\n *\n * Read-modify-write on one file is the one place two agents genuinely race,\n * and the fix is a compare-and-swap rather than a lock: hash on read, verify\n * the file is unchanged immediately before writing, fail if it moved. A lock\n * would buy the same guarantee and add a stale-lock failure mode — a writer\n * killed mid-hold blocks every later one until someone reasons about\n * timeouts.\n */\n async setStatus(\n bundlePath: string,\n conceptId: string,\n status: KbRecordStatus,\n actor = \"unknown\",\n ): Promise<KbRecord> {\n assertActor(actor);\n return this.mutate(\n bundlePath,\n conceptId,\n (frontmatter) => ({ ...frontmatter, strauss_status: status }),\n { operation: `status:${status}`, by: actor },\n );\n }\n\n /**\n * Replaces a record's anchors, preserving everything else. An array is the\n * whole set; a function is a patch and runs inside the mutation, against\n * the anchors the record holds then — see\n * `decision.anchor-update-patch-inside-mutation`.\n */\n async updateAnchors(\n bundlePath: string,\n conceptId: string,\n anchors: KbAnchor[] | ((current: KbAnchor[]) => KbAnchorWrite),\n actor = \"unknown\",\n ): Promise<KbRecord> {\n assertActor(actor);\n let entry: Omit<KbLogEntry, \"at\" | \"conceptId\"> = {\n operation: \"anchor-resolve\",\n by: actor,\n };\n return this.mutate(\n bundlePath,\n conceptId,\n (frontmatter) => {\n const write =\n typeof anchors === \"function\"\n ? anchors(frontmatter.strauss_anchors ?? [])\n : { anchors };\n if (write.log) entry = { ...write.log, by: actor };\n return {\n ...frontmatter,\n strauss_anchors: write.anchors.map((anchor) =>\n kbAnchorWriteSchema.parse(anchor),\n ),\n };\n },\n () => entry,\n );\n }\n\n /**\n * Appends one `verified[]` event: who checked the record, when, and what the\n * check found. Append-only — prior events are history, and are spread into\n * the new array untouched rather than reshaped through the write schema.\n *\n * A record's generator cannot verify its own record unless the actor is\n * human: the generator re-reading its own output is not an independent\n * check. The rule runs before the mutation so a refusal never publishes,\n * and the refusal is logged under its own operation name — `mutate` only\n * logs what it publishes.\n */\n async verify(\n bundlePath: string,\n conceptId: string,\n note: string,\n actor = \"unknown\",\n at = new Date().toISOString(),\n ): Promise<KbRecord> {\n assertActor(actor, { named: true });\n const event = kbVerifiedEventSchema.parse({ by: actor, at, note });\n\n const existing = await this.read(bundlePath, conceptId);\n if (!existing) throw new KbRecordNotFoundError(conceptId);\n\n // The equality test compares whole actors case-insensitively: case drift\n // (`agent:Claude` vs `agent:claude`) must not mint a distinct verifier\n // identity. Only the `human:` exemption keeps the prefix-only\n // normalization.\n const generatedBy = existing.frontmatter.generated?.by;\n if (\n generatedBy !== undefined &&\n actor.toLowerCase() === generatedBy.toLowerCase() &&\n !normalizeActor(actor).startsWith(\"human:\")\n ) {\n await this.record(this.root(bundlePath), {\n operation: \"verify:refused\",\n conceptId,\n by: actor,\n });\n throw new KbSelfVerificationError(conceptId, actor, generatedBy);\n }\n\n return this.mutate(\n bundlePath,\n conceptId,\n (frontmatter) => ({\n ...frontmatter,\n verified: [...(frontmatter.verified ?? []), event],\n }),\n { operation: \"verify\", by: actor },\n );\n }\n\n /**\n * Marks `conceptId` superseded by `replacementId`, and links both directions.\n *\n * Writing one side and letting a validator notice the other is missing was\n * the previous arrangement; doing both here means the backlink cannot drift\n * in normal use, and validation drops to catching hand-edits.\n */\n async supersede(\n bundlePath: string,\n conceptId: string,\n replacementId: string,\n actor = \"unknown\",\n ): Promise<KbRecord> {\n assertActor(actor);\n const replacement = await this.read(bundlePath, replacementId);\n if (!replacement) throw new KbRecordNotFoundError(replacementId);\n\n const superseded = await this.markSuperseded(\n bundlePath,\n conceptId,\n replacementId,\n actor,\n );\n\n await this.mutate(\n bundlePath,\n replacementId,\n (frontmatter) => ({\n ...frontmatter,\n strauss_supersedes: [\n ...new Set([...(frontmatter.strauss_supersedes ?? []), conceptId]),\n ],\n }),\n { operation: \"supersedes\", by: actor, target: conceptId },\n );\n\n return superseded;\n }\n\n /** Resolves an open question, stamping who answered and when. */\n async answer(\n bundlePath: string,\n conceptId: string,\n answer: string,\n actor = \"unknown\",\n at = new Date().toISOString(),\n ): Promise<KbRecord> {\n assertActor(actor);\n return this.mutate(\n bundlePath,\n conceptId,\n (frontmatter) => ({\n ...frontmatter,\n strauss_status: \"resolved\" as const,\n strauss_answered: { by: actor, at },\n }),\n { operation: \"answer\", by: actor },\n (body) => `${body.trimEnd()}\\n\\n## Answer\\n\\n${answer}\\n`,\n );\n }\n\n /**\n * Removes one record, logged as `sweep`. The only path in this store that\n * deletes — see the specification for the scope that makes it safe.\n *\n * `expected` is re-read and re-checked immediately before the unlink, the\n * compare-and-swap `mutate` makes: a record retagged or moved out of a\n * terminal status since the caller listed it is reported, not removed.\n */\n async deleteRecord(\n bundlePath: string,\n conceptId: string,\n expected: KbDeleteExpectation,\n actor = \"unknown\",\n ): Promise<KbDeleteOutcome> {\n assertActor(actor);\n const target = this.recordPath(bundlePath, conceptId);\n const witness = await this.read(bundlePath, conceptId);\n if (!witness) throw new KbRecordNotFoundError(conceptId);\n\n const { tags, strauss_status } = witness.frontmatter;\n if (\n !(tags ?? []).includes(expected.tag) ||\n !expected.statuses.includes(strauss_status)\n ) {\n return \"changed-since-listing\";\n }\n\n try {\n await unlink(target);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n throw new KbRecordNotFoundError(conceptId);\n }\n await this.record(this.root(bundlePath), {\n operation: \"sweep\",\n by: actor,\n conceptId,\n });\n return \"deleted\";\n }\n\n /**\n * Records matching a text query, each carrying its standing.\n *\n * Relevance comes from qmd's BM25 where an index is available and from a\n * substring scan where it is not. What never moves to the ranker is the\n * adjudication below it: a ranker answers relevance, and relevance is not\n * standing — a superseded record is the older, longer, more general one, so\n * ranking alone prefers what is no longer true.\n *\n * The fallback is deliberate. A search index is an optimisation, so losing it\n * degrades recall and must never change the answer's shape or fail the call.\n */\n async query(\n bundlePath: string,\n text: string,\n options: {\n type?: string;\n includeNonCurrent?: boolean;\n repoRoot?: string;\n } & KbTagFilter = {},\n ): Promise<KbAdjudicated[]> {\n const bundle = await this.list(bundlePath);\n const needle = text.trim();\n const hits = needle ? await this.rank(bundlePath, needle, bundle) : bundle;\n const narrowed = options.type\n ? hits.filter((r) => r.frontmatter.type === options.type)\n : hits;\n const adjudicated = adjudicate(\n narrowed,\n bundle,\n new Date(),\n await this.detectDrift(narrowed, options.repoRoot),\n );\n\n // Tags cut after adjudication: a tag narrows what is returned, never what\n // anything's standing is or which record replaced it.\n const kept = adjudicated.filter((hit) => matchesTags(hit.record, options));\n\n if (options.includeNonCurrent) return kept;\n // Superseded records are dropped only once their replacement is in the\n // result too — otherwise the caller loses the thread entirely rather than\n // being handed a newer version of it. Over `kept`, so a replacement the\n // tag filter cut cannot silence the record it replaced.\n const present = new Set(kept.map((hit) => hit.record.conceptId));\n return kept.filter(\n (hit) =>\n hit.standing !== \"superseded\" ||\n !hit.heads.some((head) => present.has(head.conceptId)),\n );\n }\n\n private async rank(\n bundlePath: string,\n needle: string,\n bundle: KbRecord[],\n ): Promise<KbRecord[]> {\n const ranked = await searchBase(this.root(bundlePath), needle, {\n logger: this.logger,\n });\n if (ranked) {\n const found = resolveHits(ranked, bundle);\n if (found.length) return found;\n }\n const lowered = needle.toLowerCase();\n return bundle.filter((record) => matches(record, lowered));\n }\n\n /**\n * Anchor drift over the records about to be handed back. Like the search\n * index, this is an enrichment: a filesystem failure degrades to \"no drift\n * reported\" rather than failing the read. Anchors without a stored hash are\n * skipped inside `detectAnchorDrift`, so a base nobody has stamped pays no\n * fs cost here. `repoRoot` defaults to the working directory — the CLI runs\n * at the repo root, and the MCP server's cwd is the workspace.\n *\n * Public because `doctor` needs the same map with the same degradation: a\n * sweep that failed to read the tree should report no drift, not fail — and\n * `offline: false` there, because a sweep is worth a fetch.\n *\n * When no root was given and not one anchored file was found, the finding is\n * discarded. A base read from somewhere other than the tree it describes\n * misses every file at once, and that shape is far likelier to be a wrong\n * default root than a repository where every anchored file was deleted on\n * the same day. Reporting it would put a drift warning on every record in\n * the base, which teaches a reader to ignore the warning — the one outcome\n * worse than not having it. One file found anywhere makes the root\n * plausible, and the misses become findings again; an explicit `repoRoot` is\n * taken at its word either way.\n */\n async detectDrift(\n records: KbRecord[],\n repoRoot?: string,\n options: { offline?: boolean } = {},\n ): Promise<Map<string, KbAnchorDriftEntry[]> | undefined> {\n try {\n const drift = await detectAnchorDrift(records, {\n repoRoot: repoRoot ?? process.cwd(),\n // Offline by default: a read path must never spend a network fetch per\n // call. `doctor` and `anchor-resolve` are the verbs that go get it.\n remote: { offline: options.offline !== false },\n });\n if (repoRoot === undefined && looksLikeWrongRepoRoot(drift)) {\n this.logger.warn?.({\n operation: \"kb.anchor-drift\",\n outcome: \"skipped\",\n reason: \"no anchored file found under the default repo root\",\n });\n return undefined;\n }\n return drift;\n } catch (error) {\n this.logger.warn?.({\n operation: \"kb.anchor-drift\",\n outcome: \"skipped\",\n error: error instanceof Error ? error.message : \"unknown\",\n });\n return undefined;\n }\n }\n\n /**\n * The whole base, adjudicated, when it is small enough to hand over.\n *\n * At the sizes these reach — twenty records is about three thousand tokens —\n * loading everything beats searching it, and measurably: on nine questions\n * whose wording appears in no record, a reader holding the base answered\n * eight against an embedding search's four. Two of those differences are\n * structural. A reader can say no record answers the question; vector search\n * returns its nearest neighbour whatever the distance. And a reader picks the\n * record that answers the question rather than the one nearest the topic.\n * See the README's retrieval section for the measurements.\n *\n * Load it for a question, not for a session — a base read into a long\n * conversation is summarised away by the end of it.\n *\n * Refuses rather than truncates when the base is too large. A truncated base\n * is indistinguishable from a complete one, so a caller would answer \"that\n * was never decided\" from a slice it did not know was a slice.\n *\n * A token budget decides that, measured over what is actually handed back.\n * The refusal names the estimate and the budget, because a caller told only\n * \"too big\" cannot tell whether to narrow the type filter, raise the budget,\n * or stop loading the base whole altogether. Past the budget the answer is\n * the catalog and then a pack, which is what the refusal says.\n *\n * That refusal is the default guardrail. `all` bypasses the budget outright\n * and always hands back the whole bundle: an explicit, never-accidental\n * escape hatch for an operator who has the budget to spend, not a wider\n * default.\n */\n async load(\n bundlePath: string,\n options: {\n budgetTokens?: number;\n type?: string;\n all?: boolean;\n repoRoot?: string;\n /** Records carrying any of these are left out. See `kb-tags.ts`. */\n excludeTags?: string[];\n } = {},\n ): Promise<KbLoadResult> {\n const budgetTokens = options.budgetTokens ?? DEFAULT_LOAD_BUDGET;\n const bundle = await this.list(bundlePath);\n const wanted = options.type\n ? bundle.filter((record) => record.frontmatter.type === options.type)\n : bundle;\n\n // Adjudicated against the whole base, not the filtered slice: a record's\n // replacement may be of another type.\n const adjudicated = adjudicate(\n wanted,\n bundle,\n new Date(),\n await this.detectDrift(wanted, options.repoRoot),\n );\n // Excluded tags cut after adjudication, so nothing's standing moves and\n // the estimate below still measures exactly what is handed back.\n const kept = adjudicated.filter((hit) =>\n matchesTags(hit.record, { excludeTags: options.excludeTags }),\n );\n const records = kept.filter((hit) => hit.standing !== \"superseded\");\n const superseded = kept\n .filter((hit) => hit.standing === \"superseded\")\n .map(stub);\n\n // Measured over what is actually handed back. Costing the full bodies would\n // refuse bases that fit comfortably once the superseded ones are stubs.\n const approxTokens =\n records.reduce((total, hit) => total + estimateTokens(hit.record), 0) +\n superseded.reduce((total, entry) => total + estimateStubTokens(entry), 0);\n\n // Adjudication has already run either way, so this costs nothing extra —\n // computed once and carried on whichever branch returns.\n const bundleDigestValue = bundleDigest(records, superseded);\n\n if (!options.all && approxTokens > budgetTokens) {\n return {\n loaded: false,\n recordCount: kept.length,\n approxTokens,\n budgetTokens,\n message: refusalMessage({\n approxTokens,\n budgetTokens,\n type: options.type,\n }),\n digest: bundleDigestValue,\n };\n }\n\n return {\n loaded: true,\n recordCount: kept.length,\n tokensLoaded: approxTokens,\n budgetTokens: options.all ? null : budgetTokens,\n records,\n superseded,\n digest: bundleDigestValue,\n };\n }\n\n /**\n * `load`'s digest without `load`'s bodies — the same records, adjudicated\n * the same way, handed back as a stamp.\n *\n * Drift is counted but kept out of the digest, which is what lets the reload\n * hook ask one question and get two answers: whether the base moved, and\n * whether the code under it did. A `load` and a `stamp` of the same base\n * still agree on the digest, because no warning has ever reached it.\n */\n async stamp(\n bundlePath: string,\n options: { repoRoot?: string } = {},\n ): Promise<KbStampResult> {\n const bundle = await this.list(bundlePath);\n const adjudicated = adjudicate(bundle, bundle, new Date());\n const current = adjudicated.filter((hit) => hit.standing !== \"superseded\");\n const superseded = adjudicated\n .filter((hit) => hit.standing === \"superseded\")\n .map(stub);\n\n const stamped = bundleStamp(current, superseded);\n const dates = bundle\n .map((record) => record.frontmatter.generated?.at ?? null)\n .filter((at): at is string => typeof at === \"string\")\n .sort();\n\n // Counted after the digest, so a failed or suppressed drift pass can only\n // cost the count, never the stamp.\n //\n // Deliberately the shallow pass: `detectAnchorDrift` compares hashes and\n // stops, so this reads each anchored file once and never lists or parses\n // the repository. `moved` and `cosmetic` would need both, and a count does\n // not want them — a reload hook runs this after ordinary git commands, and\n // it asks how many records need a look, not which of them are relocatable.\n // That question belongs to `reassess` and `doctor --drifted`. Anchors\n // naming another repository are read from the local cache only — never\n // fetched — and an unchecked one is never counted.\n const drift = await this.detectDrift(bundle, options.repoRoot);\n const drifted =\n drift === undefined\n ? null\n : [...drift.values()].filter((entries) =>\n entries.some(\n (entry) =>\n entry.state !== \"match\" && !isUncheckedReason(entry.reason),\n ),\n ).length;\n\n return {\n path: bundlePath,\n digest: stamped.digest,\n recordCount: bundle.length,\n superseded: superseded.length,\n newestAt: dates.at(-1) ?? null,\n records: stamped.records,\n drifted,\n };\n }\n\n /** How a position was arrived at, as a timeline. See `trace.ts`. */\n async trace(\n bundlePath: string,\n seedId: string,\n options: KbTraceOptions = {},\n ): Promise<KbTraceStep[]> {\n return trace(seedId, await this.list(bundlePath), options);\n }\n\n /** Every record named in one line each. See `catalog.ts`. */\n async catalog(\n bundlePath: string,\n options: { type?: string; now?: Date } & KbTagFilter = {},\n ): Promise<KbCatalogResult> {\n return catalog(await this.list(bundlePath), options);\n }\n\n /** A bounded neighbourhood around one record. See `pack.ts`. */\n async pack(\n bundlePath: string,\n rootId: string,\n options: KbPackOptions = {},\n ): Promise<KbPackResult> {\n return pack(await this.list(bundlePath), rootId, options);\n }\n\n /** What breaks if this record changes. See `kb-links/impact.ts`. */\n async impact(\n bundlePath: string,\n targetId: string,\n options: KbImpactOptions = {},\n ): Promise<KbImpactResult> {\n return impact(targetId, await this.list(bundlePath), options);\n }\n\n /** Who points at this record, one hop. See `kb-links/backlinks.ts`. */\n async backlinks(\n bundlePath: string,\n targetId: string,\n ): Promise<KbBacklinksResult> {\n return backlinks(targetId, await this.list(bundlePath));\n }\n\n /**\n * The stored index, rebuilt if it disagrees with the records.\n *\n * Repair on read is what makes the lock-free write path safe: a writer whose\n * scan predated another writer's record publishes a momentarily stale index,\n * and the next reader through here settles it.\n */\n async readIndex(bundlePath: string): Promise<string> {\n const root = this.root(bundlePath);\n const expected = renderIndex(await this.list(bundlePath));\n const stored = await readFile(join(root, INDEX_FILE), \"utf8\").catch(\n () => null,\n );\n\n if (indexIsStale(stored, expected)) {\n await this.publish(join(root, INDEX_FILE), expected, true, INDEX_FILE);\n this.logger.info?.({\n operation: \"kb.index.repair\",\n bundlePath: root,\n reason: stored === null ? \"missing\" : \"stale\",\n });\n }\n return expected;\n }\n\n /**\n * Drops the derived search index, so the next search rebuilds it.\n *\n * `searchBase` re-indexes when a record is newer than the index, which no\n * deletion makes true — a swept record would stay findable until some other\n * record was written.\n */\n async dropSearchIndex(bundlePath: string): Promise<void> {\n await unlink(join(this.root(bundlePath), SEARCH_INDEX_FILE)).catch(\n () => undefined,\n );\n }\n\n /**\n * The log, with unparseable lines reported rather than repaired.\n *\n * The log is the bundle's only artifact that cannot be reconstructed — the\n * records rebuild the index, and the code outlives both, but nothing else\n * knows which agent touched what. So a bad line is surfaced and left alone.\n * Conflict markers are read past rather than reported per line.\n */\n async readLog(bundlePath: string): Promise<ReturnType<typeof parseLog>> {\n const raw = await readFile(\n join(this.root(bundlePath), LOG_FILE),\n \"utf8\",\n ).catch(() => \"\");\n const result = parseLog(raw);\n // One warning for the file, not one per marker: the fact to report is\n // that the log is unresolved, and it is reported once.\n if (result.conflicted) {\n this.logger.warn?.({\n operation: \"kb.log.parse\",\n bundlePath: this.root(bundlePath),\n outcome: \"conflicted\",\n });\n }\n for (const bad of result.malformed) {\n this.logger.warn?.({\n operation: \"kb.log.parse\",\n line: bad.line,\n outcome: \"skipped\",\n });\n }\n return result;\n }\n\n /**\n * Appends one log entry for a move the store cannot see from one base.\n * Promotion writes into a target base and has to be legible from the source\n * base too, where nothing was written.\n */\n async note(bundlePath: string, entry: Omit<KbLogEntry, \"at\">): Promise<void> {\n assertActor(entry.by);\n await this.record(this.root(bundlePath), entry);\n }\n\n /**\n * `markSuperseded`, tolerant of the two ways it legitimately doesn't land:\n * a missing target (a broken link, legal per compose.ts) or a CAS conflict\n * from a concurrent writer touching the same target. A conflict is retried\n * a bounded number of times — each attempt re-reads the target fresh — and\n * on the last, `false` reports \"not marked\" rather than throwing: the\n * caller's own record is already published, so failing here would leave\n * that publish unreported instead of undone. kb_validate's existing\n * \"not marked superseded\" check is what surfaces the residue.\n */\n private async markSupersededRetrying(\n bundlePath: string,\n conceptId: string,\n replacementId: string,\n actor: string,\n retries = 3,\n ): Promise<boolean> {\n for (let attempt = 0; attempt <= retries; attempt++) {\n try {\n await this.markSuperseded(bundlePath, conceptId, replacementId, actor);\n return true;\n } catch (error) {\n if (error instanceof KbRecordNotFoundError) return false;\n if (!(error instanceof KbWriteConflictError)) throw error;\n if (attempt === retries) return false;\n }\n }\n return false;\n }\n\n /** The one-directional half of `supersede`: marks `conceptId` superseded. */\n private async markSuperseded(\n bundlePath: string,\n conceptId: string,\n replacementId: string,\n actor: string,\n ): Promise<KbRecord> {\n return this.mutate(\n bundlePath,\n conceptId,\n (frontmatter) => ({\n ...frontmatter,\n strauss_status: \"superseded\" as const,\n strauss_superseded_by: replacementId,\n }),\n { operation: \"supersede\", by: actor, target: replacementId },\n );\n }\n\n private async mutate(\n bundlePath: string,\n conceptId: string,\n change: (frontmatter: KbRecordFrontmatter) => KbRecordFrontmatter,\n // A thunk where the entry is only knowable once `change` has run.\n entry:\n | (Omit<KbLogEntry, \"at\" | \"conceptId\"> & { target?: string })\n | (() => Omit<KbLogEntry, \"at\" | \"conceptId\"> & { target?: string }),\n changeBody: (body: string) => string = (body) => body,\n ): Promise<KbRecord> {\n const target = this.recordPath(bundlePath, conceptId);\n const before = await readFile(target, \"utf8\").catch(() => null);\n if (before === null) throw new KbRecordNotFoundError(conceptId);\n\n const parsed = this.parse(conceptId, before);\n if (!parsed) throw new KbRecordNotFoundError(conceptId);\n\n const frontmatter = change(parsed.frontmatter);\n const body = changeBody(parsed.body);\n const contents = stringifyMarkdownWithFrontmatter(body, frontmatter);\n\n // Optimistic check, not a hard guarantee: a writer landing between this\n // read and the publish below still wins silently. It narrows the window\n // from \"the whole compose\" to two adjacent syscalls, which is as far as a\n // filesystem goes without a lock — and a lock's stale-hold failure mode is\n // worse than the residue.\n const witness = await readFile(target, \"utf8\").catch(() => null);\n if (witness === null || digest(witness) !== digest(before)) {\n throw new KbWriteConflictError(conceptId);\n }\n await this.publish(target, contents, true, conceptId);\n await this.record(this.root(bundlePath), {\n ...(typeof entry === \"function\" ? entry() : entry),\n conceptId,\n });\n\n return { conceptId, frontmatter, body };\n }\n\n /**\n * Two guarantees, both about writers running in parallel.\n *\n * The record is written to a staging file and only then published, so a\n * concurrent reader sees the whole record or no record — never half of one. A\n * plain write is not atomic, and `list()` skips what it cannot parse, so a\n * torn read would be silently reported as a malformed record.\n *\n * Publishing uses `link` rather than `rename` unless the caller asked to\n * overwrite: `link` fails with EEXIST instead of replacing, which turns \"two\n * writers chose the same concept id\" from silent data loss into a collision\n * the caller has to answer. Both are atomic; only `rename` clobbers.\n *\n * The staging name deliberately does not end in `.md` — `list()` would\n * otherwise try to read it mid-write.\n */\n private async publish(\n target: string,\n contents: string,\n overwrite: boolean,\n conceptId: string,\n ): Promise<void> {\n const staging = `${target}.${process.pid}.tmp`;\n await writeFile(staging, contents, \"utf8\");\n\n try {\n if (overwrite) {\n await rename(staging, target);\n return;\n }\n await link(staging, target);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"EEXIST\") {\n throw new KbRecordAlreadyExistsError(conceptId);\n }\n throw error;\n } finally {\n // `rename` consumed the staging file; `link` left it behind.\n await unlink(staging).catch(() => undefined);\n }\n }\n\n /**\n * Declares union merge for the log, so two worktrees writing the same\n * bundle interleave their `log.jsonl` lines on merge rather than one\n * side's appends silently losing to git's ordinary line-level merge — and\n * marks every store-owned file generated, so GitHub collapses it in a diff.\n *\n * Called from `record` — every path that appends a log line, not just\n * `write` — so a bundle only ever mutated through `setStatus`/`verify`/\n * `supersede` still gets it. There is no cheaper reliable signal for\n * \"first write\" than checking the file itself, and after the first call\n * the check is a no-op `readFile`.\n *\n * A missing `.gitattributes` is created outright, with `wx` (exclusive\n * create) rather than a plain write: if another process's `write()` won a\n * race and created the file between the `readFile` below and this call,\n * `wx` fails instead of truncating what that writer just wrote, and the\n * failure is swallowed by the catch below same as any other best-effort\n * miss. A file that exists gets only the lines it lacks appended, never a\n * wholesale rewrite; an attribute it already sets — this one's value or a\n * user's own — is left alone (see `missingGitattributesLines`).\n *\n * `readFile` failing is `existing === null` only for `ENOENT` — genuinely\n * missing. Any other error (a permission problem, a transient `EMFILE`,\n * the path being a directory) is *not* \"missing\" and must not fall into\n * the create branch, which would truncate whatever is actually there with\n * just the union-merge line: that is the file-destroying bug this\n * function exists to avoid, not commit. An unreadable existing file is\n * therefore left untouched and reported as a failure like any other.\n *\n * Two processes racing the append branch — both read a file without the\n * lines, both append them — is possible and left unguarded: `appendFile` is\n * `O_APPEND`, so the result is two copies of the same lines rather than a\n * torn write, and the next call sees a duplicate declaration as \"already\n * declared\". A cheap-to-detect, harmless-to-leave residue, not a reason to\n * add a cross-process lock (see `ARCHITECTURE.md`'s rejection of one for\n * the same trade on records).\n *\n * Best-effort, like the log append it precedes: failing to write this\n * file must not fail the mutation it guards.\n */\n private async ensureGitattributes(root: string): Promise<void> {\n const target = join(root, GITATTRIBUTES_FILE);\n try {\n let existing: string | null;\n try {\n existing = await readFile(target, \"utf8\");\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n existing = null;\n }\n\n if (existing === null) {\n try {\n await writeFile(target, appendGitattributesLines(\"\"), {\n encoding: \"utf8\",\n flag: \"wx\",\n });\n } catch (error) {\n // Another writer created the same file with the same content\n // between our read and our write — a win for them counts as a win\n // for us, not a failure.\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") throw error;\n this.logger.info?.({\n operation: \"kb.gitattributes.ensure\",\n bundlePath: root,\n outcome: \"exists\",\n });\n return;\n }\n this.logger.info?.({\n operation: \"kb.gitattributes.ensure\",\n bundlePath: root,\n outcome: \"created\",\n });\n return;\n }\n const addition = appendGitattributesLines(existing);\n if (addition) {\n await appendFile(target, addition, \"utf8\");\n this.logger.info?.({\n operation: \"kb.gitattributes.ensure\",\n bundlePath: root,\n outcome: \"appended\",\n });\n }\n } catch (error) {\n this.logger.warn?.({\n operation: \"kb.gitattributes.ensure\",\n outcome: \"failed\",\n error: error instanceof Error ? error.message : \"unknown\",\n });\n }\n }\n\n /** Appends one log line. Failing to log must not fail the mutation. */\n private async record(\n root: string,\n entry: Omit<KbLogEntry, \"at\"> & { at?: string },\n ): Promise<void> {\n await this.ensureGitattributes(root);\n const line = renderLogEntry({ at: new Date().toISOString(), ...entry });\n await appendFile(join(root, LOG_FILE), line, \"utf8\").catch((error) => {\n this.logger.warn?.({\n operation: \"kb.log.append\",\n outcome: \"failed\",\n error: error instanceof Error ? error.message : \"unknown\",\n });\n });\n }\n\n private parse(conceptId: string, raw: string): KbRecord | null {\n const parsed = parseMarkdownWithFrontmatter(raw, kbRecordFrontmatterSchema);\n if (!parsed.frontmatter.success) {\n this.logger.warn?.({\n operation: \"kb.parse\",\n conceptId,\n outcome: \"skipped\",\n error: parsed.frontmatter.error.issues[0]?.message ?? \"invalid\",\n });\n return null;\n }\n return {\n conceptId,\n frontmatter: parsed.frontmatter.data,\n body: parsed.content,\n };\n }\n\n private root(bundlePath: string): string {\n return resolve(bundlePath);\n }\n\n // Concept ids are `<type>.<slug>` and map to a single file directly under the\n // bundle root; anything carrying a separator would escape it.\n private recordPath(bundlePath: string, conceptId: string): string {\n if (conceptId.includes(sep) || conceptId.includes(\"/\")) {\n throw new KbInvalidConceptIdError(\n \"concept id must not contain a path separator\",\n { conceptId },\n );\n }\n return join(this.root(bundlePath), `${conceptId}.md`);\n }\n}\n\n/**\n * Deliberately crude, and labelled `approx` everywhere it surfaces. A real\n * tokeniser would be a dependency carried to decide whether to avoid carrying\n * dependencies, and four characters per token is close enough to choose\n * between \"hand it over\" and \"do not\".\n *\n * Exported (with `estimateStubTokens` and `stub`) so `pack` costs and stubs\n * records exactly as `load` does — two accountings would drift.\n */\nexport function estimateTokens(record: KbRecord): number {\n return Math.ceil(\n (record.body.length + JSON.stringify(record.frontmatter).length) / 4,\n );\n}\n\nexport function estimateStubTokens(entry: KbSupersededStub): number {\n return Math.ceil(JSON.stringify(entry).length / 4);\n}\n\n/** What a refused load says: what tripped the budget, and what to call next. */\nfunction refusalMessage(refusal: {\n approxTokens: number;\n budgetTokens: number;\n type?: string;\n}): string {\n const scope = refusal.type ? ` of type ${refusal.type}` : \"\";\n\n return [\n `Refusing to load this base whole: ~${refusal.approxTokens} tokens is past the ${refusal.budgetTokens}-token budget.`,\n `Call kb_catalog for one line per record${scope} (id, type, title, standing), then kb_pack on the record that matters; kb_query works for a lookup by wording.`,\n `To load anyway: raise budgetTokens (currently ${refusal.budgetTokens}), or all=true to bypass the budget.`,\n ].join(\" \");\n}\n\n/**\n * `heads` is where the supersession chain ends, which is what a reader needs:\n * pointing at an intermediate record that is itself superseded would answer\n * \"what replaced this\" with something else that no longer holds. A broken or\n * forked chain resolves to no head, and the warning that says so travels with\n * the head record rather than here.\n */\nexport function stub(hit: KbAdjudicated): KbSupersededStub {\n return {\n conceptId: hit.record.conceptId,\n title: hit.record.frontmatter.title ?? null,\n supersededBy: hit.heads.map((head) => head.conceptId),\n at: hit.record.frontmatter.generated?.at ?? null,\n };\n}\n\nfunction matches(record: KbRecord, needle: string): boolean {\n const { title, description } = record.frontmatter;\n // The concept id is searched too: a slug is chosen to describe the record, so\n // a base where `decision.cursor-v2` does not answer \"cursor\" is surprising in\n // a way no caller would think to work around.\n return [record.conceptId, title, description, record.body].some((field) =>\n field?.toLowerCase().includes(needle),\n );\n}\n\n/**\n * Case-normalizes only the kind prefix — the segment up to and including the\n * first `:` — so `Human:alice` and `human:alice` name the same kind of actor\n * while the identity after the colon keeps its case. An id with no colon is\n * all prefix, and is lowercased whole.\n */\nfunction normalizeActor(id: string): string {\n const colon = id.indexOf(\":\");\n if (colon === -1) return id.toLowerCase();\n return id.slice(0, colon + 1).toLowerCase() + id.slice(colon + 1);\n}\n\n/** `kind` or `kind:name`: no quotes, spaces, or control bytes. */\nconst KB_ACTOR_PATTERN = /^[A-Za-z][\\w-]*(?::[\\p{L}\\p{M}\\p{N}_.@+/-]+)?$/u;\n\n/**\n * Refuses an actor no write may carry. `named` also refuses the CLI default\n * `unknown`: a verification nobody can attribute is not a check.\n */\nfunction assertActor(actor: string, { named = false } = {}): void {\n if (!KB_ACTOR_PATTERN.test(actor)) {\n throw new KbInvalidActorError(actor, \"is not kind or kind:name\");\n }\n if (named && normalizeActor(actor) === \"unknown\") {\n throw new KbInvalidActorError(actor, \"cannot verify: name who checked\");\n }\n}\n","/**\n * A base's content stamp: `load`'s digest, and the per-record digests it is\n * built from.\n *\n * The aggregate answers \"did anything change\"; the per-record entries answer\n * \"which records\", which is what a reload notice has to name. One pass\n * produces both, so `load` and `stamp` cannot disagree.\n */\nimport { createHash } from \"node:crypto\";\nimport { stringifyMarkdownWithFrontmatter } from \"./markdown.js\";\nimport type { KbAdjudicated } from \"./adjudicate.js\";\nimport type { KbSupersededStub } from \"./kb-store.js\";\n\nexport type KbRecordStamp = { conceptId: string; digest: string };\n\nexport type KbBundleStamp = { digest: string; records: KbRecordStamp[] };\n\nexport function sha256(contents: string): string {\n return createHash(\"sha256\").update(contents).digest(\"hex\");\n}\n\n/**\n * Entries are sorted by concept id, so the digest never depends on listing\n * order; each is hashed over its record's canonical recomposed form, not the\n * on-disk bytes; superseded stubs are included, so a standing flip changes the\n * digest even when the body did not.\n */\nexport function bundleStamp(\n records: KbAdjudicated[],\n superseded: KbSupersededStub[],\n): KbBundleStamp {\n const entries: KbRecordStamp[] = [\n ...records.map((hit) => ({\n conceptId: hit.record.conceptId,\n digest: `current:${sha256(\n stringifyMarkdownWithFrontmatter(\n hit.record.body,\n hit.record.frontmatter,\n ),\n )}`,\n })),\n ...superseded.map((entry) => ({\n conceptId: entry.conceptId,\n digest: `superseded:${sha256(JSON.stringify(entry))}`,\n })),\n ].sort((a, b) => (a.conceptId < b.conceptId ? -1 : 1));\n\n return {\n digest: sha256(\n entries.map((entry) => `${entry.conceptId}:${entry.digest}`).join(\"\\n\"),\n ),\n records: entries,\n };\n}\n\nexport function bundleDigest(\n records: KbAdjudicated[],\n superseded: KbSupersededStub[],\n): string {\n return bundleStamp(records, superseded).digest;\n}\n","import { INDEX_FILE } from \"./kb-index.js\";\nimport { LOG_FILE } from \"./kb-log.js\";\nimport { SEARCH_INDEX_FILE } from \"./search-index.js\";\n\n/**\n * The files the store owns rather than a producer. Not records: listings skip\n * them, and `.gitattributes` marks them generated.\n */\nexport const STORE_OWNED_FILES = [INDEX_FILE, LOG_FILE, SEARCH_INDEX_FILE];\n","import { STORE_OWNED_FILES } from \"./kb-files.js\";\nimport { LOG_FILE } from \"./kb-log.js\";\n\nexport const GITATTRIBUTES_FILE = \".gitattributes\";\n\nconst GENERATED = \"linguist-generated\";\n\n/**\n * Declares the log's merge driver, its line endings, and that it is derived.\n *\n * `merge=union` interleaves both sides' lines instead of the ordinary\n * line-level merge, which can drop one side's appends outright. The log is\n * append-only JSONL and two worktrees against the same bundle is the normal\n * case, not an edge case — `kb_log`'s reader sorts on `at` and dedupes exact\n * repeats (`kb-log.ts`), so interleaved line order — or a line a union merge\n * happened to keep twice — coming out of a merge is exactly as readable as a\n * single writer's log.\n *\n * `text eol=lf` pins line endings to `\\n` regardless of a checkout's\n * `core.autocrlf`. Without it, Windows with `autocrlf=true` normalizes the\n * file to CRLF on checkout while every append after that (`O_APPEND`, raw\n * `\\n`) keeps writing LF — a file with mixed endings, which is exactly the\n * kind of divergence a merge driver can't paper over.\n */\nexport const UNION_MERGE_LINE = `${LOG_FILE} text eol=lf merge=union ${GENERATED}=true`;\n\n/**\n * One parsed `.gitattributes` line: the pattern and its whitespace-separated\n * attributes. `null` for a blank line or a `#` comment — gitattributes\n * ignores both.\n */\nfunction parseLine(line: string): { pattern: string; attrs: string[] } | null {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith(\"#\")) return null;\n const [pattern, ...attrs] = trimmed.split(/\\s+/);\n return pattern === undefined ? null : { pattern, attrs };\n}\n\n/**\n * Whether `contents` already assigns *any* `merge` attribute to the log\n * file — our own `merge=union`, a plain `merge` (the default driver), an\n * explicit `-merge` (merging disabled), or a user's own choice such as\n * `merge=ours`.\n *\n * Exact-string matching against `UNION_MERGE_LINE` was the first cut, and it\n * both under- and over-reaches: a line with a tab or doubled space between\n * tokens, or one that also sets an unrelated attribute alongside `merge`,\n * would not match and get a harmless-looking but wrong second line appended\n * — and it can never see a deliberate `merge=ours` as \"already decided\",\n * which is the one case where appending anything at all would be wrong.\n * Whitespace-tokenizing the pattern and attributes separately answers the\n * question this function actually needs answered: does *some* line already\n * give `log.jsonl` a merge strategy, whatever it is — and if so, that\n * strategy is left alone rather than layered under a second, possibly\n * conflicting one. gitattributes itself resolves multiple matching lines by\n * \"last one wins\", so appending a second `merge=` line for the same pattern\n * would silently override a user's `merge=ours` with `merge=union` — the\n * opposite of respecting what they set.\n */\nexport function hasMergeDeclaration(contents: string): boolean {\n return declares(contents, LOG_FILE, \"merge\");\n}\n\n/** Whether some line already assigns `attribute` to `pattern`, at any value. */\nfunction declares(\n contents: string,\n pattern: string,\n attribute: string,\n): boolean {\n return contents.split(\"\\n\").some((line) => {\n const parsed = parseLine(line);\n if (!parsed || parsed.pattern !== pattern) return false;\n return parsed.attrs.some(\n (attr) =>\n attr === attribute ||\n attr === `-${attribute}` ||\n attr.startsWith(`${attribute}=`),\n );\n });\n}\n\n/**\n * The lines `contents` still lacks, in file order. Each attribute is asked\n * for separately, so a base written before this list grew gains only what it\n * is missing and a hand-set value is never layered over.\n */\nexport function missingGitattributesLines(contents: string): string[] {\n const needsMerge = !hasMergeDeclaration(contents);\n const generated = STORE_OWNED_FILES.filter(\n // The union-merge line carries the log's `linguist-generated` too, so the\n // log needs its own line only where that line is already there without it.\n (file) => !(needsMerge && file === LOG_FILE),\n )\n .filter((file) => !declares(contents, file, GENERATED))\n .map((file) => `${file} ${GENERATED}=true`);\n\n return needsMerge ? [UNION_MERGE_LINE, ...generated] : generated;\n}\n\n/** What a `.gitattributes` this store creates from nothing contains. */\nexport const GITATTRIBUTES_BLOCK = `${missingGitattributesLines(\"\").join(\"\\n\")}\\n`;\n\n/**\n * The bytes to append to bring `contents` up to date — a newline first unless\n * it already ends in one, so the first line lands on its own rather than\n * tacked onto the file's last. Empty when nothing is missing.\n */\nexport function appendGitattributesLines(contents: string): string {\n const lines = missingGitattributesLines(contents);\n if (lines.length === 0) return \"\";\n const separator =\n contents.length === 0 || contents.endsWith(\"\\n\") ? \"\" : \"\\n\";\n return `${separator}${lines.join(\"\\n\")}\\n`;\n}\n","import { adjudicate, type KbStanding, type KbWarning } from \"./adjudicate.js\";\nimport { neighbours } from \"./kb-edges.js\";\nimport {\n KbPackBudgetExceededError,\n KbRecordNotFoundError,\n} from \"./kb-errors.js\";\nimport {\n KB_RECORD_TYPES,\n type KbAnchor,\n type KbRecord,\n} from \"./kb-record.schema.js\";\nimport {\n DEFAULT_LOAD_BUDGET,\n estimateStubTokens,\n estimateTokens,\n stub,\n type KbSupersededStub,\n} from \"./kb-store.js\";\n\nexport const DEFAULT_PACK_HOPS = 2;\nexport const DEFAULT_PACK_MAX_NODES = 20;\n\nexport type KbPackOptions = {\n /** How far from the root the walk may reach. */\n hops?: number;\n /** How many records the pack may hold, root included. */\n maxNodes?: number;\n /** Approximate token ceiling over what is actually emitted. */\n budgetTokens?: number;\n};\n\n/** One record as the pack emits it — the same mapping `kb_load` hands back. */\nexport type KbPackedRecord = {\n conceptId: string;\n title: string | null;\n standing: KbStanding;\n supersededBy: string[];\n warnings: KbWarning[];\n anchors: KbAnchor[];\n body: string;\n};\n\n/**\n * Deliberately timestamp-free: the same bundle and root must produce the same\n * bytes on every run, so a caller can diff two packs and trust that a changed\n * byte means changed knowledge.\n */\nexport type KbPackResult = {\n root: string;\n records: KbPackedRecord[];\n /** Named only, exactly as `load` stubs them. Bodies reachable via trace. */\n superseded: KbSupersededStub[];\n /** Every reachable record the hop and node limits cut, never summarized. */\n excluded: string[];\n recordCount: number;\n tokensLoaded: number;\n budgetTokens: number;\n};\n\n// What a reader wants first when the walk has to cut: what was settled\n// (decision), then what binds (constraint, requirement), then the rest in\n// their declared order.\nconst TYPE_PRIORITY: readonly string[] = [\n \"decision\",\n \"constraint\",\n \"requirement\",\n ...KB_RECORD_TYPES.filter(\n (type) => ![\"decision\", \"constraint\", \"requirement\"].includes(type),\n ),\n];\n\ntype Reached = { record: KbRecord; depth: number };\n\n/**\n * A bounded, progressively disclosed neighbourhood around one record.\n *\n * Where `load` hands over a whole base and `trace` a timeline, a pack is the\n * subgraph a reader needs to act near one record: everything within `hops`\n * of the root, cut to `maxNodes` by ranking, with every cut id listed —\n * a named gap is knowable, a silent one is not.\n *\n * Adjudication runs against the whole bundle, not the reached slice, so a\n * record's standing cannot depend on whether its replacement happened to be\n * within reach. Superseded records become the same stubs `load` emits, costed\n * as stubs, and the budget is a refusal rather than a truncation: a partial\n * pack looks complete to its reader.\n */\nexport function pack(\n bundle: KbRecord[],\n rootId: string,\n options: KbPackOptions = {},\n): KbPackResult {\n const hops = options.hops ?? DEFAULT_PACK_HOPS;\n const maxNodes = options.maxNodes ?? DEFAULT_PACK_MAX_NODES;\n const budgetTokens = options.budgetTokens ?? DEFAULT_LOAD_BUDGET;\n\n const byId = new Map(bundle.map((record) => [record.conceptId, record]));\n const root = byId.get(rootId);\n if (!root) throw new KbRecordNotFoundError(rootId);\n\n // The whole reachable component is walked, not just the first `hops` rings:\n // the bundle is already in memory, and knowing what lies past the bound is\n // what lets the excluded list name records instead of waving at them.\n const reached: Reached[] = [{ record: root, depth: 0 }];\n const seen = new Set([rootId]);\n let frontier: KbRecord[] = [root];\n for (let depth = 1; frontier.length; depth += 1) {\n const next: KbRecord[] = [];\n for (const from of frontier) {\n for (const { record } of neighbours(from, bundle)) {\n if (seen.has(record.conceptId)) continue;\n seen.add(record.conceptId);\n reached.push({ record, depth });\n next.push(record);\n }\n }\n frontier = next;\n }\n\n reached.sort(byRank);\n const within = reached.filter((entry) => entry.depth <= hops);\n const kept = within.slice(0, maxNodes);\n const excluded = [\n ...within.slice(maxNodes),\n ...reached.filter((entry) => entry.depth > hops),\n ]\n .map((entry) => entry.record.conceptId)\n .sort();\n\n const adjudicated = adjudicate(\n kept.map((entry) => entry.record),\n bundle,\n );\n const superseded = adjudicated\n .filter((hit) => hit.standing === \"superseded\")\n .map(stub);\n const whole = adjudicated.filter((hit) => hit.standing !== \"superseded\");\n\n const tokensLoaded =\n whole.reduce((total, hit) => total + estimateTokens(hit.record), 0) +\n superseded.reduce((total, entry) => total + estimateStubTokens(entry), 0);\n const recordCount = adjudicated.length;\n\n if (tokensLoaded > budgetTokens) {\n throw new KbPackBudgetExceededError(\n recordCount,\n tokensLoaded,\n budgetTokens,\n excluded,\n );\n }\n\n return {\n root: rootId,\n records: whole.map((hit) => ({\n conceptId: hit.record.conceptId,\n title: hit.record.frontmatter.title ?? null,\n standing: hit.standing,\n supersededBy: hit.heads.map((head) => head.conceptId),\n warnings: hit.warnings,\n anchors: hit.record.frontmatter.strauss_anchors ?? [],\n body: hit.record.body,\n })),\n superseded,\n excluded,\n recordCount,\n tokensLoaded,\n budgetTokens,\n };\n}\n\nfunction byRank(left: Reached, right: Reached): number {\n return (\n left.depth - right.depth ||\n typeRank(left.record) - typeRank(right.record) ||\n (left.record.frontmatter.title ?? \"\").localeCompare(\n right.record.frontmatter.title ?? \"\",\n ) ||\n left.record.conceptId.localeCompare(right.record.conceptId)\n );\n}\n\n// A foreign type — legal under OKF — ranks after every known one.\nfunction typeRank(record: KbRecord): number {\n const index = TYPE_PRIORITY.indexOf(record.frontmatter.type);\n return index === -1 ? TYPE_PRIORITY.length : index;\n}\n","/**\n * The package version, injected at build time by tsup's `define`.\n *\n * Hardcoding it here would be a second copy of `package.json`'s version, and a\n * copy that only a human comparing two numbers would ever catch: it reaches\n * users as `serverInfo.version`, which is the one thing a client can ask a\n * running server about itself. It sat at 0.1.0 through five releases.\n *\n * `typeof` rather than a bare reference so this also works unbuilt — under\n * Vitest the identifier is never defined, and reading an undeclared name would\n * throw where reading its type does not.\n */\ndeclare const __STRAUSS_KB_VERSION__: string | undefined;\n\nexport const VERSION: string =\n typeof __STRAUSS_KB_VERSION__ === \"string\"\n ? __STRAUSS_KB_VERSION__\n : \"0.0.0-dev\";\n"],"mappings":"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","names":["at","at","execFile","promisify","execFileAsync","promisify","execFile","at","key","group","rejected","at","cached","at","mkdir","readFile","homedir","join","sha256","dirname","join","sha256","dirname","join","readFile","base","resolve","pack","key","at","readFile","pack","createHash","matches","at","at","at","pack","matches","key","createHash","cached","createHash","index","header","at","span","createHash","tokens","execFile","promisify","execFileAsync","promisify","execFile","git","base","shown","at","key","at","z","Fault","ErrorTypes","span","key","z","z","link","z","z","impact","conceptId","approxTokens","table","key","raw","bundlePath","join","z","mkdir","readFile","writeFile","homedir","dirname","isAbsolute","join","relative","resolve","sep","homedir","resolve","join","readFile","mkdir","dirname","writeFile","isAbsolute","sep","bundlePath","relative","resolve","bundlePath","resolve","bundlePath","at","entry","resolve","bundlePath","resolve","z","z","z","value","at","z","z","z","bundlePath","z","key","base","z","matches","resolve","unchecked","missing","standings","matches","at","stat","at","size","stat","at","settled","header","table","row","col","open","base","readFile","writeFile","HEADING","superseded","base","readFile","writeFile","link","conceptId","link","span","standings","at","key","count","link","key","link","link","why","conceptId","z","z","resolve","at","resolve","conceptId","link","z","z","index","key","z","z","at","z","z","z","z","z","z","join","z","z","z","rename","open","at","key","z","base","diff","index","at","z","base","diff","REFUSED","fromStdin","mapLimit","join","at","width","z","z","z","z","z","impact","z","expiring","unverified","drifted","standings","render","width","group","mkdir","readFile","rename","writeFile","join","z","z","mkdir","join","writeFile","rename","readFile","z","z","z","z","z","z","z","z","z","z","z","z","render","at","z","z","z","z","z","z","z","z","z","z","readFile","z","z","bundlePath","conceptId","readFile","z","z","z","z","z","z","conceptId","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","stat","join","bundlePath","join","stat","readdir","at","mkdir","readdir","readFile","rename","unlink","writeFile","join","resolve","sep","createHash","sha256","createHash","join","bundlePath","conceptId","mkdir","readFile","readdir","at","unlink","matches","approxTokens","drifted","sha256","writeFile","rename","resolve","sep","index"]}
|