@orquentra/codebuddy 2.14.0 → 2.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +98 -0
- package/README.md +87 -6
- package/dist/{chunk-YNSTIMCF.js → chunk-4DTO2E4Y.js} +352 -157
- package/dist/chunk-4DTO2E4Y.js.map +1 -0
- package/dist/{chunk-CAEPHLHC.js → chunk-57642NGU.js} +2 -44
- package/dist/chunk-57642NGU.js.map +1 -0
- package/dist/chunk-6OQKL35B.js +55 -0
- package/dist/chunk-6OQKL35B.js.map +1 -0
- package/dist/{chunk-4DKYKDHI.js → chunk-7IPSDDO5.js} +5 -3
- package/dist/{chunk-4DKYKDHI.js.map → chunk-7IPSDDO5.js.map} +1 -1
- package/dist/chunk-7JPUMXFE.js +413 -0
- package/dist/chunk-7JPUMXFE.js.map +1 -0
- package/dist/{chunk-LRQNPYCK.js → chunk-AFXWCSQ4.js} +13 -7
- package/dist/chunk-AFXWCSQ4.js.map +1 -0
- package/dist/chunk-BNZDEU5K.js +368 -0
- package/dist/chunk-BNZDEU5K.js.map +1 -0
- package/dist/chunk-EMWGLKPR.js +45 -0
- package/dist/chunk-EMWGLKPR.js.map +1 -0
- package/dist/{chunk-YJPCS2GP.js → chunk-GNV4X67F.js} +59 -20
- package/dist/chunk-GNV4X67F.js.map +1 -0
- package/dist/{chunk-YWDH6DQ6.js → chunk-IM5RFEW4.js} +21 -19
- package/dist/{chunk-YWDH6DQ6.js.map → chunk-IM5RFEW4.js.map} +1 -1
- package/dist/chunk-K4XNTYV7.js +136 -0
- package/dist/chunk-K4XNTYV7.js.map +1 -0
- package/dist/{chunk-ESZXCZIN.js → chunk-MNSMW4MZ.js} +33 -5
- package/dist/chunk-MNSMW4MZ.js.map +1 -0
- package/dist/chunk-NNJSAYHY.js +372 -0
- package/dist/chunk-NNJSAYHY.js.map +1 -0
- package/dist/{chunk-XSNW6Y3X.js → chunk-OO7Q7XZF.js} +28 -24
- package/dist/chunk-OO7Q7XZF.js.map +1 -0
- package/dist/{chunk-L6BRYZ6G.js → chunk-PZ4EBFIA.js} +7 -7
- package/dist/{chunk-L6BRYZ6G.js.map → chunk-PZ4EBFIA.js.map} +1 -1
- package/dist/chunk-RGIVHKBH.js +156 -0
- package/dist/chunk-RGIVHKBH.js.map +1 -0
- package/dist/{chunk-LW75SKZR.js → chunk-RKF4HBBQ.js} +126 -18
- package/dist/chunk-RKF4HBBQ.js.map +1 -0
- package/dist/{chunk-7QMHIJBA.js → chunk-VBDM7HC5.js} +969 -968
- package/dist/chunk-VBDM7HC5.js.map +1 -0
- package/dist/chunk-VF7DKRIU.js +50 -0
- package/dist/chunk-VF7DKRIU.js.map +1 -0
- package/dist/{chunk-KNR2P2UY.js → chunk-Y4QQML24.js} +21 -6
- package/dist/chunk-Y4QQML24.js.map +1 -0
- package/dist/cli/index.js +4 -4
- package/dist/config-S2BDMT4B.js +15 -0
- package/dist/expand-TONFVT5D.js +98 -0
- package/dist/expand-TONFVT5D.js.map +1 -0
- package/dist/file-vectors-VREL75MA.js +19 -0
- package/dist/index-facts-MBJKBYA3.js +38 -0
- package/dist/index-pass-RP23G2CR.js +15 -0
- package/dist/index.js +24 -22
- package/dist/{install-EU35ERK5.js → install-MCJIJMFF.js} +11 -10
- package/dist/{lean-43ADYTBW.js → lean-CBHVW6JM.js} +8 -7
- package/dist/local-TH5XCLVJ.js +48 -0
- package/dist/local-llm-GZREB5DF.js +19 -0
- package/dist/local-llm-GZREB5DF.js.map +1 -0
- package/dist/{main-SFC5LV4E.js → main-QF6Z552J.js} +346 -140
- package/dist/main-QF6Z552J.js.map +1 -0
- package/dist/{memory-TGHVTBME.js → memory-LSZKSF53.js} +9 -6
- package/dist/{memory-TGHVTBME.js.map → memory-LSZKSF53.js.map} +1 -1
- package/dist/{operations-6Z6ZDVBP.js → operations-BPI633VN.js} +8 -7
- package/dist/operations-BPI633VN.js.map +1 -0
- package/dist/{rerank-IQAEWLQR.js → rerank-EPCTSEVP.js} +7 -4
- package/dist/{rerank-IQAEWLQR.js.map → rerank-EPCTSEVP.js.map} +1 -1
- package/dist/{runtime-W5AW32SD.js → runtime-W5ACTDFS.js} +9 -8
- package/dist/runtime-W5ACTDFS.js.map +1 -0
- package/dist/summaries-W2J5FCLG.js +32 -0
- package/dist/summaries-W2J5FCLG.js.map +1 -0
- package/dist/{zvec-24HLAFGN.js → zvec-LSA2IRAU.js} +13 -5
- package/dist/zvec-LSA2IRAU.js.map +1 -0
- package/package.json +3 -2
- package/dist/chunk-7QMHIJBA.js.map +0 -1
- package/dist/chunk-CAEPHLHC.js.map +0 -1
- package/dist/chunk-ESC4Y3L7.js +0 -204
- package/dist/chunk-ESC4Y3L7.js.map +0 -1
- package/dist/chunk-ESZXCZIN.js.map +0 -1
- package/dist/chunk-KNR2P2UY.js.map +0 -1
- package/dist/chunk-LRQNPYCK.js.map +0 -1
- package/dist/chunk-LW75SKZR.js.map +0 -1
- package/dist/chunk-SFMIMLXR.js +0 -63
- package/dist/chunk-SFMIMLXR.js.map +0 -1
- package/dist/chunk-XSNW6Y3X.js.map +0 -1
- package/dist/chunk-YJPCS2GP.js.map +0 -1
- package/dist/chunk-YNSTIMCF.js.map +0 -1
- package/dist/config-GEZFLXK6.js +0 -12
- package/dist/main-SFC5LV4E.js.map +0 -1
- package/dist/summaries-32PHOB6L.js +0 -20
- /package/dist/{config-GEZFLXK6.js.map → config-S2BDMT4B.js.map} +0 -0
- /package/dist/{install-EU35ERK5.js.map → file-vectors-VREL75MA.js.map} +0 -0
- /package/dist/{lean-43ADYTBW.js.map → index-facts-MBJKBYA3.js.map} +0 -0
- /package/dist/{operations-6Z6ZDVBP.js.map → index-pass-RP23G2CR.js.map} +0 -0
- /package/dist/{runtime-W5AW32SD.js.map → install-MCJIJMFF.js.map} +0 -0
- /package/dist/{summaries-32PHOB6L.js.map → lean-CBHVW6JM.js.map} +0 -0
- /package/dist/{zvec-24HLAFGN.js.map → local-TH5XCLVJ.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/migrate-to-files.ts","../src/telemetry/telemetry.ts","../src/mcp/tools/index.ts","../src/context/delivery.ts","../src/context/reuse.ts","../src/suggest/engine.ts","../src/suggest/types.ts","../src/mcp/database-retry.ts","../src/mcp/tool-result.ts","../src/mcp/server.ts","../src/automation/project-sync.ts","../src/indexer/watch.ts","../src/core/project-root.ts","../src/mcp/database.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { redactPersisted } from \"../core/sensitive.js\";\nimport type { MemoryFileStore } from \"./memory-file-store.js\";\nimport type { MemoryRepository } from \"./repository.js\";\n\nexport type MigrationConflict = {\n kind: \"fact\" | \"summary\";\n id: string;\n databaseChecksum: string;\n fileChecksum: string;\n};\n\nexport type MigrationFailure = {\n kind: \"fact\" | \"summary\";\n id: string;\n error: string;\n};\n\nexport type MigrationPreview = {\n namespace: string;\n dryRun: boolean;\n facts: { found: number; existing: number; toWrite: number; conflicts: number; written: number };\n summaries: {\n found: number;\n existing: number;\n toWrite: number;\n conflicts: number;\n written: number;\n };\n conflicts: MigrationConflict[];\n failures: MigrationFailure[];\n};\n\nexport async function migrateMemoryToFiles(input: {\n repository: MemoryRepository;\n store: MemoryFileStore;\n namespace: string;\n write: boolean;\n}): Promise<MigrationPreview> {\n const namespace = await input.repository.getNamespaceByName(input.namespace);\n if (!namespace) {\n return {\n namespace: input.namespace,\n dryRun: !input.write,\n facts: { found: 0, existing: 0, toWrite: 0, conflicts: 0, written: 0 },\n summaries: { found: 0, existing: 0, toWrite: 0, conflicts: 0, written: 0 },\n conflicts: [],\n failures: [],\n };\n }\n\n const [facts, summaries, existingFacts, existingSummaries] = await Promise.all([\n input.repository.listFacts({ namespaceId: namespace.id, limit: 100_000 }),\n input.repository.listSummaries({ namespaceId: namespace.id, limit: 100_000 }),\n input.store.listFacts(),\n input.store.listSummaries(),\n ]);\n // The DB reads are hard-capped at 100k rows; a namespace at that ceiling\n // may be silently truncated. Say so instead of implying completeness.\n const warnings =\n facts.length >= 100_000 || summaries.length >= 100_000\n ? [\n \"namespace is at or above the 100,000-row read cap; the migration may be partial — prune or export in batches\",\n ]\n : [];\n const existingFactsById = new Map(existingFacts.map((fact) => [fact.id, fact]));\n const existingSummariesById = new Map(existingSummaries.map((summary) => [summary.id, summary]));\n const conflicts: MigrationConflict[] = [];\n const failures: MigrationFailure[] = [];\n const factsToWrite = facts.filter((fact) => {\n const existing = existingFactsById.get(fact.id);\n if (!existing) return true;\n // The file holds the redacted form, so compare against that.\n const databaseChecksum = checksum(redactPersisted(fact).content);\n const fileChecksum = checksum(existing.content);\n if (databaseChecksum !== fileChecksum) {\n conflicts.push({ kind: \"fact\", id: fact.id, databaseChecksum, fileChecksum });\n }\n return false;\n });\n const summariesToWrite = summaries.filter((summary) => {\n const existing = existingSummariesById.get(summary.id);\n if (!existing) return true;\n const databaseChecksum = checksum(summary.content);\n const fileChecksum = checksum(existing.content);\n if (databaseChecksum !== fileChecksum) {\n conflicts.push({ kind: \"summary\", id: summary.id, databaseChecksum, fileChecksum });\n }\n return false;\n });\n let factsWritten = 0;\n let summariesWritten = 0;\n\n if (input.write) {\n for (const fact of factsToWrite) {\n try {\n await input.store.writeFact({\n id: fact.id,\n namespace: input.namespace,\n subject: fact.subject,\n predicate: fact.predicate,\n object: fact.object,\n confidence: fact.confidence,\n createdAt: fact.createdAt.toISOString(),\n createdByAgent: fact.createdByAgent,\n sourceInteractionId: fact.sourceInteractionId,\n sourceDeleted: fact.sourceDeleted,\n supersededBy: fact.supersededBy,\n content: fact.content,\n });\n factsWritten += 1;\n } catch (error) {\n failures.push({ kind: \"fact\", id: fact.id, error: (error as Error).message });\n }\n }\n for (const summary of summariesToWrite) {\n try {\n await input.store.writeSummary({\n id: summary.id,\n namespace: input.namespace,\n sessionId: summary.sessionId,\n version: summary.version,\n tokenCount: summary.tokenCount,\n createdAt: summary.createdAt.toISOString(),\n createdByAgent: summary.createdByAgent,\n content: summary.content,\n });\n summariesWritten += 1;\n } catch (error) {\n failures.push({ kind: \"summary\", id: summary.id, error: (error as Error).message });\n }\n }\n }\n\n const factConflicts = conflicts.filter((conflict) => conflict.kind === \"fact\").length;\n const summaryConflicts = conflicts.length - factConflicts;\n return {\n namespace: input.namespace,\n dryRun: !input.write,\n ...(warnings.length > 0 ? { warnings } : {}),\n facts: {\n found: facts.length,\n existing: facts.length - factsToWrite.length - factConflicts,\n toWrite: factsToWrite.length,\n conflicts: factConflicts,\n written: factsWritten,\n },\n summaries: {\n found: summaries.length,\n existing: summaries.length - summariesToWrite.length - summaryConflicts,\n toWrite: summariesToWrite.length,\n conflicts: summaryConflicts,\n written: summariesWritten,\n },\n conflicts,\n failures,\n };\n}\n\nfunction checksum(content: string): string {\n return createHash(\"sha256\").update(content).digest(\"hex\");\n}\n","import { createHash, randomUUID } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { readTraces, recordTrace } from \"../tracing/log.js\";\nimport { VERSION } from \"../version.js\";\n\n/**\n * Anonymous usage telemetry: the local traces (`tracing/log.ts`) reduced to\n * counts and timings and sent in batches to the collector\n * (`telemetry/collector.ts`). Never sent: prompts, recalled text, file paths,\n * repository names, trace `detail`, raw session ids. Nothing is sent until the\n * first-run notice has been shown on a terminal, and never under\n * `CODEBUDDY_TELEMETRY=0`, `DO_NOT_TRACK=1`, `CI`, or `codebuddy telemetry\n * disable`. Every failure is silent: telemetry never breaks a tool or a hook.\n */\n\n/** Where installs send batches (`codebuddy collector` behind `tailscale funnel`). Empty = off. */\nexport const TELEMETRY_URL = \"https://tanmay-hp-linux-server.tail41864f.ts.net/v1/events\";\n\n/** One batch at most this often per project. */\nconst FLUSH_INTERVAL_MS = 10 * 60_000;\nconst MAX_EVENTS = 500;\nconst SEND_TIMEOUT_MS = 3_000;\nconst NAME = /^[A-Za-z][A-Za-z0-9_:.-]{0,63}$/;\n\nexport type TelemetryState = { installId: string; noticeAt?: string; disabled?: boolean };\n\nexport type TelemetryEvent = {\n ts: string;\n kind: string;\n name: string;\n ms: number;\n ok: boolean;\n tokensIn?: number;\n tokensOut?: number;\n session?: string;\n};\n\nexport type TelemetryBatch = {\n installId: string;\n project: string;\n version: string;\n platform: string;\n arch: string;\n node: string;\n clients: string[];\n events: TelemetryEvent[];\n};\n\nexport function telemetryStatePath(home = homedir()): string {\n return join(home, \".codebuddy\", \"telemetry.json\");\n}\n\n/** The machine's state, created with a fresh random install id on first read. */\nexport async function readTelemetryState(home = homedir()): Promise<TelemetryState> {\n try {\n const state = JSON.parse(await readFile(telemetryStatePath(home), \"utf8\")) as TelemetryState;\n if (typeof state.installId === \"string\" && state.installId) return state;\n } catch {\n // Missing or corrupt: start over with a new id.\n }\n return writeTelemetryState({ installId: randomUUID() }, home);\n}\n\nexport async function writeTelemetryState(\n state: TelemetryState,\n home = homedir(),\n): Promise<TelemetryState> {\n const path = telemetryStatePath(home);\n await mkdir(dirname(path), { recursive: true, mode: 0o700 });\n await writeFile(path, `${JSON.stringify(state, null, 2)}\\n`, { mode: 0o600 });\n return state;\n}\n\n/** Why telemetry is off, or null when it may send. */\nexport function telemetryBlocked(\n state: TelemetryState,\n env: NodeJS.ProcessEnv = process.env,\n): string | null {\n if (env.CODEBUDDY_TELEMETRY === \"0\") return \"CODEBUDDY_TELEMETRY=0\";\n if (env.DO_NOT_TRACK === \"1\" || env.DO_NOT_TRACK === \"true\") return \"DO_NOT_TRACK\";\n if (env.CI) return \"CI\";\n if (state.disabled) return \"disabled with `codebuddy telemetry disable`\";\n if (!telemetryUrl(env)) return \"no collector configured\";\n if (!state.noticeAt) return \"first-run notice not shown yet\";\n return null;\n}\n\nexport function telemetryUrl(env: NodeJS.ProcessEnv = process.env): string {\n return env.CODEBUDDY_TELEMETRY_URL ?? TELEMETRY_URL;\n}\n\nexport const TELEMETRY_NOTICE = `CodeBuddy collects anonymous usage data (which tools run, how long they take,\nsuccess/failure, version, OS, agent client) to improve the product.\nPrompts, code, file paths and repository names are never sent.\nOpt out any time: \\`codebuddy telemetry disable\\` or CODEBUDDY_TELEMETRY=0.\nDetails: https://github.com/Orquentra-Inc/CodeBuddy/blob/main/docs/telemetry.md`;\n\n/** Print the notice once per machine, only on an interactive terminal. */\nexport async function showTelemetryNoticeOnce(\n write: (text: string) => void = (text) => process.stderr.write(text),\n options: { home?: string; env?: NodeJS.ProcessEnv; tty?: boolean } = {},\n): Promise<void> {\n const env = options.env ?? process.env;\n if (!(options.tty ?? process.stderr.isTTY)) return;\n try {\n const state = await readTelemetryState(options.home);\n if (state.noticeAt || state.disabled || env.CODEBUDDY_TELEMETRY === \"0\" || env.CI) return;\n if (!telemetryUrl(env)) return;\n write(`\\n${TELEMETRY_NOTICE}\\n\\n`);\n await writeTelemetryState({ ...state, noticeAt: new Date().toISOString() }, options.home);\n } catch {\n // An unwritable home directory only means no notice, and so nothing is sent.\n }\n}\n\n/** Salted so the collector can count projects and sessions without learning names. */\nfunction anonymize(installId: string, value: string): string {\n return createHash(\"sha256\").update(`${installId}\\0${value}`).digest(\"hex\").slice(0, 16);\n}\n\n/** The anonymous subset of a local trace. Free-form names become `other`. */\nexport function toTelemetryEvents(\n installId: string,\n traces: Awaited<ReturnType<typeof readTraces>>,\n): TelemetryEvent[] {\n return traces.map((trace) => ({\n ts: trace.ts,\n kind: NAME.test(trace.kind) ? trace.kind : \"other\",\n name: NAME.test(trace.name) ? trace.name : \"other\",\n ms: Math.max(0, Math.round(trace.ms) || 0),\n ok: trace.ok === true,\n ...(typeof trace.tokensIn === \"number\" ? { tokensIn: trace.tokensIn } : {}),\n ...(typeof trace.tokensOut === \"number\" ? { tokensOut: trace.tokensOut } : {}),\n ...(trace.session ? { session: anonymize(installId, trace.session) } : {}),\n }));\n}\n\ntype Cursor = { sentTs?: string; flushedAt?: number };\n\n/**\n * Send this project's traces recorded since the last successful batch. At most\n * one attempt per `FLUSH_INTERVAL_MS`; a failed send is retried next interval.\n * Returns the number of events the collector accepted.\n */\nexport async function flushTelemetry(\n repositoryRoot: string,\n options: {\n home?: string;\n env?: NodeJS.ProcessEnv;\n now?: number;\n fetchImpl?: typeof fetch;\n clients?: () => Promise<string[]>;\n } = {},\n): Promise<number> {\n const env = options.env ?? process.env;\n const now = options.now ?? Date.now();\n try {\n const state = await readTelemetryState(options.home);\n if (telemetryBlocked(state, env)) return 0;\n const cursorPath = join(repositoryRoot, \".codebuddy\", \"cache\", \"telemetry.json\");\n const cursor = await readFile(cursorPath, \"utf8\")\n .then((raw) => JSON.parse(raw) as Cursor)\n .catch((): Cursor => ({}));\n if (cursor.flushedAt && now - cursor.flushedAt < FLUSH_INTERVAL_MS) return 0;\n // Claim the interval first, so concurrent hook processes do not all send.\n const save = (next: Cursor) =>\n mkdir(dirname(cursorPath), { recursive: true }).then(() =>\n writeFile(cursorPath, JSON.stringify(next)),\n );\n await save({ ...cursor, flushedAt: now });\n\n const pending = (await readTraces(repositoryRoot, 10_000))\n .filter((trace) => !cursor.sentTs || trace.ts > cursor.sentTs)\n .slice(-MAX_EVENTS);\n const last = pending.at(-1);\n if (!last) return 0;\n const batch: TelemetryBatch = {\n installId: state.installId,\n project: anonymize(state.installId, repositoryRoot),\n version: VERSION,\n platform: process.platform,\n arch: process.arch,\n node: process.versions.node.split(\".\")[0] ?? \"\",\n clients: await (options.clients ?? (() => installedClients(repositoryRoot)))().catch(\n () => [],\n ),\n events: toTelemetryEvents(state.installId, pending),\n };\n const response = await (options.fetchImpl ?? fetch)(telemetryUrl(env), {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(batch),\n signal: AbortSignal.timeout(SEND_TIMEOUT_MS),\n });\n if (!response.ok) return 0;\n await save({ sentTs: last.ts, flushedAt: now });\n return batch.events.length;\n } catch {\n return 0;\n }\n}\n\ntype CommandLike = { name(): string; description(): string; parent: CommandLike | null };\n\n/**\n * After a CLI command in a CodeBuddy project: trace it (`kind: cli`, the\n * command path such as `hooks.install`, never its arguments) and flush. Hook\n * runtime (`[hook]`), `[admin]` and `serve` commands are skipped: hooks and\n * MCP tools trace themselves. Outside a project nothing is written.\n */\nexport async function traceCliCommand(\n command: CommandLike,\n started: number,\n root = process.cwd(),\n): Promise<void> {\n if (/^\\[(hook|admin)\\]/.test(command.description()) || command.name() === \"serve\") return;\n if (!existsSync(join(root, \".codebuddy\"))) return;\n const path: string[] = [];\n for (let current: CommandLike | null = command; current?.parent; current = current.parent) {\n path.unshift(current.name());\n }\n await recordTrace(root, {\n kind: \"cli\",\n name: path.join(\".\") || \"use\",\n ms: Date.now() - started,\n ok: !process.exitCode,\n });\n await flushTelemetry(root);\n}\n\n/** Agent clients wired into this project (hooks or MCP config). */\nasync function installedClients(repositoryRoot: string): Promise<string[]> {\n const { CLIENT_IDS } = await import(\"../clients/adapters.js\");\n const { detectClient } = await import(\"../clients/install.js\");\n const found: string[] = [];\n for (const id of CLIENT_IDS) {\n const status = await detectClient(id, repositoryRoot).catch(() => null);\n if (status && (status.hooks || status.mcp)) found.push(id);\n }\n return found;\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { enforceContextBudget } from \"../../context/budget.js\";\nimport { applySessionDelivery, type DeliveryOptions } from \"../../context/delivery.js\";\nimport { loadProjectArchitectureMap } from \"../../context/discovery.js\";\nimport { buildBeforeEditContext, buildBootstrapContext } from \"../../context/engine.js\";\nimport { findReuse } from \"../../context/reuse.js\";\nimport type { CodeBuddy } from \"../../core/codebuddy.js\";\nimport { loadPlanPolicy } from \"../../core/config-file.js\";\nimport { listFactsPage } from \"../../core/operations.js\";\nimport { PlanFileStore } from \"../../core/plan-file-store.js\";\nimport { PlanLifecycle } from \"../../core/plan-lifecycle.js\";\nimport type { MemoryRepository } from \"../../core/repository.js\";\nimport type {\n CodeBuddyConfig,\n RecallInput,\n RecallResult,\n RememberInput,\n} from \"../../core/types.js\";\nimport { llmMemoryOptions } from \"../../hooks/runtime.js\";\nimport { configuredReranker } from \"../../hooks/semantic.js\";\nimport { loadFreshIndex } from \"../../indexer/engine.js\";\nimport { neighbours, queryMap } from \"../../map/indexer.js\";\nimport { captureAfterTurn } from \"../../memory-extract/engine.js\";\nimport { assessRisk } from \"../../risk/service.js\";\nimport { estimateTokens } from \"../../savings/tokens.js\";\nimport { generateSuggestions } from \"../../suggest/engine.js\";\nimport { recordTrace } from \"../../tracing/log.js\";\nimport type { DatabaseServices, LazyDatabase } from \"../database.js\";\nimport { isTransientDatabaseError, withDatabaseRetry } from \"../database-retry.js\";\nimport { serializeToolResult } from \"../tool-result.js\";\n\n/**\n * Input caps. The output side is bounded (LIMITS in the context engine,\n * list_facts ≤ 100); the input side must be too — one tool call should never\n * push megabytes of content into Postgres, the embedding queue, or a plan\n * file that later flows back into agent context.\n */\nconst INPUT_LIMITS = {\n contentChars: 32_000,\n batchItems: 100,\n summaryChars: 32_000,\n planBodyChars: 64_000,\n planBriefChars: 4_000,\n titleChars: 300,\n arrayItems: 100,\n pathChars: 1_024,\n taskChars: 2_000,\n agentIdChars: 200,\n /** Entity ids and list cursors are short; a megabyte one is never valid. */\n idChars: 512,\n} as const;\n\n/** Optional session-aware delivery fields shared by the context tools. */\nconst deliverySchema = {\n sessionId: z.string().min(1).max(200).optional(),\n ack: z\n .string()\n .regex(/^dlv_[a-z0-9]+$/)\n .optional(),\n full: z.boolean().optional(),\n};\n\n/** PostgreSQL text rejects U+0000; fail validation, not with a raw SQL error. */\nconst pgText = (max: number) =>\n z\n .string()\n .min(1)\n .max(max)\n .refine((value) => !value.includes(\"\\u0000\"), \"must not contain NUL bytes\");\n\nconst rememberSchema = {\n sessionId: pgText(200).optional(),\n content: pgText(INPUT_LIMITS.contentChars),\n type: z.enum([\"interaction\", \"fact\", \"summary\"]).optional(),\n idempotencyKey: pgText(200).optional(),\n agentId: pgText(INPUT_LIMITS.agentIdChars).optional(),\n};\n\nconst recallSchema = {\n sessionId: pgText(200),\n query: pgText(INPUT_LIMITS.taskChars),\n budget: z.number().int().positive().optional(),\n callerModel: z.string().min(1).max(200).optional(),\n conflictMode: z.enum([\"all\", \"latest\", \"highest_confidence\"]).optional(),\n /** Default true: a flat list of memories (id, content, date). false = full provenance + stats. */\n compact: z.boolean().optional(),\n};\n\nconst shareSchema = {\n from: z.string().min(1).max(INPUT_LIMITS.agentIdChars).optional(),\n to_namespace: z.string().min(1).max(INPUT_LIMITS.agentIdChars),\n factIds: z.array(z.string().min(1).max(100)).min(1).max(INPUT_LIMITS.arrayItems),\n mode: z.enum([\"reference\", \"snapshot\"]).optional(),\n /** Snapshot mode: the target project's root; its Markdown store receives the copy. */\n to_project_root: z.string().min(1).max(INPUT_LIMITS.pathChars).optional(),\n agentId: z.string().min(1).max(INPUT_LIMITS.agentIdChars).optional(),\n};\n\nconst unshareSchema = {\n to_namespace: z.string().min(1).max(INPUT_LIMITS.agentIdChars),\n factIds: z.array(z.string().min(1).max(100)).min(1).max(INPUT_LIMITS.arrayItems),\n agentId: z.string().min(1).max(INPUT_LIMITS.agentIdChars).optional(),\n};\n\nconst plannedFileSchema = z.object({\n path: z.string().min(1).max(INPUT_LIMITS.pathChars),\n action: z.enum([\"create\", \"edit\", \"delete\"]),\n notes: z.string().max(INPUT_LIMITS.taskChars).optional(),\n});\nconst plannedTestSchema = z.object({\n path: z.string().min(1).max(INPUT_LIMITS.pathChars),\n description: z.string().max(INPUT_LIMITS.taskChars).optional(),\n});\nconst planPatchSchema = {\n title: z.string().min(1).max(INPUT_LIMITS.titleChars).optional(),\n brief: z.string().max(INPUT_LIMITS.planBriefChars).optional(),\n body: z.string().max(INPUT_LIMITS.planBodyChars).optional(),\n filesToTouch: z.array(plannedFileSchema).max(INPUT_LIMITS.arrayItems).optional(),\n testsToAdd: z.array(plannedTestSchema).max(INPUT_LIMITS.arrayItems).optional(),\n outOfScope: z\n .array(z.string().max(INPUT_LIMITS.pathChars))\n .max(INPUT_LIMITS.arrayItems)\n .optional(),\n risks: z.array(z.string().max(INPUT_LIMITS.taskChars)).max(INPUT_LIMITS.arrayItems).optional(),\n};\n\nexport const mcpToolInputSchemas = {\n remember: z.object(rememberSchema),\n remember_batch: z.object({\n items: z.array(z.object(rememberSchema)).min(1).max(INPUT_LIMITS.batchItems),\n }),\n recall: z.object(recallSchema),\n list_facts: z.object({\n subject: z.string().max(INPUT_LIMITS.titleChars).optional(),\n limit: z.number().int().positive().max(100).default(50),\n cursor: z.string().max(INPUT_LIMITS.idChars).optional(),\n }),\n list_namespaces: z.object({}),\n forget: z.object({ id: z.string().min(1).max(INPUT_LIMITS.idChars) }),\n share: z.object(shareSchema),\n unshare: z.object(unshareSchema),\n plan_current: z.object({}),\n plan_create: z.object({\n title: z.string().min(1).max(INPUT_LIMITS.titleChars),\n brief: z.string().min(1).max(INPUT_LIMITS.planBriefChars),\n body: z.string().max(INPUT_LIMITS.planBodyChars).optional(),\n filesToTouch: z.array(plannedFileSchema).max(INPUT_LIMITS.arrayItems).optional(),\n testsToAdd: z.array(plannedTestSchema).max(INPUT_LIMITS.arrayItems).optional(),\n outOfScope: z\n .array(z.string().max(INPUT_LIMITS.pathChars))\n .max(INPUT_LIMITS.arrayItems)\n .optional(),\n risks: z.array(z.string().max(INPUT_LIMITS.taskChars)).max(INPUT_LIMITS.arrayItems).optional(),\n agentId: z.string().min(1).max(INPUT_LIMITS.agentIdChars).optional(),\n }),\n plan_amend: z.object({ id: z.string().min(1), patch: z.object(planPatchSchema) }),\n plan_status: z.object({\n id: z.string().min(1),\n status: z.enum([\"approved\", \"executing\", \"complete\", \"abandoned\"]),\n commitSha: z.string().optional(),\n notes: z.string().optional(),\n reason: z.string().optional(),\n }),\n risk_assess: z.object({\n planId: z.string().min(1).max(100).optional(),\n paths: z\n .array(z.string().min(1).max(INPUT_LIMITS.pathChars))\n .max(INPUT_LIMITS.arrayItems)\n .optional(),\n evidence: z.enum([\"overview\", \"source\"]).optional(),\n useGit: z.boolean().optional(),\n limit: z.number().int().positive().max(100).optional(),\n }),\n map_query: z.object({\n from: z.string().min(1).max(INPUT_LIMITS.pathChars).optional(),\n to: z.string().min(1).max(INPUT_LIMITS.pathChars).optional(),\n limit: z.number().int().positive().max(100).optional(),\n }),\n map_neighbours: z.object({\n module: z.string().min(1).max(INPUT_LIMITS.pathChars),\n direction: z.enum([\"in\", \"out\", \"both\"]).default(\"both\"),\n }),\n context_bootstrap: z.object({ ...deliverySchema }),\n context_before_edit: z.object({\n task: z.string().min(1).max(INPUT_LIMITS.taskChars).optional(),\n paths: z\n .array(z.string().min(1).max(INPUT_LIMITS.pathChars))\n .max(INPUT_LIMITS.arrayItems)\n .optional(),\n planId: z.string().min(1).max(100).optional(),\n evidence: z.enum([\"overview\", \"source\"]).optional(),\n useGit: z.boolean().optional(),\n tokenBudget: z.number().int().positive().max(100_000).optional(),\n ...deliverySchema,\n }),\n context_pack: z.object({\n task: z.string().min(1).max(INPUT_LIMITS.taskChars),\n paths: z\n .array(z.string().min(1).max(INPUT_LIMITS.pathChars))\n .max(INPUT_LIMITS.arrayItems)\n .optional(),\n planId: z.string().min(1).max(100).optional(),\n evidence: z.enum([\"overview\", \"source\"]).optional(),\n useGit: z.boolean().optional(),\n tokenBudget: z.number().int().positive().max(100_000).optional(),\n ...deliverySchema,\n }),\n context_after_turn: z.object({\n summary: z.string().min(1).max(INPUT_LIMITS.summaryChars),\n changedFiles: z\n .array(z.string().min(1).max(INPUT_LIMITS.pathChars))\n .max(INPUT_LIMITS.arrayItems)\n .optional(),\n planId: z.string().min(1).max(100).optional(),\n taskType: z.string().min(1).max(100).optional(),\n agentId: z.string().min(1).max(INPUT_LIMITS.agentIdChars).optional(),\n sessionId: z.string().min(1).max(200).optional(),\n verification: z.array(z.string().min(1).max(500)).max(20).optional(),\n commitSha: z.string().min(7).max(64).optional(),\n }),\n code_suggestions: z.object({\n paths: z\n .array(z.string().min(1).max(INPUT_LIMITS.pathChars))\n .max(INPUT_LIMITS.arrayItems)\n .optional(),\n planId: z.string().min(1).max(100).optional(),\n evidence: z.enum([\"overview\", \"source\"]).optional(),\n useGit: z.boolean().optional(),\n limit: z.number().int().positive().max(100).optional(),\n }),\n health: z.object({}),\n} as const;\n\n/** Tools that need PostgreSQL; every other tool is file-based. */\nconst DATABASE_TOOLS = [\n \"remember\",\n \"remember_batch\",\n \"recall\",\n \"list_facts\",\n \"list_namespaces\",\n \"forget\",\n \"share\",\n \"unshare\",\n];\nconst FILE_TOOLS = Object.keys(mcpToolInputSchemas).filter(\n (name) => !DATABASE_TOOLS.includes(name),\n);\nconst DEGRADED_FALLBACK =\n \"PostgreSQL is unavailable, so this call did nothing. File-based tools still work; read the repository directly and say recall is unavailable instead of guessing. Run `codebuddy db doctor` to diagnose; the next call after retryInMs reconnects.\";\n\n/**\n * Client tool profiles (#45). `full` lists every tool; `core` lists\n * only the automatic context workflow, so a client pays a fraction of the\n * tool-schema tokens per session. Set `CODEBUDDY_TOOL_PROFILE=core` in the\n * client's MCP server environment.\n */\nexport type ToolProfile = \"lean\" | \"core\" | \"full\";\n\n/**\n * The default profile (benchmark v3): one context tool plus memory, with short\n * descriptions and only the parameters an agent needs. The advertised schemas\n * carry no length limits; every call is still validated against the full\n * schema in `mcpToolInputSchemas`, so nothing looser reaches the handlers.\n * Measured: 21 tools / 3,486 cl100k tokens (`full`) vs 3 tools (`lean`).\n */\nexport const LEAN_TOOLS: Record<\n string,\n {\n description: string;\n inputSchema: z.ZodRawShape;\n /** Applied before full validation for fields lean does not advertise. */\n defaults?: Record<string, unknown>;\n }\n> = {\n context_pack: {\n description:\n \"Find the files, symbols and line ranges for a coding task. Call only when the injected CodeBuddy block names no files.\",\n defaults: { tokenBudget: 800 },\n inputSchema: {\n task: z.string(),\n paths: z.array(z.string()).optional(),\n sessionId: z.string().optional(),\n ack: z.string().optional(),\n },\n },\n recall: {\n description: \"Recall stored project memory (conventions, decisions, gotchas) for a question.\",\n inputSchema: { query: z.string() },\n defaults: { sessionId: \"agent\" },\n },\n remember: {\n description: \"Store one durable project fact (convention, decision, gotcha).\",\n inputSchema: { content: z.string() },\n // A fact is Markdown-backed and survives reindex; the full profile's\n // default (`interaction`) is a database-only conversation record.\n defaults: { type: \"fact\" },\n },\n};\n\nexport const CORE_TOOLS = [\n \"context_pack\",\n \"context_bootstrap\",\n \"context_before_edit\",\n \"context_after_turn\",\n \"code_suggestions\",\n \"health\",\n];\n\nexport function resolveToolProfile(value = process.env.CODEBUDDY_TOOL_PROFILE): ToolProfile {\n if (value === undefined || value === \"\" || value === \"lean\") return \"lean\";\n if (value === \"core\" || value === \"full\") return value;\n throw new Error(`CODEBUDDY_TOOL_PROFILE must be \"lean\", \"core\" or \"full\", got \"${value}\"`);\n}\n\nexport type RegisterCodeBuddyToolsOptions =\n | { memory: CodeBuddy; repository: MemoryRepository }\n | {\n /** File-based tools read only namespace/projectRoot/tokenBudget from this. */\n config: Pick<CodeBuddyConfig, \"namespace\"> & {\n projectRoot?: string | undefined;\n tokenBudget?: number | undefined;\n };\n /** Optional PostgreSQL services; database tools degrade while it is unavailable. */\n database: Pick<LazyDatabase, \"get\" | \"status\">;\n };\n\n/** Cap plan bodies returned over MCP so a huge plan can't blow the context. */\nconst PLAN_BODY_LIMIT = 8_000;\n\nfunction serializePlan(plan: import(\"../../core/plan-file-store.js\").PlanSpec | null) {\n if (!plan) return { plan: null };\n const body =\n plan.body.length > PLAN_BODY_LIMIT\n ? `${plan.body.slice(0, PLAN_BODY_LIMIT)}\\n\\n…[truncated]`\n : plan.body;\n return { plan: { ...plan, body } };\n}\n\nexport function registerCodeBuddyTools(\n server: McpServer,\n options: RegisterCodeBuddyToolsOptions,\n profile: ToolProfile = \"full\",\n) {\n const exposed = (name: string) =>\n profile === \"full\" || (profile === \"lean\" ? name in LEAN_TOOLS : CORE_TOOLS.includes(name));\n // Every tool is defined once; tools outside the profile are dropped from tools/list.\n const config = \"database\" in options ? options.config : options.memory.config;\n const traceRoot = config.projectRoot ?? process.cwd();\n // Every tool is traced here, once, for `codebuddy dashboard`.\n const register: McpServer[\"registerTool\"] = (name, toolConfig, callback) => {\n const traced = (async (...args: unknown[]) => {\n const started = Date.now();\n const input = args.length > 1 ? (args[0] as { sessionId?: unknown }) : undefined;\n const trace = (ok: boolean, output?: string) =>\n void recordTrace(traceRoot, {\n kind: \"tool\",\n name,\n ms: Date.now() - started,\n ok,\n tokensIn: estimateTokens(input),\n tokensOut: estimateTokens(output),\n ...(typeof input?.sessionId === \"string\" ? { session: input.sessionId } : {}),\n });\n try {\n const result = (await (callback as (...a: unknown[]) => Promise<unknown>)(...args)) as {\n content?: Array<{ text?: string }>;\n isError?: boolean;\n };\n trace(result?.isError !== true, result?.content?.map((part) => part.text ?? \"\").join(\"\"));\n return result;\n } catch (error) {\n trace(false);\n throw error;\n }\n }) as typeof callback;\n const lean = profile === \"lean\" ? LEAN_TOOLS[name] : undefined;\n const full = mcpToolInputSchemas[name as keyof typeof mcpToolInputSchemas];\n const tool = lean\n ? server.registerTool(\n name,\n {\n ...toolConfig,\n description: lean.description,\n inputSchema: lean.inputSchema,\n } as typeof toolConfig,\n // The lean schema only lists fields; the full schema enforces limits.\n (async (input: Record<string, unknown>, extra: unknown) => {\n const parsed = full.safeParse({ ...lean.defaults, ...input });\n if (!parsed.success) {\n return {\n content: [\n { type: \"text\" as const, text: `Invalid input: ${parsed.error.message}` },\n ],\n isError: true,\n };\n }\n return (traced as (...a: unknown[]) => unknown)(parsed.data, extra);\n }) as typeof callback,\n )\n : server.registerTool(name, toolConfig, traced);\n if (!exposed(name)) tool.remove();\n return tool;\n };\n const json = serializeToolResult;\n\n const database: Pick<LazyDatabase, \"get\" | \"status\"> =\n \"database\" in options\n ? options.database\n : { get: async () => options, status: () => ({ available: true, state: \"ready\" }) };\n /** Run a database tool, or return an explicit, bounded degraded result. */\n const viaDatabase = async (tool: string, run: (db: DatabaseServices) => Promise<unknown>) => {\n let db: DatabaseServices;\n try {\n db = await database.get();\n } catch {\n return {\n ...json({ degraded: true, tool, database: database.status(), fallback: DEGRADED_FALLBACK }),\n isError: true,\n };\n }\n try {\n return json(\n await withDatabaseRetry(\n () => run(db),\n [\"recall\", \"list_facts\", \"list_namespaces\"].includes(tool),\n ),\n );\n } catch (error) {\n if (!isTransientDatabaseError(error)) throw error;\n return {\n ...json({\n degraded: true,\n tool,\n database: { ...database.status(), available: false, state: \"unavailable\" },\n fallback:\n \"The database connection failed during this operation. A write may have committed; verify state before repeating it. File-based context remains available.\",\n }),\n isError: true,\n };\n }\n };\n\n const namespace = config.namespace;\n const projectRoot = config.projectRoot ?? process.cwd();\n const rankContextFacts = async (\n task: string,\n candidates: Array<{ id: string; text: string }>,\n ) => {\n // File context never starts or waits for an unavailable database connection.\n if (database.status().state !== \"ready\") return {};\n try {\n const { memory } = await database.get();\n return await memory.rankContextFacts(\n task,\n candidates.map(({ id }) => id),\n );\n } catch {\n return {};\n }\n };\n // Read once per server: `rerank` changes take effect on the next restart.\n const reranker = configuredReranker(projectRoot).catch(() => undefined);\n const rerankerOption = async () => {\n const configured = await reranker;\n return configured ? { reranker: configured } : {};\n };\n const planStore = new PlanFileStore(projectRoot);\n const planLifecycle = new PlanLifecycle(planStore);\n const toFiles = (\n items?: Array<{\n path: string;\n action: \"create\" | \"edit\" | \"delete\";\n notes?: string | undefined;\n }>,\n ) => items?.map((item) => ({ path: item.path, action: item.action, notes: item.notes ?? \"\" }));\n const toTests = (items?: Array<{ path: string; description?: string | undefined }>) =>\n items?.map((item) => ({ path: item.path, description: item.description ?? \"\" }));\n\n register(\n \"remember\",\n {\n title: \"Remember\",\n description: \"Store one CodeBuddy memory item.\",\n inputSchema: mcpToolInputSchemas.remember.shape,\n },\n async (input) => viaDatabase(\"remember\", (db) => db.memory.remember(toRememberInput(input))),\n );\n\n register(\n \"remember_batch\",\n {\n title: \"Remember batch\",\n description: \"Store multiple CodeBuddy memory items.\",\n inputSchema: mcpToolInputSchemas.remember_batch.shape,\n },\n async (input) =>\n viaDatabase(\"remember_batch\", async (db) => ({\n items: await db.memory.rememberBatch(input.items.map(toRememberInput)),\n })),\n );\n\n register(\n \"recall\",\n {\n title: \"Recall\",\n description:\n \"Recall project memory for a query. Returns a flat list of memories (id, content, date), or an empty list when nothing is relevant. Pass compact=false for full provenance and token stats.\",\n inputSchema: mcpToolInputSchemas.recall.shape,\n },\n async (input) =>\n viaDatabase(\"recall\", async (db) =>\n input.compact === false\n ? withResponseTokens(await db.memory.recall(toRecallInput(input)))\n : compactRecall(await db.memory.recall(toRecallInput(input))),\n ),\n );\n\n register(\n \"list_facts\",\n {\n title: \"List facts\",\n description: \"List facts in the configured namespace.\",\n inputSchema: mcpToolInputSchemas.list_facts.shape,\n },\n async (input) =>\n viaDatabase(\"list_facts\", (db) =>\n listFactsPage(\n db.memory,\n db.repository,\n cleanOptional(input) as { subject?: string; limit?: number; cursor?: string },\n ),\n ),\n );\n\n register(\n \"list_namespaces\",\n {\n title: \"List namespaces\",\n description: \"List CodeBuddy namespaces.\",\n inputSchema: mcpToolInputSchemas.list_namespaces.shape,\n },\n async () =>\n viaDatabase(\"list_namespaces\", async (db) => ({\n namespaces: await db.repository.listNamespaces(),\n })),\n );\n\n register(\n \"forget\",\n {\n title: \"Forget\",\n description: \"Delete an interaction or fact by id.\",\n inputSchema: mcpToolInputSchemas.forget.shape,\n },\n async (input) => viaDatabase(\"forget\", (db) => db.memory.forget(input.id)),\n );\n\n register(\n \"share\",\n {\n title: \"Share\",\n description:\n \"Share facts from the configured namespace to another namespace. Reference (default) is a live, revocable grant; snapshot copies the fact into the target project's Markdown store (requires to_project_root).\",\n inputSchema: mcpToolInputSchemas.share.shape,\n },\n async (input) =>\n viaDatabase(\"share\", (db) =>\n db.memory.share({\n from: input.from ?? namespace,\n to: input.to_namespace,\n factIds: input.factIds,\n ...(input.mode ? { mode: input.mode } : {}),\n ...(input.to_project_root ? { targetProjectRoot: input.to_project_root } : {}),\n ...(input.agentId ? { agentId: input.agentId } : {}),\n }),\n ),\n );\n\n register(\n \"unshare\",\n {\n title: \"Unshare\",\n description:\n \"Revoke live reference shares of configured-namespace facts to another namespace.\",\n inputSchema: mcpToolInputSchemas.unshare.shape,\n },\n async (input) =>\n viaDatabase(\"unshare\", (db) =>\n db.memory.unshare({\n to: input.to_namespace,\n factIds: input.factIds,\n ...(input.agentId ? { agentId: input.agentId } : {}),\n }),\n ),\n );\n\n // ── Plan tools (Proposal 02.6) ────────────────────────────────────\n register(\n \"plan_current\",\n {\n title: \"Current plan\",\n description: \"Return the active (approved or executing) plan for this namespace, or null.\",\n inputSchema: mcpToolInputSchemas.plan_current.shape,\n },\n async () => {\n const [current, policy] = await Promise.all([\n planLifecycle.current(namespace),\n loadPlanPolicy(projectRoot),\n ]);\n return json({ ...serializePlan(current), policy });\n },\n );\n\n register(\n \"plan_create\",\n {\n title: \"Create plan\",\n description: \"Create a draft plan in this namespace.\",\n inputSchema: mcpToolInputSchemas.plan_create.shape,\n },\n async (input) => {\n const files = toFiles(input.filesToTouch);\n const tests = toTests(input.testsToAdd);\n const created = await planLifecycle.create({\n namespace,\n title: input.title,\n brief: input.brief,\n ...(input.body !== undefined ? { body: input.body } : {}),\n ...(files ? { filesToTouch: files } : {}),\n ...(tests ? { testsToAdd: tests } : {}),\n ...(input.outOfScope !== undefined ? { outOfScope: input.outOfScope } : {}),\n ...(input.risks !== undefined ? { risks: input.risks } : {}),\n ...(input.agentId !== undefined ? { createdByAgent: input.agentId } : {}),\n });\n return json(serializePlan(created));\n },\n );\n\n register(\n \"plan_amend\",\n {\n title: \"Amend plan\",\n description: \"Amend a draft or executing plan's content fields.\",\n inputSchema: mcpToolInputSchemas.plan_amend.shape,\n },\n async (input) => {\n const patch = input.patch;\n const files = toFiles(patch.filesToTouch);\n const tests = toTests(patch.testsToAdd);\n const amended = await planLifecycle.amend(input.id, {\n ...(patch.title !== undefined ? { title: patch.title } : {}),\n ...(patch.brief !== undefined ? { brief: patch.brief } : {}),\n ...(patch.body !== undefined ? { body: patch.body } : {}),\n ...(files ? { filesToTouch: files } : {}),\n ...(tests ? { testsToAdd: tests } : {}),\n ...(patch.outOfScope !== undefined ? { outOfScope: patch.outOfScope } : {}),\n ...(patch.risks !== undefined ? { risks: patch.risks } : {}),\n });\n return json(serializePlan(amended));\n },\n );\n\n register(\n \"plan_status\",\n {\n title: \"Transition plan\",\n description: \"Move a plan through its lifecycle: approved, executing, complete, abandoned.\",\n inputSchema: mcpToolInputSchemas.plan_status.shape,\n },\n async (input) => {\n let next: import(\"../../core/plan-file-store.js\").PlanSpec;\n if (input.status === \"approved\") next = await planLifecycle.approve(input.id);\n else if (input.status === \"executing\") next = await planLifecycle.start(input.id);\n else if (input.status === \"complete\")\n next = await planLifecycle.complete(input.id, {\n ...(input.commitSha !== undefined ? { commitSha: input.commitSha } : {}),\n ...(input.notes !== undefined ? { notes: input.notes } : {}),\n });\n else\n next = await planLifecycle.abandon(\n input.id,\n input.reason !== undefined ? { reason: input.reason } : {},\n );\n return json(serializePlan(next));\n },\n );\n\n register(\n \"risk_assess\",\n {\n title: \"Assess risk\",\n description: \"Assess evidence-backed risk for a plan, explicit paths, or git changes.\",\n inputSchema: mcpToolInputSchemas.risk_assess.shape,\n },\n async (input) =>\n json(\n await assessRisk({\n repositoryRoot: projectRoot,\n namespace,\n ...(input.planId !== undefined ? { planId: input.planId } : {}),\n ...(input.paths !== undefined ? { paths: input.paths } : {}),\n ...(input.useGit !== undefined ? { useGit: input.useGit } : {}),\n ...(input.limit !== undefined ? { limit: input.limit } : {}),\n }),\n ),\n );\n\n register(\n \"map_query\",\n {\n title: \"Query architecture map\",\n description: \"Query lightweight module import edges in the current repository.\",\n inputSchema: mcpToolInputSchemas.map_query.shape,\n },\n async (input) => {\n const graph = await cachedMap();\n return json(\n queryMap(graph, {\n ...(input.from !== undefined ? { from: input.from } : {}),\n ...(input.to !== undefined ? { to: input.to } : {}),\n ...(input.limit !== undefined ? { limit: input.limit } : {}),\n }),\n );\n },\n );\n\n register(\n \"map_neighbours\",\n {\n title: \"Module neighbours\",\n description: \"Return inbound/outbound neighbours for a repository module.\",\n inputSchema: mcpToolInputSchemas.map_neighbours.shape,\n },\n async (input) => json(neighbours(await cachedMap(), input.module, input.direction)),\n );\n\n // ── Context engine tools (Proposal 04.2) ──────────────────────────\n const tokenBudget = config.tokenBudget;\n\n /**\n * The same map the context engine uses: the import-map cache\n * (`.codebuddy/cache/architecture.json`) merged with fresh Graphify\n * relations when Graphify is enabled. The index is validated against current\n * source first so edited imports are re-read.\n */\n const cachedMap = async () =>\n loadProjectArchitectureMap(\n projectRoot,\n loadFreshIndex(projectRoot).then(({ manifest }) => manifest),\n );\n\n register(\n \"context_bootstrap\",\n {\n title: \"Bootstrap project context\",\n description:\n \"Return compact project awareness for the start of a turn: identity, active plan and policy, top policy rules, incident hotspots, and an architecture summary. Prefer this over a manual recall at session start. Optional sessionId enables session-aware delivery: pass the previous response's delivery.deliveryId as ack and unchanged sections are omitted (listed in delivery.unchanged); pass full=true to get everything again.\",\n inputSchema: mcpToolInputSchemas.context_bootstrap.shape,\n },\n async (input) =>\n json(\n await applySessionDelivery(\n projectRoot,\n await buildBootstrapContext({\n repositoryRoot: projectRoot,\n namespace,\n ...(tokenBudget !== undefined ? { tokenBudget } : {}),\n }),\n deliveryOptions(input),\n ),\n ),\n );\n\n register(\n \"context_before_edit\",\n {\n title: \"Context before edit\",\n description:\n \"Assemble relevant context before changing code: resolves target files from paths, a plan, or git, then returns the relevant plan, matching policy rules, incident memory, an evidence-backed risk assessment, and import neighbours. Optional sessionId enables session-aware delivery: pass the previous response's delivery.deliveryId as ack and unchanged sections are omitted (listed in delivery.unchanged); pass full=true to get everything again.\",\n inputSchema: mcpToolInputSchemas.context_before_edit.shape,\n },\n async (input) =>\n json(\n await applySessionDelivery(\n projectRoot,\n await buildBeforeEditContext({\n repositoryRoot: projectRoot,\n namespace,\n semanticRanker: rankContextFacts,\n ...(await rerankerOption()),\n ...(input.evidence ? { evidence: input.evidence } : {}),\n ...(input.task !== undefined ? { task: input.task } : {}),\n ...(input.paths !== undefined ? { paths: input.paths } : {}),\n ...(input.planId !== undefined ? { planId: input.planId } : {}),\n ...(input.useGit !== undefined ? { useGit: input.useGit } : {}),\n ...(input.tokenBudget !== undefined ? { tokenBudget: input.tokenBudget } : {}),\n ...(tokenBudget !== undefined && input.tokenBudget === undefined\n ? { tokenBudget }\n : {}),\n }),\n deliveryOptions(input),\n ),\n ),\n );\n\n register(\n \"context_pack\",\n {\n title: \"Build task context pack\",\n description:\n \"Build the smallest useful context pack for a coding task. Automatically finds relevant files from the local index when paths are omitted, then includes only bounded symbols, policies, risks, incidents, architecture neighbours, and relevant team facts within the requested token budget. Use this once at the start of a task instead of manually chaining context, risk, map, and memory tools. Request evidence=source with exact paths when short excerpts omit needed behavior; source excerpts remain bounded by the token budget. Optional sessionId enables session-aware delivery: pass the previous response's delivery.deliveryId as ack and unchanged sections are omitted (listed in delivery.unchanged); pass full=true to get everything again.\",\n inputSchema: mcpToolInputSchemas.context_pack.shape,\n },\n async (input) => {\n const context = await buildBeforeEditContext({\n repositoryRoot: projectRoot,\n namespace,\n task: input.task,\n semanticRanker: rankContextFacts,\n ...(await rerankerOption()),\n ...(input.evidence ? { evidence: input.evidence } : {}),\n ...(input.paths !== undefined ? { paths: input.paths } : {}),\n ...(input.planId !== undefined ? { planId: input.planId } : {}),\n ...(input.useGit !== undefined ? { useGit: input.useGit } : {}),\n tokenBudget: input.tokenBudget ?? tokenBudget ?? 4_000,\n });\n // Existing helpers the task could reuse; present only when one clearly matches.\n // After the engine: its own refresh reports staleness, this one finds none left.\n const reuse = await loadFreshIndex(projectRoot)\n .then(async ({ manifest }) =>\n findReuse(\n projectRoot,\n input.task,\n manifest,\n await loadProjectArchitectureMap(projectRoot, manifest),\n ),\n )\n .catch(() => []);\n return json(\n await applySessionDelivery(\n projectRoot,\n enforceContextBudget({ ...context, ...(reuse.length > 0 ? { reuse } : {}) }),\n deliveryOptions(input),\n ),\n );\n },\n );\n\n register(\n \"context_after_turn\",\n {\n title: \"Capture context after a turn\",\n description:\n \"Extract durable knowledge from a turn summary. Confident facts/decisions/incidents are auto-saved as Markdown; temporary notes, low-confidence, and sensitive items are queued for review under .codebuddy/memory/review/; chatter is ignored. Never saves sensitive content automatically. Turns that changed files or report verification also record a bounded worklog handoff under .codebuddy/worklog/ so later chats can recover the work.\",\n inputSchema: mcpToolInputSchemas.context_after_turn.shape,\n },\n async (input) => {\n const result = await captureAfterTurn(\n {\n summary: input.summary,\n namespace,\n ...(input.changedFiles !== undefined ? { changedFiles: input.changedFiles } : {}),\n ...(input.planId !== undefined ? { planId: input.planId } : {}),\n ...(input.taskType !== undefined ? { taskType: input.taskType } : {}),\n ...(input.agentId !== undefined ? { agentId: input.agentId } : {}),\n ...(input.sessionId !== undefined ? { sessionId: input.sessionId } : {}),\n ...(input.verification !== undefined ? { verification: input.verification } : {}),\n ...(input.commitSha !== undefined ? { commitSha: input.commitSha } : {}),\n },\n {\n repositoryRoot: projectRoot,\n ...((input.changedFiles?.length ?? 0) > 0 ? await llmMemoryOptions(projectRoot) : {}),\n },\n );\n // Capture writes reviewable Markdown first. Import it immediately so\n // database recall and the embedding worker see the same memory without\n // requiring a restart or a manual `codebuddy reindex`. Without a\n // database the Markdown is still saved and imported on reconnect.\n const db = await database.get().catch(() => undefined);\n await db?.memory.reindexMemory({ respace: false });\n return json({\n saved: result.saved.map((d) => ({\n id: d.ref,\n class: d.candidate.class,\n subject: d.candidate.subject,\n })),\n queuedForReview: result.queuedForReview.map((d) => ({\n id: d.ref,\n class: d.candidate.class,\n reason: d.reason,\n sensitive: d.sensitive,\n })),\n ignored: result.ignored.length,\n reasons: result.reasons,\n extractor: result.extractor,\n worklogId: result.worklogId,\n ...(db ? {} : { degraded: true, database: database.status() }),\n });\n },\n );\n\n register(\n \"code_suggestions\",\n {\n title: \"Code suggestions\",\n description:\n \"Return read-only, evidence-backed code-quality suggestions for a change set (paths, a plan, or git). Composes risk, plan divergence, architecture blast radius, incident history, missing tests, and stale policies. Never edits code.\",\n inputSchema: mcpToolInputSchemas.code_suggestions.shape,\n },\n async (input) =>\n json(\n await generateSuggestions({\n repositoryRoot: projectRoot,\n namespace,\n ...(input.paths !== undefined ? { paths: input.paths } : {}),\n ...(input.planId !== undefined ? { planId: input.planId } : {}),\n ...(input.useGit !== undefined ? { useGit: input.useGit } : {}),\n ...(input.limit !== undefined ? { limit: input.limit } : {}),\n }),\n ),\n );\n\n register(\n \"health\",\n {\n title: \"Health\",\n description:\n \"Report which CodeBuddy tools are available right now: file-based tools always work; database tools (recall, remember, facts) need PostgreSQL. Does not wait on a connection attempt.\",\n inputSchema: mcpToolInputSchemas.health.shape,\n },\n async () =>\n json({\n database: database.status(),\n tools: {\n profile,\n file: FILE_TOOLS.filter(exposed),\n database: DATABASE_TOOLS.filter(exposed),\n },\n }),\n );\n}\n\nfunction deliveryOptions(input: {\n sessionId?: string | undefined;\n ack?: string | undefined;\n full?: boolean | undefined;\n}): DeliveryOptions {\n return cleanOptional(input as Record<string, unknown>) as DeliveryOptions;\n}\n\nfunction toRememberInput(input: z.infer<typeof mcpToolInputSchemas.remember>): RememberInput {\n return cleanOptional(input) as RememberInput;\n}\n\nfunction toRecallInput(input: z.infer<typeof mcpToolInputSchemas.recall>): RecallInput {\n const { compact: _compact, ...rest } = input;\n return cleanOptional(rest) as RecallInput;\n}\n\n/**\n * The default recall answer (benchmark v3): only what the agent reads. The\n * previous envelope cost 316 tokens for an empty result and ~450-570 for one\n * fact; skip reasons and coverage stats stay available with compact=false.\n */\nexport function compactRecall(result: RecallResult) {\n const memories = result.messages.map((message) => ({\n ...(message.fact ? { id: message.fact.id } : {}),\n content: message.content,\n ...(message.fact?.createdAt ? { date: message.fact.createdAt.slice(0, 10) } : {}),\n }));\n return memories.length > 0 ? { memories } : { memories, note: \"nothing relevant\" };\n}\n\n/**\n * `stats.tokensUsed` counts message content only (the budget contract); the\n * response also carries provenance, stats and JSON framing. Report what is\n * really sent: `responseTokens` for the JSON text, `transportTokens` for the\n * whole tool result (structuredContent repeats the payload).\n */\nfunction withResponseTokens(result: RecallResult) {\n const stats: Record<string, unknown> = { ...result.stats };\n const value = { ...result, stats };\n // Two passes: the counts are part of the text they count.\n for (let pass = 0; pass < 2; pass++) {\n const serialized = serializeToolResult(value);\n stats.responseTokens = estimateTokens(serialized.content[0]?.text);\n stats.transportTokens = estimateTokens(serialized);\n }\n return value;\n}\n\nfunction cleanOptional(input: Record<string, unknown>): Record<string, unknown> {\n return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== undefined));\n}\n","import { createHash } from \"node:crypto\";\nimport { estimateTokens } from \"../savings/tokens.js\";\nimport { enforceContextBudget } from \"./budget.js\";\nimport { SessionCapsuleLedger } from \"./session-ledger.js\";\n\n/**\n * Session-aware delivery for the MCP context tools. With a `sessionId`, a\n * section whose exact content the client already confirmed receiving (via\n * `ack`) in this session is omitted and listed in `delivery.unchanged`; the\n * ledger keeps a few acknowledged versions per section, so switching back to\n * an earlier task does not resend what the client still holds. Without a\n * `sessionId` the payload is returned untouched, so clients without session\n * support always get complete context.\n *\n * Safety evidence that changes per call (target paths, risks, diffs) is never\n * omitted. Any ledger failure falls back to the full payload.\n */\n\n/** Delivery contract version, bumped on any incompatible change. */\nexport const DELIVERY_VERSION = 1;\n\n/** Sections that may be omitted when unchanged. Everything else is always sent. */\nconst OMITTABLE_SECTIONS = [\n \"plan\",\n \"policyRules\",\n \"incidents\",\n \"facts\",\n \"rules\",\n \"handoffs\",\n \"architecture\",\n \"symbols\",\n \"neighbours\",\n \"reuse\",\n] as const;\n\n/**\n * An acknowledged section is only treated as already-seen for this long; after\n * that it is resent, bounding how stale a client's copy can get.\n */\nconst SESSION_TTL_MS = 30 * 60 * 1000;\n\nexport type DeliveryOptions = {\n sessionId?: string;\n /** The `deliveryId` of the previous response the client actually received. */\n ack?: string;\n /** Resend every section, e.g. after the client's context was compacted. */\n full?: boolean;\n};\n\nexport type DeliveryInfo = {\n version: typeof DELIVERY_VERSION;\n sessionId: string;\n deliveryId: string;\n ack: \"none\" | \"accepted\" | \"unknown\";\n unchanged: string[];\n avoidedTokens: number;\n note: string;\n};\n\nexport async function applySessionDelivery(\n repositoryRoot: string,\n payload: object,\n options: DeliveryOptions,\n): Promise<Record<string, unknown>> {\n let output: Record<string, unknown> = { ...payload };\n if (!options.sessionId) return output;\n\n // Keys stay `mcp:`-prefixed on purpose, separate from the hook capsule keys\n // (`plan`, `fact:<id>`, ...) in the same session ledger. The hook block sends\n // bounded one-line renderings marked on write; these hashes cover the full\n // JSON section and count only once acknowledged. A shared key would let a\n // clipped hook line suppress a full section it never carried, or the two\n // paths overwrite each other's records. The paths share only reset.\n const sections = OMITTABLE_SECTIONS.filter((key) => output[key] !== undefined).map((key) => ({\n key: `mcp:${key}`,\n hash: createHash(\"sha256\").update(JSON.stringify(output[key])).digest(\"hex\"),\n }));\n\n try {\n await new SessionCapsuleLedger(repositoryRoot).exchange(options.sessionId, sections, {\n ...(options.ack !== undefined ? { ack: options.ack } : {}),\n ttlMs: SESSION_TTL_MS,\n ...(options.full ? { full: true } : {}),\n prepare: (exchange) => {\n const unchanged = exchange.unchanged.map((key) => key.slice(\"mcp:\".length));\n let avoidedTokens = 0;\n for (const key of unchanged) {\n avoidedTokens += estimateTokens(output[key]);\n delete output[key];\n }\n const delivery: DeliveryInfo = {\n version: DELIVERY_VERSION,\n sessionId: options.sessionId as string,\n deliveryId: exchange.deliveryId,\n ack: exchange.ack,\n unchanged,\n avoidedTokens,\n note: \"Pass deliveryId as ack. Use full=true after losing context.\",\n };\n output.delivery = delivery;\n output = enforceContextBudget(output);\n // Hash what was actually delivered. A section shortened or omitted by\n // the budget must never acknowledge its original, complete version.\n return OMITTABLE_SECTIONS.filter((key) => output[key] !== undefined).map((key) => ({\n key: `mcp:${key}`,\n hash: createHash(\"sha256\").update(JSON.stringify(output[key])).digest(\"hex\"),\n }));\n },\n });\n return output;\n } catch {\n return enforceContextBudget({ ...payload });\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { IndexManifest } from \"../indexer/types.js\";\nimport type { ArchitectureMap } from \"../map/types.js\";\nimport { NON_SOURCE_PATH, TEST_PATH, taskTerms } from \"./discovery.js\";\nimport { rankSemanticReuse } from \"./reuse-vectors.js\";\nimport { findCoveringTest } from \"./tests.js\";\n\n/**\n * Reuse-first code search (queue Q6): existing exported helpers whose names\n * say what the task asks for, so an agent extends or calls them instead of\n * writing a second one. Code search only; remembered facts are a separate path.\n *\n * Lexical and deterministic: a symbol's name words (camelCase/snake split,\n * stopwords dropped, plurals folded) are matched against the task's terms,\n * weighted by how rare each word is among all symbol names. A candidate needs\n * `minMatched` matched words covering `minCoverage` of its name, so a common\n * one-word name the task merely mentions (\"recall\", \"state\") is withheld.\n * Thresholds: `evals/reuse-dev.json`, calibrated with `scripts/eval-reuse.mts`.\n */\n\nexport const REUSE_ADMISSION = { minMatched: 2, minCoverage: 0.67, limit: 3 } as const;\n\nexport type ReuseCandidate = {\n path: string;\n name: string;\n signature: string;\n startLine: number;\n endLine: number;\n /** Task terms found in the name. */\n matched: string[];\n score: number;\n evidence?: \"lexical\" | \"semantic\";\n /** One call site in an importing source file: `path:line: code`. */\n usage?: string;\n test?: string;\n};\n\nconst REUSABLE_KINDS = new Set([\"function\", \"class\", \"method\", \"const\"]);\n\nexport async function findReuse(\n repositoryRoot: string,\n task: string,\n manifest: IndexManifest,\n map: ArchitectureMap | null,\n admission: { minMatched: number; minCoverage: number; limit: number } = REUSE_ADMISSION,\n semanticRanker: typeof rankSemanticReuse = rankSemanticReuse,\n): Promise<ReuseCandidate[]> {\n const terms = new Set(taskTerms(task));\n if (terms.size < admission.minMatched) return [];\n const symbols = Object.values(manifest.entries)\n .filter((entry) => !TEST_PATH.test(entry.path) && !NON_SOURCE_PATH.test(entry.path))\n .flatMap((entry) =>\n (entry.symbolTable ?? [])\n .filter((symbol) => symbol.exported && REUSABLE_KINDS.has(symbol.kind))\n .map((symbol) => ({ ...symbol, path: entry.path, words: new Set(taskTerms(symbol.name)) })),\n );\n const frequency = new Map<string, number>();\n for (const symbol of symbols) {\n for (const word of symbol.words) frequency.set(word, (frequency.get(word) ?? 0) + 1);\n }\n const idf = (word: string) => Math.log((symbols.length + 1) / ((frequency.get(word) ?? 0) + 1));\n const ranked = symbols\n .map((symbol) => {\n const matched = [...symbol.words].filter((word) => terms.has(word));\n return {\n symbol,\n matched,\n coverage: symbol.words.size > 0 ? matched.length / symbol.words.size : 0,\n score: matched.reduce((sum, word) => sum + idf(word), 0),\n };\n })\n .filter(\n (item) =>\n item.matched.length >= admission.minMatched && item.coverage >= admission.minCoverage,\n )\n .sort((a, b) => b.score - a.score || a.symbol.path.localeCompare(b.symbol.path));\n // A semantic fallback only when lexical evidence cannot name a helper. Strong\n // top score and separation are required; this is a conservative policy, not\n // a calibrated probability or a claim of benchmark accuracy.\n let semantic = false;\n if (!ranked.length) {\n const candidates = await semanticRanker(repositoryRoot, task, manifest);\n const first = candidates[0];\n if (first && first.score >= 0.84 && first.score - (candidates[1]?.score ?? 0) >= 0.04) {\n const symbol = symbols.find((item) => item.path === first.path && item.name === first.name);\n if (symbol) {\n ranked.push({ symbol, matched: [], coverage: 0, score: first.score });\n semantic = true;\n }\n }\n }\n const indexed = new Set(Object.keys(manifest.entries));\n const seen = new Set<string>();\n const picked: ReuseCandidate[] = [];\n for (const { symbol, matched, score } of ranked) {\n const key = `${symbol.path}:${symbol.name}`;\n if (seen.has(key)) continue;\n seen.add(key);\n const usage = await usageSite(repositoryRoot, symbol.path, symbol.name, map);\n const test = findCoveringTest(symbol.path, indexed);\n picked.push({\n path: symbol.path,\n name: symbol.name,\n signature: symbol.signature,\n startLine: symbol.startLine,\n endLine: symbol.endLine,\n matched,\n score: Math.round(score * 100) / 100,\n ...(semantic ? { evidence: \"semantic\" as const } : {}),\n ...(usage ? { usage } : {}),\n ...(test ? { test } : {}),\n });\n if (picked.length === admission.limit) break;\n }\n return picked;\n}\n\n/** The first line in a non-test importer that uses the symbol (by its last name part). */\nasync function usageSite(\n root: string,\n path: string,\n name: string,\n map: ArchitectureMap | null,\n): Promise<string | undefined> {\n const short = name.split(\".\").at(-1) ?? name;\n const pattern = new RegExp(`\\\\b${short.replace(/[^\\w$]/g, \"\")}\\\\b`);\n const importers = (map?.edges ?? [])\n .filter((edge) => edge.to === path && !TEST_PATH.test(edge.from))\n .map((edge) => edge.from)\n .sort();\n for (const importer of importers.slice(0, 20)) {\n const source = await readFile(join(root, importer), \"utf8\").catch(() => \"\");\n const lines = source.split(\"\\n\");\n const index = lines.findIndex((line) => pattern.test(line) && !/^\\s*import\\b/.test(line));\n if (index !== -1)\n return `${importer}:${index + 1}: ${(lines[index] ?? \"\").trim().slice(0, 140)}`;\n }\n return undefined;\n}\n","import { constants } from \"node:fs\";\nimport { access } from \"node:fs/promises\";\nimport { extname, join, resolve } from \"node:path\";\nimport { coveringTestCandidates } from \"../context/tests.js\";\nimport { MemoryFileStore } from \"../core/memory-file-store.js\";\nimport { PlanFileStore, type PlanSpec } from \"../core/plan-file-store.js\";\nimport { PlanLifecycle } from \"../core/plan-lifecycle.js\";\nimport { buildArchitectureMap } from \"../map/indexer.js\";\nimport type { ArchitectureMap } from \"../map/types.js\";\nimport { assessRisk, resolveRiskPaths } from \"../risk/service.js\";\nimport { readPolicyFile } from \"../risk/signals/policy.js\";\nimport { SEVERITY_RANK, type Suggestion, type SuggestResult } from \"./types.js\";\n\n/**\n * Deterministic, read-only suggestion generation. Nothing here writes to disk\n * or edits code — it only reads the working tree and CodeBuddy's own artifacts.\n * Each category attaches its own evidence; anything without evidence is not\n * emitted. Findings are de-duplicated per (category, path) and ranked by\n * severity so the few important ones surface first.\n */\n\nconst RISK_SUGGEST_THRESHOLD = 50;\nconst BLAST_RADIUS_MEDIUM = 5;\nconst BLAST_RADIUS_HIGH = 10;\nconst CODE_EXTENSIONS = new Set([\".ts\", \".tsx\", \".js\", \".jsx\", \".mjs\", \".cjs\", \".py\"]);\n\nexport type SuggestInput = {\n repositoryRoot?: string;\n namespace: string;\n paths?: string[];\n planId?: string;\n useGit?: boolean;\n limit?: number;\n};\n\nexport async function generateSuggestions(input: SuggestInput): Promise<SuggestResult> {\n const repositoryRoot = resolve(input.repositoryRoot ?? process.cwd());\n const namespace = input.namespace;\n\n const targetPaths = await resolveRiskPaths({\n repositoryRoot,\n ...(input.paths !== undefined ? { paths: input.paths } : {}),\n ...(input.planId !== undefined ? { planId: input.planId } : {}),\n ...(input.useGit !== undefined ? { useGit: input.useGit } : {}),\n });\n\n const planStore = new PlanFileStore(repositoryRoot);\n const memoryStore = new MemoryFileStore(repositoryRoot);\n\n const [risks, plan, incidents, map, policyFile] = await Promise.all([\n assessRisk({\n repositoryRoot,\n namespace,\n ...(input.paths !== undefined ? { paths: input.paths } : {}),\n ...(input.planId !== undefined ? { planId: input.planId } : {}),\n ...(input.useGit !== undefined ? { useGit: input.useGit } : {}),\n }),\n resolveRelevantPlan(planStore, namespace, input.planId),\n memoryStore.findIncidentFactsForPaths({ namespace, paths: targetPaths }),\n buildArchitectureMap(repositoryRoot),\n readPolicyFile(join(repositoryRoot, \".codebuddy\", \"policies.yaml\")),\n ]);\n\n const suggestions: Suggestion[] = [];\n\n // 1. Risk — surface the change set's highest-scoring paths.\n for (const item of risks.items) {\n if (item.score < RISK_SUGGEST_THRESHOLD) continue;\n suggestions.push({\n id: `risk:${item.path}`,\n category: \"risk\",\n severity: item.score >= 75 ? \"high\" : \"medium\",\n title: `Review high-risk change to ${item.path}`,\n detail: item.reason,\n path: item.path,\n evidence: [\n { kind: \"risk_score\", detail: `score ${item.score} (${item.category})` },\n ...(item.evidence.length > 0\n ? [{ kind: \"risk_evidence\", detail: `${item.evidence.length} evidence item(s)` }]\n : []),\n ],\n commandHint: `codebuddy risk assess --paths ${item.path} --explain`,\n });\n }\n\n // 2. Incident history — files with an unresolved past incident.\n for (const incident of incidents) {\n const path = incident.paths[0] ?? \"(unknown)\";\n suggestions.push({\n id: `incident:${path}`,\n category: \"incident\",\n severity: \"high\",\n title: `Recurring incident hotspot: ${path}`,\n detail: `${incident.subject} — proceed carefully; this area has an unresolved incident.`,\n path,\n evidence: [{ kind: \"incident\", detail: `${incident.id} severity=${incident.severity}` }],\n });\n }\n\n // 3. Architecture — high blast radius (many dependents).\n const inbound = inboundDegrees(map);\n for (const path of targetPaths) {\n const dependents = inbound.get(path) ?? 0;\n if (dependents < BLAST_RADIUS_MEDIUM) continue;\n suggestions.push({\n id: `architecture:${path}`,\n category: \"architecture\",\n severity: dependents >= BLAST_RADIUS_HIGH ? \"high\" : \"medium\",\n title: `High blast radius: ${path}`,\n detail: `${dependents} module(s) import ${path}; a change here ripples widely.`,\n path,\n evidence: [{ kind: \"dependents\", detail: `${dependents} inbound import(s)` }],\n commandHint: `codebuddy map dependents ${path}`,\n });\n }\n\n // 4. Plan divergence — editing files the active plan does not cover.\n if (plan) {\n const planned = new Set(plan.filesToTouch.map((file) => normalize(file.path)));\n const strays = targetPaths.filter((path) => !planned.has(normalize(path)));\n if (planned.size > 0 && strays.length > 0) {\n suggestions.push({\n id: `plan_divergence:${plan.id}`,\n category: \"plan_divergence\",\n severity: \"medium\",\n title: `Change set diverges from plan ${plan.id}`,\n detail: `${strays.length} target file(s) are outside the active plan's scope: ${strays\n .slice(0, 5)\n .join(\", \")}.`,\n evidence: [\n { kind: \"plan\", detail: `plan ${plan.id} (${plan.status})` },\n { kind: \"out_of_scope\", detail: strays.slice(0, 5).join(\", \") },\n ],\n commandHint: `codebuddy plan show ${plan.id}`,\n });\n }\n }\n\n // 5. Missing tests — changed code files with no discoverable test.\n for (const path of targetPaths) {\n if (!isTestableCode(path)) continue;\n if (await hasSiblingTest(repositoryRoot, path)) continue;\n suggestions.push({\n id: `missing_test:${path}`,\n category: \"missing_test\",\n severity: \"low\",\n title: `No test found for ${path}`,\n detail: \"Consider adding a test alongside this change.\",\n path,\n evidence: [{ kind: \"no_test\", detail: \"no conventional test file found\" }],\n });\n }\n\n // 6. Stale policy — a rule whose target directory no longer exists.\n for (const rule of policyFile.rules) {\n const prefix = literalPrefix(rule.pattern);\n if (!prefix) continue;\n if (await pathExists(join(repositoryRoot, prefix))) continue;\n suggestions.push({\n id: `stale_policy:${rule.id}`,\n category: \"stale_policy\",\n severity: \"low\",\n title: `Stale policy rule \"${rule.id}\"`,\n detail: `Pattern \"${rule.pattern}\" targets \"${prefix}\", which does not exist.`,\n evidence: [{ kind: \"policy_rule\", detail: `${rule.id} → ${rule.pattern}` }],\n });\n }\n\n const deduped = dedupe(suggestions).sort(compareSuggestions);\n const limited = input.limit ? deduped.slice(0, input.limit) : deduped;\n\n return {\n suggestions: limited,\n stats: buildStats(targetPaths.length, limited),\n };\n}\n\n// ── helpers ─────────────────────────────────────────────────────────\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 inboundDegrees(map: ArchitectureMap): Map<string, number> {\n const inbound = new Map<string, number>();\n for (const edge of map.edges) inbound.set(edge.to, (inbound.get(edge.to) ?? 0) + 1);\n return inbound;\n}\n\nfunction isTestableCode(path: string): boolean {\n if (/\\.(test|spec)\\.[cm]?[jt]sx?$/.test(path)) return false;\n if (path.endsWith(\".d.ts\")) return false;\n if (path.includes(\"__tests__/\")) return false;\n // Python tests, fixtures and package markers are not modules to cover.\n if (/(^|\\/)(test_[^/]*|[^/]*_test|conftest|__init__)\\.py$|(^|\\/)tests?\\/.*\\.py$/.test(path)) {\n return false;\n }\n return CODE_EXTENSIONS.has(extname(path).toLowerCase());\n}\n\nasync function hasSiblingTest(repositoryRoot: string, path: string): Promise<boolean> {\n for (const candidate of coveringTestCandidates(path)) {\n if (await pathExists(join(repositoryRoot, candidate))) return true;\n }\n return false;\n}\n\n/**\n * The literal directory prefix of a glob — everything before the first\n * wildcard, trimmed to a whole path segment. `src/auth/**` → `src/auth`,\n * `src/**/*.ts` → `src`, `*.env` → `` (no literal prefix to check).\n */\nfunction literalPrefix(pattern: string): string {\n const normalized = normalize(pattern);\n const wildcard = normalized.search(/[*?[]/);\n if (wildcard === -1) return normalized.replace(/\\/+$/, \"\");\n const beforeWildcard = normalized.slice(0, wildcard);\n const lastSlash = beforeWildcard.lastIndexOf(\"/\");\n return lastSlash === -1 ? \"\" : beforeWildcard.slice(0, lastSlash);\n}\n\nfunction dedupe(suggestions: Suggestion[]): Suggestion[] {\n const byId = new Map<string, Suggestion>();\n for (const suggestion of suggestions) {\n const existing = byId.get(suggestion.id);\n if (!existing || SEVERITY_RANK[suggestion.severity] > SEVERITY_RANK[existing.severity]) {\n byId.set(suggestion.id, suggestion);\n }\n }\n return [...byId.values()];\n}\n\nfunction compareSuggestions(left: Suggestion, right: Suggestion): number {\n const severity = SEVERITY_RANK[right.severity] - SEVERITY_RANK[left.severity];\n if (severity !== 0) return severity;\n if (left.category !== right.category) return left.category.localeCompare(right.category);\n return (left.path ?? \"\").localeCompare(right.path ?? \"\");\n}\n\nfunction buildStats(pathsConsidered: number, suggestions: Suggestion[]) {\n const byCategory: Record<string, number> = {};\n const bySeverity: Record<string, number> = {};\n for (const suggestion of suggestions) {\n byCategory[suggestion.category] = (byCategory[suggestion.category] ?? 0) + 1;\n bySeverity[suggestion.severity] = (bySeverity[suggestion.severity] ?? 0) + 1;\n }\n return { pathsConsidered, produced: suggestions.length, byCategory, bySeverity };\n}\n\nasync function pathExists(path: string): Promise<boolean> {\n try {\n await access(path, constants.F_OK);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction normalize(path: string): string {\n return path.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\");\n}\n","/**\n * Suggestion model (Proposal 04 Phase 04.6). The suggestion engine reads the\n * signals CodeBuddy already computes — risk, the active plan, the architecture\n * map, incident memory — plus a couple of deterministic checks (missing tests,\n * stale policies) and turns them into a short list of evidence-backed, severity-\n * ranked suggestions. It is strictly read-only: it never edits code, and it\n * never emits a suggestion without evidence. The bias is a careful senior\n * reviewer, not a noisy linter — few strong findings over many weak ones.\n */\n\nexport const SUGGESTION_CATEGORIES = [\n \"risk\",\n \"plan_divergence\",\n \"architecture\",\n \"incident\",\n \"missing_test\",\n \"stale_policy\",\n] as const;\nexport type SuggestionCategory = (typeof SUGGESTION_CATEGORIES)[number];\n\nexport const SUGGESTION_SEVERITIES = [\"info\", \"low\", \"medium\", \"high\"] as const;\nexport type SuggestionSeverity = (typeof SUGGESTION_SEVERITIES)[number];\n\n/** Every suggestion cites at least one of these. No evidence, no suggestion. */\nexport type SuggestionEvidence = {\n kind: string;\n detail: string;\n};\n\nexport type Suggestion = {\n /** Stable id (`category:path`) so a UI can dedupe and track across runs. */\n id: string;\n category: SuggestionCategory;\n severity: SuggestionSeverity;\n title: string;\n detail: string;\n path?: string;\n evidence: SuggestionEvidence[];\n /** Optional follow-up command, e.g. `codebuddy risk assess --paths …`. */\n commandHint?: string;\n};\n\nexport type SuggestionStats = {\n pathsConsidered: number;\n produced: number;\n byCategory: Record<string, number>;\n bySeverity: Record<string, number>;\n};\n\nexport type SuggestResult = {\n suggestions: Suggestion[];\n stats: SuggestionStats;\n};\n\nexport const SEVERITY_RANK: Record<SuggestionSeverity, number> = {\n high: 3,\n medium: 2,\n low: 1,\n info: 0,\n};\n","/** Only transport/server-restart failures are retryable; never retry arbitrary SQL errors. */\nexport function isTransientDatabaseError(error: unknown): boolean {\n let current = error;\n for (let depth = 0; depth < 4 && current && typeof current === \"object\"; depth++) {\n const item = current as { code?: unknown; cause?: unknown };\n if (\n typeof item.code === \"string\" &&\n new Set([\n \"ECONNRESET\",\n \"ECONNREFUSED\",\n \"EPIPE\",\n \"CONNECTION_CLOSED\",\n \"CONNECTION_ENDED\",\n \"08000\",\n \"08001\",\n \"08003\",\n \"08006\",\n \"57P01\",\n \"57P02\",\n \"57P03\",\n ]).has(item.code)\n )\n return true;\n current = item.cause;\n }\n return false;\n}\n\n/** A failed write may already have committed: only read-only operations get one retry. */\nexport async function withDatabaseRetry<T>(\n operation: () => Promise<T>,\n readOnly: boolean,\n delayMs = 250,\n): Promise<T> {\n try {\n return await operation();\n } catch (error) {\n if (!readOnly || !isTransientDatabaseError(error)) throw error;\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n return operation();\n }\n}\n","/** Preserve compatibility by default; hosts forwarding both forms can select text. */\nexport function serializeToolResult(\n value: unknown,\n format = process.env.CODEBUDDY_RESPONSE_FORMAT ?? \"both\",\n) {\n if (format !== \"text\" && format !== \"both\") {\n throw new Error('CODEBUDDY_RESPONSE_FORMAT must be \"text\" or \"both\"');\n }\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(value) }],\n ...(format === \"both\" && value !== null && typeof value === \"object\" && !Array.isArray(value)\n ? { structuredContent: value as Record<string, unknown> }\n : {}),\n };\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport pino from \"pino\";\nimport { startProjectSync } from \"../automation/project-sync.js\";\nimport type { CodeBuddy } from \"../core/codebuddy.js\";\nimport { codeBuddyConfigSchema } from \"../core/config.js\";\nimport { loadRuntimeConfig } from \"../core/config-file.js\";\nimport { createRuntime } from \"../core/operations.js\";\nimport { resolveInitializedProjectRoot } from \"../core/project-root.js\";\nimport type { CodeBuddyConfig } from \"../core/types.js\";\nimport { flushTelemetry } from \"../telemetry/telemetry.js\";\nimport { VERSION } from \"../version.js\";\nimport { createLazyDatabase } from \"./database.js\";\nimport { serializeToolResult } from \"./tool-result.js\";\nimport { registerCodeBuddyTools, resolveToolProfile } from \"./tools/index.js\";\n\nexport type StartMcpServerOptions = {\n config?: CodeBuddyConfig;\n};\n\nexport async function startMcpServer(options: StartMcpServerOptions = {}): Promise<void> {\n const logger = pino({ level: process.env.LOG_LEVEL ?? \"info\" }, process.stderr);\n let projectRoot: string;\n try {\n projectRoot = await resolveInitializedProjectRoot(\n options.config?.projectRoot ?? process.env.CODEBUDDY_PROJECT_ROOT,\n );\n } catch (error) {\n // Exiting here shows up in the client only as \"server failed to connect\".\n // Stay connected instead, scan nothing, and explain the fix through the\n // `health` tool and the server instructions the agent reads.\n logger.error((error as Error).message);\n await startSetupServer((error as Error).message);\n return;\n }\n const config = {\n ...(options.config ?? (await loadRuntimeConfig(projectRoot, { requireDatabase: false }))),\n projectRoot,\n };\n // Invalid config is a startup error; a missing or unreachable database is not.\n (config.postgresUrl\n ? codeBuddyConfigSchema\n : codeBuddyConfigSchema.omit({ postgresUrl: true })\n ).parse(config);\n const toolProfile = resolveToolProfile();\n // PostgreSQL is optional: file-based tools are served immediately and the\n // database tools report a degraded result until a connection succeeds.\n // A failed or partial memory import must not hide the healthy file-only\n // context, so it is logged, never thrown.\n // `respace` only on connect (server start): a hand edit re-importing live\n // must not re-queue another install's vectors on every file change.\n const importMemory = async (memory: CodeBuddy, respace: boolean) => {\n try {\n const result = await memory.reindexMemory(respace ? {} : { respace: false });\n for (const failure of result.failures) {\n logger.error(`[sync] memory file skipped (${failure.id}): ${failure.error}`);\n }\n } catch (error) {\n logger.error(`[sync] Markdown memory import failed: ${(error as Error).message}`);\n }\n };\n const database = createLazyDatabase(async () => {\n try {\n const runtime = await createRuntime(config, { autoBootstrap: true }).catch(\n (error: unknown) => {\n // The bundled Docker Postgres may simply be stopped (Docker restarted,\n // container removed): start it once in the background (an image pull\n // can take a minute) and fail this attempt now, so database tools\n // answer \"degraded\" at once instead of waiting; once it is up, a\n // retry connects.\n void startBundledPostgres(config.postgresUrl, error, logger).then((started) => {\n if (started) retryUntilConnected();\n });\n throw error;\n },\n );\n await importMemory(runtime.memory, true);\n logger.info(\"PostgreSQL connected; memory tools available\");\n return runtime;\n } catch (error) {\n logger.warn(\n `PostgreSQL unavailable; serving file-based tools only: ${(error as Error).message}`,\n );\n throw error;\n }\n });\n void database.get().catch(() => undefined);\n // After starting the container: PostgreSQL needs a few seconds to accept\n // connections, so retry (past the lazy cooldown) for up to two minutes.\n const retryUntilConnected = (attempt = 0) => {\n if (attempt >= 20 || database.status().state === \"ready\") return;\n setTimeout(() => {\n void database.get().then(\n () => undefined,\n () => retryUntilConnected(attempt + 1),\n );\n }, 6_000).unref();\n };\n const sync = startProjectSync({\n repositoryRoot: projectRoot,\n ...(config.graphify ? { graphify: config.graphify } : {}),\n logger,\n // Hand edits re-import live once PostgreSQL is connected; until then the\n // next successful connect imports everything.\n onMemoryChange: async () => {\n if (database.status().state === \"ready\") {\n await importMemory((await database.get()).memory, false);\n }\n },\n });\n const server = new McpServer({ name: \"codebuddy\", version: VERSION });\n registerCodeBuddyTools(server, { config, database }, toolProfile);\n // Anonymous usage batches; flushTelemetry itself throttles to one per 10 minutes.\n const telemetry = setInterval(() => void flushTelemetry(projectRoot), 60_000);\n telemetry.unref();\n\n const shutdown = async () => {\n logger.info(\"codebuddy MCP server shutting down\");\n clearInterval(telemetry);\n await server.close();\n await sync.close();\n await database.close();\n };\n let stopping: Promise<void> | undefined;\n const stop = () => {\n if (!stopping) stopping = shutdown().finally(() => process.exit(0));\n };\n process.once(\"SIGINT\", stop);\n process.once(\"SIGTERM\", stop);\n // EOF on stdin means the client is gone; without this the server outlives it.\n process.stdin.once(\"end\", stop);\n\n try {\n await sync.ready;\n await server.connect(new StdioServerTransport());\n } catch (error) {\n await sync.close();\n await database.close();\n throw error;\n }\n logger.info(`codebuddy MCP server started over stdio (tool profile: ${toolProfile})`);\n}\n\n/**\n * Connected, but unconfigured: one `health` tool and MCP instructions that say\n * why no project is served and how to fix it. No file is indexed or read.\n */\nasync function startSetupServer(problem: string): Promise<void> {\n const fix = [\n \"Open your project folder in a terminal and run `codebuddy use` (or `codebuddy init`) if it has no .codebuddy/config.json.\",\n \"Then register CodeBuddy from that folder so the client starts it there: `codebuddy claude install` (Claude Desktop) or `codebuddy codex install` (Codex), and restart the client.\",\n \"Or set CODEBUDDY_PROJECT_ROOT to the project's absolute path in this server's env.\",\n ];\n const server = new McpServer(\n { name: \"codebuddy\", version: VERSION },\n {\n instructions: `CodeBuddy is connected but not serving a project: ${problem} To fix it: ${fix.join(\" \")}`,\n },\n );\n server.registerTool(\n \"health\",\n {\n title: \"Health\",\n description:\n \"Report CodeBuddy's status. This server has no project yet; the result says why and how to fix it.\",\n },\n async () => serializeToolResult({ ok: false, project: null, problem, fix }),\n );\n const stop = () => void server.close().finally(() => process.exit(0));\n process.once(\"SIGINT\", stop);\n process.once(\"SIGTERM\", stop);\n process.stdin.once(\"end\", stop);\n await server.connect(new StdioServerTransport());\n}\n\nlet triedBundledPostgres = false;\n\n/**\n * When PostgreSQL refuses connections at the bundled default address\n * (localhost:5432, user codebuddy), start the bundled container once per\n * process: `docker start codebuddy-postgres`, or `docker compose up -d` when\n * the container was removed (its data volume is reused). Never starts Docker\n * itself. CODEBUDDY_DOCKER_AUTOSTART=0 turns this off.\n */\nexport async function startBundledPostgres(\n postgresUrl: string,\n error: unknown,\n logger: Pick<pino.Logger, \"info\" | \"warn\">,\n): Promise<boolean> {\n if (triedBundledPostgres || process.env.CODEBUDDY_DOCKER_AUTOSTART === \"0\") return false;\n if (!isBundledPostgres(postgresUrl) || !isConnectionRefused(error)) return false;\n triedBundledPostgres = true;\n const { isDockerDaemonRunning } = await import(\"../cli/commands/docker-autostart.js\");\n if (!(await isDockerDaemonRunning())) {\n logger.warn(\n \"PostgreSQL is down and Docker is not running; start Docker Desktop, then `codebuddy postgres up`.\",\n );\n return false;\n }\n const { execFile } = await import(\"node:child_process\");\n const started = await new Promise<boolean>((done) =>\n execFile(\"docker\", [\"start\", \"codebuddy-postgres\"], { timeout: 30_000 }, (failed) =>\n done(failed === null),\n ),\n );\n if (started) {\n logger.info(\"Started the stopped codebuddy-postgres container; retrying PostgreSQL.\");\n return true;\n }\n const { postgresUp } = await import(\"../cli/commands/postgres-docker.js\");\n const result = await postgresUp().catch(() => ({ code: 1, stderr: \"docker compose failed\" }));\n if (result.code === 0) {\n logger.info(\"Started the bundled PostgreSQL container; retrying PostgreSQL.\");\n return true;\n }\n logger.warn(\n `Could not start the bundled PostgreSQL container: ${String(result.stderr).trim().slice(0, 200)}`,\n );\n return false;\n}\n\n/** The address `codebuddy use` / docker-compose.yml set up. */\nexport function isBundledPostgres(postgresUrl: string): boolean {\n try {\n const url = new URL(postgresUrl);\n return (\n [\"localhost\", \"127.0.0.1\", \"::1\", \"[::1]\"].includes(url.hostname) &&\n (url.port === \"\" || url.port === \"5432\") &&\n url.username === \"codebuddy\"\n );\n } catch {\n return false;\n }\n}\n\nfunction isConnectionRefused(error: unknown): boolean {\n for (\n let current = error as { code?: unknown; cause?: unknown; errors?: unknown[] } | undefined;\n current;\n ) {\n if (current.code === \"ECONNREFUSED\") return true;\n if (\n Array.isArray(current.errors) &&\n current.errors.some((inner) => isConnectionRefused(inner))\n ) {\n return true;\n }\n current = current.cause as typeof current;\n }\n return false;\n}\n","import { type FSWatcher, watch as fsWatch } from \"node:fs\";\nimport { join, relative, resolve, sep } from \"node:path\";\nimport { indexRepository } from \"../indexer/engine.js\";\nimport { createCoalescer, watchRepository } from \"../indexer/watch.js\";\nimport { generateGraphifyGraph } from \"../integrations/graphify.js\";\nimport { refreshZvecIndex, type ZvecRefresh } from \"../retrieval/zvec.js\";\n\nexport type ProjectSyncOptions = {\n repositoryRoot: string;\n graphify?: { enabled: boolean; graphPath?: string | undefined };\n logger?: Pick<Console, \"info\" | \"error\">;\n /**\n * Called (coalesced) when a managed Markdown memory file changes. The owner\n * of the database runtime re-imports memory; sync itself never needs it.\n */\n onMemoryChange?: () => Promise<void>;\n};\n\nexport type ProjectSyncHandle = {\n ready: Promise<void>;\n close(): Promise<void>;\n};\n\n/**\n * Owns all derived project state. A running MCP server should never require a\n * user or an agent to remember `index`, `graphify`, or `reindex` commands.\n */\nexport function startProjectSync(options: ProjectSyncOptions): ProjectSyncHandle {\n const repositoryRoot = resolve(options.repositoryRoot);\n const logger = options.logger ?? console;\n const controller = new AbortController();\n let watcher: Promise<void> | null = null;\n let closing = false;\n let memoryWatcher: FSWatcher | null = null;\n let memoryRefresh: ReturnType<typeof createCoalescer> | null = null;\n\n /** Run a derived-state refresh in the background, coalescing overlapping requests. */\n const backgroundRefresh = (task: () => Promise<void>) => {\n let current: Promise<void> | null = null;\n let pending = false;\n const schedule = () => {\n if (closing) return;\n if (current) {\n pending = true;\n return;\n }\n current = (async () => {\n do {\n pending = false;\n await task();\n } while (pending && !closing);\n })().finally(() => {\n current = null;\n if (pending && !closing) schedule();\n });\n };\n return { schedule, settled: async () => current?.catch(() => undefined) };\n };\n\n const graphRefresh = backgroundRefresh(() =>\n refreshGraph().catch((error) =>\n logger.error(`[sync] Graphify refresh failed: ${(error as Error).message}`),\n ),\n );\n // Queries never refresh zg on the prompt path (`--refresh off`); this keeps\n // the zg index incrementally current instead, and is a no-op unless enabled.\n // Closing aborts a running `zg index` rather than waiting it out.\n const zvecRefresh = backgroundRefresh(async () => {\n const result = await refreshZvecIndex(repositoryRoot, { signal: controller.signal }).catch(\n (error): ZvecRefresh => ({\n status: \"failed\",\n reason: (error as Error).message,\n }),\n );\n if (result.status !== \"disabled\") logger.info(`[sync] ${result.reason}`);\n });\n\n const ready = (async () => {\n // The index is the useful fallback if Graphify is unavailable in a\n // pre-made repository. Markdown memory is imported by the database\n // runtime when (and whenever) PostgreSQL connects.\n await indexRepository({ repositoryRoot });\n zvecRefresh.schedule();\n watchMemory();\n if (options.graphify?.enabled) {\n await refreshGraph().catch((error) =>\n logger.error(`[sync] Graphify startup refresh failed: ${(error as Error).message}`),\n );\n }\n\n watcher = watchRepository({\n repositoryRoot,\n signal: controller.signal,\n ...(options.graphify?.enabled\n ? {\n ignoredPaths: [\n options.graphify.graphPath\n ? relative(repositoryRoot, resolve(repositoryRoot, options.graphify.graphPath))\n .split(sep)\n .join(\"/\")\n : \"graphify-out\",\n ],\n }\n : {}),\n onIndex: (result) => {\n if (result.added + result.changed + result.removed === 0) return;\n zvecRefresh.schedule();\n if (options.graphify?.enabled) graphRefresh.schedule();\n },\n onError: (error) => logger.error(`[sync] repository watch failed: ${error.message}`),\n });\n // watchRepository performs its own initial index. It is intentionally\n // detached after the awaited startup pass so MCP can accept requests.\n // A platform without recursive fs.watch still gets a healthy MCP server\n // and the completed startup index.\n void watcher.catch((error) =>\n logger.error(`[sync] live repository watch unavailable: ${(error as Error).message}`),\n );\n })().catch((error) => {\n logger.error(`[sync] startup synchronization failed: ${(error as Error).message}`);\n throw error;\n });\n\n // The repository watcher ignores `.codebuddy/`; Markdown memory is the\n // source of truth, so hand edits and deletions are re-imported live.\n function watchMemory(): void {\n const onMemoryChange = options.onMemoryChange;\n if (closing || !onMemoryChange) return;\n try {\n memoryRefresh = createCoalescer(\n () =>\n onMemoryChange().catch((error) =>\n logger.error(`[sync] memory reindex failed: ${(error as Error).message}`),\n ),\n 300,\n );\n memoryWatcher = fsWatch(\n join(repositoryRoot, \".codebuddy\", \"memory\"),\n { recursive: true },\n (_event, filename) => {\n const name = filename?.replace(/\\\\/g, \"/\") ?? \"\";\n if (/^(facts\\/fact|summaries\\/sum)_[a-z0-9]+\\.md$/.test(name)) memoryRefresh?.trigger();\n },\n );\n memoryWatcher.on(\"error\", () => memoryWatcher?.close());\n } catch (error) {\n logger.error(`[sync] live memory watch unavailable: ${(error as Error).message}`);\n }\n }\n\n async function refreshGraph(): Promise<void> {\n const result = await generateGraphifyGraph({\n repositoryRoot,\n ...(options.graphify?.graphPath ? { graphPath: options.graphify.graphPath } : {}),\n });\n logger.info(`[sync] Graphify updated (${result.nodes} nodes, ${result.edges} edges)`);\n }\n\n return {\n ready,\n async close() {\n closing = true;\n controller.abort();\n memoryRefresh?.stop();\n memoryWatcher?.close();\n await watcher?.catch(() => undefined);\n await Promise.all([graphRefresh.settled(), zvecRefresh.settled()]);\n },\n };\n}\n","import { watch as fsWatch } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { type IndexOptions, indexRepository } from \"./engine.js\";\nimport type { IndexResult } from \"./types.js\";\n\n/**\n * `codebuddy watch` is an explicit, foreground incremental indexer — not a\n * hidden daemon (Proposal 04.3 non-goal). It coalesces bursts of file-save\n * events into a single index pass so a formatter rewriting fifty files triggers\n * one refresh, not fifty.\n */\n\nconst DEFAULT_DEBOUNCE_MS = 300;\n\n/**\n * A trailing debouncer: `trigger()` schedules `fn` to run after `delayMs` of\n * quiet, collapsing any calls made in that window into one. Runs are\n * serialized. A trigger marks the work dirty; a run clears the mark when it\n * starts, so an event that lands while a pass is in flight is never lost — the\n * pass reschedules itself when it settles. `stop()` cancels pending work and\n * resolves once any in-flight pass has finished. Exposed on its own so the\n * coalescing logic is testable without touching the filesystem.\n */\nexport function createCoalescer(\n fn: () => Promise<void>,\n delayMs: number,\n): { trigger: () => void; stop: () => Promise<void> } {\n let timer: NodeJS.Timeout | null = null;\n let running: Promise<void> | null = null;\n let dirty = false;\n let stopped = false;\n // Trailing debounce alone starves under sustained event streams (every new\n // event resets the window). maxWait forces a run this long after the FIRST\n // deferred trigger, so continuous activity still indexes eventually.\n let firstTriggerAt: number | null = null;\n let maxWaitTimer: NodeJS.Timeout | null = null;\n\n const clearTimers = () => {\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n if (maxWaitTimer) {\n clearTimeout(maxWaitTimer);\n maxWaitTimer = null;\n }\n firstTriggerAt = null;\n };\n\n const run = () => {\n // A busy run keeps `dirty` set; its settle step reschedules.\n if (stopped || running) return;\n clearTimers();\n dirty = false;\n running = (async () => {\n try {\n await fn();\n } finally {\n running = null;\n if (dirty) schedule();\n }\n })();\n };\n\n const schedule = () => {\n if (stopped) return;\n dirty = true;\n if (firstTriggerAt === null) {\n firstTriggerAt = Date.now();\n maxWaitTimer = setTimeout(run, MAX_WAIT_MS);\n }\n if (timer) clearTimeout(timer);\n timer = setTimeout(run, delayMs);\n };\n\n return {\n trigger: schedule,\n stop: async () => {\n stopped = true;\n clearTimers();\n await running?.catch(() => undefined);\n },\n };\n}\n\n/** Hard ceiling on how long a burst of events can defer a run. */\nconst MAX_WAIT_MS = 5_000;\n\nexport type WatchOptions = IndexOptions & {\n debounceMs?: number;\n ignoredPaths?: string[];\n onIndex?: (result: IndexResult) => void;\n onError?: (error: Error) => void;\n /** Abort to stop the watcher (e.g. wired to SIGINT). */\n signal?: AbortSignal;\n};\n\n/** Ignore churn we cause ourselves or that git would ignore. */\nexport function isIgnoredEvent(filename: string | null, ignoredPaths: string[] = []): boolean {\n if (!filename) return false;\n const normalized = filename.replace(/\\\\/g, \"/\");\n return (\n ignoredPaths.some((path) => normalized === path || normalized.startsWith(`${path}/`)) ||\n normalized.startsWith(\".codebuddy/\") ||\n normalized.includes(\"/.git/\") ||\n normalized.startsWith(\".git/\") ||\n normalized.includes(\"/node_modules/\") ||\n normalized.startsWith(\"node_modules/\") ||\n normalized.endsWith(\".tmp\")\n );\n}\n\n/**\n * Watch `repositoryRoot` recursively and run an incremental index on change.\n * Resolves when the signal aborts. Does an initial index pass on start so the\n * manifest is fresh before the first edit.\n */\nexport async function watchRepository(options: WatchOptions = {}): Promise<void> {\n const repositoryRoot = resolve(options.repositoryRoot ?? process.cwd());\n const debounceMs = options.debounceMs ?? DEFAULT_DEBOUNCE_MS;\n\n const runIndex = async () => {\n try {\n const result = await indexRepository({\n repositoryRoot,\n ...(options.now ? { now: options.now } : {}),\n });\n options.onIndex?.(result);\n } catch (error) {\n options.onError?.(error as Error);\n }\n };\n\n await runIndex();\n\n const coalescer = createCoalescer(runIndex, debounceMs);\n const watcher = fsWatch(repositoryRoot, { recursive: true }, (_event, filename) => {\n if (isIgnoredEvent(filename, options.ignoredPaths)) return;\n coalescer.trigger();\n });\n\n return new Promise<void>((resolvePromise) => {\n const stop = () => {\n watcher.close();\n // Resolve only after an in-flight pass settles, so callers that stop the\n // watcher never race a manifest write.\n void coalescer.stop().then(() => resolvePromise());\n };\n if (options.signal) {\n if (options.signal.aborted) return stop();\n options.signal.addEventListener(\"abort\", stop, { once: true });\n }\n watcher.on(\"error\", () => stop());\n });\n}\n","import { realpath, stat } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { isAbsolute, parse, resolve } from \"node:path\";\nimport { configPath } from \"./config-file.js\";\n\n/** Resolve a server's project before any indexing, watching, or database work. */\nexport async function resolveInitializedProjectRoot(\n configuredRoot?: string,\n cwd = process.cwd(),\n): Promise<string> {\n if (configuredRoot !== undefined && !isAbsolute(configuredRoot)) {\n throw new Error(\"CODEBUDDY_PROJECT_ROOT must be an absolute path to an initialized project.\");\n }\n const selected = resolve(configuredRoot ?? cwd);\n const root = await realpath(selected);\n if (root === parse(root).root || root === (await realpath(homedir()))) {\n throw new Error(\n \"Select an initialized project folder, not the filesystem root or home folder.\",\n );\n }\n const initialized = await stat(configPath(root)).then(\n (info) => info.isFile(),\n () => false,\n );\n if (!initialized) {\n throw new Error(\n `CodeBuddy will not scan ${root}: run codebuddy use (or codebuddy init) in your project folder first. ` +\n \"For a desktop client, re-register CodeBuddy from that folder to save its project path.\",\n );\n }\n return root;\n}\n","import type { CodeBuddy } from \"../core/codebuddy.js\";\nimport { redactSecrets } from \"../core/config-file.js\";\nimport type { RuntimeHandle } from \"../core/operations.js\";\nimport type { MemoryRepository } from \"../core/repository.js\";\n\nexport type DatabaseServices = { memory: CodeBuddy; repository: MemoryRepository };\n\nexport type DatabaseStatus = {\n available: boolean;\n state: \"idle\" | \"connecting\" | \"ready\" | \"unavailable\";\n error?: string;\n retryInMs?: number;\n};\n\nexport type LazyDatabase = {\n /** Resolve the runtime, connecting (or retrying after the cooldown) on demand. */\n get(): Promise<DatabaseServices>;\n status(): DatabaseStatus;\n close(): Promise<void>;\n};\n\n/**\n * Owns the optional PostgreSQL runtime for the MCP server so file-based tools\n * never wait on it. One connection attempt runs at a time; a failure is cached\n * for `retryMs` so database tools answer fast while Postgres is down, and the\n * first call after the cooldown retries. Once connected, the runtime (and its\n * embedding worker) is created exactly once.\n */\nexport function createLazyDatabase(\n connect: () => Promise<RuntimeHandle>,\n options: { retryMs?: number } = {},\n): LazyDatabase {\n const retryMs = options.retryMs ?? 5_000;\n let runtime: RuntimeHandle | undefined;\n let pending: Promise<RuntimeHandle> | undefined;\n let failure: { error: string; at: number } | undefined;\n let closed = false;\n\n return {\n get() {\n if (runtime) return Promise.resolve(runtime);\n if (closed) return Promise.reject(new Error(\"CodeBuddy MCP server is shutting down.\"));\n if (pending) return pending;\n if (failure && Date.now() - failure.at < retryMs) {\n return Promise.reject(new Error(failure.error));\n }\n pending = connect()\n .then(\n async (handle) => {\n if (closed) {\n await handle.close();\n throw new Error(\"CodeBuddy MCP server is shutting down.\");\n }\n runtime = handle;\n failure = undefined;\n return handle;\n },\n (error: unknown) => {\n failure = { error: describeError(error), at: Date.now() };\n throw error;\n },\n )\n .finally(() => {\n pending = undefined;\n });\n return pending;\n },\n status() {\n if (runtime) return { available: true, state: \"ready\" };\n if (pending) return { available: false, state: \"connecting\" };\n if (!failure) return { available: false, state: \"idle\" };\n return {\n available: false,\n state: \"unavailable\",\n error: failure.error,\n retryInMs: Math.max(0, failure.at + retryMs - Date.now()),\n };\n },\n async close() {\n closed = true;\n await pending?.catch(() => undefined);\n const current = runtime;\n runtime = undefined;\n await current?.close();\n },\n };\n}\n\n/** Bounded, credential-free error text (connection errors can echo the URL). */\nfunction describeError(error: unknown): string {\n const err = error as { message?: string; code?: string } | undefined;\n const text = err?.message || err?.code || String(error);\n return String(redactSecrets(text)).slice(0, 300);\n}\n"],"mappings":"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","names":["createHash","createHash","createHash","createHash","readFile","join","readFile","join","join","join","resolve","fsWatch","join","resolve","resolve","resolve","resolve","fsWatch","join","homedir","resolve","resolve","homedir"]}
|