@saasontools/strauss-kb 0.1.4 → 0.1.5

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/README.md CHANGED
@@ -196,7 +196,7 @@ strauss-kb [--bundle PATH] <command> [args]
196
196
  status <concept-id> <status> Move a record's status, compare-and-swap.
197
197
  supersede <concept-id> <replacement-id> Mark a record superseded, linking both directions.
198
198
  answer <concept-id> <answer...> Resolve an open question and append the answer.
199
- load [type] [--budget N] Hand over the whole base, each record with its standing.
199
+ load [type] [--budget N | --all] Hand over the whole base, each record with its standing.
200
200
  query <text...> Search; every match arrives flagged with its standing.
201
201
  trace <concept-id> [edges...] How a position was arrived at, as a timeline.
202
202
  list [type] Every record, optionally narrowed to one type.
@@ -323,6 +323,17 @@ by default). Superseded records come back as name, replacement and date only —
323
323
  their bodies no longer hold, and a body read later in a long session outlives
324
324
  the qualifier that said so. `trace` still reaches them by id.
325
325
 
326
+ `--all` (`all: true` over MCP) is the escape hatch: it bypasses the refusal
327
+ outright and hands back the entire bundle whatever its size. A loaded result
328
+ carries `tokensLoaded`, the same estimate the budget is held against, and
329
+ `budgetTokens: null` marks that no ceiling was applied; `--all` is mutually
330
+ exclusive with `--budget`. That refusal is the guardrail an agent needs so a
331
+ wide base does not silently consume its whole context; `--all` is for a
332
+ deliberate operator who has decided the size is worth the tokens, not a
333
+ setting to reach for by default. A reader that does not actually need every
334
+ record is better served by a narrower `type` filter or a `query` than by
335
+ turning the guardrail off.
336
+
326
337
  **Flag, never filter.** `query` returns every hit with its standing, because a
327
338
  filtered result set is invisible — the caller cannot tell it missed anything.
328
339
  The single exception is narrow: a superseded record is dropped only when its
