@orquentra/codebuddy 2.15.0 → 2.15.3

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.
Files changed (82) hide show
  1. package/ARCHITECTURE.md +12 -7
  2. package/README.md +2 -2
  3. package/dist/{chunk-YMXFSHXT.js → chunk-3L5IR6OW.js} +2 -2
  4. package/dist/{chunk-YMXFSHXT.js.map → chunk-3L5IR6OW.js.map} +1 -1
  5. package/dist/{chunk-JJQDVGF7.js → chunk-3TZNQJTH.js} +3 -3
  6. package/dist/{chunk-4BSO3HST.js → chunk-4LMBZWIF.js} +48 -13
  7. package/dist/chunk-4LMBZWIF.js.map +1 -0
  8. package/dist/{chunk-WHKXUXHE.js → chunk-4TKKLQLH.js} +5 -5
  9. package/dist/chunk-4TKKLQLH.js.map +1 -0
  10. package/dist/{chunk-KQCP3ZYH.js → chunk-5ZLNHYJH.js} +31 -15
  11. package/dist/chunk-5ZLNHYJH.js.map +1 -0
  12. package/dist/{chunk-U7KDM62P.js → chunk-6KSSJJZO.js} +17 -9
  13. package/dist/chunk-6KSSJJZO.js.map +1 -0
  14. package/dist/{chunk-6YI2D5F5.js → chunk-7IXPARDM.js} +3 -3
  15. package/dist/{chunk-UTPC66MV.js → chunk-FEFOZ2ZW.js} +23 -4
  16. package/dist/chunk-FEFOZ2ZW.js.map +1 -0
  17. package/dist/{chunk-ITXE27SZ.js → chunk-FGJ2KPPN.js} +104 -22
  18. package/dist/chunk-FGJ2KPPN.js.map +1 -0
  19. package/dist/{chunk-D5E7SGI5.js → chunk-KGDRGA2L.js} +14 -14
  20. package/dist/{chunk-D5E7SGI5.js.map → chunk-KGDRGA2L.js.map} +1 -1
  21. package/dist/{chunk-UR3DF74I.js → chunk-LZTYPJ5I.js} +36 -18
  22. package/dist/chunk-LZTYPJ5I.js.map +1 -0
  23. package/dist/{chunk-UATJCD2T.js → chunk-R5E2YGLE.js} +14 -8
  24. package/dist/chunk-R5E2YGLE.js.map +1 -0
  25. package/dist/chunk-R5JRKMEP.js +55 -0
  26. package/dist/chunk-R5JRKMEP.js.map +1 -0
  27. package/dist/{chunk-RZ266NHE.js → chunk-SPQU2422.js} +5 -5
  28. package/dist/{chunk-RZ266NHE.js.map → chunk-SPQU2422.js.map} +1 -1
  29. package/dist/{chunk-BTTQWSDS.js → chunk-SXVH74NE.js} +36 -6
  30. package/dist/chunk-SXVH74NE.js.map +1 -0
  31. package/dist/{chunk-KYRM3HPP.js → chunk-TIMS3PB7.js} +3 -3
  32. package/dist/{chunk-M75SN4D4.js → chunk-Y4QQML24.js} +3 -3
  33. package/dist/{chunk-M75SN4D4.js.map → chunk-Y4QQML24.js.map} +1 -1
  34. package/dist/cli/index.js +4 -4
  35. package/dist/{config-TXQJCCVI.js → config-32X53LWY.js} +4 -4
  36. package/dist/{expand-KWYGNCKZ.js → expand-VFYOWNZS.js} +5 -5
  37. package/dist/{file-vectors-MKXTSGGH.js → file-vectors-UBOKGYXX.js} +4 -3
  38. package/dist/{index-facts-4MTEHKMN.js → index-facts-ZTUANWBF.js} +7 -7
  39. package/dist/index-pass-S6NC25P5.js +15 -0
  40. package/dist/index.js +9 -8
  41. package/dist/{install-E3JWINTN.js → install-ZTE3H7QM.js} +8 -7
  42. package/dist/{lean-MLTAFS5L.js → lean-5N6BOONS.js} +5 -4
  43. package/dist/{local-75DJECVR.js → local-5EYLEBEP.js} +4 -2
  44. package/dist/{local-llm-MECVJTVU.js → local-llm-ESMVP5LE.js} +4 -4
  45. package/dist/{main-RLMKQZW4.js → main-B3HZCGVE.js} +61 -50
  46. package/dist/main-B3HZCGVE.js.map +1 -0
  47. package/dist/{memory-PFFVMTCH.js → memory-CI7HIGHN.js} +5 -5
  48. package/dist/{operations-STR7S5UO.js → operations-MW52HIQ3.js} +4 -4
  49. package/dist/{rerank-XXKWDI5Q.js → rerank-O4S5BC45.js} +5 -5
  50. package/dist/{runtime-SWFWGTQ4.js → runtime-SZAWIXEB.js} +6 -5
  51. package/dist/{summaries-QXWFFDUZ.js → summaries-GCHZGIIA.js} +11 -8
  52. package/dist/{zvec-F73IBWO5.js → zvec-V34P24WF.js} +11 -6
  53. package/package.json +1 -1
  54. package/dist/chunk-4BSO3HST.js.map +0 -1
  55. package/dist/chunk-BTTQWSDS.js.map +0 -1
  56. package/dist/chunk-ITXE27SZ.js.map +0 -1
  57. package/dist/chunk-KQCP3ZYH.js.map +0 -1
  58. package/dist/chunk-U7KDM62P.js.map +0 -1
  59. package/dist/chunk-UATJCD2T.js.map +0 -1
  60. package/dist/chunk-UR3DF74I.js.map +0 -1
  61. package/dist/chunk-UTPC66MV.js.map +0 -1
  62. package/dist/chunk-WHKXUXHE.js.map +0 -1
  63. package/dist/index-pass-TBDUEZCB.js +0 -14
  64. package/dist/main-RLMKQZW4.js.map +0 -1
  65. /package/dist/{chunk-JJQDVGF7.js.map → chunk-3TZNQJTH.js.map} +0 -0
  66. /package/dist/{chunk-6YI2D5F5.js.map → chunk-7IXPARDM.js.map} +0 -0
  67. /package/dist/{chunk-KYRM3HPP.js.map → chunk-TIMS3PB7.js.map} +0 -0
  68. /package/dist/{config-TXQJCCVI.js.map → config-32X53LWY.js.map} +0 -0
  69. /package/dist/{expand-KWYGNCKZ.js.map → expand-VFYOWNZS.js.map} +0 -0
  70. /package/dist/{file-vectors-MKXTSGGH.js.map → file-vectors-UBOKGYXX.js.map} +0 -0
  71. /package/dist/{index-facts-4MTEHKMN.js.map → index-facts-ZTUANWBF.js.map} +0 -0
  72. /package/dist/{index-pass-TBDUEZCB.js.map → index-pass-S6NC25P5.js.map} +0 -0
  73. /package/dist/{install-E3JWINTN.js.map → install-ZTE3H7QM.js.map} +0 -0
  74. /package/dist/{lean-MLTAFS5L.js.map → lean-5N6BOONS.js.map} +0 -0
  75. /package/dist/{local-75DJECVR.js.map → local-5EYLEBEP.js.map} +0 -0
  76. /package/dist/{local-llm-MECVJTVU.js.map → local-llm-ESMVP5LE.js.map} +0 -0
  77. /package/dist/{memory-PFFVMTCH.js.map → memory-CI7HIGHN.js.map} +0 -0
  78. /package/dist/{operations-STR7S5UO.js.map → operations-MW52HIQ3.js.map} +0 -0
  79. /package/dist/{rerank-XXKWDI5Q.js.map → rerank-O4S5BC45.js.map} +0 -0
  80. /package/dist/{runtime-SWFWGTQ4.js.map → runtime-SZAWIXEB.js.map} +0 -0
  81. /package/dist/{summaries-QXWFFDUZ.js.map → summaries-GCHZGIIA.js.map} +0 -0
  82. /package/dist/{zvec-F73IBWO5.js.map → zvec-V34P24WF.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hooks/runtime.ts","../src/context/engine.ts","../src/core/plan-file-store.ts","../src/risk/service.ts","../src/risk/assessor.ts","../src/risk/signals/churn.ts","../src/risk/signals/incident.ts","../src/risk/signals/policy.ts","../src/core/plan-lifecycle.ts","../src/worklog/store.ts","../src/core/freshness.ts","../src/context/budget.ts","../src/context/reuse-vectors.ts","../src/journal/journal.ts","../src/memory-extract/engine.ts","../src/memory-extract/deterministic.ts","../src/memory-extract/llm.ts","../src/memory-extract/resolution.ts","../src/memory-extract/review-store.ts","../src/memory-extract/rules.ts","../src/hooks/semantic.ts","../src/hooks/staging.ts"],"sourcesContent":["import { mkdir, readFile, rm, stat, writeFile } from \"node:fs/promises\";\nimport { basename, dirname, isAbsolute, join, relative, resolve, sep } from \"node:path\";\nimport pTimeout from \"p-timeout\";\nimport { taskTerms } from \"../context/discovery.js\";\nimport { buildBeforeEditContext, buildBootstrapContext } from \"../context/engine.js\";\nimport { syncFileVectors } from \"../context/file-vectors.js\";\nimport { syncReuseVectors } from \"../context/reuse-vectors.js\";\nimport { type ContextCapsule, SessionCapsuleLedger } from \"../context/session-ledger.js\";\nimport type { BeforeEditContext, BootstrapContext } from \"../context/types.js\";\nimport type { ReindexResult } from \"../core/codebuddy.js\";\nimport { loadRuntimeConfig, readConfigFile } from \"../core/config-file.js\";\nimport { redactSensitive } from \"../core/sensitive.js\";\nimport {\n appendHostEvents,\n type HostJournalEvent,\n ingestTranscript,\n isVerificationCommand,\n latestUnfinished,\n readCheckpoint,\n renderCheckpointNow,\n} from \"../journal/journal.js\";\nimport { captureAfterTurn } from \"../memory-extract/engine.js\";\nimport { extractUserRules } from \"../memory-extract/rules.js\";\nimport type { AfterTurnResult } from \"../memory-extract/types.js\";\nimport { estimateTokens } from \"../savings/tokens.js\";\nimport { recordTrace, type TraceEvent } from \"../tracing/log.js\";\nimport { skipPromptRetrieval } from \"./prompt-gate.js\";\nimport { hookRoot } from \"./root.js\";\nimport { openHookSemantics } from \"./semantic.js\";\nimport { HookStagingStore } from \"./staging.js\";\n\n/**\n * The runtime side of `codebuddy hooks`. Each function is the deterministic\n * action a Claude Code hook triggers, independent of whether the model chose to\n * call anything:\n * - context: recall — compact project context, injected at prompt submit.\n * - stage: record the files an edit tool just changed.\n * - capture: at turn end, capture durable memory from the real change set.\n *\n * All are best-effort: a hook must never break the user's turn, so callers wrap\n * these and always exit 0.\n */\n\n/** The subset of a Claude Code hook payload CodeBuddy reads. */\nexport type HookInput = {\n session_id?: string;\n transcript_path?: string;\n cwd?: string;\n hook_event_name?: string;\n prompt?: string;\n tool_name?: string;\n tool_input?: Record<string, unknown>;\n /** SessionStart only: startup | resume | clear | compact. */\n source?: string;\n /** Turn end, for hosts without a transcript file (OpenCode): the last assistant text. */\n last_assistant_message?: string;\n /** Turn end, for hosts without a transcript file: shell commands run this turn. */\n shell_commands?: Array<{ command: string; exit_code: number | null }>;\n /**\n * The host injects the block into this turn only and never keeps it in the\n * conversation (Hermes pre_llm_call), so nothing may be skipped as already sent.\n */\n ephemeral_context?: boolean;\n /** Normalized visible events from hosts without a stable transcript format. */\n journal_events?: HostJournalEvent[];\n journal_event_id?: string;\n bridge_recovery?: \"resume\" | \"compact\" | \"current\";\n injection?: \"full\" | \"lean\";\n user_prompts?: string[];\n};\n\nconst CONTEXT_BLOCK_MAX_CHARS = 1800;\n/** Capsules that never make a block on their own (see renderContextBlock). */\nconst STANDALONE_FREE = new Set([\"session\", \"test-command\"]);\n/**\n * Task files named per prompt. A wrong file costs the agent a read; on the\n * dsicord-bot labelled set, naming 2 instead of 3 cut wrong names from 48 to\n * 37 and lost 2 of 25 hits (the full list stays one `context_pack` away).\n */\nconst HOOK_TASK_FILES = 2;\n/** Facts recalled per prompt: few and precise beats many and noisy. */\nconst PROMPT_FACTS = 3;\n/** Named symbol ranges shown per task file. */\nconst HOOK_SPANS_PER_FILE = 2;\n\n/**\n * A block built later than this is dropped instead of emitted. Every bridge\n * kills the hook later (OpenCode and Hermes after 20s from spawn, Claude Code\n * after 60s), so a block is marked delivered only when it was written with\n * seconds to spare, never just before a host timeout throws the output away.\n */\nexport const CONTEXT_HOOK_BUDGET_MS = 15_000;\n\nasync function resolveNamespace(repositoryRoot: string): Promise<string> {\n if (process.env.CODEBUDDY_NAMESPACE) return process.env.CODEBUDDY_NAMESPACE;\n const file = await readConfigFile(repositoryRoot);\n return file.namespace ?? basename(repositoryRoot);\n}\n\n/**\n * UserPromptSubmit → a compact, injectable context block (recall).\n *\n * `emit` writes the block to the client. Capsules are recorded as delivered\n * only after it resolves, so a failed write leaves the session ledger untouched.\n */\nexport async function runContextHook(\n input: HookInput,\n emit?: (block: string) => Promise<void>,\n budgetMs = CONTEXT_HOOK_BUDGET_MS,\n): Promise<string> {\n if (skipPromptRetrieval(input.prompt)) return \"\";\n const started = Date.now();\n const repositoryRoot = hookRoot(input.cwd);\n const namespace = await resolveNamespace(repositoryRoot);\n\n const bootstrap = await buildBootstrapContext({ repositoryRoot, namespace });\n const ledger = new SessionCapsuleLedger(repositoryRoot);\n const sessionId = input.session_id ?? \"default\";\n // Earlier blocks are gone from the model's view. No host event says when\n // MCP results are compacted away either, so the whole session starts over.\n if (input.ephemeral_context) await ledger.reset(sessionId);\n // \"run the tests again\" in a session that already has context: retrieval\n // would only add a guess, so the prompt gets no task files.\n const followUp =\n input.prompt !== undefined &&\n input.session_id !== undefined &&\n isFollowUpPrompt(input.prompt) &&\n (await ledger.delivered(sessionId));\n let beforeEdit: BeforeEditContext | null = null;\n const semantics = input.prompt && !followUp ? await openHookSemantics(repositoryRoot) : null;\n if (!followUp)\n try {\n beforeEdit = await buildBeforeEditContext({\n repositoryRoot,\n namespace,\n // Git changes are the targets only without a prompt; a prompt that\n // matches no file gets none (an explicit useGit would force them back).\n ...(input.prompt ? { task: input.prompt } : {}),\n ...(semantics?.semanticRanker ? { semanticRanker: semantics.semanticRanker } : {}),\n ...(semantics?.reranker ? { reranker: semantics.reranker } : {}),\n });\n } catch {\n beforeEdit = null;\n } finally {\n await semantics?.close();\n }\n const { text, emitted } = await renderContextBlock(\n bootstrap,\n beforeEdit,\n ledger,\n sessionId,\n input.session_id !== undefined,\n );\n // Too late: the host may already have given up on this hook. Nothing is\n // marked, so the next prompt delivers the block.\n const late = Date.now() - started >= budgetMs;\n await recordTrace(\n repositoryRoot,\n recallTrace(input, beforeEdit, emitted, late ? \"\" : text, started, late),\n );\n if (late) return \"\";\n if (text.trim()) await emit?.(text);\n await ledger.markSent(sessionId, emitted);\n return text;\n}\n\n/**\n * A short prompt with at most three task terms (\"run the tests again\",\n * \"continue\", \"yes do it\") continues the current task rather than naming one.\n */\nexport function isFollowUpPrompt(prompt: string): boolean {\n const words = prompt.trim().split(/\\s+/).filter(Boolean);\n return words.length <= 6 && taskTerms(prompt).length <= 3;\n}\n\n/**\n * What one prompt recalled, for `codebuddy dashboard`: the prompt (redacted, cut\n * to 120 chars) and the block the agent actually received (redacted, cut to\n * 2,000 chars), so the page shows real context rather than a summary of it.\n */\nfunction recallTrace(\n input: HookInput,\n beforeEdit: BeforeEditContext | null,\n emitted: ContextCapsule[],\n text: string,\n started: number,\n late: boolean,\n): Omit<TraceEvent, \"ts\"> {\n const shown = new Set(\n emitted.filter((c) => c.key.startsWith(\"fact:\")).map((c) => c.key.slice(5)),\n );\n const facts = (beforeEdit?.facts ?? []).filter((fact) => shown.has(fact.id));\n const prompt = redactSensitive(input.prompt ?? \"\")\n .replace(/\\s+/g, \" \")\n .trim();\n return {\n kind: \"recall\",\n name: \"context\",\n ms: Date.now() - started,\n ok: !late,\n tokensIn: estimateTokens(input.prompt ?? \"\"),\n tokensOut: estimateTokens(text),\n ...(input.session_id ? { session: input.session_id } : {}),\n detail: {\n prompt: clip(prompt, 120),\n facts: facts.map((fact) => fact.summary.slice(0, 100)),\n dense: facts.filter((fact) => fact.reason.includes(\"semantic\")).length,\n lexical: facts.filter((fact) => /task term|target path/.test(fact.reason)).length,\n files: (beforeEdit?.targetPaths ?? []).slice(0, 3),\n sections: emitted.length,\n ...(text.trim() ? { block: clip(redactSensitive(text.trim()), 2000) } : {}),\n ...(late ? { dropped: \"built after the hook budget\" } : {}),\n },\n };\n}\n\nfunction clip(text: string, max: number): string {\n return text.length > max ? `${text.slice(0, max - 1)}…` : text;\n}\n\n/** PostToolUse(edit) → stage the changed paths for capture. */\nexport async function runStageHook(input: HookInput): Promise<string[]> {\n const repositoryRoot = hookRoot(input.cwd);\n const paths = extractEditedPaths(input.tool_input)\n .map((path) => toRepoRelative(repositoryRoot, path))\n .filter((path): path is string => path !== null);\n await new HookStagingStore(repositoryRoot).add(input.session_id ?? \"default\", paths);\n if (input.journal_event_id)\n await appendHostEvents(\n repositoryRoot,\n input.session_id ?? \"default\",\n paths.map((path, index) => ({\n id: `${input.journal_event_id}:${index}`,\n kind: \"edit\",\n path,\n })),\n );\n if (input.journal_events?.length) await runCheckpointHook(input).catch(() => null);\n // A session killed before its turn ends is still recoverable from its last edit.\n if (input.transcript_path) {\n await ingestTranscript(\n repositoryRoot,\n input.session_id ?? \"default\",\n input.transcript_path,\n ).catch(() => null);\n }\n return paths;\n}\n\nexport type CaptureHookResult = {\n changedFiles: string[];\n result: AfterTurnResult | null;\n};\n\n/** BYOK memory extraction options (empty when the layer or its memory feature is off). */\nexport async function llmMemoryOptions(\n repositoryRoot: string,\n): Promise<Awaited<ReturnType<typeof import(\"../llm/memory.js\").llmCaptureOptions>>> {\n try {\n return await (await import(\"../llm/memory.js\")).llmCaptureOptions(repositoryRoot);\n } catch {\n return {};\n }\n}\n\n/** A turn with no edits still leaves a handoff when the assistant reported at least this much. */\nconst INVESTIGATION_MIN_CHARS = 200;\n/** A handoff must point at code: a file path with an extension, or a backticked identifier. */\nconst NAMES_CODE =\n /[\\w.-]+\\/[\\w./-]*\\.\\w{1,5}\\b|\\b[\\w-]+\\.(?:ts|tsx|js|jsx|mjs|py|go|rs|java|rb|php|cs|c|cpp|h|swift|kt)\\b|`[^`\\s]+`/;\n\n/**\n * Stop → capture durable memory from the staged change set + transcript. A\n * turn without edits is still captured when the user stated or withdrew a\n * rule, or when the assistant reported findings (an investigation handoff).\n */\nexport async function runCaptureHook(input: HookInput): Promise<CaptureHookResult> {\n const captureStarted = Date.now();\n const repositoryRoot = hookRoot(input.cwd);\n const staging = new HookStagingStore(repositoryRoot);\n const sessionId = input.session_id ?? \"default\";\n if (input.journal_events?.length) await runCheckpointHook(input).catch(() => null);\n // The journal keeps every turn's prompts, findings, edits and checks, even\n // turns that produce no memory below. It never blocks capture.\n if (input.transcript_path) {\n await ingestTranscript(repositoryRoot, sessionId, input.transcript_path).catch(() => null);\n }\n // null: another capture holds this session's lock and handles the turn.\n const claimed = await staging.claim(sessionId);\n if (claimed === null) return { changedFiles: [], result: null };\n const changedFiles = claimed;\n try {\n const transcript = input.transcript_path ? await readCaptureTurn(input.transcript_path) : null;\n const prompts = transcript?.prompts ?? input.user_prompts ?? [];\n const { rules, revocations, policies } = extractUserRules(prompts);\n let investigation = false;\n if (changedFiles.length === 0) {\n const assistant = transcript?.assistant ?? input.last_assistant_message?.trim() ?? \"\";\n investigation = assistant.length >= INVESTIGATION_MIN_CHARS && NAMES_CODE.test(assistant);\n if (\n !investigation &&\n rules.length === 0 &&\n revocations.length === 0 &&\n policies.length === 0\n ) {\n await staging.acknowledge(sessionId);\n return { changedFiles, result: null };\n }\n }\n const namespace = await resolveNamespace(repositoryRoot);\n const summary = await deriveSummary(\n undefined,\n changedFiles,\n transcript?.assistant ?? input.last_assistant_message,\n );\n const verification = transcript\n ? transcript.verification\n : verificationLines(\n (input.shell_commands ?? []).map(({ command, exit_code }) => ({\n command,\n ok: typeof exit_code === \"number\" ? exit_code === 0 : undefined,\n })),\n );\n const result = await captureAfterTurn(\n {\n summary,\n changedFiles,\n namespace,\n sessionId,\n ...(verification.length > 0 ? { verification } : {}),\n ...(rules.length > 0 ? { userRules: rules } : {}),\n ...(policies.length > 0 ? { userPolicies: policies } : {}),\n ...(revocations.length > 0 ? { revokedRules: revocations } : {}),\n ...(investigation ? { investigation } : {}),\n // Without edits, only the user's own rules and a handoff are kept: an\n // explanation is not evidence of a decision or an incident.\n ...(changedFiles.length === 0 ? { extract: false } : {}),\n },\n {\n repositoryRoot,\n ...(changedFiles.length > 0 ? await llmMemoryOptions(repositoryRoot) : {}),\n },\n );\n await staging.acknowledge(sessionId);\n await recordTrace(repositoryRoot, {\n kind: \"capture\",\n name: \"capture\",\n ms: Date.now() - captureStarted,\n ok: true,\n session: sessionId,\n detail: {\n changedFiles: changedFiles.length,\n saved: result.saved.length,\n queued: result.queuedForReview.length,\n ignored: result.ignored.length,\n },\n });\n return { changedFiles, result };\n } catch (error) {\n await staging.rollback(sessionId);\n throw error;\n }\n}\n\n/** Long enough for the first run to download the model (~90 MB) on a slow link. */\nconst SYNC_BUDGET_MS = 5 * 60_000;\n\nexport type SyncHookResult = { reindex: ReindexResult; drained: boolean } | null;\n\n/**\n * Background, after capture: Markdown (the source of truth) → PostgreSQL\n * (reindex) → local embeddings for every new or re-spaced row, so the next\n * prompt's dense recall already sees this turn's memory (and the first run\n * downloads the local model). null when no database is configured.\n */\nexport async function runSyncHook(\n repositoryRoot: string,\n options: { respace?: boolean } = {},\n): Promise<SyncHookResult> {\n const config = await loadRuntimeConfig(repositoryRoot, { requireDatabase: false });\n if (!config.postgresUrl) return null;\n // One sync per project at a time: a burst of captured turns would otherwise\n // start one process (a DB pool and a loaded model) per turn. A sync that\n // finds the lock held leaves a marker; the holder runs once more for it.\n const lock = join(repositoryRoot, \".codebuddy\", \"cache\", \"sync.lock\");\n const dirty = join(repositoryRoot, \".codebuddy\", \"cache\", \"sync.dirty\");\n await mkdir(dirname(lock), { recursive: true });\n if (!(await takeLock(lock))) {\n await writeFile(dirty, \"\").catch(() => undefined);\n return null;\n }\n const { createRuntime } = await import(\"../core/operations.js\");\n const runtime = await createRuntime(config, { repositoryRoot }).catch(async (error) => {\n await rm(lock, { recursive: true, force: true });\n throw error;\n });\n try {\n let result: NonNullable<SyncHookResult>;\n let round = 0;\n do {\n await rm(dirty, { force: true });\n const started = Date.now();\n const reindex = await runtime.memory.reindexMemory(options.respace ? {} : { respace: false });\n const drained = await pTimeout(runtime.memory.getWorker().drain(), {\n milliseconds: SYNC_BUDGET_MS,\n }).then(\n () => true,\n () => false,\n );\n await recordTrace(repositoryRoot, {\n kind: \"sync\",\n name: \"sync\",\n ms: Date.now() - started,\n ok: drained,\n detail: {\n imported: reindex.facts.imported,\n updated: reindex.facts.updated,\n reembedding: reindex.reembedding ?? 0,\n failures: reindex.failures.length,\n },\n });\n result = { reindex, drained };\n round += 1;\n } while (\n round < 3 &&\n (await stat(dirty).then(\n () => true,\n () => false,\n ))\n );\n if (config.provider.type === \"local\") {\n const started = Date.now();\n const vectorStarted = Date.now();\n const vectors = await syncFileVectors(repositoryRoot, SYNC_BUDGET_MS);\n await syncReuseVectors(repositoryRoot, SYNC_BUDGET_MS - (Date.now() - vectorStarted));\n // Locked: another process is embedding this repo right now; nothing to trace.\n if (vectors && vectors.lockedBy === undefined) {\n const { lockedBy: _, ...counts } = vectors;\n await recordTrace(repositoryRoot, {\n kind: \"sync\",\n name: \"file-vectors\",\n ms: Date.now() - started,\n ok: true,\n detail: counts,\n });\n }\n }\n return result;\n } finally {\n await runtime.close();\n await rm(lock, { recursive: true, force: true });\n }\n}\n\n/** A sync longer than this crashed or hung; its lock may be taken over. */\nconst SYNC_LOCK_STALE_MS = SYNC_BUDGET_MS + 60_000;\n\nasync function takeLock(path: string): Promise<boolean> {\n try {\n await mkdir(path);\n return true;\n } catch {\n const age = await stat(path).then(\n (info) => Date.now() - info.mtimeMs,\n () => 0,\n );\n if (age < SYNC_LOCK_STALE_MS) return false;\n await rm(path, { recursive: true, force: true });\n return mkdir(path).then(\n () => true,\n () => false,\n );\n }\n}\n\n/** SessionStart(compact|clear) → resend all context on the next prompt. */\nexport async function runResetHook(\n input: HookInput,\n emit?: (block: string) => Promise<void>,\n): Promise<string> {\n const repositoryRoot = hookRoot(input.cwd);\n const sessionId = input.session_id ?? \"default\";\n const ledger = new SessionCapsuleLedger(repositoryRoot);\n await ledger.reset(sessionId);\n // Claude Code adds a SessionStart(compact|clear) hook's output to the new\n // context. Earlier injections were summarized away, so put the standing\n // project context (plan, rules, procedures, incidents, handoffs) back now\n // instead of waiting for the next prompt. Bridges that discard this output\n // (OpenCode, Hermes) keep the old behaviour: the next prompt resends it all.\n if (input.hook_event_name !== \"SessionStart\") return \"\";\n const namespace = await resolveNamespace(repositoryRoot);\n const bootstrap = await buildBootstrapContext({ repositoryRoot, namespace });\n const { text: block, emitted } = await renderContextBlock(\n bootstrap,\n null,\n ledger,\n sessionId,\n input.session_id !== undefined,\n );\n // Compaction summarized the task away; /clear means the user dropped it.\n let task = \"\";\n if (input.source === \"compact\") {\n if (input.transcript_path) {\n await ingestTranscript(repositoryRoot, sessionId, input.transcript_path).catch(() => null);\n }\n const checkpoint = await readCheckpoint(repositoryRoot, sessionId).catch(() => null);\n if (checkpoint?.goal) {\n task = await renderCheckpointNow(\n repositoryRoot,\n checkpoint,\n \"this session, before compaction\",\n );\n }\n }\n const text = [block, task].filter(Boolean).join(\"\\n\");\n if (text.trim()) await emit?.(text);\n await ledger.markSent(sessionId, emitted);\n return text;\n}\n\n/** PreCompact: journal the transcript while it still holds the unsummarized turns. */\nexport async function runCheckpointHook(input: HookInput): Promise<void> {\n const repositoryRoot = hookRoot(input.cwd);\n if (input.transcript_path)\n await ingestTranscript(repositoryRoot, input.session_id ?? \"default\", input.transcript_path);\n if (input.journal_events?.length)\n await appendHostEvents(repositoryRoot, input.session_id ?? \"default\", input.journal_events);\n}\n\n/**\n * SessionStart(startup|resume): an unfinished task from another session (an\n * interrupted chat, or a Codex rollout imported with `codebuddy journal\n * import-codex`), at most 3 days old. Prints nothing when there is none.\n */\nexport async function runResumeHook(\n input: HookInput,\n emit?: (block: string) => Promise<void>,\n): Promise<string> {\n const repositoryRoot = hookRoot(input.cwd);\n const checkpoint = await latestUnfinished(repositoryRoot, input.session_id);\n if (!checkpoint) return \"\";\n const text = await renderCheckpointNow(\n repositoryRoot,\n checkpoint,\n `unfinished, from session ${checkpoint.session}`,\n );\n await emit?.(text);\n return text;\n}\n\n// ── helpers ─────────────────────────────────────────────────────────\n\n/**\n * Pull edited paths out of a tool input: Claude Edit/Write (`file_path`),\n * MultiEdit (`edits[]`), OpenCode edit/write (`filePath`) and apply_patch/patch\n * (`patchText` file headers, including move targets), Hermes write_file and\n * patch replace mode (`path`) and patch mode (V4A headers in `patch`).\n */\nexport function extractEditedPaths(toolInput: Record<string, unknown> | undefined): string[] {\n if (!toolInput) return [];\n const paths: string[] = [];\n const push = (value: unknown) => {\n if (typeof value === \"string\" && value.trim()) paths.push(value);\n };\n push(toolInput.file_path);\n push(toolInput.filePath);\n push(toolInput.path);\n for (const patch of [toolInput.patchText, toolInput.patch]) {\n if (typeof patch !== \"string\") continue;\n for (const match of patch.matchAll(\n /^\\*\\*\\*\\s+(?:(?:Add|Update|Delete)\\s+File|Move\\s+to):\\s*(.+)$/gm,\n )) {\n push(match[1]?.trim());\n }\n }\n if (Array.isArray(toolInput.edits)) {\n for (const edit of toolInput.edits) {\n if (edit && typeof edit === \"object\") push((edit as Record<string, unknown>).file_path);\n }\n }\n return [...new Set(paths)];\n}\n\nfunction toRepoRelative(repositoryRoot: string, path: string): string | null {\n const absolute = isAbsolute(path) ? resolve(path) : resolve(repositoryRoot, path);\n const rel = relative(repositoryRoot, absolute);\n if (rel === \"\" || rel === \"..\" || rel.startsWith(`..${sep}`) || isAbsolute(rel)) return null;\n return rel.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\");\n}\n\n/**\n * Build a capture summary from the turn transcript (the last assistant message)\n * plus the change set. If the transcript can't be read, fall back to a plain\n * file list — which the conservative extractor will simply not turn into durable\n * facts, exactly the safe outcome.\n */\nexport async function deriveSummary(\n transcriptPath: string | undefined,\n changedFiles: string[],\n /** Used when there is no transcript (OpenCode passes the last assistant text). */\n lastAssistantText?: string,\n): Promise<string> {\n const fileList = changedFiles.length > 0 ? `Changed files: ${changedFiles.join(\", \")}.` : \"\";\n const assistantText = transcriptPath\n ? await lastAssistantMessage(transcriptPath)\n : (lastAssistantText?.trim().slice(0, 2000) ?? \"\");\n return [assistantText, fileList].filter(Boolean).join(\"\\n\\n\");\n}\n\n/**\n * A shell segment counts as verification when a known runner invokes a\n * test/lint/typecheck/build step (`rm -rf build` does not count).\n */\n/**\n * Verification evidence for the current turn: test/lint/typecheck/build shell\n * commands run since the user's last prompt, with pass/fail from the tool\n * result. Only commands and outcomes are kept, never their output.\n */\nexport async function turnVerification(transcriptPath: string): Promise<string[]> {\n return (await readCaptureTurn(transcriptPath)).verification;\n}\n\n/** Format verification runs (non-checks dropped); `ok` undefined = no result. */\nexport function verificationLines(\n runs: Array<{ command: string; ok: boolean | undefined }>,\n): string[] {\n const lines = runs\n .filter((run) => isVerificationCommand(run.command))\n .map(({ command, ok }) => {\n const label = ok === undefined ? \"no result\" : ok ? \"passed\" : \"failed\";\n return `${command.replace(/\\s+/g, \" \").trim().slice(0, 120)}: ${label}`;\n });\n // Keep the latest runs; a re-run after a fix is the one that matters.\n return lines.slice(-10);\n}\n\n/** Prompts longer than this are pasted material, not instructions to remember. */\nconst MAX_RULE_PROMPT_CHARS = 1500;\n/** Harness-inserted markup (reminders, slash-command echoes) inside user content. */\nconst TAGGED_BLOCK = /<([a-z][\\w-]*)[^>]*>[\\s\\S]*?<\\/\\1>/gi;\n\n/**\n * The user's own prompt text for the current turn (since the last assistant\n * reply): tool results, harness-inserted meta messages (skill bodies, command\n * output) and tagged blocks are excluded, so only what the user typed can\n * become a rule.\n */\nexport async function turnUserPrompts(transcriptPath: string): Promise<string[]> {\n return (await readCaptureTurn(transcriptPath)).prompts;\n}\n\nexport async function lastAssistantMessage(transcriptPath: string): Promise<string> {\n return (await readCaptureTurn(transcriptPath)).assistant;\n}\n\n/** One read and JSON parse per line for Stop capture, rather than three full transcript scans. */\nexport async function readCaptureTurn(\n transcriptPath: string,\n): Promise<{ prompts: string[]; assistant: string; verification: string[] }> {\n let raw: string;\n try {\n raw = await readFile(transcriptPath, \"utf8\");\n } catch {\n return { prompts: [], assistant: \"\", verification: [] };\n }\n let prompts: string[] = [];\n let answered = false;\n let assistant = \"\";\n const commands = new Map<string, string>();\n const outcomes = new Map<string, boolean>();\n for (const line of raw.split(\"\\n\")) {\n let entry: Record<string, unknown>;\n try {\n entry = JSON.parse(line) as Record<string, unknown>;\n } catch {\n continue;\n }\n const message = (entry.message ?? entry) as Record<string, unknown>;\n const role = message.role ?? entry.type;\n const content = message.content;\n const blocks = Array.isArray(content) ? content : [];\n if (role === \"assistant\") {\n answered = true;\n const text = extractText(content);\n if (text) assistant = text.slice(0, 2000);\n for (const block of blocks) {\n if (\n block?.type === \"tool_use\" &&\n block.name === \"Bash\" &&\n typeof block.id === \"string\" &&\n typeof block.input?.command === \"string\" &&\n isVerificationCommand(block.input.command)\n )\n commands.set(block.id, block.input.command);\n }\n } else if (role === \"user\") {\n const text =\n entry.isMeta === true ? \"\" : extractText(content).replace(TAGGED_BLOCK, \" \").trim();\n if (text) {\n commands.clear();\n outcomes.clear();\n if (answered) {\n prompts = [];\n answered = false;\n }\n if (text.length <= MAX_RULE_PROMPT_CHARS) prompts.push(text);\n }\n for (const block of blocks) {\n if (block?.type === \"tool_result\" && typeof block.tool_use_id === \"string\")\n outcomes.set(block.tool_use_id, block.is_error !== true);\n }\n }\n }\n return {\n prompts,\n assistant,\n verification: verificationLines(\n [...commands].map(([id, command]) => ({ command, ok: outcomes.get(id) })),\n ),\n };\n}\n\nfunction extractText(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return \"\";\n return content\n .map((block) =>\n block && typeof block === \"object\" && (block as Record<string, unknown>).type === \"text\"\n ? String((block as Record<string, unknown>).text ?? \"\")\n : \"\",\n )\n .join(\" \")\n .trim();\n}\n\n/** Below this a risk score (0–100) is one routine signal, e.g. a few commits. */\nconst RISK_LINE_MIN_SCORE = 50;\n\n/** A rendered line; lower `priority` is packed first. */\ntype BlockItem = { priority: number; text: string; capsule?: ContextCapsule };\n\n/** Capsule text is bounded so one huge subject can never become undeliverable. */\nfunction bound(text: string, max = 300): string {\n return text.length > max ? `${text.slice(0, max - 1)}…` : text;\n}\n\n/**\n * Pack whole lines into the block by priority (current-task risk, relevant\n * facts, then broad bootstrap evidence) and return only the capsules whose\n * full text made it in. Lines are never cut; omitted capsules stay unseen.\n */\nexport async function renderContextBlock(\n bootstrap: BootstrapContext,\n beforeEdit: BeforeEditContext | null,\n ledger: SessionCapsuleLedger,\n sessionId: string,\n announceSession = false,\n): Promise<{ text: string; emitted: ContextCapsule[] }> {\n const capsules: Array<{ priority: number; capsule: ContextCapsule }> = [\n // Sent once per session (and again after a reset): MCP context calls that\n // pass it as `sessionId` share this ledger, so compaction resets both paths.\n ...(announceSession\n ? [\n {\n priority: 1,\n capsule: {\n key: \"session\",\n text: `session: ${sessionId} (pass as sessionId to CodeBuddy tools)`,\n },\n },\n ]\n : []),\n // Benchmark v3: \"project: <name>\", \"plan: none\" and the architecture size\n // were re-read every turn and never acted on, so only an active plan is shown.\n ...(bootstrap.plan\n ? [\n {\n priority: 4,\n capsule: {\n key: \"plan\",\n text: `plan: ${bootstrap.plan.title} (${bootstrap.plan.status}); policy: ${bootstrap.policy}`,\n },\n },\n ]\n : []),\n ];\n // Only rules that match this prompt's target files; the full rule list is\n // the same on every prompt and rarely relevant.\n const policyRules = beforeEdit?.policyRules ?? [];\n if (policyRules.length > 0) {\n capsules.push({\n priority: 4,\n capsule: {\n key: \"policies\",\n text: `policies: ${policyRules.map((r) => `${r.id}(${r.weight})`).join(\", \")}`,\n },\n });\n }\n for (const incident of bootstrap.incidents) {\n capsules.push({\n priority: 5,\n capsule: {\n key: `incident:${incident.id}`,\n text: `incident: ${bound(incident.subject)} [${incident.severity}]`,\n },\n });\n }\n for (const rule of bootstrap.rules ?? []) {\n const procedure = rule.subject === \"procedure\";\n capsules.push({\n priority: 2,\n capsule: {\n key: `${procedure ? \"procedure\" : \"rule\"}:${rule.id}`,\n text: bound(`${procedure ? \"verify\" : \"rule\"}: ${rule.summary}`),\n },\n });\n }\n // With a prompt, memory is what the prompt retrieved (hybrid-ranked; none\n // = abstain), never the most recent facts; those are only for a bare start.\n const ranked = Boolean(beforeEdit?.task);\n // A code-search prompt (task files found) rarely needs team memory: the top\n // fact only, plus any that match a target path or have both lexical and\n // dense evidence (2.15.1 benchmark: unrelated notes on routing tasks).\n const codeSearch = beforeEdit?.pathSource === \"task\" && beforeEdit.targetPaths.length > 0;\n const strong = (fact: { reason: string }) =>\n fact.reason.includes(\"matches a target path\") ||\n (fact.reason.includes(\"task term\") && fact.reason.includes(\"semantic\"));\n const facts = (ranked ? (beforeEdit?.facts ?? []) : bootstrap.facts).filter(\n (fact, index) => !codeSearch || index === 0 || strong(fact),\n );\n for (const fact of facts) {\n capsules.push({\n priority: ranked ? 2 : 6,\n capsule: { key: `fact:${fact.id}`, text: bound(`fact: ${fact.summary}`) },\n });\n }\n // With a prompt, prior work only when it touched or named one of this\n // task's files (one line at most); unrelated sessions were most of the lines.\n const targets = new Set(beforeEdit?.targetPaths ?? []);\n const handoffs = ranked\n ? bootstrap.handoffs\n .filter(\n (handoff) =>\n handoff.files.some((file) => targets.has(file)) ||\n // An investigation handoff edits nothing; it names the file instead.\n [...targets].some((path) => handoff.summary.includes(path)),\n )\n .slice(0, 1)\n : bootstrap.handoffs;\n for (const handoff of handoffs) {\n const drift = [\n handoff.changedSince.length > 0 ? `${handoff.changedSince.length} file(s) changed since` : \"\",\n handoff.missing.length > 0 ? `${handoff.missing.length} missing` : \"\",\n ]\n .filter(Boolean)\n .join(\", \");\n capsules.push({\n priority: 7,\n capsule: {\n key: `handoff:${handoff.id}`,\n text: `prior work (${handoff.ageDays}d ago${drift ? `; ${drift}` : \"\"}): ${handoff.summary\n .replace(/\\s+/g, \" \")\n .slice(0, 160)}`,\n },\n });\n }\n if (beforeEdit?.testCommand) {\n capsules.push({\n priority: 3,\n capsule: { key: \"test-command\", text: `test command: ${beforeEdit.testCommand}` },\n });\n }\n\n if (beforeEdit && beforeEdit.targetPaths.length > 0) {\n // Only git-derived targets are edits in progress; task/plan/explicit paths are not.\n const targetLabel = beforeEdit.pathSource === \"git\" ? \"current changes\" : \"task files\";\n const tests = (beforeEdit.tests ?? []).map((entry) => entry.test);\n // Line ranges let the agent open the right region without a search first.\n const ranges = new Map(\n (beforeEdit.symbols ?? []).map((file) => [\n file.path,\n (file.spans ?? [])\n .filter((span) => span.name)\n .slice(0, HOOK_SPANS_PER_FILE)\n .map((span) => `${span.name} L${span.startLine}-${span.endLine}`),\n ]),\n );\n const describe = (path: string) => {\n const spans = ranges.get(path) ?? [];\n return spans.length > 0 ? `${path} (${spans.join(\", \")})` : path;\n };\n capsules.push({\n priority: 3,\n capsule: {\n key: \"task-files\",\n text: bound(\n `${targetLabel}: ${beforeEdit.targetPaths\n .slice(0, beforeEdit.pathSource === \"task\" ? HOOK_TASK_FILES : 8)\n .map(describe)\n .join(\", \")}${tests.length > 0 ? `; tests: ${tests.join(\", \")}` : \"\"}`,\n 500,\n ),\n },\n });\n // Risk for the listed files only (task discovery also assesses unrelated\n // git changes), and only when the score means something.\n const targets = new Set(beforeEdit.targetPaths);\n const risks = beforeEdit.risks.items.filter(\n (item) => targets.has(item.path) && item.score >= RISK_LINE_MIN_SCORE,\n );\n if (risks.length > 0) {\n capsules.push({\n priority: 1,\n capsule: {\n key: \"risk\",\n text: bound(\n `risk: ${risks\n .slice(0, 3)\n .map((item) => `${item.path}=${item.score}`)\n .join(\", \")}`,\n 500,\n ),\n },\n });\n }\n }\n\n const seen = await ledger.seen(\n sessionId,\n capsules.map((entry) => entry.capsule),\n );\n const items: BlockItem[] = [\n { priority: 0, text: \"## CodeBuddy project context (auto-recalled)\" },\n ];\n // Facts already in the conversation do not use up this prompt's fact slots.\n // Capsules already delivered are not resent, nor announced (benchmark v3).\n let newFacts = 0;\n for (const { priority, capsule } of capsules) {\n if (seen.has(capsule.key)) continue;\n if (ranked && capsule.key.startsWith(\"fact:\") && ++newFacts > PROMPT_FACTS) continue;\n else items.push({ priority, text: capsule.text, capsule });\n }\n // Nothing new, or only the session id / test command: no block at all. Those two\n // ride along with real evidence (they stay unsent until then), so a prompt\n // retrieval abstains on costs nothing.\n if (!items.some((item) => item.capsule && !STANDALONE_FREE.has(item.capsule.key)))\n return { text: \"\", emitted: [] };\n\n // Greedy by priority; a line that does not fit is skipped whole, a smaller one may still fit.\n const chosen = new Set<BlockItem>();\n let used = -1; // joining \"\\n\" is only paid between lines\n const byPriority = items\n .map((item, index) => ({ item, index }))\n .sort((a, b) => a.item.priority - b.item.priority || a.index - b.index);\n for (const { item } of byPriority) {\n const cost = item.text.length + 1;\n if (used + cost > CONTEXT_BLOCK_MAX_CHARS) continue;\n used += cost;\n chosen.add(item);\n }\n const packed = items.filter((item) => chosen.has(item));\n return {\n text: packed.map((item) => item.text).join(\"\\n\"),\n emitted: packed.flatMap((item) => (item.capsule ? [item.capsule] : [])),\n };\n}\n","import { execFile } from \"node:child_process\";\nimport { join, resolve } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { loadPlanPolicy } from \"../core/config-file.js\";\nimport {\n type FactFile,\n type IncidentFactFile,\n MemoryFileStore,\n} from \"../core/memory-file-store.js\";\nimport { isEligibleMemory } from \"../core/memory-lifecycle.js\";\nimport { admitsLexically, lexicalTerms, termOverlap } from \"../core/memory-search.js\";\nimport { PlanFileStore, type PlanSpec } from \"../core/plan-file-store.js\";\nimport { PlanLifecycle } from \"../core/plan-lifecycle.js\";\nimport {\n isCredentialPath,\n loadKnownSecretValues,\n REDACTED_LINE,\n redactSourceText,\n} from \"../core/sensitive.js\";\nimport { loadFreshIndex } from \"../indexer/engine.js\";\nimport { extractSymbolTable, type SymbolSpan, supportsSymbols } from \"../indexer/symbols.js\";\nimport type { ArchitectureMap } from \"../map/types.js\";\nimport type { RetrievalHit } from \"../retrieval/zvec.js\";\nimport { assessRisk, resolveRiskPaths } from \"../risk/service.js\";\nimport { matchesPolicyGlob, type PolicyRule, readPolicyFile } from \"../risk/signals/policy.js\";\nimport { estimateTokens } from \"../savings/tokens.js\";\nimport { type HandoffSummary, WorklogStore } from \"../worklog/store.js\";\nimport { enforceContextBudget } from \"./budget.js\";\nimport {\n countTerms,\n discoverTaskPaths,\n identifierTokens,\n loadProjectArchitectureMap,\n namedSegments,\n readBoundedSource,\n TASK_PATH_LIMIT,\n taskTerms,\n} from \"./discovery.js\";\nimport { detectTestCommand, findCoveringTest } from \"./tests.js\";\nimport type {\n ArchitectureSummary,\n BeforeEditContext,\n BootstrapContext,\n ContextSpan,\n DiffHunk,\n FileSymbols,\n IncidentSummary,\n ModuleNeighbours,\n PathSource,\n PlanSummary,\n PolicyRuleSummary,\n RelevantFactSummary,\n TokenStats,\n} from \"./types.js\";\n\n/**\n * Bounds. These keep both tool outputs compact regardless of repository size —\n * a bootstrap or before-edit payload should orient the agent, not dump the\n * whole project. Tune here rather than at each call site.\n */\nconst LIMITS = {\n bootstrapIncidents: 5,\n beforeEditIncidents: 8,\n policyRules: 5,\n hotspots: 5,\n neighbourPaths: 10,\n neighbourEdges: 10,\n incidentSummaryChars: 140,\n symbolFiles: TASK_PATH_LIMIT,\n symbolsPerFile: 12,\n spanFiles: 3,\n excerptLines: 6,\n excerptCharsPerSpan: 400,\n excerptChars: 1_200,\n relevantFacts: 5,\n} as const;\n\nconst DEFAULT_TOKEN_BUDGET = 4_000;\nconst MAX_DIFF_FILES = 8;\nconst MAX_DIFF_CHARS_PER_FILE = 2_400;\nconst execFileAsync = promisify(execFile);\n\nexport type BootstrapInput = {\n repositoryRoot?: string;\n namespace: string;\n tokenBudget?: number;\n};\n\nexport type BeforeEditInput = {\n repositoryRoot?: string;\n namespace: string;\n task?: string;\n paths?: string[];\n planId?: string;\n useGit?: boolean;\n tokenBudget?: number;\n semanticRanker?: SemanticRelevanceRanker;\n /** Optional (`rerank.provider`): orders the fused facts, never admits one. */\n reranker?: ContextReranker;\n evidence?: \"overview\" | \"source\";\n};\n\n/** Cross-encoder scores for (task, document) pairs, in input order (higher = more relevant). */\nexport type ContextReranker = (task: string, documents: string[]) => Promise<number[]>;\n\n/** Dense evidence: cosine per fact id, only for facts at or above the model's floor. */\nexport type SemanticRelevanceRanker = (\n task: string,\n candidates: Array<{ id: string; text: string }>,\n) => Promise<Record<string, number>>;\n\n/**\n * Assemble compact project awareness for the start of a turn: identity, the\n * active plan and policy, top policy rules, incident hotspots, and a\n * lightweight architecture summary. No edit target is required.\n */\nexport async function buildBootstrapContext(input: BootstrapInput): Promise<BootstrapContext> {\n const repositoryRoot = resolve(input.repositoryRoot ?? process.cwd());\n const namespace = input.namespace;\n\n const planStore = new PlanFileStore(repositoryRoot);\n const memoryStore = new MemoryFileStore(repositoryRoot);\n const freshPromise = loadFreshIndex(repositoryRoot);\n const manifestPromise = freshPromise.then((fresh) => fresh.manifest);\n const mapPromise = loadProjectArchitectureMap(repositoryRoot, manifestPromise);\n\n const [activePlan, policy, policyFile, incidents, facts, fresh, map, handoffs] =\n await Promise.all([\n new PlanLifecycle(planStore).current(namespace),\n loadPlanPolicy(repositoryRoot),\n readPolicyFile(join(repositoryRoot, \".codebuddy\", \"policies.yaml\")),\n memoryStore.listIncidentFacts({ namespace }),\n memoryStore.listFacts(),\n freshPromise,\n mapPromise,\n recallHandoffs(repositoryRoot, { namespace }),\n ]);\n\n const explain: string[] = [fresh.explain];\n const plan = summarizePlan(activePlan);\n explain.push(plan ? `plan: active plan ${plan.id} (${plan.status})` : \"plan: no active plan\");\n explain.push(`policy: plan policy is \"${policy}\"`);\n\n const policyRules = summarizePolicyRules(policyFile.rules);\n if (policyRules.length > 0) explain.push(`policyRules: ${policyRules.length} rule(s) by weight`);\n\n const incidentSummaries = sortIncidents(incidents)\n .slice(0, LIMITS.bootstrapIncidents)\n .map(summarizeIncident);\n if (incidentSummaries.length > 0) {\n explain.push(`incidents: ${incidentSummaries.length} unresolved incident hotspot(s)`);\n }\n\n const architecture = summarizeArchitecture(map);\n explain.push(\n `architecture: ${architecture.moduleCount} module(s), ${architecture.edgeCount} edge(s)` +\n (map.source ? ` (${map.source})` : \"\"),\n );\n\n const rules = selectRules(facts, namespace);\n if (rules.length > 0) {\n const procedures = rules.filter((rule) => rule.subject === \"procedure\").length;\n explain.push(`rules: ${rules.length - procedures} rule(s), ${procedures} procedure(s)`);\n }\n const bootstrapFacts = await rankRelevantFacts(\n facts.filter((fact) => !STANDING_PREDICATES.has(fact.predicate)),\n namespace,\n \"\",\n [],\n );\n explainHandoffs(explain, handoffs);\n const assembled = {\n project: { namespace, root: repositoryRoot },\n plan,\n policy,\n policyRules,\n incidents: incidentSummaries,\n facts: bootstrapFacts,\n rules,\n handoffs,\n architecture,\n explain,\n };\n const tokens = buildTokenStats(assembled, input.tokenBudget);\n return enforceContextBudget({ ...assembled, tokens });\n}\n\n/**\n * Assemble the most relevant context before an edit: resolve the target files\n * (explicit paths, a plan, or git), then attach the relevant plan, policy\n * rules, incident memory for those files, an evidence-backed risk assessment,\n * and the import neighbours of each target.\n */\nexport async function buildBeforeEditContext(input: BeforeEditInput): Promise<BeforeEditContext> {\n const repositoryRoot = resolve(input.repositoryRoot ?? process.cwd());\n const namespace = input.namespace;\n\n const hasExplicitTargets = (input.paths?.length ?? 0) > 0 || input.planId !== undefined;\n // Validate the index against current source before any indexed symbol,\n // summary or import is trusted (issue #34).\n const fresh = await loadFreshIndex(repositoryRoot);\n const manifest = fresh.manifest;\n const resolvedPaths = await resolveRiskPaths({\n repositoryRoot,\n ...(input.paths !== undefined ? { paths: input.paths } : {}),\n ...(input.planId !== undefined ? { planId: input.planId } : {}),\n ...(hasExplicitTargets\n ? { useGit: false }\n : input.useGit !== undefined\n ? { useGit: input.useGit }\n : {}),\n });\n const mapPromise = loadProjectArchitectureMap(repositoryRoot, manifest);\n const discovery =\n !hasExplicitTargets && input.task\n ? await discoverTaskPaths(repositoryRoot, input.task, manifest, mapPromise)\n : { paths: [], hits: [], explain: [], confidence: undefined };\n const taskPaths = discovery.paths;\n // A task that matched no file gets no targets: uncommitted files (often\n // .DS_Store, editor or tool config) are not evidence for an unrelated task.\n // Only an explicit `useGit: true` (\"review my changes\") keeps them.\n const askedTask = Boolean(input.task?.trim());\n const targetPaths = hasExplicitTargets\n ? resolvedPaths\n : taskPaths.length > 0\n ? taskPaths\n : askedTask && input.useGit !== true\n ? []\n : resolvedPaths;\n const discoveredFromTask = taskPaths.length > 0;\n const pathSource = classifyPathSource(input, targetPaths.length, discoveredFromTask);\n\n const planStore = new PlanFileStore(repositoryRoot);\n const memoryStore = new MemoryFileStore(repositoryRoot);\n // File text leaves this machine for the agent's model provider: diffs, spans\n // and signatures are redacted line by line, and credential files never read.\n const knownSecrets = await loadKnownSecretValues(repositoryRoot);\n\n const [referencedPlan, policy, policyFile, incidents, facts, risks, map, diffs, handoffs] =\n await Promise.all([\n resolveRelevantPlan(planStore, namespace, input.planId),\n loadPlanPolicy(repositoryRoot),\n readPolicyFile(join(repositoryRoot, \".codebuddy\", \"policies.yaml\")),\n memoryStore.findIncidentFactsForPaths({ namespace, paths: targetPaths }),\n memoryStore.listFacts(),\n assessRisk({\n repositoryRoot,\n namespace,\n ...(targetPaths.length > 0 ? { paths: targetPaths } : {}),\n ...(input.planId !== undefined ? { planId: input.planId } : {}),\n useGit: !hasExplicitTargets && input.useGit !== false,\n }),\n mapPromise,\n input.useGit === false\n ? Promise.resolve([] as DiffHunk[])\n : readGitDiffs(repositoryRoot, targetPaths, knownSecrets),\n recallHandoffs(repositoryRoot, {\n namespace,\n paths: targetPaths,\n ...(input.task !== undefined ? { task: input.task } : {}),\n }),\n ]);\n\n const explain: string[] = [];\n explain.push(`paths: ${targetPaths.length} target(s) resolved from ${pathSource}`);\n explain.push(fresh.explain);\n if (discoveredFromTask && resolvedPaths.length > 0) {\n explain.push(\n `git: ${resolvedPaths.length} observed changed path(s) assessed separately from task targets`,\n );\n }\n explain.push(...discovery.explain);\n if (askedTask && !hasExplicitTargets && taskPaths.length === 0) {\n explain.push(\n targetPaths.length > 0\n ? \"paths: no file matched the task; useGit asked for the uncommitted changes instead\"\n : \"paths: no file matched the task; none returned rather than unrelated changes\",\n );\n }\n\n const plan = summarizePlan(referencedPlan);\n if (plan) explain.push(`plan: ${plan.id} (${plan.status})`);\n\n const policyRules = summarizeMatchingPolicyRules(policyFile.rules, targetPaths);\n if (policyRules.length > 0) {\n explain.push(`policyRules: ${policyRules.length} rule(s) match target paths`);\n }\n\n const incidentSummaries = sortIncidents(incidents)\n .slice(0, LIMITS.beforeEditIncidents)\n .map(summarizeIncident);\n if (incidentSummaries.length > 0) {\n explain.push(`incidents: ${incidentSummaries.length} incident(s) touch target paths`);\n }\n\n if (risks.items.length > 0) explain.push(`risks: ${risks.items.length} scored path(s)`);\n\n const neighbours = computeNeighbours(map, targetPaths);\n if (neighbours.length > 0)\n explain.push(\n `neighbours: import graph for ${neighbours.length} file(s)` +\n (map.source ? ` (${map.source})` : \"\"),\n );\n\n const symbols = await computeTargetSymbols(\n repositoryRoot,\n targetPaths,\n input.task ?? \"\",\n discovery.hits,\n \"symbols\" in discovery ? (discovery.symbols ?? {}) : {},\n input.evidence ?? \"overview\",\n knownSecrets,\n );\n if (symbols.length > 0) {\n const spans = symbols.reduce((total, file) => total + (file.spans?.length ?? 0), 0);\n explain.push(\n `symbols: signatures for ${symbols.length} target file(s) (in place of full source)` +\n (spans > 0 ? `; ${spans} task-ranked span(s) read from current source` : \"\"),\n );\n }\n\n const relevantFacts = await rankRelevantFacts(\n facts.filter((fact) => !STANDING_PREDICATES.has(fact.predicate)),\n namespace,\n input.task ?? \"\",\n targetPaths,\n input.semanticRanker,\n input.reranker,\n );\n if (relevantFacts.length > 0) {\n const semantic = relevantFacts.filter((fact) => fact.reason.includes(\"semantic\")).length;\n explain.push(\n `facts: ${relevantFacts.length} durable fact(s) by hybrid rank fusion` +\n (input.semanticRanker\n ? ` (${semantic} with dense evidence${relevantFacts[0]?.reason.endsWith(\"reranked\") ? \", reranked\" : \"\"})`\n : \" (lexical only; no semantic fact ranker configured)\"),\n );\n }\n explainHandoffs(explain, handoffs);\n\n const indexed = new Set(Object.keys(manifest.entries));\n const tests = targetPaths.flatMap((path) => {\n const test = findCoveringTest(path, indexed);\n return test ? [{ path, test }] : [];\n });\n const testCommand = targetPaths.length > 0 ? await detectTestCommand(repositoryRoot) : null;\n if (tests.length > 0 || testCommand) {\n explain.push(\n `tests: ${tests.length} covering test(s) by naming convention; command ${testCommand ?? \"unknown\"}`,\n );\n }\n\n const assembled = {\n project: { namespace, root: repositoryRoot },\n task: input.task ?? null,\n targetPaths,\n pathSource,\n plan,\n policy,\n policyRules,\n incidents: incidentSummaries,\n facts: relevantFacts,\n handoffs,\n risks,\n neighbours,\n symbols,\n tests,\n testCommand,\n diffs,\n explain,\n ...(discovery.confidence && !hasExplicitTargets ? { confidence: discovery.confidence } : {}),\n // A plain abstention: no guessed files, and the agent is told to search itself.\n ...(askedTask && !hasExplicitTargets && targetPaths.length === 0\n ? { note: NO_MATCH_NOTE }\n : {}),\n };\n const tokens = buildTokenStats(assembled, input.tokenBudget);\n return enforceContextBudget({ ...assembled, tokens });\n}\n\nexport const NO_MATCH_NOTE =\n \"No confident file match for this task; search the repository normally (grep/glob) instead of relying on CodeBuddy targets.\";\n\n// ── helpers ─────────────────────────────────────────────────────────\n\n/** Prior worklog handoffs. A broken worklog must never break context assembly. */\nasync function recallHandoffs(\n repositoryRoot: string,\n input: Parameters<WorklogStore[\"recall\"]>[0],\n): Promise<HandoffSummary[]> {\n try {\n return await new WorklogStore(repositoryRoot).recall(input);\n } catch {\n return [];\n }\n}\n\nfunction explainHandoffs(explain: string[], handoffs: HandoffSummary[]): void {\n if (handoffs.length === 0) return;\n const stale = handoffs.filter((h) => h.changedSince.length > 0 || h.missing.length > 0).length;\n explain.push(\n `handoffs: ${handoffs.length} prior worklog entr${handoffs.length === 1 ? \"y\" : \"ies\"}` +\n (stale > 0 ? ` (${stale} with files changed or missing since — verify before relying)` : \"\"),\n );\n}\n\nfunction summarizePlan(plan: PlanSpec | null): PlanSummary {\n if (!plan) return null;\n return {\n id: plan.id,\n title: plan.title,\n status: plan.status,\n brief: plan.brief,\n filesToTouch: plan.filesToTouch.map((file) => file.path),\n risks: plan.risks,\n };\n}\n\n/**\n * Prefer an explicitly referenced plan; fall back to the namespace's active\n * plan so before-edit context stays useful even when the caller passes only\n * paths.\n */\nasync function resolveRelevantPlan(\n store: PlanFileStore,\n namespace: string,\n planId?: string,\n): Promise<PlanSpec | null> {\n if (planId) {\n try {\n return await store.readPlan(planId);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return null;\n throw error;\n }\n }\n return new PlanLifecycle(store).current(namespace);\n}\n\nfunction sortIncidents(incidents: IncidentFactFile[]): IncidentFactFile[] {\n const severity = { critical: 4, high: 3, medium: 2, low: 1 };\n return [...incidents].sort(\n (a, b) =>\n Number(a.resolvedBy !== null) - Number(b.resolvedBy !== null) ||\n severity[b.severity] - severity[a.severity],\n );\n}\n\nfunction summarizeIncident(fact: IncidentFactFile): IncidentSummary {\n return {\n id: fact.id,\n severity: fact.severity,\n subject: fact.subject,\n summary: truncate(fact.content || fact.object || fact.subject, LIMITS.incidentSummaryChars),\n paths: fact.paths,\n resolved: fact.resolvedBy !== null,\n createdAt: fact.createdAt,\n };\n}\n\nfunction summarizePolicyRules(rules: PolicyRule[]): PolicyRuleSummary[] {\n return [...rules]\n .sort((left, right) => right.weight - left.weight)\n .slice(0, LIMITS.policyRules)\n .map((rule) => ({\n id: rule.id,\n pattern: rule.pattern,\n message: rule.message ?? rule.reason ?? `Policy rule ${rule.id}.`,\n weight: rule.weight,\n }));\n}\n\nfunction summarizeMatchingPolicyRules(rules: PolicyRule[], paths: string[]): PolicyRuleSummary[] {\n const matching = rules.filter((rule) =>\n paths.some((path) => matchesPolicyGlob(path, rule.pattern)),\n );\n return summarizePolicyRules(matching);\n}\n\nfunction summarizeArchitecture(map: ArchitectureMap): ArchitectureSummary {\n const inbound = new Map<string, number>();\n const outbound = new Map<string, number>();\n for (const edge of map.edges) {\n outbound.set(edge.from, (outbound.get(edge.from) ?? 0) + 1);\n inbound.set(edge.to, (inbound.get(edge.to) ?? 0) + 1);\n }\n\n const hotspots = map.modules\n .map((module) => ({\n path: module.path,\n inbound: inbound.get(module.path) ?? 0,\n outbound: outbound.get(module.path) ?? 0,\n }))\n .filter((entry) => entry.inbound + entry.outbound > 0)\n .sort((left, right) => {\n const degree = right.inbound + right.outbound - (left.inbound + left.outbound);\n if (degree !== 0) return degree;\n return left.path.localeCompare(right.path);\n })\n .slice(0, LIMITS.hotspots);\n\n return { moduleCount: map.modules.length, edgeCount: map.edges.length, hotspots };\n}\n\nfunction computeNeighbours(map: ArchitectureMap, paths: string[]): ModuleNeighbours[] {\n const result: ModuleNeighbours[] = [];\n for (const path of paths.slice(0, LIMITS.neighbourPaths)) {\n // Dedupe BEFORE slicing: duplicate edges from a many-to-many import would\n // otherwise crowd unique neighbours out of the bounded payload.\n const dependsOn = [\n ...new Set(map.edges.filter((edge) => edge.from === path).map((edge) => edge.to)),\n ].slice(0, LIMITS.neighbourEdges);\n const dependedOnBy = [\n ...new Set(map.edges.filter((edge) => edge.to === path).map((edge) => edge.from)),\n ].slice(0, LIMITS.neighbourEdges);\n if (dependsOn.length === 0 && dependedOnBy.length === 0) continue;\n const usesSymbols: Record<string, string[]> = {};\n for (const dependency of dependsOn) {\n const symbols = map.edges.find(\n (edge) => edge.from === path && edge.to === dependency,\n )?.symbols;\n if (symbols?.length) usesSymbols[dependency] = symbols;\n }\n result.push({\n path,\n dependsOn,\n dependedOnBy,\n ...(Object.keys(usesSymbols).length > 0 ? { usesSymbols } : {}),\n });\n }\n return result;\n}\n\n/**\n * Read the target files' public API as compact signatures (Roadmap N.3), so the\n * agent can see what each file offers without the tool sending its full source.\n * The whole bounded symbol table is ranked by the task *before* it is limited,\n * so a relevant thirteenth declaration still wins (issue #35); declarations\n * overlapping a semantic hit are preferred. The best match comes back as a span\n * read from current source, with a short excerpt drawn from one global budget.\n * Bounded and best-effort: unreadable files are skipped.\n */\nasync function computeTargetSymbols(\n repositoryRoot: string,\n targetPaths: string[],\n task: string,\n hits: RetrievalHit[],\n /** Symbols the BYOK rerank named per file; they outrank term matches. */\n picked: Record<string, string[]> = {},\n evidence: \"overview\" | \"source\" = \"overview\",\n knownSecrets: readonly string[] = [],\n): Promise<FileSymbols[]> {\n const terms = taskTerms(task);\n const tokens = identifierTokens(task);\n const result: FileSymbols[] = [];\n let excerptBudget: number = evidence === \"source\" ? 5400 : LIMITS.excerptChars;\n let spanned = 0;\n for (const path of targetPaths.slice(0, LIMITS.symbolFiles)) {\n const source = await readBoundedSource(repositoryRoot, path);\n if (source === null) continue;\n // Redacted whole lines first: an excerpt or signature cut later can then\n // never expose part of a secret.\n const lines = redactSourceText(source, knownSecrets).split(/\\r?\\n/);\n // zg's index may be stale: only trust hit ranges that still fit the file.\n const fileHits = hits.filter((hit) => hit.path === path && hit.endLine <= lines.length);\n const table = supportsSymbols(path) ? extractSymbolTable(source, path) : [];\n // Each semantic hit credits only the narrowest declaration containing it,\n // so a method beats its enclosing class.\n const credited = new Map<SymbolSpan, RetrievalHit>();\n for (const hit of fileHits) {\n const owner = table\n .filter((symbol) => hit.startLine <= symbol.endLine && hit.endLine >= symbol.startLine)\n .sort(\n (left, right) => left.endLine - left.startLine - (right.endLine - right.startLine),\n )[0];\n if (owner && !credited.has(owner)) credited.set(owner, hit);\n }\n const ranked = table\n .map((symbol) => {\n const hit = credited.get(symbol);\n // A class body repeats its methods' words; let the narrower method win.\n const body =\n symbol.kind === \"class\"\n ? \"\"\n : lines.slice(symbol.startLine - 1, symbol.endLine).join(\" \");\n const score =\n (picked[path]?.includes(symbol.name) ? 1_000 : 0) +\n 100 * namedSegments(symbol.name, tokens) +\n (hit ? 10 : 0) +\n 3 * countTerms(lines[symbol.startLine - 1] ?? \"\", terms) +\n countTerms(body, terms);\n return { symbol, hit, score };\n })\n .sort(\n (left, right) => right.score - left.score || left.symbol.startLine - right.symbol.startLine,\n );\n // Methods only earn a signature line when the task points at them.\n const signatures = ranked\n .filter(({ symbol, score }) => symbol.kind !== \"method\" || score > 0)\n .slice(0, LIMITS.symbolsPerFile)\n .map(({ symbol }) =>\n lines[symbol.startLine - 1] === REDACTED_LINE\n ? REDACTED_LINE\n : redactSourceText(symbol.signature, knownSecrets),\n );\n // One grounded span per file: the best task match, else the top semantic\n // hit (unsupported languages, or no declaration matched). Only the first\n // few files get one, so the extra tokens stay bounded.\n const best = ranked[0]?.score ? ranked[0] : undefined;\n const hit = best ? best.hit : fileHits[0];\n const range = best?.symbol ?? hit;\n const spans: ContextSpan[] = [];\n if (range && spanned < LIMITS.spanFiles) {\n const span: ContextSpan = {\n ...(best ? { name: best.symbol.name } : {}),\n startLine: range.startLine,\n endLine: range.endLine,\n ...(hit\n ? { source: hit.source, rank: hit.rank, freshness: \"current-source\" }\n : { source: \"lexical\", freshness: \"current-source\" }),\n };\n if (excerptBudget > 0) {\n const headShown = best !== undefined && headInSignature(lines, best.symbol);\n span.excerpt = sourceExcerpt(\n lines,\n span,\n terms,\n hit?.startLine,\n hit?.endLine,\n excerptBudget,\n headShown,\n evidence,\n );\n excerptBudget -= span.excerpt.text.length;\n }\n spans.push(span);\n spanned++;\n }\n if (signatures.length > 0 || spans.length > 0) {\n result.push({ path, signatures, ...(spans.length > 0 ? { spans } : {}) });\n }\n }\n return result;\n}\n\n/**\n * A few lines of current source around the best task-term line (or the semantic\n * hit), so behavior and comments a signature can't show are still grounded.\n */\nfunction sourceExcerpt(\n lines: string[],\n span: ContextSpan,\n terms: string[],\n anchorLine: number | undefined,\n anchorEndLine: number | undefined,\n budget: number,\n headShown = false,\n evidence: \"overview\" | \"source\" = \"overview\",\n): NonNullable<ContextSpan[\"excerpt\"]> {\n let anchor = Math.max(span.startLine, anchorLine ?? span.startLine);\n let best = 0;\n if (anchorLine === undefined) {\n for (let line = span.startLine; line <= span.endLine; line++) {\n const score = countTerms(lines[line - 1] ?? \"\", terms);\n if (score > best) {\n best = score;\n anchor = line;\n }\n }\n }\n const detailed = evidence === \"source\";\n const windowStart =\n detailed && span.endLine - span.startLine < 40\n ? span.startLine\n : Math.max(span.startLine, anchor - 1);\n const endLine = Math.min(\n span.endLine,\n windowStart + (detailed ? 40 : LIMITS.excerptLines) - 1,\n detailed || anchorEndLine === undefined ? span.endLine : anchorEndLine + 1,\n );\n // The declaration line is already a listed signature; don't send it twice.\n const startLine =\n headShown && windowStart === span.startLine && endLine > windowStart\n ? windowStart + 1\n : windowStart;\n const raw = lines.slice(startLine - 1, endLine).join(\"\\n\");\n const text = raw.slice(0, Math.min(budget, detailed ? 1800 : LIMITS.excerptCharsPerSpan));\n return {\n startLine,\n endLine: startLine + text.split(\"\\n\").length - 1,\n text,\n truncated: windowStart > span.startLine || endLine < span.endLine || text.length < raw.length,\n };\n}\n\n/** True when the declaration line adds nothing beyond its (untruncated) signature. */\nfunction headInSignature(lines: string[], symbol: SymbolSpan): boolean {\n const head =\n symbol.kind === \"method\"\n ? symbol.signature.slice(symbol.signature.indexOf(\": \") + 2)\n : symbol.signature;\n const line = (lines[symbol.startLine - 1] ?? \"\").trim();\n return (\n !head.endsWith(\"…\") && line.startsWith(head) && /^[\\s{=>(]*$/.test(line.slice(head.length))\n );\n}\n\n/**\n * Read the current staged and unstaged hunks for target paths. The result is\n * bounded per file so a large change cannot crowd out plan and risk context.\n */\nasync function readGitDiffs(\n repositoryRoot: string,\n paths: string[],\n knownSecrets: readonly string[] = [],\n): Promise<DiffHunk[]> {\n if (paths.length === 0) return [];\n const sections: string[] = [];\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\n \"-c\",\n \"core.quotePath=false\",\n \"diff\",\n \"HEAD\",\n \"--no-ext-diff\",\n \"--unified=3\",\n \"--\",\n ...paths,\n ],\n { cwd: repositoryRoot, maxBuffer: 2_000_000 },\n );\n sections.push(stdout);\n } catch {\n // Repositories without a first commit cannot use `git diff HEAD`. Their\n // staged and unstaged tracked changes are still useful independently.\n for (const args of [\n [\n \"-c\",\n \"core.quotePath=false\",\n \"diff\",\n \"--cached\",\n \"--no-ext-diff\",\n \"--unified=3\",\n \"--\",\n ...paths,\n ],\n [\"-c\", \"core.quotePath=false\", \"diff\", \"--no-ext-diff\", \"--unified=3\", \"--\", ...paths],\n ]) {\n try {\n const { stdout } = await execFileAsync(\"git\", args, {\n cwd: repositoryRoot,\n maxBuffer: 2_000_000,\n });\n sections.push(stdout);\n } catch {\n // Fall through to untracked-file handling.\n }\n }\n }\n\n const parsed = parseGitDiff(sections.join(\"\\n\"), knownSecrets);\n const known = new Set(parsed.map((diff) => diff.path));\n const untracked = await listUntrackedPaths(repositoryRoot, paths);\n for (const path of untracked) {\n if (known.has(path)) continue;\n const patch = isCredentialPath(path)\n ? withheldPatch(path)\n : await buildUntrackedPatch(repositoryRoot, path, knownSecrets);\n if (patch) parsed.push(patch);\n }\n return parsed.slice(0, MAX_DIFF_FILES);\n}\n\n/**\n * Old and new path of a `diff --git` section. Git C-quotes names holding a\n * quote, backslash, tab or newline (`\"a/x\\ty.ts\"`), even with core.quotePath off.\n */\nfunction diffHeaderPaths(section: string): [string, string, string] | null {\n const quoted = '\"(?:[^\"\\\\\\\\]|\\\\\\\\.)*\"';\n const header = new RegExp(`^diff --git (${quoted}|a/.+?) (${quoted}|b/.+?)\\\\n`, \"m\").exec(\n section,\n );\n if (!header?.[1] || !header[2]) return null;\n const path = (raw: string) => (raw.startsWith('\"') ? unquoteGitPath(raw) : raw).slice(2);\n return [header[0], path(header[1]), path(header[2])];\n}\n\nconst C_ESCAPES: Record<string, number> = { a: 7, b: 8, t: 9, n: 10, v: 11, f: 12, r: 13 };\n\n/** Undo git's C-style path quoting; octal escapes are UTF-8 bytes. */\nfunction unquoteGitPath(raw: string): string {\n const bytes: number[] = [];\n const body = raw.slice(1, -1);\n for (let at = 0; at < body.length; at++) {\n const char = body[at] as string;\n if (char !== \"\\\\\") {\n bytes.push(...Buffer.from(char, \"utf8\"));\n continue;\n }\n const next = body[++at] ?? \"\";\n const octal = /^[0-7]{3}/.exec(body.slice(at))?.[0];\n if (octal) {\n bytes.push(Number.parseInt(octal, 8));\n at += 2;\n } else bytes.push(C_ESCAPES[next] ?? next.charCodeAt(0));\n }\n return Buffer.from(bytes).toString(\"utf8\");\n}\n\n/** A credential file's change is reported without reading or showing its contents. */\nfunction withheldPatch(path: string): DiffHunk {\n return {\n path,\n patch: `diff --git a/${path} b/${path}\\n(contents withheld: credential file)`,\n };\n}\n\nfunction parseGitDiff(diff: string, knownSecrets: readonly string[] = []): DiffHunk[] {\n return diff\n .split(/(?=^diff --git )/m)\n .filter((section) => section.startsWith(\"diff --git \"))\n .flatMap((section) => {\n const header = diffHeaderPaths(section);\n if (!header?.[2]) return [];\n // A rename out of a credential file still shows its old contents.\n if (isCredentialPath(header[1] ?? \"\") || isCredentialPath(header[2])) {\n return [withheldPatch(header[2])];\n }\n // Redact before truncating so a cut can never expose part of a secret.\n const rawPatch = redactSourceText(section.trim(), knownSecrets, true);\n const patch = rawPatch.slice(0, MAX_DIFF_CHARS_PER_FILE).trim();\n return patch\n ? [\n {\n path: header[2],\n patch,\n ...(patch.length < rawPatch.length ? { truncated: true } : {}),\n },\n ]\n : [];\n });\n}\n\nasync function listUntrackedPaths(repositoryRoot: string, paths: string[]): Promise<string[]> {\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"ls-files\", \"-z\", \"--others\", \"--exclude-standard\", \"--\", ...paths],\n { cwd: repositoryRoot, maxBuffer: 1_000_000 },\n );\n return stdout.split(\"\\0\").filter(Boolean);\n } catch {\n return [];\n }\n}\n\nasync function buildUntrackedPatch(\n repositoryRoot: string,\n path: string,\n knownSecrets: readonly string[],\n): Promise<DiffHunk | null> {\n try {\n // Bounded like any evidence read: oversized and binary files are skipped.\n const content = await readBoundedSource(repositoryRoot, path);\n if (content === null) return null;\n const lines = content.split(/\\r?\\n/);\n const body = redactSourceText(lines.map((line) => `+${line}`).join(\"\\n\"), knownSecrets, true);\n const rawPatch = [\n `diff --git a/${path} b/${path}`,\n \"new file mode 100644\",\n \"--- /dev/null\",\n `+++ b/${path}`,\n `@@ -0,0 +1,${lines.length} @@`,\n body,\n ].join(\"\\n\");\n const patch = rawPatch.slice(0, MAX_DIFF_CHARS_PER_FILE).trim();\n return {\n path,\n patch,\n ...(patch.length < rawPatch.length ? { truncated: true } : {}),\n };\n } catch {\n return null;\n }\n}\n\n/** Facts delivered as standing guidance, not ranked against the task. */\nconst STANDING_PREDICATES = new Set([\"rule\", \"procedure\"]);\nconst STANDING_LIMITS = { rule: 5, procedure: 3, chars: 200 } as const;\n\n/** Live user rules (newest 5) then procedures (newest 3), regardless of task overlap. */\n/**\n * Standing rules and procedures reach every session, and fact files can arrive\n * through git, so neither may be steered by a planted file: one dated in the\n * future (to sort first forever) is not shown, and a procedure is shown only\n * when it is one plain command (no chaining, pipes, substitution or\n * redirection), since agents tend to run what `verify:` says.\n */\nconst SHELL_CONTROL = /[;&|`$<>\\n\\r]/;\n\nfunction selectRules(facts: FactFile[], namespace: string): RelevantFactSummary[] {\n // A day of clock-skew slack; anything later was not captured here.\n const latest = new Date(Date.now() + 86_400_000).toISOString();\n const newest = (predicate: \"rule\" | \"procedure\") =>\n facts\n .filter((fact) => fact.predicate === predicate && isEligibleMemory(fact, { namespace }))\n .filter((fact) => fact.createdAt <= latest)\n .filter((fact) => predicate !== \"procedure\" || !SHELL_CONTROL.test(fact.object))\n .sort((left, right) => right.createdAt.localeCompare(left.createdAt))\n .slice(0, STANDING_LIMITS[predicate]);\n return [...newest(\"rule\"), ...newest(\"procedure\")].map((fact) => ({\n id: fact.id,\n subject: fact.predicate,\n summary: truncate(fact.object, STANDING_LIMITS.chars),\n paths: fact.paths,\n confidence: fact.confidence,\n relevance: 0,\n reason:\n fact.predicate === \"rule\" ? \"standing user rule\" : \"verification that passed repeatedly\",\n createdAt: fact.createdAt,\n createdByAgent: fact.createdByAgent,\n }));\n}\n\n/** Reciprocal rank fusion constant (Cormack et al. 2009): damps the head so no one list dominates. */\nconst RRF_K = 60;\n/** At most this many fused facts go to the optional cross-encoder. */\nconst RERANK_POOL = 20;\n\n/**\n * Hybrid fact retrieval:\n * 1. gate: lexical (task words + target paths) or dense evidence (pgvector\n * cosine at or above the model's calibrated floor) admits a fact;\n * 2. rank: reciprocal rank fusion of the lexical and dense rankings,\n * score(f) = Σ_lists 1 / (RRF_K + rank_list(f));\n * 3. rerank: optional cross-encoder that orders the fused pool. Off by\n * default: on `npm run eval:semantic` none of eight local rerankers\n * beat the dense order. Its scores never admit a fact.\n * Every model step is optional and fail-soft.\n */\nexport async function rankRelevantFacts(\n facts: FactFile[],\n namespace: string,\n task: string,\n targetPaths: string[],\n semanticRanker?: SemanticRelevanceRanker,\n reranker?: ContextReranker,\n): Promise<RelevantFactSummary[]> {\n // Eligibility runs before ranking and duplicate suppression, so only\n // same-namespace, live incidents can suppress a fact with identical text.\n const eligible = facts.filter((fact) => isEligibleMemory(fact, { namespace }));\n const incidentText = new Set(\n eligible\n .filter((fact) => fact.category === \"incident\")\n .map((fact) => normalizeText(fact.content || fact.object)),\n );\n const terms = lexicalTerms(task).filter((term) => term.length > 2);\n const withTerms = eligible\n .filter((fact) => fact.category !== \"incident\")\n .filter((fact) => !incidentText.has(normalizeText(fact.content || fact.object)))\n .map((fact) => {\n const text = `${fact.subject} ${fact.predicate} ${fact.object} ${fact.content}`;\n const words = new Set(text.toLowerCase().match(/[\\p{L}\\p{N}_]+/gu) ?? []);\n // Distinct task terms (stopwords dropped) found as whole words.\n return { fact, text, shared: terms.filter((term) => words.has(term)) };\n });\n const documentFrequency = new Map(\n terms.map((term) => [term, withTerms.filter(({ shared }) => shared.includes(term)).length]),\n );\n const candidates = withTerms.map(({ fact, text, shared }) => {\n const taskScore = shared.length * 3;\n // A path match is strong supporting evidence, but must not overwhelm a\n // clearly different task (for example database work near an auth file).\n const pathScore = fact.paths.some((path) => targetPaths.includes(path)) ? 5 : 0;\n // One everyday word in common is a coincidence, not evidence (#9).\n const admitted = admitsLexically(shared, documentFrequency, withTerms.length);\n return {\n fact,\n text,\n taskScore,\n pathScore,\n admitted,\n lexical: (admitted ? taskScore : 0) + pathScore,\n };\n });\n const summarize = (fact: FactFile, relevance: number, reason: string): RelevantFactSummary => ({\n id: fact.id,\n subject: fact.subject,\n summary: truncate(fact.content || fact.object, LIMITS.incidentSummaryChars),\n paths: fact.paths,\n confidence: fact.confidence,\n relevance,\n reason,\n createdAt: fact.createdAt,\n createdByAgent: fact.createdByAgent,\n });\n\n if (!task.trim()) {\n return candidates\n .sort(\n (left, right) =>\n right.fact.confidence - left.fact.confidence ||\n right.fact.createdAt.localeCompare(left.fact.createdAt),\n )\n .slice(0, LIMITS.relevantFacts)\n .map(({ fact }) => summarize(fact, Math.round(fact.confidence * 5), \"recent project fact\"));\n }\n\n let dense: Record<string, number> = {};\n if (semanticRanker) {\n try {\n dense = await semanticRanker(\n task,\n candidates.map(({ fact, text }) => ({ id: fact.id, text })),\n );\n } catch {\n dense = {};\n }\n }\n const cosine = (id: string) => {\n const value = dense[id];\n return typeof value === \"number\" && Number.isFinite(value) ? value : undefined;\n };\n const gated = candidates.filter(\n (candidate) => candidate.lexical > 0 || cosine(candidate.fact.id) !== undefined,\n );\n const rankOf = (ordered: Array<(typeof gated)[number]>) =>\n new Map(ordered.map((candidate, index) => [candidate.fact.id, index + 1]));\n const lexicalRank = rankOf(\n gated.filter(({ lexical }) => lexical > 0).sort((a, b) => b.lexical - a.lexical),\n );\n const denseRank = rankOf(\n gated\n .filter(({ fact }) => cosine(fact.id) !== undefined)\n .sort((a, b) => (cosine(b.fact.id) ?? 0) - (cosine(a.fact.id) ?? 0)),\n );\n const rrf = (rank: number | undefined) => (rank === undefined ? 0 : 1 / (RRF_K + rank));\n const fused = gated\n .map((candidate) => ({\n ...candidate,\n score: rrf(lexicalRank.get(candidate.fact.id)) + rrf(denseRank.get(candidate.fact.id)),\n }))\n .sort(\n (left, right) =>\n right.score - left.score ||\n right.fact.confidence - left.fact.confidence ||\n right.fact.createdAt.localeCompare(left.fact.createdAt),\n );\n\n let reranked = false;\n if (reranker && fused.length > 1) {\n const pool = fused.slice(0, RERANK_POOL);\n try {\n const scores = await reranker(\n task,\n pool.map(({ text }) => text),\n );\n if (scores.length === pool.length && scores.every((score) => !Number.isNaN(score))) {\n const scoreOf = new Map(pool.map((candidate, index) => [candidate, scores[index] ?? 0]));\n // Stable: equal scores keep their fused order; the rest of the list follows.\n pool.sort((left, right) => (scoreOf.get(right) ?? 0) - (scoreOf.get(left) ?? 0));\n fused.splice(0, pool.length, ...pool);\n reranked = true;\n }\n } catch {\n // Keep the fused order.\n }\n }\n\n // Diversity: a fact that restates one already selected adds no information\n // and would spend one of the few slots (maximal marginal relevance, lexically).\n const selected: typeof fused = [];\n for (const candidate of fused) {\n if (selected.length >= LIMITS.relevantFacts) break;\n const text = candidate.fact.content || candidate.fact.object;\n if (selected.some((kept) => termOverlap(text, kept.fact.content || kept.fact.object) >= 0.8)) {\n continue;\n }\n selected.push(candidate);\n }\n\n return selected.map(({ fact, taskScore, pathScore, score, admitted }) => {\n const evidence = [\n pathScore > 0 ? \"matches a target path\" : \"\",\n admitted && taskScore > 0 ? `shares ${taskScore / 3} task term(s)` : \"\",\n cosine(fact.id) !== undefined ? `semantic ${cosine(fact.id)?.toFixed(2)}` : \"\",\n ].filter(Boolean);\n return summarize(\n fact,\n // Fused score scaled to a readable integer (max = 2/61 · 1000 ≈ 33).\n Math.round(score * 1000),\n evidence.join(\"; \") + (reranked ? \"; reranked\" : \"\"),\n );\n });\n}\n\nfunction normalizeText(value: string): string {\n return value\n .toLowerCase()\n .replace(/[^a-z0-9_./-]+/g, \" \")\n .trim();\n}\n\nfunction classifyPathSource(\n input: BeforeEditInput,\n resolvedCount: number,\n discoveredFromTask: boolean,\n): PathSource {\n if (resolvedCount === 0) return \"none\";\n if (discoveredFromTask) return \"task\";\n if (input.paths && input.paths.length > 0) return \"paths\";\n if (input.planId) return \"plan\";\n return \"git\";\n}\n\n/** Estimate the payload's token footprint against its budget. */\nfunction buildTokenStats(payload: unknown, tokenBudget: number | undefined): TokenStats {\n return {\n budget: tokenBudget ?? DEFAULT_TOKEN_BUDGET,\n returnedEstimate: estimateTokens(payload ?? {}),\n status: \"within_budget\",\n countedSurface: \"compact_json\",\n essentialOmitted: 0,\n };\n}\n\nfunction truncate(value: string, max: number): string {\n const trimmed = value.trim();\n return trimmed.length <= max ? trimmed : `${trimmed.slice(0, max - 1)}…`;\n}\n\nexport { rankTaskPaths, scoreTaskPaths } from \"./discovery.js\";\n","import { mkdir, open, readdir, readFile, rm, stat } from \"node:fs/promises\";\nimport { dirname, join, relative, resolve, sep } from \"node:path\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { z } from \"zod\";\nimport {\n assertNoSymlinkBetween,\n composeMarkdown,\n parseFrontMatter,\n writeAtomic,\n} from \"./markdown-store-fs.js\";\n\n/**\n * Plans are durable Markdown artifacts under `.codebuddy/plans/`. Git is\n * the version history; PostgreSQL (when present) is a derived index, never\n * the source of truth. This store owns the on-disk representation:\n * schema, round-trip serialization, atomic writes, and the locks that keep\n * concurrent CLI/MCP clients from corrupting a plan or approving two active\n * plans in one namespace.\n */\n\nexport const PLAN_STATUSES = [\"draft\", \"approved\", \"executing\", \"complete\", \"abandoned\"] as const;\nexport type PlanStatus = (typeof PLAN_STATUSES)[number];\n\n/** A plan is \"active\" while approved or executing — at most one per namespace. */\nexport const ACTIVE_PLAN_STATUSES: readonly PlanStatus[] = [\"approved\", \"executing\"];\n\nconst plannedFileSchema = z.object({\n path: z.string().min(1),\n action: z.enum([\"create\", \"edit\", \"delete\"]),\n notes: z.string().default(\"\"),\n});\n\nconst plannedTestSchema = z.object({\n path: z.string().min(1),\n description: z.string().default(\"\"),\n});\n\nconst nullableDateTime = z\n .preprocess(\n (value) => (value instanceof Date ? value.toISOString() : value),\n z.string().datetime().nullable(),\n )\n .nullable();\n\nconst planFrontMatterSchema = z.object({\n schemaVersion: z.literal(1),\n id: z.string().regex(/^pln_[a-z0-9]+$/),\n namespace: z.string().min(1),\n type: z.literal(\"plan\"),\n title: z.string().min(1),\n status: z.enum(PLAN_STATUSES),\n brief: z.string(),\n filesToTouch: z.array(plannedFileSchema).default([]),\n testsToAdd: z.array(plannedTestSchema).default([]),\n outOfScope: z.array(z.string()).default([]),\n risks: z.array(z.string()).default([]),\n createdAt: z.preprocess(\n (value) => (value instanceof Date ? value.toISOString() : value),\n z.string().datetime(),\n ),\n createdByAgent: z.string().nullable(),\n approvedAt: nullableDateTime,\n executingAt: nullableDateTime,\n completedAt: nullableDateTime,\n abandonedAt: nullableDateTime,\n commitSha: z.string().nullable(),\n abandonReason: z.string().nullable(),\n});\n\nexport type PlannedFile = z.infer<typeof plannedFileSchema>;\nexport type PlannedTest = z.infer<typeof plannedTestSchema>;\nexport type PlanFrontMatter = z.infer<typeof planFrontMatterSchema>;\n\n/** A fully materialized plan: front matter + Markdown body + on-disk path. */\nexport type PlanSpec = PlanFrontMatter & {\n body: string;\n path: string;\n};\n\n/** Shape accepted by `writePlan` — path/schemaVersion/type are managed here. */\nexport type PlanWrite = Omit<PlanFrontMatter, \"schemaVersion\" | \"type\"> & {\n body: string;\n};\n\nexport type PlanLockOptions = {\n /** Max time to wait for the lock before failing. */\n timeoutMs?: number;\n /** A lock older than this is considered abandoned and stolen. */\n staleMs?: number;\n /** Poll interval while waiting. */\n pollMs?: number;\n};\n\nexport class PlanLockError extends Error {\n constructor(resource: string) {\n super(\n `Could not acquire lock for ${resource} within the timeout. Another client may be holding it.`,\n );\n this.name = \"PlanLockError\";\n }\n}\n\nexport class PlanValidationError extends Error {\n constructor(path: string, issues: string[]) {\n super(`Invalid plan file ${path}:\\n${issues.map((issue) => ` - ${issue}`).join(\"\\n\")}`);\n this.name = \"PlanValidationError\";\n }\n}\n\nconst DEFAULT_LOCK: Required<PlanLockOptions> = {\n timeoutMs: 5_000,\n staleMs: 30_000,\n pollMs: 50,\n};\n\nexport class PlanFileStore {\n readonly repositoryRoot: string;\n readonly plansDirectory: string;\n readonly locksDirectory: string;\n\n constructor(repositoryRoot = process.cwd()) {\n this.repositoryRoot = resolve(repositoryRoot);\n this.plansDirectory = join(this.repositoryRoot, \".codebuddy\", \"plans\");\n this.locksDirectory = join(this.plansDirectory, \".locks\");\n }\n\n // ── Read / write ────────────────────────────────────────────────────\n\n async writePlan(input: PlanWrite): Promise<string> {\n const path = this.planPath(input.id);\n await this.prepareDirectory(this.plansDirectory);\n await assertNoSymlinkBetween(this.repositoryRoot, dirname(path));\n\n const frontMatter = stringifyYaml({\n schemaVersion: 1,\n id: input.id,\n namespace: input.namespace,\n type: \"plan\",\n title: input.title,\n status: input.status,\n brief: input.brief,\n filesToTouch: input.filesToTouch,\n testsToAdd: input.testsToAdd,\n outOfScope: input.outOfScope,\n risks: input.risks,\n createdAt: input.createdAt,\n createdByAgent: input.createdByAgent,\n approvedAt: input.approvedAt,\n executingAt: input.executingAt,\n completedAt: input.completedAt,\n abandonedAt: input.abandonedAt,\n commitSha: input.commitSha,\n abandonReason: input.abandonReason,\n });\n\n await writeAtomic(path, composeMarkdown(frontMatter, input.body));\n return path;\n }\n\n async readPlan(pathOrId: string): Promise<PlanSpec> {\n const path = pathOrId.endsWith(\".md\") ? this.safePath(pathOrId) : this.planPath(pathOrId);\n await assertNoSymlinkBetween(this.repositoryRoot, path);\n const parsed = parseFrontMatter(await readFile(path, \"utf8\"));\n const result = planFrontMatterSchema.safeParse(parseYaml(parsed.frontMatter));\n if (!result.success) {\n throw new PlanValidationError(path, formatIssues(result.error));\n }\n return { ...result.data, body: parsed.content.trim(), path };\n }\n\n async listPlans(): Promise<PlanSpec[]> {\n try {\n await this.prepareDirectory(this.plansDirectory);\n const entries = await readdir(this.plansDirectory, { withFileTypes: true });\n const plans: PlanSpec[] = [];\n for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {\n // Plans are always written as `<pln_id>.md`. Ignore any other markdown\n // (hand-written notes, READMEs, build plans) so a shared plans dir with\n // non-plan files can't make discovery throw.\n if (!entry.isFile() || !entry.name.endsWith(\".md\")) continue;\n if (!/^pln_[a-z0-9]+\\.md$/.test(entry.name)) continue;\n plans.push(await this.readPlan(join(this.plansDirectory, entry.name)));\n }\n return plans;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return [];\n throw error;\n }\n }\n\n async deletePlan(id: string): Promise<void> {\n await rm(this.planPath(id), { force: true });\n }\n\n /**\n * The single approved-or-executing plan in `namespace`, or null. If the\n * filesystem somehow holds more than one (a hand edit, a crash mid-\n * transition), the earliest-created wins and the situation is the\n * caller's to reconcile.\n */\n async findActivePlan(namespace: string): Promise<PlanSpec | null> {\n const active = (await this.listPlans()).filter(\n (plan) => plan.namespace === namespace && ACTIVE_PLAN_STATUSES.includes(plan.status),\n );\n if (active.length === 0) return null;\n active.sort((left, right) => left.createdAt.localeCompare(right.createdAt));\n return active[0] ?? null;\n }\n\n // ── Locking ─────────────────────────────────────────────────────────\n\n /** Serialize amendments to a single plan. */\n async withPlanLock<T>(id: string, fn: () => Promise<T>, options?: PlanLockOptions): Promise<T> {\n this.assertPlanId(id);\n return this.withLock(`${id}.lock`, id, fn, options);\n }\n\n /**\n * Serialize lifecycle transitions across an entire namespace so two\n * clients cannot both promote a plan to active. Hold this around the\n * read-active-then-write window.\n */\n async withNamespaceLock<T>(\n namespace: string,\n fn: () => Promise<T>,\n options?: PlanLockOptions,\n ): Promise<T> {\n const safeName = namespace.replace(/[^a-zA-Z0-9_.:-]/g, \"-\");\n return this.withLock(`namespace_${safeName}.lock`, `namespace ${namespace}`, fn, options);\n }\n\n private async withLock<T>(\n lockFileName: string,\n resourceLabel: string,\n fn: () => Promise<T>,\n options?: PlanLockOptions,\n ): Promise<T> {\n const config = { ...DEFAULT_LOCK, ...options };\n await this.prepareDirectory(this.locksDirectory);\n const lockPath = join(this.locksDirectory, lockFileName);\n const deadline = Date.now() + config.timeoutMs;\n\n for (;;) {\n try {\n const handle = await open(lockPath, \"wx\", 0o600);\n await handle.writeFile(`${process.pid}\\n${new Date().toISOString()}\\n`, \"utf8\");\n await handle.close();\n break;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") throw error;\n if (await this.tryStealStaleLock(lockPath, config.staleMs)) continue;\n if (Date.now() >= deadline) throw new PlanLockError(resourceLabel);\n await delay(config.pollMs);\n }\n }\n\n try {\n return await fn();\n } finally {\n await releaseOwnedLock(lockPath);\n }\n }\n\n private async tryStealStaleLock(lockPath: string, staleMs: number): Promise<boolean> {\n try {\n const info = await stat(lockPath);\n if (Date.now() - info.mtimeMs > staleMs) {\n await rm(lockPath, { force: true });\n return true;\n }\n } catch (error) {\n // Lock vanished between EEXIST and stat — treat as free, retry.\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return true;\n throw error;\n }\n return false;\n }\n\n // ── Paths ───────────────────────────────────────────────────────────\n\n private planPath(id: string): string {\n this.assertPlanId(id);\n return this.safePath(join(this.plansDirectory, `${id}.md`));\n }\n\n private assertPlanId(id: string): void {\n if (!/^pln_[a-z0-9]+$/.test(id)) {\n throw new Error(`Invalid plan id: ${id}`);\n }\n }\n\n private safePath(path: string): string {\n const absolute = resolve(path);\n const relativePath = relative(this.repositoryRoot, absolute);\n if (relativePath === \"..\" || relativePath.startsWith(`..${sep}`) || relativePath === \"\") {\n throw new Error(`Plan path escapes repository root: ${path}`);\n }\n return absolute;\n }\n\n private async prepareDirectory(directory: string): Promise<void> {\n await assertNoSymlinkBetween(this.repositoryRoot, dirname(directory));\n await mkdir(directory, { recursive: true, mode: 0o700 });\n }\n}\n\nfunction formatIssues(error: z.ZodError): string[] {\n return error.issues.map((issue) => {\n const path = issue.path.length > 0 ? issue.path.join(\".\") : \"(root)\";\n return `${path}: ${issue.message}`;\n });\n}\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Delete `lockPath` only when it still belongs to this process. If a holder's\n * work ran past `staleMs`, another client may have stolen and re-created the\n * lock — deleting it unconditionally would release *their* critical section.\n */\nasync function releaseOwnedLock(lockPath: string): Promise<void> {\n try {\n const contents = await readFile(lockPath, \"utf8\");\n const ownerPid = Number.parseInt(contents.split(\"\\n\")[0] ?? \"\", 10);\n if (ownerPid === process.pid) {\n await rm(lockPath, { force: true });\n }\n } catch {\n // Lock already vanished (stolen then released) — nothing to release.\n }\n}\n","import { spawn } from \"node:child_process\";\nimport { realpath } from \"node:fs/promises\";\nimport { dirname, relative, resolve, sep } from \"node:path\";\nimport { readConfigFile } from \"../core/config-file.js\";\nimport { MemoryFileStore } from \"../core/memory-file-store.js\";\nimport { PlanFileStore } from \"../core/plan-file-store.js\";\nimport { RiskAssessor } from \"./assessor.js\";\nimport { createChurnSignal } from \"./signals/churn.js\";\nimport { createIncidentSignal } from \"./signals/incident.js\";\nimport { createPolicySignal } from \"./signals/policy.js\";\nimport type { Assessment, Signal } from \"./types.js\";\n\nexport type RiskAssessRequest = {\n repositoryRoot?: string;\n namespace: string;\n paths?: string[];\n planId?: string;\n useGit?: boolean;\n limit?: number;\n signals?: Signal[];\n};\n\nexport async function assessRisk(input: RiskAssessRequest): Promise<Assessment> {\n const repositoryRoot = resolve(input.repositoryRoot ?? process.cwd());\n const paths = await resolveRiskPaths({\n repositoryRoot,\n ...(input.planId !== undefined ? { planId: input.planId } : {}),\n ...(input.paths !== undefined ? { paths: input.paths } : {}),\n ...(input.useGit !== undefined ? { useGit: input.useGit } : {}),\n });\n if (paths.length === 0) {\n return {\n items: [],\n stats: { pathsConsidered: 0, itemsProduced: 0, signalsRun: 0, perSignal: [] },\n };\n }\n\n const memoryStore = new MemoryFileStore(repositoryRoot);\n const churn = (await readConfigFile(repositoryRoot).catch(() => ({ risk: undefined }))).risk;\n const signals = input.signals ?? [\n createIncidentSignal({ store: memoryStore }),\n createPolicySignal({ repositoryRoot }),\n ...(input.useGit === false\n ? []\n : [\n createChurnSignal({\n repositoryRoot,\n ...(churn?.churnWindowDays !== undefined ? { windowDays: churn.churnWindowDays } : {}),\n ...(churn?.churnMode !== undefined ? { mode: churn.churnMode } : {}),\n }),\n ]),\n ];\n\n const assessment = await new RiskAssessor(signals).assess({\n paths,\n repositoryRoot,\n namespace: input.namespace,\n });\n return {\n ...assessment,\n items: input.limit ? assessment.items.slice(0, input.limit) : assessment.items,\n };\n}\n\nexport async function resolveRiskPaths(input: {\n repositoryRoot: string;\n paths?: string[];\n planId?: string;\n useGit?: boolean;\n}): Promise<string[]> {\n const paths = new Set<string>();\n for (const path of input.paths ?? []) {\n if (!path.trim()) continue;\n // Containment guard: tool callers can pass arbitrary path strings, and a\n // `../`-style escape must never flow into file reads downstream\n // (computeTargetSymbols, savings fallbacks, etc.). Kept paths are\n // rewritten to their resolved repo-relative POSIX form.\n const contained = containedRelativePath(input.repositoryRoot, path);\n if (contained) paths.add(contained);\n }\n\n if (input.planId) {\n const plan = await new PlanFileStore(input.repositoryRoot).readPlan(input.planId);\n for (const file of plan.filesToTouch) {\n const contained = containedRelativePath(input.repositoryRoot, file.path);\n if (contained) paths.add(contained);\n }\n }\n\n if (input.useGit !== false && (input.useGit || paths.size === 0)) {\n for (const path of await changedGitPaths(input.repositoryRoot)) {\n const contained = containedRelativePath(input.repositoryRoot, path);\n if (contained) paths.add(contained);\n }\n }\n\n const realRoot = await realpath(input.repositoryRoot).catch(() => resolve(input.repositoryRoot));\n const inside = await Promise.all(\n [...paths].map((path) => realPathInside(realRoot, resolve(input.repositoryRoot, path))),\n );\n const resolved = [...paths].filter((_, index) => inside[index]).sort();\n // Bound the change set so one huge branch cannot blow any payload derived\n // from it. Sorted above, so the cap keeps the lexicographically-first paths.\n return resolved.length > MAX_RESOLVED_PATHS ? resolved.slice(0, MAX_RESOLVED_PATHS) : resolved;\n}\n\n/** Hard cap on resolved target paths per assessment/context call. */\nexport const MAX_RESOLVED_PATHS = 200;\n\n/**\n * Resolve `path` against `root`; return its repo-relative POSIX form when it\n * stays inside the repository, or null when it escapes (or is empty).\n * Rejects NUL bytes and absolute paths pointing outside the root.\n */\n/**\n * Repo-relative POSIX form of `path` when it stays inside `root` both by name\n * and through symlinks; null when it escapes. Shared by risk targets and plans.\n */\nexport async function containedRepoPath(root: string, path: string): Promise<string | null> {\n const contained = containedRelativePath(root, path);\n if (contained === null) return null;\n const realRoot = await realpath(root).catch(() => resolve(root));\n return (await realPathInside(realRoot, resolve(root, contained))) ? contained : null;\n}\n\n/**\n * A path that stays inside the repository by name can still leave it through\n * a symlink (`docs/k -> ~/.ssh`); downstream reads must never follow it out.\n * A deleted or not-yet-created file is judged by its nearest existing parent.\n */\nasync function realPathInside(realRoot: string, absolute: string): Promise<boolean> {\n for (let current = absolute; ; current = dirname(current)) {\n const real = await realpath(current).catch(() => null);\n if (real !== null) return real === realRoot || real.startsWith(`${realRoot}${sep}`);\n if (dirname(current) === current) return false;\n }\n}\n\nfunction containedRelativePath(root: string, path: string): string | null {\n const trimmed = normalizePath(path);\n if (!trimmed || trimmed.includes(\"\\0\")) return null;\n const absolute = resolve(root, trimmed);\n const relativePath = relative(resolve(root), absolute).split(sep).join(\"/\");\n if (relativePath === \"\" || relativePath === \"..\" || relativePath.startsWith(\"../\")) return null;\n return relativePath;\n}\n\nasync function changedGitPaths(repositoryRoot: string): Promise<string[]> {\n const [tracked, untracked] = await Promise.all([\n // `-z`: NUL-separated, unquoted names (non-ASCII, quotes, tabs, newlines).\n runGit(repositoryRoot, [\"diff\", \"--name-only\", \"-z\", \"HEAD\"]),\n runGit(repositoryRoot, [\"ls-files\", \"-z\", \"--others\", \"--exclude-standard\"]),\n ]);\n return (\n [...tracked.stdout.split(\"\\0\"), ...untracked.stdout.split(\"\\0\")]\n // Hidden paths are never code under change: CodeBuddy's own memory and\n // caches (.codebuddy/), .DS_Store, editor/agent config (.claude/), tool\n // indexes and .env files. As targets they add noise, secrets and a\n // `git log` each.\n .filter((path) => path && !path.split(\"/\").some((segment) => segment.startsWith(\".\")))\n );\n}\n\nfunction runGit(\n cwd: string,\n args: string[],\n): Promise<{ code: number; stdout: string; stderr: string }> {\n return new Promise((resolveResult, reject) => {\n const child = spawn(\"git\", args, { cwd, stdio: [\"ignore\", \"pipe\", \"pipe\"] });\n let stdout = \"\";\n let stderr = \"\";\n child.stdout.setEncoding(\"utf8\");\n child.stdout.on(\"data\", (chunk) => {\n stdout += String(chunk);\n });\n child.stderr.on(\"data\", (chunk) => {\n stderr += String(chunk);\n });\n child.on(\"error\", reject);\n child.on(\"close\", (code) => resolveResult({ code: code ?? 0, stdout, stderr }));\n });\n}\n\n/** POSIX form; a backslash is a separator only on Windows, elsewhere part of the name. */\nfunction normalizePath(path: string): string {\n return (sep === \"\\\\\" ? path.replace(/\\\\/g, \"/\") : path).replace(/^\\.\\//, \"\");\n}\n","import type {\n Assessment,\n AssessmentInput,\n Evidence,\n RiskCategory,\n RiskItem,\n Signal,\n SignalContribution,\n SignalStat,\n} from \"./types.js\";\n\nexport type AssessorOptions = {\n /** Items scoring below this are dropped from the result. Default 0. */\n minScore?: number;\n};\n\ntype ContributionWithSignal = {\n signal: Signal;\n contribution: SignalContribution;\n};\n\n/**\n * Runs every enabled signal in parallel and folds their per-path\n * contributions into a single ranked list. Scoring is deterministic: the\n * same inputs and the same cache state always produce the same output, with\n * stable tie-breaking.\n */\nexport class RiskAssessor {\n private readonly signals: Signal[];\n private readonly minScore: number;\n\n constructor(signals: Signal[], options: AssessorOptions = {}) {\n this.signals = signals;\n this.minScore = options.minScore ?? 0;\n }\n\n async assess(input: AssessmentInput): Promise<Assessment> {\n const enabled = this.signals.filter((signal) => signal.enabled);\n\n const settled = await Promise.all(\n enabled.map(async (signal) => ({\n signal,\n contributions: await signal.assess(input),\n })),\n );\n\n // Group contributions by path, remembering which signal produced each.\n const byPath = new Map<string, ContributionWithSignal[]>();\n const perSignal = new Map<string, SignalStat>();\n\n for (const { signal, contributions } of settled) {\n const stat: SignalStat = perSignal.get(signal.id) ?? {\n id: signal.id,\n category: signal.category,\n contributions: 0,\n totalWeight: 0,\n };\n for (const contribution of contributions) {\n // A signal that returns no evidence for a path does not get to vote —\n // the normalization only counts signals that actually have something\n // to say. This keeps a silent signal from diluting a real one.\n if (contribution.evidence.length === 0) continue;\n const list = byPath.get(contribution.path) ?? [];\n list.push({ signal, contribution });\n byPath.set(contribution.path, list);\n stat.contributions += 1;\n stat.totalWeight += contribution.weight;\n }\n perSignal.set(signal.id, stat);\n }\n\n const items: RiskItem[] = [];\n for (const [path, contributions] of byPath) {\n items.push(this.fold(path, contributions));\n }\n\n const ranked = items.filter((item) => item.score >= this.minScore).sort(compareRiskItems);\n\n return {\n items: ranked,\n stats: {\n pathsConsidered: input.paths.length,\n itemsProduced: ranked.length,\n signalsRun: enabled.length,\n perSignal: [...perSignal.values()].sort((a, b) => a.id.localeCompare(b.id)),\n },\n };\n }\n\n /** Fold all contributions for one path into a single RiskItem. */\n private fold(path: string, contributions: ContributionWithSignal[]): RiskItem {\n let weightedSum = 0;\n let coefficientSum = 0;\n let dominant: ContributionWithSignal | null = null;\n const evidence: Evidence[] = [];\n const contributingSignals: string[] = [];\n\n for (const entry of contributions) {\n const coefficient = entry.signal.coefficient;\n weightedSum += entry.contribution.weight * coefficient;\n coefficientSum += coefficient;\n evidence.push(...entry.contribution.evidence);\n contributingSignals.push(entry.signal.id);\n if (!dominant || dominantWeight(entry) > dominantWeight(dominant)) {\n dominant = entry;\n }\n }\n\n // Normalize only over the signals that contributed, so a path is not\n // punished for the signals that stayed silent about it.\n const score = coefficientSum === 0 ? 0 : clip(weightedSum / coefficientSum, 0, 100);\n const category: RiskCategory = dominant?.signal.category ?? \"policy\";\n const reason = dominant?.contribution.reason ?? \"\";\n\n return {\n path,\n score: round2(score),\n category,\n reason,\n contributingSignals: contributingSignals.sort(),\n evidence,\n };\n }\n}\n\nfunction dominantWeight(entry: ContributionWithSignal): number {\n return entry.contribution.weight * entry.signal.coefficient;\n}\n\n/** Deterministic ordering: score desc, then more signals, then path asc. */\nfunction compareRiskItems(a: RiskItem, b: RiskItem): number {\n if (b.score !== a.score) return b.score - a.score;\n if (b.contributingSignals.length !== a.contributingSignals.length) {\n return b.contributingSignals.length - a.contributingSignals.length;\n }\n return a.path.localeCompare(b.path);\n}\n\nfunction clip(value: number, low: number, high: number): number {\n return Math.min(high, Math.max(low, value));\n}\n\nfunction round2(value: number): number {\n return Math.round(value * 100) / 100;\n}\n","import { spawn } from \"node:child_process\";\nimport { readFile, realpath } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport type { Signal, SignalContribution } from \"../types.js\";\n\n/**\n * `window` (default): commits, authors and reverts in the last `windowDays`.\n * `lifetime-size`: log-scaled commit count over all history plus log-scaled\n * line count. On a time-split benchmark (later bug-fix commits) the 30-day\n * window scored AUC 0.518, lifetime churn 0.791 and line count 0.834\n * (`scripts/eval-churn-split.mts` reproduces the comparison).\n */\nexport type ChurnMode = \"window\" | \"lifetime-size\";\n\nexport type ChurnSignalOptions = {\n repositoryRoot: string;\n enabled?: boolean;\n coefficient?: number;\n /** Explicit git `--since` value; overrides `windowDays`. */\n since?: string;\n /** Window for `window` mode, in days (default 30). */\n windowDays?: number;\n mode?: ChurnMode;\n /**\n * Score as of this date: only commits before it, and (lifetime-size) file\n * sizes at the last such commit. For time-split evaluation; default now.\n */\n asOf?: string | Date;\n};\n\ntype CommitRecord = {\n sha: string;\n author: string;\n ts: string;\n message: string;\n};\n\nconst GIT_LOG_CONCURRENCY = 4;\nconst DAY_MS = 86_400_000;\n\nexport function createChurnSignal(options: ChurnSignalOptions): Signal {\n return {\n id: \"git-churn\",\n category: \"churn\",\n enabled: options.enabled ?? true,\n coefficient: options.coefficient ?? 0.7,\n async assess(input) {\n // Churn is only meaningful at the repository root. Check it once per\n // assessment, not once per path: it was half of every git spawn (#45).\n const root = await runGit(options.repositoryRoot, [\"rev-parse\", \"--show-toplevel\"]);\n // git prints the symlink-resolved top level (macOS /var -> /private/var).\n const expected = await realpath(options.repositoryRoot).catch(() =>\n resolve(options.repositoryRoot),\n );\n if (root.code !== 0 || resolve(root.stdout.trim()) !== expected) {\n return [];\n }\n const lifetime = options.mode === \"lifetime-size\";\n const asOf = options.asOf === undefined ? undefined : new Date(options.asOf);\n const end = asOf ?? new Date();\n const range = [\n ...(lifetime\n ? []\n : [\n `--since=${options.since ?? new Date(end.getTime() - (options.windowDays ?? 30) * DAY_MS).toISOString()}`,\n ]),\n ...(asOf ? [`--until=${asOf.toISOString()}`] : []),\n ];\n // Sizes as of the cutoff come from the last commit before it.\n const revision =\n lifetime && asOf\n ? (\n await runGit(options.repositoryRoot, [\n \"rev-list\",\n \"-1\",\n `--before=${asOf.toISOString()}`,\n \"HEAD\",\n ])\n ).stdout.trim()\n : null;\n // `git log --follow` takes one path: run a few at a time, kept in path order.\n const logs: CommitRecord[][] = [];\n const sizes: number[] = [];\n for (let start = 0; start < input.paths.length; start += GIT_LOG_CONCURRENCY) {\n const batch = input.paths.slice(start, start + GIT_LOG_CONCURRENCY);\n logs.push(\n ...(await Promise.all(\n batch.map((path) => gitLogForPath(options.repositoryRoot, path, range)),\n )),\n );\n if (lifetime) {\n sizes.push(\n ...(await Promise.all(\n batch.map((path) => lineCount(options.repositoryRoot, path, revision)),\n )),\n );\n }\n }\n const contributions: SignalContribution[] = [];\n for (const [index, path] of input.paths.entries()) {\n const commits = logs[index] ?? [];\n if (commits.length === 0) continue;\n if (lifetime) {\n const lines = sizes[index] ?? 0;\n contributions.push({\n path,\n // ponytail: hand-picked coefficients; fit them on the time-split eval before defaulting on.\n weight: Math.min(\n 100,\n Math.round(8 * Math.log2(1 + commits.length) + 4 * Math.log2(1 + lines)),\n ),\n reason: `${path} has ${commits.length} commit${commits.length === 1 ? \"\" : \"s\"}, ${lines} line${lines === 1 ? \"\" : \"s\"} (lifetime churn and size).`,\n evidence: evidenceOf(commits),\n });\n continue;\n }\n const authors = new Set(commits.map((commit) => commit.author));\n const reverts = commits.filter((commit) => /revert|rollback|backout/i.test(commit.message));\n const weight = Math.min(100, commits.length * 8 + authors.size * 12 + reverts.length * 20);\n contributions.push({\n path,\n weight,\n reason: `${path} changed ${commits.length} time${commits.length === 1 ? \"\" : \"s\"} in the recent git history by ${authors.size} author${authors.size === 1 ? \"\" : \"s\"}.`,\n evidence: evidenceOf(commits),\n });\n }\n return contributions;\n },\n };\n}\n\nfunction evidenceOf(commits: CommitRecord[]) {\n return commits.slice(0, 5).map((commit) => ({\n kind: \"git_commit\" as const,\n sha: commit.sha,\n message: commit.message,\n ts: commit.ts,\n }));\n}\n\n/** Lines in `path` at `revision`, or in the working tree when null; 0 when absent. */\nasync function lineCount(\n repositoryRoot: string,\n path: string,\n revision: string | null,\n): Promise<number> {\n let text = \"\";\n if (revision === null) {\n text = await readFile(resolve(repositoryRoot, path), \"utf8\").catch(() => \"\");\n } else if (revision) {\n const shown = await runGit(repositoryRoot, [\"show\", `${revision}:${path}`]);\n if (shown.code === 0) text = shown.stdout;\n }\n if (text.length === 0) return 0;\n return text.split(\"\\n\").length - (text.endsWith(\"\\n\") ? 1 : 0);\n}\n\nasync function gitLogForPath(\n repositoryRoot: string,\n path: string,\n range: string[],\n): Promise<CommitRecord[]> {\n const result = await runGit(repositoryRoot, [\n \"log\",\n \"--follow\",\n \"--max-count=1000\",\n ...range,\n \"--format=%H%x1f%an%x1f%cI%x1f%s%x1e\",\n \"--\",\n path,\n ]);\n if (result.code !== 0 || result.stdout.trim().length === 0) return [];\n return result.stdout\n .split(\"\\x1e\")\n .map((record) => record.trim())\n .filter(Boolean)\n .map((record) => {\n const [sha = \"\", author = \"\", ts = \"\", message = \"\"] = record.split(\"\\x1f\");\n return { sha, author, ts, message };\n })\n .filter((record) => record.sha.length > 0);\n}\n\nfunction runGit(\n cwd: string,\n args: string[],\n): Promise<{ code: number; stdout: string; stderr: string }> {\n return new Promise((resolve, reject) => {\n const child = spawn(\"git\", args, { cwd, stdio: [\"ignore\", \"pipe\", \"pipe\"] });\n let stdout = \"\";\n let stderr = \"\";\n child.stdout.on(\"data\", (chunk) => {\n stdout += String(chunk);\n });\n child.stderr.on(\"data\", (chunk) => {\n stderr += String(chunk);\n });\n child.on(\"error\", reject);\n child.on(\"close\", (code) => resolve({ code: code ?? 0, stdout, stderr }));\n });\n}\n","import type { IncidentSeverity, MemoryFileStore } from \"../../core/memory-file-store.js\";\nimport type { Signal, SignalContribution } from \"../types.js\";\n\nexport type IncidentSignalOptions = {\n store: MemoryFileStore;\n enabled?: boolean;\n coefficient?: number;\n includeResolved?: boolean;\n};\n\n/**\n * Historical incident signal (Proposal 03.2/03.5 foundation). It reads\n * structured incident metadata from Markdown facts and produces one\n * evidence-backed contribution per affected path.\n */\nexport function createIncidentSignal(options: IncidentSignalOptions): Signal {\n return {\n id: \"incident-memory\",\n category: \"incident\",\n enabled: options.enabled ?? true,\n coefficient: options.coefficient ?? 1.2,\n async assess(input) {\n const incidents = await options.store.findIncidentFactsForPaths({\n namespace: input.namespace,\n paths: input.paths,\n includeResolved: options.includeResolved ?? false,\n });\n\n const byPath = new Map<string, SignalContribution>();\n for (const incident of incidents) {\n for (const path of input.paths) {\n if (!incident.paths.map(normalizePath).includes(normalizePath(path))) continue;\n const existing = byPath.get(path);\n const evidence = {\n kind: \"memory_fact\" as const,\n factId: incident.id,\n content: incident.content,\n createdAt: incident.createdAt,\n };\n if (!existing) {\n byPath.set(path, {\n path,\n weight: severityWeight(incident.severity),\n reason: `This file is linked to prior ${incident.severity} incident memory.`,\n evidence: [evidence],\n });\n continue;\n }\n existing.weight = Math.max(existing.weight, severityWeight(incident.severity));\n existing.reason = `This file is linked to ${existing.evidence.length + 1} prior incident memories.`;\n existing.evidence.push(evidence);\n }\n }\n\n return [...byPath.values()];\n },\n };\n}\n\nfunction normalizePath(path: string): string {\n return path.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\");\n}\n\nfunction severityWeight(severity: IncidentSeverity): number {\n switch (severity) {\n case \"critical\":\n return 95;\n case \"high\":\n return 80;\n case \"medium\":\n return 55;\n case \"low\":\n return 30;\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { parse as parseYaml } from \"yaml\";\nimport { z } from \"zod\";\nimport type { Signal, SignalContribution } from \"../types.js\";\n\nconst policyRuleSchema = z.object({\n id: z.string().min(1),\n pattern: z.string().min(1),\n message: z.string().min(1).optional(),\n reason: z.string().min(1).optional(),\n weight: z.number().min(0).max(100).default(50),\n});\n\nconst policyFileSchema = z.object({\n rules: z.array(policyRuleSchema).default([]),\n});\n\nexport type PolicyRule = z.infer<typeof policyRuleSchema>;\nexport type PolicyFile = z.infer<typeof policyFileSchema>;\n\nexport type PolicySignalOptions = {\n repositoryRoot: string;\n enabled?: boolean;\n coefficient?: number;\n policyPath?: string;\n};\n\nexport function createPolicySignal(options: PolicySignalOptions): Signal {\n return {\n id: \"policy\",\n category: \"policy\",\n enabled: options.enabled ?? true,\n coefficient: options.coefficient ?? 1,\n async assess(input) {\n const policy = await readPolicyFile(\n options.policyPath ?? join(options.repositoryRoot, \".codebuddy\", \"policies.yaml\"),\n );\n if (policy.rules.length === 0) return [];\n\n const byPath = new Map<string, SignalContribution>();\n for (const path of input.paths) {\n for (const rule of policy.rules) {\n if (!matchesPolicyGlob(path, rule.pattern)) continue;\n const existing = byPath.get(path);\n const evidence = { kind: \"policy_rule\" as const, ruleId: rule.id, pattern: rule.pattern };\n const reason = rule.message ?? rule.reason ?? `Policy rule ${rule.id} matched ${path}.`;\n if (!existing) {\n byPath.set(path, {\n path,\n weight: rule.weight,\n reason,\n evidence: [evidence],\n });\n continue;\n }\n existing.weight = Math.max(existing.weight, rule.weight);\n existing.evidence.push(evidence);\n if (rule.weight >= existing.weight) existing.reason = reason;\n }\n }\n return [...byPath.values()];\n },\n };\n}\n\nexport async function readPolicyFile(path: string): Promise<PolicyFile> {\n try {\n const raw = await readFile(path, \"utf8\");\n return policyFileSchema.parse(parseYaml(raw) ?? {});\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return { rules: [] };\n throw error;\n }\n}\n\n/** Match a repo-relative path against a simple `*` / `**` glob pattern. */\nexport function matchesPolicyGlob(path: string, glob: string): boolean {\n const normalizedPath = normalize(path);\n const normalizedGlob = normalize(glob);\n const pattern = normalizedGlob\n .split(\"**\")\n .map((part) => part.split(\"*\").map(escapeRegExp).join(\"[^/]*\"))\n .join(\".*\");\n return new RegExp(`^${pattern}$`).test(normalizedPath);\n}\n\nfunction normalize(path: string): string {\n return path.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\");\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[|\\\\{}()[\\]^$+?.]/g, \"\\\\$&\");\n}\n","import { containedRepoPath } from \"../risk/service.js\";\nimport { generateEntityId } from \"./ids.js\";\nimport {\n ACTIVE_PLAN_STATUSES,\n type PlanFileStore,\n type PlannedFile,\n type PlannedTest,\n type PlanSpec,\n type PlanStatus,\n} from \"./plan-file-store.js\";\n\n/**\n * The plan lifecycle service enforces the state machine on top of the\n * file store. The store knows how to read/write/lock; this service knows\n * which transitions are legal and guarantees that at most one plan in a\n * namespace is active at a time. Transitions that change active state run\n * under the namespace lock; amendments run under the per-plan lock.\n */\n\n/** Legal transitions. Terminal states (complete, abandoned) have none. */\nconst TRANSITIONS: Record<PlanStatus, readonly PlanStatus[]> = {\n draft: [\"approved\", \"abandoned\"],\n approved: [\"executing\", \"abandoned\"],\n executing: [\"complete\", \"abandoned\"],\n complete: [],\n abandoned: [],\n};\n\n/** Only these states accept content amendments. */\nconst AMENDABLE: readonly PlanStatus[] = [\"draft\", \"executing\"];\n\nexport class PlanTransitionError extends Error {\n constructor(from: PlanStatus, to: PlanStatus) {\n super(`Illegal plan transition: ${from} → ${to}.`);\n this.name = \"PlanTransitionError\";\n }\n}\n\nexport class PlanNotFoundError extends Error {\n constructor(id: string) {\n super(`Plan ${id} not found.`);\n this.name = \"PlanNotFoundError\";\n }\n}\n\nexport class ActivePlanExistsError extends Error {\n readonly activePlanId: string;\n constructor(namespace: string, activePlanId: string) {\n super(\n `Namespace \"${namespace}\" already has an active plan (${activePlanId}). ` +\n `Complete or abandon it before approving another.`,\n );\n this.name = \"ActivePlanExistsError\";\n this.activePlanId = activePlanId;\n }\n}\n\nexport type CreatePlanInput = {\n namespace: string;\n title: string;\n brief: string;\n body?: string;\n filesToTouch?: PlannedFile[];\n testsToAdd?: PlannedTest[];\n outOfScope?: string[];\n risks?: string[];\n createdByAgent?: string | null;\n now?: string;\n};\n\nexport type AmendPlanPatch = {\n title?: string;\n brief?: string;\n body?: string;\n filesToTouch?: PlannedFile[];\n testsToAdd?: PlannedTest[];\n outOfScope?: string[];\n risks?: string[];\n};\n\nexport type CompleteOptions = { commitSha?: string; notes?: string };\nexport type AbandonOptions = { reason?: string };\n\nconst DEFAULT_BODY = [\n \"# Goal\",\n \"\",\n \"(what this plan achieves)\",\n \"\",\n \"# Approach\",\n \"\",\n \"(ordered steps)\",\n \"\",\n \"# Notes\",\n \"\",\n \"(freeform; ignored by tooling)\",\n].join(\"\\n\");\n\nexport class PlanLifecycle {\n private readonly store: PlanFileStore;\n\n constructor(store: PlanFileStore) {\n this.store = store;\n }\n\n async create(input: CreatePlanInput): Promise<PlanSpec> {\n await this.assertPathsInside(input);\n const id = generateEntityId(\"pln\");\n const now = input.now ?? new Date().toISOString();\n await this.store.writePlan({\n id,\n namespace: input.namespace,\n title: input.title,\n status: \"draft\",\n brief: input.brief,\n filesToTouch: input.filesToTouch ?? [],\n testsToAdd: input.testsToAdd ?? [],\n outOfScope: input.outOfScope ?? [],\n risks: input.risks ?? [],\n createdAt: now,\n createdByAgent: input.createdByAgent ?? null,\n approvedAt: null,\n executingAt: null,\n completedAt: null,\n abandonedAt: null,\n commitSha: null,\n abandonReason: null,\n body: input.body ?? DEFAULT_BODY,\n });\n return this.store.readPlan(id);\n }\n\n async approve(id: string, now = new Date().toISOString()): Promise<PlanSpec> {\n const current = await this.require(id);\n // The active-plan guard and the write must be atomic across the\n // namespace, otherwise two approvals could both observe \"no active plan\".\n return this.store.withNamespaceLock(current.namespace, async () => {\n const fresh = await this.require(id);\n this.assertTransition(fresh.status, \"approved\");\n const active = await this.store.findActivePlan(fresh.namespace);\n if (active && active.id !== id) {\n throw new ActivePlanExistsError(fresh.namespace, active.id);\n }\n return this.rewrite(fresh, { status: \"approved\", approvedAt: now });\n });\n }\n\n async start(id: string, now = new Date().toISOString()): Promise<PlanSpec> {\n const current = await this.require(id);\n return this.store.withNamespaceLock(current.namespace, async () => {\n const fresh = await this.require(id);\n this.assertTransition(fresh.status, \"executing\");\n return this.rewrite(fresh, { status: \"executing\", executingAt: now });\n });\n }\n\n async complete(\n id: string,\n options: CompleteOptions = {},\n now = new Date().toISOString(),\n ): Promise<PlanSpec> {\n const current = await this.require(id);\n return this.store.withNamespaceLock(current.namespace, async () => {\n const fresh = await this.require(id);\n this.assertTransition(fresh.status, \"complete\");\n return this.rewrite(fresh, {\n status: \"complete\",\n completedAt: now,\n ...(options.commitSha !== undefined ? { commitSha: options.commitSha } : {}),\n });\n });\n }\n\n async abandon(\n id: string,\n options: AbandonOptions = {},\n now = new Date().toISOString(),\n ): Promise<PlanSpec> {\n const current = await this.require(id);\n return this.store.withNamespaceLock(current.namespace, async () => {\n const fresh = await this.require(id);\n this.assertTransition(fresh.status, \"abandoned\");\n return this.rewrite(fresh, {\n status: \"abandoned\",\n abandonedAt: now,\n ...(options.reason !== undefined ? { abandonReason: options.reason } : {}),\n });\n });\n }\n\n async amend(id: string, patch: AmendPlanPatch): Promise<PlanSpec> {\n // Amend takes the NAMESPACE lock, like every lifecycle transition. The\n // per-plan lock alone let an amend interleave with e.g. abandon():\n // amend reads `draft` -> abandon writes `abandoned` -> amend writes back\n // its stale full snapshot, resurrecting the plan as `draft`. One shared\n // mutex makes read-check-write atomic across all mutators.\n await this.assertPathsInside(patch);\n const current = await this.require(id);\n return this.store.withNamespaceLock(current.namespace, async () => {\n const fresh = await this.require(id);\n if (!AMENDABLE.includes(fresh.status)) {\n throw new Error(\n `Plan ${id} is ${fresh.status}; only draft or executing plans can be amended.`,\n );\n }\n return this.rewrite(fresh, {\n ...(patch.title !== undefined ? { title: patch.title } : {}),\n ...(patch.brief !== undefined ? { brief: patch.brief } : {}),\n ...(patch.filesToTouch !== undefined ? { filesToTouch: patch.filesToTouch } : {}),\n ...(patch.testsToAdd !== undefined ? { testsToAdd: patch.testsToAdd } : {}),\n ...(patch.outOfScope !== undefined ? { outOfScope: patch.outOfScope } : {}),\n ...(patch.risks !== undefined ? { risks: patch.risks } : {}),\n ...(patch.body !== undefined ? { body: patch.body } : {}),\n });\n });\n }\n\n /** Plan paths flow into risk, context and file reads; none may leave the repository. */\n private async assertPathsInside(input: {\n filesToTouch?: PlannedFile[] | undefined;\n testsToAdd?: PlannedTest[] | undefined;\n }): Promise<void> {\n for (const { path } of [...(input.filesToTouch ?? []), ...(input.testsToAdd ?? [])]) {\n if ((await containedRepoPath(this.store.repositoryRoot, path)) === null) {\n throw new Error(`Plan path is outside the repository: ${path}`);\n }\n }\n }\n\n async current(namespace: string): Promise<PlanSpec | null> {\n return this.store.findActivePlan(namespace);\n }\n\n private assertTransition(from: PlanStatus, to: PlanStatus): void {\n if (!TRANSITIONS[from].includes(to)) {\n throw new PlanTransitionError(from, to);\n }\n }\n\n private async require(id: string): Promise<PlanSpec> {\n try {\n return await this.store.readPlan(id);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n throw new PlanNotFoundError(id);\n }\n throw error;\n }\n }\n\n /** Rewrite the plan file with a partial set of changed fields. */\n private async rewrite(plan: PlanSpec, changes: Partial<PlanSpec>): Promise<PlanSpec> {\n const next = { ...plan, ...changes };\n await this.store.writePlan({\n id: next.id,\n namespace: next.namespace,\n title: next.title,\n status: next.status,\n brief: next.brief,\n filesToTouch: next.filesToTouch,\n testsToAdd: next.testsToAdd,\n outOfScope: next.outOfScope,\n risks: next.risks,\n createdAt: next.createdAt,\n createdByAgent: next.createdByAgent,\n approvedAt: next.approvedAt,\n executingAt: next.executingAt,\n completedAt: next.completedAt,\n abandonedAt: next.abandonedAt,\n commitSha: next.commitSha,\n abandonReason: next.abandonReason,\n body: next.body,\n });\n return this.store.readPlan(next.id);\n }\n}\n\nexport { ACTIVE_PLAN_STATUSES };\n","import { createHash } from \"node:crypto\";\nimport { mkdir, readdir, readFile } from \"node:fs/promises\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { z } from \"zod\";\nimport { compareFreshness, fileHashes, repoIdentity } from \"../core/freshness.js\";\nimport { generateEntityId } from \"../core/ids.js\";\nimport {\n assertNoSymlinkBetween,\n composeMarkdown,\n parseFrontMatter,\n writeAtomic,\n} from \"../core/markdown-store-fs.js\";\nimport { scanSensitive } from \"../core/sensitive.js\";\n\n/**\n * The worklog is a chronological record of completed turns — what was done,\n * which files, what memory it produced, how it was verified — so a fresh chat\n * can pick up prior work without the transcript. It is a timeline, not project\n * truth: durable facts stay in `.codebuddy/memory/` and the working tree stays\n * authoritative, so every recalled entry carries a freshness check against the\n * current files. Entries are bounded Markdown under `.codebuddy/worklog/`; raw\n * transcripts are never stored and sensitive summaries are redacted.\n */\n\nconst LIMITS = {\n summaryChars: 600,\n files: 50,\n verification: 10,\n verificationChars: 200,\n} as const;\n\nconst REDACTED = \"[REDACTED SENSITIVE CONTENT]\";\n\nconst entrySchema = z.object({\n schemaVersion: z.literal(1),\n id: z.string().regex(/^wlg_[a-z0-9]+$/),\n namespace: z.string().min(1),\n createdAt: z.string(),\n sourceSessionId: z.string().nullable().default(null),\n sourcePlanId: z.string().nullable().default(null),\n commitSha: z.string().nullable().default(null),\n agentId: z.string().nullable().default(null),\n files: z.array(z.string()).default([]),\n verification: z.array(z.string()).default([]),\n savedMemory: z.array(z.string()).default([]),\n queuedForReview: z.array(z.string()).default([]),\n fingerprint: z.string().regex(/^[a-f0-9]{64}$/),\n /** Content hash per file when recorded (absent in entries written before 2.10). */\n fileHashes: z.record(z.string(), z.string().nullable()).optional(),\n branch: z.string().nullable().optional(),\n});\n\nexport type WorklogEntry = z.infer<typeof entrySchema> & { summary: string; path: string };\n\nexport type WorklogRecordInput = {\n namespace: string;\n summary: string;\n files?: string[];\n verification?: string[];\n savedMemory?: string[];\n queuedForReview?: string[];\n sessionId?: string;\n planId?: string;\n commitSha?: string;\n agentId?: string;\n};\n\n/** A worklog entry as recalled into context, with freshness against the working tree. */\nexport type HandoffSummary = {\n id: string;\n createdAt: string;\n ageDays: number;\n summary: string;\n files: string[];\n verification: string[];\n savedMemory: string[];\n /** Recorded files whose content differs from when the entry was written. */\n changedSince: string[];\n /** Recorded files that no longer exist. */\n missing: string[];\n /** Recorded without a content hash (older entries): freshness cannot be told. */\n unknown: string[];\n reason: string;\n};\n\nexport class WorklogStore {\n readonly repositoryRoot: string;\n readonly directory: string;\n\n constructor(repositoryRoot = process.cwd()) {\n this.repositoryRoot = resolve(repositoryRoot);\n this.directory = join(this.repositoryRoot, \".codebuddy\", \"worklog\");\n }\n\n /**\n * Record one entry for a completed turn. A retry of the same turn (same\n * namespace, session, summary and files) returns the existing id instead of\n * writing a duplicate.\n */\n async record(input: WorklogRecordInput, now = new Date()): Promise<string> {\n const files = [...new Set((input.files ?? []).map(normalizePath))]\n .filter(Boolean)\n .sort()\n .slice(0, LIMITS.files);\n const summary = boundSummary(input.summary, files);\n const verification = (input.verification ?? [])\n .map((line) => line.trim().slice(0, LIMITS.verificationChars))\n .filter((line) => line && !scanSensitive(line).sensitive)\n .slice(0, LIMITS.verification);\n const fingerprint = createHash(\"sha256\")\n .update(\n JSON.stringify({\n namespace: input.namespace.trim().toLowerCase(),\n session: input.sessionId ?? null,\n summary: summary.replace(/\\s+/g, \" \").toLowerCase(),\n files,\n }),\n )\n .digest(\"hex\");\n\n const existing = (await this.list()).find((entry) => entry.fingerprint === fingerprint);\n if (existing) return existing.id;\n\n const [hashes, identity] = await Promise.all([\n fileHashes(this.repositoryRoot, files),\n repoIdentity(this.repositoryRoot),\n ]);\n const id = generateEntityId(\"wlg\", now.getTime());\n const path = this.entryPath(id);\n await assertNoSymlinkBetween(this.repositoryRoot, dirname(path));\n await mkdir(this.directory, { recursive: true, mode: 0o700 });\n const frontMatter = stringifyYaml({\n schemaVersion: 1,\n id,\n namespace: input.namespace,\n createdAt: now.toISOString(),\n sourceSessionId: input.sessionId ?? null,\n sourcePlanId: input.planId ?? null,\n commitSha: input.commitSha ?? null,\n agentId: input.agentId ?? null,\n files,\n verification,\n savedMemory: input.savedMemory ?? [],\n queuedForReview: input.queuedForReview ?? [],\n fingerprint,\n fileHashes: hashes,\n branch: identity.branch,\n });\n await writeAtomic(path, composeMarkdown(frontMatter, summary));\n return id;\n }\n\n async read(id: string): Promise<WorklogEntry> {\n const path = this.entryPath(id);\n await assertNoSymlinkBetween(this.repositoryRoot, path);\n const parsed = parseFrontMatter(await readFile(path, \"utf8\"));\n return {\n ...entrySchema.parse(parseYaml(parsed.frontMatter)),\n summary: parsed.content.trim(),\n path,\n };\n }\n\n /** All readable entries, newest first. Corrupt or foreign files are skipped. */\n // ponytail: full directory scan per call; add an index file if worklogs reach thousands of entries.\n async list(namespace?: string): Promise<WorklogEntry[]> {\n let names: string[];\n try {\n await assertNoSymlinkBetween(this.repositoryRoot, this.directory);\n names = await readdir(this.directory);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return [];\n throw error;\n }\n const entries: WorklogEntry[] = [];\n for (const name of names) {\n if (!/^wlg_[a-z0-9]+\\.md$/.test(name)) continue;\n try {\n const entry = await this.read(name.replace(/\\.md$/, \"\"));\n if (namespace === undefined || entry.namespace === namespace) entries.push(entry);\n } catch {\n // Leave corrupt entries on disk for inspection; never fail recall on one.\n }\n }\n return entries.sort(\n (left, right) =>\n right.createdAt.localeCompare(left.createdAt) || right.id.localeCompare(left.id),\n );\n }\n\n /**\n * Prior handoffs for a new turn. With target paths or a task, only entries\n * that overlap them are returned (ranked by overlap, then recency); without\n * either, the most recent entries are returned.\n */\n async recall(input: {\n namespace: string;\n paths?: string[];\n task?: string;\n limit?: number;\n now?: Date;\n }): Promise<HandoffSummary[]> {\n const now = input.now ?? new Date();\n const limit = input.limit ?? 3;\n const entries = await this.list(input.namespace);\n const paths = new Set((input.paths ?? []).map(normalizePath));\n const taskWords = words(input.task ?? \"\");\n const targeted = paths.size > 0 || taskWords.size > 0;\n\n const ranked = entries\n .map((entry, recency) => {\n const fileHits = entry.files.filter((file) => paths.has(file));\n const summaryWords = words(entry.summary);\n const wordHits = [...taskWords].filter((word) => summaryWords.has(word));\n const score = fileHits.length * 3 + Math.min(wordHits.length, 5);\n const reason = !targeted\n ? \"recent work\"\n : [\n fileHits.length > 0 ? `touched ${fileHits.slice(0, 3).join(\", \")}` : \"\",\n wordHits.length > 0 ? `task terms: ${wordHits.slice(0, 5).join(\", \")}` : \"\",\n ]\n .filter(Boolean)\n .join(\"; \");\n return { entry, score, recency, reason };\n })\n .filter((item) => !targeted || item.score > 0)\n .sort((left, right) => right.score - left.score || left.recency - right.recency)\n .slice(0, limit);\n\n return Promise.all(\n ranked.map(async ({ entry, reason }) => {\n const freshness = await this.freshness(entry);\n return {\n id: entry.id,\n createdAt: entry.createdAt,\n ageDays: Math.max(\n 0,\n Math.floor((now.getTime() - Date.parse(entry.createdAt)) / 86_400_000),\n ),\n summary: entry.summary.slice(0, 240),\n files: entry.files.slice(0, 8),\n verification: entry.verification.slice(0, 3),\n savedMemory: entry.savedMemory,\n ...freshness,\n reason,\n };\n }),\n );\n }\n\n private async freshness(\n entry: WorklogEntry,\n ): Promise<{ changedSince: string[]; missing: string[]; unknown: string[] }> {\n const { changed, missing, unknown } = await compareFreshness(\n this.repositoryRoot,\n entry.files,\n entry.fileHashes,\n );\n return { changedSince: changed, missing, unknown };\n }\n\n private entryPath(id: string): string {\n if (!/^wlg_[a-z0-9]+$/.test(id)) throw new Error(`Invalid worklog id: ${id}`);\n return join(this.directory, `${id}.md`);\n }\n}\n\n/**\n * Keep the human summary, drop the hook's trailing \"Changed files:\" line (files\n * are recorded separately), cap the length, and redact anything sensitive.\n */\nfunction boundSummary(summary: string, files: string[]): string {\n const text = summary\n .replace(/\\n*Changed files: [^\\n]*\\.?\\s*$/, \"\")\n .trim()\n .slice(0, LIMITS.summaryChars);\n if (!text) return files.length > 0 ? `Changed ${files.slice(0, 5).join(\", \")}.` : \"(no summary)\";\n return redactSentences(text);\n}\n\n/**\n * Redact only the sentences (or lines) that scan sensitive, so one pasted key\n * does not erase the whole handoff. If the result still scans sensitive (a\n * credential split across a sentence boundary), redact the whole summary.\n */\nfunction redactSentences(text: string): string {\n if (!scanSensitive(text).sensitive) return text;\n const redacted = text\n .split(/(?<=[.!?])\\s+|\\n+/)\n .map((sentence) => (scanSensitive(sentence).sensitive ? REDACTED : sentence))\n .join(\" \");\n return scanSensitive(redacted).sensitive ? REDACTED : redacted;\n}\n\nfunction normalizePath(path: string): string {\n return path.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\").trim();\n}\n\nfunction words(text: string): Set<string> {\n return new Set(text.toLowerCase().match(/[a-z0-9_]{4,}/g) ?? []);\n}\n","import { execFile } from \"node:child_process\";\nimport { readFile } from \"node:fs/promises\";\nimport { relative, resolve, sep } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { hashContent } from \"../indexer/engine.js\";\n\n/**\n * Content-based freshness (queue Q4). An mtime says when a file was touched,\n * not whether it changed: a checkout or formatter run touches without changing,\n * and a restored mtime hides a real change. Recorded evidence therefore keeps a\n * content hash per file, and a check compares contents.\n */\n\n/** null: the file is missing, unreadable or outside the repository. */\nexport type FileHashes = Record<string, string | null>;\n\nexport type Freshness = {\n current: string[];\n changed: string[];\n missing: string[];\n /** Recorded without a hash (older entries): cannot say. */\n unknown: string[];\n};\n\nexport async function hashFile(root: string, path: string): Promise<string | null> {\n const absolute = resolve(root, path);\n const rel = relative(resolve(root), absolute);\n if (rel === \"..\" || rel.startsWith(`..${sep}`)) return null;\n try {\n return hashContent(await readFile(absolute, \"utf8\")).slice(0, 16);\n } catch {\n return null;\n }\n}\n\nexport async function fileHashes(root: string, paths: string[]): Promise<FileHashes> {\n const entries = await Promise.all(\n paths.map(async (path) => [path, await hashFile(root, path)] as const),\n );\n return Object.fromEntries(entries);\n}\n\n/** Compare `paths` now against the hashes recorded for them. */\nexport async function compareFreshness(\n root: string,\n paths: string[],\n recorded: FileHashes | undefined,\n): Promise<Freshness> {\n const result: Freshness = { current: [], changed: [], missing: [], unknown: [] };\n for (const path of paths) {\n const now = await hashFile(root, path);\n const then = recorded?.[path];\n if (now === null) result.missing.push(path);\n else if (then === undefined) result.unknown.push(path);\n else if (then === now) result.current.push(path);\n else result.changed.push(path);\n }\n return result;\n}\n\n/** Which checkout this evidence came from; fields are null outside git. */\nexport type RepoIdentity = {\n /** The worktree's top-level directory. */\n worktree: string | null;\n /** Per-worktree git dir: differs between linked worktrees of one repository. */\n gitDir: string | null;\n branch: string | null;\n head: string | null;\n};\n\nconst run = promisify(execFile);\n\nexport async function repoIdentity(root: string): Promise<RepoIdentity> {\n const git = async (...args: string[]) => {\n try {\n const { stdout } = await run(\"git\", args, { cwd: root, timeout: 2_000 });\n return stdout.trim() || null;\n } catch {\n return null;\n }\n };\n const [worktree, gitDir, branch, head] = await Promise.all([\n git(\"rev-parse\", \"--show-toplevel\"),\n git(\"rev-parse\", \"--absolute-git-dir\"),\n git(\"rev-parse\", \"--abbrev-ref\", \"HEAD\"),\n git(\"rev-parse\", \"HEAD\"),\n ]);\n return { worktree, gitDir, branch, head };\n}\n","import { estimateTokens } from \"../savings/tokens.js\";\nimport type { TokenStats } from \"./types.js\";\n\nconst WARNING = \"Context incomplete: inspect omitted policies, risks and incidents before editing.\";\n\ntype Payload = Record<string, unknown> & { tokens: TokenStats };\ntype Candidate = { section: string; value: unknown; priority: number; essential: boolean };\n\n/** Budget the complete compact JSON text, including this accounting and delivery metadata. */\nexport function enforceContextBudget<T extends object>(input: T): T {\n const output = structuredClone(input) as Payload;\n if (!output.tokens) return input;\n output.tokens.essentialOmitted ??= 0;\n if (account(output) <= output.tokens.budget) return output as T;\n\n const candidates: Candidate[] = [];\n const add = (section: string, value: unknown, priority: number, essential = false) => {\n candidates.push({ section, value, priority, essential });\n };\n for (const [section, priority] of [\n [\"diffs\", 10],\n [\"neighbours\", 20],\n [\"handoffs\", 30],\n [\"facts\", 40],\n [\"rules\", 45],\n [\"symbols\", 50],\n [\"reuse\", 75],\n [\"policyRules\", 90],\n [\"incidents\", 80],\n ] as const) {\n const values = output[section];\n if (!Array.isArray(values)) continue;\n for (const value of values) {\n const essential = section === \"policyRules\" || (section === \"incidents\" && !value.resolved);\n const severity =\n section === \"incidents\"\n ? ({ critical: 4, high: 3, medium: 2, low: 1 }[value.severity as string] ?? 0)\n : 0;\n add(section, value, priority + severity, essential);\n }\n output[section] = [];\n }\n const risks = output.risks as { items: Array<{ score: number }> } | undefined;\n if (risks) {\n for (const value of risks.items)\n add(\n \"risks\",\n value,\n value.score >= 50 ? 100 + value.score : 60 + value.score / 100,\n value.score > 0,\n );\n risks.items = [];\n }\n if (output.plan) {\n add(\"plan\", output.plan, 55);\n output.plan = null;\n }\n const architecture = output.architecture as { hotspots: unknown[] } | undefined;\n if (architecture) {\n for (const value of architecture.hotspots) add(\"hotspots\", value, 25);\n architecture.hotspots = [];\n }\n output.explain = [];\n if (typeof output.task === \"string\") output.task = compact(output.task, 160);\n const riskStats = (output.risks as { stats?: { perSignal: unknown[] } } | undefined)?.stats;\n if (riskStats) riskStats.perSignal = [];\n\n // Reserve a bounded warning before selecting evidence so adding it cannot\n // silently displace the last safety item. Identity and target paths are exact.\n const previousOmitted = output.tokens.essentialOmitted;\n output.tokens.essentialOmitted = previousOmitted + candidates.filter((c) => c.essential).length;\n output.tokens.warning = WARNING;\n if (account(output) > output.tokens.budget && output.task) output.task = null;\n // No candidate selection can rescue a target set that alone exceeds the\n // budget. Avoid repeatedly tokenizing enormous change sets in that case.\n if (\n estimateTokens({ project: output.project, targetPaths: output.targetPaths }) >\n output.tokens.budget\n ) {\n account(output);\n return output as T;\n }\n\n candidates.sort((a, b) => b.priority - a.priority);\n for (const candidate of candidates) {\n const insert = (value: unknown) => {\n if (candidate.section === \"plan\") output.plan = value;\n else if (candidate.section === \"risks\") risks?.items.push(value as { score: number });\n else if (candidate.section === \"hotspots\") architecture?.hotspots.push(value);\n else (output[candidate.section] as unknown[]).push(value);\n };\n const remove = () => {\n if (candidate.section === \"plan\") output.plan = null;\n else if (candidate.section === \"risks\") risks?.items.pop();\n else if (candidate.section === \"hotspots\") architecture?.hotspots.pop();\n else (output[candidate.section] as unknown[]).pop();\n };\n insert(candidate.value);\n if (candidate.essential) output.tokens.essentialOmitted--;\n if (account(output) <= output.tokens.budget) continue;\n remove();\n if (candidate.essential) output.tokens.essentialOmitted++;\n // A shortened helper path/signature can become misleading; omit it whole.\n if (candidate.section === \"reuse\") continue;\n // Keep policy instructions verbatim. A shortened safety item is explicitly\n // incomplete and retains the warning.\n const smaller = candidate.essential\n ? compactSafety(candidate.value)\n : compact(candidate.value, 100);\n insert(smaller);\n if (account(output) <= output.tokens.budget) continue;\n remove();\n }\n if (output.tokens.essentialOmitted === 0) delete output.tokens.warning;\n account(output);\n return output as T;\n}\n\nfunction compactSafety(value: unknown): unknown {\n if (!value || typeof value !== \"object\") return value;\n const item = value as Record<string, unknown>;\n // Patterns, messages, identities and paths remain exact. Risk/incident\n // narratives may be shortened with an explicit incomplete status.\n return {\n ...item,\n ...(typeof item.reason === \"string\" ? { reason: compact(item.reason, 100) } : {}),\n ...(typeof item.summary === \"string\" ? { summary: compact(item.summary, 100) } : {}),\n ...(Array.isArray(item.evidence)\n ? { evidence: item.evidence.slice(0, 1).map((entry) => compact(entry, 100)) }\n : {}),\n };\n}\n\nfunction compact(value: unknown, limit: number): unknown {\n if (typeof value === \"string\")\n return value.length > limit ? `${value.slice(0, limit - 1)}…` : value;\n if (Array.isArray(value)) return value.slice(0, 3).map((item) => compact(item, limit));\n if (value && typeof value === \"object\")\n return Object.fromEntries(\n Object.entries(value).map(([key, item]) => [key, compact(item, limit)]),\n );\n return value;\n}\n\n/** Find an exact fixed point because the reported count itself occupies tokens. */\nfunction account(output: Payload): number {\n const tokens = output.tokens;\n const set = (count: number) => {\n tokens.returnedEstimate = count;\n tokens.countedSurface = \"compact_json\";\n tokens.status =\n count > tokens.budget\n ? \"overflow\"\n : tokens.essentialOmitted > 0\n ? \"minimum_envelope\"\n : \"within_budget\";\n if (tokens.status === \"overflow\") tokens.warning = WARNING;\n };\n // Numeric token boundaries can form a cycle. A JSON whitespace field gives\n // deterministic alternative encodings without changing any evidence.\n for (let padding = 0; padding < 32; padding++) {\n if (padding > 0) output.accountingPadding = \" \".repeat(padding);\n let count = estimateTokens(output);\n for (let attempt = 0; attempt < 12; attempt++) {\n set(count);\n const measured = estimateTokens(output);\n if (measured === count) return count;\n count = measured;\n }\n }\n throw new Error(\"Could not stabilize compact context token accounting\");\n}\n","import { mkdir, readFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport pTimeout from \"p-timeout\";\nimport { writeAtomic } from \"../core/markdown-store-fs.js\";\nimport { loadFreshIndex } from \"../indexer/engine.js\";\nimport type { IndexManifest } from \"../indexer/types.js\";\nimport { withCardLock } from \"../llm/card-lock.js\";\nimport { LOCAL_EMBEDDING_MODEL } from \"../providers/models.js\";\nimport { NON_SOURCE_PATH, readBoundedSource, TEST_PATH } from \"./discovery.js\";\nimport type { Embed } from \"./file-vectors.js\";\n\ntype Entry = { path: string; name: string; hash: string; vector: number[] };\ntype Cache = { version: 1; model: string; entries: Entry[] };\nconst MODEL = `${LOCAL_EMBEDDING_MODEL.id}@${LOCAL_EMBEDDING_MODEL.revision}:${LOCAL_EMBEDDING_MODEL.schema}`;\nconst file = (root: string) => join(root, \".codebuddy\", \"cache\", \"reuse-vectors.json\");\nconst kinds = new Set([\"function\", \"class\", \"method\", \"const\"]);\nconst valid = (vector: number[]) =>\n Array.isArray(vector) &&\n vector.length === LOCAL_EMBEDDING_MODEL.dimensions &&\n vector.every(Number.isFinite) &&\n vector.some((value) => value !== 0);\nasync function embedLocal(texts: string[]) {\n const { LocalModelProvider } = await import(\"../providers/local.js\");\n return (await new LocalModelProvider().embed({ input: texts })).vectors;\n}\nasync function load(root: string): Promise<Cache> {\n try {\n const cache = JSON.parse(await readFile(file(root), \"utf8\")) as Cache;\n if (cache.version === 1 && cache.model === MODEL && Array.isArray(cache.entries))\n return {\n ...cache,\n entries: cache.entries.filter(\n (entry) =>\n typeof entry.path === \"string\" && typeof entry.name === \"string\" && valid(entry.vector),\n ),\n };\n } catch {}\n return { version: 1, model: MODEL, entries: [] };\n}\n\n/** Only background/index work embeds source. Query-time never downloads a corpus or bills a hosted model. */\nexport async function refreshReuseVectors(\n root: string,\n manifest: IndexManifest,\n deadlineAt: number,\n embed: Embed = embedLocal,\n): Promise<{ embedded: number; pending: number }> {\n const cache = await load(root);\n const cached = new Map(cache.entries.map((entry) => [`${entry.path}\\0${entry.name}`, entry]));\n const entries: Entry[] = [];\n const pending: Array<{ path: string; name: string; hash: string; text: string }> = [];\n for (const entry of Object.values(manifest.entries)) {\n if (NON_SOURCE_PATH.test(entry.path) || TEST_PATH.test(entry.path)) continue;\n const symbols = (entry.symbolTable ?? []).filter(\n (symbol) => symbol.exported && kinds.has(symbol.kind),\n );\n if (!symbols.length) continue;\n const source = await readBoundedSource(root, entry.path);\n if (source === null) continue;\n const lines = source.split(\"\\n\");\n for (const symbol of symbols) {\n const old = cached.get(`${entry.path}\\0${symbol.name}`);\n const existing = old?.hash === entry.hash ? old : undefined;\n if (existing) {\n entries.push(existing);\n continue;\n }\n pending.push({\n path: entry.path,\n name: symbol.name,\n hash: entry.hash,\n text: `${entry.path}\\n${symbol.signature}\\n${lines.slice(Math.max(0, symbol.startLine - 4), symbol.endLine).join(\"\\n\")}`.slice(\n 0,\n 2000,\n ),\n });\n }\n }\n let embedded = 0;\n for (let start = 0; start < pending.length && Date.now() < deadlineAt; start += 16) {\n const batch = pending.slice(start, start + 16);\n const vectors = await embed(batch.map((item) => item.text));\n if (vectors.length !== batch.length || vectors.some((vector) => !valid(vector)))\n throw new Error(\"Invalid reuse embedding batch\");\n batch.forEach(({ text: _text, ...entry }, index) => {\n entries.push({ ...entry, vector: vectors[index] as number[] });\n });\n embedded += batch.length;\n }\n await mkdir(dirname(file(root)), { recursive: true });\n await writeAtomic(file(root), JSON.stringify({ version: 1, model: MODEL, entries }), {\n mode: 0o600,\n });\n return { embedded, pending: pending.length - embedded };\n}\n\nexport async function syncReuseVectors(root: string, budgetMs: number) {\n if (budgetMs <= 0 || process.env.CODEBUDDY_SEMANTIC === \"0\") return null;\n try {\n // Same single-writer lock as file vectors and cards (`llm/card-lock.ts`).\n const locked = await withCardLock(root, async () => {\n const { manifest } = await loadFreshIndex(root);\n return refreshReuseVectors(root, manifest, Date.now() + budgetMs);\n });\n return locked.ok ? locked.value : { embedded: 0, pending: 0, lockedBy: locked.holder };\n } catch {\n return null;\n }\n}\n\n/** Cosines are only comparable within the pinned embedding space; stale symbols are excluded. */\nexport async function rankSemanticReuse(\n root: string,\n task: string,\n manifest: IndexManifest,\n embed: Embed = embedLocal,\n): Promise<Array<{ path: string; name: string; score: number }>> {\n if (process.env.CODEBUDDY_SEMANTIC === \"0\") return [];\n const cache = await load(root);\n const eligible = cache.entries.filter(\n (entry) => manifest.entries[entry.path]?.hash === entry.hash,\n );\n if (!eligible.length) return [];\n try {\n const vectors = await pTimeout(embed([task]), { milliseconds: 2000 });\n const query = vectors[0];\n if (!query || !valid(query)) return [];\n const norm = Math.sqrt(query.reduce((sum, value) => sum + value * value, 0));\n return eligible\n .map((entry) => {\n const denominator =\n norm * Math.sqrt(entry.vector.reduce((sum, value) => sum + value * value, 0));\n return {\n path: entry.path,\n name: entry.name,\n score:\n entry.vector.reduce((sum, value, index) => sum + value * (query[index] ?? 0), 0) /\n denominator,\n };\n })\n .sort((left, right) => right.score - left.score || left.path.localeCompare(right.path));\n } catch {\n return [];\n }\n}\n","import { createHash } from \"node:crypto\";\nimport {\n appendFile,\n chmod,\n mkdir,\n open,\n readdir,\n readFile,\n realpath,\n rm,\n stat,\n} from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { isAbsolute, join, relative, sep } from \"node:path\";\nimport { taskTerms } from \"../context/discovery.js\";\nimport {\n compareFreshness,\n type FileHashes,\n fileHashes,\n type RepoIdentity,\n repoIdentity,\n} from \"../core/freshness.js\";\nimport { writeAtomic } from \"../core/markdown-store-fs.js\";\nimport { redactSensitive } from \"../core/sensitive.js\";\n\n/**\n * Incremental session journal (queue Q2). A host transcript is ingested as a\n * delta from a durable byte cursor, so a long session is never re-parsed and\n * intermediate findings survive even when the final reply says only \"Done\".\n *\n * Kept: the user's prompts, the assistant's visible text, edited paths, shell\n * commands and their pass/fail. Never kept: thinking blocks, tool output, or any\n * text the secret scan flags (replaced whole). Everything is bounded: per event,\n * per journal (oldest half dropped), and by age.\n *\n * Layout under `.codebuddy/cache/journal/` (gitignored in every project, since\n * it holds prompts; rebuildable from the host transcript while that exists):\n * <session>.jsonl versioned events, one per line\n * <session>.cursor.json { transcript, offset, head, seq }\n * <session>.checkpoint.json the active-task checkpoint derived from events\n */\n\nexport const JOURNAL_VERSION = 1;\nexport const JOURNAL_LIMITS = {\n eventChars: 1_000,\n journalBytes: 1_000_000,\n /** Largest transcript delta read per ingest; the rest is read by the next one. */\n chunkBytes: 4_000_000,\n maxAgeDays: 30,\n findings: 5,\n findingChars: 300,\n verification: 5,\n constraints: 5,\n editedPaths: 100,\n} as const;\n\nexport type JournalEvent = {\n v: typeof JOURNAL_VERSION;\n seq: number;\n /** Stable across re-ingestion of the same transcript bytes: dedupe key. */\n id: string;\n at: string;\n kind: \"user\" | \"assistant\" | \"edit\" | \"command\" | \"result\" | \"gap\";\n text?: string;\n path?: string;\n /** `command` only: its tool-use id, matched by a later `result`. */\n ref?: string;\n ok?: boolean;\n /** Byte offset of the transcript line this came from (provenance). */\n offset: number;\n};\n\ntype Cursor = {\n v: number;\n transcript: string;\n offset: number;\n head: string;\n seq: number;\n headBytes?: number;\n};\n\nexport type Checkpoint = {\n v: typeof JOURNAL_VERSION;\n session: string;\n updatedAt: string;\n /** The latest prompt that states a task (follow-ups like \"continue\" are skipped). */\n goal: string | null;\n constraints: string[];\n editedPaths: string[];\n /** `stale`: a file was edited after this check ran, so its result no longer holds. */\n verification: Array<{ command: string; ok: boolean | null; stale: boolean }>;\n failedApproaches: string[];\n /** Intermediate assistant statements since the goal, not only the final reply. */\n findings: string[];\n nextAction: string | null;\n /** Journal events this checkpoint was derived from. */\n evidence: { fromSeq: number; toSeq: number } | null;\n /** Set at ingest: which checkout, and the edited files' contents then. */\n identity?: RepoIdentity;\n fileHashes?: FileHashes;\n /** Correlate a delayed result even after its command was evicted from the journal. */\n verificationRefs?: Array<string | null>;\n /** Preserve an intermediate reply when the next text arrives in a later ingest. */\n lastAssistant?: string;\n /** Recovery copy if the standalone cursor is lost after journal trimming. */\n sourceCursor?: Cursor;\n recentHostEventIds?: string[];\n omittedTranscriptLines?: number;\n};\n\nexport function journalDir(root: string): string {\n return join(root, \".codebuddy\", \"cache\", \"journal\");\n}\n\nfunction safeSession(session: string): string {\n const clean = session.replace(/[^A-Za-z0-9_.-]/g, \"_\");\n if (clean === session && clean.length <= 120 && clean !== \".\" && clean !== \"..\" && clean !== \"\")\n return clean;\n const name = clean.slice(0, 100);\n return `${name.replace(/^\\.+$/, \"session\") || \"session\"}-${createHash(\"sha256\").update(session).digest(\"hex\").slice(0, 16)}`;\n}\n\nconst paths = (root: string, session: string) => {\n const base = join(journalDir(root), safeSession(session));\n return {\n journal: `${base}.jsonl`,\n cursor: `${base}.cursor.json`,\n checkpoint: `${base}.checkpoint.json`,\n lock: `${base}.lock`,\n };\n};\n\nconst VERIFICATION_SEGMENT =\n /^\\s*(?:\\w+=\\S*\\s+)*(?:npm|pnpm|yarn|bun|npx|cargo|go|make|mvn|gradle|\\.\\/gradlew|tsc|vitest|jest|pytest|python3? -m pytest|ruff|mypy|eslint|biome)\\b.*\\b(?:test|tests|lint|typecheck|tsc|build|check|vet|clippy|vitest|jest|pytest|ruff|mypy|eslint|biome)\\b/;\n\nexport function isVerificationCommand(command: string): boolean {\n return command.split(/&&|\\|\\||;/).some((segment) => VERIFICATION_SEGMENT.test(segment));\n}\n\n/** Harness-inserted markup (reminders, command echoes) inside user content. */\nconst TAGGED_BLOCK = /<([a-z][\\w-]*)[^>]*>[\\s\\S]*?<\\/\\1>/gi;\nconst EDIT_TOOLS = new Set([\"Edit\", \"Write\", \"MultiEdit\", \"NotebookEdit\"]);\n\nconst clip = (text: string, max: number) =>\n text.length > max ? `${text.slice(0, max - 1)}…` : text;\n\n/** Redacted and bounded; null when nothing is left. */\nfunction clean(text: string): string | null {\n const trimmed = text.replace(TAGGED_BLOCK, \" \").replace(/\\s+/g, \" \").trim();\n return trimmed ? clip(redactSensitive(trimmed), JOURNAL_LIMITS.eventChars) : null;\n}\n\n/** Events from one transcript line (Claude Code JSONL); thinking and tool output are dropped. */\nexport function eventsFromLine(\n line: string,\n offset: number,\n): Array<Omit<JournalEvent, \"seq\" | \"v\">> {\n let entry: Record<string, unknown>;\n try {\n entry = JSON.parse(line) as Record<string, unknown>;\n } catch {\n return [];\n }\n const message = (entry.message ?? {}) as Record<string, unknown>;\n const at = typeof entry.timestamp === \"string\" ? entry.timestamp : new Date(0).toISOString();\n const lineId =\n typeof entry.uuid === \"string\"\n ? entry.uuid\n : createHash(\"sha1\").update(line).digest(\"hex\").slice(0, 16);\n const blocks: Array<Record<string, unknown>> =\n typeof message.content === \"string\"\n ? [{ type: \"text\", text: message.content }]\n : Array.isArray(message.content)\n ? (message.content as Array<Record<string, unknown>>)\n : [];\n const events: Array<Omit<JournalEvent, \"seq\" | \"v\">> = [];\n blocks.forEach((block, index) => {\n const id = `${lineId}:${index}`;\n if (message.role === \"user\") {\n if (block.type === \"tool_result\" && typeof block.tool_use_id === \"string\") {\n events.push({\n id,\n at,\n kind: \"result\",\n ref: block.tool_use_id,\n ok: block.is_error !== true,\n offset,\n });\n } else if (block.type === \"text\" && entry.isMeta !== true) {\n const text = clean(String(block.text ?? \"\"));\n if (text) events.push({ id, at, kind: \"user\", text, offset });\n }\n return;\n }\n if (message.role !== \"assistant\") return;\n if (block.type === \"text\") {\n const text = clean(String(block.text ?? \"\"));\n if (text) events.push({ id, at, kind: \"assistant\", text, offset });\n return;\n }\n if (block.type !== \"tool_use\") return;\n const input = (block.input ?? {}) as Record<string, unknown>;\n const name = String(block.name ?? \"\");\n const path = input.file_path ?? input.notebook_path;\n if (EDIT_TOOLS.has(name) && typeof path === \"string\") {\n events.push({ id, at, kind: \"edit\", path: clip(path, 500), offset });\n } else if (name === \"Bash\" && typeof input.command === \"string\") {\n const text = clean(input.command);\n if (text) {\n events.push({\n id,\n at,\n kind: \"command\",\n text,\n ...(typeof block.id === \"string\" ? { ref: block.id } : {}),\n offset,\n });\n }\n }\n });\n return events;\n}\n\nexport async function readJournal(root: string, session: string): Promise<JournalEvent[]> {\n let raw: string;\n try {\n raw = await readFile(paths(root, session).journal, \"utf8\");\n } catch {\n return [];\n }\n const events: JournalEvent[] = [];\n for (const line of raw.split(\"\\n\")) {\n if (!line) continue;\n try {\n const event = JSON.parse(line) as JournalEvent;\n // A torn final line from an interrupted append is skipped, not fatal.\n if (event.v === JOURNAL_VERSION && typeof event.id === \"string\") events.push(event);\n } catch {}\n }\n return events;\n}\n\nasync function readCursor(path: string): Promise<Cursor | null> {\n try {\n const cursor = JSON.parse(await readFile(path, \"utf8\")) as Cursor;\n return validCursor(cursor) ? cursor : null;\n } catch {\n return null;\n }\n}\n\nfunction validCursor(cursor: Cursor): boolean {\n return (\n cursor !== null &&\n typeof cursor === \"object\" &&\n cursor.v === JOURNAL_VERSION &&\n typeof cursor.transcript === \"string\" &&\n typeof cursor.head === \"string\" &&\n Number.isSafeInteger(cursor.offset) &&\n cursor.offset >= 0 &&\n Number.isSafeInteger(cursor.seq) &&\n cursor.seq >= 0 &&\n (cursor.headBytes === undefined ||\n (Number.isInteger(cursor.headBytes) && cursor.headBytes >= 0 && cursor.headBytes <= 256))\n );\n}\n\nasync function headHash(path: string, length = 256): Promise<string> {\n const handle = await open(path, \"r\");\n try {\n const buffer = Buffer.alloc(length);\n const { bytesRead } = await handle.read(buffer, 0, length, 0);\n return createHash(\"sha1\").update(buffer.subarray(0, bytesRead)).digest(\"hex\");\n } finally {\n await handle.close();\n }\n}\n\nasync function withLock<T>(lock: string, run: () => Promise<T>, waitMs = 0): Promise<T | null> {\n const deadline = Date.now() + waitMs;\n for (;;) {\n try {\n await mkdir(lock);\n break;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") throw error;\n const age =\n Date.now() -\n (await stat(lock).then(\n (value) => value.mtimeMs,\n () => Date.now(),\n ));\n if (age >= 60_000) {\n await rm(lock, { recursive: true, force: true });\n continue;\n }\n if (Date.now() >= deadline) return null;\n await new Promise((resolve) => setTimeout(resolve, 10));\n }\n }\n try {\n return await run();\n } finally {\n await rm(lock, { recursive: true, force: true });\n }\n}\n\nexport type IngestResult = {\n added: number;\n offset: number;\n rotated: boolean;\n checkpoint: Checkpoint;\n};\n\n/**\n * Append the transcript's new complete lines to the session journal and\n * refresh the checkpoint. Idempotent: replaying the same bytes adds nothing.\n * Returns null when another ingest for this session holds the lock.\n */\nexport type LineParser = (line: string, offset: number) => Array<Omit<JournalEvent, \"seq\" | \"v\">>;\n\nexport async function ingestTranscript(\n root: string,\n session: string,\n transcript: string,\n now = new Date(),\n parse: LineParser = eventsFromLine,\n): Promise<IngestResult | null> {\n const files = paths(root, session);\n await mkdir(journalDir(root), { recursive: true, mode: 0o700 });\n return withLock(files.lock, async () => {\n const size = (await stat(transcript)).size;\n const previous = await readCheckpoint(root, session);\n const storedCursor = await readCursor(files.cursor);\n const cursor =\n storedCursor ??\n (previous?.sourceCursor && validCursor(previous.sourceCursor) ? previous.sourceCursor : null);\n const headBytes = Math.min(size, 256);\n const head = size > 0 ? await headHash(transcript, headBytes) : \"\";\n const priorHead =\n cursor?.headBytes !== undefined\n ? cursor.headBytes === 0\n ? \"\"\n : await headHash(transcript, Math.min(size, cursor.headBytes))\n : head;\n // Another file, a truncated one, or rewritten first bytes: start over.\n // Ids already journaled keep the replay from duplicating anything.\n const rotated =\n cursor !== null &&\n (cursor.transcript !== transcript || cursor.offset > size || cursor.head !== priorHead);\n let offset = cursor && !rotated ? cursor.offset : 0;\n if (\n cursor &&\n previous &&\n !rotated &&\n cursor.offset === size &&\n (previous.evidence?.toSeq ?? 0) === cursor.seq\n ) {\n if (!storedCursor)\n await writeAtomic(files.cursor, `${JSON.stringify(cursor)}\\n`, { mode: 0o600 });\n return { added: 0, offset: cursor.offset, rotated: false, checkpoint: previous };\n }\n const existing = await readJournal(root, session);\n const appended: JournalEvent[] = [];\n const seen = new Set(existing.map((event) => event.id));\n let seq = Math.max(existing.at(-1)?.seq ?? 0, cursor?.seq ?? 0, previous?.evidence?.toSeq ?? 0);\n let added = 0;\n const handle = await open(transcript, \"r\");\n try {\n while (offset < size) {\n const length = Math.min(size - offset, JOURNAL_LIMITS.chunkBytes);\n const buffer = Buffer.alloc(length);\n const { bytesRead } = await handle.read(buffer, 0, length, offset);\n const end = buffer.subarray(0, bytesRead).lastIndexOf(0x0a);\n // A huge tool-result line must not permanently block all following events.\n // Wait for incomplete lines; skip completed oversized lines with a visible gap.\n if (end === -1) {\n let scan = offset + bytesRead;\n let boundary = -1;\n while (scan < size) {\n const chunk = Buffer.alloc(Math.min(size - scan, JOURNAL_LIMITS.chunkBytes));\n const read = await handle.read(chunk, 0, chunk.length, scan);\n if (read.bytesRead === 0) break;\n const newline = chunk.subarray(0, read.bytesRead).indexOf(0x0a);\n if (newline !== -1) {\n boundary = scan + newline;\n break;\n }\n scan += read.bytesRead;\n }\n if (boundary === -1) break;\n const id = `gap:${createHash(\"sha256\").update(`${transcript}:${offset}:${boundary}`).digest(\"hex\").slice(0, 24)}`;\n if (!seen.has(id)) {\n const gap: JournalEvent = {\n v: JOURNAL_VERSION,\n seq: ++seq,\n id,\n at: now.toISOString(),\n kind: \"gap\",\n offset,\n };\n const torn = !(await endsWithNewline(files.journal));\n await appendFile(files.journal, `${torn ? \"\\n\" : \"\"}${JSON.stringify(gap)}\\n`, {\n mode: 0o600,\n });\n await chmod(files.journal, 0o600);\n seen.add(id);\n appended.push(gap);\n added++;\n }\n offset = boundary + 1;\n continue;\n }\n const lines: string[] = [];\n let lineStart = 0;\n for (const line of buffer.subarray(0, end).toString(\"utf8\").split(\"\\n\")) {\n const lineOffset = offset + lineStart;\n lineStart += Buffer.byteLength(line) + 1;\n for (const event of parse(line, lineOffset)) {\n if (seen.has(event.id)) continue;\n seen.add(event.id);\n const saved: JournalEvent = { ...event, v: JOURNAL_VERSION, seq: ++seq };\n appended.push(saved);\n lines.push(JSON.stringify(saved));\n }\n }\n if (lines.length > 0) {\n // A torn last line (interrupted append) must not swallow the next event.\n const torn = !(await endsWithNewline(files.journal));\n await appendFile(files.journal, `${torn ? \"\\n\" : \"\"}${lines.join(\"\\n\")}\\n`, {\n mode: 0o600,\n });\n // Also repair journals created by earlier releases with default permissions.\n await chmod(files.journal, 0o600);\n }\n added += lines.length;\n offset += end + 1;\n }\n } finally {\n await handle.close();\n }\n // The cursor moves only after the events are appended: a crash in between\n // re-reads the same bytes, and the ids above drop the duplicates.\n const next: Cursor = { v: JOURNAL_VERSION, transcript, offset, head, headBytes, seq };\n await writeAtomic(files.cursor, `${JSON.stringify(next)}\\n`, { mode: 0o600 });\n const events = [...existing, ...appended];\n const fresh = previous\n ? events.filter((event) => event.seq > (previous.evidence?.toSeq ?? 0))\n : events;\n if (previous && fresh.length === 0) {\n await enforceRetention(files.journal);\n return { added, offset, rotated, checkpoint: previous };\n }\n const checkpoint = await persistCheckpoint(root, session, fresh, previous, now, {\n sourceCursor: next,\n });\n // Persist the compact state before discarding any events it summarizes.\n await enforceRetention(files.journal);\n void pruneOldJournals(root, now).catch(() => undefined);\n return { added, offset, rotated, checkpoint };\n });\n}\n\nasync function persistCheckpoint(\n root: string,\n session: string,\n fresh: JournalEvent[],\n previous: Checkpoint | null,\n now: Date,\n metadata: Partial<Pick<Checkpoint, \"sourceCursor\" | \"recentHostEventIds\">> = {},\n): Promise<Checkpoint> {\n const derived = deriveCheckpoint(session, fresh, now, previous ?? undefined);\n const editedPaths = [...new Set(derived.editedPaths.map((path) => repoRelative(root, path)))];\n const sameTask = previous && derived.evidence?.fromSeq === previous.evidence?.fromSeq;\n const newlyEdited = fresh\n .filter((event) => event.kind === \"edit\" && event.path)\n .map((event) => repoRelative(root, event.path as string));\n const hashes = {\n ...(sameTask ? previous.fileHashes : {}),\n ...(await fileHashes(root, sameTask ? newlyEdited : editedPaths)),\n };\n const checkpoint: Checkpoint = {\n ...derived,\n editedPaths,\n identity: (sameTask && previous.identity) || (await repoIdentity(root)),\n fileHashes: Object.fromEntries(editedPaths.map((path) => [path, hashes[path] ?? null])),\n ...metadata,\n };\n await writeAtomic(paths(root, session).checkpoint, `${JSON.stringify(checkpoint, null, 2)}\\n`, {\n mode: 0o600,\n });\n return checkpoint;\n}\n\n/** Observable host events only: never send reasoning blocks or full tool outputs. */\nexport type HostJournalEvent = {\n id: string;\n kind: \"user\" | \"assistant\" | \"edit\" | \"command\" | \"result\";\n text?: string;\n path?: string;\n ref?: string;\n ok?: boolean;\n};\n\n/** A durable event bridge for hosts whose transcript format is unavailable or unstable. */\nexport async function appendHostEvents(\n root: string,\n session: string,\n input: HostJournalEvent[],\n now = new Date(),\n): Promise<{ added: number; checkpoint: Checkpoint } | null> {\n if (!input.length) return null;\n const files = paths(root, session);\n await mkdir(journalDir(root), { recursive: true, mode: 0o700 });\n return withLock(\n files.lock,\n async () => {\n const previous = await readCheckpoint(root, session);\n const existing = await readJournal(root, session);\n const pending = previous\n ? existing.filter((event) => event.seq > (previous.evidence?.toSeq ?? 0))\n : existing;\n const seen = new Set([\n ...existing.map((event) => event.id),\n ...(previous?.recentHostEventIds ?? []),\n ]);\n let seq = Math.max(existing.at(-1)?.seq ?? 0, previous?.evidence?.toSeq ?? 0);\n const fresh: JournalEvent[] = [];\n for (const candidate of input.slice(0, 100)) {\n if (\n !candidate ||\n typeof candidate.id !== \"string\" ||\n !candidate.id ||\n ![\"user\", \"assistant\", \"edit\", \"command\", \"result\"].includes(candidate.kind)\n )\n continue;\n const id = `host:${createHash(\"sha256\").update(candidate.id).digest(\"hex\").slice(0, 32)}`;\n if (seen.has(id)) continue;\n const text = typeof candidate.text === \"string\" ? clean(candidate.text) : null;\n const path = typeof candidate.path === \"string\" ? clean(candidate.path) : null;\n if (\n (candidate.kind === \"user\" ||\n candidate.kind === \"assistant\" ||\n candidate.kind === \"command\") &&\n !text\n )\n continue;\n if (candidate.kind === \"edit\" && !path) continue;\n if (candidate.kind === \"result\" && typeof candidate.ref !== \"string\") continue;\n fresh.push({\n v: JOURNAL_VERSION,\n seq: ++seq,\n id,\n at: now.toISOString(),\n kind: candidate.kind,\n offset: -1,\n ...(text ? { text } : {}),\n ...(path ? { path: clip(path, 500) } : {}),\n ...(typeof candidate.ref === \"string\" ? { ref: clip(candidate.ref, 500) } : {}),\n ...(typeof candidate.ok === \"boolean\" ? { ok: candidate.ok } : {}),\n });\n seen.add(id);\n }\n if (!fresh.length && !pending.length && previous) return { added: 0, checkpoint: previous };\n if (fresh.length) {\n const torn = !(await endsWithNewline(files.journal));\n await appendFile(\n files.journal,\n `${torn ? \"\\n\" : \"\"}${fresh.map((event) => JSON.stringify(event)).join(\"\\n\")}\\n`,\n { mode: 0o600 },\n );\n await chmod(files.journal, 0o600);\n }\n const checkpoint = await persistCheckpoint(\n root,\n session,\n [...pending, ...fresh],\n previous,\n now,\n {\n recentHostEventIds: [\n ...new Set([\n ...(previous?.recentHostEventIds ?? []),\n ...fresh.map((event) => event.id),\n ]),\n ].slice(-256),\n },\n );\n await enforceRetention(files.journal);\n void pruneOldJournals(root, now).catch(() => undefined);\n return { added: fresh.length, checkpoint };\n },\n 2000,\n );\n}\n\nasync function endsWithNewline(path: string): Promise<boolean> {\n try {\n const handle = await open(path, \"r\");\n try {\n const { size } = await handle.stat();\n if (size === 0) return true;\n const byte = Buffer.alloc(1);\n await handle.read(byte, 0, 1, size - 1);\n return byte[0] === 0x0a;\n } finally {\n await handle.close();\n }\n } catch {\n return true; // no journal yet\n }\n}\n\n/** Host tools report absolute paths; inside the repository they become relative. */\nfunction repoRelative(root: string, path: string): string {\n if (!isAbsolute(path)) return path;\n const rel = relative(root, path);\n return rel && rel !== \"..\" && !rel.startsWith(`..${sep}`) && !isAbsolute(rel) ? rel : path;\n}\n\n/** Keep a byte-bounded tail; the checkpoint preserves the active task's older state. */\nasync function enforceRetention(journal: string): Promise<void> {\n const size = await stat(journal).then(\n (s) => s.size,\n () => 0,\n );\n if (size <= JOURNAL_LIMITS.journalBytes) return;\n const lines = (await readFile(journal, \"utf8\")).split(\"\\n\").filter(Boolean);\n let bytes = 0;\n let cut = lines.length;\n const budget = Math.floor(JOURNAL_LIMITS.journalBytes / 2);\n while (cut > 0) {\n const length = Buffer.byteLength(lines[cut - 1] as string) + 1;\n if (bytes + length > budget) break;\n bytes += length;\n cut--;\n }\n const kept = lines.slice(cut);\n await writeAtomic(journal, `${kept.join(\"\\n\")}\\n`, { mode: 0o600 });\n}\n\nasync function pruneOldJournals(root: string, now: Date): Promise<number> {\n const cutoff = now.getTime() - JOURNAL_LIMITS.maxAgeDays * 86_400_000;\n let removed = 0;\n for (const name of await readdir(journalDir(root)).catch(() => [] as string[])) {\n const path = join(journalDir(root), name);\n if (\n (await stat(path).then(\n (s) => s.mtimeMs,\n () => now.getTime(),\n )) < cutoff\n ) {\n await rm(path, { recursive: true, force: true });\n removed++;\n }\n }\n return removed;\n}\n\n/** Capture lag per session: transcript bytes not yet journaled (0 = up to date). */\nexport async function journalLag(\n root: string,\n): Promise<Array<{ session: string; behindBytes: number | null }>> {\n const names = await readdir(journalDir(root)).catch(() => [] as string[]);\n return Promise.all(\n names\n .filter((name) => name.endsWith(\".cursor.json\"))\n .map(async (name) => {\n const cursor = await readCursor(join(journalDir(root), name));\n const size = cursor\n ? await stat(cursor.transcript).then(\n (s) => s.size,\n () => null,\n )\n : null;\n return {\n session: name.replace(/\\.cursor\\.json$/, \"\"),\n // null: the transcript is gone, so nothing more can be journaled.\n behindBytes: cursor && size !== null ? Math.max(0, size - cursor.offset) : null,\n };\n }),\n );\n}\n\n/** Delete one session's journal, cursor and checkpoint (or every session's). */\nexport async function forgetJournal(root: string, session?: string): Promise<void> {\n if (session === undefined) {\n await rm(journalDir(root), { recursive: true, force: true });\n return;\n }\n const files = paths(root, session);\n await Promise.all(\n [files.journal, files.cursor, files.checkpoint].map((path) => rm(path, { force: true })),\n );\n}\n\nexport async function readCheckpoint(root: string, session: string): Promise<Checkpoint | null> {\n try {\n const checkpoint = JSON.parse(\n await readFile(paths(root, session).checkpoint, \"utf8\"),\n ) as Checkpoint;\n return validCheckpoint(checkpoint) && checkpoint.session === session ? checkpoint : null;\n } catch {\n return null;\n }\n}\n\nfunction validCheckpoint(value: Checkpoint): boolean {\n return (\n value !== null &&\n typeof value === \"object\" &&\n value.v === JOURNAL_VERSION &&\n typeof value.session === \"string\" &&\n typeof value.updatedAt === \"string\" &&\n Number.isFinite(Date.parse(value.updatedAt)) &&\n (value.goal === null || typeof value.goal === \"string\") &&\n [value.constraints, value.editedPaths, value.findings, value.failedApproaches].every(\n (items) => Array.isArray(items) && items.every((item) => typeof item === \"string\"),\n ) &&\n Array.isArray(value.verification) &&\n value.verification.every(\n (run) =>\n run !== null &&\n typeof run === \"object\" &&\n typeof run.command === \"string\" &&\n (run.ok === null || typeof run.ok === \"boolean\") &&\n typeof run.stale === \"boolean\",\n ) &&\n (value.nextAction === null || typeof value.nextAction === \"string\")\n );\n}\n\n/** Sessions with a journal, newest first. */\nexport async function listJournals(\n root: string,\n): Promise<Array<{ session: string; updatedAt: string }>> {\n const names = await readdir(journalDir(root)).catch(() => [] as string[]);\n const sessions = await Promise.all(\n names\n .filter((name) => name.endsWith(\".checkpoint.json\"))\n .map(async (name) => {\n try {\n const checkpoint = JSON.parse(\n await readFile(join(journalDir(root), name), \"utf8\"),\n ) as Checkpoint;\n return validCheckpoint(checkpoint)\n ? { session: checkpoint.session, updatedAt: checkpoint.updatedAt }\n : null;\n } catch {\n return null;\n }\n }),\n );\n return sessions\n .filter((item): item is { session: string; updatedAt: string } => item !== null)\n .sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));\n}\n\n/**\n * Codex rollout lines (`rollout-*.jsonl` under `~/.codex/sessions/`, codex-cli 0.169):\n * user and assistant text, and paths from `apply_patch` headers. Shell commands\n * run through code-mode `exec` blocks, so they are not imported (no verification\n * outcomes from Codex). Reasoning items are never read.\n */\nexport function eventsFromCodexLine(\n line: string,\n offset: number,\n): Array<Omit<JournalEvent, \"seq\" | \"v\">> {\n let entry: Record<string, unknown>;\n try {\n entry = JSON.parse(line) as Record<string, unknown>;\n } catch {\n return [];\n }\n const payload = (entry.payload ?? {}) as Record<string, unknown>;\n if (entry.type !== \"response_item\") return [];\n const at = typeof entry.timestamp === \"string\" ? entry.timestamp : new Date(0).toISOString();\n const base =\n typeof payload.id === \"string\"\n ? payload.id\n : createHash(\"sha1\").update(line).digest(\"hex\").slice(0, 16);\n if (payload.type === \"message\" && (payload.role === \"user\" || payload.role === \"assistant\")) {\n const kind = payload.role === \"user\" ? \"user\" : \"assistant\";\n return ((payload.content ?? []) as Array<Record<string, unknown>>).flatMap((item, index) => {\n if (item.type !== \"input_text\" && item.type !== \"output_text\") return [];\n const text = clean(String(item.text ?? \"\"));\n return text ? [{ id: `${base}:${index}`, at, kind, text, offset } as const] : [];\n });\n }\n if (payload.type === \"custom_tool_call\" && payload.name === \"apply_patch\") {\n const patch = String(payload.input ?? \"\");\n const files = [...patch.matchAll(/^\\*\\*\\* (?:Add|Update|Delete) File: (.+)$/gm)];\n return files.map((match, index) => ({\n id: `${base}:${index}`,\n at,\n kind: \"edit\" as const,\n path: clip((match[1] ?? \"\").trim(), 500),\n offset,\n }));\n }\n return [];\n}\n\n/** The first line of a file (Codex `session_meta` can be large), up to 2 MB. */\nasync function firstLine(path: string): Promise<string> {\n const handle = await open(path, \"r\");\n try {\n const buffer = Buffer.alloc(2_000_000);\n const { bytesRead } = await handle.read(buffer, 0, buffer.length, 0);\n const end = buffer.subarray(0, bytesRead).indexOf(0x0a);\n return buffer.subarray(0, end === -1 ? bytesRead : end).toString(\"utf8\");\n } finally {\n await handle.close();\n }\n}\n\n/**\n * Codex rollouts whose `session_meta.cwd` is this repository, newest first.\n * Scans the newest `limit` files under `<home>/sessions/YYYY/MM/DD/`.\n */\nexport async function findCodexRollouts(\n root: string,\n codexHome = join(homedir(), \".codex\"),\n limit = 300,\n): Promise<Array<{ path: string; id: string }>> {\n const want = await realpath(root).catch(() => root);\n const files: Array<{ path: string; mtime: number }> = [];\n const walk = async (dir: string, depth: number): Promise<void> => {\n for (const name of await readdir(dir).catch(() => [] as string[])) {\n const path = join(dir, name);\n if (depth < 3) await walk(path, depth + 1);\n else if (name.startsWith(\"rollout-\") && name.endsWith(\".jsonl\")) {\n files.push({\n path,\n mtime: await stat(path).then(\n (s) => s.mtimeMs,\n () => 0,\n ),\n });\n }\n }\n };\n await walk(join(codexHome, \"sessions\"), 0);\n const found: Array<{ path: string; id: string }> = [];\n for (const { path } of files.sort((a, b) => b.mtime - a.mtime).slice(0, limit)) {\n try {\n const meta = JSON.parse(await firstLine(path)) as {\n type?: string;\n payload?: { id?: string; cwd?: string };\n };\n if (meta.type !== \"session_meta\" || !meta.payload?.cwd || !meta.payload.id) continue;\n const cwd = await realpath(meta.payload.cwd).catch(() => meta.payload?.cwd);\n if (cwd === want) found.push({ path, id: meta.payload.id });\n } catch {}\n }\n return found;\n}\n\n/** Journal a Codex rollout as session `codex-<id>` (idempotent, incremental). */\nexport function importCodexRollout(\n root: string,\n rollout: { path: string; id: string },\n now = new Date(),\n): Promise<IngestResult | null> {\n return ingestTranscript(root, `codex-${rollout.id}`, rollout.path, now, eventsFromCodexLine);\n}\n\n/** Recovery text for an agent: bounded, only fields that have content. */\nexport function renderCheckpoint(\n checkpoint: Checkpoint,\n label: string,\n annotate: {\n changed?: string[];\n missing?: string[];\n identity?: string;\n sourceChanged?: boolean;\n } = {},\n): string {\n const mark = (path: string) =>\n annotate.missing?.includes(path)\n ? `${path} (missing now)`\n : annotate.changed?.includes(path)\n ? `${path} (changed since)`\n : path;\n const lines = [\n `## CodeBuddy task checkpoint (${label}, ${checkpoint.updatedAt.slice(0, 16)}Z)`,\n checkpoint.omittedTranscriptLines\n ? `coverage: ${checkpoint.omittedTranscriptLines} oversized transcript line(s) omitted; consult the original transcript`\n : \"\",\n annotate.identity ?? \"\",\n checkpoint.goal ? `goal: ${clip(checkpoint.goal, 300)}` : \"\",\n checkpoint.constraints.length > 0 ? `constraints: ${checkpoint.constraints.join(\" \")}` : \"\",\n checkpoint.editedPaths.length > 0\n ? `edited: ${checkpoint.editedPaths.slice(-8).map(mark).join(\", \")}`\n : \"\",\n checkpoint.verification.length > 0\n ? `checks: ${checkpoint.verification\n .map(\n (run) =>\n `${run.command} (${run.ok === null ? \"no result\" : run.ok ? \"passed\" : \"failed\"}${run.stale ? (annotate.sourceChanged ? \", stale: source changed\" : \", stale: edited after\") : \"\"})`,\n )\n .join(\"; \")}`\n : \"\",\n checkpoint.findings.length > 0 ? `findings: ${checkpoint.findings.slice(-3).join(\" | \")}` : \"\",\n checkpoint.nextAction ? `next: ${checkpoint.nextAction}` : \"\",\n ];\n return clip(lines.filter(Boolean).join(\"\\n\"), 1_500);\n}\n\n/**\n * The checkpoint as of now: edited files whose content changed or vanished\n * since it was taken, and the branch/checkout it was taken on when that differs.\n */\nexport async function renderCheckpointNow(\n root: string,\n checkpoint: Checkpoint,\n label: string,\n): Promise<string> {\n const freshness = await compareFreshness(root, checkpoint.editedPaths, checkpoint.fileHashes);\n const now = await repoIdentity(root);\n const then = checkpoint.identity;\n const moved =\n then && (then.branch !== now.branch || then.gitDir !== now.gitDir)\n ? `recorded on ${then.branch ?? \"no branch\"}${then.head ? ` at ${then.head.slice(0, 7)}` : \"\"}${then.gitDir !== now.gitDir ? ` in ${then.worktree ?? \"another checkout\"}` : \"\"}; now on ${now.branch ?? \"no branch\"}`\n : undefined;\n const sourceChanged = freshness.changed.length > 0 || freshness.missing.length > 0;\n const rendered = sourceChanged\n ? {\n ...checkpoint,\n verification: checkpoint.verification.map((run) => ({ ...run, stale: true })),\n }\n : checkpoint;\n return renderCheckpoint(rendered, label, {\n changed: freshness.changed,\n missing: freshness.missing,\n sourceChanged,\n ...(moved ? { identity: moved } : {}),\n });\n}\n\n/** Unfinished: a stated task whose last check did not pass, or that names a next step. */\nexport function isUnfinished(checkpoint: Checkpoint): boolean {\n if (!checkpoint.goal) return false;\n return (\n checkpoint.nextAction !== null ||\n [...new Map(checkpoint.verification.map((run) => [run.command, run])).values()].some(\n (run) => run.ok !== true || run.stale,\n ) ||\n (checkpoint.editedPaths.length > 0 && checkpoint.verification.length === 0) ||\n (!checkpoint.lastAssistant && checkpoint.verification.length === 0)\n );\n}\n\n/** The newest unfinished checkpoint from another session, at most `maxAgeDays` old. */\nexport async function latestUnfinished(\n root: string,\n excludeSession: string | undefined,\n now = new Date(),\n maxAgeDays = 3,\n): Promise<Checkpoint | null> {\n const cutoff = now.getTime() - maxAgeDays * 86_400_000;\n for (const { session, updatedAt } of await listJournals(root)) {\n if (session === excludeSession || Date.parse(updatedAt) < cutoff) continue;\n const checkpoint = await readCheckpoint(root, session);\n if (checkpoint && isUnfinished(checkpoint)) return checkpoint;\n }\n return null;\n}\n\nconst CONSTRAINT = /\\b(must|never|don't|do not|always|only|without|keep|avoid)\\b/i;\nconst NEXT_STEP = /\\b(next|remaining|todo|still need|then I(?:'ll| will)|will now)\\b/i;\n/** Same rule as the prompt hook's `isFollowUpPrompt`: ≤ 6 words, ≤ 3 task terms. */\nfunction isFollowUp(text: string): boolean {\n return text.split(/\\s+/).filter(Boolean).length <= 6 && taskTerms(text).length <= 3;\n}\n\n/**\n * Fold new evidence into the last checkpoint, independently of the journal tail.\n * Detailed follow-ups keep the active task; explicit switches start fresh. A\n * new substantive prompt after verified completion can also start another task.\n */\nexport function deriveCheckpoint(\n session: string,\n events: JournalEvent[],\n now = new Date(),\n previous?: Checkpoint,\n): Checkpoint {\n let goal = previous?.goal ?? null;\n let constraints = [...(previous?.constraints ?? [])];\n let editedPaths = [...(previous?.editedPaths ?? [])];\n let runs = (previous?.verification ?? []).map((run, index) => ({\n ...run,\n ref: previous?.verificationRefs?.[index] ?? null,\n }));\n let findings = [...(previous?.findings ?? [])];\n let lastAssistant = previous?.lastAssistant ?? \"\";\n let nextAction = previous?.nextAction ?? null;\n let fromSeq = previous?.evidence?.fromSeq ?? events[0]?.seq ?? 0;\n let omittedTranscriptLines = previous?.omittedTranscriptLines ?? 0;\n const continuation =\n /^(?:also|and|please also|following up|continue|keep|do not|don't|instead of|for (?:this|that)|what about|why|how|can you|could you)\\b/i;\n const switchTask =\n /^(?:new task\\s*:|switch (?:tasks?|to)\\b|now (?:refactor|implement|build|create|fix|migrate|port)\\b)/i;\n const bareFollowUp =\n /^(?:continue|go on|yes|ok(?:ay)?|thanks|run (?:the )?(?:tests?|checks?)(?: again)?)[.!]?$/i;\n for (const event of events) {\n if (event.kind === \"user\" && event.text) {\n const completed =\n runs.length > 0 &&\n [...new Map(runs.map((run) => [run.command, run])).values()].every(\n (run) => run.ok === true && !run.stale,\n ) &&\n !nextAction;\n const start = !goal\n ? !bareFollowUp.test(event.text)\n : switchTask.test(event.text) ||\n (completed && !continuation.test(event.text) && !isFollowUp(event.text));\n if (start) {\n goal = event.text;\n constraints = [];\n editedPaths = [];\n runs = [];\n findings = [];\n lastAssistant = \"\";\n nextAction = null;\n fromSeq = event.seq;\n }\n constraints.push(\n ...event.text\n .split(/(?<=[.!?])\\s+/)\n .filter((sentence) => CONSTRAINT.test(sentence))\n .map((sentence) => clip(sentence, 200)),\n );\n constraints = [...new Set(constraints)].slice(-JOURNAL_LIMITS.constraints);\n } else if (event.kind === \"edit\" && event.path) {\n editedPaths = [...new Set([...editedPaths, event.path])].slice(-JOURNAL_LIMITS.editedPaths);\n for (const run of runs) run.stale = true;\n } else if (event.kind === \"command\" && event.text && isVerificationCommand(event.text)) {\n runs.push({ command: clip(event.text, 160), ok: null, stale: false, ref: event.ref ?? null });\n runs = runs.slice(-JOURNAL_LIMITS.verification);\n } else if (event.kind === \"result\" && event.ref) {\n for (const run of runs) if (run.ref === event.ref) run.ok = event.ok ?? null;\n } else if (event.kind === \"assistant\" && event.text) {\n if (lastAssistant) findings.push(clip(lastAssistant, JOURNAL_LIMITS.findingChars));\n findings = findings.slice(-JOURNAL_LIMITS.findings);\n lastAssistant = event.text;\n const next = lastAssistant\n .split(/(?<=[.!?])\\s+/)\n .find((sentence) => NEXT_STEP.test(sentence));\n nextAction = next ? clip(next, 200) : null;\n } else if (event.kind === \"gap\") {\n omittedTranscriptLines++;\n }\n }\n return {\n v: JOURNAL_VERSION,\n session,\n updatedAt: now.toISOString(),\n goal,\n constraints,\n editedPaths,\n verification: runs.map(({ ref: _ref, ...run }) => run),\n verificationRefs: runs.map((run) => run.ref),\n failedApproaches: [\n ...new Set(runs.filter((run) => run.ok === false).map((run) => `${run.command}: failed`)),\n ].slice(-JOURNAL_LIMITS.verification),\n findings,\n lastAssistant,\n ...(omittedTranscriptLines ? { omittedTranscriptLines } : {}),\n nextAction,\n evidence:\n events.length > 0\n ? { fromSeq, toSeq: events.at(-1)?.seq ?? 0 }\n : (previous?.evidence ?? null),\n };\n}\n","import { createHash } from \"node:crypto\";\nimport { resolve } from \"node:path\";\nimport { generateEntityId } from \"../core/ids.js\";\nimport { MemoryFileStore } from \"../core/memory-file-store.js\";\nimport { isEligibleMemory } from \"../core/memory-lifecycle.js\";\nimport { termOverlap } from \"../core/memory-search.js\";\nimport {\n claimText,\n redactPersisted,\n type SensitivityResult,\n scanFields,\n} from \"../core/sensitive.js\";\nimport { WorklogStore } from \"../worklog/store.js\";\nimport { incidentDoubt } from \"./deterministic.js\";\nimport { type ExtractOptions, extractCandidates } from \"./llm.js\";\nimport { matchResolution } from \"./resolution.js\";\nimport { ReviewStore } from \"./review-store.js\";\nimport { revokes } from \"./rules.js\";\nimport type {\n AfterTurnResult,\n CandidateDecision,\n ExtractionInput,\n MemoryCandidate,\n} from \"./types.js\";\n\n/**\n * The capture orchestrator (`context_after_turn`). It extracts candidates,\n * then gates each one:\n *\n * - `ignored` → dropped.\n * - sensitive content → queued for review, flagged (never auto-saved).\n * - `note` (temporary) → queued for review (never durable).\n * - confident fact/decision/incident (≥ threshold) → saved as durable Markdown.\n * - everything else → queued for review (low confidence).\n *\n * The bias is deliberate: durable memory is the exception, review is the rule.\n */\n\n/** Minimum confidence for a fact/decision/incident to skip review. */\nconst AUTO_SAVE_THRESHOLD = 0.7;\n/** The user stated it (rule) or it passed repeatedly (procedure): trusted, still sensitive-scanned. */\nconst STATED_CONFIDENCE = 0.9;\n/**\n * A user's policy-like statement (\"Decision: …\", \"X must …\") that is not an\n * explicit rule: below the auto-save threshold, so a person approves it (and\n * approval makes it a standing rule).\n */\nconst POLICY_CONFIDENCE = 0.6;\n\nexport type CaptureOptions = ExtractOptions & {\n repositoryRoot?: string;\n now?: () => Date;\n};\n\nexport async function captureAfterTurn(\n input: ExtractionInput,\n options: CaptureOptions = {},\n): Promise<AfterTurnResult> {\n const repositoryRoot = resolve(options.repositoryRoot ?? process.cwd());\n const now = options.now ?? (() => new Date());\n const memoryStore = new MemoryFileStore(repositoryRoot);\n const reviewStore = new ReviewStore(repositoryRoot);\n\n const extracted =\n input.extract === false\n ? { candidates: [], source: \"deterministic\" as const }\n : await extractCandidates(input, options);\n const source = extracted.source;\n const candidates = [\n ...extracted.candidates,\n ...(input.userRules ?? []).map((rule) => ruleCandidate(rule)),\n ...(input.userPolicies ?? []).map((policy) => ruleCandidate(policy, POLICY_CONFIDENCE)),\n ...(await procedureCandidates(input, repositoryRoot)),\n ];\n\n const saved: CandidateDecision[] = [];\n const queuedForReview: CandidateDecision[] = [];\n const ignored: CandidateDecision[] = [];\n const reasons: string[] = [];\n\n for (const candidate of candidates) {\n // Scan every text surface that reaches durable Markdown: all candidate\n // fields plus the turn's provenance (verification, paths, agent/plan/session/commit).\n const sensitivity = scanFields([\n claimText(candidate),\n candidate.content,\n candidate.subject,\n candidate.predicate,\n candidate.object,\n ...candidate.paths,\n ...(input.verification ?? []),\n input.agentId,\n input.planId,\n input.sessionId,\n input.commitSha,\n ]);\n const decision = await gate({\n candidate,\n input,\n sensitivity,\n memoryStore,\n reviewStore,\n now,\n });\n reasons.push(`${candidate.class}: ${decision.outcome} — ${decision.reason}`);\n if (decision.outcome === \"saved\") saved.push(decision);\n else if (decision.outcome === \"queued\") queuedForReview.push(decision);\n else ignored.push(decision);\n }\n\n for (const revocation of input.revokedRules ?? []) {\n const decision = await revokeRule(revocation, input, memoryStore, reviewStore, now);\n reasons.push(`rule: ${decision.outcome} — ${decision.reason}`);\n // A matched revocation changes existing memory; only an unmatched one is new.\n if (decision.outcome === \"queued\") queuedForReview.push(decision);\n }\n\n const worklogId = await recordWorklog(\n input,\n saved,\n queuedForReview,\n repositoryRoot,\n now,\n reasons,\n );\n return { saved, queuedForReview, ignored, reasons, extractor: source, worklogId };\n}\n\n/**\n * One worklog entry per meaningful turn (files changed, memory saved, or\n * verification reported), so a later chat can recover the work. A worklog\n * failure never undoes or blocks the memory capture above.\n */\nasync function recordWorklog(\n input: ExtractionInput,\n saved: CandidateDecision[],\n queued: CandidateDecision[],\n repositoryRoot: string,\n now: () => Date,\n reasons: string[],\n): Promise<string | null> {\n const files = input.changedFiles ?? [];\n const verification = input.verification ?? [];\n if (files.length === 0 && saved.length === 0 && verification.length === 0 && !input.investigation)\n return null;\n try {\n return await new WorklogStore(repositoryRoot).record(\n {\n namespace: input.namespace,\n summary: input.summary,\n files,\n verification,\n savedMemory: saved.flatMap((decision) => (decision.ref ? [decision.ref] : [])),\n queuedForReview: queued.flatMap((decision) => (decision.ref ? [decision.ref] : [])),\n ...(input.sessionId !== undefined ? { sessionId: input.sessionId } : {}),\n ...(input.planId !== undefined ? { planId: input.planId } : {}),\n ...(input.commitSha !== undefined ? { commitSha: input.commitSha } : {}),\n ...(input.agentId !== undefined ? { agentId: input.agentId } : {}),\n },\n now(),\n );\n } catch (error) {\n reasons.push(`worklog: not recorded — ${(error as Error).message}`);\n return null;\n }\n}\n\nfunction ruleCandidate(rule: string, confidence = STATED_CONFIDENCE): MemoryCandidate {\n return {\n class: \"decision\",\n content: rule,\n subject: \"rule\",\n predicate: \"rule\",\n object: rule,\n confidence,\n paths: [],\n severity: null,\n };\n}\n\n/**\n * A verification command that passed this turn and in at least one earlier\n * captured turn becomes a procedure (\"Verify with: npm test\"). Dedupe is the\n * usual fingerprint, so it is saved once.\n */\nasync function procedureCandidates(\n input: ExtractionInput,\n repositoryRoot: string,\n): Promise<MemoryCandidate[]> {\n const passed = (input.verification ?? []).filter((line) => line.endsWith(\": passed\"));\n if (passed.length === 0) return [];\n let history: string[][];\n try {\n history = (await new WorklogStore(repositoryRoot).list(input.namespace)).map(\n (entry) => entry.verification,\n );\n } catch {\n return [];\n }\n return [...new Set(passed)]\n .filter((line) => history.some((verification) => verification.includes(line)))\n .map((line) => {\n const command = line.slice(0, -\": passed\".length);\n return {\n class: \"fact\" as const,\n content: `Verify with: ${command}`,\n subject: \"procedure\",\n predicate: \"procedure\",\n object: command,\n confidence: STATED_CONFIDENCE,\n paths: [],\n severity: null,\n };\n });\n}\n\n/** Supersede the live rules a user sentence withdraws; with no match, ask a human. */\nasync function revokeRule(\n revocation: string,\n input: ExtractionInput,\n memoryStore: MemoryFileStore,\n reviewStore: ReviewStore,\n now: () => Date,\n): Promise<CandidateDecision> {\n const candidate: MemoryCandidate = {\n class: \"note\",\n content: revocation,\n subject: \"rule\",\n predicate: \"revoke\",\n object: revocation,\n confidence: 0.4,\n paths: [],\n severity: null,\n };\n const matches = (await memoryStore.listFacts()).filter(\n (fact) =>\n fact.predicate === \"rule\" &&\n isEligibleMemory(fact, { namespace: input.namespace }) &&\n revokes(revocation, fact.object),\n );\n const base = { candidate, sensitive: false, sensitiveReasons: [] };\n if (matches.length === 0) {\n const sensitivity = scanFields([revocation]);\n const decision = await gate({ candidate, input, sensitivity, memoryStore, reviewStore, now });\n return { ...decision, reason: `revocation matched no rule; ${decision.reason}` };\n }\n const marker = `revoked:${now().toISOString()}`;\n for (const fact of matches) await memoryStore.markFactSuperseded(fact.id, marker);\n return {\n ...base,\n outcome: \"saved\",\n reason: `revoked ${matches.map((fact) => fact.id).join(\", \")}`,\n ref: matches[0]?.id as string,\n };\n}\n\nasync function gate(args: {\n candidate: MemoryCandidate;\n input: ExtractionInput;\n sensitivity: SensitivityResult;\n memoryStore: MemoryFileStore;\n reviewStore: ReviewStore;\n now: () => Date;\n}): Promise<CandidateDecision> {\n const { candidate, sensitivity } = args;\n const fingerprint = candidateFingerprint(args.input.namespace, candidate);\n const base = {\n candidate,\n sensitive: sensitivity.sensitive,\n sensitiveReasons: sensitivity.reasons,\n };\n\n if (candidate.class === \"ignored\") {\n return { ...base, outcome: \"ignored\", reason: \"classified as chatter\" };\n }\n\n if (sensitivity.sensitive) {\n const existing = (await args.reviewStore.list()).find(\n (item) => item.fingerprint === fingerprint,\n );\n const ref =\n existing?.id ?? (await queue(args, `sensitive content (${sensitivity.reasons.join(\", \")})`));\n return {\n ...base,\n outcome: \"queued\",\n reason: `sensitive: ${sensitivity.reasons.join(\", \")}`,\n ref,\n };\n }\n\n if (candidate.class === \"note\") {\n const existing = (await args.reviewStore.list()).find(\n (item) => item.fingerprint === fingerprint,\n );\n if (existing) {\n return { ...base, outcome: \"queued\", reason: \"duplicate review candidate\", ref: existing.id };\n }\n const ref = await queue(args, \"temporary note\");\n return { ...base, outcome: \"queued\", reason: \"temporary note held for review\", ref };\n }\n\n if (candidate.confidence < AUTO_SAVE_THRESHOLD) {\n const existing = (await args.reviewStore.list()).find(\n (item) => item.fingerprint === fingerprint,\n );\n if (existing) {\n return { ...base, outcome: \"queued\", reason: \"duplicate review candidate\", ref: existing.id };\n }\n const ref = await queue(args, `low confidence (${candidate.confidence.toFixed(2)})`);\n return {\n ...base,\n outcome: \"queued\",\n reason: `low confidence ${candidate.confidence.toFixed(2)} < ${AUTO_SAVE_THRESHOLD}`,\n ref,\n };\n }\n\n if (candidate.class === \"incident\") {\n const doubt = incidentDoubt(candidate.content);\n if (doubt) {\n const existing = (await args.reviewStore.list()).find(\n (item) => item.fingerprint === fingerprint,\n );\n const ref = existing?.id ?? (await queue(args, `uncertain incident: ${doubt}`));\n return { ...base, outcome: \"queued\", reason: `uncertain incident: ${doubt}`, ref };\n }\n }\n\n if (candidate.class === \"incident\" && isResolution(candidate.content)) {\n const unresolved = await args.memoryStore.listIncidentFacts({\n namespace: args.input.namespace,\n });\n const sharingPaths = await args.memoryStore.findIncidentFactsForPaths({\n namespace: args.input.namespace,\n paths: candidate.paths,\n });\n const match = matchResolution(candidate.content, sharingPaths, unresolved);\n if (match.kind === \"queue\") {\n const ref = await queue(\n args,\n `incident resolution not grounded: ${match.reason}`,\n match.candidates,\n );\n return {\n ...base,\n outcome: \"queued\",\n reason: `resolution not grounded: ${match.reason}`,\n ref,\n };\n }\n await args.memoryStore.markIncidentResolved(match.incident.id, fingerprint);\n return {\n ...base,\n outcome: \"saved\",\n reason: `resolved incident ${match.incident.id} (${match.reason})`,\n ref: match.incident.id,\n };\n }\n\n const superseded = candidate.content.match(/\\bsupersedes\\s+(fact_[a-z0-9]+)\\b/i)?.[1];\n // Mem0-style update check without an LLM: a reworded copy of a live fact is\n // dropped, and a partial overlap goes to review as a possible update rather\n // than being saved beside the fact it may replace. Incidents may recur, and\n // an explicit \"supersedes fact_x\" already says what it replaces.\n if (candidate.class !== \"incident\" && !superseded) {\n const similar = await nearestFact(\n args.memoryStore,\n args.input.namespace,\n candidate,\n fingerprint,\n );\n if (similar && similar.overlap >= DUPLICATE_OVERLAP) {\n return {\n ...base,\n outcome: \"ignored\",\n reason: `near-duplicate of ${similar.id} (${Math.round(similar.overlap * 100)}% shared words)`,\n ref: similar.id,\n };\n }\n if (similar && similar.overlap >= UPDATE_OVERLAP) {\n const existing = (await args.reviewStore.list()).find(\n (item) => item.fingerprint === fingerprint,\n );\n const ref = existing?.id ?? (await queue(args, `possible update of ${similar.id}`));\n return {\n ...base,\n outcome: \"queued\",\n reason: `overlaps ${similar.id} (${Math.round(similar.overlap * 100)}% shared words): review as a possible update`,\n ref,\n };\n }\n }\n\n const ref = await saveDurable(args);\n if (superseded && superseded !== ref) {\n try {\n await args.memoryStore.markFactSuperseded(superseded, ref);\n } catch {\n // A missing/invalid referenced fact does not invalidate the new decision.\n }\n }\n return { ...base, outcome: \"saved\", reason: `confident ${candidate.class} auto-saved`, ref };\n}\n\n/** At or above this word overlap a new fact restates a live one. */\nconst DUPLICATE_OVERLAP = 0.8;\n/** At or above this overlap a new fact may update a live one: a person decides. */\nconst UPDATE_OVERLAP = 0.5;\n\n/** The live fact of this namespace whose content overlaps the candidate most. */\nasync function nearestFact(\n memoryStore: MemoryFileStore,\n namespace: string,\n candidate: MemoryCandidate,\n fingerprint: string,\n): Promise<{ id: string; overlap: number } | null> {\n let best: { id: string; overlap: number } | null = null;\n for (const fact of await memoryStore.listFacts()) {\n // An exact repeat keeps its existing outcome (saveDurable returns that fact).\n if (fact.fingerprint === fingerprint || fact.category === \"incident\") continue;\n if (fact.predicate === \"rule\" || fact.predicate === \"procedure\") continue;\n if (!isEligibleMemory(fact, { namespace })) continue;\n const overlap = termOverlap(candidate.content, fact.content || fact.object);\n if (!best || overlap > best.overlap) best = { id: fact.id, overlap };\n }\n return best;\n}\n\nasync function saveDurable(args: {\n candidate: MemoryCandidate;\n input: ExtractionInput;\n memoryStore: MemoryFileStore;\n now: () => Date;\n}): Promise<string> {\n const { candidate, input, memoryStore, now } = args;\n const fingerprint = candidateFingerprint(input.namespace, candidate);\n const existing = (await memoryStore.listFacts()).find(\n (fact) => fact.namespace === input.namespace && fact.fingerprint === fingerprint,\n );\n if (existing) return existing.id;\n const id = generateEntityId(\"fact\");\n const isIncident = candidate.class === \"incident\";\n await memoryStore.writeFact({\n id,\n namespace: input.namespace,\n subject: candidate.subject,\n predicate: candidate.predicate,\n object: candidate.object,\n confidence: candidate.confidence,\n createdAt: now().toISOString(),\n createdByAgent: input.agentId ?? null,\n sourceInteractionId: null,\n sourceDeleted: false,\n content: candidate.content,\n category: isIncident ? \"incident\" : \"general\",\n paths: candidate.paths,\n severity: isIncident ? candidate.severity : null,\n fingerprint,\n sourcePlanId: input.planId ?? null,\n sourceSessionId: input.sessionId ?? null,\n verification: input.verification ?? [],\n introducedBy: isIncident ? (input.commitSha ?? null) : null,\n });\n return id;\n}\n\nasync function queue(\n args: {\n candidate: MemoryCandidate;\n input: ExtractionInput;\n sensitivity: SensitivityResult;\n reviewStore: ReviewStore;\n now: () => Date;\n },\n reason: string,\n resolvesIncidents: string[] | null = null,\n): Promise<string> {\n const { candidate, input, sensitivity, reviewStore, now } = args;\n const fingerprint = candidateFingerprint(input.namespace, candidate);\n const id = generateEntityId(\"rev\");\n await reviewStore.write({\n id,\n namespace: input.namespace,\n class: candidate.class,\n subject: candidate.subject,\n predicate: candidate.predicate,\n object: candidate.object,\n confidence: candidate.confidence,\n paths: candidate.paths,\n severity: candidate.severity,\n sensitive: sensitivity.sensitive,\n sensitiveReasons: sensitivity.reasons,\n reason,\n createdAt: now().toISOString(),\n createdByAgent: input.agentId ?? null,\n sourcePlanId: input.planId ?? null,\n fingerprint,\n sourceSessionId: input.sessionId ?? null,\n verification: input.verification ?? [],\n content: candidate.content,\n resolvesIncidents,\n });\n await reviewStore.enforceLimit();\n return id;\n}\n\nfunction isResolution(content: string): boolean {\n return /\\b(fixed|resolved|closed|no longer reproduces|verified the fix)\\b/i.test(content);\n}\n\nexport function candidateFingerprint(namespace: string, raw: MemoryCandidate): string {\n // Hash the redacted form so the persisted fingerprint never derives from a raw secret.\n const candidate = redactPersisted(raw);\n const canonical = JSON.stringify({\n namespace: namespace.trim().toLowerCase(),\n class: candidate.class,\n subject: candidate.subject.trim().toLowerCase(),\n predicate: candidate.predicate.trim().toLowerCase(),\n object: candidate.object.trim().replace(/\\s+/g, \" \").toLowerCase(),\n content: candidate.content.trim().replace(/\\s+/g, \" \").toLowerCase(),\n paths: [...new Set(candidate.paths.map((path) => path.replace(/\\\\/g, \"/\")))].sort(),\n });\n return createHash(\"sha256\").update(canonical).digest(\"hex\");\n}\n\n/**\n * Promote a queued review item to a durable fact and remove it from the queue.\n * A queued incident resolution instead resolves the chosen existing incident\n * (`incidentId`, or the single recorded candidate) and returns its id.\n * Powers `codebuddy memory review approve`.\n */\nexport async function approveReviewItem(\n id: string,\n options: { repositoryRoot?: string; now?: () => Date; incidentId?: string } = {},\n): Promise<string> {\n const repositoryRoot = resolve(options.repositoryRoot ?? process.cwd());\n const now = options.now ?? (() => new Date());\n const reviewStore = new ReviewStore(repositoryRoot);\n const memoryStore = new MemoryFileStore(repositoryRoot);\n\n const item = await reviewStore.read(id);\n\n // A queued resolution closes an existing incident; it never writes a new one.\n if (item.resolvesIncidents) {\n const unresolved = await memoryStore.listIncidentFacts({ namespace: item.namespace });\n const target =\n options.incidentId ??\n (item.resolvesIncidents.length === 1 ? item.resolvesIncidents[0] : undefined);\n if (!target) {\n throw new Error(\n item.resolvesIncidents.length === 0\n ? `Review item ${id} is an incident resolution with no candidate incident; pass an incident id to resolve.`\n : `Review item ${id} is an ambiguous incident resolution; pass one incident id. Candidates: ${item.resolvesIncidents.join(\", \")}`,\n );\n }\n if (!unresolved.some((incident) => incident.id === target)) {\n throw new Error(`${target} is not an unresolved incident in namespace ${item.namespace}.`);\n }\n await memoryStore.markIncidentResolved(target, item.fingerprint ?? id);\n await reviewStore.delete(id);\n return target;\n }\n\n const factId = generateEntityId(\"fact\");\n const isIncident = item.class === \"incident\";\n await memoryStore.writeFact({\n id: factId,\n namespace: item.namespace,\n subject: item.subject,\n predicate: item.predicate,\n object: item.object,\n confidence: item.confidence,\n createdAt: now().toISOString(),\n createdByAgent: item.createdByAgent,\n sourceInteractionId: null,\n sourceDeleted: false,\n content: item.content,\n category: isIncident ? \"incident\" : \"general\",\n paths: item.paths,\n severity: isIncident ? (item.severity ?? \"medium\") : null,\n fingerprint: item.fingerprint,\n sourcePlanId: item.sourcePlanId,\n sourceSessionId: item.sourceSessionId,\n verification: item.verification,\n });\n await reviewStore.delete(id);\n return factId;\n}\n","import type { IncidentSeverity } from \"../core/memory-file-store.js\";\nimport type { ExtractionInput, MemoryCandidate, MemoryClass } from \"./types.js\";\n\n/**\n * Deterministic, no-LLM extraction. This is the always-available baseline\n * (offline mode) and the fallback when LLM extraction fails validation. It\n * segments the turn summary into sentences and classifies each with ordered\n * keyword rules. The same input always yields the same candidates, which keeps\n * capture predictable and auditable.\n *\n * Rule order matters: a \"TODO: fix the crash\" is a note, not an incident, so\n * note markers are checked before incident markers.\n */\n\ntype Rule = {\n class: MemoryClass;\n regex: RegExp;\n confidence: number;\n predicate: string;\n subject: string;\n};\n\n/** \"Resolved fact_abc123\": names its incident, so it is unambiguous by construction. */\nconst EXPLICIT_RESOLUTION = /\\b(?:fixed|resolved|closed)\\b.*\\bfact_[a-z0-9]+\\b/i;\n\nconst RULES: Rule[] = [\n {\n class: \"note\",\n subject: \"note\",\n predicate: \"todo\",\n confidence: 0.4,\n regex:\n /\\b(todo|to-do|follow[- ]?up|later|remember to|revisit|temporary|tmp|next time|should probably)\\b/i,\n },\n {\n // Explicit resolution of a named incident (\"Resolved fact_abc123\").\n class: \"incident\",\n subject: \"incident\",\n predicate: \"resolved\",\n confidence: 0.8,\n regex: EXPLICIT_RESOLUTION,\n },\n {\n // An explicit label (\"Decision: …\") is the agent saying this is durable.\n class: \"decision\",\n subject: \"decision\",\n predicate: \"made\",\n confidence: 0.8,\n regex: /^(?:decision|decided)\\s*:/i,\n },\n {\n class: \"fact\",\n subject: \"project\",\n predicate: \"fact\",\n confidence: 0.75,\n regex: /^(?:convention|fact|rule|policy)\\s*:/i,\n },\n {\n class: \"decision\",\n subject: \"decision\",\n predicate: \"made\",\n confidence: 0.8,\n regex:\n /\\b(decided|chose|choose|we will|going with|switched to|switch to|adopt(?:ed)?|agreed|settled on|opt(?:ed)? for)\\b/i,\n },\n {\n class: \"incident\",\n subject: \"incident\",\n predicate: \"occurred\",\n confidence: 0.75,\n regex:\n /\\b(bug|regression|broke|broken|crash(?:ed)?|outage|incident|root cause|failure|failed|null pointer|race condition|deadlock)\\b/i,\n },\n {\n class: \"fact\",\n subject: \"project\",\n predicate: \"fact\",\n confidence: 0.55,\n regex:\n /\\b(uses?|is|are|requires?|depends on|stores?|returns?|implemented|added|supports?|configured|lives in|located|handles?|must)\\b|\\b(?:always|never)\\b(?!\\s+(?:the|a|an|mind)\\b)/i,\n },\n];\n\nconst INCIDENT_REGEX = (RULES.find((rule) => rule.predicate === \"occurred\") as Rule).regex;\nexport const SPECULATIVE =\n /\\b(might|maybe|possibly|could|consider(?:ing)?|planned|planning|should|if|would|unless|whether|suppose|hypothetical(?:ly)?|in theory|in case)\\b/i;\n/**\n * Hedges that make even a labelled or imperative statement uncertain.\n * `SPECULATIVE` without the conditions (\"if\", \"unless\", \"in case\") and\n * \"should\", which in a stated policy are its scope, not doubt.\n */\nexport const HEDGED =\n /\\b(might|maybe|perhaps|possibly|probably|could|consider(?:ing)?|planned|planning|would|whether|suppose|hypothetical(?:ly)?|in theory)\\b/i;\n/**\n * Statements about the moment, not the project: \"for now\", \"today\", \"this\n * session\", \"temporarily\", \"I'll\", \"let me\", \"never mind\", first-person\n * guesses, and \"it must be …\" (a guess, not an obligation).\n */\nexport const NOT_DURABLE =\n /\\b(?:for now|for the moment|right now|today|tonight|tomorrow|yesterday|this (?:session|turn|time|week|sprint)|for this (?:pr|change|task|ticket|branch|commit|session)|temporarily|as a temporary|i['’]ll|i will|i['’]m going to|let me|never ?mind|i think|i guess|i suspect)\\b|^(?:it|this|that|there)\\s+must\\s+be\\b/i;\n/** A label naming the statement's kind: \"Decision:\", \"Rule:\", \"Convention:\", \"Policy:\". */\nexport const DURABLE_LABEL = /^(?:decision|decided|rule|policy|convention|fact)\\s*:/i;\n\n/**\n * Drop a leading list marker and the emphasis around a leading label, so\n * \"- **Decision:** x\" reads \"Decision: x\". Nothing else in the sentence is\n * touched (`src/**` and `__init__` stay as written).\n */\nexport function stripDecoration(sentence: string): string {\n return sentence\n .replace(/^(?:[-*•]\\s+|\\d+[.)]\\s+)/, \"\")\n .replace(\n /^(?:\\*{1,2}|_{1,2})?(decision|decided|rule|policy|convention|fact)(?:\\*{1,2}|_{1,2})?\\s*:\\s*(?:\\*{1,2}|_{1,2})?\\s*/i,\n \"$1: \",\n )\n .trim();\n}\n// \"no longer reproduces\" is a resolution, not a negation.\nconst NEGATION =\n /\\b(no|not|never|none|nothing|nobody|without|zero|neither|nor|cannot)\\b(?!\\s+longer)|\\w+n['’]t\\b/i;\nconst EXAMPLE = /\\b(?:e\\.g|i\\.e|for example|for instance|such as|example|sample|hypothetical)\\b/i;\n// Balanced \"double\", \\u201ccurly\\u201d and `code` quotes.\nconst QUOTED = /\"[^\"]*\"|\\u201c[^\\u201d]*\\u201d|`[^`]*`/g;\n\n/**\n * Why an incident-looking sentence is not trustworthy enough to become a\n * durable incident: negated (\"no crash occurred\"), hypothetical (\"if it\n * crashes\"), or quoted/example text. Returns null when it reads as a real\n * event. Shared by the deterministic extractor and the capture gate so LLM\n * candidates get the same scrutiny.\n */\nexport function incidentDoubt(sentence: string): string | null {\n if (EXPLICIT_RESOLUTION.test(sentence)) return null;\n const unquoted = sentence.replace(QUOTED, \" \");\n const onlyQuoted = INCIDENT_REGEX.test(sentence) && !INCIDENT_REGEX.test(unquoted);\n const unbalanced = (sentence.match(/[\"\\u201c\\u201d]/g)?.length ?? 0) % 2 === 1;\n if (onlyQuoted || unbalanced || EXAMPLE.test(sentence)) return \"quoted or example text\";\n if (NEGATION.test(unquoted)) return \"negated statement\";\n if (SPECULATIVE.test(unquoted) && !EXPLICIT_DECISION.test(unquoted))\n return \"hypothetical statement\";\n return null;\n}\nconst EXPLICIT_DECISION = /\\b(decided|chose|agreed|settled on|adopted|switched to)\\b/i;\n\nconst SEVERITY_MARKERS: Array<{ severity: IncidentSeverity; regex: RegExp }> = [\n { severity: \"critical\", regex: /\\b(critical|outage|data loss|corruption|security)\\b/i },\n {\n severity: \"high\",\n regex: /\\b(high severity|regression|crash(?:ed)?|deadlock|broke production)\\b/i,\n },\n { severity: \"low\", regex: /\\b(minor|cosmetic|typo|trivial)\\b/i },\n];\n\nexport function deterministicExtract(input: ExtractionInput): MemoryCandidate[] {\n const changedFiles = (input.changedFiles ?? []).filter(Boolean);\n const candidates: MemoryCandidate[] = [];\n\n for (const sentence of splitSentences(input.summary).map(stripDecoration)) {\n const classified = classify(sentence);\n const doubt = classified?.class === \"incident\" ? incidentDoubt(sentence) : null;\n // A labelled statement's \"if\"/\"unless\"/\"should\" scope it; only hedges doubt it.\n const speculative = DURABLE_LABEL.test(sentence)\n ? HEDGED.test(sentence)\n : SPECULATIVE.test(sentence) &&\n !EXPLICIT_DECISION.test(sentence) &&\n !EXPLICIT_RESOLUTION.test(sentence);\n const rule =\n doubt || speculative\n ? {\n class: \"note\" as const,\n subject: \"speculation\",\n predicate: \"consider\",\n confidence: 0.3,\n regex: SPECULATIVE,\n }\n : classified;\n // \"For now…\", \"today…\", \"I'll…\": true this turn, not a project fact.\n const passing =\n (rule?.class === \"decision\" || rule?.class === \"fact\") && NOT_DURABLE.test(sentence);\n if (!rule || passing) {\n candidates.push(ignoredCandidate(sentence));\n continue;\n }\n\n const isIncident = rule.class === \"incident\";\n let confidence = rule.confidence;\n if (isIncident && /\\broot cause\\b/i.test(sentence)) confidence = Math.min(1, confidence + 0.1);\n\n candidates.push({\n class: rule.class,\n content: sentence,\n subject: rule.subject,\n predicate: rule.predicate,\n object: sentence,\n confidence,\n // Incidents and decisions carry the change set so recall can link them to\n // the files they concern (the risk incident signal matches on paths).\n paths: rule.class === \"incident\" || rule.class === \"decision\" ? changedFiles : [],\n severity: isIncident ? guessSeverity(sentence) : null,\n });\n }\n\n return candidates;\n}\n\nfunction classify(sentence: string): Rule | null {\n for (const rule of RULES) {\n if (rule.regex.test(sentence)) return rule;\n }\n return null;\n}\n\nfunction ignoredCandidate(sentence: string): MemoryCandidate {\n return {\n class: \"ignored\",\n content: sentence,\n subject: \"chatter\",\n predicate: \"ignored\",\n object: sentence,\n confidence: 0.2,\n paths: [],\n severity: null,\n };\n}\n\nfunction guessSeverity(sentence: string): IncidentSeverity {\n for (const marker of SEVERITY_MARKERS) {\n if (marker.regex.test(sentence)) return marker.severity;\n }\n return \"medium\";\n}\n\n/** Split into trimmed sentences on terminators and newlines; drop tiny fragments. */\nexport function splitSentences(summary: string): string[] {\n return summary\n .split(/(?<=[.!?])(?<!\\b(?:e\\.g|i\\.e|vs|etc)\\.)\\s+|\\n+/)\n .map((sentence) => sentence.trim().replace(/^[-*•]\\s*/, \"\"))\n .filter((sentence) => sentence.length > 3);\n}\n","import { z } from \"zod\";\nimport { deterministicExtract } from \"./deterministic.js\";\nimport { type ExtractionInput, type MemoryCandidate, memoryCandidateSchema } from \"./types.js\";\n\n/**\n * LLM-assisted extraction is optional and never trusted blindly. An extractor\n * returns raw JSON; we validate it strictly against the candidate schema and\n * retry a bounded number of times. If it never produces valid output — or no\n * extractor is configured — we fall back to the deterministic parser rather\n * than inventing certainty. Raw LLM output is a suggestion, not a fact.\n */\n\n/** Pluggable model backend. Returns unvalidated candidate JSON. */\nexport type MemoryExtractor = {\n extract(input: ExtractionInput): Promise<unknown>;\n};\n\nconst candidateArraySchema = z.array(memoryCandidateSchema);\n\nexport type ExtractOptions = {\n extractor?: MemoryExtractor;\n retries?: number;\n};\n\nexport type ExtractOutcome = {\n candidates: MemoryCandidate[];\n source: \"deterministic\" | \"llm\";\n};\n\nexport async function extractCandidates(\n input: ExtractionInput,\n options: ExtractOptions = {},\n): Promise<ExtractOutcome> {\n if (options.extractor) {\n const validated = await tryLlmExtraction(input, options.extractor, options.retries ?? 2);\n if (validated) return { candidates: validated, source: \"llm\" };\n }\n return { candidates: deterministicExtract(input), source: \"deterministic\" };\n}\n\nasync function tryLlmExtraction(\n input: ExtractionInput,\n extractor: MemoryExtractor,\n retries: number,\n): Promise<MemoryCandidate[] | null> {\n for (let attempt = 0; attempt <= retries; attempt++) {\n try {\n const parsed = candidateArraySchema.safeParse(await extractor.extract(input));\n if (parsed.success) return parsed.data;\n } catch {\n // Swallow and retry; a throwing extractor is treated like invalid output.\n }\n }\n return null;\n}\n","import type { IncidentFactFile } from \"../core/memory-file-store.js\";\n\n/**\n * Deciding which unresolved incident a \"fixed X\" statement closes. A shared\n * file is never enough: resolution needs an explicit incident id, or fix text\n * that matches exactly one candidate's terms better than every other one.\n * Anything else is ambiguous and goes to review. Severity/recency never break\n * ties, so a generic fix can't close an unrelated higher-severity incident.\n *\n * Terms every candidate shares (e.g. the module name) say nothing about WHICH\n * incident was fixed, so only terms that tell candidates apart count, and the\n * fix must hit exactly one candidate's distinctive terms. A multi-topic fix\n * that touches two incidents is therefore ambiguous, however many terms match.\n */\n\nexport type ResolutionMatch =\n | { kind: \"resolved\"; incident: IncidentFactFile; reason: string }\n /** `candidates` are the unresolved incident ids a reviewer may pick from. */\n | { kind: \"queue\"; reason: string; candidates: string[] };\n\nconst FACT_ID = /\\bfact_[a-z0-9]+\\b/gi;\n\n// Words that carry no event identity: grammar plus generic fix/bug vocabulary.\nconst GENERIC = new Set(\n (\n \"a an the and or but of in on at to for from by with as is are was were be been it its this that these those \" +\n \"we i you they he she them there then than so not no also again now still just only into onto after before when while \" +\n \"fix fixed fixes fixing resolve resolved resolves resolving close closed closes verify verified verifies \" +\n \"bug bugs issue issues problem problems incident incidents error errors regression longer reproduce reproduces \" +\n \"test tests passed passing work works worked working change changed changes\"\n ).split(\" \"),\n);\n\n/** Lowercased content terms with a crude suffix stem (\"crashed\"/\"crashes\" -> \"crash\"). */\nexport function groundingTerms(text: string): Set<string> {\n const terms = new Set<string>();\n for (const word of text.toLowerCase().match(/[a-z][a-z0-9]+/g) ?? []) {\n if (GENERIC.has(word) || /^fact_/.test(word)) continue;\n terms.add(word.length > 4 ? word.replace(/(ing|ed|es|s)$/, \"\") : word);\n }\n return terms;\n}\n\nexport function matchResolution(\n fixText: string,\n pathCandidates: IncidentFactFile[],\n unresolved: IncidentFactFile[],\n): ResolutionMatch {\n const explicit = [...new Set(fixText.match(FACT_ID)?.map((id) => id.toLowerCase()))];\n if (explicit.length > 0) {\n const named = unresolved.filter((incident) => explicit.includes(incident.id));\n const [only] = named;\n if (named.length === 1 && only) {\n return { kind: \"resolved\", incident: only, reason: `explicit incident id ${only.id}` };\n }\n return {\n kind: \"queue\",\n candidates: named.map((incident) => incident.id),\n reason:\n named.length === 0\n ? \"explicit incident id does not name an unresolved incident\"\n : \"explicit ids name several incidents\",\n };\n }\n\n const candidates = pathCandidates.map((incident) => incident.id);\n const fixTerms = groundingTerms(fixText);\n if (pathCandidates.length === 0) {\n return {\n kind: \"queue\",\n candidates,\n reason: \"no unresolved incident touches the changed paths\",\n };\n }\n if (fixTerms.size === 0) {\n return { kind: \"queue\", candidates, reason: \"fix text names no specific event\" };\n }\n\n const incidentTerms = pathCandidates.map((incident) =>\n groundingTerms(`${incident.subject} ${incident.content}`),\n );\n // With several candidates, ignore terms all of them share (no discriminating power).\n const distinctive = (term: string) =>\n pathCandidates.length === 1 || incidentTerms.some((terms) => !terms.has(term));\n const hits = incidentTerms.map((terms) => [...fixTerms].filter((term) => terms.has(term)));\n const withDistinctive = hits\n .map((matched, index) => ({ index, matched, count: matched.filter(distinctive).length }))\n .filter((entry) => entry.count > 0 || pathCandidates.length === 1);\n\n const [best] = withDistinctive;\n if (!best || withDistinctive.length > 1) {\n return {\n kind: \"queue\",\n candidates,\n reason: best\n ? \"fix text matches distinctive terms of several unresolved incidents\"\n : \"fix text does not single out any unresolved incident\",\n };\n }\n const need = Math.min(2, fixTerms.size);\n if (best.matched.length < need) {\n return { kind: \"queue\", candidates, reason: \"fix text is too weakly grounded in the incident\" };\n }\n const incident = pathCandidates[best.index] as IncidentFactFile;\n return {\n kind: \"resolved\",\n incident,\n reason: `grounded match on ${best.matched.length} shared term${best.matched.length === 1 ? \"\" : \"s\"}`,\n };\n}\n","import { mkdir, readdir, readFile, rename, rm } from \"node:fs/promises\";\nimport { dirname, join, relative, resolve, sep } from \"node:path\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { z } from \"zod\";\nimport {\n assertNoSymlinkBetween,\n composeMarkdown,\n parseFrontMatter,\n writeAtomic,\n} from \"../core/markdown-store-fs.js\";\nimport { INCIDENT_SEVERITIES } from \"../core/memory-file-store.js\";\nimport { redactPersisted } from \"../core/sensitive.js\";\nimport { MEMORY_CLASSES } from \"./types.js\";\n\n/**\n * The review queue holds memory candidates that are not safe to auto-save —\n * low confidence, sensitive content, or an inherently temporary note. Items are\n * plain Markdown with YAML front matter under `.codebuddy/memory/review/`, so\n * they are inspectable, diffable, and deletable by hand. Approving an item\n * promotes it to a durable fact; rejecting deletes it. Nothing here is ever\n * committed automatically.\n */\n\nconst reviewSchema = z.object({\n schemaVersion: z.literal(1),\n id: z.string().regex(/^rev_[a-z0-9]+$/),\n namespace: z.string().min(1),\n class: z.enum(MEMORY_CLASSES),\n subject: z.string().min(1),\n predicate: z.string().min(1),\n object: z.string().min(1),\n confidence: z.number().min(0).max(1),\n paths: z.array(z.string().min(1)).default([]),\n severity: z.enum(INCIDENT_SEVERITIES).nullable().default(null),\n sensitive: z.boolean().default(false),\n sensitiveReasons: z.array(z.string()).default([]),\n reason: z.string(),\n createdAt: z.string(),\n createdByAgent: z.string().nullable(),\n sourcePlanId: z.string().nullable().default(null),\n fingerprint: z\n .string()\n .regex(/^[a-f0-9]{64}$/)\n .nullable()\n .default(null),\n sourceSessionId: z.string().nullable().default(null),\n verification: z.array(z.string()).default([]),\n /**\n * Set only on a queued incident *resolution* (\"Fixed X\") that could not be\n * grounded: the unresolved incident ids it might close. Approving it resolves\n * one of them instead of writing a new incident. null = ordinary item.\n */\n resolvesIncidents: z.array(z.string()).nullable().default(null),\n});\n\nexport type ReviewItemWrite = Omit<\n z.infer<typeof reviewSchema>,\n \"schemaVersion\" | \"fingerprint\" | \"sourceSessionId\" | \"verification\" | \"resolvesIncidents\"\n> & {\n resolvesIncidents?: string[] | null;\n fingerprint?: string | null;\n sourceSessionId?: string | null;\n verification?: string[];\n content: string;\n};\nexport type ReviewItem = z.infer<typeof reviewSchema> & { content: string; path: string };\n\nexport class ReviewStore {\n readonly repositoryRoot: string;\n readonly reviewDirectory: string;\n readonly archiveDirectory: string;\n\n constructor(repositoryRoot = process.cwd()) {\n this.repositoryRoot = resolve(repositoryRoot);\n this.reviewDirectory = join(this.repositoryRoot, \".codebuddy\", \"memory\", \"review\");\n this.archiveDirectory = join(this.repositoryRoot, \".codebuddy\", \"memory\", \"review-archive\");\n }\n\n async write(raw: ReviewItemWrite): Promise<string> {\n // Persistence boundary: nothing sensitive reaches disk, whatever the caller did.\n const input = redactPersisted(raw);\n const path = this.itemPath(input.id);\n await this.prepareDirectory();\n await assertNoSymlinkBetween(this.repositoryRoot, dirname(path));\n const frontMatter = stringifyYaml({\n schemaVersion: 1,\n id: input.id,\n namespace: input.namespace,\n class: input.class,\n subject: input.subject,\n predicate: input.predicate,\n object: input.object,\n confidence: input.confidence,\n paths: input.paths,\n severity: input.severity,\n sensitive: input.sensitive,\n sensitiveReasons: input.sensitiveReasons,\n reason: input.reason,\n createdAt: input.createdAt,\n createdByAgent: input.createdByAgent,\n sourcePlanId: input.sourcePlanId,\n fingerprint: input.fingerprint,\n sourceSessionId: input.sourceSessionId,\n verification: input.verification,\n resolvesIncidents: input.resolvesIncidents ?? null,\n });\n await writeAtomic(path, composeMarkdown(frontMatter, input.content));\n return path;\n }\n\n async read(id: string): Promise<ReviewItem> {\n const path = this.itemPath(id);\n await assertNoSymlinkBetween(this.repositoryRoot, path);\n const parsed = parseFrontMatter(await readFile(path, \"utf8\"));\n return {\n ...reviewSchema.parse(parseYaml(parsed.frontMatter)),\n content: parsed.content.trim(),\n path,\n };\n }\n\n async list(): Promise<ReviewItem[]> {\n try {\n await this.prepareDirectory();\n const entries = await readdir(this.reviewDirectory, { withFileTypes: true });\n const items: ReviewItem[] = [];\n for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {\n if (!entry.isFile() || !entry.name.endsWith(\".md\")) continue;\n // Only managed review files are queue items. A hand-written README.md\n // (or any non-rev_ markdown) must be ignored, not thrown on — one\n // stray file used to brick every future capture turn.\n if (!/^rev_[a-z0-9]+\\.md$/.test(entry.name)) continue;\n try {\n items.push(await this.read(entry.name.replace(/\\.md$/, \"\")));\n } catch {\n // A single corrupt item is skipped rather than poisoning the whole\n // queue; it stays on disk for manual inspection.\n }\n }\n return items;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return [];\n throw error;\n }\n }\n\n async delete(id: string): Promise<void> {\n await rm(this.itemPath(id), { force: true });\n }\n\n async archiveExpired(options: { olderThanDays?: number; now?: Date } = {}): Promise<number> {\n const cutoff =\n (options.now ?? new Date()).getTime() - (options.olderThanDays ?? 30) * 24 * 60 * 60 * 1000;\n const items = await this.list();\n let archived = 0;\n for (const item of items) {\n if (Date.parse(item.createdAt) >= cutoff) continue;\n await this.archive(item);\n archived++;\n }\n return archived;\n }\n\n async enforceLimit(maxItems = 500): Promise<number> {\n const items = (await this.list()).sort((left, right) =>\n left.createdAt.localeCompare(right.createdAt),\n );\n const overflow = Math.max(0, items.length - maxItems);\n for (const item of items.slice(0, overflow)) await this.archive(item);\n return overflow;\n }\n\n private async archive(item: ReviewItem): Promise<void> {\n await mkdir(this.archiveDirectory, { recursive: true, mode: 0o700 });\n await assertNoSymlinkBetween(this.repositoryRoot, this.archiveDirectory);\n await rename(item.path, join(this.archiveDirectory, `${item.id}.md`));\n }\n\n private itemPath(id: string): string {\n if (!/^rev_[a-z0-9]+$/.test(id)) throw new Error(`Invalid review id: ${id}`);\n return this.safePath(join(this.reviewDirectory, `${id}.md`));\n }\n\n private safePath(path: string): string {\n const absolute = resolve(path);\n const relativePath = relative(this.repositoryRoot, absolute);\n if (relativePath === \"..\" || relativePath.startsWith(`..${sep}`) || relativePath === \"\") {\n throw new Error(`Review path escapes repository root: ${path}`);\n }\n return absolute;\n }\n\n private async prepareDirectory(): Promise<void> {\n await assertNoSymlinkBetween(this.repositoryRoot, dirname(this.reviewDirectory));\n await mkdir(this.reviewDirectory, { recursive: true, mode: 0o700 });\n }\n}\n","import { HEDGED, NOT_DURABLE, stripDecoration } from \"./deterministic.js\";\n\n/**\n * Standing rules the user states (\"from now on…\", \"never…\", \"every PR\n * must…\") and revocations of them (\"stop…\", \"no longer…\"). A rule the user\n * stated is the most trustworthy memory there is, so it is read from the\n * user's own prompt, never from the assistant's paraphrase. Questions,\n * hedged and temporary statements (\"for now\", \"today\", \"I'll\") are not rules.\n *\n * Policies are durable-looking statements that are not explicit rules\n * (\"Decision: …\", \"Convention: …\", \"<subject> must …\", \"we decided …\"): they\n * go to the review queue, never straight to memory.\n */\n\nconst MAX_RULE_CHARS = 300;\n/** CodeBuddy's injected context starts here; nothing after it is the user's. */\nconst INJECTED_BLOCK = /^##\\s*CodeBuddy\\b/m;\n/** Quoted or code material is never an instruction to this project. */\nconst FENCED_CODE = /```[\\s\\S]*?(?:```|$)/g;\nconst QUOTE_LINE = /^\\s*>.*$/gm;\n/** An explicit rule introduction: \"from now on\", \"going forward\", \"(a) rule (for …):\". */\nconst RULE_PREFIX =\n /^(?:also,?\\s+|please,?\\s+)?(?:from now on|going forward|(?:a\\s+)?rule\\b[^:.]{0,60}:)[,:]?\\s*/i;\n/** Imperative position: the sentence itself starts with the marker, or \"we/you always|never|must\". */\nconst IMPERATIVE =\n /^(?:please,?\\s+)?(?:always|never)\\s+(?!(?:the|a|an|mind|so|again|ever)\\b)\\S+\\s+\\S+|^(?:we|you)\\s+(?:always|never|must)\\b|^every\\s+(?!time\\b)\\S+.*\\bmust\\b/i;\n/**\n * A stated policy for review: a decision/convention/policy label, \"we\n * decided/agreed …\", or \"<noun phrase> must (not) <verb>\". Not \"I/it/this\n * must …\", \"must be <verb>ing\" or \"must have been/<verb>ed\": those are guesses.\n */\nconst POLICY =\n /^(?:decision|decided|convention|policy)\\s*:\\s*\\S+\\s+\\S+|^we\\s+(?:decided|agreed|settled on|chose)\\b|^(?!(?:i|it|this|that|there|he|she|they|which|what)\\b)[a-z][\\w-]*(?:\\s+[\\w./-]+){0,6}\\s+must(?:\\s+not|n['’]t)?\\s+(?!be\\s+\\w+ing\\b|have\\s+(?:been\\b|\\w+ed\\b))\\w+/i;\nconst QUESTION_START =\n /^(?:why|how|what|when|where|which|who|can|could|would|will|do|does|did|is|are|should)\\b/i;\n/** Withdrawal of a rule: \"stop <verb>ing\", \"no longer\", \"don't … anymore\", \"forget the rule\". */\nconst REVOCATION_MARKER =\n /^(?:please,?\\s+)?stop\\s+\\w+ing\\b|\\bno longer\\b|\\b(?:don't|do not)\\b.*\\banymore\\b|\\b(?:forget|drop|remove)\\s+the\\s+rule\\b/i;\nconst STOPWORDS = new Set([\n \"the\",\n \"and\",\n \"for\",\n \"from\",\n \"now\",\n \"always\",\n \"never\",\n \"rule\",\n \"about\",\n \"longer\",\n \"don't\",\n \"anymore\",\n \"every\",\n \"must\",\n \"please\",\n \"with\",\n \"that\",\n \"this\",\n \"our\",\n \"you\",\n]);\n\nexport function extractUserRules(prompts: string[]): {\n rules: string[];\n revocations: string[];\n policies: string[];\n} {\n const rules = new Map<string, string>();\n const revocations = new Map<string, string>();\n const policies = new Map<string, string>();\n for (const prompt of prompts) {\n const own = (prompt.split(INJECTED_BLOCK)[0] ?? \"\")\n .replace(FENCED_CODE, \"\\n\")\n .replace(QUOTE_LINE, \"\");\n for (const raw of own.split(/(?<=[.!?])\\s+|\\n+/)) {\n const sentence = stripDecoration(raw.trim());\n if (!sentence || sentence.length > MAX_RULE_CHARS || sentence.endsWith(\"?\")) continue;\n if (QUESTION_START.test(sentence)) continue;\n const key = sentence\n .toLowerCase()\n .replace(/\\s+/g, \" \")\n .replace(/[.!]+$/, \"\");\n if (REVOCATION_MARKER.test(sentence)) {\n if (!revocations.has(key)) revocations.set(key, sentence);\n continue;\n }\n // \"Never X unless Y\" states a rule's scope; only a hedge or \"for now\" doubts it.\n if (HEDGED.test(sentence) || NOT_DURABLE.test(sentence)) continue;\n if (isRule(sentence)) {\n if (!rules.has(key)) rules.set(key, sentence);\n } else if (POLICY.test(sentence) && !policies.has(key)) {\n policies.set(key, sentence);\n }\n }\n }\n return {\n rules: [...rules.values()],\n revocations: [...revocations.values()],\n policies: [...policies.values()],\n };\n}\n\n/** A rule is explicitly introduced, or an imperative with at least a verb and an object. */\nfunction isRule(sentence: string): boolean {\n const rest = sentence.replace(RULE_PREFIX, \"\");\n if (rest !== sentence) return rest.split(/\\s+/).filter(Boolean).length >= 3;\n return IMPERATIVE.test(sentence);\n}\n\n/** Content words, crudely stemmed so \"running\"/\"run\" and \"committing\"/\"commit\" match. */\nexport function ruleWords(text: string): Set<string> {\n return new Set(\n (text.toLowerCase().match(/[a-z][a-z'-]+/g) ?? [])\n .filter((word) => word.length >= 3 && !STOPWORDS.has(word))\n .map((word) => word.replace(/(?:ing|ed|es|s)$/, \"\").replace(/([b-df-hj-np-tv-z])\\1$/, \"$1\")),\n );\n}\n\n/**\n * A revocation names a rule only when it repeats every content word of the\n * rule; anything looser goes to review instead of silently dropping a rule.\n */\nexport function revokes(revocation: string, rule: string): boolean {\n const ruleSet = ruleWords(rule);\n if (ruleSet.size === 0) return false;\n const words = ruleWords(revocation);\n return [...ruleSet].every((word) => words.has(word));\n}\n","import pTimeout from \"p-timeout\";\nimport type { ContextReranker, SemanticRelevanceRanker } from \"../context/engine.js\";\nimport { loadRuntimeConfig, readConfigFile } from \"../core/config-file.js\";\nimport type { RuntimeHandle } from \"../core/operations.js\";\nimport { DEFAULT_RERANK_MODELS } from \"../providers/models.js\";\n\n/**\n * The model side of per-prompt recall: dense evidence from PostgreSQL/pgvector,\n * the query embedded by the configured provider (local by default). Optional\n * and bounded: a slow or absent database or model leaves lexical recall intact.\n * `CODEBUDDY_SEMANTIC=0` turns it off (never connects to PostgreSQL).\n */\nexport type HookSemantics = {\n semanticRanker?: SemanticRelevanceRanker;\n reranker?: ContextReranker;\n close(): Promise<void>;\n};\n\n/** Connect + namespace lookup; a local PostgreSQL answers in milliseconds. */\nconst CONNECT_BUDGET_MS = 2_500;\n/** Query embedding + exact vector search (the first call also loads the model). */\nconst SEARCH_BUDGET_MS = 3_000;\nconst RERANK_BUDGET_MS = 2_000;\n\n/**\n * The cross-encoder chosen by `.codebuddy/config.json` `rerank` (off by\n * default). Hosted ones need OPENROUTER_API_KEY / HF_TOKEN; without a key\n * (or `CODEBUDDY_RERANK=0`) there is none and the fused order stands.\n */\nexport async function configuredReranker(\n repositoryRoot: string,\n): Promise<ContextReranker | undefined> {\n if (process.env.CODEBUDDY_RERANK === \"0\") return undefined;\n const file = await readConfigFile(repositoryRoot);\n const provider = file.rerank?.provider ?? \"off\";\n if (provider === \"off\") return undefined;\n const model = file.rerank?.model ?? DEFAULT_RERANK_MODELS[provider].id;\n const bounded = (scores: Promise<number[]>) =>\n pTimeout(scores, { milliseconds: RERANK_BUDGET_MS });\n if (provider === \"local\") {\n const revision =\n model === DEFAULT_RERANK_MODELS.local.id ? DEFAULT_RERANK_MODELS.local.revision : undefined;\n return async (task, documents) => {\n const { rerankLocally } = await import(\"../providers/local.js\");\n return bounded(\n rerankLocally({ id: model, ...(revision ? { revision } : {}) }, task, documents),\n );\n };\n }\n const apiKey =\n provider === \"openrouter\"\n ? process.env.OPENROUTER_API_KEY\n : (process.env.HF_TOKEN ?? file.provider?.apiKey);\n if (!apiKey) return undefined;\n const { rerankHuggingFace, rerankOpenRouter } = await import(\"../providers/cloud.js\");\n const call = provider === \"openrouter\" ? rerankOpenRouter : rerankHuggingFace;\n return (task, documents) => call({ apiKey, model, timeoutMs: RERANK_BUDGET_MS }, task, documents);\n}\n\nexport async function openHookSemantics(repositoryRoot: string): Promise<HookSemantics> {\n let runtime: Promise<RuntimeHandle | null> | null = null;\n const connect = async (): Promise<RuntimeHandle | null> => {\n const config = await loadRuntimeConfig(repositoryRoot, { requireDatabase: false });\n if (!config.postgresUrl) return null;\n const { createRuntime } = await import(\"../core/operations.js\");\n const opening = createRuntime(config, {\n repositoryRoot,\n startWorker: false,\n connectTimeoutSeconds: 2,\n });\n try {\n return await pTimeout(opening, { milliseconds: CONNECT_BUDGET_MS });\n } catch {\n // Too slow: release whatever eventually connects.\n void opening.then((handle) => handle.close()).catch(() => undefined);\n return null;\n }\n };\n\n const semanticRanker: SemanticRelevanceRanker | undefined =\n process.env.CODEBUDDY_SEMANTIC === \"0\"\n ? undefined\n : async (task, candidates) => {\n runtime ??= connect().catch(() => null);\n const handle = await runtime;\n if (!handle) return {};\n return handle.memory.rankContextFacts(\n task,\n candidates.map(({ id }) => id),\n { timeoutMs: SEARCH_BUDGET_MS },\n );\n };\n\n const reranker = await configuredReranker(repositoryRoot).catch(() => undefined);\n return {\n ...(semanticRanker ? { semanticRanker } : {}),\n ...(reranker ? { reranker } : {}),\n async close() {\n const handle = await runtime?.catch(() => null);\n await handle?.close().catch(() => undefined);\n },\n };\n}\n","import { mkdir, readdir, readFile, rename, rm, stat } from \"node:fs/promises\";\nimport { join, resolve } from \"node:path\";\nimport { writeAtomic } from \"../core/markdown-store-fs.js\";\n\n/**\n * Between the edit hook and the turn-end hook, CodeBuddy needs to remember which\n * files an agent actually changed. This staging store holds that set per session\n * under `.codebuddy/cache/hooks/` (rebuildable, local, gitignored). The turn-end\n * capture hook drains it, so capture works from the *real* change set rather\n * than a summary the model may or may not write.\n */\n/** The staging lock guards a few file writes; one older than this was abandoned. */\nconst STAGING_LOCK_STALE_MS = 10_000;\n\nexport class HookStagingStore {\n readonly directory: string;\n private operations = Promise.resolve();\n\n constructor(repositoryRoot = process.cwd()) {\n this.directory = join(resolve(repositoryRoot), \".codebuddy\", \"cache\", \"hooks\");\n }\n\n async add(sessionId: string, paths: string[]): Promise<void> {\n await this.serialize(async () => {\n const clean = paths.map(normalize).filter(Boolean);\n if (clean.length === 0) return;\n await mkdir(this.directory, { recursive: true, mode: 0o700 });\n await this.withFileLock(sessionId, async () => {\n const merged = [...new Set([...(await this.read(sessionId)), ...clean])].sort();\n await writeAtomic(\n this.filePath(sessionId),\n `${JSON.stringify({ paths: merged }, null, 2)}\\n`,\n );\n });\n });\n }\n\n /** Sessions with edits staged but not yet captured by a turn end. */\n async pending(): Promise<Array<{ session: string; paths: number }>> {\n const names = await readdir(this.directory).catch(() => [] as string[]);\n const sessions = names\n .filter((name) => name.endsWith(\".json\"))\n .map((name) => name.slice(0, -5));\n const counts = await Promise.all(\n sessions.map(async (session) => ({ session, paths: (await this.read(session)).length })),\n );\n return counts.filter((entry) => entry.paths > 0);\n }\n\n async read(sessionId: string): Promise<string[]> {\n try {\n const parsed = JSON.parse(await readFile(this.filePath(sessionId), \"utf8\"));\n return Array.isArray(parsed?.paths)\n ? parsed.paths.filter((p: unknown) => typeof p === \"string\")\n : [];\n } catch {\n return [];\n }\n }\n\n /** Return the staged paths and clear them. */\n async drain(sessionId: string): Promise<string[]> {\n return this.serialize(async () => {\n await mkdir(this.directory, { recursive: true, mode: 0o700 });\n return this.withFileLock(sessionId, async () => {\n const path = this.filePath(sessionId);\n const draining = `${path}.${process.pid}.${Date.now()}.drain`;\n try {\n await rename(path, draining);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return [];\n throw error;\n }\n try {\n const parsed = JSON.parse(await readFile(draining, \"utf8\"));\n return Array.isArray(parsed?.paths)\n ? parsed.paths.filter((item: unknown) => typeof item === \"string\")\n : [];\n } finally {\n await rm(draining, { force: true });\n }\n });\n });\n }\n\n /** Claim a batch without consuming edits staged while capture runs. */\n async claim(sessionId: string): Promise<string[] | null> {\n await mkdir(this.directory, { recursive: true, mode: 0o700 });\n const captureLock = `${this.filePath(sessionId)}.capture-lock`;\n for (let attempt = 0; ; attempt++) {\n try {\n await mkdir(captureLock);\n break;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") throw error;\n const age =\n Date.now() - (await stat(captureLock).catch(() => ({ mtimeMs: Date.now() }))).mtimeMs;\n if (age > 60_000) {\n await rm(captureLock, { recursive: true, force: true });\n continue;\n }\n if (attempt >= 200) return null;\n await new Promise((resolveWait) => setTimeout(resolveWait, 10));\n }\n }\n try {\n return await this.withFileLock(sessionId, async () => {\n const claimed = this.claimPath(sessionId);\n try {\n return parsePaths(await readFile(claimed, \"utf8\"));\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n }\n try {\n await rename(this.filePath(sessionId), claimed);\n return parsePaths(await readFile(claimed, \"utf8\"));\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return [];\n throw error;\n }\n });\n } catch (error) {\n await rm(captureLock, { recursive: true, force: true });\n throw error;\n }\n }\n\n /** Acknowledge only the claimed batch; later edits remain staged. */\n async acknowledge(sessionId: string): Promise<void> {\n await this.withFileLock(sessionId, async () => {\n await rm(this.claimPath(sessionId), { force: true });\n });\n await rm(`${this.filePath(sessionId)}.capture-lock`, { recursive: true, force: true });\n }\n\n /** Restore the claimed batch for retry, merging edits that arrived during capture. */\n async rollback(sessionId: string): Promise<void> {\n await this.withFileLock(sessionId, async () => {\n const claimed = await readFile(this.claimPath(sessionId), \"utf8\")\n .then(parsePaths)\n .catch(() => []);\n const merged = [...new Set([...claimed, ...(await this.read(sessionId))])].sort();\n if (merged.length > 0)\n await writeAtomic(\n this.filePath(sessionId),\n `${JSON.stringify({ paths: merged }, null, 2)}\\n`,\n );\n await rm(this.claimPath(sessionId), { force: true });\n });\n await rm(`${this.filePath(sessionId)}.capture-lock`, { recursive: true, force: true });\n }\n\n private claimPath(sessionId: string): string {\n return `${this.filePath(sessionId)}.claimed`;\n }\n\n private async withFileLock<T>(sessionId: string, operation: () => Promise<T>): Promise<T> {\n const lock = `${this.filePath(sessionId)}.lock`;\n for (let attempt = 0; ; attempt++) {\n try {\n await mkdir(lock);\n break;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\" || attempt >= 200) throw error;\n // A hook killed while holding the lock (host timeout, crash) would\n // otherwise block this session's staging forever. Every operation\n // under it is a few file writes, so 10 s is certainly stale.\n const age = await stat(lock).then(\n (info) => Date.now() - info.mtimeMs,\n () => 0,\n );\n if (age > STAGING_LOCK_STALE_MS) {\n await rm(lock, { recursive: true, force: true });\n continue;\n }\n await new Promise((resolveWait) => setTimeout(resolveWait, 10));\n }\n }\n try {\n return await operation();\n } finally {\n await rm(lock, { recursive: true, force: true });\n }\n }\n\n private async serialize<T>(operation: () => Promise<T>): Promise<T> {\n const previous = this.operations;\n let release!: () => void;\n this.operations = new Promise<void>((resolveOperation) => {\n release = resolveOperation;\n });\n await previous;\n try {\n return await operation();\n } finally {\n release();\n }\n }\n\n private filePath(sessionId: string): string {\n const safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, \"_\") || \"default\";\n return join(this.directory, `${safe}.json`);\n }\n}\n\nfunction normalize(path: string): string {\n return path.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\").trim();\n}\n\nfunction parsePaths(raw: string): string[] {\n const parsed = JSON.parse(raw);\n return Array.isArray(parsed?.paths)\n ? parsed.paths.filter((path: unknown): path is string => typeof path === \"string\")\n : [];\n}\n"],"mappings":"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","names":["mkdir","readFile","rm","stat","dirname","isAbsolute","join","relative","resolve","sep","pTimeout","execFile","join","resolve","promisify","resolve","spawn","realpath","dirname","relative","resolve","sep","stat","readFile","resolve","readFile","join","parseYaml","z","resolve","paths","file","realpath","dirname","sep","normalizePath","relative","runGit","spawn","mkdir","readdir","readFile","dirname","join","resolve","parseYaml","stringifyYaml","z","readFile","relative","resolve","sep","resolve","relative","sep","readFile","paths","z","resolve","join","normalizePath","dirname","mkdir","stringifyYaml","readFile","parseYaml","readdir","paths","file","LIMITS","promisify","execFile","resolve","fresh","join","file","paths","hit","words","mkdir","readFile","dirname","join","join","readFile","mkdir","dirname","createHash","mkdir","open","readdir","readFile","realpath","rm","stat","join","relative","sep","join","clean","createHash","clip","readFile","open","run","mkdir","stat","rm","resolve","relative","sep","readdir","realpath","createHash","resolve","z","z","incident","mkdir","readdir","readFile","rm","dirname","join","relative","resolve","sep","parseYaml","stringifyYaml","z","z","resolve","join","dirname","stringifyYaml","readFile","parseYaml","readdir","rm","mkdir","relative","sep","words","resolve","ref","createHash","pTimeout","file","pTimeout","mkdir","readdir","readFile","rename","rm","stat","join","resolve","join","resolve","paths","clean","normalize","mkdir","readdir","readFile","rename","rm","stat","file","words","clip","paths","join","mkdir","dirname","rm","pTimeout","stat","isAbsolute","resolve","relative","sep","run","TAGGED_BLOCK","readFile","targets"]}