codealmanac 0.2.5 → 0.2.7
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 +25 -20
- package/dist/{agents-RVTQYE6A.js → agents-V2ZOIACP.js} +6 -5
- package/dist/{chunk-P5WGG4FJ.js → chunk-5BWUMAOX.js} +2 -2
- package/dist/chunk-5BWUMAOX.js.map +1 -0
- package/dist/{chunk-KQUVMF27.js → chunk-BFIG2CXM.js} +2 -516
- package/dist/chunk-BFIG2CXM.js.map +1 -0
- package/dist/{chunk-DL5BXZCX.js → chunk-BQY5L3DL.js} +3 -53
- package/dist/chunk-BQY5L3DL.js.map +1 -0
- package/dist/{chunk-F53U6JQG.js → chunk-CQJVM34R.js} +2 -2
- package/dist/chunk-FUBE6KCO.js +124 -0
- package/dist/chunk-FUBE6KCO.js.map +1 -0
- package/dist/chunk-IZBXXAVL.js +524 -0
- package/dist/chunk-IZBXXAVL.js.map +1 -0
- package/dist/{chunk-7JUX4ADQ.js → chunk-IZT6RBHS.js} +1 -1
- package/dist/{chunk-SMIK2YLU.js → chunk-JLQZELHQ.js} +82 -88
- package/dist/chunk-JLQZELHQ.js.map +1 -0
- package/dist/{chunk-TT6ZP4GS.js → chunk-KZXWPG4P.js} +2 -2
- package/dist/{chunk-6BJUYZ43.js → chunk-QIA22IAM.js} +8 -16
- package/dist/chunk-QIA22IAM.js.map +1 -0
- package/dist/{chunk-BGUID5BS.js → chunk-RALBM6HZ.js} +20 -139
- package/dist/chunk-RALBM6HZ.js.map +1 -0
- package/dist/{chunk-TILAKDN6.js → chunk-U5DLLWIC.js} +3 -3
- package/dist/chunk-WL4UE7Q6.js +1386 -0
- package/dist/chunk-WL4UE7Q6.js.map +1 -0
- package/dist/{chunk-GFUB57IT.js → chunk-ZUQN5Y3K.js} +48 -124
- package/dist/chunk-ZUQN5Y3K.js.map +1 -0
- package/dist/{chunk-MRRX4UQB.js → chunk-ZZLLOAI6.js} +3 -3
- package/dist/{cli-CL4ID7EO.js → cli-XWPNARA6.js} +35 -18
- package/dist/cli-XWPNARA6.js.map +1 -0
- package/dist/codealmanac.js +1 -1
- package/dist/{config-ML2RCR7J.js → config-KH3JUMG6.js} +4 -4
- package/dist/doctor-ENJT665Z.js +18 -0
- package/dist/paths-O5CZADP2.js +14 -0
- package/dist/process-KFSLENL3.js +61 -0
- package/dist/{register-commands-FBJ6XQ3L.js → register-commands-LULZUSPO.js} +993 -1015
- package/dist/register-commands-LULZUSPO.js.map +1 -0
- package/dist/uninstall-BD4MMQ7M.js +16 -0
- package/dist/uninstall-BD4MMQ7M.js.map +1 -0
- package/dist/update-XSKPDFMJ.js +11 -0
- package/dist/update-XSKPDFMJ.js.map +1 -0
- package/dist/{wiki-IGNRNLUZ.js → wiki-O4RWMAE6.js} +8 -6
- package/dist/wiki-O4RWMAE6.js.map +1 -0
- package/guides/mini.md +11 -9
- package/guides/reference.md +96 -39
- package/hooks/almanac-capture.sh +7 -8
- package/package.json +1 -1
- package/prompts/agents/.gitkeep +1 -0
- package/prompts/base/notability.md +139 -0
- package/prompts/base/purpose.md +85 -0
- package/prompts/base/syntax.md +114 -0
- package/prompts/operations/absorb.md +43 -0
- package/prompts/operations/build.md +49 -0
- package/prompts/operations/garden.md +51 -0
- package/dist/chunk-6BJUYZ43.js.map +0 -1
- package/dist/chunk-BGUID5BS.js.map +0 -1
- package/dist/chunk-DL5BXZCX.js.map +0 -1
- package/dist/chunk-GFUB57IT.js.map +0 -1
- package/dist/chunk-KQUVMF27.js.map +0 -1
- package/dist/chunk-P5WGG4FJ.js.map +0 -1
- package/dist/chunk-SMIK2YLU.js.map +0 -1
- package/dist/cli-CL4ID7EO.js.map +0 -1
- package/dist/doctor-DOLJRGS4.js +0 -17
- package/dist/register-commands-FBJ6XQ3L.js.map +0 -1
- package/dist/uninstall-DX6LFKMX.js +0 -15
- package/dist/update-P2IPG7RO.js +0 -11
- package/dist/wiki-IGNRNLUZ.js.map +0 -1
- package/prompts/bootstrap.md +0 -176
- package/prompts/reviewer.md +0 -129
- package/prompts/writer.md +0 -134
- /package/dist/{agents-RVTQYE6A.js.map → agents-V2ZOIACP.js.map} +0 -0
- /package/dist/{chunk-F53U6JQG.js.map → chunk-CQJVM34R.js.map} +0 -0
- /package/dist/{chunk-7JUX4ADQ.js.map → chunk-IZT6RBHS.js.map} +0 -0
- /package/dist/{chunk-TT6ZP4GS.js.map → chunk-KZXWPG4P.js.map} +0 -0
- /package/dist/{chunk-TILAKDN6.js.map → chunk-U5DLLWIC.js.map} +0 -0
- /package/dist/{chunk-MRRX4UQB.js.map → chunk-ZZLLOAI6.js.map} +0 -0
- /package/dist/{config-ML2RCR7J.js.map → config-KH3JUMG6.js.map} +0 -0
- /package/dist/{doctor-DOLJRGS4.js.map → doctor-ENJT665Z.js.map} +0 -0
- /package/dist/{uninstall-DX6LFKMX.js.map → paths-O5CZADP2.js.map} +0 -0
- /package/dist/{update-P2IPG7RO.js.map → process-KFSLENL3.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/topics/frontmatter-rewrite.ts","../src/topics/paths.ts","../src/commands/tag.ts","../src/commands/topics/workspace.ts","../src/commands/topics/create.ts","../src/commands/topics/page-rewrite.ts","../src/commands/topics/delete.ts","../src/commands/topics/describe.ts","../src/commands/topics/link.ts","../src/commands/topics/list.ts","../src/commands/topics/rename.ts","../src/commands/topics/read.ts","../src/commands/topics/show.ts","../src/commands/topics/unlink.ts","../src/registry/autoregister.ts","../src/cli/register-edit-commands.ts","../src/commands/list.ts","../src/commands/search.ts","../src/commands/show.ts","../src/cli/register-query-commands.ts","../src/cli/register-setup-commands.ts","../src/commands/jobs.ts","../src/cli/outcome.ts","../src/commands/operations.ts","../src/agent/prompts.ts","../src/operations/run.ts","../src/operations/absorb.ts","../src/operations/build.ts","../src/commands/init.ts","../src/operations/garden.ts","../src/commands/session-transcripts.ts","../src/commands/reindex.ts","../src/cli/register-wiki-lifecycle-commands.ts","../src/cli/register-commands.ts"],"sourcesContent":["import { readFile, rename, writeFile } from \"node:fs/promises\";\n\nimport yaml from \"js-yaml\";\n\n/**\n * Rewrite the `topics:` field in a markdown file's YAML frontmatter.\n *\n * The absolute requirement is **body byte-preservation**. Tag/untag/\n * rename commands touch only the frontmatter; everything after the\n * closing `---` must be byte-identical to the input (same line endings,\n * same trailing whitespace, same final-newline-or-not). We lean on a\n * precise split rather than re-serializing the whole file so any\n * incidental bytes in the body (literal `\\r\\n`, unusual trailing\n * whitespace, triple-hyphen rulers) are left alone.\n *\n * For the frontmatter itself we do a **surgical rewrite of the `topics:`\n * field only** — not a full YAML roundtrip. Reasons:\n * - `js-yaml` normalizes quoting, re-orders keys alphabetically by\n * default, and can drop comments. Any of those would surprise a user\n * who hand-edited their own frontmatter and expects their formatting\n * preserved byte-for-byte.\n * - We only care about one field. Replacing just that field lets the\n * rest of the YAML survive verbatim.\n *\n * The strategy:\n * 1. Find the exact span of the `topics:` key (whether flow\n * `topics: [a, b]` or block `topics:\\n - a\\n - b\\n`) using a\n * small line scanner.\n * 2. Compute the new topics list from the caller's transform.\n * 3. Replace the span with a freshly-emitted `topics: [a, b, c]` line\n * (flow style — compact, readable, and what most authors write).\n * 4. If no `topics:` key exists and the new list is non-empty, append\n * a line to the end of the frontmatter block.\n * 5. If `topics:` exists but the new list is empty, drop the line\n * entirely rather than leaving `topics: []` around.\n *\n * The transform function gets the current deduplicated topic list and\n * returns the new list. Returning an empty array means \"remove the\n * `topics:` key entirely\".\n */\n\nexport interface RewriteResult {\n /** The page's topics before the rewrite (possibly empty). */\n before: string[];\n /** The page's topics after the rewrite (possibly empty). */\n after: string[];\n /** True iff the file content actually changed. */\n changed: boolean;\n}\n\n/**\n * Read `filePath`, compute the new topics via `transform`, and\n * atomically rewrite if the result differs.\n *\n * Atomic per file: write to `<path>.tmp` then rename, same pattern as\n * the registry and topics.yaml writers. A half-written page would\n * corrupt committed user content, so this is non-negotiable.\n */\nexport async function rewritePageTopics(\n filePath: string,\n transform: (current: string[]) => string[],\n): Promise<RewriteResult> {\n const raw = await readFile(filePath, \"utf8\");\n const { before, after, output, changed } = applyTopicsTransform(\n raw,\n transform,\n );\n if (changed) {\n const tmp = `${filePath}.tmp`;\n await writeFile(tmp, output, \"utf8\");\n await rename(tmp, filePath);\n }\n return { before, after, changed };\n}\n\ninterface TransformApplied {\n before: string[];\n after: string[];\n output: string;\n changed: boolean;\n}\n\n/**\n * Pure-string version of `rewritePageTopics`. Useful for tests and for\n * the few places (rename, delete) where we loop many files and want to\n * short-circuit no-op writes cheaply.\n */\nexport function applyTopicsTransform(\n raw: string,\n transform: (current: string[]) => string[],\n): TransformApplied {\n const parsed = splitFrontmatter(raw);\n if (parsed === null) {\n // No frontmatter at all. Tagging a topic on such a page means\n // creating a frontmatter block. We keep the body untouched and\n // prepend `---\\ntopics: [...]\\n---\\n\\n`. If the transform yields\n // an empty list, this is a no-op. Line endings: default to LF for a\n // brand-new frontmatter — we can't infer intent from a file that\n // doesn't have frontmatter yet, and LF is the committed default in\n // most modern repos.\n const next = dedupeSlugs(transform([]));\n if (next.length === 0) {\n return { before: [], after: [], output: raw, changed: false };\n }\n const fm = `---\\ntopics: ${flowList(next)}\\n---\\n\\n`;\n return {\n before: [],\n after: next,\n output: `${fm}${raw}`,\n changed: true,\n };\n }\n\n const { opener, fmLines, closer, body, eol } = parsed;\n const { before, existingRange } = readTopicsFromLines(fmLines);\n const beforeDeduped = dedupeSlugs(before);\n const after = dedupeSlugs(transform(beforeDeduped));\n\n if (arraysEqual(beforeDeduped, after)) {\n return { before: beforeDeduped, after, output: raw, changed: false };\n }\n\n let nextFmLines: string[];\n if (existingRange === null) {\n // No `topics:` key currently present. Add one (only if non-empty).\n if (after.length === 0) {\n return { before: beforeDeduped, after, output: raw, changed: false };\n }\n nextFmLines = [...fmLines, `topics: ${flowList(after)}`];\n } else {\n const replacement =\n after.length === 0 ? null : `topics: ${flowList(after)}`;\n // Interleaved comments/blank lines from a block-style list are\n // re-emitted BELOW the new flow-style `topics:` line so the\n // author's commentary sticks around. Flow/scalar inputs produce an\n // empty `preserved` array, so this collapses to the old behavior\n // for the common case. When we fully delete the key (empty after)\n // the preserved lines go too — without a `topics:` key to anchor\n // them to, trailing \"# below the topics list\" comments become\n // orphans that no longer mean what they said.\n const preservedTail =\n replacement === null ? [] : existingRange.preserved;\n nextFmLines = [\n ...fmLines.slice(0, existingRange.start),\n ...(replacement === null ? [] : [replacement]),\n ...preservedTail,\n ...fmLines.slice(existingRange.end),\n ];\n }\n\n // Rejoin with the same line ending the input frontmatter used so a\n // CRLF-authored file comes out CRLF end-to-end. `splitFrontmatter`\n // sniffed the dominant separator for us.\n const fmBlock =\n nextFmLines.length === 0 ? \"\" : `${nextFmLines.join(eol)}${eol}`;\n const output = `${opener}${fmBlock}${closer}${body}`;\n return {\n before: beforeDeduped,\n after,\n output,\n changed: true,\n };\n}\n\ninterface SplitFrontmatter {\n /** The opening `---\\n` or `---\\r\\n`. */\n opener: string;\n /** Frontmatter lines (no line-ending character included). */\n fmLines: string[];\n /** The closing `---\\n` (or `---\\r\\n`, possibly without trailing newline if EOF). */\n closer: string;\n /** Everything after the closing fence, byte-for-byte. */\n body: string;\n /**\n * Dominant line ending inside the frontmatter block. CRLF-authored\n * files stay CRLF on write; LF stays LF. We sniff once at split time\n * so rewriting doesn't have to re-inspect every line.\n */\n eol: \"\\n\" | \"\\r\\n\";\n}\n\n/**\n * Split a file into (opener, frontmatter lines, closer, body). The\n * regex mirrors `parseFrontmatter` in `indexer/frontmatter.ts` so the\n * indexer and the rewriter agree on what \"has frontmatter\" means.\n *\n * Returns `null` when the file doesn't start with a `---` fence or\n * lacks a matching closer — both cases are legal (a page with only\n * body content) and the caller treats them as \"no frontmatter to\n * rewrite\".\n */\nfunction splitFrontmatter(raw: string): SplitFrontmatter | null {\n if (!raw.startsWith(\"---\")) return null;\n // Match the exact opener (with its line ending) so we can preserve\n // it byte-for-byte.\n const openerMatch = raw.match(/^---(\\r?\\n)/);\n if (openerMatch === null) return null;\n const opener = `---${openerMatch[1] ?? \"\\n\"}`;\n const rest = raw.slice(opener.length);\n // Find the closing `---` that begins at the start of a line. We\n // also handle the edge case where the closer sits at position 0 of\n // `rest` (frontmatter was empty).\n let fenceIdx: number;\n if (rest.startsWith(\"---\")) {\n fenceIdx = 0;\n } else {\n const m = rest.match(/\\r?\\n---(\\r?\\n|$)/);\n if (m === null || m.index === undefined) return null;\n // `m.index` points at the `\\r?\\n` before `---`; skip that newline\n // so fenceIdx lands exactly on the `-`.\n const leadingNewlineLen = (m[0] ?? \"\").startsWith(\"\\r\\n\") ? 2 : 1;\n fenceIdx = m.index + leadingNewlineLen;\n }\n const fmBlock = rest.slice(0, fenceIdx);\n // Determine the closer's full span, including its trailing newline if any.\n const afterDashes = rest.slice(fenceIdx + 3);\n let closerTail = \"\";\n if (afterDashes.startsWith(\"\\r\\n\")) {\n closerTail = \"\\r\\n\";\n } else if (afterDashes.startsWith(\"\\n\")) {\n closerTail = \"\\n\";\n }\n const closer = `---${closerTail}`;\n const body = afterDashes.slice(closerTail.length);\n const fmLines =\n fmBlock.length === 0 ? [] : fmBlock.replace(/\\r?\\n$/, \"\").split(/\\r?\\n/);\n // Sniff the frontmatter's dominant line ending. We look at the\n // opener first (most reliable signal — it's always present and\n // always has an ending). Fall back to checking the fmBlock for any\n // `\\r\\n` runs so a frontmatter with a single-line opener and\n // multi-line body still gets classified right.\n const eol: \"\\n\" | \"\\r\\n\" =\n opener.endsWith(\"\\r\\n\") || /\\r\\n/.test(fmBlock) ? \"\\r\\n\" : \"\\n\";\n return { opener, fmLines, closer, body, eol };\n}\n\ninterface ExistingRange {\n /** Index in `fmLines` of the `topics:` key line (inclusive). */\n start: number;\n /** Index in `fmLines` one past the last line belonging to this key. */\n end: number;\n /**\n * Lines inside `[start+1, end)` that aren't `- entry` lines — i.e.\n * interleaved comments and blank lines a user wrote between entries.\n * We preserve these verbatim when rewriting block-style lists to\n * flow; otherwise a `tag` on a commented list would silently drop\n * the commentary. Empty for flow/scalar shapes.\n */\n preserved: string[];\n}\n\n/**\n * Find `topics:` in a frontmatter-lines array and read the values.\n *\n * Handles three YAML shapes authors commonly write:\n * - `topics: [a, b, c]` (flow sequence, one line)\n * - `topics:` followed by block entries like ` - a` (block sequence)\n * - `topics: a` (a single scalar — treated as one element)\n *\n * Also handles the empty case `topics:` with nothing after it, and the\n * \"no topics key\" case (returns `existingRange: null`).\n *\n * This is NOT a general YAML parser — it's intentionally scoped to the\n * one key we mutate, because using `js-yaml` for a round-trip would\n * lose comments and re-quote strings the user picked a specific way.\n */\nfunction readTopicsFromLines(fmLines: string[]): {\n before: string[];\n existingRange: ExistingRange | null;\n} {\n const keyLineIdx = findTopKey(fmLines, \"topics\");\n if (keyLineIdx === -1) {\n return { before: [], existingRange: null };\n }\n const keyLine = fmLines[keyLineIdx] ?? \"\";\n const colonIdx = keyLine.indexOf(\":\");\n // Everything to the right of the first colon, trimmed.\n const after = keyLine.slice(colonIdx + 1).trim();\n // Strip trailing `# ...` line-comment from a flow value so we don't\n // parse comments as list contents. (A block list's sub-items have\n // their own comments stripped in the block branch below.)\n const afterNoComment = stripTrailingComment(after);\n\n if (afterNoComment.length === 0) {\n // Block sequence style: collect subsequent `- item` lines. Between\n // entries a user may have written:\n // - interleaved `# comment` lines\n // - blank lines\n // We must NOT break the scan on those — doing so would drop every\n // entry after the first comment/blank when we rewrite (silent data\n // loss: the original bug that triggered this fix). We skip them in\n // the scan and stash them in `preserved` so the replacement step\n // can re-emit them verbatim BETWEEN the new flow-style line and\n // the rest of the frontmatter.\n //\n // Edge: comments/blanks that appear BEFORE the first `- entry` or\n // AFTER the last `- entry` count as part of the block too — pulling\n // them out keeps the author's commentary near the list it belongs\n // to. We cap the scan when we hit a real non-entry line (e.g. the\n // next top-level key), leaving everything from that line onward\n // outside the range.\n const values: string[] = [];\n const preserved: string[] = [];\n // Provisional scan cursor. `endIdx` only advances when we've seen\n // something we're sure belongs to this block (an entry line), so\n // trailing whitespace/comments that don't precede another entry\n // stay OUTSIDE the range and aren't shuffled on rewrite.\n let i = keyLineIdx + 1;\n let endIdx = i;\n // `pendingNonEntries` holds comments/blanks we've seen since the\n // last confirmed entry. They're committed to `preserved` only\n // when a subsequent `- entry` proves they live mid-list.\n let pendingNonEntries: string[] = [];\n while (i < fmLines.length) {\n const line = fmLines[i] ?? \"\";\n const trimmed = line.trim();\n if (trimmed.length === 0 || trimmed.startsWith(\"#\")) {\n pendingNonEntries.push(line);\n i += 1;\n continue;\n }\n const m = line.match(/^\\s*-\\s+(.*)$/);\n if (m === null) break;\n // Promote any pending comments/blanks — they're between entries\n // (or before the first entry within the block).\n if (pendingNonEntries.length > 0) {\n preserved.push(...pendingNonEntries);\n pendingNonEntries = [];\n }\n const raw = stripTrailingComment((m[1] ?? \"\").trim());\n const parsed = parseScalar(raw);\n if (parsed.length > 0) values.push(parsed);\n i += 1;\n endIdx = i;\n }\n return {\n before: values,\n existingRange: { start: keyLineIdx, end: endIdx, preserved },\n };\n }\n\n // Flow / scalar shape on one line. Let js-yaml handle the value-parsing\n // (quoting, escapes, etc.) for the RHS only.\n let parsed: unknown;\n try {\n parsed = yaml.load(afterNoComment);\n } catch {\n parsed = null;\n }\n const values: string[] = [];\n if (Array.isArray(parsed)) {\n for (const v of parsed) {\n if (typeof v === \"string\" && v.trim().length > 0) {\n values.push(v.trim());\n }\n }\n } else if (typeof parsed === \"string\" && parsed.trim().length > 0) {\n values.push(parsed.trim());\n }\n return {\n before: values,\n existingRange: { start: keyLineIdx, end: keyLineIdx + 1, preserved: [] },\n };\n}\n\n/**\n * Find a top-level key line. \"Top-level\" means no leading whitespace —\n * we don't walk into nested mappings. The indexer's frontmatter parser\n * only reads top-level keys too, so this matches.\n */\nfunction findTopKey(fmLines: string[], key: string): number {\n const re = new RegExp(`^${escapeRegex(key)}\\\\s*:`);\n for (let i = 0; i < fmLines.length; i += 1) {\n if (re.test(fmLines[i] ?? \"\")) return i;\n }\n return -1;\n}\n\nfunction escapeRegex(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nfunction stripTrailingComment(s: string): string {\n // Only strip `#` outside of quotes. For the shapes we handle —\n // slug-like kebab-case topics — quoted strings with `#` are rare, but\n // be defensive.\n let inSingle = false;\n let inDouble = false;\n for (let i = 0; i < s.length; i += 1) {\n const ch = s[i];\n if (ch === \"'\" && !inDouble) inSingle = !inSingle;\n else if (ch === '\"' && !inSingle) inDouble = !inDouble;\n else if (ch === \"#\" && !inSingle && !inDouble) {\n return s.slice(0, i).trimEnd();\n }\n }\n return s;\n}\n\n/**\n * Strip YAML quoting from a scalar. Block-sequence items might be\n * written as `- 'foo'` or `- \"foo\"` or bare `- foo`; we accept all\n * three and return the plain string.\n */\nfunction parseScalar(s: string): string {\n if (s.length === 0) return s;\n if (s.length >= 2 && s[0] === '\"' && s[s.length - 1] === '\"') {\n return s.slice(1, -1);\n }\n if (s.length >= 2 && s[0] === \"'\" && s[s.length - 1] === \"'\") {\n return s.slice(1, -1);\n }\n return s;\n}\n\n/**\n * Emit a flow-style YAML sequence like `[auth, jwt, security]`. We use\n * flow because it's the shape most authors write by hand and stays on\n * one line, which keeps diffs tight. Values are quoted only when\n * necessary — plain kebab-case slugs never need quoting.\n */\nfunction flowList(items: string[]): string {\n return `[${items.map((t) => formatScalar(t)).join(\", \")}]`;\n}\n\nfunction formatScalar(s: string): string {\n // If it's a bare kebab/alnum slug, no quotes. Otherwise fall back to\n // js-yaml for correct escaping. We check against a conservative\n // pattern — anything outside it gets YAML-quoted.\n if (/^[a-z0-9][a-z0-9-]*$/.test(s)) return s;\n return yaml\n .dump(s, { flowLevel: 0, lineWidth: Number.MAX_SAFE_INTEGER })\n .trimEnd();\n}\n\nfunction dedupeSlugs(list: string[]): string[] {\n const seen = new Set<string>();\n const out: string[] = [];\n for (const raw of list) {\n const s = raw.trim();\n if (s.length === 0) continue;\n if (seen.has(s)) continue;\n seen.add(s);\n out.push(s);\n }\n return out;\n}\n\nfunction arraysEqual(a: string[], b: string[]): boolean {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i += 1) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n}\n","import { join } from \"node:path\";\n\n/**\n * `.almanac/topics.yaml` inside a given repo root. Single helper so no\n * caller has to remember where the file lives.\n */\nexport function topicsYamlPath(repoRoot: string): string {\n return join(repoRoot, \".almanac\", \"topics.yaml\");\n}\n\n/**\n * `.almanac/index.db` inside a given repo root. Mirrors `topicsYamlPath`\n * so the topics commands don't have to import from scattered places.\n */\nexport function indexDbPath(repoRoot: string): string {\n return join(repoRoot, \".almanac\", \"index.db\");\n}\n","import { ensureFreshIndex, runIndexer } from \"../indexer/index.js\";\nimport { resolveWikiRoot } from \"../indexer/resolve-wiki.js\";\nimport { openIndex } from \"../indexer/schema.js\";\nimport { toKebabCase } from \"../slug.js\";\nimport { rewritePageTopics } from \"../topics/frontmatter-rewrite.js\";\nimport { indexDbPath, topicsYamlPath } from \"../topics/paths.js\";\nimport {\n ensureTopic,\n loadTopicsFile,\n writeTopicsFile,\n} from \"../topics/yaml.js\";\n\n/**\n * `almanac tag <page> <topic>...` and `almanac untag <page> <topic>`.\n *\n * These are the page-side of the topics system — `topics ...` manages\n * the DAG and metadata; `tag`/`untag` wires concrete pages into\n * topics. Both commands mutate page frontmatter atomically per file\n * and leave body bytes untouched.\n *\n * Auto-creation policy: if a topic passed to `tag` doesn't yet exist\n * in `topics.yaml`, we create a minimal entry for it (title-cased\n * title, no description, no parents). This matches the spec: \"Ensure\n * topic exists in topics.yaml; if not, create a minimal entry.\" We\n * don't silently create topics on `untag` — you can only untag\n * something that was already a topic.\n */\n\nexport interface TagCommandOutput {\n stdout: string;\n stderr: string;\n exitCode: number;\n}\n\nexport interface TagOptions {\n cwd: string;\n wiki?: string;\n page?: string;\n topics: string[];\n stdin?: boolean;\n stdinInput?: string;\n}\n\nexport interface UntagOptions {\n cwd: string;\n wiki?: string;\n page: string;\n topic: string;\n}\n\nexport async function runTag(options: TagOptions): Promise<TagCommandOutput> {\n const repoRoot = await resolveWikiRoot({ cwd: options.cwd, wiki: options.wiki });\n\n const topics = options.topics\n .map((t) => toKebabCase(t))\n .filter((t) => t.length > 0);\n if (topics.length === 0) {\n return {\n stdout: \"\",\n stderr: \"almanac: tag requires at least one topic\\n\",\n exitCode: 1,\n };\n }\n\n // Bulk mode reads slugs from stdin; single mode uses the positional.\n const pages: string[] = [];\n if (options.stdin === true) {\n if (options.stdinInput === undefined) {\n return {\n stdout: \"\",\n stderr: \"almanac: tag --stdin called without stdin input\\n\",\n exitCode: 1,\n };\n }\n for (const line of options.stdinInput.split(/\\r?\\n/)) {\n const s = line.trim();\n if (s.length > 0) pages.push(s);\n }\n } else if (options.page !== undefined && options.page.length > 0) {\n pages.push(options.page);\n } else {\n return {\n stdout: \"\",\n stderr: \"almanac: tag requires a page slug (or --stdin)\\n\",\n exitCode: 1,\n };\n }\n\n // Resolve slugs to file paths from the DB. A stale index is fine for\n // `tag` — we just need to find each page's file; `ensureFreshIndex`\n // runs first so the common path is consistent.\n await ensureFreshIndex({ repoRoot });\n const db = openIndex(indexDbPath(repoRoot));\n\n // Validate every requested page exists BEFORE touching topics.yaml.\n // Previously we auto-created topics first, which meant\n // `almanac tag does-not-exist brand-new` left `brand-new` in\n // topics.yaml as a state leak even though the tag itself errored. We\n // resolve rows up front, then short-circuit with an error (and no\n // mutations) if none of the pages are valid.\n const stmt = db.prepare<[string], { file_path: string }>(\n \"SELECT file_path FROM pages WHERE slug = ?\",\n );\n const resolved: { page: string; filePath: string }[] = [];\n const missing: string[] = [];\n try {\n for (const page of pages) {\n const row = stmt.get(toKebabCase(page));\n if (row === undefined) {\n missing.push(page);\n } else {\n resolved.push({ page, filePath: row.file_path });\n }\n }\n } finally {\n db.close();\n }\n\n // Hard-fail when NO page resolved. We deliberately don't mutate\n // topics.yaml on this path — the user's intent (tag page X) is\n // inarguably unsatisfiable, so we shouldn't leave breadcrumbs.\n //\n // In bulk mode (`--stdin`) some pages might resolve and others\n // won't; keeping the original partial-progress behavior for that case\n // (topics get created, resolved pages get tagged, `missing` are\n // reported on stderr with exitCode 1). The state leak only matters\n // when NOTHING succeeds, and that's the case we're fixing.\n if (resolved.length === 0) {\n const stderr = missing.map((p) => `almanac: no such page \"${p}\"\\n`).join(\"\");\n return {\n stdout: \"\",\n stderr,\n exitCode: 1,\n };\n }\n\n // Auto-create missing topics in topics.yaml. Safe to do now — we have\n // at least one page that will actually end up tagged with them.\n const yamlPath = topicsYamlPath(repoRoot);\n const file = await loadTopicsFile(yamlPath);\n let fileChanged = false;\n for (const t of topics) {\n // ensureTopic mutates the file; we check presence beforehand so\n // we only write when something actually changes (skip a redundant\n // atomic rewrite + mtime bump).\n const before = file.topics.length;\n ensureTopic(file, t);\n if (file.topics.length > before) fileChanged = true;\n }\n if (fileChanged) {\n await writeTopicsFile(yamlPath, file);\n }\n\n const summary: string[] = [];\n let taggedPages = 0;\n for (const { page, filePath } of resolved) {\n const result = await rewritePageTopics(filePath, (current) => {\n // Preserve existing order; append new topics in the order\n // the caller supplied them. `applyTopicsTransform` will\n // dedupe for us, but we skip redundant work here too.\n const out = [...current];\n for (const t of topics) if (!current.includes(t)) out.push(t);\n return out;\n });\n if (result.changed) {\n taggedPages += 1;\n // Only surface the NEWLY ADDED topics — not the full request.\n // Reporting every requested topic (including ones the page\n // already had) reads like false positives in commit diffs.\n const added = result.after.filter((t) => !result.before.includes(t));\n summary.push(`tagged ${page}: ${added.join(\", \")}`);\n } else {\n summary.push(\n `no change ${page} (already tagged with ${topics.join(\", \")})`,\n );\n }\n }\n\n if (taggedPages > 0 || fileChanged) {\n // Trigger a reindex so downstream queries see the new rows\n // immediately. Writes to page files bumped their mtimes; writes to\n // topics.yaml are caught by `topicsYamlNewerThan`.\n await runIndexer({ repoRoot });\n }\n\n const stderr = missing.map((p) => `almanac: no such page \"${p}\"\\n`).join(\"\");\n return {\n stdout: summary.length > 0 ? `${summary.join(\"\\n\")}\\n` : \"\",\n stderr,\n exitCode: missing.length > 0 ? 1 : 0,\n };\n}\n\nexport async function runUntag(\n options: UntagOptions,\n): Promise<TagCommandOutput> {\n const repoRoot = await resolveWikiRoot({ cwd: options.cwd, wiki: options.wiki });\n const page = toKebabCase(options.page);\n const topic = toKebabCase(options.topic);\n if (page.length === 0) {\n return {\n stdout: \"\",\n stderr: \"almanac: untag requires a page slug\\n\",\n exitCode: 1,\n };\n }\n if (topic.length === 0) {\n return {\n stdout: \"\",\n stderr: \"almanac: untag requires a topic\\n\",\n exitCode: 1,\n };\n }\n\n await ensureFreshIndex({ repoRoot });\n const db = openIndex(indexDbPath(repoRoot));\n let filePath: string;\n try {\n const row = db\n .prepare<[string], { file_path: string }>(\n \"SELECT file_path FROM pages WHERE slug = ?\",\n )\n .get(page);\n if (row === undefined) {\n return {\n stdout: \"\",\n stderr: `almanac: no such page \"${page}\"\\n`,\n exitCode: 1,\n };\n }\n filePath = row.file_path;\n } finally {\n db.close();\n }\n\n const result = await rewritePageTopics(filePath, (current) =>\n current.filter((t) => t !== topic),\n );\n if (result.changed) {\n await runIndexer({ repoRoot });\n }\n\n return {\n stdout: result.changed\n ? `untagged ${page}: ${topic}\\n`\n : `no change ${page} (not tagged with ${topic})\\n`,\n stderr: \"\",\n exitCode: 0,\n };\n}\n","import type Database from \"better-sqlite3\";\n\nimport { ensureFreshIndex } from \"../../indexer/index.js\";\nimport { resolveWikiRoot } from \"../../indexer/resolve-wiki.js\";\nimport { openIndex } from \"../../indexer/schema.js\";\nimport { indexDbPath, topicsYamlPath } from \"../../topics/paths.js\";\nimport {\n findTopic,\n loadTopicsFile,\n type TopicsFile,\n} from \"../../topics/yaml.js\";\n\ninterface TopicsRepoOptions {\n cwd: string;\n wiki?: string;\n}\n\nexport interface TopicsWorkspace {\n repoRoot: string;\n yamlPath: string;\n file: TopicsFile;\n db: Database.Database;\n}\n\nexport function resolveTopicsRepo(options: TopicsRepoOptions): Promise<string> {\n return resolveWikiRoot({ cwd: options.cwd, wiki: options.wiki });\n}\n\n/**\n * Shared setup path for mutating topic commands. These commands all need\n * a fresh DB view so ad-hoc topics from page frontmatter can be promoted\n * into `topics.yaml` before mutation.\n */\nexport async function openFreshTopicsWorkspace(\n repoRoot: string,\n): Promise<TopicsWorkspace> {\n await ensureFreshIndex({ repoRoot });\n\n const yamlPath = topicsYamlPath(repoRoot);\n const file = await loadTopicsFile(yamlPath);\n const db = openIndex(indexDbPath(repoRoot));\n return { repoRoot, yamlPath, file, db };\n}\n\nexport function closeWorkspace(workspace: TopicsWorkspace): void {\n workspace.db.close();\n}\n\n/**\n * Is `slug` a known topic anywhere — in `topics.yaml`, or as an ad-hoc\n * slug that a page's frontmatter mentioned and the indexer seeded?\n */\nexport function topicExists(\n file: TopicsFile,\n db: Database.Database,\n slug: string,\n): boolean {\n if (findTopic(file, slug) !== null) return true;\n const row = db\n .prepare<[string], { slug: string }>(\n \"SELECT slug FROM topics WHERE slug = ?\",\n )\n .get(slug);\n return row !== undefined;\n}\n","import { runIndexer } from \"../../indexer/index.js\";\nimport { toKebabCase } from \"../../slug.js\";\nimport { ancestorsInFile } from \"../../topics/dag.js\";\nimport {\n ensureTopic,\n findTopic,\n titleCase,\n writeTopicsFile,\n type TopicEntry,\n} from \"../../topics/yaml.js\";\nimport type { TopicsCommandOutput, TopicsCreateOptions } from \"./types.js\";\nimport {\n closeWorkspace,\n openFreshTopicsWorkspace,\n resolveTopicsRepo,\n topicExists,\n} from \"./workspace.js\";\n\n/**\n * `almanac topics create <name> [--parent <slug>]...`.\n *\n * Policy: `--parent <slug>` MUST refer to an existing topic (created\n * earlier in topics.yaml or indexed from page frontmatter). Auto-\n * creating parents silently would let typos cascade — `create JWT\n * --parent secuirty` would quietly spawn a \"secuirty\" topic. Better to\n * refuse and point the user at `almanac topics create <parent>` first.\n *\n * Already-exists is not an error if no new parents are being added —\n * rerunning the same `create` is a no-op. If new parents are introduced\n * we add them (respecting cycle prevention, just like `link`).\n */\nexport async function runTopicsCreate(\n options: TopicsCreateOptions,\n): Promise<TopicsCommandOutput> {\n const repoRoot = await resolveTopicsRepo(options);\n const slug = toKebabCase(options.name);\n if (slug.length === 0) {\n return {\n stdout: \"\",\n stderr: `almanac: topic name \"${options.name}\" has no slug-able characters\\n`,\n exitCode: 1,\n };\n }\n const title = options.name.trim().length > 0 ? options.name.trim() : titleCase(slug);\n\n const workspace = await openFreshTopicsWorkspace(repoRoot);\n try {\n const { repoRoot, yamlPath, file, db } = workspace;\n // Resolve/validate parents BEFORE mutating the file. All-or-nothing.\n const requestedParents = (options.parents ?? [])\n .map((p) => toKebabCase(p))\n .filter((p) => p.length > 0);\n for (const p of requestedParents) {\n if (p === slug) {\n return {\n stdout: \"\",\n stderr: `almanac: topic cannot be its own parent\\n`,\n exitCode: 1,\n };\n }\n if (!topicExists(file, db, p)) {\n return {\n stdout: \"\",\n stderr: `almanac: parent topic \"${p}\" does not exist; create it first with \\`almanac topics create ${p}\\`\\n`,\n exitCode: 1,\n };\n }\n if (findTopic(file, p) === null) {\n // Topic exists only as an ad-hoc DB entry. Promote it into\n // topics.yaml so it has a proper record. `ensureTopic` is\n // idempotent so this is safe even if two loop iterations\n // reference the same ad-hoc parent.\n ensureTopic(file, p);\n }\n }\n\n const existing = findTopic(file, slug);\n if (existing === null) {\n const entry: TopicEntry = {\n slug,\n title,\n description: null,\n parents: requestedParents,\n };\n file.topics.push(entry);\n } else {\n // Add any new parents, skipping ones that already exist or would\n // create a cycle.\n for (const p of requestedParents) {\n if (existing.parents.includes(p)) continue;\n const ancestors = ancestorsInFile(file, p);\n if (ancestors.has(slug) || p === slug) {\n return {\n stdout: \"\",\n stderr: `almanac: adding \"${p}\" as a parent of \"${slug}\" would create a cycle\\n`,\n exitCode: 1,\n };\n }\n existing.parents.push(p);\n }\n // Promote the user-supplied title only if the existing one was a\n // title-cased default (i.e., they didn't describe it yet). Don't\n // clobber a deliberate title silently.\n if (\n existing.title === titleCase(existing.slug) &&\n title !== titleCase(slug) &&\n title !== existing.title\n ) {\n existing.title = title;\n }\n }\n\n await writeTopicsFile(yamlPath, file);\n await runIndexer({ repoRoot });\n return {\n stdout: existing === null\n ? `created topic \"${slug}\"\\n`\n : `updated topic \"${slug}\"\\n`,\n stderr: \"\",\n exitCode: 0,\n };\n } finally {\n closeWorkspace(workspace);\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport fg from \"fast-glob\";\n\nimport {\n applyTopicsTransform,\n rewritePageTopics,\n} from \"../../topics/frontmatter-rewrite.js\";\n\n/**\n * Apply a `topic-list transform` to every `.almanac/pages/*.md` file\n * whose frontmatter contains a relevant topic. Returns the number of\n * files actually changed.\n *\n * We glob page files ourselves (not the DB) so this works even on a\n * stale index — `rename` and `delete` run the indexer AFTER mutation,\n * and we don't want the scan to miss a page that was just modified.\n */\nexport async function rewriteTopicOnPages(\n repoRoot: string,\n transform: (topics: string[]) => string[],\n): Promise<number> {\n const pagesDir = join(repoRoot, \".almanac\", \"pages\");\n const files = await fg(\"**/*.md\", {\n cwd: pagesDir,\n absolute: true,\n onlyFiles: true,\n });\n let changed = 0;\n for (const filePath of files) {\n // Cheap read → in-memory check. Skip files that wouldn't be\n // changed so we don't bump their mtime.\n const raw = await readFile(filePath, \"utf8\");\n const applied = applyTopicsTransform(raw, transform);\n if (!applied.changed) continue;\n await rewritePageTopics(filePath, transform);\n changed += 1;\n }\n return changed;\n}\n","import { runIndexer } from \"../../indexer/index.js\";\nimport { toKebabCase } from \"../../slug.js\";\nimport { writeTopicsFile } from \"../../topics/yaml.js\";\nimport { rewriteTopicOnPages } from \"./page-rewrite.js\";\nimport type { TopicsCommandOutput, TopicsDeleteOptions } from \"./types.js\";\nimport {\n closeWorkspace,\n openFreshTopicsWorkspace,\n resolveTopicsRepo,\n topicExists,\n} from \"./workspace.js\";\n\n/**\n * `almanac topics delete <slug>`. Removes the topic from `topics.yaml`\n * (if present), scrubs any parent edges pointing at it, and untags\n * every page that had it. Pages themselves are left alone — deleting a\n * topic doesn't delete pages, just the relationship.\n */\nexport async function runTopicsDelete(\n options: TopicsDeleteOptions,\n): Promise<TopicsCommandOutput> {\n const repoRoot = await resolveTopicsRepo(options);\n const slug = toKebabCase(options.slug);\n if (slug.length === 0) {\n return { stdout: \"\", stderr: `almanac: empty topic slug\\n`, exitCode: 1 };\n }\n\n const workspace = await openFreshTopicsWorkspace(repoRoot);\n let pagesUpdated: number;\n try {\n const { repoRoot, yamlPath, file, db } = workspace;\n if (!topicExists(file, db, slug)) {\n return {\n stdout: \"\",\n stderr: `almanac: no such topic \"${slug}\"\\n`,\n exitCode: 1,\n };\n }\n\n // Remove the entry and strip it from everyone else's `parents` list.\n file.topics = file.topics.filter((t) => t.slug !== slug);\n for (const t of file.topics) {\n t.parents = t.parents.filter((p) => p !== slug);\n }\n\n // Same write ordering as rename: topics.yaml first (atomic), then\n // pages. A crash between the two leaves topics.yaml already scrubbed\n // and any remaining in-page references become ad-hoc topics — which\n // the reindex will pick up as empty-topics on next health, and the\n // user can re-run to finish untagging.\n await writeTopicsFile(yamlPath, file);\n\n pagesUpdated = await rewriteTopicOnPages(repoRoot, (topics) =>\n topics.filter((t) => t !== slug),\n );\n } finally {\n closeWorkspace(workspace);\n }\n\n await runIndexer({ repoRoot: workspace.repoRoot });\n return {\n stdout: `deleted topic \"${slug}\" (${pagesUpdated} page${pagesUpdated === 1 ? \"\" : \"s\"} untagged)\\n`,\n stderr: \"\",\n exitCode: 0,\n };\n}\n","import { runIndexer } from \"../../indexer/index.js\";\nimport { toKebabCase } from \"../../slug.js\";\nimport { ensureTopic, writeTopicsFile } from \"../../topics/yaml.js\";\nimport type { TopicsCommandOutput, TopicsDescribeOptions } from \"./types.js\";\nimport {\n closeWorkspace,\n openFreshTopicsWorkspace,\n resolveTopicsRepo,\n topicExists,\n} from \"./workspace.js\";\n\n/**\n * `almanac topics describe <slug> \"<text>\"`. Sets or updates the\n * one-liner description. An empty string clears it.\n */\nexport async function runTopicsDescribe(\n options: TopicsDescribeOptions,\n): Promise<TopicsCommandOutput> {\n const repoRoot = await resolveTopicsRepo(options);\n const slug = toKebabCase(options.slug);\n if (slug.length === 0) {\n return { stdout: \"\", stderr: `almanac: empty topic slug\\n`, exitCode: 1 };\n }\n\n const workspace = await openFreshTopicsWorkspace(repoRoot);\n try {\n const { yamlPath, file, db } = workspace;\n if (!topicExists(file, db, slug)) {\n return {\n stdout: \"\",\n stderr: `almanac: no such topic \"${slug}\"\\n`,\n exitCode: 1,\n };\n }\n // `ensureTopic` is idempotent — if the topic was DB-only it\n // promotes into `file`; if already in `file` it returns the\n // existing entry. Either way we get a concrete entry to mutate.\n const entry = ensureTopic(file, slug);\n\n const text = options.description.trim();\n entry.description = text.length === 0 ? null : text;\n\n await writeTopicsFile(yamlPath, file);\n } finally {\n closeWorkspace(workspace);\n }\n\n await runIndexer({ repoRoot: workspace.repoRoot });\n return {\n stdout: `described ${slug}\\n`,\n stderr: \"\",\n exitCode: 0,\n };\n}\n","import { runIndexer } from \"../../indexer/index.js\";\nimport { toKebabCase } from \"../../slug.js\";\nimport { ancestorsInFile } from \"../../topics/dag.js\";\nimport {\n ensureTopic,\n findTopic,\n writeTopicsFile,\n} from \"../../topics/yaml.js\";\nimport type { TopicsCommandOutput, TopicsLinkOptions } from \"./types.js\";\nimport {\n closeWorkspace,\n openFreshTopicsWorkspace,\n resolveTopicsRepo,\n topicExists,\n} from \"./workspace.js\";\n\n/**\n * `almanac topics link <child> <parent>`. Adds a DAG edge after\n * checking that it wouldn't close a cycle. Both topics must exist.\n */\nexport async function runTopicsLink(\n options: TopicsLinkOptions,\n): Promise<TopicsCommandOutput> {\n const repoRoot = await resolveTopicsRepo(options);\n const child = toKebabCase(options.child);\n const parent = toKebabCase(options.parent);\n if (child.length === 0 || parent.length === 0) {\n return { stdout: \"\", stderr: `almanac: empty topic slug\\n`, exitCode: 1 };\n }\n if (child === parent) {\n return {\n stdout: \"\",\n stderr: `almanac: topic cannot be its own parent\\n`,\n exitCode: 1,\n };\n }\n\n const workspace = await openFreshTopicsWorkspace(repoRoot);\n try {\n const { repoRoot, yamlPath, file, db } = workspace;\n for (const slug of [child, parent]) {\n if (!topicExists(file, db, slug)) {\n return {\n stdout: \"\",\n stderr: `almanac: topic \"${slug}\" does not exist\\n`,\n exitCode: 1,\n };\n }\n if (findTopic(file, slug) === null) {\n // DB-only ad-hoc topic → promote it into topics.yaml so the\n // new DAG edge has a concrete home.\n ensureTopic(file, slug);\n }\n }\n\n const childEntry = findTopic(file, child);\n if (childEntry === null) {\n // Shouldn't happen after ensureTopic above — defensive.\n return {\n stdout: \"\",\n stderr: `almanac: topic \"${child}\" not found\\n`,\n exitCode: 1,\n };\n }\n\n if (childEntry.parents.includes(parent)) {\n return {\n stdout: `edge ${child} → ${parent} already exists\\n`,\n stderr: \"\",\n exitCode: 0,\n };\n }\n\n // Cycle check BEFORE mutation. Uses the in-memory file so the check\n // operates on the state we're about to write — no DB round-trip needed.\n const parentAncestors = ancestorsInFile(file, parent);\n if (parentAncestors.has(child) || parent === child) {\n return {\n stdout: \"\",\n stderr: `almanac: adding ${parent} as parent of ${child} would create a cycle\\n`,\n exitCode: 1,\n };\n }\n\n childEntry.parents.push(parent);\n await writeTopicsFile(yamlPath, file);\n await runIndexer({ repoRoot });\n return {\n stdout: `linked ${child} → ${parent}\\n`,\n stderr: \"\",\n exitCode: 0,\n };\n } finally {\n closeWorkspace(workspace);\n }\n}\n","import { BLUE, DIM, RST } from \"../../ansi.js\";\nimport { ensureFreshIndex } from \"../../indexer/index.js\";\nimport { resolveWikiRoot } from \"../../indexer/resolve-wiki.js\";\nimport { openIndex } from \"../../indexer/schema.js\";\nimport { indexDbPath } from \"../../topics/paths.js\";\nimport type { TopicsCommandOutput, TopicsListOptions } from \"./types.js\";\n\n/**\n * `almanac topics` (and `almanac topics list`). Prints one line per\n * known topic — from the DB, which already unions topics.yaml with any\n * ad-hoc slugs found in page frontmatter. Page counts come straight\n * from `page_topics`, which the indexer rebuilt on entry.\n */\nexport async function runTopicsList(\n options: TopicsListOptions,\n): Promise<TopicsCommandOutput> {\n const repoRoot = await resolveWikiRoot({ cwd: options.cwd, wiki: options.wiki });\n await ensureFreshIndex({ repoRoot });\n\n const db = openIndex(indexDbPath(repoRoot));\n try {\n const rows = db\n .prepare<\n [],\n { slug: string; title: string | null; description: string | null; page_count: number }\n >(\n // page_count excludes archived pages — matches the policy used\n // by `topics show` (see `pagesDirectlyTagged`) and by every\n // page-scoped check in `health`. Pick one rule and apply it\n // everywhere; a topic with \"5 pages\" in `topics list` and \"3\n // pages\" in `topics show` is a trust-eroding inconsistency.\n `SELECT t.slug, t.title, t.description,\n (SELECT COUNT(*)\n FROM page_topics pt\n JOIN pages p ON p.slug = pt.page_slug\n WHERE pt.topic_slug = t.slug AND p.archived_at IS NULL\n ) AS page_count\n FROM topics t\n ORDER BY t.slug`,\n )\n .all();\n\n if (options.json === true) {\n return {\n stdout: `${JSON.stringify(rows, null, 2)}\\n`,\n stderr: \"\",\n exitCode: 0,\n };\n }\n\n if (rows.length === 0) {\n return {\n stdout:\n \"no topics. create one with `almanac topics create <name>` or tag a page.\\n\",\n stderr: \"\",\n exitCode: 0,\n };\n }\n\n const slugWidth = rows.reduce((w, r) => Math.max(w, r.slug.length), 0);\n const lines = rows.map((r) => {\n const slug = r.slug.padEnd(slugWidth);\n const count = `(${r.page_count} page${r.page_count === 1 ? \"\" : \"s\"})`;\n return `${BLUE}${slug}${RST} ${DIM}${count}${RST}`;\n });\n return { stdout: `${lines.join(\"\\n\")}\\n`, stderr: \"\", exitCode: 0 };\n } finally {\n db.close();\n }\n}\n","import { runIndexer } from \"../../indexer/index.js\";\nimport { toKebabCase } from \"../../slug.js\";\nimport {\n findTopic,\n titleCase,\n writeTopicsFile,\n} from \"../../topics/yaml.js\";\nimport { rewriteTopicOnPages } from \"./page-rewrite.js\";\nimport type { TopicsCommandOutput, TopicsRenameOptions } from \"./types.js\";\nimport {\n closeWorkspace,\n openFreshTopicsWorkspace,\n resolveTopicsRepo,\n topicExists,\n} from \"./workspace.js\";\n\n/**\n * `almanac topics rename <old> <new>`. Rewrites the slug both in\n * `topics.yaml` (as an entry key and in anyone who declared it as a\n * parent) and in every affected page's frontmatter.\n *\n * Refuses if `<new>` is already a distinct topic — \"merging\" two topics\n * should be explicit, not a silent side effect of a rename.\n */\nexport async function runTopicsRename(\n options: TopicsRenameOptions,\n): Promise<TopicsCommandOutput> {\n const repoRoot = await resolveTopicsRepo(options);\n const oldSlug = toKebabCase(options.oldSlug);\n const newSlug = toKebabCase(options.newSlug);\n if (oldSlug.length === 0 || newSlug.length === 0) {\n return { stdout: \"\", stderr: `almanac: empty topic slug\\n`, exitCode: 1 };\n }\n if (oldSlug === newSlug) {\n return {\n stdout: `topic \"${oldSlug}\" unchanged\\n`,\n stderr: \"\",\n exitCode: 0,\n };\n }\n\n const workspace = await openFreshTopicsWorkspace(repoRoot);\n let pagesUpdated: number;\n try {\n const { repoRoot, yamlPath, file, db } = workspace;\n // Fetch existence info. `oldInYaml` is kept as a direct reference\n // because we mutate the entry; the DB check is only needed when\n // the slug isn't in the file (ad-hoc-only).\n const oldInYaml = findTopic(file, oldSlug);\n if (!topicExists(file, db, oldSlug)) {\n return {\n stdout: \"\",\n stderr: `almanac: no such topic \"${oldSlug}\"\\n`,\n exitCode: 1,\n };\n }\n\n if (topicExists(file, db, newSlug)) {\n return {\n stdout: \"\",\n stderr: `almanac: topic \"${newSlug}\" already exists; delete it first if you intend to merge\\n`,\n exitCode: 1,\n };\n }\n\n // Rewrite `topics.yaml`: the entry itself (if present) plus any\n // parent reference to `oldSlug`.\n if (oldInYaml !== null) {\n oldInYaml.slug = newSlug;\n if (oldInYaml.title === titleCase(oldSlug)) {\n // Title was the auto-generated default — refresh it to the new\n // slug's title-case. A custom title stays as-is.\n oldInYaml.title = titleCase(newSlug);\n }\n }\n for (const t of file.topics) {\n t.parents = t.parents.map((p) => (p === oldSlug ? newSlug : p));\n }\n\n // Write ordering matters: topics.yaml FIRST (atomic tmp+rename), THEN\n // the page rewrites. If topics.yaml write fails, no page was touched.\n // If a page rewrite fails midway, topics.yaml already reflects the\n // rename so the next reindex picks up the ad-hoc state and the user\n // can re-run to finish the remaining pages. The opposite ordering\n // would leave half-rewritten pages referencing a slug that\n // topics.yaml doesn't know about.\n await writeTopicsFile(yamlPath, file);\n\n // Rewrite every page that has `oldSlug` in `topics:` frontmatter.\n pagesUpdated = await rewriteTopicOnPages(repoRoot, (topics) =>\n topics.map((t) => (t === oldSlug ? newSlug : t)),\n );\n } finally {\n closeWorkspace(workspace);\n }\n\n await runIndexer({ repoRoot: workspace.repoRoot });\n return {\n stdout: `renamed ${oldSlug} → ${newSlug} (${pagesUpdated} page${pagesUpdated === 1 ? \"\" : \"s\"} updated)\\n`,\n stderr: \"\",\n exitCode: 0,\n };\n}\n","import type Database from \"better-sqlite3\";\n\nimport { BLUE, DIM, RST } from \"../../ansi.js\";\nimport { descendantsInDb } from \"../../topics/dag.js\";\nimport { titleCase } from \"../../topics/yaml.js\";\n\nexport interface TopicsShowRecord {\n slug: string;\n title: string | null;\n description: string | null;\n parents: string[];\n children: string[];\n pages: string[];\n descendants_used?: boolean;\n}\n\nexport function pagesDirectlyTagged(\n db: Database.Database,\n slug: string,\n): string[] {\n return db\n .prepare<[string], { page_slug: string }>(\n `SELECT pt.page_slug\n FROM page_topics pt\n JOIN pages p ON p.slug = pt.page_slug\n WHERE pt.topic_slug = ? AND p.archived_at IS NULL\n ORDER BY pt.page_slug`,\n )\n .all(slug)\n .map((r) => r.page_slug);\n}\n\nexport function pagesForSubtree(\n db: Database.Database,\n slug: string,\n): string[] {\n const slugs = [slug, ...descendantsInDb(db, slug)];\n // Deduplicate + preserve order via a Set — a page can belong to\n // multiple topics in the subtree and we only want one row per page.\n const placeholders = slugs.map(() => \"?\").join(\", \");\n const rows = db\n .prepare<unknown[], { page_slug: string }>(\n `SELECT DISTINCT pt.page_slug\n FROM page_topics pt\n JOIN pages p ON p.slug = pt.page_slug\n WHERE pt.topic_slug IN (${placeholders}) AND p.archived_at IS NULL\n ORDER BY pt.page_slug`,\n )\n .all(...slugs);\n return rows.map((r) => r.page_slug);\n}\n\nexport function formatShow(r: TopicsShowRecord): string {\n const lines: string[] = [];\n lines.push(`${DIM}slug:${RST} ${BLUE}${r.slug}${RST}`);\n lines.push(`${DIM}title:${RST} ${r.title ?? titleCase(r.slug)}`);\n lines.push(`${DIM}description:${RST} ${r.description ?? \"—\"}`);\n lines.push(\n `${DIM}parents:${RST} ${r.parents.length > 0 ? r.parents.join(\", \") : \"—\"}`,\n );\n lines.push(\n `${DIM}children:${RST} ${r.children.length > 0 ? r.children.join(\", \") : \"—\"}`,\n );\n const pagesLabel = r.descendants_used === true\n ? \"pages (incl. descendants)\"\n : \"pages\";\n lines.push(`${DIM}${pagesLabel}:${RST}`);\n if (r.pages.length === 0) {\n lines.push(\" —\");\n } else {\n for (const p of r.pages) lines.push(` ${BLUE}${p}${RST}`);\n }\n return `${lines.join(\"\\n\")}\\n`;\n}\n","import { ensureFreshIndex } from \"../../indexer/index.js\";\nimport { resolveWikiRoot } from \"../../indexer/resolve-wiki.js\";\nimport { openIndex } from \"../../indexer/schema.js\";\nimport { toKebabCase } from \"../../slug.js\";\nimport { indexDbPath } from \"../../topics/paths.js\";\nimport {\n formatShow,\n pagesDirectlyTagged,\n pagesForSubtree,\n type TopicsShowRecord,\n} from \"./read.js\";\nimport type { TopicsCommandOutput, TopicsShowOptions } from \"./types.js\";\n\n/**\n * `almanac topics show <slug>`. Prints metadata + parents, children,\n * and the page list. `--descendants` widens the page list to include\n * pages tagged with any descendant topic (via the DAG).\n */\nexport async function runTopicsShow(\n options: TopicsShowOptions,\n): Promise<TopicsCommandOutput> {\n const repoRoot = await resolveWikiRoot({ cwd: options.cwd, wiki: options.wiki });\n await ensureFreshIndex({ repoRoot });\n\n const slug = toKebabCase(options.slug);\n if (slug.length === 0) {\n return {\n stdout: \"\",\n stderr: `almanac: empty topic slug\\n`,\n exitCode: 1,\n };\n }\n\n const db = openIndex(indexDbPath(repoRoot));\n try {\n const row = db\n .prepare<\n [string],\n { slug: string; title: string | null; description: string | null }\n >(\"SELECT slug, title, description FROM topics WHERE slug = ?\")\n .get(slug);\n if (row === undefined) {\n return {\n stdout: \"\",\n stderr: `almanac: no such topic \"${slug}\"\\n`,\n exitCode: 1,\n };\n }\n\n const parents = db\n .prepare<[string], { parent_slug: string }>(\n \"SELECT parent_slug FROM topic_parents WHERE child_slug = ? ORDER BY parent_slug\",\n )\n .all(slug)\n .map((r) => r.parent_slug);\n\n const children = db\n .prepare<[string], { child_slug: string }>(\n \"SELECT child_slug FROM topic_parents WHERE parent_slug = ? ORDER BY child_slug\",\n )\n .all(slug)\n .map((r) => r.child_slug);\n\n const pageSlugs = options.descendants === true\n ? pagesForSubtree(db, slug)\n : pagesDirectlyTagged(db, slug);\n\n const record: TopicsShowRecord = {\n slug: row.slug,\n title: row.title,\n description: row.description,\n parents,\n children,\n pages: pageSlugs,\n descendants_used: options.descendants === true,\n };\n\n if (options.json === true) {\n return {\n stdout: `${JSON.stringify(record, null, 2)}\\n`,\n stderr: \"\",\n exitCode: 0,\n };\n }\n return { stdout: formatShow(record), stderr: \"\", exitCode: 0 };\n } finally {\n db.close();\n }\n}\n","import { runIndexer } from \"../../indexer/index.js\";\nimport { resolveWikiRoot } from \"../../indexer/resolve-wiki.js\";\nimport { toKebabCase } from \"../../slug.js\";\nimport { topicsYamlPath } from \"../../topics/paths.js\";\nimport {\n findTopic,\n loadTopicsFile,\n writeTopicsFile,\n} from \"../../topics/yaml.js\";\nimport type { TopicsCommandOutput, TopicsUnlinkOptions } from \"./types.js\";\n\n/**\n * `almanac topics unlink <child> <parent>`. Removes a DAG edge if it\n * exists. No-op (exit 0) if not. Never deletes topics.\n */\nexport async function runTopicsUnlink(\n options: TopicsUnlinkOptions,\n): Promise<TopicsCommandOutput> {\n const repoRoot = await resolveWikiRoot({ cwd: options.cwd, wiki: options.wiki });\n const child = toKebabCase(options.child);\n const parent = toKebabCase(options.parent);\n if (child.length === 0 || parent.length === 0) {\n return { stdout: \"\", stderr: `almanac: empty topic slug\\n`, exitCode: 1 };\n }\n const yamlPath = topicsYamlPath(repoRoot);\n const file = await loadTopicsFile(yamlPath);\n const childEntry = findTopic(file, child);\n if (childEntry === null || !childEntry.parents.includes(parent)) {\n return {\n stdout: `no edge ${child} → ${parent}\\n`,\n stderr: \"\",\n exitCode: 0,\n };\n }\n childEntry.parents = childEntry.parents.filter((p) => p !== parent);\n await writeTopicsFile(yamlPath, file);\n await runIndexer({ repoRoot });\n return {\n stdout: `unlinked ${child} → ${parent}\\n`,\n stderr: \"\",\n exitCode: 0,\n };\n}\n","import { existsSync } from \"node:fs\";\nimport { basename } from \"node:path\";\n\nimport { findNearestAlmanacDir } from \"../paths.js\";\nimport { toKebabCase } from \"../slug.js\";\nimport {\n addEntry,\n readRegistry,\n type RegistryEntry,\n} from \"./index.js\";\n\n/**\n * If the current working directory (or any parent) has a `.almanac/` that\n * isn't in the registry, silently add it. Runs as a side effect of every\n * command except `init` (which does its own registration) and `list --drop`\n * (which shouldn't resurrect the entry the user just removed).\n *\n * The contract is \"silent\" for environmental problems — missing home dir,\n * unreadable registry file, permission errors. Those shouldn't block the\n * real command from running. But a **malformed** registry IS surfaced: if\n * the JSON is corrupt, the user needs to know, not have auto-register\n * quietly pretend the registry was empty and start overwriting entries.\n */\nexport async function autoRegisterIfNeeded(\n cwd: string,\n): Promise<RegistryEntry | null> {\n try {\n const repoRoot = findNearestAlmanacDir(cwd);\n if (repoRoot === null) return null;\n\n // Double-check the directory still exists — `findNearestAlmanacDir`\n // already confirms this, but we're explicit about the precondition.\n if (!existsSync(repoRoot)) return null;\n\n // Read the registry ONCE. `resolveNameCollision` scans this snapshot\n // in memory; re-reading per iteration would be O(N²) in collision\n // count and needlessly hit the filesystem.\n const entries = await readRegistry();\n\n const existing = entries.find((e) => samePath(e.path, repoRoot));\n if (existing !== undefined) return existing;\n\n // Derive a kebab-case name from the directory. If the dir name is\n // somehow empty (e.g. repo is at filesystem root), skip — we don't\n // want to register a nameless entry.\n const name = toKebabCase(basename(repoRoot));\n if (name.length === 0) return null;\n\n // Resolve collisions on name by falling back to a disambiguated form.\n // Auto-registration should never overwrite an existing named entry\n // that points elsewhere.\n const finalName = resolveNameCollision(entries, name, repoRoot);\n if (finalName === null) return null;\n\n const entry: RegistryEntry = {\n name: finalName,\n description: \"\",\n path: repoRoot,\n registered_at: new Date().toISOString(),\n };\n await addEntry(entry);\n return entry;\n } catch (err: unknown) {\n // Only swallow errors that mean \"registry state isn't readable right\n // now\" — everything else (malformed JSON, programmer errors, bugs)\n // should propagate so the user can see it.\n if (\n err instanceof Error &&\n \"code\" in err &&\n (err.code === \"ENOENT\" ||\n err.code === \"EACCES\" ||\n err.code === \"EPERM\")\n ) {\n return null;\n }\n throw err;\n }\n}\n\n/**\n * If another repo already claims `name`, append `-2`, `-3`, ... until we\n * find an unused slug. Only relevant for auto-registration — `init` with\n * `--name` lets the user resolve collisions explicitly.\n *\n * Takes a snapshot of registry entries instead of re-reading the file per\n * iteration. Caps at 1000 attempts to prevent pathological loops if the\n * registry somehow contains every suffix (it can't, but we'd rather fail\n * explicitly than spin).\n */\nfunction resolveNameCollision(\n entries: RegistryEntry[],\n baseName: string,\n repoPath: string,\n): string | null {\n const owner = entries.find((e) => e.name === baseName);\n if (owner === undefined || samePath(owner.path, repoPath)) {\n return baseName;\n }\n const taken = new Set(entries.map((e) => e.name));\n const MAX_ATTEMPTS = 1000;\n for (let suffix = 2; suffix < MAX_ATTEMPTS + 2; suffix += 1) {\n const candidate = `${baseName}-${suffix}`;\n if (!taken.has(candidate)) return candidate;\n }\n return null;\n}\n\n/**\n * Mirror `pathsEqual` in `registry/index.ts` — case-insensitive on\n * macOS/Windows, case-sensitive on Linux. Duplicated here rather than\n * exported to keep the registry module's public surface small.\n */\nfunction samePath(a: string, b: string): boolean {\n if (process.platform === \"darwin\" || process.platform === \"win32\") {\n return a.toLowerCase() === b.toLowerCase();\n }\n return a === b;\n}\n","import { Command } from \"commander\";\n\nimport { runTag, runUntag } from \"../commands/tag.js\";\nimport {\n runTopicsCreate,\n runTopicsDelete,\n runTopicsDescribe,\n runTopicsLink,\n runTopicsList,\n runTopicsRename,\n runTopicsShow,\n runTopicsUnlink,\n} from \"../commands/topics.js\";\nimport { autoRegisterIfNeeded } from \"../registry/autoregister.js\";\nimport { collectOption, emit, readStdin } from \"./helpers.js\";\n\nexport function registerEditCommands(program: Command): void {\n program\n .command(\"tag [page] [topics...]\")\n .description(\"add topics to a page (auto-creates missing topics)\")\n .option(\"--stdin\", \"read page slugs from stdin (one per line)\")\n .option(\"--wiki <name>\", \"target a specific registered wiki\")\n .action(\n async (\n page: string | undefined,\n topicsArg: string[],\n opts: { stdin?: boolean; wiki?: string },\n ) => {\n await autoRegisterIfNeeded(process.cwd());\n const resolvedTopics = opts.stdin === true\n ? [page, ...topicsArg].filter(\n (t): t is string => typeof t === \"string\" && t.length > 0,\n )\n : topicsArg;\n const result = await runTag({\n cwd: process.cwd(),\n page: opts.stdin === true ? undefined : page,\n topics: resolvedTopics,\n stdin: opts.stdin,\n stdinInput: opts.stdin === true ? await readStdin() : undefined,\n wiki: opts.wiki,\n });\n emit(result);\n },\n );\n\n program\n .command(\"untag <page> <topic>\")\n .description(\"remove a topic from a page's frontmatter\")\n .option(\"--wiki <name>\", \"target a specific registered wiki\")\n .action(\n async (page: string, topic: string, opts: { wiki?: string }) => {\n await autoRegisterIfNeeded(process.cwd());\n const result = await runUntag({\n cwd: process.cwd(),\n page,\n topic,\n wiki: opts.wiki,\n });\n emit(result);\n },\n );\n\n const topics = program\n .command(\"topics\")\n .description(\"manage the topic DAG\");\n\n topics\n .command(\"list\", { isDefault: true })\n .description(\"list all topics with page counts\")\n .option(\"--wiki <name>\", \"target a specific registered wiki\")\n .option(\"--json\", \"emit structured JSON\")\n .action(async (opts: { wiki?: string; json?: boolean }) => {\n await autoRegisterIfNeeded(process.cwd());\n const result = await runTopicsList({\n cwd: process.cwd(),\n wiki: opts.wiki,\n json: opts.json,\n });\n emit(result);\n });\n\n topics\n .command(\"show <slug>\")\n .description(\"print a topic's metadata, parents, children, and pages\")\n .option(\"--descendants\", \"include pages tagged with descendant topics\")\n .option(\"--wiki <name>\", \"target a specific registered wiki\")\n .option(\"--json\", \"emit structured JSON\")\n .action(\n async (\n slug: string,\n opts: { descendants?: boolean; wiki?: string; json?: boolean },\n ) => {\n await autoRegisterIfNeeded(process.cwd());\n const result = await runTopicsShow({\n cwd: process.cwd(),\n slug,\n descendants: opts.descendants,\n wiki: opts.wiki,\n json: opts.json,\n });\n emit(result);\n },\n );\n\n topics\n .command(\"create <name>\")\n .description(\"create a topic (rejects if --parent slug does not exist)\")\n .option(\"--parent <slug>\", \"parent topic slug (repeat for multiple parents)\", collectOption, [] as string[])\n .option(\"--wiki <name>\", \"target a specific registered wiki\")\n .action(\n async (name: string, opts: { parent?: string[]; wiki?: string }) => {\n await autoRegisterIfNeeded(process.cwd());\n const result = await runTopicsCreate({\n cwd: process.cwd(),\n name,\n parents: opts.parent,\n wiki: opts.wiki,\n });\n emit(result);\n },\n );\n\n topics\n .command(\"link <child> <parent>\")\n .description(\"add a DAG edge (cycle-checked)\")\n .option(\"--wiki <name>\", \"target a specific registered wiki\")\n .action(async (child: string, parent: string, opts: { wiki?: string }) => {\n await autoRegisterIfNeeded(process.cwd());\n const result = await runTopicsLink({\n cwd: process.cwd(),\n child,\n parent,\n wiki: opts.wiki,\n });\n emit(result);\n });\n\n topics\n .command(\"unlink <child> <parent>\")\n .description(\"remove a DAG edge\")\n .option(\"--wiki <name>\", \"target a specific registered wiki\")\n .action(async (child: string, parent: string, opts: { wiki?: string }) => {\n await autoRegisterIfNeeded(process.cwd());\n const result = await runTopicsUnlink({\n cwd: process.cwd(),\n child,\n parent,\n wiki: opts.wiki,\n });\n emit(result);\n });\n\n topics\n .command(\"rename <old> <new>\")\n .description(\"rename a topic; rewrites every affected page's frontmatter\")\n .option(\"--wiki <name>\", \"target a specific registered wiki\")\n .action(async (oldSlug: string, newSlug: string, opts: { wiki?: string }) => {\n await autoRegisterIfNeeded(process.cwd());\n const result = await runTopicsRename({\n cwd: process.cwd(),\n oldSlug,\n newSlug,\n wiki: opts.wiki,\n });\n emit(result);\n });\n\n topics\n .command(\"delete <slug>\")\n .description(\"delete a topic; untags every affected page\")\n .option(\"--wiki <name>\", \"target a specific registered wiki\")\n .action(async (slug: string, opts: { wiki?: string }) => {\n await autoRegisterIfNeeded(process.cwd());\n const result = await runTopicsDelete({\n cwd: process.cwd(),\n slug,\n wiki: opts.wiki,\n });\n emit(result);\n });\n\n topics\n .command(\"describe <slug> <text>\")\n .description(\"set a topic's one-line description\")\n .option(\"--wiki <name>\", \"target a specific registered wiki\")\n .action(async (slug: string, text: string, opts: { wiki?: string }) => {\n await autoRegisterIfNeeded(process.cwd());\n const result = await runTopicsDescribe({\n cwd: process.cwd(),\n slug,\n description: text,\n wiki: opts.wiki,\n });\n emit(result);\n });\n}\n","import { existsSync } from \"node:fs\";\n\nimport { BLUE, BOLD, DIM, RST } from \"../ansi.js\";\nimport {\n dropEntry,\n readRegistry,\n type RegistryEntry,\n} from \"../registry/index.js\";\n\nexport interface ListOptions {\n json?: boolean;\n drop?: string;\n}\n\nexport interface ListCommandOutput {\n stdout: string;\n exitCode: number;\n}\n\n/**\n * `almanac list` — the global discovery surface. Three modes:\n *\n * - default: pretty table of reachable wikis\n * - `--json`: structured output (reachable wikis only, by default)\n * - `--drop <name>`: explicit removal, then exits\n *\n * **Unreachable paths are silently skipped in the default output**, but\n * never auto-dropped. This is the registry hygiene rule from the design —\n * branch switches, unmounted drives, and VM-offline repos should not cost\n * the user a registration. Only `--drop` removes entries.\n */\nexport async function listWikis(\n options: ListOptions,\n): Promise<ListCommandOutput> {\n if (options.drop !== undefined) {\n return handleDrop(options.drop);\n }\n\n const entries = await readRegistry();\n const reachable = entries.filter((e) => isReachable(e));\n\n if (options.json === true) {\n return { stdout: `${JSON.stringify(reachable, null, 2)}\\n`, exitCode: 0 };\n }\n\n return { stdout: formatPretty(reachable), exitCode: 0 };\n}\n\nasync function handleDrop(name: string): Promise<ListCommandOutput> {\n const removed = await dropEntry(name);\n if (removed === null) {\n return {\n stdout: `no registry entry named \"${name}\"\\n`,\n exitCode: 1,\n };\n }\n return {\n stdout: `removed \"${removed.name}\" (${removed.path})\\n`,\n exitCode: 0,\n };\n}\n\n/**\n * A registry path is \"reachable\" if something still exists at that path.\n * We use `existsSync` rather than `stat` — we don't care whether the path\n * is a directory or has a `.almanac/` inside; we only hide it from default\n * output when the path itself is gone (e.g., repo deleted, drive\n * unmounted).\n */\nfunction isReachable(entry: RegistryEntry): boolean {\n if (entry.path.length === 0) return false;\n return existsSync(entry.path);\n}\n\n/**\n * Human-readable listing. Empty state prints a gentle hint rather than a\n * blank screen, and entries render in registration order (chronological,\n * since `addEntry` appends).\n */\nfunction formatPretty(entries: RegistryEntry[]): string {\n if (entries.length === 0) {\n return `${DIM}no wikis registered. run \\`almanac init\\` in a repo to create one.${RST}\\n`;\n }\n\n // Column-width the name for alignment; cap at 30 so absurd names don't\n // stretch the whole table.\n const nameWidth = Math.min(\n 30,\n entries.reduce((w, e) => Math.max(w, e.name.length), 0),\n );\n\n const lines: string[] = [];\n for (const entry of entries) {\n const name = entry.name.padEnd(nameWidth);\n const desc = entry.description.length > 0 ? entry.description : \"—\";\n lines.push(`${BLUE}${BOLD}${name}${RST} ${desc}`);\n lines.push(`${\" \".repeat(nameWidth)} ${DIM}${entry.path}${RST}`);\n }\n return `${lines.join(\"\\n\")}\\n`;\n}\n","import { join } from \"node:path\";\n\nimport type Database from \"better-sqlite3\";\n\nimport { BLUE, RST } from \"../ansi.js\";\nimport { parseDuration } from \"../indexer/duration.js\";\nimport { ensureFreshIndex } from \"../indexer/index.js\";\nimport { looksLikeDir, normalizePath } from \"../indexer/paths.js\";\nimport { resolveWikiRoot } from \"../indexer/resolve-wiki.js\";\nimport { openIndex } from \"../indexer/schema.js\";\n\nexport interface SearchOptions {\n cwd: string;\n query?: string;\n topics: string[];\n mentions?: string;\n since?: string;\n stale?: string;\n orphan?: boolean;\n includeArchive?: boolean;\n archived?: boolean;\n wiki?: string;\n json?: boolean;\n limit?: number;\n}\n\nexport interface SearchResult {\n slug: string;\n title: string | null;\n updated_at: number;\n archived_at: number | null;\n superseded_by: string | null;\n topics: string[];\n}\n\nexport interface SearchCommandOutput {\n stdout: string;\n stderr: string;\n exitCode: number;\n}\n\n/**\n * `almanac search` — the core query surface.\n *\n * Filters compose with AND logic. The implementation is deliberately\n * pedestrian: build a list of clauses + params, join them with `AND`,\n * intersect topic filters by requiring one subquery per `--topic`. No\n * clever query-planner tricks needed for the sizes we handle (<10k pages).\n *\n * All output ordering is stable: `updated_at DESC, slug ASC`. FTS5 rank\n * is layered on top when the user passed a text query — we ORDER BY rank\n * first, then fall through to the default.\n */\nexport async function runSearch(\n options: SearchOptions,\n): Promise<SearchCommandOutput> {\n const repoRoot = await resolveWikiRoot({\n cwd: options.cwd,\n wiki: options.wiki,\n });\n await ensureFreshIndex({ repoRoot });\n\n const dbPath = join(repoRoot, \".almanac\", \"index.db\");\n const db = openIndex(dbPath);\n\n try {\n const rows = executeQuery(db, options);\n const limited =\n options.limit !== undefined && options.limit >= 0\n ? rows.slice(0, options.limit)\n : rows;\n\n const stdout = formatResults(limited, options);\n const stderr = buildStderr(limited, options);\n return { stdout, stderr, exitCode: 0 };\n } finally {\n db.close();\n }\n}\n\ninterface PageRow {\n slug: string;\n title: string | null;\n updated_at: number;\n archived_at: number | null;\n superseded_by: string | null;\n}\n\nfunction executeQuery(\n db: Database.Database,\n options: SearchOptions,\n): SearchResult[] {\n const whereClauses: string[] = [];\n const params: (string | number)[] = [];\n\n // Archive scope. Three modes, mutually exclusive in practice:\n // - default → active only\n // - --include-archive → active + archived\n // - --archived → archived only\n // `--archived` wins over `--include-archive` when both are passed —\n // being explicit about \"only archived\" is strictly narrower than\n // \"include archived\", so intersecting them yields \"only archived\".\n if (options.archived === true) {\n whereClauses.push(\"p.archived_at IS NOT NULL\");\n } else if (options.includeArchive !== true) {\n whereClauses.push(\"p.archived_at IS NULL\");\n }\n\n // --topic foo --topic bar → page must have BOTH. We add one EXISTS\n // subquery per topic rather than grouping, which keeps param order\n // simple and the plan readable.\n for (const rawTopic of options.topics) {\n const topicSlug = slugForTopic(rawTopic);\n if (topicSlug.length === 0) continue;\n whereClauses.push(\n \"EXISTS (SELECT 1 FROM page_topics pt WHERE pt.page_slug = p.slug AND pt.topic_slug = ?)\",\n );\n params.push(topicSlug);\n }\n\n // --mentions: look for a file_refs row on this page that either\n // matches exactly, OR is a containing folder (is_dir=1 and the query\n // path starts with the row's path), OR the row itself lives inside\n // the queried folder. See spec → \"Graph querying → Query examples\".\n //\n // We deliberately avoid GLOB on the RHS of the comparison with stored\n // `r.path`, because stored paths can legitimately contain GLOB\n // metacharacters — Next.js dynamic routes like `src/[id]/page.tsx`\n // store a literal `[id]`, and `[abc]` is a SQL GLOB character class.\n // Concatenating `r.path || '*'` into a GLOB pattern would make\n // `src/[id]/page.tsx*` match `src/i/page.tsx` (spurious hit on the\n // character class).\n //\n // Instead we enumerate the prefix folders in JS and use parameterized\n // equality. For `src/checkout/handler.ts` the prefixes are\n // `['src/', 'src/checkout/']`; any file_refs row with is_dir=1 and\n // a path in that list is a containing folder of the queried file.\n // This also lets SQLite use `idx_file_refs_path` as an equality\n // probe rather than a range scan.\n if (options.mentions !== undefined && options.mentions.length > 0) {\n const isDir = looksLikeDir(options.mentions);\n const norm = normalizePath(options.mentions, isDir);\n if (isDir) {\n // Query is a folder. Match: the exact folder, OR any file/sub-\n // folder whose path starts with the folder prefix. The prefix\n // match is the one place we still need GLOB — but we escape any\n // wildcard metacharacters in `norm` first so a user-supplied\n // `src/[id]/` query is treated as a literal. Note: the query\n // path comes from the caller, not from stored data, but a user\n // typing `--mentions src/[id]/` should get the literal folder,\n // not a character class.\n const escaped = escapeGlobMeta(norm);\n whereClauses.push(\n `EXISTS (\n SELECT 1 FROM file_refs r\n WHERE r.page_slug = p.slug\n AND (r.path = ? OR r.path GLOB ?)\n )`,\n );\n params.push(norm, `${escaped}*`);\n } else {\n // Query is a file. Match: the exact file, OR any folder whose\n // path is a prefix of this file. Build the prefix list in JS and\n // probe file_refs with equality — no GLOB on stored values.\n const prefixes = parentFolderPrefixes(norm);\n if (prefixes.length === 0) {\n whereClauses.push(\n `EXISTS (\n SELECT 1 FROM file_refs r\n WHERE r.page_slug = p.slug AND r.path = ?\n )`,\n );\n params.push(norm);\n } else {\n const placeholders = prefixes.map(() => \"?\").join(\", \");\n whereClauses.push(\n `EXISTS (\n SELECT 1 FROM file_refs r\n WHERE r.page_slug = p.slug\n AND (\n r.path = ?\n OR (r.is_dir = 1 AND r.path IN (${placeholders}))\n )\n )`,\n );\n params.push(norm, ...prefixes);\n }\n }\n }\n\n const now = Math.floor(Date.now() / 1000);\n\n if (options.since !== undefined) {\n const seconds = parseDuration(options.since);\n whereClauses.push(\"p.updated_at >= ?\");\n params.push(now - seconds);\n }\n\n if (options.stale !== undefined) {\n const seconds = parseDuration(options.stale);\n whereClauses.push(\"p.updated_at < ?\");\n params.push(now - seconds);\n }\n\n if (options.orphan === true) {\n whereClauses.push(\n \"NOT EXISTS (SELECT 1 FROM page_topics pt WHERE pt.page_slug = p.slug)\",\n );\n }\n\n // FTS5 text query. When a text query is supplied we JOIN against\n // `fts_pages` so we can ORDER BY its `rank` column — lower (more\n // negative) ranks are better matches. Without a query we skip the\n // join entirely.\n let sql: string;\n if (options.query !== undefined && options.query.trim().length > 0) {\n const ftsExpr = buildFtsQuery(options.query);\n sql = `\n SELECT p.slug, p.title, p.updated_at, p.archived_at, p.superseded_by\n FROM pages p\n JOIN fts_pages f ON f.slug = p.slug\n WHERE fts_pages MATCH ?\n ${whereClauses.length > 0 ? `AND ${whereClauses.join(\" AND \")}` : \"\"}\n ORDER BY f.rank ASC, p.updated_at DESC, p.slug ASC\n `;\n // MATCH param goes first (it's the first `?` in the compiled SQL).\n params.unshift(ftsExpr);\n } else {\n sql = buildSql(whereClauses);\n }\n\n const rows = db.prepare<unknown[], PageRow>(sql).all(...params);\n\n // Attach topics in a second pass — simpler than a correlated\n // `GROUP_CONCAT`, and the output rows are small enough that N+1 on a\n // single prepared statement is fine.\n const topicStmt = db.prepare<[string], { topic_slug: string }>(\n \"SELECT topic_slug FROM page_topics WHERE page_slug = ? ORDER BY topic_slug\",\n );\n const out: SearchResult[] = rows.map((row) => ({\n slug: row.slug,\n title: row.title,\n updated_at: row.updated_at,\n archived_at: row.archived_at,\n superseded_by: row.superseded_by,\n topics: topicStmt.all(row.slug).map((t) => t.topic_slug),\n }));\n\n return out;\n}\n\nfunction buildSql(whereClauses: string[]): string {\n const where =\n whereClauses.length > 0 ? `WHERE ${whereClauses.join(\" AND \")}` : \"\";\n return `\n SELECT p.slug, p.title, p.updated_at, p.archived_at, p.superseded_by\n FROM pages p\n ${where}\n ORDER BY p.updated_at DESC, p.slug ASC\n `;\n}\n\n/**\n * Turn a user query into an FTS5 MATCH expression. FTS5's default\n * grammar gets unhappy with punctuation (hyphens, colons, slashes), so\n * we tokenize into alphanumeric runs and emit a conjunction of prefixed\n * tokens. Each token is suffixed with `*` so \"stri\" matches \"stripe\".\n *\n * Quoted input (`\"stripe webhook\"`) is treated as an FTS5 phrase query\n * — tokens must appear contiguously in that order. This matches shell\n * conventions where quoting something means \"match it literally\". We\n * strip the surrounding quotes, collapse inner punctuation to spaces,\n * and re-wrap in quotes for FTS5's phrase syntax. Any embedded `\"` in\n * the user input is dropped (FTS5 phrase syntax has no escape).\n *\n * Anything that tokenizes to empty (e.g. pure punctuation) falls back\n * to an empty MATCH, which yields no rows — which is the right answer.\n */\nfunction buildFtsQuery(raw: string): string {\n const trimmed = raw.trim();\n if (\n trimmed.length >= 2 &&\n trimmed.startsWith(\"\\\"\") &&\n trimmed.endsWith(\"\\\"\")\n ) {\n // Phrase mode. Strip outer quotes, lowercase, collapse non-alnum\n // runs to a single space, trim. Any surviving inner `\"` are\n // removed since FTS5 phrase syntax has no escape mechanism.\n const inner = trimmed\n .slice(1, -1)\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \" \")\n .trim();\n if (inner.length === 0) return \"\\\"\\\"\";\n return `\"${inner}\"`;\n }\n const tokens = trimmed\n .toLowerCase()\n .split(/[^a-z0-9]+/)\n .filter((t) => t.length > 0);\n if (tokens.length === 0) return \"\\\"\\\"\";\n return tokens.map((t) => `${t}*`).join(\" AND \");\n}\n\nfunction slugForTopic(raw: string): string {\n return raw\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n}\n\n/**\n * For a normalized file path like `src/checkout/handler.ts`, enumerate\n * every containing folder in the form those folders are stored (trailing\n * slash): `['src/', 'src/checkout/']`. Empty for paths with no folder\n * separator (e.g. `README.md`) — a top-level file has no parent folder\n * recorded in `file_refs`.\n *\n * Used by the `--mentions <file>` path to let us probe `file_refs` with\n * equality instead of GLOB, sidestepping wildcard-escape bugs entirely.\n */\nfunction parentFolderPrefixes(filePath: string): string[] {\n const out: string[] = [];\n let cursor = 0;\n while (true) {\n const next = filePath.indexOf(\"/\", cursor);\n if (next === -1) break;\n // Slice includes the slash — matches how directories are stored.\n out.push(filePath.slice(0, next + 1));\n cursor = next + 1;\n }\n return out;\n}\n\n/**\n * Escape SQLite GLOB metacharacters (`*`, `?`, `[`) by wrapping each in\n * a single-character class. SQLite GLOB has no backslash-escape, so the\n * idiomatic trick is `[*]` → literal `*`, `[?]` → literal `?`, `[[]` →\n * literal `[`. `]` doesn't need escaping outside a class.\n *\n * We only need this on the *query* side — stored paths aren't\n * concatenated into GLOB patterns anymore (see --mentions handling).\n * But a user-typed `--mentions src/[id]/` should still match a stored\n * `src/[id]/` literally, not as a character class over `i` or `d`.\n */\nfunction escapeGlobMeta(s: string): string {\n return s.replace(/[\\*\\?\\[]/g, (ch) => `[${ch}]`);\n}\n\nfunction formatResults(\n rows: SearchResult[],\n options: SearchOptions,\n): string {\n if (options.json === true) {\n return `${JSON.stringify(rows, null, 2)}\\n`;\n }\n // Default output: one slug per line. Empty result = empty output (not\n // \"no results found\") — makes piping into xargs / subsequent commands\n // degrade gracefully.\n if (rows.length === 0) return \"\";\n return `${rows.map((r) => `${BLUE}${r.slug}${RST}`).join(\"\\n\")}\\n`;\n}\n\nfunction buildStderr(rows: SearchResult[], options: SearchOptions): string {\n // Spec: \"print warns if >50 when not --json\". The warning goes to\n // stderr so it doesn't corrupt pipelines that filter stdout.\n if (options.json === true) return \"\";\n // Empty-result breadcrumb (v0.1.3). Interviews showed users saw blank\n // stdout and concluded the wiki was broken rather than the query\n // genuinely matched nothing. A single `# 0 results` line to stderr\n // makes the outcome legible without corrupting stdout pipelines (the\n // downstream command still sees zero lines). `--json` mode is silent\n // because `[]` is the unambiguous empty signal there.\n if (rows.length === 0) {\n return \"# 0 results\\n\";\n }\n if (options.limit !== undefined) return \"\";\n if (rows.length > 50) {\n return `almanac: ${rows.length} results — consider --limit or a narrower query\\n`;\n }\n return \"\";\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport type Database from \"better-sqlite3\";\n\nimport { BLUE, DIM, RST } from \"../ansi.js\";\nimport { ensureFreshIndex } from \"../indexer/index.js\";\nimport { resolveWikiRoot } from \"../indexer/resolve-wiki.js\";\nimport { openIndex } from \"../indexer/schema.js\";\n\n/**\n * `almanac show <slug>` — structured view of a page.\n *\n * This file absorbs what used to be split across `show` (body), `info`\n * (metadata), and `path` (file path resolution). One command, multiple\n * view flags.\n *\n * Three output \"shapes\":\n *\n * 1. **Default** — metadata header + `\\n---\\n` separator + body. Useful\n * to skim a page and still see its topics/files/links at a glance.\n * 2. **View flags** (mutually exclusive-ish):\n * --json structured JSON, overrides everything else\n * --body body only (`--raw` is a deprecated CLI alias)\n * --meta metadata only, no body\n * --lead first paragraph of body only (cheap preview)\n * 3. **Field flags** (composable). Each selects one \"field\" of the page:\n * --title / --topics / --files / --links / --backlinks / --xwiki\n * --lineage / --updated / --path\n * A single field → bare, pipe-friendly output (one item per line).\n * Multiple fields → labeled sections, one per flag.\n *\n * `--stdin` is always JSON Lines (one record per line). This avoids the\n * separator ambiguity with markdown `---` in bulk output: the old `info`\n * used a human-readable array; the old `show` used `\\n---\\n` which\n * collided with page frontmatter delimiters.\n */\nexport interface ShowOptions {\n cwd: string;\n slug?: string;\n stdin?: boolean;\n stdinInput?: string;\n wiki?: string;\n\n // View modes (mutually exclusive-ish — precedence: json > raw > meta > lead > default).\n json?: boolean;\n raw?: boolean; // alias: body\n meta?: boolean;\n lead?: boolean;\n\n // Composable field flags.\n title?: boolean;\n topics?: boolean;\n files?: boolean;\n links?: boolean;\n backlinks?: boolean;\n xwiki?: boolean;\n lineage?: boolean;\n updated?: boolean;\n path?: boolean;\n}\n\nexport interface ShowCommandOutput {\n stdout: string;\n stderr: string;\n exitCode: number;\n}\n\n/**\n * The structured record emitted by `--json`. Also the shape we read into\n * in order to compose any other output. Keeping this a plain flat object\n * means callers can JSON.parse downstream tooling without chasing nested\n * subschemas.\n */\nexport interface ShowRecord {\n slug: string;\n title: string | null;\n file_path: string;\n updated_at: number;\n archived_at: number | null;\n superseded_by: string | null;\n supersedes: string[];\n topics: string[];\n file_refs: Array<{ path: string; is_dir: boolean }>;\n wikilinks_out: string[];\n wikilinks_in: string[];\n cross_wiki_links: Array<{ wiki: string; target: string }>;\n body: string;\n}\n\nexport async function runShow(\n options: ShowOptions,\n): Promise<ShowCommandOutput> {\n const repoRoot = await resolveWikiRoot({\n cwd: options.cwd,\n wiki: options.wiki,\n });\n await ensureFreshIndex({ repoRoot });\n\n const dbPath = join(repoRoot, \".almanac\", \"index.db\");\n const db = openIndex(dbPath);\n\n try {\n const slugs = collectSlugs(options);\n if (slugs.length === 0) {\n return {\n stdout: \"\",\n stderr: \"almanac: show requires a slug (or --stdin)\\n\",\n exitCode: 1,\n };\n }\n\n const records: ShowRecord[] = [];\n const missing: string[] = [];\n for (const slug of slugs) {\n const rec = await fetchRecord(db, slug);\n if (rec === null) {\n missing.push(slug);\n continue;\n }\n records.push(rec);\n }\n\n const bulk = options.stdin === true;\n const stdout = bulk\n ? formatBulk(records)\n : formatSingle(records, options);\n\n const stderr = missing\n .map((s) => `almanac: no such page \"${s}\"\\n`)\n .join(\"\");\n\n return {\n stdout,\n stderr,\n exitCode: missing.length > 0 ? 1 : 0,\n };\n } finally {\n db.close();\n }\n}\n\n// ─── Record fetch ────────────────────────────────────────────────────\n\nasync function fetchRecord(\n db: Database.Database,\n slug: string,\n): Promise<ShowRecord | null> {\n const pageRow = db\n .prepare<\n [string],\n {\n slug: string;\n title: string | null;\n file_path: string;\n updated_at: number;\n archived_at: number | null;\n superseded_by: string | null;\n }\n >(\n \"SELECT slug, title, file_path, updated_at, archived_at, superseded_by FROM pages WHERE slug = ?\",\n )\n .get(slug);\n if (pageRow === undefined) return null;\n\n const topics = db\n .prepare<[string], { topic_slug: string }>(\n \"SELECT topic_slug FROM page_topics WHERE page_slug = ? ORDER BY topic_slug\",\n )\n .all(slug)\n .map((r) => r.topic_slug);\n\n const refs = db\n .prepare<[string], { original_path: string; is_dir: number }>(\n \"SELECT original_path, is_dir FROM file_refs WHERE page_slug = ? ORDER BY original_path\",\n )\n .all(slug)\n .map((r) => ({ path: r.original_path, is_dir: r.is_dir === 1 }));\n\n const linksOut = db\n .prepare<[string], { target_slug: string }>(\n \"SELECT target_slug FROM wikilinks WHERE source_slug = ? ORDER BY target_slug\",\n )\n .all(slug)\n .map((r) => r.target_slug);\n\n const linksIn = db\n .prepare<[string], { source_slug: string }>(\n \"SELECT source_slug FROM wikilinks WHERE target_slug = ? ORDER BY source_slug\",\n )\n .all(slug)\n .map((r) => r.source_slug);\n\n const xwiki = db\n .prepare<[string], { target_wiki: string; target_slug: string }>(\n \"SELECT target_wiki, target_slug FROM cross_wiki_links WHERE source_slug = ? ORDER BY target_wiki, target_slug\",\n )\n .all(slug)\n .map((r) => ({ wiki: r.target_wiki, target: r.target_slug }));\n\n const supersedesRows = db\n .prepare<[string], { slug: string }>(\n \"SELECT slug FROM pages WHERE superseded_by = ? ORDER BY slug\",\n )\n .all(slug)\n .map((r) => r.slug);\n\n // Read body (strip YAML frontmatter). `show` is the only command\n // permitted to read page content, per the spec.\n let body = \"\";\n try {\n body = stripFrontmatter(await readFile(pageRow.file_path, \"utf8\"));\n } catch {\n // If the page row exists but the file is unreadable (race with `git\n // mv`, permission change, …) we keep the record — everything else we\n // have is sourced from the index. Body renders as empty. The missing\n // view flags still work.\n }\n\n return {\n slug: pageRow.slug,\n title: pageRow.title,\n file_path: pageRow.file_path,\n updated_at: pageRow.updated_at,\n archived_at: pageRow.archived_at,\n superseded_by: pageRow.superseded_by,\n supersedes: supersedesRows,\n topics,\n file_refs: refs,\n wikilinks_out: linksOut,\n wikilinks_in: linksIn,\n cross_wiki_links: xwiki,\n body,\n };\n}\n\n// ─── Formatting ──────────────────────────────────────────────────────\n\nfunction formatBulk(records: ShowRecord[]): string {\n // JSON Lines. One record per line, trailing newline when non-empty.\n // Consumers split on `\\n` and `JSON.parse` each line.\n if (records.length === 0) return \"\";\n return records.map((r) => JSON.stringify(r)).join(\"\\n\") + \"\\n\";\n}\n\nfunction formatSingle(\n records: ShowRecord[],\n options: ShowOptions,\n): string {\n if (options.json === true) {\n // JSON always wins. Positional mode emits a single object (never an\n // array) for a found page, `null` for a missing one — matches the\n // shape contract from the old `info --json`.\n const only = records[0] ?? null;\n return `${JSON.stringify(only, null, 2)}\\n`;\n }\n return records.map((r) => formatRecord(r, options)).join(\"\");\n}\n\n/**\n * Figure out which fields the user asked for. Precedence:\n * 1. Body-only mode — everything else is ignored.\n * 2. `--meta` — metadata only, no body. Ignores `--lead`.\n * 3. `--lead` — first paragraph only.\n * 4. Any field flag (`--title`, `--topics`, …) set → those fields only.\n * 5. Nothing set → full view (metadata header + body).\n */\ntype FieldName =\n | \"title\"\n | \"topics\"\n | \"files\"\n | \"links\"\n | \"backlinks\"\n | \"xwiki\"\n | \"lineage\"\n | \"updated\"\n | \"path\";\n\nconst FIELD_ORDER: FieldName[] = [\n \"title\",\n \"topics\",\n \"files\",\n \"links\",\n \"backlinks\",\n \"xwiki\",\n \"lineage\",\n \"updated\",\n \"path\",\n];\n\nfunction selectedFields(options: ShowOptions): FieldName[] {\n const selected: FieldName[] = [];\n for (const f of FIELD_ORDER) {\n if (options[f] === true) selected.push(f);\n }\n return selected;\n}\n\nfunction formatRecord(rec: ShowRecord, options: ShowOptions): string {\n // 1. raw / body\n if (options.raw === true) {\n // Guarantee exactly one trailing newline. Without it, shell redirects\n // (`almanac show foo --body > foo.md`) produce files missing a final\n // newline, which confuses concatenation and diff tools. We don't\n // collapse multiple trailing newlines — a page that ends with a\n // blank line is intentional.\n if (rec.body.length === 0) return \"\";\n return rec.body.endsWith(\"\\n\") ? rec.body : `${rec.body}\\n`;\n }\n\n // 4. Field flags (check before meta/lead so --meta + --title is unambiguous).\n const fields = selectedFields(options);\n if (fields.length > 0) {\n if (fields.length === 1) {\n return bareField(rec, fields[0]!);\n }\n return labeledFields(rec, fields);\n }\n\n // 2. meta only\n if (options.meta === true) {\n return metadataHeader(rec) + \"\\n\";\n }\n\n // 3. lead only\n if (options.lead === true) {\n return firstParagraph(rec.body) + \"\\n\";\n }\n\n // 5. Default — metadata header + separator + body.\n const header = metadataHeader(rec);\n const body = rec.body;\n const sep = body.length > 0 ? `\\n\\n${DIM}---${RST}\\n\\n` : \"\\n\";\n return header + sep + body;\n}\n\n/**\n * Single-field bare output. One item per line, no labels, no colons —\n * designed to be piped directly into another command. The exact format\n * per field tries to preserve \"scriptable by default\":\n *\n * --title → the title (or empty if null)\n * --topics → one topic slug per line\n * --files → one file ref per line; trailing slash for folders\n * --links → one outgoing slug per line\n * --backlinks → one incoming slug per line\n * --xwiki → one `wiki:slug` per line\n * --lineage → archived_at / supersedes / superseded_by, one per line\n * (only the ones that exist — silent when all absent)\n * --updated → ISO-8601 UTC timestamp\n * --path → absolute file path (replaces the old `almanac path`)\n */\nfunction bareField(rec: ShowRecord, field: FieldName): string {\n switch (field) {\n case \"title\":\n return (rec.title ?? \"\") + \"\\n\";\n case \"topics\":\n return rec.topics.map((t) => `${t}\\n`).join(\"\");\n case \"files\":\n return rec.file_refs\n .map((r) => `${r.path}\\n`)\n .join(\"\");\n case \"links\":\n return rec.wikilinks_out.map((t) => `${t}\\n`).join(\"\");\n case \"backlinks\":\n return rec.wikilinks_in.map((t) => `${t}\\n`).join(\"\");\n case \"xwiki\":\n return rec.cross_wiki_links\n .map((x) => `${x.wiki}:${x.target}\\n`)\n .join(\"\");\n case \"lineage\": {\n const lines: string[] = [];\n if (rec.archived_at !== null) {\n lines.push(\n `archived_at: ${new Date(rec.archived_at * 1000).toISOString()}`,\n );\n }\n if (rec.superseded_by !== null) {\n lines.push(`superseded_by: ${rec.superseded_by}`);\n }\n if (rec.supersedes.length > 0) {\n lines.push(`supersedes: ${rec.supersedes.join(\", \")}`);\n }\n return lines.length > 0 ? `${lines.join(\"\\n\")}\\n` : \"\";\n }\n case \"updated\":\n return `${new Date(rec.updated_at * 1000).toISOString()}\\n`;\n case \"path\":\n return `${rec.file_path}\\n`;\n }\n}\n\n/**\n * Multi-field labeled output. Each requested field renders as a labeled\n * section, in canonical order (the order of `FIELD_ORDER`, not the order\n * flags appeared on the command line). Sections are separated by blank\n * lines to make grep-by-label reliable.\n */\nfunction labeledFields(rec: ShowRecord, fields: FieldName[]): string {\n const parts: string[] = [];\n for (const f of fields) {\n parts.push(labeledSection(rec, f));\n }\n return parts.join(\"\\n\");\n}\n\nfunction labeledSection(rec: ShowRecord, field: FieldName): string {\n switch (field) {\n case \"title\":\n return `${DIM}title:${RST} ${rec.title ?? \"—\"}\\n`;\n case \"topics\":\n return rec.topics.length > 0\n ? `${DIM}topics:${RST} ${rec.topics.join(\", \")}\\n`\n : `${DIM}topics:${RST} —\\n`;\n case \"files\":\n return formatListSection(\n \"files\",\n rec.file_refs.map((r) => `${r.path}`),\n );\n case \"links\":\n return formatListSection(\"links\", rec.wikilinks_out);\n case \"backlinks\":\n return formatListSection(\"backlinks\", rec.wikilinks_in);\n case \"xwiki\":\n return formatListSection(\n \"xwiki\",\n rec.cross_wiki_links.map((x) => `${x.wiki}:${x.target}`),\n );\n case \"lineage\": {\n const lines: string[] = [`${DIM}lineage:${RST}`];\n if (rec.archived_at !== null) {\n lines.push(\n ` ${DIM}archived_at:${RST} ${new Date(rec.archived_at * 1000).toISOString()}`,\n );\n }\n if (rec.superseded_by !== null) {\n lines.push(` ${DIM}superseded_by:${RST} ${rec.superseded_by}`);\n }\n if (rec.supersedes.length > 0) {\n lines.push(` ${DIM}supersedes:${RST} ${rec.supersedes.join(\", \")}`);\n }\n if (lines.length === 1) lines.push(\" —\");\n return lines.join(\"\\n\") + \"\\n\";\n }\n case \"updated\":\n return `${DIM}updated:${RST} ${new Date(rec.updated_at * 1000).toISOString()}\\n`;\n case \"path\":\n return `${DIM}path:${RST} ${rec.file_path}\\n`;\n }\n}\n\nfunction formatListSection(label: string, items: string[]): string {\n if (items.length === 0) return `${DIM}${label}:${RST} —\\n`;\n if (items.length <= 3) return `${DIM}${label}:${RST} ${items.join(\", \")}\\n`;\n return `${DIM}${label}:${RST}\\n${items.map((i) => ` ${i}`).join(\"\\n\")}\\n`;\n}\n\n/**\n * Metadata header rendered for default and `--meta` views. Single-line\n * fields for short lists; indented block form for long lists. This is\n * the human-readable counterpart to the JSON dump — labeled, column-\n * aligned, skimmable.\n */\nfunction metadataHeader(rec: ShowRecord): string {\n const lines: string[] = [];\n lines.push(`${DIM}slug:${RST} ${BLUE}${rec.slug}${RST}`);\n lines.push(`${DIM}title:${RST} ${rec.title ?? \"—\"}`);\n lines.push(\n `${DIM}topics:${RST} ${rec.topics.length > 0 ? rec.topics.join(\", \") : \"—\"}`,\n );\n\n if (rec.file_refs.length > 0) {\n const parts = rec.file_refs.map(\n (r) => `${r.path}`,\n );\n lines.push(`${DIM}files:${RST} ${parts.join(\", \")}`);\n }\n\n lines.push(\n `${DIM}updated:${RST} ${new Date(rec.updated_at * 1000).toISOString()}`,\n );\n\n if (rec.wikilinks_out.length > 0) {\n lines.push(`${DIM}links:${RST} ${rec.wikilinks_out.join(\", \")}`);\n }\n if (rec.wikilinks_in.length > 0) {\n lines.push(`${DIM}backlinks:${RST} ${rec.wikilinks_in.join(\", \")}`);\n }\n if (rec.cross_wiki_links.length > 0) {\n lines.push(\n `${DIM}xwiki:${RST} ${rec.cross_wiki_links\n .map((x) => `${x.wiki}:${x.target}`)\n .join(\", \")}`,\n );\n }\n if (rec.archived_at !== null) {\n lines.push(\n `${DIM}archived:${RST} ${new Date(rec.archived_at * 1000).toISOString()}`,\n );\n }\n if (rec.superseded_by !== null) {\n lines.push(`${DIM}superseded_by:${RST} ${rec.superseded_by}`);\n }\n if (rec.supersedes.length > 0) {\n lines.push(`${DIM}supersedes:${RST} ${rec.supersedes.join(\", \")}`);\n }\n\n return lines.join(\"\\n\");\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────\n\n/**\n * Strip a leading YAML frontmatter block (fenced by `---` on its own\n * lines). Everything between the opening `---\\n` and the next `---\\n` is\n * dropped, along with the surrounding fence. If no opening fence is\n * present we return the source unchanged.\n *\n * Hand-rolled rather than pulling in gray-matter because the CLI's only\n * goal here is \"show the body without the YAML header\" — we don't need\n * the parsed fields, the indexer already has them.\n */\nfunction stripFrontmatter(src: string): string {\n if (!src.startsWith(\"---\\n\") && !src.startsWith(\"---\\r\\n\")) return src;\n // Strip the opening fence. A regex replace handles both LF and CRLF\n // line endings without the off-by-one that `src.indexOf(\"\\n\") + 1`\n // suffered on CRLF files — `indexOf(\"\\n\")` landed AFTER the `\\r`, so\n // the `\\r` survived as a prefix on the first body byte.\n const afterOpen = src.replace(/^---\\r?\\n/, \"\");\n const endMatch = afterOpen.match(/^---[ \\t]*\\r?\\n/m);\n if (endMatch === null || endMatch.index === undefined) return src;\n // Slice after the closing fence's line.\n return afterOpen.slice(endMatch.index + endMatch[0].length);\n}\n\n/**\n * First paragraph of the body, where \"paragraph\" is everything up to (but\n * not including) the first blank line. Skips a leading `# Title` line if\n * present so `--lead` previews the first real sentence, not the heading.\n */\nfunction firstParagraph(body: string): string {\n let src = body.trimStart();\n if (src.startsWith(\"# \")) {\n const nl = src.indexOf(\"\\n\");\n src = nl === -1 ? \"\" : src.slice(nl + 1).trimStart();\n }\n const blank = src.search(/\\n[ \\t]*\\n/);\n if (blank === -1) return src.trimEnd();\n return src.slice(0, blank).trimEnd();\n}\n\nfunction collectSlugs(options: ShowOptions): string[] {\n if (options.stdin === true && options.stdinInput !== undefined) {\n return options.stdinInput\n .split(/\\r?\\n/)\n .map((s) => s.trim())\n .filter((s) => s.length > 0);\n }\n if (options.slug !== undefined && options.slug.length > 0) {\n return [options.slug];\n }\n return [];\n}\n","import { Command } from \"commander\";\n\nimport { runHealth } from \"../commands/health.js\";\nimport { listWikis } from \"../commands/list.js\";\nimport { runSearch } from \"../commands/search.js\";\nimport { runShow } from \"../commands/show.js\";\nimport { autoRegisterIfNeeded } from \"../registry/autoregister.js\";\nimport {\n collectOption,\n deprecationWarning,\n emit,\n parsePositiveInt,\n readStdin,\n withWarning,\n} from \"./helpers.js\";\n\nexport function registerQueryCommands(program: Command): void {\n program\n .command(\"search [query]\")\n .description(\"find pages by text, topic, file mentions, freshness\")\n .option(\n \"--topic <name...>\",\n \"filter by topic (repeat for intersection)\",\n collectOption,\n [] as string[],\n )\n .option(\n \"--mentions <path>\",\n \"pages referencing this path; matches exact file, trailing-slash folders, and any file under a folder prefix\",\n )\n .option(\"--since <duration>\", \"updated within duration, by file mtime (e.g. 2w, 30d)\")\n .option(\"--stale <duration>\", \"NOT updated within duration, by file mtime\")\n .option(\"--orphan\", \"pages with no topics\")\n .option(\"--include-archive\", \"include archived pages\")\n .option(\"--archived\", \"archived pages only\")\n .option(\"--wiki <name>\", \"target a specific registered wiki\")\n .option(\"--json\", \"emit structured JSON\")\n .option(\"--limit <n>\", \"cap results\", parsePositiveInt)\n .action(\n async (\n query: string | undefined,\n opts: {\n topic?: string[];\n mentions?: string;\n since?: string;\n stale?: string;\n orphan?: boolean;\n includeArchive?: boolean;\n archived?: boolean;\n wiki?: string;\n json?: boolean;\n limit?: number;\n },\n ) => {\n await autoRegisterIfNeeded(process.cwd());\n const result = await runSearch({\n cwd: process.cwd(),\n query,\n topics: opts.topic ?? [],\n mentions: opts.mentions,\n since: opts.since,\n stale: opts.stale,\n orphan: opts.orphan,\n includeArchive: opts.includeArchive,\n archived: opts.archived,\n wiki: opts.wiki,\n json: opts.json,\n limit: opts.limit,\n });\n emit(result);\n },\n );\n\n program\n .command(\"show [slug]\")\n .description(\"print a page (metadata + body; flags to narrow)\")\n .option(\"--stdin\", \"read slugs from stdin (one per line)\")\n .option(\"--wiki <name>\", \"target a specific registered wiki\")\n .option(\"--json\", \"structured JSON (overrides other view/field flags)\")\n .option(\"--body\", \"body only\")\n .option(\"--raw\", \"deprecated alias for --body\")\n .option(\"--meta\", \"metadata only, no body\")\n .option(\"--lead\", \"first paragraph of the body only\")\n .option(\"--title\", \"print title\")\n .option(\"--topics\", \"print topics\")\n .option(\"--files\", \"print file refs\")\n .option(\"--links\", \"print outgoing wikilinks\")\n .option(\"--backlinks\", \"print incoming wikilinks\")\n .option(\"--xwiki\", \"print cross-wiki links\")\n .option(\"--lineage\", \"print archived_at / supersedes / superseded_by\")\n .option(\"--updated\", \"print updated timestamp\")\n .option(\"--path\", \"print absolute file path\")\n .action(\n async (\n slug: string | undefined,\n opts: {\n stdin?: boolean;\n wiki?: string;\n json?: boolean;\n raw?: boolean;\n body?: boolean;\n meta?: boolean;\n lead?: boolean;\n title?: boolean;\n topics?: boolean;\n files?: boolean;\n links?: boolean;\n backlinks?: boolean;\n xwiki?: boolean;\n lineage?: boolean;\n updated?: boolean;\n path?: boolean;\n },\n ) => {\n await autoRegisterIfNeeded(process.cwd());\n const result = await runShow({\n cwd: process.cwd(),\n slug,\n stdin: opts.stdin,\n stdinInput: opts.stdin === true ? await readStdin() : undefined,\n wiki: opts.wiki,\n json: opts.json,\n raw: opts.raw === true || opts.body === true,\n meta: opts.meta,\n lead: opts.lead,\n title: opts.title,\n topics: opts.topics,\n files: opts.files,\n links: opts.links,\n backlinks: opts.backlinks,\n xwiki: opts.xwiki,\n lineage: opts.lineage,\n updated: opts.updated,\n path: opts.path,\n });\n emit(opts.raw === true\n ? withWarning(\n result,\n deprecationWarning(\"almanac show <slug> --raw\", \"almanac show <slug> --body\"),\n )\n : result);\n },\n );\n\n program\n .command(\"health\")\n .description(\"report graph integrity problems\")\n .option(\"--topic <name>\", \"scope to a topic + its descendants\")\n .option(\"--stale <duration>\", \"stale threshold (default 90d)\")\n .option(\"--stdin\", \"read page slugs from stdin (limit to these pages)\")\n .option(\"--json\", \"emit structured JSON\")\n .option(\"--wiki <name>\", \"target a specific registered wiki\")\n .action(\n async (opts: {\n topic?: string;\n stale?: string;\n stdin?: boolean;\n json?: boolean;\n wiki?: string;\n }) => {\n await autoRegisterIfNeeded(process.cwd());\n const result = await runHealth({\n cwd: process.cwd(),\n topic: opts.topic,\n stale: opts.stale,\n stdin: opts.stdin,\n stdinInput: opts.stdin === true ? await readStdin() : undefined,\n json: opts.json,\n wiki: opts.wiki,\n });\n emit(result);\n },\n );\n\n program\n .command(\"list\")\n .description(\"list registered wikis\")\n .option(\"--json\", \"emit structured JSON\")\n .option(\n \"--drop <name>\",\n \"remove a wiki from the registry (the only way entries are ever removed)\",\n )\n .action(async (opts: { json?: boolean; drop?: string }) => {\n if (opts.drop === undefined) {\n await autoRegisterIfNeeded(process.cwd());\n }\n const result = await listWikis(opts);\n process.stdout.write(result.stdout);\n if (result.exitCode !== 0) {\n process.exitCode = result.exitCode;\n }\n });\n}\n","import { Command } from \"commander\";\n\nimport {\n runAgentsDoctor,\n runAgentsList,\n runAgentsModel,\n runAgentsUse,\n runDeprecatedSetAgentModel,\n runDeprecatedSetDefaultAgent,\n} from \"../commands/agents.js\";\nimport {\n runConfigGet,\n runConfigList,\n runConfigSet,\n runConfigUnset,\n} from \"../commands/config.js\";\nimport { runDoctor } from \"../commands/doctor.js\";\nimport { runSetup } from \"../commands/setup.js\";\nimport { runUninstall } from \"../commands/uninstall.js\";\nimport { runUpdate } from \"../commands/update.js\";\nimport { emit } from \"./helpers.js\";\n\nexport function registerSetupCommands(program: Command): void {\n const agents = program\n .command(\"agents\")\n .description(\"list supported AI agent providers and readiness\");\n\n agents\n .command(\"list\")\n .description(\"show Claude, Codex, and Cursor provider status\")\n .action(async () => {\n emit(await runAgentsList());\n });\n\n agents\n .command(\"doctor\")\n .description(\"diagnose supported AI agent providers\")\n .action(async () => {\n emit(await runAgentsDoctor());\n });\n\n agents\n .command(\"use\")\n .description(\"set the default AI agent provider\")\n .argument(\"<provider>\", \"claude, codex, cursor, or claude/<model>\")\n .action(async (provider: string) => {\n emit(await runAgentsUse({ provider }));\n });\n\n agents\n .command(\"model\")\n .description(\"set or reset a provider model\")\n .argument(\"<provider>\", \"claude, codex, or cursor\")\n .argument(\"[model]\", \"provider-specific model id\")\n .option(\"--default\", \"reset to provider default\")\n .action(async (\n provider: string,\n model: string | undefined,\n opts: { default?: boolean },\n ) => {\n emit(await runAgentsModel({\n provider,\n model,\n defaultModel: opts.default,\n }));\n });\n\n const config = program\n .command(\"config\")\n .description(\"read and write codealmanac settings\");\n\n config\n .command(\"list\")\n .description(\"show supported config keys\")\n .option(\"--json\", \"emit structured JSON\")\n .option(\"--show-origin\", \"show whether each value came from file or default\")\n .action(async (opts: { json?: boolean; showOrigin?: boolean }) => {\n emit(await runConfigList(opts));\n });\n\n config\n .command(\"get\")\n .description(\"print one config value\")\n .argument(\"<key>\", \"config key\")\n .option(\"--json\", \"emit structured JSON\")\n .option(\"--show-origin\", \"show whether the value came from file or default\")\n .action(async (\n key: string,\n opts: { json?: boolean; showOrigin?: boolean },\n ) => {\n emit(await runConfigGet({ key, ...opts }));\n });\n\n config\n .command(\"set\")\n .description(\"set one config value\")\n .argument(\"<key>\", \"config key\")\n .argument(\"<value>\", \"config value\")\n .option(\"--project\", \"write .almanac/config.toml for this repo\")\n .action(async (\n key: string,\n value: string,\n opts: { project?: boolean },\n ) => {\n emit(await runConfigSet({ key, value, project: opts.project }));\n });\n\n config\n .command(\"unset\")\n .description(\"restore one config value to default\")\n .argument(\"<key>\", \"config key\")\n .option(\"--project\", \"remove from .almanac/config.toml for this repo\")\n .action(async (key: string, opts: { project?: boolean }) => {\n emit(await runConfigUnset({ key, project: opts.project }));\n });\n\n program\n .command(\"set\")\n .description(\"configure codealmanac defaults\")\n .argument(\"<key>\", \"setting key, e.g. default-agent or model\")\n .argument(\"[value...]\", \"setting value\")\n .action(async (key: string, value: string[]) => {\n if (key === \"default-agent\") {\n emit(await runDeprecatedSetDefaultAgent({ provider: value[0] ?? \"\" }));\n return;\n }\n if (key === \"model\") {\n emit(await runDeprecatedSetAgentModel({\n provider: value[0] ?? \"\",\n model: value[1],\n }));\n return;\n }\n emit({\n stdout: \"\",\n stderr:\n \"almanac: unknown setting. Use `default-agent` or `model`.\\n\",\n exitCode: 1,\n });\n });\n\n program\n .command(\"setup\")\n .description(\"install the hook + CLAUDE.md guides (bare codealmanac alias)\")\n .option(\"-y, --yes\", \"skip prompts; install everything\")\n .option(\"--agent <agent>\", \"default agent: claude, codex, or cursor\")\n .option(\"--model <model>\", \"default model for the selected agent\")\n .option(\"--skip-hook\", \"opt out of the SessionEnd hook\")\n .option(\"--skip-guides\", \"opt out of the CLAUDE.md guides\")\n .action(\n async (opts: {\n yes?: boolean;\n agent?: string;\n model?: string;\n skipHook?: boolean;\n skipGuides?: boolean;\n }) => {\n const result = await runSetup({\n yes: opts.yes,\n agent: opts.agent,\n model: opts.model,\n skipHook: opts.skipHook,\n skipGuides: opts.skipGuides,\n });\n emit(result);\n },\n );\n\n program\n .command(\"doctor\")\n .description(\"report on the codealmanac install + current wiki health\")\n .option(\"--json\", \"emit structured JSON\")\n .option(\"--install-only\", \"report only on the install (skip wiki checks)\")\n .option(\"--wiki-only\", \"report only on the current wiki (skip install checks)\")\n .action(\n async (opts: {\n json?: boolean;\n installOnly?: boolean;\n wikiOnly?: boolean;\n }) => {\n const result = await runDoctor({\n cwd: process.cwd(),\n json: opts.json,\n installOnly: opts.installOnly,\n wikiOnly: opts.wikiOnly,\n });\n emit(result);\n },\n );\n\n program\n .command(\"update\")\n .description(\"install the latest codealmanac (synchronous foreground `npm i -g`)\")\n .option(\n \"--dismiss\",\n \"silence the update banner for the current `latest_version` without installing\",\n )\n .option(\"--check\", \"force a registry check now (bypasses the 24h cache); no install\")\n .option(\n \"--enable-notifier\",\n \"deprecated: use `almanac config set update_notifier true`\",\n )\n .option(\n \"--disable-notifier\",\n \"deprecated: use `almanac config set update_notifier false`\",\n )\n .action(\n async (opts: {\n dismiss?: boolean;\n check?: boolean;\n enableNotifier?: boolean;\n disableNotifier?: boolean;\n }) => {\n const result = await runUpdate({\n dismiss: opts.dismiss,\n check: opts.check,\n enableNotifier: opts.enableNotifier,\n disableNotifier: opts.disableNotifier,\n });\n emit(result);\n },\n );\n\n program\n .command(\"uninstall\")\n .description(\"remove the hook + guides + import line\")\n .option(\"-y, --yes\", \"skip confirmations; remove everything\")\n .option(\"--keep-hook\", \"don't remove the SessionEnd hook (guides still prompted unless --yes)\")\n .option(\n \"--keep-guides\",\n \"don't remove the guides or CLAUDE.md import (hook still prompted unless --yes)\",\n )\n .action(\n async (opts: {\n yes?: boolean;\n keepHook?: boolean;\n keepGuides?: boolean;\n }) => {\n const result = await runUninstall({\n yes: opts.yes,\n keepHook: opts.keepHook,\n keepGuides: opts.keepGuides,\n });\n emit(result);\n },\n );\n}\n","import { readFile } from \"node:fs/promises\";\n\nimport type { CommandResult } from \"../cli/helpers.js\";\nimport { renderOutcome } from \"../cli/outcome.js\";\nimport { findNearestAlmanacDir } from \"../paths.js\";\nimport {\n finishRunRecord,\n markRunCancelled,\n listRunRecords,\n readRunRecord,\n runRecordPath,\n toRunView,\n writeRunRecord,\n} from \"../process/index.js\";\nimport type { RunView } from \"../process/index.js\";\n\nexport interface JobsOptions {\n cwd: string;\n json?: boolean;\n now?: () => Date;\n isPidAlive?: (pid: number) => boolean;\n}\n\nexport interface JobByIdOptions extends JobsOptions {\n runId: string;\n}\n\nexport interface JobAttachStreamOptions extends JobByIdOptions {\n write?: (chunk: string) => void;\n pollMs?: number;\n}\n\nexport async function runJobsList(\n options: JobsOptions,\n): Promise<CommandResult> {\n const repoRoot = resolveWikiOrResult(options.cwd, options.json);\n if (typeof repoRoot !== \"string\") return repoRoot;\n\n const views = await listRunViews(repoRoot, options);\n if (options.json === true) {\n return {\n stdout: `${JSON.stringify({ runs: views }, null, 2)}\\n`,\n stderr: \"\",\n exitCode: 0,\n };\n }\n\n if (views.length === 0) {\n return { stdout: \"Jobs\\n\\nNo jobs found.\\n\", stderr: \"\", exitCode: 0 };\n }\n const lines = [\"Jobs\", \"\"];\n for (const view of views) {\n lines.push(\n `${view.id} ${view.operation} ${view.displayStatus} ${formatMs(view.elapsedMs)}`,\n );\n }\n return { stdout: `${lines.join(\"\\n\")}\\n`, stderr: \"\", exitCode: 0 };\n}\n\nexport async function runJobsShow(\n options: JobByIdOptions,\n): Promise<CommandResult> {\n const repoRoot = resolveWikiOrResult(options.cwd, options.json);\n if (typeof repoRoot !== \"string\") return repoRoot;\n const view = await readRunView(repoRoot, options);\n if (view === null) return missingRun(options.runId, options.json);\n\n if (options.json === true) {\n return {\n stdout: `${JSON.stringify(view, null, 2)}\\n`,\n stderr: \"\",\n exitCode: 0,\n };\n }\n\n return {\n stdout:\n [\n `Run: ${view.id}`,\n `Operation: ${view.operation}`,\n `Status: ${view.displayStatus}`,\n `Provider: ${view.provider}${view.model !== undefined ? `/${view.model}` : \"\"}`,\n `Elapsed: ${formatMs(view.elapsedMs)}`,\n `Log: ${view.logPath}`,\n view.failure !== undefined\n ? `Reason: ${view.failure.message}`\n : view.error !== undefined\n ? `Error: ${view.error}`\n : undefined,\n view.failure?.fix !== undefined ? `Fix: ${view.failure.fix}` : undefined,\n ].filter((line): line is string => line !== undefined).join(\"\\n\") + \"\\n\",\n stderr: \"\",\n exitCode: 0,\n };\n}\n\nexport async function runJobsLogs(\n options: JobByIdOptions,\n): Promise<CommandResult> {\n const repoRoot = resolveWikiOrResult(options.cwd, options.json);\n if (typeof repoRoot !== \"string\") return repoRoot;\n const record = await readRunRecord(runRecordPath(repoRoot, options.runId));\n if (record === null) return missingRun(options.runId, options.json);\n try {\n return {\n stdout: await readFile(record.logPath, \"utf8\"),\n stderr: \"\",\n exitCode: 0,\n };\n } catch (err: unknown) {\n return renderOutcome(\n {\n type: \"error\",\n message: err instanceof Error ? err.message : String(err),\n },\n { json: options.json },\n );\n }\n}\n\nexport async function runJobsAttach(\n options: JobByIdOptions,\n): Promise<CommandResult> {\n const logs = await runJobsLogs(options);\n if (logs.exitCode !== 0 || options.json === true) return logs;\n return {\n ...logs,\n stdout:\n logs.stdout.length > 0\n ? logs.stdout\n : \"No log events have been written yet.\\n\",\n };\n}\n\nexport async function streamJobsAttach(\n options: JobAttachStreamOptions,\n): Promise<CommandResult> {\n const repoRoot = resolveWikiOrResult(options.cwd, options.json);\n if (typeof repoRoot !== \"string\") return repoRoot;\n const initial = await readRunRecord(runRecordPath(repoRoot, options.runId));\n if (initial === null) return missingRun(options.runId, options.json);\n\n const write = options.write ?? ((chunk: string) => process.stdout.write(chunk));\n let offset = 0;\n while (true) {\n const record = await readRunRecord(runRecordPath(repoRoot, options.runId));\n if (record === null) return missingRun(options.runId, options.json);\n offset = await writeLogChunk(record.logPath, offset, write);\n const view = toRunView({\n record,\n now: options.now?.() ?? new Date(),\n isPidAlive: options.isPidAlive ?? isPidAlive,\n });\n if (\n view.displayStatus === \"done\" ||\n view.displayStatus === \"failed\" ||\n view.displayStatus === \"cancelled\" ||\n view.displayStatus === \"stale\"\n ) {\n const summary = terminalAttachSummary(view);\n if (summary.length > 0) write(summary);\n return { stdout: \"\", stderr: \"\", exitCode: 0 };\n }\n await sleep(options.pollMs ?? 500);\n }\n}\n\nexport async function runJobsCancel(\n options: JobByIdOptions,\n): Promise<CommandResult> {\n const repoRoot = resolveWikiOrResult(options.cwd, options.json);\n if (typeof repoRoot !== \"string\") return repoRoot;\n const path = runRecordPath(repoRoot, options.runId);\n const record = await readRunRecord(path);\n if (record === null) return missingRun(options.runId, options.json);\n if (record.status === \"done\" || record.status === \"failed\" || record.status === \"cancelled\") {\n return renderOutcome(\n {\n type: \"noop\",\n message: `job already ${record.status}: ${record.id}`,\n data: { runId: record.id, status: record.status },\n },\n { json: options.json },\n );\n }\n\n await markRunCancelled(repoRoot, record.id);\n\n if (record.pid > 0) {\n try {\n process.kill(record.pid, \"SIGTERM\");\n } catch {\n // The final record still becomes cancelled; stale detection covers\n // processes that already exited.\n }\n }\n\n const cancelled = finishRunRecord({\n record,\n status: \"cancelled\",\n finishedAt: options.now?.() ?? new Date(),\n });\n await writeRunRecord(path, cancelled);\n return renderOutcome(\n {\n type: \"success\",\n message: `cancelled job: ${record.id}`,\n data: { runId: record.id, status: \"cancelled\" },\n },\n { json: options.json },\n );\n}\n\nasync function listRunViews(\n repoRoot: string,\n options: JobsOptions,\n): Promise<RunView[]> {\n const records = await listRunRecords(repoRoot);\n return records.map((record) =>\n toRunView({\n record,\n now: options.now?.() ?? new Date(),\n isPidAlive: options.isPidAlive ?? isPidAlive,\n }),\n );\n}\n\nasync function readRunView(\n repoRoot: string,\n options: JobByIdOptions,\n): Promise<RunView | null> {\n const record = await readRunRecord(runRecordPath(repoRoot, options.runId));\n if (record === null) return null;\n return toRunView({\n record,\n now: options.now?.() ?? new Date(),\n isPidAlive: options.isPidAlive ?? isPidAlive,\n });\n}\n\nfunction resolveWikiOrResult(\n cwd: string,\n json: boolean | undefined,\n): string | CommandResult {\n const repoRoot = findNearestAlmanacDir(cwd);\n if (repoRoot !== null) return repoRoot;\n return renderOutcome(\n {\n type: \"needs-action\",\n message: \"no .almanac/ found in this directory or any parent\",\n fix: \"run: almanac init\",\n },\n { json },\n );\n}\n\nfunction missingRun(runId: string, json: boolean | undefined): CommandResult {\n return renderOutcome(\n { type: \"error\", message: `run not found: ${runId}` },\n { json },\n );\n}\n\nasync function writeLogChunk(\n path: string,\n offset: number,\n write: (chunk: string) => void,\n): Promise<number> {\n let text = \"\";\n try {\n text = await readFile(path, \"utf8\");\n } catch {\n return offset;\n }\n if (text.length <= offset) return offset;\n const chunk = text.slice(offset);\n write(chunk);\n return text.length;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction isPidAlive(pid: number): boolean {\n if (pid <= 0) return false;\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction formatMs(ms: number): string {\n if (ms < 1_000) return `${ms}ms`;\n const seconds = Math.round(ms / 1_000);\n if (seconds < 60) return `${seconds}s`;\n const minutes = Math.round(seconds / 60);\n if (minutes < 60) return `${minutes}m`;\n return `${Math.round(minutes / 60)}h`;\n}\n\nfunction terminalAttachSummary(view: RunView): string {\n if (view.displayStatus !== \"failed\" && view.displayStatus !== \"stale\") {\n return \"\";\n }\n const lines = [`job ${view.displayStatus}: ${view.id}`];\n if (view.failure !== undefined) {\n lines.push(`Reason: ${view.failure.message}`);\n if (view.failure.fix !== undefined) lines.push(`Fix: ${view.failure.fix}`);\n } else if (view.error !== undefined) {\n lines.push(`Error: ${view.error}`);\n }\n return `${lines.join(\"\\n\")}\\n`;\n}\n","import type { CommandResult } from \"./helpers.js\";\n\nexport type CommandOutcome =\n | {\n type: \"success\";\n message: string;\n data?: Record<string, unknown>;\n }\n | {\n type: \"noop\";\n message: string;\n data?: Record<string, unknown>;\n }\n | {\n type: \"needs-action\";\n message: string;\n fix: string;\n data?: Record<string, unknown>;\n }\n | {\n type: \"error\";\n message: string;\n data?: Record<string, unknown>;\n };\n\nexport function renderOutcome(\n outcome: CommandOutcome,\n opts: { json?: boolean; exitCode?: number; stdout?: string } = {},\n): CommandResult {\n const exitCode = opts.exitCode ?? defaultExitCode(outcome);\n if (opts.json === true) {\n return {\n stdout: `${JSON.stringify(outcome, null, 2)}\\n`,\n stderr: \"\",\n exitCode,\n };\n }\n if (outcome.type === \"needs-action\") {\n return {\n stdout: opts.stdout ?? \"\",\n stderr: `almanac: ${outcome.message}\\n${outcome.fix}\\n`,\n exitCode,\n };\n }\n if (outcome.type === \"error\") {\n return {\n stdout: opts.stdout ?? \"\",\n stderr: `almanac: ${outcome.message}\\n`,\n exitCode,\n };\n }\n return {\n stdout: opts.stdout ?? `${outcome.message}\\n`,\n stderr: \"\",\n exitCode,\n };\n}\n\nfunction defaultExitCode(outcome: CommandOutcome): number {\n switch (outcome.type) {\n case \"success\":\n case \"noop\":\n return 0;\n case \"needs-action\":\n case \"error\":\n return 1;\n }\n}\n","import { resolve } from \"node:path\";\n\nimport type { CommandResult } from \"../cli/helpers.js\";\nimport { renderOutcome } from \"../cli/outcome.js\";\nimport type { HarnessEvent } from \"../harness/events.js\";\nimport type { HarnessProviderId } from \"../harness/types.js\";\nimport { runAbsorbOperation } from \"../operations/absorb.js\";\nimport { runBuildOperation } from \"../operations/build.js\";\nimport { runGardenOperation } from \"../operations/garden.js\";\nimport { readConfig } from \"../update/config.js\";\nimport { resolveCaptureTranscripts } from \"./session-transcripts.js\";\nimport type {\n OperationProviderSelection,\n OperationRunResult,\n StartBackgroundProcess,\n StartForegroundProcess,\n} from \"../operations/types.js\";\n\nexport interface OperationCommandDeps {\n startForeground?: StartForegroundProcess;\n startBackground?: StartBackgroundProcess;\n onEvent?: (event: HarnessEvent) => void | Promise<void>;\n}\n\nexport interface InitCommandOptions extends OperationCommandDeps {\n cwd: string;\n using?: string;\n background?: boolean;\n json?: boolean;\n force?: boolean;\n yes?: boolean;\n}\n\nexport interface CaptureCommandOptions extends OperationCommandDeps {\n cwd: string;\n sessionFiles?: string[];\n app?: string;\n session?: string;\n since?: string;\n limit?: number;\n all?: boolean;\n allApps?: boolean;\n using?: string;\n foreground?: boolean;\n json?: boolean;\n yes?: boolean;\n claudeProjectsDir?: string;\n}\n\nexport interface IngestCommandOptions extends OperationCommandDeps {\n cwd: string;\n paths: string[];\n using?: string;\n foreground?: boolean;\n json?: boolean;\n yes?: boolean;\n}\n\nexport interface GardenCommandOptions extends OperationCommandDeps {\n cwd: string;\n using?: string;\n foreground?: boolean;\n json?: boolean;\n yes?: boolean;\n}\n\nexport async function runInitCommand(\n options: InitCommandOptions,\n): Promise<CommandResult> {\n const provider = await resolveProviderOrOutcome(options);\n if (\"error\" in provider) return provider.error;\n const background = options.background === true;\n if (options.json === true && !background) return jsonForegroundError(options.json);\n\n try {\n const result = await runBuildOperation({\n cwd: options.cwd,\n provider: provider.value,\n background,\n context: initContext(options),\n force: options.force,\n onEvent: options.onEvent,\n startForeground: options.startForeground,\n startBackground: options.startBackground,\n });\n return renderOperationResult(\"init\", result, options.json);\n } catch (err: unknown) {\n return renderOperationError(err, options.json);\n }\n}\n\nexport async function runCaptureCommand(\n options: CaptureCommandOptions,\n): Promise<CommandResult> {\n const provider = await resolveProviderOrOutcome(options);\n if (\"error\" in provider) return provider.error;\n if (options.json === true && options.foreground === true) {\n return jsonForegroundError(options.json);\n }\n\n try {\n const repoRoot = await resolveCaptureRepoRoot(options.cwd, options.json);\n if (typeof repoRoot !== \"string\") return repoRoot;\n const resolved = await resolveCaptureTranscripts({\n repoRoot,\n cwd: options.cwd,\n files: options.sessionFiles,\n app: options.app,\n session: options.session,\n since: options.since,\n limit: options.limit,\n all: options.all,\n allApps: options.allApps,\n claudeProjectsDir: options.claudeProjectsDir,\n });\n if (!resolved.ok) {\n return renderOutcome(\n {\n type: \"needs-action\",\n message: resolved.error,\n fix: resolved.fix,\n data: {\n app: options.app,\n session: options.session,\n since: options.since,\n limit: options.limit,\n all: options.all,\n allApps: options.allApps,\n },\n },\n { json: options.json },\n );\n }\n const paths = resolved.paths;\n const result = await runAbsorbOperation({\n cwd: options.cwd,\n provider: provider.value,\n background: options.foreground !== true,\n context: captureContext({ ...options, sessionFiles: paths }),\n targetKind: \"session\",\n targetPaths: paths,\n onEvent: options.onEvent,\n startForeground: options.startForeground,\n startBackground: options.startBackground,\n });\n return renderOperationResult(\"capture\", result, options.json);\n } catch (err: unknown) {\n return renderOperationError(err, options.json);\n }\n}\n\nexport async function runIngestCommand(\n options: IngestCommandOptions,\n): Promise<CommandResult> {\n const provider = await resolveProviderOrOutcome(options);\n if (\"error\" in provider) return provider.error;\n if (options.paths.length === 0) {\n return renderOutcome(\n { type: \"error\", message: \"ingest requires at least one file or folder\" },\n { json: options.json },\n );\n }\n if (options.json === true && options.foreground === true) {\n return jsonForegroundError(options.json);\n }\n\n try {\n const paths = options.paths.map((path) => resolve(options.cwd, path));\n const result = await runAbsorbOperation({\n cwd: options.cwd,\n provider: provider.value,\n background: options.foreground !== true,\n context: ingestContext(paths),\n targetKind: \"path\",\n targetPaths: paths,\n onEvent: options.onEvent,\n startForeground: options.startForeground,\n startBackground: options.startBackground,\n });\n return renderOperationResult(\"ingest\", result, options.json);\n } catch (err: unknown) {\n return renderOperationError(err, options.json);\n }\n}\n\nexport async function runGardenCommand(\n options: GardenCommandOptions,\n): Promise<CommandResult> {\n const provider = await resolveProviderOrOutcome(options);\n if (\"error\" in provider) return provider.error;\n if (options.json === true && options.foreground === true) {\n return jsonForegroundError(options.json);\n }\n\n try {\n const result = await runGardenOperation({\n cwd: options.cwd,\n provider: provider.value,\n background: options.foreground !== true,\n onEvent: options.onEvent,\n startForeground: options.startForeground,\n startBackground: options.startBackground,\n });\n return renderOperationResult(\"garden\", result, options.json);\n } catch (err: unknown) {\n return renderOperationError(err, options.json);\n }\n}\n\nexport function parseUsing(value: string | undefined): OperationProviderSelection {\n if (value === undefined || value.trim().length === 0) {\n return { id: \"claude\" };\n }\n const [rawProvider, ...modelParts] = value.split(\"/\");\n if (!isProviderId(rawProvider)) {\n throw new Error(\n `invalid --using \"${value}\" (expected claude, codex, or cursor)`,\n );\n }\n const model = modelParts.join(\"/\");\n return {\n id: rawProvider,\n model: model.length > 0 ? model : undefined,\n };\n}\n\nasync function resolveProviderOrOutcome(\n options: {\n cwd: string;\n using?: string;\n json?: boolean;\n },\n): Promise<{ value: OperationProviderSelection } | { error: CommandResult }> {\n try {\n if (options.using !== undefined) {\n return { value: parseUsing(options.using) };\n }\n const config = await readConfig({ cwd: options.cwd });\n const id = config.agent.default;\n const model = config.agent.models[id] ?? undefined;\n return { value: { id, model: model ?? undefined } };\n } catch (err: unknown) {\n return {\n error: renderOutcome(\n { type: \"error\", message: err instanceof Error ? err.message : String(err) },\n { json: options.json },\n ),\n };\n }\n}\n\nfunction isProviderId(value: string | undefined): value is HarnessProviderId {\n return value === \"claude\" || value === \"codex\" || value === \"cursor\";\n}\n\nfunction renderOperationResult(\n operation: string,\n result: OperationRunResult,\n json: boolean | undefined,\n): CommandResult {\n const record = result.background?.record ?? result.foreground?.record;\n const status = record?.status;\n const foregroundResult = result.foreground?.result;\n if (\n result.mode === \"foreground\" &&\n (foregroundResult?.success === false || status === \"failed\")\n ) {\n const failure = foregroundResult?.failure ?? record?.failure;\n return renderOutcome(\n {\n type: \"error\",\n message: renderOperationFailureMessage({\n operation,\n runId: result.runId,\n error: foregroundResult?.error,\n failure,\n }),\n data: {\n operation,\n runId: result.runId,\n mode: result.mode,\n status,\n pid: record?.pid,\n logPath: record?.logPath,\n error: foregroundResult?.error,\n failure,\n },\n },\n { json },\n );\n }\n return renderOutcome(\n {\n type: \"success\",\n message:\n result.mode === \"background\"\n ? `${operation} started: ${result.runId}`\n : `${operation} finished: ${result.runId}`,\n data: {\n operation,\n runId: result.runId,\n mode: result.mode,\n status,\n pid: record?.pid,\n logPath: record?.logPath,\n },\n },\n { json },\n );\n}\n\nfunction renderOperationFailureMessage(args: {\n operation: string;\n runId: string;\n error?: string;\n failure?: import(\"../harness/events.js\").HarnessFailure;\n}): string {\n const lines = [`${args.operation} failed: ${args.runId}`];\n if (args.failure !== undefined) {\n lines.push(`Reason: ${args.failure.message}`);\n if (args.failure.fix !== undefined) lines.push(`Fix: ${args.failure.fix}`);\n return lines.join(\"\\n\");\n }\n if (args.error !== undefined) lines[0] += `: ${args.error}`;\n return lines.join(\"\\n\");\n}\n\nfunction renderOperationError(\n err: unknown,\n json: boolean | undefined,\n): CommandResult {\n const message = err instanceof Error ? err.message : String(err);\n if (message.includes(\"no .almanac/\")) {\n return renderOutcome(\n {\n type: \"needs-action\",\n message,\n fix: \"run: almanac init\",\n },\n { json },\n );\n }\n return renderOutcome({ type: \"error\", message }, { json });\n}\n\nasync function resolveCaptureRepoRoot(\n cwd: string,\n json: boolean | undefined,\n): Promise<string | CommandResult> {\n const { findNearestAlmanacDir } = await import(\"../paths.js\");\n const repoRoot = findNearestAlmanacDir(cwd);\n if (repoRoot !== null) return repoRoot;\n return renderOutcome(\n {\n type: \"needs-action\",\n message: \"no .almanac/ found in this directory or any parent\",\n fix: \"run: almanac init\",\n },\n { json },\n );\n}\n\nfunction jsonForegroundError(json: boolean | undefined): CommandResult {\n return renderOutcome({\n type: \"error\",\n message: \"--json is only supported for background job start responses\",\n }, { json });\n}\n\nfunction initContext(options: InitCommandOptions): string {\n return [\n \"Command context:\",\n `- Command: init`,\n `- Force requested: ${options.force === true ? \"yes\" : \"no\"}`,\n `- Non-interactive confirmation: ${options.yes === true ? \"yes\" : \"no\"}`,\n ].join(\"\\n\");\n}\n\nfunction captureContext(options: CaptureCommandOptions): string {\n const lines = [\"Command context:\", \"- Command: capture\"];\n if (options.app !== undefined) lines.push(`- App: ${options.app}`);\n if (options.session !== undefined) lines.push(`- Session id: ${options.session}`);\n if (options.since !== undefined) lines.push(`- Since: ${options.since}`);\n if (options.limit !== undefined) lines.push(`- Limit: ${options.limit}`);\n if (options.all === true) lines.push(\"- Capture all matching sessions\");\n if (options.allApps === true) lines.push(\"- Capture all supported apps\");\n const paths = options.sessionFiles ?? [];\n if (paths.length > 0) {\n lines.push(\"- Session/transcript files:\");\n for (const path of paths) lines.push(` - ${path}`);\n }\n if (paths.length === 0 && options.session === undefined) {\n lines.push(\"- No explicit session file or session id was provided.\");\n }\n return lines.join(\"\\n\");\n}\n\nfunction ingestContext(paths: string[]): string {\n return [\n \"Command context:\",\n \"- Command: ingest\",\n \"- Paths:\",\n ...paths.map((path) => ` - ${path}`),\n ].join(\"\\n\");\n}\n","import { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n/**\n * Loads bundled prompt text from the `prompts/` directory that ships with\n * the npm package. V1 prompts are split into shared base modules and\n * operation-specific instructions.\n *\n * ## Why not embed the prompts as TS string literals?\n *\n * The non-negotiable from the spec (see CLAUDE.md → \"Non-negotiables\"):\n * \"Prompts are shipped from the npm package. They live in `prompts/` at\n * repo root, are bundled into `files` in `package.json`, and the agent\n * harness reads them from the package install path at runtime.\"\n *\n * Keeping them as separate files means they can be reviewed as prose,\n * diffed meaningfully, and (in the future) edited by users without\n * rebuilding the package.\n *\n * ## Path resolution\n *\n * Two runtime layouts need to work:\n *\n * 1. **Installed (`npm i -g codealmanac`).** The entry point lives at\n * `dist/codealmanac.js`; prompts at `prompts/*.md`. Walking up from\n * `import.meta.url` (`.../<pkg>/dist/codealmanac.js`) one level and\n * into `prompts/` hits the right directory.\n *\n * 2. **Source dev.** During `npm run dev`, tsup emits to `dist/` just\n * like in production, so case 1 applies. Tests import\n * `src/agent/prompts.ts` directly via tsx/vitest; `import.meta.url`\n * points at `src/agent/prompts.ts`. Walking up two levels from there\n * lands at the repo root, where `prompts/` also lives.\n *\n * We probe a small list of candidates in order and use the first that\n * contains the required prompt files. This keeps a single source of truth —\n * the `prompts/` directory on disk — without baking in whether\n * we're running from `dist/` or `src/`.\n */\n\nexport type PromptName =\n | \"base/purpose\"\n | \"base/notability\"\n | \"base/syntax\"\n | \"operations/build\"\n | \"operations/absorb\"\n | \"operations/garden\";\n\nconst PROMPT_NAMES: readonly PromptName[] = [\n \"base/purpose\",\n \"base/notability\",\n \"base/syntax\",\n \"operations/build\",\n \"operations/absorb\",\n \"operations/garden\",\n];\n\n/**\n * Override the prompts directory, for tests. Production code should never\n * call this — the auto-resolution handles both installed + source layouts.\n */\nlet overrideDir: string | null = null;\n\nexport function setPromptsDirForTesting(dir: string | null): void {\n overrideDir = dir;\n}\n\n/**\n * Resolve the prompts directory by probing candidate locations. Cached\n * after the first call so repeated `loadPrompt()` calls don't stat the\n * filesystem more than once per process.\n */\nlet resolvedDir: string | null = null;\n\nexport function resolvePromptsDir(): string {\n if (overrideDir !== null) return overrideDir;\n if (resolvedDir !== null) return resolvedDir;\n\n const here = path.dirname(fileURLToPath(import.meta.url));\n\n // Candidates, most-specific first. Each path is where `prompts/` MIGHT\n // live given some plausible bundle layout. The first one that exists\n // and contains our expected prompt files wins.\n const candidates = [\n // Bundled dist layout: `.../<pkg>/dist/codealmanac.js` → `../prompts`\n path.resolve(here, \"..\", \"prompts\"),\n // Source layout: `.../<pkg>/src/agent/prompts.ts` → `../../prompts`\n path.resolve(here, \"..\", \"..\", \"prompts\"),\n // Defensive fallback: if tsup someday emits a nested `dist/src/agent`,\n // walk up three levels.\n path.resolve(here, \"..\", \"..\", \"..\", \"prompts\"),\n ];\n\n for (const dir of candidates) {\n if (isPromptsDir(dir)) {\n resolvedDir = dir;\n return dir;\n }\n }\n\n // If none matched, give a helpful error with the candidates we tried.\n // This typically means the package was installed without the `prompts/`\n // dir included — shouldn't happen unless someone broke `files` in\n // package.json.\n throw new Error(\n \"could not locate bundled prompts/ directory. Tried:\\n\" +\n candidates.map((c) => ` - ${c}`).join(\"\\n\"),\n );\n}\n\nfunction isPromptsDir(dir: string): boolean {\n if (!existsSync(dir)) return false;\n // Require all base and operation prompts to be present. A half-populated\n // directory is worse than not finding one — we'd rather error early.\n return PROMPT_NAMES.every((name) =>\n existsSync(path.join(dir, `${name}.md`)),\n );\n}\n\nexport async function loadPrompt(name: PromptName | string): Promise<string> {\n const dir = resolvePromptsDir();\n return readFile(resolvePromptPath(dir, name), \"utf8\");\n}\n\nfunction resolvePromptPath(dir: string, name: string): string {\n if (\n name.length === 0 ||\n path.isAbsolute(name) ||\n name.includes(\"\\\\\") ||\n name.split(\"/\").some((part) => part === \"\" || part === \".\" || part === \"..\")\n ) {\n throw new Error(`invalid prompt name: ${name}`);\n }\n const file = path.resolve(dir, `${name}.md`);\n const relative = path.relative(dir, file);\n if (relative.startsWith(\"..\") || path.isAbsolute(relative)) {\n throw new Error(`invalid prompt name: ${name}`);\n }\n return file;\n}\n\nexport function joinPrompts(\n parts: Array<string | null | undefined>,\n): string {\n return parts\n .map((part) => part?.trim())\n .filter((part): part is string => part !== undefined && part.length > 0)\n .join(\"\\n\\n---\\n\\n\");\n}\n","import { joinPrompts, loadPrompt } from \"../agent/prompts.js\";\nimport type { HarnessEvent } from \"../harness/events.js\";\nimport type { AgentRunSpec, OperationKind } from \"../harness/types.js\";\nimport type { ToolRequest } from \"../harness/tools.js\";\nimport {\n startBackgroundProcess,\n startForegroundProcess,\n} from \"../process/index.js\";\nimport type {\n OperationProviderSelection,\n OperationRunResult,\n StartBackgroundProcess,\n StartForegroundProcess,\n} from \"./types.js\";\n\nconst DEFAULT_MAX_TURNS = 150;\n\nconst BASE_OPERATION_TOOLS: ToolRequest[] = [\n { id: \"read\" },\n { id: \"write\" },\n { id: \"edit\" },\n { id: \"search\" },\n { id: \"shell\" },\n];\n\nconst BASE_PROMPTS = [\n \"base/purpose\",\n \"base/notability\",\n \"base/syntax\",\n] as const;\n\nexport async function createOperationRunSpec(args: {\n operation: OperationKind;\n promptName: string;\n repoRoot: string;\n provider?: OperationProviderSelection;\n context?: string;\n targetKind?: string;\n targetPaths?: string[];\n}): Promise<AgentRunSpec> {\n const basePrompts = await Promise.all(\n BASE_PROMPTS.map((name) => loadPrompt(name)),\n );\n const operationPrompt = await loadPrompt(args.promptName);\n const prompt = joinPrompts([\n ...basePrompts,\n operationPrompt,\n operationRuntimeContext(args.repoRoot),\n args.context,\n ]);\n\n return {\n provider: args.provider ?? { id: \"claude\" },\n cwd: args.repoRoot,\n prompt,\n tools: BASE_OPERATION_TOOLS,\n limits: {\n maxTurns: DEFAULT_MAX_TURNS,\n },\n metadata: {\n operation: args.operation,\n targetKind: args.targetKind,\n targetPaths: args.targetPaths,\n },\n };\n}\n\nexport async function runOperationProcess(args: {\n repoRoot: string;\n spec: AgentRunSpec;\n background: boolean;\n runId?: string;\n onEvent?: (event: HarnessEvent) => void | Promise<void>;\n startForeground?: StartForegroundProcess;\n startBackground?: StartBackgroundProcess;\n}): Promise<OperationRunResult> {\n if (args.background) {\n const background = await (args.startBackground ?? startBackgroundProcess)({\n repoRoot: args.repoRoot,\n spec: args.spec,\n runId: args.runId,\n });\n return { mode: \"background\", runId: background.runId, background };\n }\n\n const foreground = await (args.startForeground ?? startForegroundProcess)({\n repoRoot: args.repoRoot,\n spec: args.spec,\n runId: args.runId,\n onEvent: args.onEvent,\n });\n return { mode: \"foreground\", runId: foreground.runId, foreground };\n}\n\nfunction operationRuntimeContext(repoRoot: string): string {\n return [\n \"Runtime context:\",\n `- Repository root: ${repoRoot}`,\n `- Almanac directory: ${repoRoot}/.almanac`,\n `- Wiki pages directory: ${repoRoot}/.almanac/pages`,\n ].join(\"\\n\");\n}\n","import type { AgentRunSpec } from \"../harness/types.js\";\nimport { findNearestAlmanacDir } from \"../paths.js\";\nimport type {\n OperationProviderSelection,\n OperationRunResult,\n StartBackgroundProcess,\n StartForegroundProcess,\n} from \"./types.js\";\nimport { createOperationRunSpec, runOperationProcess } from \"./run.js\";\n\nexport interface AbsorbOperationOptions {\n cwd: string;\n context: string;\n provider?: OperationProviderSelection;\n background?: boolean;\n targetKind?: string;\n targetPaths?: string[];\n runId?: string;\n onEvent?: (event: import(\"../harness/events.js\").HarnessEvent) => void | Promise<void>;\n startForeground?: StartForegroundProcess;\n startBackground?: StartBackgroundProcess;\n}\n\nexport async function createAbsorbRunSpec(args: {\n repoRoot: string;\n context: string;\n provider?: OperationProviderSelection;\n targetKind?: string;\n targetPaths?: string[];\n}): Promise<AgentRunSpec> {\n return createOperationRunSpec({\n operation: \"absorb\",\n promptName: \"operations/absorb\",\n provider: args.provider ?? { id: \"claude\" },\n repoRoot: args.repoRoot,\n context: args.context,\n targetKind: args.targetKind,\n targetPaths: args.targetPaths,\n });\n}\n\nexport async function runAbsorbOperation(\n options: AbsorbOperationOptions,\n): Promise<OperationRunResult> {\n const repoRoot = findNearestAlmanacDir(options.cwd);\n if (repoRoot === null) {\n throw new Error(\"no .almanac/ found in this directory or any parent\");\n }\n const spec = await createAbsorbRunSpec({\n repoRoot,\n provider: options.provider,\n context: options.context,\n targetKind: options.targetKind,\n targetPaths: options.targetPaths,\n });\n\n return runOperationProcess({\n repoRoot,\n spec,\n background: options.background !== false,\n runId: options.runId,\n onEvent: options.onEvent,\n startForeground: options.startForeground,\n startBackground: options.startBackground,\n });\n}\n","import { existsSync } from \"node:fs\";\nimport { readdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport type { AgentRunSpec } from \"../harness/types.js\";\nimport { initWiki } from \"../commands/init.js\";\nimport type {\n OperationProviderSelection,\n OperationRunResult,\n StartBackgroundProcess,\n StartForegroundProcess,\n} from \"./types.js\";\nimport { createOperationRunSpec, runOperationProcess } from \"./run.js\";\n\nexport interface BuildOperationOptions {\n cwd: string;\n provider?: OperationProviderSelection;\n background?: boolean;\n context?: string;\n force?: boolean;\n runId?: string;\n onEvent?: (event: import(\"../harness/events.js\").HarnessEvent) => void | Promise<void>;\n startForeground?: StartForegroundProcess;\n startBackground?: StartBackgroundProcess;\n}\n\nexport async function createBuildRunSpec(args: {\n repoRoot: string;\n provider?: OperationProviderSelection;\n context?: string;\n}): Promise<AgentRunSpec> {\n return createOperationRunSpec({\n operation: \"build\",\n promptName: \"operations/build\",\n provider: args.provider ?? { id: \"claude\" },\n repoRoot: args.repoRoot,\n context: args.context,\n targetKind: \"repo\",\n targetPaths: [args.repoRoot],\n });\n}\n\nexport async function runBuildOperation(\n options: BuildOperationOptions,\n): Promise<OperationRunResult> {\n const init = await initWiki({ cwd: options.cwd });\n const repoRoot = init.entry.path;\n const pageCount = await countWikiPages(repoRoot);\n if (pageCount > 0 && options.force !== true) {\n throw new Error(\n `.almanac/ already initialized with ${pageCount} page${pageCount === 1 ? \"\" : \"s\"}; pass --force to rebuild`,\n );\n }\n const spec = await createBuildRunSpec({\n repoRoot,\n provider: options.provider,\n context: options.context,\n });\n\n return runOperationProcess({\n repoRoot,\n spec,\n background: options.background === true,\n runId: options.runId,\n onEvent: options.onEvent,\n startForeground: options.startForeground,\n startBackground: options.startBackground,\n });\n}\n\nasync function countWikiPages(repoRoot: string): Promise<number> {\n const pagesDir = join(repoRoot, \".almanac\", \"pages\");\n if (!existsSync(pagesDir)) return 0;\n const entries = await readdir(pagesDir);\n return entries.filter((entry) => entry.endsWith(\".md\")).length;\n}\n","import { existsSync } from \"node:fs\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { basename, join } from \"node:path\";\n\nimport { findNearestAlmanacDir, getRepoAlmanacDir } from \"../paths.js\";\nimport { toKebabCase } from \"../slug.js\";\nimport {\n addEntry,\n ensureGlobalDir,\n type RegistryEntry,\n} from \"../registry/index.js\";\n\nexport interface InitOptions {\n cwd: string;\n name?: string;\n description?: string;\n}\n\nexport interface InitResult {\n entry: RegistryEntry;\n almanacDir: string;\n created: boolean; // false if .almanac/ already existed (idempotent re-init)\n}\n\n/**\n * Scaffold `.almanac/` in the repo and register it globally.\n *\n * Idempotent: running `init` on a repo that already has `.almanac/` is\n * fine — we re-register (refreshing the name/description) and skip\n * anything that already exists. We never overwrite a user-authored\n * `README.md` or touch existing pages.\n *\n * If `cwd` lives inside a subdirectory of an existing wiki, we walk up to\n * the wiki root and operate there. `almanac init` from `src/nested/`\n * should update the enclosing wiki, not create a nested one at\n * `src/nested/.almanac/` (which would fragment the registry and leave a\n * confusing orphan `.almanac/` on disk).\n */\nexport async function initWiki(options: InitOptions): Promise<InitResult> {\n // If cwd is already inside a wiki, prefer that root. Otherwise treat\n // cwd as the new wiki root.\n const repoRoot = findNearestAlmanacDir(options.cwd) ?? options.cwd;\n\n const almanacDir = getRepoAlmanacDir(repoRoot);\n const pagesDir = join(almanacDir, \"pages\");\n const readmePath = join(almanacDir, \"README.md\");\n\n const alreadyExisted = existsSync(almanacDir);\n\n await mkdir(pagesDir, { recursive: true });\n\n if (!existsSync(readmePath)) {\n await writeFile(readmePath, starterReadme(), \"utf8\");\n }\n\n await ensureGitignoreHasRuntimeArtifacts(repoRoot);\n\n const name = toKebabCase(options.name ?? basename(repoRoot));\n if (name.length === 0) {\n throw new Error(\n \"could not derive a wiki name from the current directory; pass --name\",\n );\n }\n\n const description = (options.description ?? \"\").trim();\n\n await ensureGlobalDir();\n const entry: RegistryEntry = {\n name,\n description,\n path: repoRoot,\n registered_at: new Date().toISOString(),\n };\n await addEntry(entry);\n\n return { entry, almanacDir, created: !alreadyExisted };\n}\n\n/**\n * Ensure `.gitignore` in the repo root contains the CodeAlmanac-derived\n * runtime files that should never be committed.\n *\n * The SQLite index is derived from markdown pages. Run records are local\n * process state and JSONL event logs; they can be large and are not wiki\n * content.\n *\n * We add the block regardless of whether the file exists (creating\n * `.gitignore` if needed), and we add any target lines that aren't\n * already present. Existing targets are left alone. If none of the\n * target lines need adding, the file is not touched at all.\n *\n * Formatting: when we do append, we guarantee exactly one blank line\n * between the prior content and our appended block. If the `# codealmanac`\n * header is already present but new targets need adding, we just append\n * the missing lines (no duplicate header).\n */\nasync function ensureGitignoreHasRuntimeArtifacts(cwd: string): Promise<void> {\n const path = join(cwd, \".gitignore\");\n const targets = [\n \".almanac/index.db\",\n \".almanac/index.db-wal\",\n \".almanac/index.db-shm\",\n \".almanac/runs/\",\n ];\n\n let existing = \"\";\n if (existsSync(path)) {\n existing = await readFile(path, \"utf8\");\n }\n\n // Normalize to line comparison to avoid false negatives on trailing\n // whitespace or CRLF line endings.\n const lines = existing.split(/\\r?\\n/).map((l) => l.trim());\n const missing = targets.filter((t) => !lines.includes(t));\n if (missing.length === 0) return;\n\n const hasHeader = lines.includes(\"# codealmanac\");\n const block = hasHeader\n ? missing.join(\"\\n\") + \"\\n\"\n : `# codealmanac\\n${missing.join(\"\\n\")}\\n`;\n\n // Three cases for the separator before the appended block:\n // - empty file: no separator needed\n // - ends with newline: one more newline produces a single blank line\n // - no trailing newline: two newlines (one to terminate the last line,\n // one for the blank separator)\n const sep =\n existing.length === 0 ? \"\" : existing.endsWith(\"\\n\") ? \"\\n\" : \"\\n\\n\";\n await writeFile(path, `${existing}${sep}${block}`, \"utf8\");\n}\n\n/**\n * The starter `.almanac/README.md` content. Based on the \"Wiki README\" and\n * \"Notability bar\" sections of the design spec. Kept opinionated but short\n * (~70 lines) — the user is expected to edit it to fit the repo.\n */\nfunction starterReadme(): string {\n return `# Wiki\n\nThis is the codealmanac wiki for this repository. It captures the knowledge\nthe code itself can't say — decisions, flows, invariants, gotchas, incidents.\n\nThe primary reader is an AI coding agent. The secondary reader is a human\nskimming to understand the shape of the codebase. Write accordingly: dense,\nfactual, linked.\n\n## Notability bar\n\nWrite a page when there is **non-obvious knowledge that will help a future\nagent**. Specifically:\n\n- A decision that took discussion, research, or trial-and-error\n- A gotcha discovered through failure\n- A cross-cutting flow that spans multiple files and isn't obvious from any\n one of them\n- A constraint or invariant not visible from the code\n- An entity (technology, service, system) referenced by multiple pages\n\nDo not write pages that restate what the code does. Do not write pages of\ninference — only of observation. Silence is an acceptable outcome.\n\n## Topic taxonomy\n\nTopics form a DAG; pages can belong to multiple topics. Start with these and\ngrow as the wiki does:\n\n- \\`stack\\` — technologies and services we use (frameworks, databases, APIs)\n- \\`systems\\` — custom systems we built (auth, billing, search)\n- \\`flows\\` — multi-file processes end-to-end (checkout-flow, publish-flow)\n- \\`decisions\\` — \"why X over Y\"\n- \\`incidents\\` — recorded failures and their fixes\n- \\`concepts\\` — shared vocabulary specific to this codebase\n\nDomain topics (\\`auth\\`, \\`payments\\`, \\`frontend\\`, \\`backend\\`) live alongside\nthese. A page about JWT rotation belongs to both \\`auth\\` and \\`decisions\\`.\n\n## Page shapes\n\nFour shapes cover most of what gets written. They are suggestions, not a\nschema — a page that fits none of them is fine.\n\n- **Entity** — a stable named thing (Supabase, Stripe, the search service)\n- **Decision** — why we chose X over Y\n- **Flow** — how a multi-file process works end-to-end\n- **Gotcha** — a specific surprise, failure, or constraint\n\n## Writing conventions\n\n- Every sentence contains a specific fact. If it doesn't, cut it.\n- Neutral tone. \"is\", not \"serves as\". No \"plays a pivotal role\", no\n interpretive \"-ing\" clauses, no vague attribution (\"experts argue\").\n- No hedging or knowledge-gap disclaimers. If you don't know, don't write\n the sentence.\n- Prose first. Bullets for genuine lists. Tables only for structured\n comparison.\n- No formulaic conclusions. End with the last substantive fact.\n\n## Linking\n\nOne \\`[[...]]\\` syntax for everything, disambiguated by content:\n\n- \\`[[checkout-flow]]\\` — page slug\n- \\`[[src/checkout/handler.ts]]\\` — file reference\n- \\`[[src/checkout/]]\\` — folder reference (trailing slash)\n- \\`[[other-wiki:slug]]\\` — cross-wiki reference\n\nEvery page should link to at least one entity when possible. A page with no\nentity link is suspect.\n\n## Pages live in \\`.almanac/pages/\\`\n\nOne markdown file per page, kebab-case slug. Frontmatter carries \\`topics:\\`\nand optional \\`files:\\`. The rest is prose.\n`;\n}\n","import type { AgentRunSpec } from \"../harness/types.js\";\nimport { findNearestAlmanacDir } from \"../paths.js\";\nimport type {\n OperationProviderSelection,\n OperationRunResult,\n StartBackgroundProcess,\n StartForegroundProcess,\n} from \"./types.js\";\nimport { createOperationRunSpec, runOperationProcess } from \"./run.js\";\n\nexport interface GardenOperationOptions {\n cwd: string;\n provider?: OperationProviderSelection;\n background?: boolean;\n context?: string;\n runId?: string;\n onEvent?: (event: import(\"../harness/events.js\").HarnessEvent) => void | Promise<void>;\n startForeground?: StartForegroundProcess;\n startBackground?: StartBackgroundProcess;\n}\n\nexport async function createGardenRunSpec(args: {\n repoRoot: string;\n provider?: OperationProviderSelection;\n context?: string;\n}): Promise<AgentRunSpec> {\n return createOperationRunSpec({\n operation: \"garden\",\n promptName: \"operations/garden\",\n provider: args.provider ?? { id: \"claude\" },\n repoRoot: args.repoRoot,\n context: args.context,\n targetKind: \"wiki\",\n targetPaths: [`${args.repoRoot}/.almanac`],\n });\n}\n\nexport async function runGardenOperation(\n options: GardenOperationOptions,\n): Promise<OperationRunResult> {\n const repoRoot = findNearestAlmanacDir(options.cwd);\n if (repoRoot === null) {\n throw new Error(\"no .almanac/ found in this directory or any parent\");\n }\n const spec = await createGardenRunSpec({\n repoRoot,\n provider: options.provider,\n context: options.context,\n });\n\n return runOperationProcess({\n repoRoot,\n spec,\n background: options.background !== false,\n runId: options.runId,\n onEvent: options.onEvent,\n startForeground: options.startForeground,\n startBackground: options.startBackground,\n });\n}\n","import { existsSync } from \"node:fs\";\nimport { readFile, readdir, stat } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { basename, join, resolve } from \"node:path\";\n\nimport { parseDuration } from \"../indexer/duration.js\";\n\nexport interface ResolveCaptureTranscriptsOptions {\n repoRoot: string;\n cwd: string;\n files?: string[];\n app?: string;\n session?: string;\n since?: string;\n limit?: number;\n all?: boolean;\n allApps?: boolean;\n now?: () => Date;\n claudeProjectsDir?: string;\n}\n\nexport type ResolveCaptureTranscriptsResult =\n | { ok: true; paths: string[]; app: \"claude\" | \"file\" }\n | { ok: false; error: string; fix: string };\n\ninterface TranscriptEntry {\n path: string;\n mtime: number;\n}\n\nexport async function resolveCaptureTranscripts(\n options: ResolveCaptureTranscriptsOptions,\n): Promise<ResolveCaptureTranscriptsResult> {\n const explicit = options.files ?? [];\n if (explicit.length > 0) {\n const paths = explicit.map((path) => resolve(options.cwd, path));\n const missing = paths.find((path) => !existsSync(path));\n if (missing !== undefined) {\n return {\n ok: false,\n error: `transcript not found: ${missing}`,\n fix: \"pass an existing transcript file\",\n };\n }\n return { ok: true, paths, app: \"file\" };\n }\n\n const app = options.app ?? \"claude\";\n if (options.allApps === true) {\n return {\n ok: false,\n error: \"capture --all-apps discovery is not implemented yet\",\n fix: \"run capture per app, pass transcript files explicitly, or use almanac ingest <file-or-folder>\",\n };\n }\n if (app !== \"claude\") {\n return {\n ok: false,\n error: `capture discovery for ${app} sessions is not implemented yet`,\n fix: \"pass one or more transcript files, or use almanac ingest <file-or-folder>\",\n };\n }\n\n const projectsDir =\n options.claudeProjectsDir ?? join(homedir(), \".claude\", \"projects\");\n if (!existsSync(projectsDir)) {\n return {\n ok: false,\n error:\n `could not auto-resolve Claude transcript; ${projectsDir} does not exist`,\n fix: \"pass --session <id> with a Claude transcript available, or pass a transcript file\",\n };\n }\n\n const transcripts = await collectTranscripts(projectsDir);\n if (options.session !== undefined && options.session.length > 0) {\n if (hasBulkScope(options)) {\n return {\n ok: false,\n error: \"capture --session cannot be combined with --since, --limit, --all, or --all-apps\",\n fix: \"use --session for one transcript, or remove --session to capture a filtered set\",\n };\n }\n const expected = `${options.session}.jsonl`;\n const match = transcripts.find((entry) => basename(entry.path) === expected);\n if (match === undefined) {\n return {\n ok: false,\n error: `no Claude transcript found for session ${options.session}`,\n fix: \"pass an existing transcript file\",\n };\n }\n return { ok: true, paths: [match.path], app: \"claude\" };\n }\n\n let matches = await filterTranscriptsByCwd(transcripts, options.repoRoot);\n const cutoff = parseSinceCutoff(options.since, options.now?.() ?? new Date());\n if (!cutoff.ok) return cutoff;\n const cutoffMtime = cutoff.mtime;\n if (cutoffMtime !== undefined) {\n matches = matches.filter((entry) => entry.mtime >= cutoffMtime);\n }\n if (matches.length === 0) {\n return {\n ok: false,\n error:\n `could not auto-resolve Claude transcript for cwd ${options.repoRoot}`,\n fix: \"pass --session <id> or a transcript file\",\n };\n }\n matches.sort((a, b) => b.mtime - a.mtime);\n const limit = normalizeLimit(options.limit);\n if (!limit.ok) return limit;\n const count = options.all === true ? limit.value ?? matches.length : limit.value ?? 1;\n return {\n ok: true,\n paths: matches.slice(0, count).map((entry) => entry.path),\n app: \"claude\",\n };\n}\n\nfunction hasBulkScope(options: ResolveCaptureTranscriptsOptions): boolean {\n return (\n options.since !== undefined ||\n options.limit !== undefined ||\n options.all === true ||\n options.allApps === true\n );\n}\n\nfunction normalizeLimit(\n limit: number | undefined,\n): { ok: true; value?: number } | { ok: false; error: string; fix: string } {\n if (limit === undefined) return { ok: true };\n if (Number.isInteger(limit) && limit > 0) {\n return { ok: true, value: limit };\n }\n return {\n ok: false,\n error: \"capture --limit must be a positive integer\",\n fix: \"pass --limit 1 or higher\",\n };\n}\n\nfunction parseSinceCutoff(\n since: string | undefined,\n now: Date,\n): { ok: true; mtime?: number } | { ok: false; error: string; fix: string } {\n if (since === undefined || since.trim().length === 0) return { ok: true };\n const trimmed = since.trim();\n const parsedDate = Date.parse(trimmed);\n if (!Number.isNaN(parsedDate)) return { ok: true, mtime: parsedDate };\n try {\n return {\n ok: true,\n mtime: now.getTime() - parseDuration(trimmed) * 1000,\n };\n } catch {\n return {\n ok: false,\n error: `invalid --since \"${since}\"`,\n fix: \"pass a date or a duration like 2w, 30d, 12h, or 45m\",\n };\n }\n}\n\nasync function collectTranscripts(\n projectsDir: string,\n): Promise<TranscriptEntry[]> {\n const out: TranscriptEntry[] = [];\n let topLevel: string[];\n try {\n topLevel = await readdir(projectsDir);\n } catch {\n return out;\n }\n for (const name of topLevel) {\n const projectDir = join(projectsDir, name);\n let entries: string[];\n try {\n entries = await readdir(projectDir);\n } catch {\n continue;\n }\n for (const entry of entries) {\n if (!entry.endsWith(\".jsonl\")) continue;\n const full = join(projectDir, entry);\n try {\n const st = await stat(full);\n if (st.isFile()) out.push({ path: full, mtime: st.mtimeMs });\n } catch {\n continue;\n }\n }\n }\n return out;\n}\n\nasync function filterTranscriptsByCwd(\n transcripts: TranscriptEntry[],\n repoRoot: string,\n): Promise<TranscriptEntry[]> {\n const dirHash = `-${repoRoot.replace(/^\\/+/, \"\").replace(/\\//g, \"-\")}`;\n const byDirName = transcripts.filter((entry) => {\n const parent = basename(join(entry.path, \"..\"));\n return parent === dirHash || parent.endsWith(dirHash);\n });\n if (byDirName.length > 0) return byDirName;\n\n const needle = `\"cwd\":\"${repoRoot}\"`;\n const hits: TranscriptEntry[] = [];\n for (const transcript of transcripts) {\n try {\n const head = await readHead(transcript.path, 4096);\n if (head.includes(needle)) hits.push(transcript);\n } catch {\n continue;\n }\n }\n return hits;\n}\n\nasync function readHead(path: string, bytes: number): Promise<string> {\n const content = await readFile(path, \"utf8\");\n return content.length > bytes ? content.slice(0, bytes) : content;\n}\n","import { runIndexer, type IndexResult } from \"../indexer/index.js\";\nimport { resolveWikiRoot } from \"../indexer/resolve-wiki.js\";\n\nexport interface ReindexOptions {\n cwd: string;\n wiki?: string;\n}\n\nexport interface ReindexCommandOutput {\n result: IndexResult;\n stdout: string;\n exitCode: number;\n}\n\n/**\n * `almanac reindex` — force a full rebuild.\n *\n * Unlike the implicit reindex every query command triggers, this one\n * prints a summary line so the user gets feedback for an explicitly\n * requested action. The summary is terse on purpose (one line, three\n * numbers) — verbose progress reporting would fight the design rule that\n * the CLI stays quiet by default.\n */\nexport async function runReindex(\n options: ReindexOptions,\n): Promise<ReindexCommandOutput> {\n const repoRoot = await resolveWikiRoot({\n cwd: options.cwd,\n wiki: options.wiki,\n });\n const result = await runIndexer({ repoRoot });\n // Summary wording: \"reindexed: N pages (K updated, R removed)\". When\n // some files were on disk but never made it into the index\n // (slug collisions, ENOENT races, un-sluggable filenames), tack on a\n // `; S skipped` suffix so the user notices. The per-file reason was\n // already written to stderr at indexing time.\n const skipSuffix =\n result.filesSkipped > 0 ? `; ${result.filesSkipped} skipped` : \"\";\n const stdout = `reindexed: ${result.pagesIndexed} page${result.pagesIndexed === 1 ? \"\" : \"s\"} (${result.changed} updated, ${result.removed} removed${skipSuffix})\\n`;\n return { result, stdout, exitCode: 0 };\n}\n","import { Command } from \"commander\";\n\nimport {\n runHookInstall,\n runHookStatus,\n runHookUninstall,\n} from \"../commands/hook.js\";\nimport {\n runJobsCancel,\n runJobsList,\n runJobsLogs,\n runJobsShow,\n streamJobsAttach,\n} from \"../commands/jobs.js\";\nimport {\n runCaptureCommand,\n runGardenCommand,\n runIngestCommand,\n runInitCommand,\n} from \"../commands/operations.js\";\nimport type { HarnessEvent } from \"../harness/events.js\";\nimport { runReindex } from \"../commands/reindex.js\";\nimport { autoRegisterIfNeeded } from \"../registry/autoregister.js\";\nimport {\n deprecationWarning,\n emit,\n parsePositiveInt,\n withWarning,\n} from \"./helpers.js\";\n\nexport function registerWikiLifecycleCommands(program: Command): void {\n program\n .command(\"init\")\n .description(\"initialize and build this repo's CodeAlmanac wiki\")\n .option(\"--using <provider[/model]>\", \"provider and optional model\")\n .option(\"--background\", \"start as a background job\")\n .option(\"--json\", \"emit structured JSON for background job start\")\n .option(\"--force\", \"allow rebuilding an existing wiki\")\n .option(\"-y, --yes\", \"confirm non-interactively\")\n .action(\n async (opts: {\n using?: string;\n background?: boolean;\n json?: boolean;\n force?: boolean;\n yes?: boolean;\n }) => {\n const result = await runInitCommand({\n cwd: process.cwd(),\n using: opts.using,\n background: opts.background,\n json: opts.json,\n force: opts.force,\n yes: opts.yes,\n onEvent: opts.background === true ? undefined : writeForegroundEvent,\n });\n emit(result);\n },\n );\n\n const capture = program\n .command(\"capture [sessionFiles...]\")\n .alias(\"c\")\n .description(\"absorb coding-session knowledge into the wiki\")\n .option(\"--app <app>\", \"source app: claude, codex, cursor, or generic\")\n .option(\"--session <id>\", \"target a specific session by ID\")\n .option(\"--since <duration-or-date>\", \"capture sessions since a time\")\n .option(\"--limit <n>\", \"maximum sessions to capture\", parsePositiveInt)\n .option(\"--all\", \"capture all matching sessions\")\n .option(\"--all-apps\", \"capture from all supported apps\")\n .option(\"--using <provider[/model]>\", \"provider and optional model\")\n .option(\"--foreground\", \"run now instead of starting a background job\")\n .option(\"--json\", \"emit structured JSON for background job start\")\n .option(\"-y, --yes\", \"confirm non-interactively\")\n .action(\n async (\n sessionFiles: string[],\n opts: {\n app?: string;\n session?: string;\n since?: string;\n limit?: number;\n all?: boolean;\n allApps?: boolean;\n using?: string;\n foreground?: boolean;\n json?: boolean;\n yes?: boolean;\n },\n ) => {\n await autoRegisterIfNeeded(process.cwd());\n const result = await runCaptureCommand({\n cwd: process.cwd(),\n sessionFiles,\n app: opts.app,\n session: opts.session,\n since: opts.since,\n limit: opts.limit,\n all: opts.all,\n allApps: opts.allApps,\n using: opts.using,\n foreground: opts.foreground,\n json: opts.json,\n yes: opts.yes,\n onEvent: opts.foreground === true ? writeForegroundEvent : undefined,\n });\n emit(result);\n },\n );\n\n program\n .command(\"ingest <paths...>\")\n .description(\"absorb knowledge from one or more files or folders\")\n .option(\"--using <provider[/model]>\", \"provider and optional model\")\n .option(\"--foreground\", \"run now instead of starting a background job\")\n .option(\"--json\", \"emit structured JSON for background job start\")\n .option(\"-y, --yes\", \"confirm non-interactively\")\n .action(\n async (\n paths: string[],\n opts: {\n using?: string;\n foreground?: boolean;\n json?: boolean;\n yes?: boolean;\n },\n ) => {\n await autoRegisterIfNeeded(process.cwd());\n const result = await runIngestCommand({\n cwd: process.cwd(),\n paths,\n using: opts.using,\n foreground: opts.foreground,\n json: opts.json,\n yes: opts.yes,\n onEvent: opts.foreground === true ? writeForegroundEvent : undefined,\n });\n emit(result);\n },\n );\n\n program\n .command(\"garden\")\n .description(\"clean up, reconcile, and improve the wiki\")\n .option(\"--using <provider[/model]>\", \"provider and optional model\")\n .option(\"--foreground\", \"run now instead of starting a background job\")\n .option(\"--json\", \"emit structured JSON for background job start\")\n .option(\"-y, --yes\", \"confirm non-interactively\")\n .action(\n async (opts: {\n using?: string;\n foreground?: boolean;\n json?: boolean;\n yes?: boolean;\n }) => {\n await autoRegisterIfNeeded(process.cwd());\n const result = await runGardenCommand({\n cwd: process.cwd(),\n using: opts.using,\n foreground: opts.foreground,\n json: opts.json,\n yes: opts.yes,\n onEvent: opts.foreground === true ? writeForegroundEvent : undefined,\n });\n emit(result);\n },\n );\n\n const jobs = program\n .command(\"jobs\")\n .description(\"show and manage CodeAlmanac background jobs\");\n\n jobs\n .command(\"list\", { isDefault: true })\n .description(\"list runs for this wiki\")\n .option(\"--json\", \"emit structured JSON\")\n .action(async (opts: { json?: boolean }) => {\n const result = await runJobsList({\n cwd: process.cwd(),\n json: opts.json,\n });\n emit(result);\n });\n\n jobs\n .command(\"show <run-id>\")\n .description(\"show one run record\")\n .option(\"--json\", \"emit structured JSON\")\n .action(async (runId: string, opts: { json?: boolean }) => {\n const result = await runJobsShow({\n cwd: process.cwd(),\n runId,\n json: opts.json,\n });\n emit(result);\n });\n\n jobs\n .command(\"logs <run-id>\")\n .description(\"print a run's JSONL event log\")\n .option(\"--json\", \"emit structured errors as JSON\")\n .action(async (runId: string, opts: { json?: boolean }) => {\n const result = await runJobsLogs({\n cwd: process.cwd(),\n runId,\n json: opts.json,\n });\n emit(result);\n });\n\n jobs\n .command(\"attach <run-id>\")\n .description(\"stream a run log until the job exits\")\n .option(\"--json\", \"emit structured errors as JSON\")\n .action(async (runId: string, opts: { json?: boolean }) => {\n const result = await streamJobsAttach({\n cwd: process.cwd(),\n runId,\n json: opts.json,\n });\n emit(result);\n });\n\n jobs\n .command(\"cancel <run-id>\")\n .description(\"cancel a running or queued job\")\n .option(\"--json\", \"emit structured JSON\")\n .action(async (runId: string, opts: { json?: boolean }) => {\n const result = await runJobsCancel({\n cwd: process.cwd(),\n runId,\n json: opts.json,\n });\n emit(result);\n });\n\n capture\n .command(\"status\")\n .description(\"deprecated alias for jobs\")\n .option(\"--json\", \"emit structured JSON\")\n .action(async (opts: { json?: boolean }) => {\n const result = await runJobsList({\n cwd: process.cwd(),\n json: opts.json,\n });\n emit(withWarning(\n result,\n deprecationWarning(\"almanac capture status\", \"almanac jobs\"),\n ));\n });\n\n program\n .command(\"ps\")\n .description(\"deprecated alias for jobs\")\n .option(\"--json\", \"emit structured JSON\")\n .action(async (opts: { json?: boolean }) => {\n const result = await runJobsList({\n cwd: process.cwd(),\n json: opts.json,\n });\n emit(withWarning(\n result,\n deprecationWarning(\"almanac ps\", \"almanac jobs\"),\n ));\n });\n\n const hook = program\n .command(\"hook\")\n .description(\"manage the SessionEnd auto-capture hook\");\n\n hook\n .command(\"install\")\n .description(\"add a SessionEnd entry that runs 'almanac capture' on session end\")\n .option(\"--source <source>\", \"claude, codex, cursor, or all\")\n .action(async (opts: { source?: string }) => {\n const result = await runHookInstall({\n source: normalizeHookSource(opts.source),\n });\n emit(result);\n });\n\n hook\n .command(\"uninstall\")\n .description(\"remove codealmanac's SessionEnd entry; leaves foreign entries alone\")\n .action(async () => {\n const result = await runHookUninstall();\n emit(result);\n });\n\n hook\n .command(\"status\")\n .description(\"report whether the SessionEnd hook is installed\")\n .action(async () => {\n const result = await runHookStatus();\n emit(result);\n });\n\n program\n .command(\"reindex\")\n .description(\"force a full rebuild of .almanac/index.db\")\n .option(\"--wiki <name>\", \"target a specific registered wiki\")\n .action(async (opts: { wiki?: string }) => {\n await autoRegisterIfNeeded(process.cwd());\n const result = await runReindex({\n cwd: process.cwd(),\n wiki: opts.wiki,\n });\n process.stdout.write(result.stdout);\n if (result.exitCode !== 0) process.exitCode = result.exitCode;\n });\n}\n\nfunction writeForegroundEvent(event: HarnessEvent): void {\n const line = formatForegroundEvent(event);\n if (line !== null) process.stdout.write(`${line}\\n`);\n}\n\nexport function formatForegroundEvent(event: HarnessEvent): string | null {\n switch (event.type) {\n case \"text\":\n return event.content.trim().length > 0 ? event.content.trim() : null;\n case \"tool_use\":\n return `[tool] ${event.tool}`;\n case \"tool_summary\":\n return `[tool] ${event.summary}`;\n case \"error\":\n return null;\n case \"done\":\n return event.error !== undefined ? null : \"[done]\";\n default:\n return null;\n }\n}\n\nfunction normalizeHookSource(\n source: string | undefined,\n): \"claude\" | \"codex\" | \"cursor\" | \"all\" | undefined {\n if (\n source === \"claude\" ||\n source === \"codex\" ||\n source === \"cursor\" ||\n source === \"all\"\n ) {\n return source;\n }\n return undefined;\n}\n","import { Command } from \"commander\";\n\nimport { registerEditCommands } from \"./register-edit-commands.js\";\nimport { registerQueryCommands } from \"./register-query-commands.js\";\nimport { registerSetupCommands } from \"./register-setup-commands.js\";\nimport { registerWikiLifecycleCommands } from \"./register-wiki-lifecycle-commands.js\";\n\nexport function registerCommands(program: Command): void {\n registerQueryCommands(program);\n registerEditCommands(program);\n registerWikiLifecycleCommands(program);\n registerSetupCommands(program);\n}\n"],"mappings":"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","names":["values","parsed","stderr","repoRoot","readFile","join","join","readFile","repoRoot","repoRoot","repoRoot","existsSync","existsSync","join","join","readFile","join","join","readFile","readFile","readFile","path","readFile","resolve","resolve","existsSync","readFile","existsSync","readFile","existsSync","join","existsSync","readFile","writeFile","basename","join","join","existsSync","writeFile","basename","path","readFile","join","existsSync","existsSync","readFile","readdir","basename","join","path","existsSync","join","basename","readdir","readFile","path","resolve","findNearestAlmanacDir"]}
|