@@ -1198,25 +1198,32 @@ import { z as z11 } from "zod";
1198
1198
  var loadCommand = define({
1199
1199
  name: "load",
1200
1200
  tool: "kb_load",
1201
- usage: "load [type] [--budget N]",
1202
- description: "Load the whole knowledge base at once, each record with its standing. Prefer this over searching: these bases run to a few thousand tokens, and a reader holding all of it has perfect recall and knows why it is asking, which no ranker does. Superseded records arrive under `superseded` as name, replacement and date only \u2014 their bodies no longer hold, and reading one later in a long session is the mistake this prevents; pass the id to kb_trace when you need the history. Rejected and unresolved records arrive whole: what was turned down, and what is still open, is the part a diff cannot show you. Refuses with a count rather than truncating when the base is too large \u2014 a truncated base is indistinguishable from a complete one, and would have you conclude something was never decided from a slice you did not know was a slice. Call at the point of use, not once per session: a base loaded early is summarised away by compaction, so if the visible context holds no records from this base and the question at hand is one it might govern, load before answering \u2014 never conclude nothing was decided from a context with no KB content in it. This tool (with kb_query and kb_trace) is the only supported way to read a base; a raw file read bypasses supersession resolution and returns replaced records as if current.",
1201
+ usage: "load [type] [--budget N | --all]",
1202
+ description: "Load the whole knowledge base at once, each record with its standing. Prefer this over searching: these bases run to a few thousand tokens, and a reader holding all of it has perfect recall and knows why it is asking, which no ranker does. Superseded records arrive under `superseded` as name, replacement and date only \u2014 their bodies no longer hold, and reading one later in a long session is the mistake this prevents; pass the id to kb_trace when you need the history. Rejected and unresolved records arrive whole: what was turned down, and what is still open, is the part a diff cannot show you. Refuses with a count rather than truncating when the base is too large \u2014 a truncated base is indistinguishable from a complete one, and would have you conclude something was never decided from a slice you did not know was a slice. Call at the point of use, not once per session: a base loaded early is summarised away by compaction, so if the visible context holds no records from this base and the question at hand is one it might govern, load before answering \u2014 never conclude nothing was decided from a context with no KB content in it. This tool (with kb_query and kb_trace) is the only supported way to read a base; a raw file read bypasses supersession resolution and returns replaced records as if current.\n\nThat refusal is the default guardrail, meant for an agent that would otherwise burn its whole context on one call. `all` bypasses it and loads everything regardless of size: a deliberate operator with the budget to spend, not something to reach for automatically. It is mutually exclusive with `budgetTokens`. When the reader does not need everything, kb_query or a narrower `type` filter is the better fit than either.",
1203
1203
  input: z11.object({
1204
1204
  bundlePath,
1205
1205
  type: z11.enum(KB_RECORD_TYPES).optional(),
1206
- budgetTokens: z11.number().int().positive().optional().describe("Approximate token ceiling. Defaults to 25000.")
1206
+ budgetTokens: z11.number().int().positive().optional().describe("Approximate token ceiling. Defaults to 25000."),
1207
+ all: z11.boolean().optional().describe(
1208
+ "Load the entire base regardless of size. The deliberate-operator escape hatch; mutually exclusive with budgetTokens."
1209
+ )
1210
+ }).refine((value) => !(value.all && value.budgetTokens !== void 0), {
1211
+ message: "all and budgetTokens are mutually exclusive: pass a ceiling or none, not both."
1207
1212
  }),
1208
1213
  fromArgv: (argv, path) => {
1209
1214
  const budget = argvFlag(argv, "--budget");
1210
1215
  return {
1211
1216
  bundlePath: path,
1212
- ...argv[1] && argv[1] !== "--budget" ? { type: argv[1] } : {},
1213
- ...budget ? { budgetTokens: Number(budget) } : {}
1217
+ ...argv[1] && !argv[1].startsWith("--") ? { type: argv[1] } : {},
1218
+ ...budget ? { budgetTokens: Number(budget) } : {},
1219
+ ...argv.includes("--all") ? { all: true } : {}
1214
1220
  };
1215
1221
  },
1216
- run: async ({ store }, { bundlePath: path, type, budgetTokens }) => {
1222
+ run: async ({ store }, { bundlePath: path, type, budgetTokens, all }) => {
1217
1223
  const result = await store.load(path, {
1218
1224
  ...type ? { type } : {},
1219
- ...budgetTokens ? { budgetTokens } : {}
1225
+ ...budgetTokens ? { budgetTokens } : {},
1226
+ ...all ? { all } : {}
1220
1227
  });
1221
1228
  if (!result.loaded) return result;
1222
1229
  return {
@@ -2067,6 +2074,10 @@ ${answer}
2067
2074
  * Refuses rather than truncates when the base is too large. A truncated base
2068
2075
  * is indistinguishable from a complete one, so a caller would answer "that
2069
2076
  * was never decided" from a slice it did not know was a slice.
2077
+ *
2078
+ * That refusal is the default guardrail. `all` bypasses it outright and
2079
+ * always hands back the whole bundle: an explicit, never-accidental escape
2080
+ * hatch for an operator who has the budget to spend, not a wider default.
2070
2081
  */
2071
2082
  async load(bundlePath2, options = {}) {
2072
2083
  const budgetTokens = options.budgetTokens ?? DEFAULT_LOAD_BUDGET;
@@ -2076,7 +2087,7 @@ ${answer}
2076
2087
  const records = adjudicated.filter((hit) => hit.standing !== "superseded");
2077
2088
  const superseded = adjudicated.filter((hit) => hit.standing === "superseded").map(stub);
2078
2089
  const approxTokens2 = records.reduce((total, hit) => total + estimateTokens(hit.record), 0) + superseded.reduce((total, entry) => total + estimateStubTokens(entry), 0);
2079
- if (approxTokens2 > budgetTokens) {
2090
+ if (!options.all && approxTokens2 > budgetTokens) {
2080
2091
  return {
2081
2092
  loaded: false,
2082
2093
  recordCount: wanted.length,
@@ -2087,8 +2098,8 @@ ${answer}
2087
2098
  return {
2088
2099
  loaded: true,
2089
2100
  recordCount: wanted.length,
2090
- approxTokens: approxTokens2,
2091
- budgetTokens,
2101
+ tokensLoaded: approxTokens2,
2102
+ budgetTokens: options.all ? null : budgetTokens,
2092
2103
  records,
2093
2104
  superseded
2094
2105
  };
@@ -2374,4 +2385,4 @@ export {
2374
2385
  KB_DIR,
2375
2386
  KbStore
2376
2387
  };
2377
- //# sourceMappingURL=chunk-EDH43Z7J.js.map
2388
+ //# sourceMappingURL=chunk-FZIMFPGR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/kb-record.schema.ts","../src/record-types.ts","../src/compose.ts","../src/decision-record.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/adjudicate.ts","../src/kb-index.ts","../src/kb-context.ts","../src/kb-log.ts","../src/json-schema.ts","../src/trace.ts","../src/validate.ts","../src/commands/answer.ts","../src/commands/model.ts","../src/commands/context.ts","../src/commands/list.ts","../src/commands/load.ts","../src/commands/log.ts","../src/commands/no-decision.ts","../src/commands/pin.ts","../src/commands/pins.ts","../src/commands/query.ts","../src/commands/read-index.ts","../src/commands/schema.ts","../src/commands/status.ts","../src/commands/supersede.ts","../src/commands/sync-instructions.ts","../src/commands/trace.ts","../src/commands/types.ts","../src/commands/unpin.ts","../src/commands/validate.ts","../src/commands/write.ts","../src/commands/write-decision.ts","../src/commands/index.ts","../src/markdown.ts","../src/errors.ts","../src/kb-errors.ts","../src/search-index.ts","../src/kb-store.ts"],"sourcesContent":["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 * 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. A later\n * pass resolves symbols to line ranges once the change has settled, and records\n * that resolution as a `verified[]` entry.\n */\nexport const kbAnchorSchema = z\n .object({\n file: z.string().min(1),\n symbol: z.string().min(1).optional(),\n })\n .strict();\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 // 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 KbAnchor = z.infer<typeof kbAnchorSchema>;\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","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","import { z } from \"zod\";\nimport {\n kbAnchorSchema,\n kbConceptIdSchema,\n kbSourceSchema,\n KB_CONFIDENCES,\n KB_MATERIALITIES,\n type KbRecordFrontmatter,\n type KbRecordType,\n} from \"./kb-record.schema.js\";\nimport { RECORD_TYPES } from \"./record-types.js\";\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(kbAnchorSchema).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 /** 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 if (parsed.anchors?.length) frontmatter.strauss_anchors = parsed.anchors;\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\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 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 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 return {\n ...(budgetTokens ? { budgetTokens } : {}),\n ...(fullUnderTokens !== undefined ? { fullUnderTokens } : {}),\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\nexport type KbContextBudgets = {\n budgetTokens?: number;\n fullUnderTokens?: number;\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 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\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): 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 return { record, standing: STANDING[status], heads, warnings };\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\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\";\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 * 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): 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 });\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 so a superseded record collapses to an\n // id and its replacement — the same shape `load` hands back, for the same\n // reason: a body outlives the qualifier that said it no longer holds.\n const adjudicated = adjudicate(bundle, bundle);\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\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 ),\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 { z } from \"zod\";\n\nexport const LOG_FILE = \"log.jsonl\";\n\nexport const kbLogEntrySchema = z\n .object({\n at: z.string().min(1),\n by: z.string().min(1),\n operation: z.string().min(1),\n conceptId: z.string().min(1),\n /** Second concept id, where the operation relates two — supersession. */\n target: z.string().min(1).optional(),\n })\n .strict();\n\nexport type KbLogEntry = z.infer<typeof kbLogEntrySchema>;\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(kbLogEntrySchema.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};\n\nexport function parseLog(raw: string): KbLogReadResult {\n const entries: KbLogEntry[] = [];\n const malformed: { line: number; text: string }[] = [];\n\n raw.split(\"\\n\").forEach((text, index) => {\n if (!text.trim()) return;\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 entries.push(parsed.data);\n });\n\n return { entries, malformed };\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 type { KbRecord } from \"./kb-record.schema.js\";\n\n/**\n * Edges a trace may follow.\n *\n * Two more are conceivable and absent: `strauss_answered` carries no target id,\n * so a question's resolution lives in its own body rather than in another\n * record; and following OKF's body markdown links would need a markdown AST\n * pass this package does not yet do.\n */\nexport const TRACE_EDGES = [\"supersession\", \"anchor\", \"source\"] 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 neighbours(from, bundle, edge)) {\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 neighbours(\n from: KbRecord,\n bundle: KbRecord[],\n edge: KbTraceEdge,\n): KbRecord[] {\n switch (edge) {\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 trace, 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\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 type { KbRecord } from \"./kb-record.schema.js\";\nimport { isKbRecordType } from \"./record-types.js\";\n\nexport type KbValidationProblem = {\n check: string;\n conceptId: string;\n note: string;\n};\n\n/**\n * Checks that only hold across the whole bundle.\n *\n * Per-record shape is the schema's job and is enforced on every read, so\n * nothing here re-states it. What a schema cannot see is whether one record's\n * pointers agree with another's — and since `supersede()` now writes both\n * directions, a disagreement means someone edited a file by hand.\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 = (check: string, conceptId: string, note: string) =>\n problems.push({ check, conceptId, note });\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 // 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 { 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: sets the status, stamps who answered and when, and appends an Answer section. If the answer overturns an assumption or a decision, that is a supersession — do it 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 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 /** Positional argv → the same object MCP receives. */\n fromArgv(\n argv: string[],\n bundlePath: string,\n stdin: () => Promise<string>,\n ): Promise<unknown> | unknown;\n run(\n ctx: KbCommandContext,\n input: z.infer<z.ZodObject<Shape>>,\n ): Promise<unknown>;\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 failsWhen?(result: unknown): 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\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/** The value after `--name` in argv, or undefined when the flag is absent. */\nexport function argvFlag(argv: string[], name: string): string | undefined {\n const at = argv.indexOf(name);\n return at !== -1 ? argv[at + 1] : undefined;\n}\n","import { z } from \"zod\";\nimport { buildContext, toHookJson } from \"../kb-context.js\";\nimport { argvFlag, 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] [--format json] [--event NAME]\",\n description:\n \"The pinned-base index block, for injection at every context birth — startup, clear, resume, and after compaction. An index, not the content: concept ids, titles and standing, with the bodies left behind kb_load at the point of use. Emits nothing when nothing is pinned. Refuses with the list of bases and their sizes rather than truncating past its budget. Budgets resolve most-specific-first: explicit flags, then the workspace manifests' `context` tables (per profile, over their `default`), then the built-in profile (session-start, compact, turn), then package defaults — so a repo tunes its own numbers in .strauss/kb-pins.json without touching hook commands. Like kb_schema and kb_types this takes no bundlePath — it reads the workspace pin manifests, because which bases a session should see is workspace state, not a property of one base.\",\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 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 return {\n ...(budget ? { budgetTokens: Number(budget) } : {}),\n ...(fullUnder ? { fullUnderTokens: Number(fullUnder) } : {}),\n ...(profile ? { profile } : {}),\n ...(format ? { format } : {}),\n ...(event ? { event } : {}),\n };\n },\n run: async (\n { store },\n { budgetTokens, fullUnderTokens, profile, format, event },\n ) => {\n const result = await buildContext(store, process.cwd(), {\n ...(budgetTokens ? { budgetTokens } : {}),\n ...(fullUnderTokens ? { fullUnderTokens } : {}),\n ...(profile ? { profile } : {}),\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 { KB_RECORD_TYPES } from \"../kb-record.schema.js\";\nimport { bundlePath, define } from \"./model.js\";\n\nexport const listCommand = define({\n name: \"list\",\n tool: \"kb_list\",\n usage: \"list [type]\",\n description:\n \"Every record, optionally narrowed to one type. Use kb_query when you have a question; this is for enumerating.\",\n input: z.object({ bundlePath, type: z.enum(KB_RECORD_TYPES).optional() }),\n fromArgv: (argv, path) => ({ bundlePath: path, type: argv[1] }),\n run: async ({ store }, { bundlePath: path, type }) =>\n (await store.list(path, type)).map((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","import { z } from \"zod\";\nimport { KB_RECORD_TYPES } from \"../kb-record.schema.js\";\nimport { argvFlag, bundlePath, define } from \"./model.js\";\n\nexport const loadCommand = define({\n name: \"load\",\n tool: \"kb_load\",\n usage: \"load [type] [--budget N | --all]\",\n description:\n \"Load the whole knowledge base at once, each record with its standing. Prefer this over searching: these bases run to a few thousand tokens, and a reader holding all of it has perfect recall and knows why it is asking, which no ranker does. Superseded records arrive under `superseded` as name, replacement and date only — their bodies no longer hold, and reading one later in a long session is the mistake this prevents; pass the id to kb_trace when you need the history. Rejected and unresolved records arrive whole: what was turned down, and what is still open, is the part a diff cannot show you. Refuses with a count rather than truncating when the base is too large — a truncated base is indistinguishable from a complete one, and would have you conclude something was never decided from a slice you did not know was a slice. Call at the point of use, not once per session: a base loaded early is summarised away by compaction, so if the visible context holds no records from this base and the question at hand is one it might govern, load before answering — never conclude nothing was decided from a context with no KB content in it. This tool (with kb_query and kb_trace) is the only supported way to read a base; a raw file read bypasses supersession resolution and returns replaced records as if current.\\n\\nThat refusal is the default guardrail, meant for an agent that would otherwise burn its whole context on one call. `all` bypasses it and loads everything regardless of size: a deliberate operator with the budget to spend, not something to reach for automatically. It is mutually exclusive with `budgetTokens`. When the reader does not need everything, kb_query or a narrower `type` filter is the better fit than either.\",\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 \"Load the entire base regardless of size. The deliberate-operator escape hatch; mutually exclusive with budgetTokens.\",\n ),\n })\n .refine((value) => !(value.all && value.budgetTokens !== undefined), {\n message:\n \"all and budgetTokens are mutually exclusive: pass a ceiling or none, not both.\",\n }),\n fromArgv: (argv, path) => {\n const budget = argvFlag(argv, \"--budget\");\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 };\n },\n run: async ({ store }, { bundlePath: path, type, budgetTokens, all }) => {\n const result = await store.load(path, {\n ...(type ? { type } : {}),\n ...(budgetTokens ? { budgetTokens } : {}),\n ...(all ? { all } : {}),\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 \"What touched what, and when. The only artifact here that cannot be reconstructed from the records, so malformed lines are reported rather than 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 'Claim in one sentence that there was nothing to decide. Gating on \"did you write a decision?\" rewards writing a junk one; gating on \"did you answer?\" does not, so silence has to be expressible. Idempotent — restating it is not a collision.',\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 { 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 pin manifest, so `context` surfaces it at every context birth. Three layers, nearest wins: the committed project manifest (.strauss/kb-pins.json, the default), `--local` (.strauss/kb-pins.local.json, personal and gitignored), and `--user` (~/.strauss/kb-pins.json, every workspace). Idempotent — re-pinning changes nothing unless --mode, --profiles, or --frozen/--unfreeze are given, which update just those fields. `--mode full` preloads the whole base into the block regardless of the full-under threshold; `--mode index` never upgrades. `--profiles` scopes the pin to named context profiles. `--frozen` marks the base concluded: write commands against it refuse and `context` labels it read-only. A path with no records yet succeeds with a warning; bases are routinely pinned before they are populated. Pins are workspace state: the pinned base itself is never touched.\",\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, each with its layer and whether it currently resolves to readable records. Reads the workspace manifests rather than any one base, like kb_context.\",\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 { bundlePath, define } from \"./model.js\";\n\nexport const queryCommand = define({\n name: \"query\",\n tool: \"kb_query\",\n usage: \"query <text...>\",\n description:\n \"Search and return each match with its standing. Results are flagged, never filtered: a superseded record comes back alongside whatever replaced it, and a rejected one is marked as something explicitly not adopted. Prefer kb_load when the base fits its budget: on this package's measurements, a reader holding the whole base answered eight of nine questions whose wording appears in no record, where embedding search answered four. Never read record files directly — this tool (with kb_load and kb_trace) is the only supported way to read a base; a file read bypasses supersession resolution and returns replaced records as if current.\",\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 }),\n fromArgv: (argv, path) => ({\n bundlePath: path,\n text: argv.slice(1).join(\" \").trim(),\n includeNonCurrent: true,\n }),\n run: async ({ store }, { bundlePath: path, text, type, includeNonCurrent }) =>\n (\n await store.query(path, text ?? \"\", {\n ...(type ? { type } : {}),\n includeNonCurrent: includeNonCurrent === true,\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, rebuilt if it disagrees with the records. One call gives the whole shape of the base: title, type, status, and description per record. The cheap re-orientation call after compaction or deep in a long session — a few hundred tokens; call it (or kb_context, when bases are pinned) first, then kb_load or fetch by concept 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 the frontmatter, the write input, and log entries — generated from the code that enforces them, so it cannot drift from what a write will accept.\",\n input: z.object({}),\n fromArgv: () => ({}),\n run: () => Promise.resolve(kbJsonSchemas()),\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, leaving everything else alone. Uses a compare-and-swap, so a concurrent change fails loudly rather than 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, linking both directions. Use this rather than editing a record whose meaning changed — a record that quietly becomes something else invalidates every reference to it, and the earlier understanding is what a later trace needs.\",\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 { 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 \"Idempotently plant the `context` block between sentinel comments in an instruction file (AGENTS.md, CLAUDE.md), creating the block when absent and leaving everything outside the sentinels alone. CLI-only: this is file plumbing for runtimes whose instruction files are re-read where their conversations are not, not an agent capability — the capability is kb_context.\",\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 'How a position was arrived at, as a timeline ordered by when each record was written. Deliberately includes rejected, draft, and superseded records — in a history those are the content, not noise. Follows supersession, shared code anchors, and shared sources. Use when the question is \"why is this the way it is\" rather than \"what do we hold now\". This tool (with kb_load and kb_query) is the only supported way to read a base; a raw file read bypasses supersession resolution and returns replaced records as if current.',\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 pin manifest layer that holds it — project, local, and user — because unpinned means gone, not still injected from another file. Reports which layers were 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 } 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, and assumptions that cite sources. Per-record shape is enforced on every read, so a problem here means someone edited a file by hand.\",\n input: z.object({ bundlePath }),\n fromArgv: (_argv, path) => ({ bundlePath: path }),\n run: async ({ store }, { bundlePath: path }) =>\n validateBundle(await store.list(path)),\n failsWhen: (result) => Array.isArray(result) && result.length > 0,\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 — the same knowledge filed twice under different slugs is how a base rots, and a duplicate concept id is rejected rather than overwritten. Call kb_types for the sections each type accepts.\",\n \"\",\n \"Judgment the tool cannot enforce for you:\",\n \"- An unsourced claim is an `assumption` record with assumption: true, never a `fact` with a vague source. The distinction is what lets a later reader separate what was established from what was guessed.\",\n \"- When two records conflict, say so in a `risk`, an `open-question`, or a superseding `decision`. Quietly picking a winner destroys the disagreement, which is usually the useful part.\",\n \"- Prefer a new record over overloading an existing one, and keep each short. A record nobody finishes reading is not durable memory.\",\n \"- Records are never deleted; supersede instead, so the earlier reasoning stays inspectable.\",\n ].join(\"\\n\"),\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. Takes `alternative` and `impact` as fields rather than free sections, because what was rejected is the part a later reader cannot reconstruct from the code — a heading is too easy to leave empty.\",\n \"\",\n \"What belongs in one:\",\n '- Record a decision when a later reader would otherwise \"simplify\" the constraint away. If the diff already answers the question, there is nothing here to write.',\n \"- `alternative` is what you turned down and why, not a list of everything considered.\",\n \"- A reference to material you read goes in `sources`; a reference to code goes in `anchors`; a reference to another record goes in `relatedConceptIds`.\",\n ].join(\"\\n\"),\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 { answerCommand } from \"./answer.js\";\nimport { contextCommand } from \"./context.js\";\nimport { listCommand } from \"./list.js\";\nimport { loadCommand } from \"./load.js\";\nimport { logCommand } from \"./log.js\";\nimport { noDecisionCommand } from \"./no-decision.js\";\nimport { pinCommand } from \"./pin.js\";\nimport { pinsCommand } from \"./pins.js\";\nimport { queryCommand } from \"./query.js\";\nimport { readIndexCommand } from \"./read-index.js\";\nimport { schemaCommand } from \"./schema.js\";\nimport { statusCommand } from \"./status.js\";\nimport { supersedeCommand } from \"./supersede.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 { 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 loadCommand,\n queryCommand,\n traceCommand,\n listCommand,\n readIndexCommand,\n logCommand,\n validateCommand,\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","/**\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 KbInvalidConceptId = \"KbInvalidConceptId\",\n KbRecordNotFound = \"KbRecordNotFound\",\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\";\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\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","import { stat } from \"node:fs/promises\";\nimport { join } from \"node:path\";\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/** Whether any record is newer than the index. */\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[]);\n for (const name of names) {\n if (!name.endsWith(\".md\") || name === INDEX_FILE) continue;\n const at = await stat(join(bundlePath, name))\n .then((s) => s.mtimeMs)\n .catch(() => 0);\n if (at > indexAt) return true;\n }\n return false;\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 { createHash } from \"node:crypto\";\nimport {\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 {\n parseMarkdownWithFrontmatter,\n stringifyMarkdownWithFrontmatter,\n} from \"./markdown.js\";\nimport {\n kbRecordFrontmatterSchema,\n KB_SLUG_PATTERN,\n type KbRecord,\n type KbRecordFrontmatter,\n type KbRecordStatus,\n} from \"./kb-record.schema.js\";\nimport {\n KbInvalidConceptIdError,\n KbRecordAlreadyExistsError,\n KbRecordNotFoundError,\n KbWriteConflictError,\n} from \"./kb-errors.js\";\nimport { INDEX_FILE, indexIsStale, renderIndex } from \"./kb-index.js\";\nimport { adjudicate, type KbAdjudicated } from \"./adjudicate.js\";\nimport { resolveHits, searchBase, SEARCH_INDEX_FILE } from \"./search-index.js\";\nimport { trace, type KbTraceOptions, type KbTraceStep } from \"./trace.js\";\nimport {\n LOG_FILE,\n parseLog,\n renderLogEntry,\n type KbLogEntry,\n} from \"./kb-log.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([INDEX_FILE, LOG_FILE, SEARCH_INDEX_FILE]);\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. */\nconst 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 | {\n loaded: false;\n recordCount: number;\n approxTokens: number;\n budgetTokens: number;\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\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 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 in turn. 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 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.\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(bundlePath: string, type?: string): 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 Promise.all(\n wanted.map(async ({ name, conceptId }) =>\n this.parse(conceptId, await readFile(join(root, name), \"utf8\")),\n ),\n );\n return records.filter((record): record is KbRecord => record !== null);\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 return this.mutate(\n bundlePath,\n conceptId,\n (frontmatter) => ({ ...frontmatter, strauss_status: status }),\n { operation: `status:${status}`, 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 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 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 * 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: { type?: string; includeNonCurrent?: boolean } = {},\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 adjudicated = adjudicate(\n options.type\n ? hits.filter((r) => r.frontmatter.type === options.type)\n : hits,\n bundle,\n );\n\n if (options.includeNonCurrent) return adjudicated;\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.\n const present = new Set(adjudicated.map((hit) => hit.record.conceptId));\n return adjudicated.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 * 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 * That refusal is the default guardrail. `all` bypasses it outright and\n * always hands back the whole bundle: an explicit, never-accidental escape\n * hatch for an operator who has the budget to spend, not a wider default.\n */\n async load(\n bundlePath: string,\n options: { budgetTokens?: number; type?: string; all?: boolean } = {},\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(wanted, bundle);\n const records = adjudicated.filter((hit) => hit.standing !== \"superseded\");\n const superseded = adjudicated\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 if (!options.all && approxTokens > budgetTokens) {\n return {\n loaded: false,\n recordCount: wanted.length,\n approxTokens,\n budgetTokens,\n };\n }\n\n return {\n loaded: true,\n recordCount: wanted.length,\n tokensLoaded: approxTokens,\n budgetTokens: options.all ? null : budgetTokens,\n records,\n superseded,\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 /**\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 * 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 */\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 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 * `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 entry: 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), { ...entry, conceptId });\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 /** 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 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 */\nfunction estimateTokens(record: KbRecord): number {\n return Math.ceil(\n (record.body.length + JSON.stringify(record.frontmatter).length) / 4,\n );\n}\n\nfunction estimateStubTokens(entry: KbSupersededStub): number {\n return Math.ceil(JSON.stringify(entry).length / 4);\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 */\nfunction 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\nfunction digest(contents: string): string {\n return createHash(\"sha256\").update(contents).digest(\"hex\");\n}\n"],"mappings":"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","names":["z","z","z","z","bundlePath","z","join","join","bundlePath","resolve","bundlePath","resolve","bundlePath","entry","resolve","bundlePath","resolve","readFile","writeFile","HEADING","superseded","readFile","writeFile","z","z","z","conceptId","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","Fault","ErrorTypes","conceptId","join","bundlePath","join","readdir","mkdir","readFile","writeFile","join","resolve","sep","join","bundlePath","conceptId","mkdir","readFile","approxTokens","writeFile","resolve","sep"]}