@orquentra/codebuddy 2.6.0 → 2.6.2
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/CLAUDE_CODEX.md +6 -4
- package/WORKFLOW.md +5 -5
- package/dist/{chunk-UN57FKQX.js → chunk-2XDPKFUW.js} +111 -847
- package/dist/chunk-2XDPKFUW.js.map +1 -0
- package/dist/{chunk-QDBDYCM2.js → chunk-5FW3PMNP.js} +2 -2
- package/dist/{chunk-776EQXDV.js → chunk-5KZY6OTG.js} +82 -5
- package/dist/chunk-5KZY6OTG.js.map +1 -0
- package/dist/{chunk-UFZD3JAA.js → chunk-5MQOE4J6.js} +3 -3
- package/dist/chunk-5UH3BEQR.js +32 -0
- package/dist/chunk-5UH3BEQR.js.map +1 -0
- package/dist/{chunk-N34XHWBA.js → chunk-B6CO63SQ.js} +8 -7
- package/dist/chunk-B6CO63SQ.js.map +1 -0
- package/dist/chunk-CSRD5OQA.js +79 -0
- package/dist/chunk-CSRD5OQA.js.map +1 -0
- package/dist/{chunk-PYLH4MH5.js → chunk-FJOTP632.js} +1 -1
- package/dist/{chunk-U4HAJLIB.js → chunk-IBLJOHJL.js} +15 -2
- package/dist/chunk-IBLJOHJL.js.map +1 -0
- package/dist/chunk-IMFUYEZA.js +1607 -0
- package/dist/chunk-IMFUYEZA.js.map +1 -0
- package/dist/{chunk-SYWJG5NA.js → chunk-J2EAZ4MA.js} +20 -7
- package/dist/chunk-J2EAZ4MA.js.map +1 -0
- package/dist/{chunk-L5AYZC3F.js → chunk-NERKZSSE.js} +7 -7
- package/dist/{chunk-PCE4STAY.js → chunk-OWWCDRXW.js} +5 -5
- package/dist/{chunk-WHZSVY2L.js → chunk-QBDJXGG5.js} +2 -2
- package/dist/{chunk-VAKBJV26.js → chunk-R7CD6EXS.js} +307 -1822
- package/dist/chunk-R7CD6EXS.js.map +1 -0
- package/dist/{chunk-6MKEIDX5.js → chunk-RAJJSCIP.js} +2 -2
- package/dist/chunk-S6VEG4S2.js +991 -0
- package/dist/chunk-S6VEG4S2.js.map +1 -0
- package/dist/cli/index.js +14 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/{codebuddy-DM-i0Fu5.d.ts → codebuddy-B_pCaQrV.d.ts} +22 -2
- package/dist/{config-KFEHLV6W.js → config-DEVHUDIU.js} +3 -3
- package/dist/docker-autostart-KDME7TVC.js +12 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +19 -15
- package/dist/langgraph/index.d.ts +1 -1
- package/dist/lean-command-HTQCPH76.js +15 -0
- package/dist/{local-OTOY56B4.js → local-5MZURLCZ.js} +6 -2
- package/dist/{main-HFHLGID4.js → main-MTBQZGJV.js} +139 -171
- package/dist/main-MTBQZGJV.js.map +1 -0
- package/dist/{memory-4RGVLPKG.js → memory-KIC5FJVW.js} +4 -4
- package/dist/{operations-LOBAQRLO.js → operations-POCHY3WR.js} +5 -4
- package/dist/postgres-docker-QQZQ2ABK.js +16 -0
- package/dist/{pretool-command-MQQ2UNQM.js → pretool-command-AX6JXP25.js} +3 -3
- package/dist/{rerank-3P3C2UHN.js → rerank-5QZ3PNUW.js} +4 -4
- package/dist/runtime-CUBOOPZO.js +43 -0
- package/dist/runtime-CUBOOPZO.js.map +1 -0
- package/dist/stdio-HOV4P3DQ.js +12 -0
- package/dist/stdio-HOV4P3DQ.js.map +1 -0
- package/dist/{summaries-ZBV5IN7Y.js → summaries-SB5L2TSW.js} +6 -6
- package/dist/summaries-SB5L2TSW.js.map +1 -0
- package/dist/{zvec-MAPSJQSR.js → zvec-MSRKT7IV.js} +3 -3
- package/dist/zvec-MSRKT7IV.js.map +1 -0
- package/package.json +7 -10
- package/dist/chunk-776EQXDV.js.map +0 -1
- package/dist/chunk-N34XHWBA.js.map +0 -1
- package/dist/chunk-SYWJG5NA.js.map +0 -1
- package/dist/chunk-U4HAJLIB.js.map +0 -1
- package/dist/chunk-UN57FKQX.js.map +0 -1
- package/dist/chunk-VAKBJV26.js.map +0 -1
- package/dist/lean-command-C5YPFKHP.js +0 -15
- package/dist/main-HFHLGID4.js.map +0 -1
- /package/dist/{chunk-QDBDYCM2.js.map → chunk-5FW3PMNP.js.map} +0 -0
- /package/dist/{chunk-UFZD3JAA.js.map → chunk-5MQOE4J6.js.map} +0 -0
- /package/dist/{chunk-PYLH4MH5.js.map → chunk-FJOTP632.js.map} +0 -0
- /package/dist/{chunk-L5AYZC3F.js.map → chunk-NERKZSSE.js.map} +0 -0
- /package/dist/{chunk-PCE4STAY.js.map → chunk-OWWCDRXW.js.map} +0 -0
- /package/dist/{chunk-WHZSVY2L.js.map → chunk-QBDJXGG5.js.map} +0 -0
- /package/dist/{chunk-6MKEIDX5.js.map → chunk-RAJJSCIP.js.map} +0 -0
- /package/dist/{config-KFEHLV6W.js.map → config-DEVHUDIU.js.map} +0 -0
- /package/dist/{lean-command-C5YPFKHP.js.map → docker-autostart-KDME7TVC.js.map} +0 -0
- /package/dist/{local-OTOY56B4.js.map → lean-command-HTQCPH76.js.map} +0 -0
- /package/dist/{operations-LOBAQRLO.js.map → local-5MZURLCZ.js.map} +0 -0
- /package/dist/{memory-4RGVLPKG.js.map → memory-KIC5FJVW.js.map} +0 -0
- /package/dist/{pretool-command-MQQ2UNQM.js.map → operations-POCHY3WR.js.map} +0 -0
- /package/dist/{summaries-ZBV5IN7Y.js.map → postgres-docker-QQZQ2ABK.js.map} +0 -0
- /package/dist/{zvec-MAPSJQSR.js.map → pretool-command-AX6JXP25.js.map} +0 -0
- /package/dist/{rerank-3P3C2UHN.js.map → rerank-5QZ3PNUW.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/migrate-to-files.ts","../src/core/plan-file-store.ts","../src/core/plan-lifecycle.ts","../package.json","../src/version.ts","../src/risk/assessor.ts","../src/risk/signals/churn.ts","../src/risk/signals/incident.ts","../src/risk/signals/policy.ts","../src/risk/service.ts","../src/mcp/tools/index.ts","../src/context/delivery.ts","../src/context/budget.ts","../src/context/engine.ts","../src/worklog/store.ts","../src/hooks/runtime.ts","../src/memory-extract/engine.ts","../src/memory-extract/deterministic.ts","../src/memory-extract/llm.ts","../src/memory-extract/resolution.ts","../src/memory-extract/review-store.ts","../src/memory-extract/rules.ts","../src/tracing/log.ts","../src/hooks/semantic.ts","../src/hooks/staging.ts","../src/suggest/engine.ts","../src/suggest/types.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 \"../memory-extract/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 { mkdir, open, readdir, readFile, rm, stat } from \"node:fs/promises\";\nimport { dirname, join, relative, resolve, sep } from \"node:path\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { z } from \"zod\";\nimport {\n assertNoSymlinkBetween,\n composeMarkdown,\n parseFrontMatter,\n writeAtomic,\n} from \"./markdown-store-fs.js\";\n\n/**\n * Plans are durable Markdown artifacts under `.codebuddy/plans/`. Git is\n * the version history; PostgreSQL (when present) is a derived index, never\n * the source of truth. This store owns the on-disk representation:\n * schema, round-trip serialization, atomic writes, and the locks that keep\n * concurrent CLI/MCP clients from corrupting a plan or approving two active\n * plans in one namespace.\n */\n\nexport const PLAN_STATUSES = [\"draft\", \"approved\", \"executing\", \"complete\", \"abandoned\"] as const;\nexport type PlanStatus = (typeof PLAN_STATUSES)[number];\n\n/** A plan is \"active\" while approved or executing — at most one per namespace. */\nexport const ACTIVE_PLAN_STATUSES: readonly PlanStatus[] = [\"approved\", \"executing\"];\n\nconst plannedFileSchema = z.object({\n path: z.string().min(1),\n action: z.enum([\"create\", \"edit\", \"delete\"]),\n notes: z.string().default(\"\"),\n});\n\nconst plannedTestSchema = z.object({\n path: z.string().min(1),\n description: z.string().default(\"\"),\n});\n\nconst nullableDateTime = z\n .preprocess(\n (value) => (value instanceof Date ? value.toISOString() : value),\n z.string().datetime().nullable(),\n )\n .nullable();\n\nconst planFrontMatterSchema = z.object({\n schemaVersion: z.literal(1),\n id: z.string().regex(/^pln_[a-z0-9]+$/),\n namespace: z.string().min(1),\n type: z.literal(\"plan\"),\n title: z.string().min(1),\n status: z.enum(PLAN_STATUSES),\n brief: z.string(),\n filesToTouch: z.array(plannedFileSchema).default([]),\n testsToAdd: z.array(plannedTestSchema).default([]),\n outOfScope: z.array(z.string()).default([]),\n risks: z.array(z.string()).default([]),\n createdAt: z.preprocess(\n (value) => (value instanceof Date ? value.toISOString() : value),\n z.string().datetime(),\n ),\n createdByAgent: z.string().nullable(),\n approvedAt: nullableDateTime,\n executingAt: nullableDateTime,\n completedAt: nullableDateTime,\n abandonedAt: nullableDateTime,\n commitSha: z.string().nullable(),\n abandonReason: z.string().nullable(),\n});\n\nexport type PlannedFile = z.infer<typeof plannedFileSchema>;\nexport type PlannedTest = z.infer<typeof plannedTestSchema>;\nexport type PlanFrontMatter = z.infer<typeof planFrontMatterSchema>;\n\n/** A fully materialized plan: front matter + Markdown body + on-disk path. */\nexport type PlanSpec = PlanFrontMatter & {\n body: string;\n path: string;\n};\n\n/** Shape accepted by `writePlan` — path/schemaVersion/type are managed here. */\nexport type PlanWrite = Omit<PlanFrontMatter, \"schemaVersion\" | \"type\"> & {\n body: string;\n};\n\nexport type PlanLockOptions = {\n /** Max time to wait for the lock before failing. */\n timeoutMs?: number;\n /** A lock older than this is considered abandoned and stolen. */\n staleMs?: number;\n /** Poll interval while waiting. */\n pollMs?: number;\n};\n\nexport class PlanLockError extends Error {\n constructor(resource: string) {\n super(\n `Could not acquire lock for ${resource} within the timeout. Another client may be holding it.`,\n );\n this.name = \"PlanLockError\";\n }\n}\n\nexport class PlanValidationError extends Error {\n constructor(path: string, issues: string[]) {\n super(`Invalid plan file ${path}:\\n${issues.map((issue) => ` - ${issue}`).join(\"\\n\")}`);\n this.name = \"PlanValidationError\";\n }\n}\n\nconst DEFAULT_LOCK: Required<PlanLockOptions> = {\n timeoutMs: 5_000,\n staleMs: 30_000,\n pollMs: 50,\n};\n\nexport class PlanFileStore {\n readonly repositoryRoot: string;\n readonly plansDirectory: string;\n readonly locksDirectory: string;\n\n constructor(repositoryRoot = process.cwd()) {\n this.repositoryRoot = resolve(repositoryRoot);\n this.plansDirectory = join(this.repositoryRoot, \".codebuddy\", \"plans\");\n this.locksDirectory = join(this.plansDirectory, \".locks\");\n }\n\n // ── Read / write ────────────────────────────────────────────────────\n\n async writePlan(input: PlanWrite): Promise<string> {\n const path = this.planPath(input.id);\n await this.prepareDirectory(this.plansDirectory);\n await assertNoSymlinkBetween(this.repositoryRoot, dirname(path));\n\n const frontMatter = stringifyYaml({\n schemaVersion: 1,\n id: input.id,\n namespace: input.namespace,\n type: \"plan\",\n title: input.title,\n status: input.status,\n brief: input.brief,\n filesToTouch: input.filesToTouch,\n testsToAdd: input.testsToAdd,\n outOfScope: input.outOfScope,\n risks: input.risks,\n createdAt: input.createdAt,\n createdByAgent: input.createdByAgent,\n approvedAt: input.approvedAt,\n executingAt: input.executingAt,\n completedAt: input.completedAt,\n abandonedAt: input.abandonedAt,\n commitSha: input.commitSha,\n abandonReason: input.abandonReason,\n });\n\n await writeAtomic(path, composeMarkdown(frontMatter, input.body));\n return path;\n }\n\n async readPlan(pathOrId: string): Promise<PlanSpec> {\n const path = pathOrId.endsWith(\".md\") ? this.safePath(pathOrId) : this.planPath(pathOrId);\n await assertNoSymlinkBetween(this.repositoryRoot, path);\n const parsed = parseFrontMatter(await readFile(path, \"utf8\"));\n const result = planFrontMatterSchema.safeParse(parseYaml(parsed.frontMatter));\n if (!result.success) {\n throw new PlanValidationError(path, formatIssues(result.error));\n }\n return { ...result.data, body: parsed.content.trim(), path };\n }\n\n async listPlans(): Promise<PlanSpec[]> {\n try {\n await this.prepareDirectory(this.plansDirectory);\n const entries = await readdir(this.plansDirectory, { withFileTypes: true });\n const plans: PlanSpec[] = [];\n for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {\n // Plans are always written as `<pln_id>.md`. Ignore any other markdown\n // (hand-written notes, READMEs, build plans) so a shared plans dir with\n // non-plan files can't make discovery throw.\n if (!entry.isFile() || !entry.name.endsWith(\".md\")) continue;\n if (!/^pln_[a-z0-9]+\\.md$/.test(entry.name)) continue;\n plans.push(await this.readPlan(join(this.plansDirectory, entry.name)));\n }\n return plans;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return [];\n throw error;\n }\n }\n\n async deletePlan(id: string): Promise<void> {\n await rm(this.planPath(id), { force: true });\n }\n\n /**\n * The single approved-or-executing plan in `namespace`, or null. If the\n * filesystem somehow holds more than one (a hand edit, a crash mid-\n * transition), the earliest-created wins and the situation is the\n * caller's to reconcile.\n */\n async findActivePlan(namespace: string): Promise<PlanSpec | null> {\n const active = (await this.listPlans()).filter(\n (plan) => plan.namespace === namespace && ACTIVE_PLAN_STATUSES.includes(plan.status),\n );\n if (active.length === 0) return null;\n active.sort((left, right) => left.createdAt.localeCompare(right.createdAt));\n return active[0] ?? null;\n }\n\n // ── Locking ─────────────────────────────────────────────────────────\n\n /** Serialize amendments to a single plan. */\n async withPlanLock<T>(id: string, fn: () => Promise<T>, options?: PlanLockOptions): Promise<T> {\n this.assertPlanId(id);\n return this.withLock(`${id}.lock`, id, fn, options);\n }\n\n /**\n * Serialize lifecycle transitions across an entire namespace so two\n * clients cannot both promote a plan to active. Hold this around the\n * read-active-then-write window.\n */\n async withNamespaceLock<T>(\n namespace: string,\n fn: () => Promise<T>,\n options?: PlanLockOptions,\n ): Promise<T> {\n const safeName = namespace.replace(/[^a-zA-Z0-9_.:-]/g, \"-\");\n return this.withLock(`namespace_${safeName}.lock`, `namespace ${namespace}`, fn, options);\n }\n\n private async withLock<T>(\n lockFileName: string,\n resourceLabel: string,\n fn: () => Promise<T>,\n options?: PlanLockOptions,\n ): Promise<T> {\n const config = { ...DEFAULT_LOCK, ...options };\n await this.prepareDirectory(this.locksDirectory);\n const lockPath = join(this.locksDirectory, lockFileName);\n const deadline = Date.now() + config.timeoutMs;\n\n for (;;) {\n try {\n const handle = await open(lockPath, \"wx\", 0o600);\n await handle.writeFile(`${process.pid}\\n${new Date().toISOString()}\\n`, \"utf8\");\n await handle.close();\n break;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") throw error;\n if (await this.tryStealStaleLock(lockPath, config.staleMs)) continue;\n if (Date.now() >= deadline) throw new PlanLockError(resourceLabel);\n await delay(config.pollMs);\n }\n }\n\n try {\n return await fn();\n } finally {\n await releaseOwnedLock(lockPath);\n }\n }\n\n private async tryStealStaleLock(lockPath: string, staleMs: number): Promise<boolean> {\n try {\n const info = await stat(lockPath);\n if (Date.now() - info.mtimeMs > staleMs) {\n await rm(lockPath, { force: true });\n return true;\n }\n } catch (error) {\n // Lock vanished between EEXIST and stat — treat as free, retry.\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return true;\n throw error;\n }\n return false;\n }\n\n // ── Paths ───────────────────────────────────────────────────────────\n\n private planPath(id: string): string {\n this.assertPlanId(id);\n return this.safePath(join(this.plansDirectory, `${id}.md`));\n }\n\n private assertPlanId(id: string): void {\n if (!/^pln_[a-z0-9]+$/.test(id)) {\n throw new Error(`Invalid plan id: ${id}`);\n }\n }\n\n private safePath(path: string): string {\n const absolute = resolve(path);\n const relativePath = relative(this.repositoryRoot, absolute);\n if (relativePath === \"..\" || relativePath.startsWith(`..${sep}`) || relativePath === \"\") {\n throw new Error(`Plan path escapes repository root: ${path}`);\n }\n return absolute;\n }\n\n private async prepareDirectory(directory: string): Promise<void> {\n await assertNoSymlinkBetween(this.repositoryRoot, dirname(directory));\n await mkdir(directory, { recursive: true, mode: 0o700 });\n }\n}\n\nfunction formatIssues(error: z.ZodError): string[] {\n return error.issues.map((issue) => {\n const path = issue.path.length > 0 ? issue.path.join(\".\") : \"(root)\";\n return `${path}: ${issue.message}`;\n });\n}\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Delete `lockPath` only when it still belongs to this process. If a holder's\n * work ran past `staleMs`, another client may have stolen and re-created the\n * lock — deleting it unconditionally would release *their* critical section.\n */\nasync function releaseOwnedLock(lockPath: string): Promise<void> {\n try {\n const contents = await readFile(lockPath, \"utf8\");\n const ownerPid = Number.parseInt(contents.split(\"\\n\")[0] ?? \"\", 10);\n if (ownerPid === process.pid) {\n await rm(lockPath, { force: true });\n }\n } catch {\n // Lock already vanished (stolen then released) — nothing to release.\n }\n}\n","import { generateEntityId } from \"./ids.js\";\nimport {\n ACTIVE_PLAN_STATUSES,\n type PlanFileStore,\n type PlannedFile,\n type PlannedTest,\n type PlanSpec,\n type PlanStatus,\n} from \"./plan-file-store.js\";\n\n/**\n * The plan lifecycle service enforces the state machine on top of the\n * file store. The store knows how to read/write/lock; this service knows\n * which transitions are legal and guarantees that at most one plan in a\n * namespace is active at a time. Transitions that change active state run\n * under the namespace lock; amendments run under the per-plan lock.\n */\n\n/** Legal transitions. Terminal states (complete, abandoned) have none. */\nconst TRANSITIONS: Record<PlanStatus, readonly PlanStatus[]> = {\n draft: [\"approved\", \"abandoned\"],\n approved: [\"executing\", \"abandoned\"],\n executing: [\"complete\", \"abandoned\"],\n complete: [],\n abandoned: [],\n};\n\n/** Only these states accept content amendments. */\nconst AMENDABLE: readonly PlanStatus[] = [\"draft\", \"executing\"];\n\nexport class PlanTransitionError extends Error {\n constructor(from: PlanStatus, to: PlanStatus) {\n super(`Illegal plan transition: ${from} → ${to}.`);\n this.name = \"PlanTransitionError\";\n }\n}\n\nexport class PlanNotFoundError extends Error {\n constructor(id: string) {\n super(`Plan ${id} not found.`);\n this.name = \"PlanNotFoundError\";\n }\n}\n\nexport class ActivePlanExistsError extends Error {\n readonly activePlanId: string;\n constructor(namespace: string, activePlanId: string) {\n super(\n `Namespace \"${namespace}\" already has an active plan (${activePlanId}). ` +\n `Complete or abandon it before approving another.`,\n );\n this.name = \"ActivePlanExistsError\";\n this.activePlanId = activePlanId;\n }\n}\n\nexport type CreatePlanInput = {\n namespace: string;\n title: string;\n brief: string;\n body?: string;\n filesToTouch?: PlannedFile[];\n testsToAdd?: PlannedTest[];\n outOfScope?: string[];\n risks?: string[];\n createdByAgent?: string | null;\n now?: string;\n};\n\nexport type AmendPlanPatch = {\n title?: string;\n brief?: string;\n body?: string;\n filesToTouch?: PlannedFile[];\n testsToAdd?: PlannedTest[];\n outOfScope?: string[];\n risks?: string[];\n};\n\nexport type CompleteOptions = { commitSha?: string; notes?: string };\nexport type AbandonOptions = { reason?: string };\n\nconst DEFAULT_BODY = [\n \"# Goal\",\n \"\",\n \"(what this plan achieves)\",\n \"\",\n \"# Approach\",\n \"\",\n \"(ordered steps)\",\n \"\",\n \"# Notes\",\n \"\",\n \"(freeform; ignored by tooling)\",\n].join(\"\\n\");\n\nexport class PlanLifecycle {\n private readonly store: PlanFileStore;\n\n constructor(store: PlanFileStore) {\n this.store = store;\n }\n\n async create(input: CreatePlanInput): Promise<PlanSpec> {\n const id = generateEntityId(\"pln\");\n const now = input.now ?? new Date().toISOString();\n await this.store.writePlan({\n id,\n namespace: input.namespace,\n title: input.title,\n status: \"draft\",\n brief: input.brief,\n filesToTouch: input.filesToTouch ?? [],\n testsToAdd: input.testsToAdd ?? [],\n outOfScope: input.outOfScope ?? [],\n risks: input.risks ?? [],\n createdAt: now,\n createdByAgent: input.createdByAgent ?? null,\n approvedAt: null,\n executingAt: null,\n completedAt: null,\n abandonedAt: null,\n commitSha: null,\n abandonReason: null,\n body: input.body ?? DEFAULT_BODY,\n });\n return this.store.readPlan(id);\n }\n\n async approve(id: string, now = new Date().toISOString()): Promise<PlanSpec> {\n const current = await this.require(id);\n // The active-plan guard and the write must be atomic across the\n // namespace, otherwise two approvals could both observe \"no active plan\".\n return this.store.withNamespaceLock(current.namespace, async () => {\n const fresh = await this.require(id);\n this.assertTransition(fresh.status, \"approved\");\n const active = await this.store.findActivePlan(fresh.namespace);\n if (active && active.id !== id) {\n throw new ActivePlanExistsError(fresh.namespace, active.id);\n }\n return this.rewrite(fresh, { status: \"approved\", approvedAt: now });\n });\n }\n\n async start(id: string, now = new Date().toISOString()): Promise<PlanSpec> {\n const current = await this.require(id);\n return this.store.withNamespaceLock(current.namespace, async () => {\n const fresh = await this.require(id);\n this.assertTransition(fresh.status, \"executing\");\n return this.rewrite(fresh, { status: \"executing\", executingAt: now });\n });\n }\n\n async complete(\n id: string,\n options: CompleteOptions = {},\n now = new Date().toISOString(),\n ): Promise<PlanSpec> {\n const current = await this.require(id);\n return this.store.withNamespaceLock(current.namespace, async () => {\n const fresh = await this.require(id);\n this.assertTransition(fresh.status, \"complete\");\n return this.rewrite(fresh, {\n status: \"complete\",\n completedAt: now,\n ...(options.commitSha !== undefined ? { commitSha: options.commitSha } : {}),\n });\n });\n }\n\n async abandon(\n id: string,\n options: AbandonOptions = {},\n now = new Date().toISOString(),\n ): Promise<PlanSpec> {\n const current = await this.require(id);\n return this.store.withNamespaceLock(current.namespace, async () => {\n const fresh = await this.require(id);\n this.assertTransition(fresh.status, \"abandoned\");\n return this.rewrite(fresh, {\n status: \"abandoned\",\n abandonedAt: now,\n ...(options.reason !== undefined ? { abandonReason: options.reason } : {}),\n });\n });\n }\n\n async amend(id: string, patch: AmendPlanPatch): Promise<PlanSpec> {\n // Amend takes the NAMESPACE lock, like every lifecycle transition. The\n // per-plan lock alone let an amend interleave with e.g. abandon():\n // amend reads `draft` -> abandon writes `abandoned` -> amend writes back\n // its stale full snapshot, resurrecting the plan as `draft`. One shared\n // mutex makes read-check-write atomic across all mutators.\n const current = await this.require(id);\n return this.store.withNamespaceLock(current.namespace, async () => {\n const fresh = await this.require(id);\n if (!AMENDABLE.includes(fresh.status)) {\n throw new Error(\n `Plan ${id} is ${fresh.status}; only draft or executing plans can be amended.`,\n );\n }\n return this.rewrite(fresh, {\n ...(patch.title !== undefined ? { title: patch.title } : {}),\n ...(patch.brief !== undefined ? { brief: patch.brief } : {}),\n ...(patch.filesToTouch !== undefined ? { filesToTouch: patch.filesToTouch } : {}),\n ...(patch.testsToAdd !== undefined ? { testsToAdd: patch.testsToAdd } : {}),\n ...(patch.outOfScope !== undefined ? { outOfScope: patch.outOfScope } : {}),\n ...(patch.risks !== undefined ? { risks: patch.risks } : {}),\n ...(patch.body !== undefined ? { body: patch.body } : {}),\n });\n });\n }\n\n async current(namespace: string): Promise<PlanSpec | null> {\n return this.store.findActivePlan(namespace);\n }\n\n private assertTransition(from: PlanStatus, to: PlanStatus): void {\n if (!TRANSITIONS[from].includes(to)) {\n throw new PlanTransitionError(from, to);\n }\n }\n\n private async require(id: string): Promise<PlanSpec> {\n try {\n return await this.store.readPlan(id);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n throw new PlanNotFoundError(id);\n }\n throw error;\n }\n }\n\n /** Rewrite the plan file with a partial set of changed fields. */\n private async rewrite(plan: PlanSpec, changes: Partial<PlanSpec>): Promise<PlanSpec> {\n const next = { ...plan, ...changes };\n await this.store.writePlan({\n id: next.id,\n namespace: next.namespace,\n title: next.title,\n status: next.status,\n brief: next.brief,\n filesToTouch: next.filesToTouch,\n testsToAdd: next.testsToAdd,\n outOfScope: next.outOfScope,\n risks: next.risks,\n createdAt: next.createdAt,\n createdByAgent: next.createdByAgent,\n approvedAt: next.approvedAt,\n executingAt: next.executingAt,\n completedAt: next.completedAt,\n abandonedAt: next.abandonedAt,\n commitSha: next.commitSha,\n abandonReason: next.abandonReason,\n body: next.body,\n });\n return this.store.readPlan(next.id);\n }\n}\n\nexport { ACTIVE_PLAN_STATUSES };\n","{\n \"name\": \"@orquentra/codebuddy\",\n \"version\": \"2.6.0\",\n \"description\": \"Local-first project context and memory for AI coding agents.\",\n \"type\": \"module\",\n \"license\": \"MIT\",\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"author\": \"Orquentra Inc\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/Orquentra-Inc/CodeBuddy\"\n },\n \"engines\": {\n \"node\": \">=20\"\n },\n \"bin\": {\n \"codebuddy\": \"./dist/cli/index.js\"\n },\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\"\n },\n \"./langgraph\": {\n \"types\": \"./dist/langgraph/index.d.ts\",\n \"import\": \"./dist/langgraph/index.js\"\n }\n },\n \"files\": [\n \"dist\",\n \"src/db/migrations\",\n \"README.md\",\n \"CLAUDE_CODEX.md\",\n \"ARCHITECTURE.md\",\n \"WORKFLOW.md\",\n \"LICENSE\",\n \"docker-compose.yml\",\n \"examples\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsx src/cli/index.ts\",\n \"db:generate\": \"drizzle-kit generate\",\n \"db:migrate\": \"drizzle-kit migrate\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run --passWithNoTests\",\n \"test:pg\": \"bash scripts/test-pg-recovery.sh\",\n \"eval:agent-ab\": \"tsx scripts/eval-agent-ab.mts\",\n \"eval:memory-ab\": \"tsx scripts/eval-memory-ab.mts\",\n \"eval:retrieval\": \"tsx scripts/eval-retrieval.mts\",\n \"eval:savings\": \"tsx scripts/eval-task-savings.mts\",\n \"branches:prune\": \"bash scripts/prune-merged-branches.sh\",\n \"lint\": \"biome check .\",\n \"format\": \"biome format --write .\",\n \"prepublishOnly\": \"npm run typecheck && npm test && npm run build\",\n \"eval:semantic\": \"tsx scripts/eval-semantic.mts\"\n },\n \"keywords\": [\n \"mcp\",\n \"memory\",\n \"agent\",\n \"multi-agent\",\n \"huggingface\",\n \"pgvector\",\n \"postgres\",\n \"langgraph\",\n \"claude\"\n ],\n \"homepage\": \"https://github.com/Orquentra-Inc/CodeBuddy\",\n \"bugs\": {\n \"url\": \"https://github.com/Orquentra-Inc/CodeBuddy/issues\"\n },\n \"dependencies\": {\n \"@clack/prompts\": \"^0.11.0\",\n \"@huggingface/inference\": \"^4.13.19\",\n \"@modelcontextprotocol/sdk\": \"^1.17.5\",\n \"commander\": \"^14.0.0\",\n \"drizzle-orm\": \"^0.45.2\",\n \"js-tiktoken\": \"^1.0.21\",\n \"langsmith\": \"^0.7.10\",\n \"ora\": \"^8.2.0\",\n \"p-queue\": \"^8.1.0\",\n \"p-retry\": \"^6.2.1\",\n \"p-timeout\": \"^6.1.4\",\n \"picocolors\": \"^1.1.1\",\n \"pino\": \"^9.9.0\",\n \"pino-pretty\": \"^13.1.1\",\n \"postgres\": \"^3.4.7\",\n \"yaml\": \"^2.9.0\",\n \"zod\": \"^4.6.7\"\n },\n \"peerDependencies\": {\n \"@langchain/langgraph\": \"^0.2.0 || ^0.3.0\"\n },\n \"peerDependenciesMeta\": {\n \"@langchain/langgraph\": {\n \"optional\": true\n }\n },\n \"devDependencies\": {\n \"@biomejs/biome\": \"^2.5.0\",\n \"@types/node\": \"^24.3.0\",\n \"drizzle-kit\": \"^0.31.10\",\n \"tsup\": \"^8.5.0\",\n \"tsx\": \"^4.20.5\",\n \"typescript\": \"^5.9.2\",\n \"vitest\": \"^4.1.12\"\n },\n \"optionalDependencies\": {\n \"@huggingface/transformers\": \"^4.3.2\"\n }\n}\n","import pkg from \"../package.json\" with { type: \"json\" };\n\n/**\n * The single source of truth for the product version. `package.json` is the\n * canonical value (npm reads it for the published package); the CLI `--version`\n * flag and the MCP server handshake both import it from here so a version bump\n * only ever touches `package.json`. The bundler inlines this at build time, so\n * there is no runtime file read.\n */\nexport const VERSION: string = pkg.version;\n","import type {\n Assessment,\n AssessmentInput,\n Evidence,\n RiskCategory,\n RiskItem,\n Signal,\n SignalContribution,\n SignalStat,\n} from \"./types.js\";\n\nexport type AssessorOptions = {\n /** Items scoring below this are dropped from the result. Default 0. */\n minScore?: number;\n};\n\ntype ContributionWithSignal = {\n signal: Signal;\n contribution: SignalContribution;\n};\n\n/**\n * Runs every enabled signal in parallel and folds their per-path\n * contributions into a single ranked list. Scoring is deterministic: the\n * same inputs and the same cache state always produce the same output, with\n * stable tie-breaking.\n */\nexport class RiskAssessor {\n private readonly signals: Signal[];\n private readonly minScore: number;\n\n constructor(signals: Signal[], options: AssessorOptions = {}) {\n this.signals = signals;\n this.minScore = options.minScore ?? 0;\n }\n\n async assess(input: AssessmentInput): Promise<Assessment> {\n const enabled = this.signals.filter((signal) => signal.enabled);\n\n const settled = await Promise.all(\n enabled.map(async (signal) => ({\n signal,\n contributions: await signal.assess(input),\n })),\n );\n\n // Group contributions by path, remembering which signal produced each.\n const byPath = new Map<string, ContributionWithSignal[]>();\n const perSignal = new Map<string, SignalStat>();\n\n for (const { signal, contributions } of settled) {\n const stat: SignalStat = perSignal.get(signal.id) ?? {\n id: signal.id,\n category: signal.category,\n contributions: 0,\n totalWeight: 0,\n };\n for (const contribution of contributions) {\n // A signal that returns no evidence for a path does not get to vote —\n // the normalization only counts signals that actually have something\n // to say. This keeps a silent signal from diluting a real one.\n if (contribution.evidence.length === 0) continue;\n const list = byPath.get(contribution.path) ?? [];\n list.push({ signal, contribution });\n byPath.set(contribution.path, list);\n stat.contributions += 1;\n stat.totalWeight += contribution.weight;\n }\n perSignal.set(signal.id, stat);\n }\n\n const items: RiskItem[] = [];\n for (const [path, contributions] of byPath) {\n items.push(this.fold(path, contributions));\n }\n\n const ranked = items.filter((item) => item.score >= this.minScore).sort(compareRiskItems);\n\n return {\n items: ranked,\n stats: {\n pathsConsidered: input.paths.length,\n itemsProduced: ranked.length,\n signalsRun: enabled.length,\n perSignal: [...perSignal.values()].sort((a, b) => a.id.localeCompare(b.id)),\n },\n };\n }\n\n /** Fold all contributions for one path into a single RiskItem. */\n private fold(path: string, contributions: ContributionWithSignal[]): RiskItem {\n let weightedSum = 0;\n let coefficientSum = 0;\n let dominant: ContributionWithSignal | null = null;\n const evidence: Evidence[] = [];\n const contributingSignals: string[] = [];\n\n for (const entry of contributions) {\n const coefficient = entry.signal.coefficient;\n weightedSum += entry.contribution.weight * coefficient;\n coefficientSum += coefficient;\n evidence.push(...entry.contribution.evidence);\n contributingSignals.push(entry.signal.id);\n if (!dominant || dominantWeight(entry) > dominantWeight(dominant)) {\n dominant = entry;\n }\n }\n\n // Normalize only over the signals that contributed, so a path is not\n // punished for the signals that stayed silent about it.\n const score = coefficientSum === 0 ? 0 : clip(weightedSum / coefficientSum, 0, 100);\n const category: RiskCategory = dominant?.signal.category ?? \"policy\";\n const reason = dominant?.contribution.reason ?? \"\";\n\n return {\n path,\n score: round2(score),\n category,\n reason,\n contributingSignals: contributingSignals.sort(),\n evidence,\n };\n }\n}\n\nfunction dominantWeight(entry: ContributionWithSignal): number {\n return entry.contribution.weight * entry.signal.coefficient;\n}\n\n/** Deterministic ordering: score desc, then more signals, then path asc. */\nfunction compareRiskItems(a: RiskItem, b: RiskItem): number {\n if (b.score !== a.score) return b.score - a.score;\n if (b.contributingSignals.length !== a.contributingSignals.length) {\n return b.contributingSignals.length - a.contributingSignals.length;\n }\n return a.path.localeCompare(b.path);\n}\n\nfunction clip(value: number, low: number, high: number): number {\n return Math.min(high, Math.max(low, value));\n}\n\nfunction round2(value: number): number {\n return Math.round(value * 100) / 100;\n}\n","import { spawn } from \"node:child_process\";\nimport { realpath } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport type { Signal, SignalContribution } from \"../types.js\";\n\nexport type ChurnSignalOptions = {\n repositoryRoot: string;\n enabled?: boolean;\n coefficient?: number;\n since?: string;\n};\n\ntype CommitRecord = {\n sha: string;\n author: string;\n ts: string;\n message: string;\n};\n\nconst GIT_LOG_CONCURRENCY = 4;\n\nexport function createChurnSignal(options: ChurnSignalOptions): Signal {\n return {\n id: \"git-churn\",\n category: \"churn\",\n enabled: options.enabled ?? true,\n coefficient: options.coefficient ?? 0.7,\n async assess(input) {\n // Churn is only meaningful at the repository root. Check it once per\n // assessment, not once per path: it was half of every git spawn (#45).\n const root = await runGit(options.repositoryRoot, [\"rev-parse\", \"--show-toplevel\"]);\n // git prints the symlink-resolved top level (macOS /var -> /private/var).\n const expected = await realpath(options.repositoryRoot).catch(() =>\n resolve(options.repositoryRoot),\n );\n if (root.code !== 0 || resolve(root.stdout.trim()) !== expected) {\n return [];\n }\n // `git log --follow` takes one path: run a few at a time, kept in path order.\n const since = options.since ?? \"30 days ago\";\n const logs: CommitRecord[][] = [];\n for (let start = 0; start < input.paths.length; start += GIT_LOG_CONCURRENCY) {\n const batch = input.paths.slice(start, start + GIT_LOG_CONCURRENCY);\n logs.push(\n ...(await Promise.all(\n batch.map((path) => gitLogForPath(options.repositoryRoot, path, since)),\n )),\n );\n }\n const contributions: SignalContribution[] = [];\n for (const [index, path] of input.paths.entries()) {\n const commits = logs[index] ?? [];\n if (commits.length === 0) continue;\n const authors = new Set(commits.map((commit) => commit.author));\n const reverts = commits.filter((commit) => /revert|rollback|backout/i.test(commit.message));\n const weight = Math.min(100, commits.length * 8 + authors.size * 12 + reverts.length * 20);\n contributions.push({\n path,\n weight,\n reason: `${path} changed ${commits.length} time${commits.length === 1 ? \"\" : \"s\"} in the recent git history by ${authors.size} author${authors.size === 1 ? \"\" : \"s\"}.`,\n evidence: commits.slice(0, 5).map((commit) => ({\n kind: \"git_commit\" as const,\n sha: commit.sha,\n message: commit.message,\n ts: commit.ts,\n })),\n });\n }\n return contributions;\n },\n };\n}\n\nasync function gitLogForPath(\n repositoryRoot: string,\n path: string,\n since: string,\n): Promise<CommitRecord[]> {\n const result = await runGit(repositoryRoot, [\n \"log\",\n \"--follow\",\n `--since=${since}`,\n \"--format=%H%x1f%an%x1f%cI%x1f%s%x1e\",\n \"--\",\n path,\n ]);\n if (result.code !== 0 || result.stdout.trim().length === 0) return [];\n return result.stdout\n .split(\"\\x1e\")\n .map((record) => record.trim())\n .filter(Boolean)\n .map((record) => {\n const [sha = \"\", author = \"\", ts = \"\", message = \"\"] = record.split(\"\\x1f\");\n return { sha, author, ts, message };\n })\n .filter((record) => record.sha.length > 0);\n}\n\nfunction runGit(\n cwd: string,\n args: string[],\n): Promise<{ code: number; stdout: string; stderr: string }> {\n return new Promise((resolve, reject) => {\n const child = spawn(\"git\", args, { cwd, stdio: [\"ignore\", \"pipe\", \"pipe\"] });\n let stdout = \"\";\n let stderr = \"\";\n child.stdout.on(\"data\", (chunk) => {\n stdout += String(chunk);\n });\n child.stderr.on(\"data\", (chunk) => {\n stderr += String(chunk);\n });\n child.on(\"error\", reject);\n child.on(\"close\", (code) => resolve({ code: code ?? 0, stdout, stderr }));\n });\n}\n","import type { IncidentSeverity, MemoryFileStore } from \"../../core/memory-file-store.js\";\nimport type { Signal, SignalContribution } from \"../types.js\";\n\nexport type IncidentSignalOptions = {\n store: MemoryFileStore;\n enabled?: boolean;\n coefficient?: number;\n includeResolved?: boolean;\n};\n\n/**\n * Historical incident signal (Proposal 03.2/03.5 foundation). It reads\n * structured incident metadata from Markdown facts and produces one\n * evidence-backed contribution per affected path.\n */\nexport function createIncidentSignal(options: IncidentSignalOptions): Signal {\n return {\n id: \"incident-memory\",\n category: \"incident\",\n enabled: options.enabled ?? true,\n coefficient: options.coefficient ?? 1.2,\n async assess(input) {\n const incidents = await options.store.findIncidentFactsForPaths({\n namespace: input.namespace,\n paths: input.paths,\n includeResolved: options.includeResolved ?? false,\n });\n\n const byPath = new Map<string, SignalContribution>();\n for (const incident of incidents) {\n for (const path of input.paths) {\n if (!incident.paths.map(normalizePath).includes(normalizePath(path))) continue;\n const existing = byPath.get(path);\n const evidence = {\n kind: \"memory_fact\" as const,\n factId: incident.id,\n content: incident.content,\n createdAt: incident.createdAt,\n };\n if (!existing) {\n byPath.set(path, {\n path,\n weight: severityWeight(incident.severity),\n reason: `This file is linked to prior ${incident.severity} incident memory.`,\n evidence: [evidence],\n });\n continue;\n }\n existing.weight = Math.max(existing.weight, severityWeight(incident.severity));\n existing.reason = `This file is linked to ${existing.evidence.length + 1} prior incident memories.`;\n existing.evidence.push(evidence);\n }\n }\n\n return [...byPath.values()];\n },\n };\n}\n\nfunction normalizePath(path: string): string {\n return path.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\");\n}\n\nfunction severityWeight(severity: IncidentSeverity): number {\n switch (severity) {\n case \"critical\":\n return 95;\n case \"high\":\n return 80;\n case \"medium\":\n return 55;\n case \"low\":\n return 30;\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { parse as parseYaml } from \"yaml\";\nimport { z } from \"zod\";\nimport type { Signal, SignalContribution } from \"../types.js\";\n\nconst policyRuleSchema = z.object({\n id: z.string().min(1),\n pattern: z.string().min(1),\n message: z.string().min(1).optional(),\n reason: z.string().min(1).optional(),\n weight: z.number().min(0).max(100).default(50),\n});\n\nconst policyFileSchema = z.object({\n rules: z.array(policyRuleSchema).default([]),\n});\n\nexport type PolicyRule = z.infer<typeof policyRuleSchema>;\nexport type PolicyFile = z.infer<typeof policyFileSchema>;\n\nexport type PolicySignalOptions = {\n repositoryRoot: string;\n enabled?: boolean;\n coefficient?: number;\n policyPath?: string;\n};\n\nexport function createPolicySignal(options: PolicySignalOptions): Signal {\n return {\n id: \"policy\",\n category: \"policy\",\n enabled: options.enabled ?? true,\n coefficient: options.coefficient ?? 1,\n async assess(input) {\n const policy = await readPolicyFile(\n options.policyPath ?? join(options.repositoryRoot, \".codebuddy\", \"policies.yaml\"),\n );\n if (policy.rules.length === 0) return [];\n\n const byPath = new Map<string, SignalContribution>();\n for (const path of input.paths) {\n for (const rule of policy.rules) {\n if (!matchesPolicyGlob(path, rule.pattern)) continue;\n const existing = byPath.get(path);\n const evidence = { kind: \"policy_rule\" as const, ruleId: rule.id, pattern: rule.pattern };\n const reason = rule.message ?? rule.reason ?? `Policy rule ${rule.id} matched ${path}.`;\n if (!existing) {\n byPath.set(path, {\n path,\n weight: rule.weight,\n reason,\n evidence: [evidence],\n });\n continue;\n }\n existing.weight = Math.max(existing.weight, rule.weight);\n existing.evidence.push(evidence);\n if (rule.weight >= existing.weight) existing.reason = reason;\n }\n }\n return [...byPath.values()];\n },\n };\n}\n\nexport async function readPolicyFile(path: string): Promise<PolicyFile> {\n try {\n const raw = await readFile(path, \"utf8\");\n return policyFileSchema.parse(parseYaml(raw) ?? {});\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return { rules: [] };\n throw error;\n }\n}\n\n/** Match a repo-relative path against a simple `*` / `**` glob pattern. */\nexport function matchesPolicyGlob(path: string, glob: string): boolean {\n const normalizedPath = normalize(path);\n const normalizedGlob = normalize(glob);\n const pattern = normalizedGlob\n .split(\"**\")\n .map((part) => part.split(\"*\").map(escapeRegExp).join(\"[^/]*\"))\n .join(\".*\");\n return new RegExp(`^${pattern}$`).test(normalizedPath);\n}\n\nfunction normalize(path: string): string {\n return path.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\");\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[|\\\\{}()[\\]^$+?.]/g, \"\\\\$&\");\n}\n","import { spawn } from \"node:child_process\";\nimport { relative, resolve, sep } from \"node:path\";\nimport { MemoryFileStore } from \"../core/memory-file-store.js\";\nimport { PlanFileStore } from \"../core/plan-file-store.js\";\nimport { RiskAssessor } from \"./assessor.js\";\nimport { createChurnSignal } from \"./signals/churn.js\";\nimport { createIncidentSignal } from \"./signals/incident.js\";\nimport { createPolicySignal } from \"./signals/policy.js\";\nimport type { Assessment, Signal } from \"./types.js\";\n\nexport type RiskAssessRequest = {\n repositoryRoot?: string;\n namespace: string;\n paths?: string[];\n planId?: string;\n useGit?: boolean;\n limit?: number;\n signals?: Signal[];\n};\n\nexport async function assessRisk(input: RiskAssessRequest): Promise<Assessment> {\n const repositoryRoot = resolve(input.repositoryRoot ?? process.cwd());\n const paths = await resolveRiskPaths({\n repositoryRoot,\n ...(input.planId !== undefined ? { planId: input.planId } : {}),\n ...(input.paths !== undefined ? { paths: input.paths } : {}),\n ...(input.useGit !== undefined ? { useGit: input.useGit } : {}),\n });\n if (paths.length === 0) {\n return {\n items: [],\n stats: { pathsConsidered: 0, itemsProduced: 0, signalsRun: 0, perSignal: [] },\n };\n }\n\n const memoryStore = new MemoryFileStore(repositoryRoot);\n const signals = input.signals ?? [\n createIncidentSignal({ store: memoryStore }),\n createPolicySignal({ repositoryRoot }),\n ...(input.useGit === false ? [] : [createChurnSignal({ repositoryRoot })]),\n ];\n\n const assessment = await new RiskAssessor(signals).assess({\n paths,\n repositoryRoot,\n namespace: input.namespace,\n });\n return {\n ...assessment,\n items: input.limit ? assessment.items.slice(0, input.limit) : assessment.items,\n };\n}\n\nexport async function resolveRiskPaths(input: {\n repositoryRoot: string;\n paths?: string[];\n planId?: string;\n useGit?: boolean;\n}): Promise<string[]> {\n const paths = new Set<string>();\n for (const path of input.paths ?? []) {\n if (!path.trim()) continue;\n // Containment guard: tool callers can pass arbitrary path strings, and a\n // `../`-style escape must never flow into file reads downstream\n // (computeTargetSymbols, savings fallbacks, etc.). Kept paths are\n // rewritten to their resolved repo-relative POSIX form.\n const contained = containedRelativePath(input.repositoryRoot, path);\n if (contained) paths.add(contained);\n }\n\n if (input.planId) {\n const plan = await new PlanFileStore(input.repositoryRoot).readPlan(input.planId);\n for (const file of plan.filesToTouch) {\n const contained = containedRelativePath(input.repositoryRoot, file.path);\n if (contained) paths.add(contained);\n }\n }\n\n if (input.useGit !== false && (input.useGit || paths.size === 0)) {\n for (const path of await changedGitPaths(input.repositoryRoot)) {\n const contained = containedRelativePath(input.repositoryRoot, path);\n if (contained) paths.add(contained);\n }\n }\n\n const resolved = [...paths].sort();\n // Bound the change set so one huge branch cannot blow any payload derived\n // from it. Sorted above, so the cap keeps the lexicographically-first paths.\n return resolved.length > MAX_RESOLVED_PATHS ? resolved.slice(0, MAX_RESOLVED_PATHS) : resolved;\n}\n\n/** Hard cap on resolved target paths per assessment/context call. */\nexport const MAX_RESOLVED_PATHS = 200;\n\n/**\n * Resolve `path` against `root`; return its repo-relative POSIX form when it\n * stays inside the repository, or null when it escapes (or is empty).\n * Rejects NUL bytes and absolute paths pointing outside the root.\n */\nfunction containedRelativePath(root: string, path: string): string | null {\n const trimmed = normalizePath(path);\n if (!trimmed || trimmed.includes(\"\\0\")) return null;\n const absolute = resolve(root, trimmed);\n const relativePath = relative(resolve(root), absolute).split(sep).join(\"/\");\n if (relativePath === \"\" || relativePath === \"..\" || relativePath.startsWith(\"../\")) return null;\n return relativePath;\n}\n\nasync function changedGitPaths(repositoryRoot: string): Promise<string[]> {\n const [tracked, untracked] = await Promise.all([\n runGit(repositoryRoot, [\"diff\", \"--name-only\", \"HEAD\"]),\n runGit(repositoryRoot, [\"ls-files\", \"--others\", \"--exclude-standard\"]),\n ]);\n return [...tracked.stdout.split(\"\\n\"), ...untracked.stdout.split(\"\\n\")]\n .map((path) => path.trim())\n .filter(\n (path) =>\n path && !path.startsWith(\".codebuddy/cache/\") && !path.startsWith(\".codebuddy/worklog/\"),\n );\n}\n\nfunction runGit(\n cwd: string,\n args: string[],\n): Promise<{ code: number; stdout: string; stderr: string }> {\n return new Promise((resolveResult, reject) => {\n const child = spawn(\"git\", args, { cwd, stdio: [\"ignore\", \"pipe\", \"pipe\"] });\n let stdout = \"\";\n let stderr = \"\";\n child.stdout.on(\"data\", (chunk) => {\n stdout += String(chunk);\n });\n child.stderr.on(\"data\", (chunk) => {\n stderr += String(chunk);\n });\n child.on(\"error\", reject);\n child.on(\"close\", (code) => resolveResult({ code: code ?? 0, stdout, stderr }));\n });\n}\n\nfunction normalizePath(path: string): string {\n return path.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\");\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { applySessionDelivery, type DeliveryOptions } from \"../../context/delivery.js\";\nimport { buildBeforeEditContext, buildBootstrapContext } from \"../../context/engine.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 { CodeBuddyConfig, RecallInput, RememberInput } from \"../../core/types.js\";\nimport { llmMemoryOptions } from \"../../hooks/runtime.js\";\nimport { configuredReranker } from \"../../hooks/semantic.js\";\nimport { loadFreshIndex } from \"../../indexer/engine.js\";\nimport { loadArchitectureMap } from \"../../map/cache.js\";\nimport { buildArchitectureMap, 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 { 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} 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\nconst rememberSchema = {\n sessionId: z.string().min(1).max(200).optional(),\n content: z.string().min(1).max(INPUT_LIMITS.contentChars),\n type: z.enum([\"interaction\", \"fact\", \"summary\"]).optional(),\n idempotencyKey: z.string().min(1).max(200).optional(),\n agentId: z.string().min(1).max(INPUT_LIMITS.agentIdChars).optional(),\n};\n\nconst recallSchema = {\n sessionId: z.string().min(1).max(200),\n query: z.string().min(1).max(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};\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({ items: z.array(z.object(rememberSchema)).min(1) }),\n recall: z.object(recallSchema),\n list_facts: z.object({\n subject: z.string().optional(),\n limit: z.number().int().positive().max(100).default(50),\n cursor: z.string().optional(),\n }),\n list_namespaces: z.object({}),\n forget: z.object({ id: z.string().min(1) }),\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` (default) 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 = \"core\" | \"full\";\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 === \"full\") return \"full\";\n if (value === \"core\") return \"core\";\n throw new Error(`CODEBUDDY_TOOL_PROFILE must be \"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) => profile === \"full\" || 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 tool = 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 return json(await run(db));\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: \"Recall prompt-ready CodeBuddy context.\",\n inputSchema: mcpToolInputSchemas.recall.shape,\n },\n async (input) => viaDatabase(\"recall\", (db) => db.memory.recall(toRecallInput(input))),\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 map cache (`.codebuddy/cache/architecture.json`) is the same source the\n * context engine uses. The index is validated against current source first\n * so edited imports are re-read; fall back to a fresh build only when no\n * cache exists yet.\n */\n const cachedMap = async () => {\n const { manifest } = await loadFreshIndex(projectRoot);\n const cached = await loadArchitectureMap(projectRoot, manifest);\n if (cached.map.modules.length > 0) return cached.map;\n return buildArchitectureMap(projectRoot);\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 json(\n await applySessionDelivery(\n projectRoot,\n 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 deliveryOptions(input),\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();\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 return cleanOptional(input) as RecallInput;\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] 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 { estimateTokens } from \"../savings/tokens.js\";\nimport type { TokenStats } from \"./types.js\";\n\nconst WARNING = \"Context incomplete: inspect omitted policies, risks and incidents before editing.\";\n\ntype Payload = Record<string, unknown> & { tokens: TokenStats };\ntype Candidate = { section: string; value: unknown; priority: number; essential: boolean };\n\n/** Budget the complete compact JSON text, including this accounting and delivery metadata. */\nexport function enforceContextBudget<T extends object>(input: T): T {\n const output = structuredClone(input) as Payload;\n if (!output.tokens) return input;\n output.tokens.essentialOmitted ??= 0;\n if (account(output) <= output.tokens.budget) return output as T;\n\n const candidates: Candidate[] = [];\n const add = (section: string, value: unknown, priority: number, essential = false) => {\n candidates.push({ section, value, priority, essential });\n };\n for (const [section, priority] of [\n [\"diffs\", 10],\n [\"neighbours\", 20],\n [\"handoffs\", 30],\n [\"facts\", 40],\n [\"rules\", 45],\n [\"symbols\", 50],\n [\"policyRules\", 90],\n [\"incidents\", 80],\n ] as const) {\n const values = output[section];\n if (!Array.isArray(values)) continue;\n for (const value of values) {\n const essential = section === \"policyRules\" || (section === \"incidents\" && !value.resolved);\n const severity =\n section === \"incidents\"\n ? ({ critical: 4, high: 3, medium: 2, low: 1 }[value.severity as string] ?? 0)\n : 0;\n add(section, value, priority + severity, essential);\n }\n output[section] = [];\n }\n const risks = output.risks as { items: Array<{ score: number }> } | undefined;\n if (risks) {\n for (const value of risks.items)\n add(\n \"risks\",\n value,\n value.score >= 50 ? 100 + value.score : 60 + value.score / 100,\n value.score > 0,\n );\n risks.items = [];\n }\n if (output.plan) {\n add(\"plan\", output.plan, 55);\n output.plan = null;\n }\n const architecture = output.architecture as { hotspots: unknown[] } | undefined;\n if (architecture) {\n for (const value of architecture.hotspots) add(\"hotspots\", value, 25);\n architecture.hotspots = [];\n }\n output.explain = [];\n if (typeof output.task === \"string\") output.task = compact(output.task, 160);\n const riskStats = (output.risks as { stats?: { perSignal: unknown[] } } | undefined)?.stats;\n if (riskStats) riskStats.perSignal = [];\n\n // Reserve a bounded warning before selecting evidence so adding it cannot\n // silently displace the last safety item. Identity and target paths are exact.\n const previousOmitted = output.tokens.essentialOmitted;\n output.tokens.essentialOmitted = previousOmitted + candidates.filter((c) => c.essential).length;\n output.tokens.warning = WARNING;\n if (account(output) > output.tokens.budget && output.task) output.task = null;\n // No candidate selection can rescue a target set that alone exceeds the\n // budget. Avoid repeatedly tokenizing enormous change sets in that case.\n if (\n estimateTokens({ project: output.project, targetPaths: output.targetPaths }) >\n output.tokens.budget\n ) {\n account(output);\n return output as T;\n }\n\n candidates.sort((a, b) => b.priority - a.priority);\n for (const candidate of candidates) {\n const insert = (value: unknown) => {\n if (candidate.section === \"plan\") output.plan = value;\n else if (candidate.section === \"risks\") risks?.items.push(value as { score: number });\n else if (candidate.section === \"hotspots\") architecture?.hotspots.push(value);\n else (output[candidate.section] as unknown[]).push(value);\n };\n const remove = () => {\n if (candidate.section === \"plan\") output.plan = null;\n else if (candidate.section === \"risks\") risks?.items.pop();\n else if (candidate.section === \"hotspots\") architecture?.hotspots.pop();\n else (output[candidate.section] as unknown[]).pop();\n };\n insert(candidate.value);\n if (candidate.essential) output.tokens.essentialOmitted--;\n if (account(output) <= output.tokens.budget) continue;\n remove();\n if (candidate.essential) output.tokens.essentialOmitted++;\n // Keep policy instructions verbatim. A shortened safety item is explicitly\n // incomplete and retains the warning.\n const smaller = candidate.essential\n ? compactSafety(candidate.value)\n : compact(candidate.value, 100);\n insert(smaller);\n if (account(output) <= output.tokens.budget) continue;\n remove();\n }\n if (output.tokens.essentialOmitted === 0) delete output.tokens.warning;\n account(output);\n return output as T;\n}\n\nfunction compactSafety(value: unknown): unknown {\n if (!value || typeof value !== \"object\") return value;\n const item = value as Record<string, unknown>;\n // Patterns, messages, identities and paths remain exact. Risk/incident\n // narratives may be shortened with an explicit incomplete status.\n return {\n ...item,\n ...(typeof item.reason === \"string\" ? { reason: compact(item.reason, 100) } : {}),\n ...(typeof item.summary === \"string\" ? { summary: compact(item.summary, 100) } : {}),\n ...(Array.isArray(item.evidence)\n ? { evidence: item.evidence.slice(0, 1).map((entry) => compact(entry, 100)) }\n : {}),\n };\n}\n\nfunction compact(value: unknown, limit: number): unknown {\n if (typeof value === \"string\")\n return value.length > limit ? `${value.slice(0, limit - 1)}…` : value;\n if (Array.isArray(value)) return value.slice(0, 3).map((item) => compact(item, limit));\n if (value && typeof value === \"object\")\n return Object.fromEntries(\n Object.entries(value).map(([key, item]) => [key, compact(item, limit)]),\n );\n return value;\n}\n\n/** Find an exact fixed point because the reported count itself occupies tokens. */\nfunction account(output: Payload): number {\n const tokens = output.tokens;\n const set = (count: number) => {\n tokens.returnedEstimate = count;\n tokens.countedSurface = \"compact_json\";\n tokens.status =\n count > tokens.budget\n ? \"overflow\"\n : tokens.essentialOmitted > 0\n ? \"minimum_envelope\"\n : \"within_budget\";\n if (tokens.status === \"overflow\") tokens.warning = WARNING;\n };\n // Numeric token boundaries can form a cycle. A JSON whitespace field gives\n // deterministic alternative encodings without changing any evidence.\n for (let padding = 0; padding < 32; padding++) {\n if (padding > 0) output.accountingPadding = \" \".repeat(padding);\n let count = estimateTokens(output);\n for (let attempt = 0; attempt < 12; attempt++) {\n set(count);\n const measured = estimateTokens(output);\n if (measured === count) return count;\n count = measured;\n }\n }\n throw new Error(\"Could not stabilize compact context token accounting\");\n}\n","import { execFile } from \"node:child_process\";\nimport { readFile } from \"node:fs/promises\";\nimport { join, resolve } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { loadPlanPolicy } from \"../core/config-file.js\";\nimport {\n type FactFile,\n type IncidentFactFile,\n MemoryFileStore,\n} from \"../core/memory-file-store.js\";\nimport { isEligibleMemory } from \"../core/memory-lifecycle.js\";\nimport { lexicalTerms, termOverlap } from \"../core/memory-search.js\";\nimport { PlanFileStore, type PlanSpec } from \"../core/plan-file-store.js\";\nimport { PlanLifecycle } from \"../core/plan-lifecycle.js\";\nimport { loadFreshIndex } from \"../indexer/engine.js\";\nimport { extractSymbolTable, type SymbolSpan, supportsSymbols } from \"../indexer/symbols.js\";\nimport type { ArchitectureMap } from \"../map/types.js\";\nimport type { RetrievalHit } from \"../retrieval/zvec.js\";\nimport { assessRisk, resolveRiskPaths } from \"../risk/service.js\";\nimport { matchesPolicyGlob, type PolicyRule, readPolicyFile } from \"../risk/signals/policy.js\";\nimport { estimateTokens } from \"../savings/tokens.js\";\nimport { type HandoffSummary, WorklogStore } from \"../worklog/store.js\";\nimport { enforceContextBudget } from \"./budget.js\";\nimport {\n countTerms,\n discoverTaskPaths,\n identifierTokens,\n loadProjectArchitectureMap,\n namedSegments,\n readBoundedSource,\n TASK_PATH_LIMIT,\n taskTerms,\n} from \"./discovery.js\";\nimport { detectTestCommand, findCoveringTest } from \"./tests.js\";\nimport type {\n ArchitectureSummary,\n BeforeEditContext,\n BootstrapContext,\n ContextSpan,\n DiffHunk,\n FileSymbols,\n IncidentSummary,\n ModuleNeighbours,\n PathSource,\n PlanSummary,\n PolicyRuleSummary,\n RelevantFactSummary,\n TokenStats,\n} from \"./types.js\";\n\n/**\n * Bounds. These keep both tool outputs compact regardless of repository size —\n * a bootstrap or before-edit payload should orient the agent, not dump the\n * whole project. Tune here rather than at each call site.\n */\nconst LIMITS = {\n bootstrapIncidents: 5,\n beforeEditIncidents: 8,\n policyRules: 5,\n hotspots: 5,\n neighbourPaths: 10,\n neighbourEdges: 10,\n incidentSummaryChars: 140,\n symbolFiles: TASK_PATH_LIMIT,\n symbolsPerFile: 12,\n spanFiles: 3,\n excerptLines: 6,\n excerptCharsPerSpan: 400,\n excerptChars: 1_200,\n relevantFacts: 5,\n} as const;\n\nconst DEFAULT_TOKEN_BUDGET = 4_000;\nconst MAX_DIFF_FILES = 8;\nconst MAX_DIFF_CHARS_PER_FILE = 2_400;\nconst execFileAsync = promisify(execFile);\n\nexport type BootstrapInput = {\n repositoryRoot?: string;\n namespace: string;\n tokenBudget?: number;\n};\n\nexport type BeforeEditInput = {\n repositoryRoot?: string;\n namespace: string;\n task?: string;\n paths?: string[];\n planId?: string;\n useGit?: boolean;\n tokenBudget?: number;\n semanticRanker?: SemanticRelevanceRanker;\n /** Optional (`rerank.provider`): orders the fused facts, never admits one. */\n reranker?: ContextReranker;\n evidence?: \"overview\" | \"source\";\n};\n\n/** Cross-encoder scores for (task, document) pairs, in input order (higher = more relevant). */\nexport type ContextReranker = (task: string, documents: string[]) => Promise<number[]>;\n\n/** Dense evidence: cosine per fact id, only for facts at or above the model's floor. */\nexport type SemanticRelevanceRanker = (\n task: string,\n candidates: Array<{ id: string; text: string }>,\n) => Promise<Record<string, number>>;\n\n/**\n * Assemble compact project awareness for the start of a turn: identity, the\n * active plan and policy, top policy rules, incident hotspots, and a\n * lightweight architecture summary. No edit target is required.\n */\nexport async function buildBootstrapContext(input: BootstrapInput): Promise<BootstrapContext> {\n const repositoryRoot = resolve(input.repositoryRoot ?? process.cwd());\n const namespace = input.namespace;\n\n const planStore = new PlanFileStore(repositoryRoot);\n const memoryStore = new MemoryFileStore(repositoryRoot);\n const freshPromise = loadFreshIndex(repositoryRoot);\n const manifestPromise = freshPromise.then((fresh) => fresh.manifest);\n const mapPromise = loadProjectArchitectureMap(repositoryRoot, manifestPromise);\n\n const [activePlan, policy, policyFile, incidents, facts, fresh, map, handoffs] =\n await Promise.all([\n new PlanLifecycle(planStore).current(namespace),\n loadPlanPolicy(repositoryRoot),\n readPolicyFile(join(repositoryRoot, \".codebuddy\", \"policies.yaml\")),\n memoryStore.listIncidentFacts({ namespace }),\n memoryStore.listFacts(),\n freshPromise,\n mapPromise,\n recallHandoffs(repositoryRoot, { namespace }),\n ]);\n\n const explain: string[] = [fresh.explain];\n const plan = summarizePlan(activePlan);\n explain.push(plan ? `plan: active plan ${plan.id} (${plan.status})` : \"plan: no active plan\");\n explain.push(`policy: plan policy is \"${policy}\"`);\n\n const policyRules = summarizePolicyRules(policyFile.rules);\n if (policyRules.length > 0) explain.push(`policyRules: ${policyRules.length} rule(s) by weight`);\n\n const incidentSummaries = sortIncidents(incidents)\n .slice(0, LIMITS.bootstrapIncidents)\n .map(summarizeIncident);\n if (incidentSummaries.length > 0) {\n explain.push(`incidents: ${incidentSummaries.length} unresolved incident hotspot(s)`);\n }\n\n const architecture = summarizeArchitecture(map);\n explain.push(\n `architecture: ${architecture.moduleCount} module(s), ${architecture.edgeCount} edge(s)` +\n (map.source ? ` (${map.source})` : \"\"),\n );\n\n const rules = selectRules(facts, namespace);\n if (rules.length > 0) {\n const procedures = rules.filter((rule) => rule.subject === \"procedure\").length;\n explain.push(`rules: ${rules.length - procedures} rule(s), ${procedures} procedure(s)`);\n }\n const bootstrapFacts = await rankRelevantFacts(\n facts.filter((fact) => !STANDING_PREDICATES.has(fact.predicate)),\n namespace,\n \"\",\n [],\n );\n explainHandoffs(explain, handoffs);\n const assembled = {\n project: { namespace, root: repositoryRoot },\n plan,\n policy,\n policyRules,\n incidents: incidentSummaries,\n facts: bootstrapFacts,\n rules,\n handoffs,\n architecture,\n explain,\n };\n const tokens = buildTokenStats(assembled, input.tokenBudget);\n return enforceContextBudget({ ...assembled, tokens });\n}\n\n/**\n * Assemble the most relevant context before an edit: resolve the target files\n * (explicit paths, a plan, or git), then attach the relevant plan, policy\n * rules, incident memory for those files, an evidence-backed risk assessment,\n * and the import neighbours of each target.\n */\nexport async function buildBeforeEditContext(input: BeforeEditInput): Promise<BeforeEditContext> {\n const repositoryRoot = resolve(input.repositoryRoot ?? process.cwd());\n const namespace = input.namespace;\n\n const hasExplicitTargets = (input.paths?.length ?? 0) > 0 || input.planId !== undefined;\n // Validate the index against current source before any indexed symbol,\n // summary or import is trusted (issue #34).\n const fresh = await loadFreshIndex(repositoryRoot);\n const manifest = fresh.manifest;\n const resolvedPaths = await resolveRiskPaths({\n repositoryRoot,\n ...(input.paths !== undefined ? { paths: input.paths } : {}),\n ...(input.planId !== undefined ? { planId: input.planId } : {}),\n ...(hasExplicitTargets\n ? { useGit: false }\n : input.useGit !== undefined\n ? { useGit: input.useGit }\n : {}),\n });\n const mapPromise = loadProjectArchitectureMap(repositoryRoot, manifest);\n const discovery =\n !hasExplicitTargets && input.task\n ? await discoverTaskPaths(repositoryRoot, input.task, manifest, mapPromise)\n : { paths: [], hits: [], explain: [] };\n const taskPaths = discovery.paths;\n const targetPaths = hasExplicitTargets\n ? resolvedPaths\n : taskPaths.length > 0\n ? taskPaths\n : resolvedPaths;\n const discoveredFromTask = taskPaths.length > 0;\n const pathSource = classifyPathSource(input, targetPaths.length, discoveredFromTask);\n\n const planStore = new PlanFileStore(repositoryRoot);\n const memoryStore = new MemoryFileStore(repositoryRoot);\n\n const [referencedPlan, policy, policyFile, incidents, facts, risks, map, diffs, handoffs] =\n await Promise.all([\n resolveRelevantPlan(planStore, namespace, input.planId),\n loadPlanPolicy(repositoryRoot),\n readPolicyFile(join(repositoryRoot, \".codebuddy\", \"policies.yaml\")),\n memoryStore.findIncidentFactsForPaths({ namespace, paths: targetPaths }),\n memoryStore.listFacts(),\n assessRisk({\n repositoryRoot,\n namespace,\n ...(targetPaths.length > 0 ? { paths: targetPaths } : {}),\n ...(input.planId !== undefined ? { planId: input.planId } : {}),\n useGit: !hasExplicitTargets && input.useGit !== false,\n }),\n mapPromise,\n input.useGit === false\n ? Promise.resolve([] as DiffHunk[])\n : readGitDiffs(repositoryRoot, targetPaths),\n recallHandoffs(repositoryRoot, {\n namespace,\n paths: targetPaths,\n ...(input.task !== undefined ? { task: input.task } : {}),\n }),\n ]);\n\n const explain: string[] = [];\n explain.push(`paths: ${targetPaths.length} target(s) resolved from ${pathSource}`);\n explain.push(fresh.explain);\n if (discoveredFromTask && resolvedPaths.length > 0) {\n explain.push(\n `git: ${resolvedPaths.length} observed changed path(s) assessed separately from task targets`,\n );\n }\n explain.push(...discovery.explain);\n\n const plan = summarizePlan(referencedPlan);\n if (plan) explain.push(`plan: ${plan.id} (${plan.status})`);\n\n const policyRules = summarizeMatchingPolicyRules(policyFile.rules, targetPaths);\n if (policyRules.length > 0) {\n explain.push(`policyRules: ${policyRules.length} rule(s) match target paths`);\n }\n\n const incidentSummaries = sortIncidents(incidents)\n .slice(0, LIMITS.beforeEditIncidents)\n .map(summarizeIncident);\n if (incidentSummaries.length > 0) {\n explain.push(`incidents: ${incidentSummaries.length} incident(s) touch target paths`);\n }\n\n if (risks.items.length > 0) explain.push(`risks: ${risks.items.length} scored path(s)`);\n\n const neighbours = computeNeighbours(map, targetPaths);\n if (neighbours.length > 0)\n explain.push(\n `neighbours: import graph for ${neighbours.length} file(s)` +\n (map.source ? ` (${map.source})` : \"\"),\n );\n\n const symbols = await computeTargetSymbols(\n repositoryRoot,\n targetPaths,\n input.task ?? \"\",\n discovery.hits,\n \"symbols\" in discovery ? (discovery.symbols ?? {}) : {},\n input.evidence ?? \"overview\",\n );\n if (symbols.length > 0) {\n const spans = symbols.reduce((total, file) => total + (file.spans?.length ?? 0), 0);\n explain.push(\n `symbols: signatures for ${symbols.length} target file(s) (in place of full source)` +\n (spans > 0 ? `; ${spans} task-ranked span(s) read from current source` : \"\"),\n );\n }\n\n const relevantFacts = await rankRelevantFacts(\n facts.filter((fact) => !STANDING_PREDICATES.has(fact.predicate)),\n namespace,\n input.task ?? \"\",\n targetPaths,\n input.semanticRanker,\n input.reranker,\n );\n if (relevantFacts.length > 0) {\n const semantic = relevantFacts.filter((fact) => fact.reason.includes(\"semantic\")).length;\n explain.push(\n `facts: ${relevantFacts.length} durable fact(s) by hybrid rank fusion` +\n (input.semanticRanker\n ? ` (${semantic} with dense evidence${relevantFacts[0]?.reason.endsWith(\"reranked\") ? \", reranked\" : \"\"})`\n : \" (lexical only; no semantic fact ranker configured)\"),\n );\n }\n explainHandoffs(explain, handoffs);\n\n const indexed = new Set(Object.keys(manifest.entries));\n const tests = targetPaths.flatMap((path) => {\n const test = findCoveringTest(path, indexed);\n return test ? [{ path, test }] : [];\n });\n const testCommand = targetPaths.length > 0 ? await detectTestCommand(repositoryRoot) : null;\n if (tests.length > 0 || testCommand) {\n explain.push(\n `tests: ${tests.length} covering test(s) by naming convention; command ${testCommand ?? \"unknown\"}`,\n );\n }\n\n const assembled = {\n project: { namespace, root: repositoryRoot },\n task: input.task ?? null,\n targetPaths,\n pathSource,\n plan,\n policy,\n policyRules,\n incidents: incidentSummaries,\n facts: relevantFacts,\n handoffs,\n risks,\n neighbours,\n symbols,\n tests,\n testCommand,\n diffs,\n explain,\n };\n const tokens = buildTokenStats(assembled, input.tokenBudget);\n return enforceContextBudget({ ...assembled, tokens });\n}\n\n// ── helpers ─────────────────────────────────────────────────────────\n\n/** Prior worklog handoffs. A broken worklog must never break context assembly. */\nasync function recallHandoffs(\n repositoryRoot: string,\n input: Parameters<WorklogStore[\"recall\"]>[0],\n): Promise<HandoffSummary[]> {\n try {\n return await new WorklogStore(repositoryRoot).recall(input);\n } catch {\n return [];\n }\n}\n\nfunction explainHandoffs(explain: string[], handoffs: HandoffSummary[]): void {\n if (handoffs.length === 0) return;\n const stale = handoffs.filter((h) => h.changedSince.length > 0 || h.missing.length > 0).length;\n explain.push(\n `handoffs: ${handoffs.length} prior worklog entr${handoffs.length === 1 ? \"y\" : \"ies\"}` +\n (stale > 0 ? ` (${stale} with files changed or missing since — verify before relying)` : \"\"),\n );\n}\n\nfunction summarizePlan(plan: PlanSpec | null): PlanSummary {\n if (!plan) return null;\n return {\n id: plan.id,\n title: plan.title,\n status: plan.status,\n brief: plan.brief,\n filesToTouch: plan.filesToTouch.map((file) => file.path),\n risks: plan.risks,\n };\n}\n\n/**\n * Prefer an explicitly referenced plan; fall back to the namespace's active\n * plan so before-edit context stays useful even when the caller passes only\n * paths.\n */\nasync function resolveRelevantPlan(\n store: PlanFileStore,\n namespace: string,\n planId?: string,\n): Promise<PlanSpec | null> {\n if (planId) {\n try {\n return await store.readPlan(planId);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return null;\n throw error;\n }\n }\n return new PlanLifecycle(store).current(namespace);\n}\n\nfunction sortIncidents(incidents: IncidentFactFile[]): IncidentFactFile[] {\n const severity = { critical: 4, high: 3, medium: 2, low: 1 };\n return [...incidents].sort(\n (a, b) =>\n Number(a.resolvedBy !== null) - Number(b.resolvedBy !== null) ||\n severity[b.severity] - severity[a.severity],\n );\n}\n\nfunction summarizeIncident(fact: IncidentFactFile): IncidentSummary {\n return {\n id: fact.id,\n severity: fact.severity,\n subject: fact.subject,\n summary: truncate(fact.content || fact.object || fact.subject, LIMITS.incidentSummaryChars),\n paths: fact.paths,\n resolved: fact.resolvedBy !== null,\n createdAt: fact.createdAt,\n };\n}\n\nfunction summarizePolicyRules(rules: PolicyRule[]): PolicyRuleSummary[] {\n return [...rules]\n .sort((left, right) => right.weight - left.weight)\n .slice(0, LIMITS.policyRules)\n .map((rule) => ({\n id: rule.id,\n pattern: rule.pattern,\n message: rule.message ?? rule.reason ?? `Policy rule ${rule.id}.`,\n weight: rule.weight,\n }));\n}\n\nfunction summarizeMatchingPolicyRules(rules: PolicyRule[], paths: string[]): PolicyRuleSummary[] {\n const matching = rules.filter((rule) =>\n paths.some((path) => matchesPolicyGlob(path, rule.pattern)),\n );\n return summarizePolicyRules(matching);\n}\n\nfunction summarizeArchitecture(map: ArchitectureMap): ArchitectureSummary {\n const inbound = new Map<string, number>();\n const outbound = new Map<string, number>();\n for (const edge of map.edges) {\n outbound.set(edge.from, (outbound.get(edge.from) ?? 0) + 1);\n inbound.set(edge.to, (inbound.get(edge.to) ?? 0) + 1);\n }\n\n const hotspots = map.modules\n .map((module) => ({\n path: module.path,\n inbound: inbound.get(module.path) ?? 0,\n outbound: outbound.get(module.path) ?? 0,\n }))\n .filter((entry) => entry.inbound + entry.outbound > 0)\n .sort((left, right) => {\n const degree = right.inbound + right.outbound - (left.inbound + left.outbound);\n if (degree !== 0) return degree;\n return left.path.localeCompare(right.path);\n })\n .slice(0, LIMITS.hotspots);\n\n return { moduleCount: map.modules.length, edgeCount: map.edges.length, hotspots };\n}\n\nfunction computeNeighbours(map: ArchitectureMap, paths: string[]): ModuleNeighbours[] {\n const result: ModuleNeighbours[] = [];\n for (const path of paths.slice(0, LIMITS.neighbourPaths)) {\n // Dedupe BEFORE slicing: duplicate edges from a many-to-many import would\n // otherwise crowd unique neighbours out of the bounded payload.\n const dependsOn = [\n ...new Set(map.edges.filter((edge) => edge.from === path).map((edge) => edge.to)),\n ].slice(0, LIMITS.neighbourEdges);\n const dependedOnBy = [\n ...new Set(map.edges.filter((edge) => edge.to === path).map((edge) => edge.from)),\n ].slice(0, LIMITS.neighbourEdges);\n if (dependsOn.length === 0 && dependedOnBy.length === 0) continue;\n const usesSymbols: Record<string, string[]> = {};\n for (const dependency of dependsOn) {\n const symbols = map.edges.find(\n (edge) => edge.from === path && edge.to === dependency,\n )?.symbols;\n if (symbols?.length) usesSymbols[dependency] = symbols;\n }\n result.push({\n path,\n dependsOn,\n dependedOnBy,\n ...(Object.keys(usesSymbols).length > 0 ? { usesSymbols } : {}),\n });\n }\n return result;\n}\n\n/**\n * Read the target files' public API as compact signatures (Roadmap N.3), so the\n * agent can see what each file offers without the tool sending its full source.\n * The whole bounded symbol table is ranked by the task *before* it is limited,\n * so a relevant thirteenth declaration still wins (issue #35); declarations\n * overlapping a semantic hit are preferred. The best match comes back as a span\n * read from current source, with a short excerpt drawn from one global budget.\n * Bounded and best-effort: unreadable files are skipped.\n */\nasync function computeTargetSymbols(\n repositoryRoot: string,\n targetPaths: string[],\n task: string,\n hits: RetrievalHit[],\n /** Symbols the BYOK rerank named per file; they outrank term matches. */\n picked: Record<string, string[]> = {},\n evidence: \"overview\" | \"source\" = \"overview\",\n): Promise<FileSymbols[]> {\n const terms = taskTerms(task);\n const tokens = identifierTokens(task);\n const result: FileSymbols[] = [];\n let excerptBudget: number = evidence === \"source\" ? 5400 : LIMITS.excerptChars;\n let spanned = 0;\n for (const path of targetPaths.slice(0, LIMITS.symbolFiles)) {\n const source = await readBoundedSource(repositoryRoot, path);\n if (source === null) continue;\n const lines = source.split(/\\r?\\n/);\n // zg's index may be stale: only trust hit ranges that still fit the file.\n const fileHits = hits.filter((hit) => hit.path === path && hit.endLine <= lines.length);\n const table = supportsSymbols(path) ? extractSymbolTable(source) : [];\n // Each semantic hit credits only the narrowest declaration containing it,\n // so a method beats its enclosing class.\n const credited = new Map<SymbolSpan, RetrievalHit>();\n for (const hit of fileHits) {\n const owner = table\n .filter((symbol) => hit.startLine <= symbol.endLine && hit.endLine >= symbol.startLine)\n .sort(\n (left, right) => left.endLine - left.startLine - (right.endLine - right.startLine),\n )[0];\n if (owner && !credited.has(owner)) credited.set(owner, hit);\n }\n const ranked = table\n .map((symbol) => {\n const hit = credited.get(symbol);\n // A class body repeats its methods' words; let the narrower method win.\n const body =\n symbol.kind === \"class\"\n ? \"\"\n : lines.slice(symbol.startLine - 1, symbol.endLine).join(\" \");\n const score =\n (picked[path]?.includes(symbol.name) ? 1_000 : 0) +\n 100 * namedSegments(symbol.name, tokens) +\n (hit ? 10 : 0) +\n 3 * countTerms(lines[symbol.startLine - 1] ?? \"\", terms) +\n countTerms(body, terms);\n return { symbol, hit, score };\n })\n .sort(\n (left, right) => right.score - left.score || left.symbol.startLine - right.symbol.startLine,\n );\n // Methods only earn a signature line when the task points at them.\n const signatures = ranked\n .filter(({ symbol, score }) => symbol.kind !== \"method\" || score > 0)\n .slice(0, LIMITS.symbolsPerFile)\n .map(({ symbol }) => symbol.signature);\n // One grounded span per file: the best task match, else the top semantic\n // hit (unsupported languages, or no declaration matched). Only the first\n // few files get one, so the extra tokens stay bounded.\n const best = ranked[0]?.score ? ranked[0] : undefined;\n const hit = best ? best.hit : fileHits[0];\n const range = best?.symbol ?? hit;\n const spans: ContextSpan[] = [];\n if (range && spanned < LIMITS.spanFiles) {\n const span: ContextSpan = {\n ...(best ? { name: best.symbol.name } : {}),\n startLine: range.startLine,\n endLine: range.endLine,\n ...(hit\n ? { source: hit.source, rank: hit.rank, freshness: \"current-source\" }\n : { source: \"lexical\", freshness: \"current-source\" }),\n };\n if (excerptBudget > 0) {\n const headShown = best !== undefined && headInSignature(lines, best.symbol);\n span.excerpt = sourceExcerpt(\n lines,\n span,\n terms,\n hit?.startLine,\n hit?.endLine,\n excerptBudget,\n headShown,\n evidence,\n );\n excerptBudget -= span.excerpt.text.length;\n }\n spans.push(span);\n spanned++;\n }\n if (signatures.length > 0 || spans.length > 0) {\n result.push({ path, signatures, ...(spans.length > 0 ? { spans } : {}) });\n }\n }\n return result;\n}\n\n/**\n * A few lines of current source around the best task-term line (or the semantic\n * hit), so behavior and comments a signature can't show are still grounded.\n */\nfunction sourceExcerpt(\n lines: string[],\n span: ContextSpan,\n terms: string[],\n anchorLine: number | undefined,\n anchorEndLine: number | undefined,\n budget: number,\n headShown = false,\n evidence: \"overview\" | \"source\" = \"overview\",\n): NonNullable<ContextSpan[\"excerpt\"]> {\n let anchor = Math.max(span.startLine, anchorLine ?? span.startLine);\n let best = 0;\n if (anchorLine === undefined) {\n for (let line = span.startLine; line <= span.endLine; line++) {\n const score = countTerms(lines[line - 1] ?? \"\", terms);\n if (score > best) {\n best = score;\n anchor = line;\n }\n }\n }\n const detailed = evidence === \"source\";\n const windowStart =\n detailed && span.endLine - span.startLine < 40\n ? span.startLine\n : Math.max(span.startLine, anchor - 1);\n const endLine = Math.min(\n span.endLine,\n windowStart + (detailed ? 40 : LIMITS.excerptLines) - 1,\n detailed || anchorEndLine === undefined ? span.endLine : anchorEndLine + 1,\n );\n // The declaration line is already a listed signature; don't send it twice.\n const startLine =\n headShown && windowStart === span.startLine && endLine > windowStart\n ? windowStart + 1\n : windowStart;\n const raw = lines.slice(startLine - 1, endLine).join(\"\\n\");\n const text = raw.slice(0, Math.min(budget, detailed ? 1800 : LIMITS.excerptCharsPerSpan));\n return {\n startLine,\n endLine: startLine + text.split(\"\\n\").length - 1,\n text,\n truncated: windowStart > span.startLine || endLine < span.endLine || text.length < raw.length,\n };\n}\n\n/** True when the declaration line adds nothing beyond its (untruncated) signature. */\nfunction headInSignature(lines: string[], symbol: SymbolSpan): boolean {\n const head =\n symbol.kind === \"method\"\n ? symbol.signature.slice(symbol.signature.indexOf(\": \") + 2)\n : symbol.signature;\n const line = (lines[symbol.startLine - 1] ?? \"\").trim();\n return (\n !head.endsWith(\"…\") && line.startsWith(head) && /^[\\s{=>(]*$/.test(line.slice(head.length))\n );\n}\n\n/**\n * Read the current staged and unstaged hunks for target paths. The result is\n * bounded per file so a large change cannot crowd out plan and risk context.\n */\nasync function readGitDiffs(repositoryRoot: string, paths: string[]): Promise<DiffHunk[]> {\n if (paths.length === 0) return [];\n const sections: string[] = [];\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"diff\", \"HEAD\", \"--no-ext-diff\", \"--unified=3\", \"--\", ...paths],\n { cwd: repositoryRoot, maxBuffer: 2_000_000 },\n );\n sections.push(stdout);\n } catch {\n // Repositories without a first commit cannot use `git diff HEAD`. Their\n // staged and unstaged tracked changes are still useful independently.\n for (const args of [\n [\"diff\", \"--cached\", \"--no-ext-diff\", \"--unified=3\", \"--\", ...paths],\n [\"diff\", \"--no-ext-diff\", \"--unified=3\", \"--\", ...paths],\n ]) {\n try {\n const { stdout } = await execFileAsync(\"git\", args, {\n cwd: repositoryRoot,\n maxBuffer: 2_000_000,\n });\n sections.push(stdout);\n } catch {\n // Fall through to untracked-file handling.\n }\n }\n }\n\n const parsed = parseGitDiff(sections.join(\"\\n\"));\n const known = new Set(parsed.map((diff) => diff.path));\n const untracked = await listUntrackedPaths(repositoryRoot, paths);\n for (const path of untracked) {\n if (known.has(path)) continue;\n const patch = await buildUntrackedPatch(repositoryRoot, path);\n if (patch) parsed.push(patch);\n }\n return parsed.slice(0, MAX_DIFF_FILES);\n}\n\nfunction parseGitDiff(diff: string): DiffHunk[] {\n return diff\n .split(/(?=^diff --git )/m)\n .filter((section) => section.startsWith(\"diff --git \"))\n .flatMap((section) => {\n const header = section.match(/^diff --git a\\/(.+?) b\\/(.+?)\\n/m);\n if (!header?.[2]) return [];\n const rawPatch = section.trim();\n const patch = rawPatch.slice(0, MAX_DIFF_CHARS_PER_FILE).trim();\n return patch\n ? [\n {\n path: header[2],\n patch,\n ...(patch.length < rawPatch.length ? { truncated: true } : {}),\n },\n ]\n : [];\n });\n}\n\nasync function listUntrackedPaths(repositoryRoot: string, paths: string[]): Promise<string[]> {\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"ls-files\", \"--others\", \"--exclude-standard\", \"--\", ...paths],\n { cwd: repositoryRoot, maxBuffer: 1_000_000 },\n );\n return stdout\n .split(/\\r?\\n/)\n .map((path) => path.trim())\n .filter(Boolean);\n } catch {\n return [];\n }\n}\n\nasync function buildUntrackedPatch(repositoryRoot: string, path: string): Promise<DiffHunk | null> {\n try {\n const content = await readFile(join(repositoryRoot, path), \"utf8\");\n if (content.includes(\"\\0\")) return null;\n const lines = content.split(/\\r?\\n/);\n const body = lines.map((line) => `+${line}`).join(\"\\n\");\n const rawPatch = [\n `diff --git a/${path} b/${path}`,\n \"new file mode 100644\",\n \"--- /dev/null\",\n `+++ b/${path}`,\n `@@ -0,0 +1,${lines.length} @@`,\n body,\n ].join(\"\\n\");\n const patch = rawPatch.slice(0, MAX_DIFF_CHARS_PER_FILE).trim();\n return {\n path,\n patch,\n ...(patch.length < rawPatch.length ? { truncated: true } : {}),\n };\n } catch {\n return null;\n }\n}\n\n/** Facts delivered as standing guidance, not ranked against the task. */\nconst STANDING_PREDICATES = new Set([\"rule\", \"procedure\"]);\nconst STANDING_LIMITS = { rule: 5, procedure: 3, chars: 200 } as const;\n\n/** Live user rules (newest 5) then procedures (newest 3), regardless of task overlap. */\nfunction selectRules(facts: FactFile[], namespace: string): RelevantFactSummary[] {\n const newest = (predicate: \"rule\" | \"procedure\") =>\n facts\n .filter((fact) => fact.predicate === predicate && isEligibleMemory(fact, { namespace }))\n .sort((left, right) => right.createdAt.localeCompare(left.createdAt))\n .slice(0, STANDING_LIMITS[predicate]);\n return [...newest(\"rule\"), ...newest(\"procedure\")].map((fact) => ({\n id: fact.id,\n subject: fact.predicate,\n summary: truncate(fact.object, STANDING_LIMITS.chars),\n paths: fact.paths,\n confidence: fact.confidence,\n relevance: 0,\n reason:\n fact.predicate === \"rule\" ? \"standing user rule\" : \"verification that passed repeatedly\",\n createdAt: fact.createdAt,\n createdByAgent: fact.createdByAgent,\n }));\n}\n\n/** Reciprocal rank fusion constant (Cormack et al. 2009): damps the head so no one list dominates. */\nconst RRF_K = 60;\n/** At most this many fused facts go to the optional cross-encoder. */\nconst RERANK_POOL = 20;\n\n/**\n * Hybrid fact retrieval:\n * 1. gate: lexical (task words + target paths) or dense evidence (pgvector\n * cosine at or above the model's calibrated floor) admits a fact;\n * 2. rank: reciprocal rank fusion of the lexical and dense rankings,\n * score(f) = Σ_lists 1 / (RRF_K + rank_list(f));\n * 3. rerank: optional cross-encoder that orders the fused pool. Off by\n * default: on `npm run eval:semantic` none of eight local rerankers\n * beat the dense order. Its scores never admit a fact.\n * Every model step is optional and fail-soft.\n */\nasync function rankRelevantFacts(\n facts: FactFile[],\n namespace: string,\n task: string,\n targetPaths: string[],\n semanticRanker?: SemanticRelevanceRanker,\n reranker?: ContextReranker,\n): Promise<RelevantFactSummary[]> {\n // Eligibility runs before ranking and duplicate suppression, so only\n // same-namespace, live incidents can suppress a fact with identical text.\n const eligible = facts.filter((fact) => isEligibleMemory(fact, { namespace }));\n const incidentText = new Set(\n eligible\n .filter((fact) => fact.category === \"incident\")\n .map((fact) => normalizeText(fact.content || fact.object)),\n );\n const candidates = eligible\n .filter((fact) => fact.category !== \"incident\")\n .filter((fact) => !incidentText.has(normalizeText(fact.content || fact.object)))\n .map((fact) => {\n const text = `${fact.subject} ${fact.predicate} ${fact.object} ${fact.content}`;\n const taskScore = relevanceScore(text, task);\n // A path match is strong supporting evidence, but must not overwhelm a\n // clearly different task (for example database work near an auth file).\n const pathScore = fact.paths.some((path) => targetPaths.includes(path)) ? 5 : 0;\n return { fact, text, taskScore, pathScore, lexical: taskScore + pathScore };\n });\n const summarize = (fact: FactFile, relevance: number, reason: string): RelevantFactSummary => ({\n id: fact.id,\n subject: fact.subject,\n summary: truncate(fact.content || fact.object, LIMITS.incidentSummaryChars),\n paths: fact.paths,\n confidence: fact.confidence,\n relevance,\n reason,\n createdAt: fact.createdAt,\n createdByAgent: fact.createdByAgent,\n });\n\n if (!task.trim()) {\n return candidates\n .sort(\n (left, right) =>\n right.fact.confidence - left.fact.confidence ||\n right.fact.createdAt.localeCompare(left.fact.createdAt),\n )\n .slice(0, LIMITS.relevantFacts)\n .map(({ fact }) => summarize(fact, Math.round(fact.confidence * 5), \"recent project fact\"));\n }\n\n let dense: Record<string, number> = {};\n if (semanticRanker) {\n try {\n dense = await semanticRanker(\n task,\n candidates.map(({ fact, text }) => ({ id: fact.id, text })),\n );\n } catch {\n dense = {};\n }\n }\n const cosine = (id: string) => {\n const value = dense[id];\n return typeof value === \"number\" && Number.isFinite(value) ? value : undefined;\n };\n const gated = candidates.filter(\n (candidate) => candidate.lexical > 0 || cosine(candidate.fact.id) !== undefined,\n );\n const rankOf = (ordered: Array<(typeof gated)[number]>) =>\n new Map(ordered.map((candidate, index) => [candidate.fact.id, index + 1]));\n const lexicalRank = rankOf(\n gated.filter(({ lexical }) => lexical > 0).sort((a, b) => b.lexical - a.lexical),\n );\n const denseRank = rankOf(\n gated\n .filter(({ fact }) => cosine(fact.id) !== undefined)\n .sort((a, b) => (cosine(b.fact.id) ?? 0) - (cosine(a.fact.id) ?? 0)),\n );\n const rrf = (rank: number | undefined) => (rank === undefined ? 0 : 1 / (RRF_K + rank));\n const fused = gated\n .map((candidate) => ({\n ...candidate,\n score: rrf(lexicalRank.get(candidate.fact.id)) + rrf(denseRank.get(candidate.fact.id)),\n }))\n .sort(\n (left, right) =>\n right.score - left.score ||\n right.fact.confidence - left.fact.confidence ||\n right.fact.createdAt.localeCompare(left.fact.createdAt),\n );\n\n let reranked = false;\n if (reranker && fused.length > 1) {\n const pool = fused.slice(0, RERANK_POOL);\n try {\n const scores = await reranker(\n task,\n pool.map(({ text }) => text),\n );\n if (scores.length === pool.length && scores.every((score) => !Number.isNaN(score))) {\n const scoreOf = new Map(pool.map((candidate, index) => [candidate, scores[index] ?? 0]));\n // Stable: equal scores keep their fused order; the rest of the list follows.\n pool.sort((left, right) => (scoreOf.get(right) ?? 0) - (scoreOf.get(left) ?? 0));\n fused.splice(0, pool.length, ...pool);\n reranked = true;\n }\n } catch {\n // Keep the fused order.\n }\n }\n\n // Diversity: a fact that restates one already selected adds no information\n // and would spend one of the few slots (maximal marginal relevance, lexically).\n const selected: typeof fused = [];\n for (const candidate of fused) {\n if (selected.length >= LIMITS.relevantFacts) break;\n const text = candidate.fact.content || candidate.fact.object;\n if (selected.some((kept) => termOverlap(text, kept.fact.content || kept.fact.object) >= 0.8)) {\n continue;\n }\n selected.push(candidate);\n }\n\n return selected.map(({ fact, taskScore, pathScore, score }) => {\n const evidence = [\n pathScore > 0 ? \"matches a target path\" : \"\",\n taskScore > 0 ? `shares ${taskScore / 3} task term(s)` : \"\",\n cosine(fact.id) !== undefined ? `semantic ${cosine(fact.id)?.toFixed(2)}` : \"\",\n ].filter(Boolean);\n return summarize(\n fact,\n // Fused score scaled to a readable integer (max = 2/61 · 1000 ≈ 33).\n Math.round(score * 1000),\n evidence.join(\"; \") + (reranked ? \"; reranked\" : \"\"),\n );\n });\n}\n\n/** 3 points per distinct task term (stopwords dropped) found as a whole word in `value`. */\nfunction relevanceScore(value: string, task: string): number {\n const terms = lexicalTerms(task).filter((term) => term.length > 2);\n if (terms.length === 0) return 0;\n const haystack = new Set(value.toLowerCase().match(/[\\p{L}\\p{N}_]+/gu) ?? []);\n return terms.filter((term) => haystack.has(term)).length * 3;\n}\n\nfunction normalizeText(value: string): string {\n return value\n .toLowerCase()\n .replace(/[^a-z0-9_./-]+/g, \" \")\n .trim();\n}\n\nfunction classifyPathSource(\n input: BeforeEditInput,\n resolvedCount: number,\n discoveredFromTask: boolean,\n): PathSource {\n if (resolvedCount === 0) return \"none\";\n if (discoveredFromTask) return \"task\";\n if (input.paths && input.paths.length > 0) return \"paths\";\n if (input.planId) return \"plan\";\n return \"git\";\n}\n\n/** Estimate the payload's token footprint against its budget. */\nfunction buildTokenStats(payload: unknown, tokenBudget: number | undefined): TokenStats {\n return {\n budget: tokenBudget ?? DEFAULT_TOKEN_BUDGET,\n returnedEstimate: estimateTokens(payload ?? {}),\n status: \"within_budget\",\n countedSurface: \"compact_json\",\n essentialOmitted: 0,\n };\n}\n\nfunction truncate(value: string, max: number): string {\n const trimmed = value.trim();\n return trimmed.length <= max ? trimmed : `${trimmed.slice(0, max - 1)}…`;\n}\n\nexport { rankTaskPaths, scoreTaskPaths } from \"./discovery.js\";\n","import { createHash } from \"node:crypto\";\nimport { mkdir, readdir, readFile, stat } from \"node:fs/promises\";\nimport { dirname, join, relative, resolve, sep } from \"node:path\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { z } from \"zod\";\nimport { generateEntityId } from \"../core/ids.js\";\nimport {\n assertNoSymlinkBetween,\n composeMarkdown,\n parseFrontMatter,\n writeAtomic,\n} from \"../core/markdown-store-fs.js\";\nimport { scanSensitive } from \"../memory-extract/sensitive.js\";\n\n/**\n * The worklog is a chronological record of completed turns — what was done,\n * which files, what memory it produced, how it was verified — so a fresh chat\n * can pick up prior work without the transcript. It is a timeline, not project\n * truth: durable facts stay in `.codebuddy/memory/` and the working tree stays\n * authoritative, so every recalled entry carries a freshness check against the\n * current files. Entries are bounded Markdown under `.codebuddy/worklog/`; raw\n * transcripts are never stored and sensitive summaries are redacted.\n */\n\nconst LIMITS = {\n summaryChars: 600,\n files: 50,\n verification: 10,\n verificationChars: 200,\n} as const;\n\nconst REDACTED = \"[REDACTED SENSITIVE CONTENT]\";\n\nconst entrySchema = z.object({\n schemaVersion: z.literal(1),\n id: z.string().regex(/^wlg_[a-z0-9]+$/),\n namespace: z.string().min(1),\n createdAt: z.string(),\n sourceSessionId: z.string().nullable().default(null),\n sourcePlanId: z.string().nullable().default(null),\n commitSha: z.string().nullable().default(null),\n agentId: z.string().nullable().default(null),\n files: z.array(z.string()).default([]),\n verification: z.array(z.string()).default([]),\n savedMemory: z.array(z.string()).default([]),\n queuedForReview: z.array(z.string()).default([]),\n fingerprint: z.string().regex(/^[a-f0-9]{64}$/),\n});\n\nexport type WorklogEntry = z.infer<typeof entrySchema> & { summary: string; path: string };\n\nexport type WorklogRecordInput = {\n namespace: string;\n summary: string;\n files?: string[];\n verification?: string[];\n savedMemory?: string[];\n queuedForReview?: string[];\n sessionId?: string;\n planId?: string;\n commitSha?: string;\n agentId?: string;\n};\n\n/** A worklog entry as recalled into context, with freshness against the working tree. */\nexport type HandoffSummary = {\n id: string;\n createdAt: string;\n ageDays: number;\n summary: string;\n files: string[];\n verification: string[];\n savedMemory: string[];\n /** Recorded files modified after the entry was written. */\n changedSince: string[];\n /** Recorded files that no longer exist. */\n missing: string[];\n reason: string;\n};\n\nexport class WorklogStore {\n readonly repositoryRoot: string;\n readonly directory: string;\n\n constructor(repositoryRoot = process.cwd()) {\n this.repositoryRoot = resolve(repositoryRoot);\n this.directory = join(this.repositoryRoot, \".codebuddy\", \"worklog\");\n }\n\n /**\n * Record one entry for a completed turn. A retry of the same turn (same\n * namespace, session, summary and files) returns the existing id instead of\n * writing a duplicate.\n */\n async record(input: WorklogRecordInput, now = new Date()): Promise<string> {\n const files = [...new Set((input.files ?? []).map(normalizePath))]\n .filter(Boolean)\n .sort()\n .slice(0, LIMITS.files);\n const summary = boundSummary(input.summary, files);\n const verification = (input.verification ?? [])\n .map((line) => line.trim().slice(0, LIMITS.verificationChars))\n .filter((line) => line && !scanSensitive(line).sensitive)\n .slice(0, LIMITS.verification);\n const fingerprint = createHash(\"sha256\")\n .update(\n JSON.stringify({\n namespace: input.namespace.trim().toLowerCase(),\n session: input.sessionId ?? null,\n summary: summary.replace(/\\s+/g, \" \").toLowerCase(),\n files,\n }),\n )\n .digest(\"hex\");\n\n const existing = (await this.list()).find((entry) => entry.fingerprint === fingerprint);\n if (existing) return existing.id;\n\n const id = generateEntityId(\"wlg\", now.getTime());\n const path = this.entryPath(id);\n await assertNoSymlinkBetween(this.repositoryRoot, dirname(path));\n await mkdir(this.directory, { recursive: true, mode: 0o700 });\n const frontMatter = stringifyYaml({\n schemaVersion: 1,\n id,\n namespace: input.namespace,\n createdAt: now.toISOString(),\n sourceSessionId: input.sessionId ?? null,\n sourcePlanId: input.planId ?? null,\n commitSha: input.commitSha ?? null,\n agentId: input.agentId ?? null,\n files,\n verification,\n savedMemory: input.savedMemory ?? [],\n queuedForReview: input.queuedForReview ?? [],\n fingerprint,\n });\n await writeAtomic(path, composeMarkdown(frontMatter, summary));\n return id;\n }\n\n async read(id: string): Promise<WorklogEntry> {\n const path = this.entryPath(id);\n await assertNoSymlinkBetween(this.repositoryRoot, path);\n const parsed = parseFrontMatter(await readFile(path, \"utf8\"));\n return {\n ...entrySchema.parse(parseYaml(parsed.frontMatter)),\n summary: parsed.content.trim(),\n path,\n };\n }\n\n /** All readable entries, newest first. Corrupt or foreign files are skipped. */\n // ponytail: full directory scan per call; add an index file if worklogs reach thousands of entries.\n async list(namespace?: string): Promise<WorklogEntry[]> {\n let names: string[];\n try {\n await assertNoSymlinkBetween(this.repositoryRoot, this.directory);\n names = await readdir(this.directory);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return [];\n throw error;\n }\n const entries: WorklogEntry[] = [];\n for (const name of names) {\n if (!/^wlg_[a-z0-9]+\\.md$/.test(name)) continue;\n try {\n const entry = await this.read(name.replace(/\\.md$/, \"\"));\n if (namespace === undefined || entry.namespace === namespace) entries.push(entry);\n } catch {\n // Leave corrupt entries on disk for inspection; never fail recall on one.\n }\n }\n return entries.sort(\n (left, right) =>\n right.createdAt.localeCompare(left.createdAt) || right.id.localeCompare(left.id),\n );\n }\n\n /**\n * Prior handoffs for a new turn. With target paths or a task, only entries\n * that overlap them are returned (ranked by overlap, then recency); without\n * either, the most recent entries are returned.\n */\n async recall(input: {\n namespace: string;\n paths?: string[];\n task?: string;\n limit?: number;\n now?: Date;\n }): Promise<HandoffSummary[]> {\n const now = input.now ?? new Date();\n const limit = input.limit ?? 3;\n const entries = await this.list(input.namespace);\n const paths = new Set((input.paths ?? []).map(normalizePath));\n const taskWords = words(input.task ?? \"\");\n const targeted = paths.size > 0 || taskWords.size > 0;\n\n const ranked = entries\n .map((entry, recency) => {\n const fileHits = entry.files.filter((file) => paths.has(file));\n const summaryWords = words(entry.summary);\n const wordHits = [...taskWords].filter((word) => summaryWords.has(word));\n const score = fileHits.length * 3 + Math.min(wordHits.length, 5);\n const reason = !targeted\n ? \"recent work\"\n : [\n fileHits.length > 0 ? `touched ${fileHits.slice(0, 3).join(\", \")}` : \"\",\n wordHits.length > 0 ? `task terms: ${wordHits.slice(0, 5).join(\", \")}` : \"\",\n ]\n .filter(Boolean)\n .join(\"; \");\n return { entry, score, recency, reason };\n })\n .filter((item) => !targeted || item.score > 0)\n .sort((left, right) => right.score - left.score || left.recency - right.recency)\n .slice(0, limit);\n\n return Promise.all(\n ranked.map(async ({ entry, reason }) => {\n const freshness = await this.freshness(entry);\n return {\n id: entry.id,\n createdAt: entry.createdAt,\n ageDays: Math.max(\n 0,\n Math.floor((now.getTime() - Date.parse(entry.createdAt)) / 86_400_000),\n ),\n summary: entry.summary.slice(0, 240),\n files: entry.files.slice(0, 8),\n verification: entry.verification.slice(0, 3),\n savedMemory: entry.savedMemory,\n ...freshness,\n reason,\n };\n }),\n );\n }\n\n private async freshness(\n entry: WorklogEntry,\n ): Promise<{ changedSince: string[]; missing: string[] }> {\n const createdAt = Date.parse(entry.createdAt);\n const changedSince: string[] = [];\n const missing: string[] = [];\n for (const file of entry.files) {\n const absolute = resolve(this.repositoryRoot, file);\n const rel = relative(this.repositoryRoot, absolute);\n if (rel.startsWith(`..${sep}`) || rel === \"..\") continue;\n try {\n if ((await stat(absolute)).mtimeMs > createdAt) changedSince.push(file);\n } catch {\n missing.push(file);\n }\n }\n return { changedSince, missing };\n }\n\n private entryPath(id: string): string {\n if (!/^wlg_[a-z0-9]+$/.test(id)) throw new Error(`Invalid worklog id: ${id}`);\n return join(this.directory, `${id}.md`);\n }\n}\n\n/**\n * Keep the human summary, drop the hook's trailing \"Changed files:\" line (files\n * are recorded separately), cap the length, and redact anything sensitive.\n */\nfunction boundSummary(summary: string, files: string[]): string {\n const text = summary\n .replace(/\\n*Changed files: [^\\n]*\\.?\\s*$/, \"\")\n .trim()\n .slice(0, LIMITS.summaryChars);\n if (!text) return files.length > 0 ? `Changed ${files.slice(0, 5).join(\", \")}.` : \"(no summary)\";\n return redactSentences(text);\n}\n\n/**\n * Redact only the sentences (or lines) that scan sensitive, so one pasted key\n * does not erase the whole handoff. If the result still scans sensitive (a\n * credential split across a sentence boundary), redact the whole summary.\n */\nfunction redactSentences(text: string): string {\n if (!scanSensitive(text).sensitive) return text;\n const redacted = text\n .split(/(?<=[.!?])\\s+|\\n+/)\n .map((sentence) => (scanSensitive(sentence).sensitive ? REDACTED : sentence))\n .join(\" \");\n return scanSensitive(redacted).sensitive ? REDACTED : redacted;\n}\n\nfunction normalizePath(path: string): string {\n return path.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\").trim();\n}\n\nfunction words(text: string): Set<string> {\n return new Set(text.toLowerCase().match(/[a-z0-9_]{4,}/g) ?? []);\n}\n","import { readFile } from \"node:fs/promises\";\nimport { basename, isAbsolute, relative, resolve, sep } from \"node:path\";\nimport pTimeout from \"p-timeout\";\nimport { buildBeforeEditContext, buildBootstrapContext } from \"../context/engine.js\";\nimport { type ContextCapsule, SessionCapsuleLedger } from \"../context/session-ledger.js\";\nimport type { BeforeEditContext, BootstrapContext } from \"../context/types.js\";\nimport type { ReindexResult } from \"../core/codebuddy.js\";\nimport { loadRuntimeConfig, readConfigFile } from \"../core/config-file.js\";\nimport { captureAfterTurn } from \"../memory-extract/engine.js\";\nimport { extractUserRules } from \"../memory-extract/rules.js\";\nimport { redactSensitive } from \"../memory-extract/sensitive.js\";\nimport type { AfterTurnResult } from \"../memory-extract/types.js\";\nimport { estimateTokens } from \"../savings/tokens.js\";\nimport { recordTrace, type TraceEvent } from \"../tracing/log.js\";\nimport { openHookSemantics } from \"./semantic.js\";\nimport { HookStagingStore } from \"./staging.js\";\n\n/**\n * The runtime side of `codebuddy hooks`. Each function is the deterministic\n * action a Claude Code hook triggers, independent of whether the model chose to\n * call anything:\n * - context: recall — compact project context, injected at prompt submit.\n * - stage: record the files an edit tool just changed.\n * - capture: at turn end, capture durable memory from the real change set.\n *\n * All are best-effort: a hook must never break the user's turn, so callers wrap\n * these and always exit 0.\n */\n\n/** The subset of a Claude Code hook payload CodeBuddy reads. */\nexport type HookInput = {\n session_id?: string;\n transcript_path?: string;\n cwd?: string;\n hook_event_name?: string;\n prompt?: string;\n tool_name?: string;\n tool_input?: Record<string, unknown>;\n /** SessionStart only: startup | resume | clear | compact. */\n source?: string;\n /** Turn end, for hosts without a transcript file (OpenCode): the last assistant text. */\n last_assistant_message?: string;\n /** Turn end, for hosts without a transcript file: shell commands run this turn. */\n shell_commands?: Array<{ command: string; exit_code: number | null }>;\n /**\n * The host injects the block into this turn only and never keeps it in the\n * conversation (Hermes pre_llm_call), so nothing may be skipped as already sent.\n */\n ephemeral_context?: boolean;\n};\n\nconst CONTEXT_BLOCK_MAX_CHARS = 1800;\n/** Facts recalled per prompt: few and precise beats many and noisy. */\nconst PROMPT_FACTS = 3;\n\n/**\n * A block built later than this is dropped instead of emitted. Every bridge\n * kills the hook later (OpenCode and Hermes after 20s from spawn, Claude Code\n * after 60s), so a block is marked delivered only when it was written with\n * seconds to spare, never just before a host timeout throws the output away.\n */\nexport const CONTEXT_HOOK_BUDGET_MS = 15_000;\n\nasync function resolveNamespace(repositoryRoot: string): Promise<string> {\n if (process.env.CODEBUDDY_NAMESPACE) return process.env.CODEBUDDY_NAMESPACE;\n const file = await readConfigFile(repositoryRoot);\n return file.namespace ?? basename(repositoryRoot);\n}\n\n/**\n * UserPromptSubmit → a compact, injectable context block (recall).\n *\n * `emit` writes the block to the client. Capsules are recorded as delivered\n * only after it resolves, so a failed write leaves the session ledger untouched.\n */\nexport async function runContextHook(\n input: HookInput,\n emit?: (block: string) => Promise<void>,\n budgetMs = CONTEXT_HOOK_BUDGET_MS,\n): Promise<string> {\n const started = Date.now();\n const repositoryRoot = resolve(input.cwd ?? process.cwd());\n const namespace = await resolveNamespace(repositoryRoot);\n\n const bootstrap = await buildBootstrapContext({ repositoryRoot, namespace });\n let beforeEdit: BeforeEditContext | null = null;\n const semantics = input.prompt ? await openHookSemantics(repositoryRoot) : null;\n try {\n beforeEdit = await buildBeforeEditContext({\n repositoryRoot,\n namespace,\n useGit: true,\n ...(input.prompt ? { task: input.prompt } : {}),\n ...(semantics?.semanticRanker ? { semanticRanker: semantics.semanticRanker } : {}),\n ...(semantics?.reranker ? { reranker: semantics.reranker } : {}),\n });\n } catch {\n beforeEdit = null;\n } finally {\n await semantics?.close();\n }\n const ledger = new SessionCapsuleLedger(repositoryRoot);\n const sessionId = input.session_id ?? \"default\";\n // Earlier blocks are gone from the model's view. No host event says when\n // MCP results are compacted away either, so the whole session starts over.\n if (input.ephemeral_context) await ledger.reset(sessionId);\n const { text, emitted } = await renderContextBlock(\n bootstrap,\n beforeEdit,\n ledger,\n sessionId,\n input.session_id !== undefined,\n );\n // Too late: the host may already have given up on this hook. Nothing is\n // marked, so the next prompt delivers the block.\n const late = Date.now() - started >= budgetMs;\n await recordTrace(\n repositoryRoot,\n recallTrace(input, beforeEdit, emitted, late ? \"\" : text, started, late),\n );\n if (late) return \"\";\n if (text.trim()) await emit?.(text);\n await ledger.markSent(sessionId, emitted);\n return text;\n}\n\n/** What one prompt recalled, for `codebuddy dashboard` (prompt redacted and cut to 120 chars). */\nfunction recallTrace(\n input: HookInput,\n beforeEdit: BeforeEditContext | null,\n emitted: ContextCapsule[],\n text: string,\n started: number,\n late: boolean,\n): Omit<TraceEvent, \"ts\"> {\n const shown = new Set(\n emitted.filter((c) => c.key.startsWith(\"fact:\")).map((c) => c.key.slice(5)),\n );\n const facts = (beforeEdit?.facts ?? []).filter((fact) => shown.has(fact.id));\n const prompt = redactSensitive(input.prompt ?? \"\")\n .replace(/\\s+/g, \" \")\n .trim();\n return {\n kind: \"recall\",\n name: \"context\",\n ms: Date.now() - started,\n ok: !late,\n tokensIn: estimateTokens(input.prompt ?? \"\"),\n tokensOut: estimateTokens(text),\n ...(input.session_id ? { session: input.session_id } : {}),\n detail: {\n prompt: prompt.length > 120 ? `${prompt.slice(0, 119)}…` : prompt,\n facts: facts.map((fact) => fact.summary.slice(0, 100)),\n dense: facts.filter((fact) => fact.reason.includes(\"semantic\")).length,\n lexical: facts.filter((fact) => /task term|target path/.test(fact.reason)).length,\n files: (beforeEdit?.targetPaths ?? []).slice(0, 3),\n sections: emitted.length,\n ...(late ? { dropped: \"built after the hook budget\" } : {}),\n },\n };\n}\n\n/** PostToolUse(edit) → stage the changed paths for capture. */\nexport async function runStageHook(input: HookInput): Promise<string[]> {\n const repositoryRoot = resolve(input.cwd ?? process.cwd());\n const paths = extractEditedPaths(input.tool_input)\n .map((path) => toRepoRelative(repositoryRoot, path))\n .filter((path): path is string => path !== null);\n await new HookStagingStore(repositoryRoot).add(input.session_id ?? \"default\", paths);\n return paths;\n}\n\nexport type CaptureHookResult = {\n changedFiles: string[];\n result: AfterTurnResult | null;\n};\n\n/** BYOK memory extraction options (empty when the layer or its memory feature is off). */\nexport async function llmMemoryOptions(\n repositoryRoot: string,\n): Promise<Awaited<ReturnType<typeof import(\"../llm/memory.js\").llmCaptureOptions>>> {\n try {\n return await (await import(\"../llm/memory.js\")).llmCaptureOptions(repositoryRoot);\n } catch {\n return {};\n }\n}\n\n/** A turn with no edits still leaves a handoff when the assistant reported at least this much. */\nconst INVESTIGATION_MIN_CHARS = 200;\n/** A handoff must point at code: a file path with an extension, or a backticked identifier. */\nconst NAMES_CODE =\n /[\\w.-]+\\/[\\w./-]*\\.\\w{1,5}\\b|\\b[\\w-]+\\.(?:ts|tsx|js|jsx|mjs|py|go|rs|java|rb|php|cs|c|cpp|h|swift|kt)\\b|`[^`\\s]+`/;\n\n/**\n * Stop → capture durable memory from the staged change set + transcript. A\n * turn without edits is still captured when the user stated or withdrew a\n * rule, or when the assistant reported findings (an investigation handoff).\n */\nexport async function runCaptureHook(input: HookInput): Promise<CaptureHookResult> {\n const captureStarted = Date.now();\n const repositoryRoot = resolve(input.cwd ?? process.cwd());\n const staging = new HookStagingStore(repositoryRoot);\n const sessionId = input.session_id ?? \"default\";\n // null: another capture holds this session's lock and handles the turn.\n const claimed = await staging.claim(sessionId);\n if (claimed === null) return { changedFiles: [], result: null };\n const changedFiles = claimed;\n try {\n const prompts = input.transcript_path ? await turnUserPrompts(input.transcript_path) : [];\n const { rules, revocations } = extractUserRules(prompts);\n let investigation = false;\n if (changedFiles.length === 0) {\n const assistant = input.transcript_path\n ? await lastAssistantMessage(input.transcript_path)\n : (input.last_assistant_message?.trim() ?? \"\");\n investigation = assistant.length >= INVESTIGATION_MIN_CHARS && NAMES_CODE.test(assistant);\n if (!investigation && rules.length === 0 && revocations.length === 0) {\n await staging.acknowledge(sessionId);\n return { changedFiles, result: null };\n }\n }\n const namespace = await resolveNamespace(repositoryRoot);\n const summary = await deriveSummary(\n input.transcript_path,\n changedFiles,\n input.last_assistant_message,\n );\n const verification = input.transcript_path\n ? await turnVerification(input.transcript_path)\n : verificationLines(\n (input.shell_commands ?? []).map(({ command, exit_code }) => ({\n command,\n ok: typeof exit_code === \"number\" ? exit_code === 0 : undefined,\n })),\n );\n const result = await captureAfterTurn(\n {\n summary,\n changedFiles,\n namespace,\n sessionId,\n ...(verification.length > 0 ? { verification } : {}),\n ...(rules.length > 0 ? { userRules: rules } : {}),\n ...(revocations.length > 0 ? { revokedRules: revocations } : {}),\n ...(investigation ? { investigation } : {}),\n // Without edits, only the user's own rules and a handoff are kept: an\n // explanation is not evidence of a decision or an incident.\n ...(changedFiles.length === 0 ? { extract: false } : {}),\n },\n {\n repositoryRoot,\n ...(changedFiles.length > 0 ? await llmMemoryOptions(repositoryRoot) : {}),\n },\n );\n await staging.acknowledge(sessionId);\n await recordTrace(repositoryRoot, {\n kind: \"capture\",\n name: \"capture\",\n ms: Date.now() - captureStarted,\n ok: true,\n session: sessionId,\n detail: {\n changedFiles: changedFiles.length,\n saved: result.saved.length,\n queued: result.queuedForReview.length,\n ignored: result.ignored.length,\n },\n });\n return { changedFiles, result };\n } catch (error) {\n await staging.rollback(sessionId);\n throw error;\n }\n}\n\n/** Long enough for the first run to download the model (~90 MB) on a slow link. */\nconst SYNC_BUDGET_MS = 5 * 60_000;\n\nexport type SyncHookResult = { reindex: ReindexResult; drained: boolean } | null;\n\n/**\n * Background, after capture: Markdown (the source of truth) → PostgreSQL\n * (reindex) → local embeddings for every new or re-spaced row, so the next\n * prompt's dense recall already sees this turn's memory (and the first run\n * downloads the local model). null when no database is configured.\n */\nexport async function runSyncHook(repositoryRoot: string): Promise<SyncHookResult> {\n const config = await loadRuntimeConfig(repositoryRoot, { requireDatabase: false });\n if (!config.postgresUrl) return null;\n const { createRuntime } = await import(\"../core/operations.js\");\n const started = Date.now();\n const runtime = await createRuntime(config, { repositoryRoot });\n try {\n const reindex = await runtime.memory.reindexMemory();\n const drained = await pTimeout(runtime.memory.getWorker().drain(), {\n milliseconds: SYNC_BUDGET_MS,\n }).then(\n () => true,\n () => false,\n );\n await recordTrace(repositoryRoot, {\n kind: \"sync\",\n name: \"sync\",\n ms: Date.now() - started,\n ok: drained,\n detail: {\n imported: reindex.facts.imported,\n updated: reindex.facts.updated,\n reembedding: reindex.reembedding ?? 0,\n failures: reindex.failures.length,\n },\n });\n return { reindex, drained };\n } finally {\n await runtime.close();\n }\n}\n\n/** SessionStart(compact|clear) → resend all context on the next prompt. */\nexport async function runResetHook(input: HookInput): Promise<void> {\n const repositoryRoot = resolve(input.cwd ?? process.cwd());\n await new SessionCapsuleLedger(repositoryRoot).reset(input.session_id ?? \"default\");\n}\n\n// ── helpers ─────────────────────────────────────────────────────────\n\n/**\n * Pull edited paths out of a tool input: Claude Edit/Write (`file_path`),\n * MultiEdit (`edits[]`), OpenCode edit/write (`filePath`) and apply_patch/patch\n * (`patchText` file headers, including move targets), Hermes write_file and\n * patch replace mode (`path`) and patch mode (V4A headers in `patch`).\n */\nexport function extractEditedPaths(toolInput: Record<string, unknown> | undefined): string[] {\n if (!toolInput) return [];\n const paths: string[] = [];\n const push = (value: unknown) => {\n if (typeof value === \"string\" && value.trim()) paths.push(value);\n };\n push(toolInput.file_path);\n push(toolInput.filePath);\n push(toolInput.path);\n for (const patch of [toolInput.patchText, toolInput.patch]) {\n if (typeof patch !== \"string\") continue;\n for (const match of patch.matchAll(\n /^\\*\\*\\*\\s+(?:(?:Add|Update|Delete)\\s+File|Move\\s+to):\\s*(.+)$/gm,\n )) {\n push(match[1]?.trim());\n }\n }\n if (Array.isArray(toolInput.edits)) {\n for (const edit of toolInput.edits) {\n if (edit && typeof edit === \"object\") push((edit as Record<string, unknown>).file_path);\n }\n }\n return [...new Set(paths)];\n}\n\nfunction toRepoRelative(repositoryRoot: string, path: string): string | null {\n const absolute = isAbsolute(path) ? resolve(path) : resolve(repositoryRoot, path);\n const rel = relative(repositoryRoot, absolute);\n if (rel === \"\" || rel === \"..\" || rel.startsWith(`..${sep}`) || isAbsolute(rel)) return null;\n return rel.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\");\n}\n\n/**\n * Build a capture summary from the turn transcript (the last assistant message)\n * plus the change set. If the transcript can't be read, fall back to a plain\n * file list — which the conservative extractor will simply not turn into durable\n * facts, exactly the safe outcome.\n */\nexport async function deriveSummary(\n transcriptPath: string | undefined,\n changedFiles: string[],\n /** Used when there is no transcript (OpenCode passes the last assistant text). */\n lastAssistantText?: string,\n): Promise<string> {\n const fileList = changedFiles.length > 0 ? `Changed files: ${changedFiles.join(\", \")}.` : \"\";\n const assistantText = transcriptPath\n ? await lastAssistantMessage(transcriptPath)\n : (lastAssistantText?.trim().slice(0, 2000) ?? \"\");\n return [assistantText, fileList].filter(Boolean).join(\"\\n\\n\");\n}\n\n/**\n * A shell segment counts as verification when a known runner invokes a\n * test/lint/typecheck/build step (`rm -rf build` does not count).\n */\nconst VERIFICATION_SEGMENT =\n /^\\s*(?:\\w+=\\S*\\s+)*(?:npm|pnpm|yarn|bun|npx|cargo|go|make|mvn|gradle|\\.\\/gradlew|tsc|vitest|jest|pytest|python3? -m pytest|ruff|mypy|eslint|biome)\\b.*\\b(?:test|tests|lint|typecheck|tsc|build|check|vet|clippy|vitest|jest|pytest|ruff|mypy|eslint|biome)\\b/;\n\nfunction isVerificationCommand(command: string): boolean {\n return command.split(/&&|\\|\\||;/).some((segment) => VERIFICATION_SEGMENT.test(segment));\n}\n\n/**\n * Verification evidence for the current turn: test/lint/typecheck/build shell\n * commands run since the user's last prompt, with pass/fail from the tool\n * result. Only commands and outcomes are kept, never their output.\n */\nexport async function turnVerification(transcriptPath: string): Promise<string[]> {\n let raw: string;\n try {\n raw = await readFile(transcriptPath, \"utf8\");\n } catch {\n return [];\n }\n let commands = new Map<string, string>();\n const outcomes = new Map<string, boolean>();\n for (const line of raw.split(\"\\n\")) {\n let entry: Record<string, unknown>;\n try {\n entry = JSON.parse(line) as Record<string, unknown>;\n } catch {\n continue;\n }\n const message = (entry.message ?? {}) as Record<string, unknown>;\n const content = message.content;\n if (message.role === \"user\") {\n // A real prompt (not just tool results) starts a new turn.\n const isPrompt =\n typeof content === \"string\" ||\n (Array.isArray(content) && content.some((block) => block?.type === \"text\"));\n if (isPrompt) {\n commands = new Map();\n outcomes.clear();\n }\n for (const block of Array.isArray(content) ? content : []) {\n if (block?.type === \"tool_result\" && typeof block.tool_use_id === \"string\") {\n outcomes.set(block.tool_use_id, block.is_error !== true);\n }\n }\n continue;\n }\n for (const block of Array.isArray(content) ? content : []) {\n const command = block?.input?.command;\n if (block?.type !== \"tool_use\" || block.name !== \"Bash\" || typeof command !== \"string\") {\n continue;\n }\n if (isVerificationCommand(command)) commands.set(block.id, command);\n }\n }\n return verificationLines(\n [...commands].map(([id, command]) => ({ command, ok: outcomes.get(id) })),\n );\n}\n\n/** Format verification runs (non-checks dropped); `ok` undefined = no result. */\nexport function verificationLines(\n runs: Array<{ command: string; ok: boolean | undefined }>,\n): string[] {\n const lines = runs\n .filter((run) => isVerificationCommand(run.command))\n .map(({ command, ok }) => {\n const label = ok === undefined ? \"no result\" : ok ? \"passed\" : \"failed\";\n return `${command.replace(/\\s+/g, \" \").trim().slice(0, 120)}: ${label}`;\n });\n // Keep the latest runs; a re-run after a fix is the one that matters.\n return lines.slice(-10);\n}\n\n/** Prompts longer than this are pasted material, not instructions to remember. */\nconst MAX_RULE_PROMPT_CHARS = 1500;\n/** Harness-inserted markup (reminders, slash-command echoes) inside user content. */\nconst TAGGED_BLOCK = /<([a-z][\\w-]*)[^>]*>[\\s\\S]*?<\\/\\1>/gi;\n\n/**\n * The user's own prompt text for the current turn (since the last assistant\n * reply): tool results, harness-inserted meta messages (skill bodies, command\n * output) and tagged blocks are excluded, so only what the user typed can\n * become a rule.\n */\nexport async function turnUserPrompts(transcriptPath: string): Promise<string[]> {\n let raw: string;\n try {\n raw = await readFile(transcriptPath, \"utf8\");\n } catch {\n return [];\n }\n let prompts: string[] = [];\n let answered = false;\n for (const line of raw.split(\"\\n\")) {\n let entry: Record<string, unknown>;\n try {\n entry = JSON.parse(line) as Record<string, unknown>;\n } catch {\n continue;\n }\n const message = (entry.message ?? {}) as Record<string, unknown>;\n if (message.role === \"assistant\") {\n answered = true;\n continue;\n }\n if (message.role !== \"user\" || entry.isMeta === true) continue;\n const text = extractText(message.content).replace(TAGGED_BLOCK, \" \").trim();\n if (!text) continue;\n if (answered) {\n prompts = [];\n answered = false;\n }\n if (text.length <= MAX_RULE_PROMPT_CHARS) prompts.push(text);\n }\n return prompts;\n}\n\nexport async function lastAssistantMessage(transcriptPath: string): Promise<string> {\n try {\n const raw = await readFile(transcriptPath, \"utf8\");\n let latest = \"\";\n for (const line of raw.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n try {\n const entry = JSON.parse(trimmed) as Record<string, unknown>;\n const message = (entry.message ?? entry) as Record<string, unknown>;\n const role = message.role ?? entry.type;\n if (role !== \"assistant\") continue;\n const text = extractText(message.content);\n if (text) latest = text;\n } catch {\n // Skip malformed lines; transcripts are best-effort input.\n }\n }\n return latest.slice(0, 2000);\n } catch {\n return \"\";\n }\n}\n\nfunction extractText(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return \"\";\n return content\n .map((block) =>\n block && typeof block === \"object\" && (block as Record<string, unknown>).type === \"text\"\n ? String((block as Record<string, unknown>).text ?? \"\")\n : \"\",\n )\n .join(\" \")\n .trim();\n}\n\n/** Below this a risk score (0–100) is one routine signal, e.g. a few commits. */\nconst RISK_LINE_MIN_SCORE = 50;\n\n/** A rendered line; lower `priority` is packed first. */\ntype BlockItem = { priority: number; text: string; capsule?: ContextCapsule };\n\n/** Capsule text is bounded so one huge subject can never become undeliverable. */\nfunction bound(text: string, max = 300): string {\n return text.length > max ? `${text.slice(0, max - 1)}…` : text;\n}\n\n/**\n * Pack whole lines into the block by priority (current-task risk, relevant\n * facts, then broad bootstrap evidence) and return only the capsules whose\n * full text made it in. Lines are never cut; omitted capsules stay unseen.\n */\nexport async function renderContextBlock(\n bootstrap: BootstrapContext,\n beforeEdit: BeforeEditContext | null,\n ledger: SessionCapsuleLedger,\n sessionId: string,\n announceSession = false,\n): Promise<{ text: string; emitted: ContextCapsule[] }> {\n const capsules: Array<{ priority: number; capsule: ContextCapsule }> = [\n // Sent once per session (and again after a reset): MCP context calls that\n // pass it as `sessionId` share this ledger, so compaction resets both paths.\n ...(announceSession\n ? [\n {\n priority: 1,\n capsule: {\n key: \"session\",\n text: `session: ${sessionId} (pass as sessionId to CodeBuddy tools)`,\n },\n },\n ]\n : []),\n { priority: 4, capsule: { key: \"project\", text: `project: ${bootstrap.project.namespace}` } },\n {\n priority: 4,\n capsule: {\n key: \"plan\",\n text: `plan: ${bootstrap.plan ? `${bootstrap.plan.title} (${bootstrap.plan.status})` : \"none\"}`,\n },\n },\n { priority: 4, capsule: { key: \"plan-policy\", text: `plan policy: ${bootstrap.policy}` } },\n ];\n // Only rules that match this prompt's target files; the full rule list is\n // the same on every prompt and rarely relevant.\n const policyRules = beforeEdit?.policyRules ?? [];\n if (policyRules.length > 0) {\n capsules.push({\n priority: 4,\n capsule: {\n key: \"policies\",\n text: `policies: ${policyRules.map((r) => `${r.id}(${r.weight})`).join(\", \")}`,\n },\n });\n }\n for (const incident of bootstrap.incidents) {\n capsules.push({\n priority: 5,\n capsule: {\n key: `incident:${incident.id}`,\n text: `incident: ${bound(incident.subject)} [${incident.severity}]`,\n },\n });\n }\n for (const rule of bootstrap.rules ?? []) {\n const procedure = rule.subject === \"procedure\";\n capsules.push({\n priority: 2,\n capsule: {\n key: `${procedure ? \"procedure\" : \"rule\"}:${rule.id}`,\n text: bound(`${procedure ? \"verify\" : \"rule\"}: ${rule.summary}`),\n },\n });\n }\n // With a prompt, memory is what the prompt retrieved (hybrid-ranked; none\n // = abstain), never the most recent facts; those are only for a bare start.\n const ranked = Boolean(beforeEdit?.task);\n const facts = ranked ? (beforeEdit?.facts ?? []) : bootstrap.facts;\n for (const fact of facts) {\n capsules.push({\n priority: ranked ? 2 : 6,\n capsule: { key: `fact:${fact.id}`, text: bound(`fact: ${fact.summary}`) },\n });\n }\n for (const handoff of bootstrap.handoffs) {\n const drift = [\n handoff.changedSince.length > 0 ? `${handoff.changedSince.length} file(s) changed since` : \"\",\n handoff.missing.length > 0 ? `${handoff.missing.length} missing` : \"\",\n ]\n .filter(Boolean)\n .join(\", \");\n capsules.push({\n priority: 7,\n capsule: {\n key: `handoff:${handoff.id}`,\n text: `prior work (${handoff.ageDays}d ago${drift ? `; ${drift}` : \"\"}): ${handoff.summary\n .replace(/\\s+/g, \" \")\n .slice(0, 160)}`,\n },\n });\n }\n if (beforeEdit?.testCommand) {\n capsules.push({\n priority: 3,\n capsule: { key: \"test-command\", text: `test command: ${beforeEdit.testCommand}` },\n });\n }\n capsules.push({\n priority: 8,\n capsule: {\n key: \"architecture\",\n text: `architecture: ${bootstrap.architecture.moduleCount} modules, ${bootstrap.architecture.edgeCount} edges`,\n },\n });\n\n const seen = await ledger.seen(\n sessionId,\n capsules.map((entry) => entry.capsule),\n );\n const items: BlockItem[] = [\n { priority: 0, text: \"## CodeBuddy project context (auto-recalled)\" },\n ];\n const unchanged: ContextCapsule[] = [];\n // Facts already in the conversation do not use up this prompt's fact slots.\n let newFacts = 0;\n for (const { priority, capsule } of capsules) {\n if (seen.has(capsule.key)) unchanged.push(capsule);\n else if (ranked && capsule.key.startsWith(\"fact:\") && ++newFacts > PROMPT_FACTS) continue;\n else items.push({ priority, text: capsule.text, capsule });\n }\n if (unchanged.length > 0) {\n const avoided = unchanged.reduce((sum, capsule) => sum + estimateTokens(capsule.text), 0);\n items.push({\n priority: 10,\n text: `unchanged since earlier in this session (not resent, ~${avoided} tokens): ${describeKeys(unchanged.map((c) => c.key))}`,\n });\n }\n\n if (beforeEdit && beforeEdit.targetPaths.length > 0) {\n // Only git-derived targets are edits in progress; task/plan/explicit paths are not.\n const targetLabel = beforeEdit.pathSource === \"git\" ? \"current changes\" : \"task files\";\n const tests = (beforeEdit.tests ?? []).map((entry) => entry.test);\n items.push({\n priority: 3,\n text: bound(\n `${targetLabel}: ${beforeEdit.targetPaths.slice(0, 8).join(\", \")}` +\n (tests.length > 0 ? `; tests: ${tests.join(\", \")}` : \"\"),\n 500,\n ),\n });\n // Risk for the listed files only (task discovery also assesses unrelated\n // git changes), and only when the score means something.\n const targets = new Set(beforeEdit.targetPaths);\n const risks = beforeEdit.risks.items.filter(\n (item) => targets.has(item.path) && item.score >= RISK_LINE_MIN_SCORE,\n );\n if (risks.length > 0) {\n items.push({\n priority: 1,\n text: bound(\n `risk: ${risks\n .slice(0, 3)\n .map((item) => `${item.path}=${item.score}`)\n .join(\", \")}`,\n 500,\n ),\n });\n }\n }\n\n // Greedy by priority; a line that does not fit is skipped whole, a smaller one may still fit.\n const chosen = new Set<BlockItem>();\n let used = -1; // joining \"\\n\" is only paid between lines\n const byPriority = items\n .map((item, index) => ({ item, index }))\n .sort((a, b) => a.item.priority - b.item.priority || a.index - b.index);\n for (const { item } of byPriority) {\n const cost = item.text.length + 1;\n if (used + cost > CONTEXT_BLOCK_MAX_CHARS) continue;\n used += cost;\n chosen.add(item);\n }\n const packed = items.filter((item) => chosen.has(item));\n return {\n text: packed.map((item) => item.text).join(\"\\n\"),\n emitted: packed.flatMap((item) => (item.capsule ? [item.capsule] : [])),\n };\n}\n\n/** \"project, plan, 3 fact, 1 incident\" — readable names instead of opaque hashes. */\nfunction describeKeys(keys: string[]): string {\n const counts = new Map<string, number>();\n for (const key of keys) {\n const kind = key.includes(\":\") ? key.slice(0, key.indexOf(\":\")) : key;\n counts.set(kind, (counts.get(kind) ?? 0) + 1);\n }\n return [...counts]\n .map(([kind, count]) => (count > 1 || kinds.has(kind) ? `${count} ${kind}` : kind))\n .join(\", \");\n}\n\nconst kinds = new Set([\"fact\", \"incident\", \"handoff\", \"rule\", \"procedure\"]);\n","import { createHash } from \"node:crypto\";\nimport { resolve } from \"node:path\";\nimport { generateEntityId } from \"../core/ids.js\";\nimport { MemoryFileStore } from \"../core/memory-file-store.js\";\nimport { isEligibleMemory } from \"../core/memory-lifecycle.js\";\nimport { termOverlap } from \"../core/memory-search.js\";\nimport { WorklogStore } from \"../worklog/store.js\";\nimport { incidentDoubt } from \"./deterministic.js\";\nimport { type ExtractOptions, extractCandidates } from \"./llm.js\";\nimport { matchResolution } from \"./resolution.js\";\nimport { ReviewStore } from \"./review-store.js\";\nimport { revokes } from \"./rules.js\";\nimport { claimText, redactPersisted, type SensitivityResult, scanFields } from \"./sensitive.js\";\nimport type {\n AfterTurnResult,\n CandidateDecision,\n ExtractionInput,\n MemoryCandidate,\n} from \"./types.js\";\n\n/**\n * The capture orchestrator (`context_after_turn`). It extracts candidates,\n * then gates each one:\n *\n * - `ignored` → dropped.\n * - sensitive content → queued for review, flagged (never auto-saved).\n * - `note` (temporary) → queued for review (never durable).\n * - confident fact/decision/incident (≥ threshold) → saved as durable Markdown.\n * - everything else → queued for review (low confidence).\n *\n * The bias is deliberate: durable memory is the exception, review is the rule.\n */\n\n/** Minimum confidence for a fact/decision/incident to skip review. */\nconst AUTO_SAVE_THRESHOLD = 0.7;\n/** The user stated it (rule) or it passed repeatedly (procedure): trusted, still sensitive-scanned. */\nconst STATED_CONFIDENCE = 0.9;\n\nexport type CaptureOptions = ExtractOptions & {\n repositoryRoot?: string;\n now?: () => Date;\n};\n\nexport async function captureAfterTurn(\n input: ExtractionInput,\n options: CaptureOptions = {},\n): Promise<AfterTurnResult> {\n const repositoryRoot = resolve(options.repositoryRoot ?? process.cwd());\n const now = options.now ?? (() => new Date());\n const memoryStore = new MemoryFileStore(repositoryRoot);\n const reviewStore = new ReviewStore(repositoryRoot);\n\n const extracted =\n input.extract === false\n ? { candidates: [], source: \"deterministic\" as const }\n : await extractCandidates(input, options);\n const source = extracted.source;\n const candidates = [\n ...extracted.candidates,\n ...(input.userRules ?? []).map(ruleCandidate),\n ...(await procedureCandidates(input, repositoryRoot)),\n ];\n\n const saved: CandidateDecision[] = [];\n const queuedForReview: CandidateDecision[] = [];\n const ignored: CandidateDecision[] = [];\n const reasons: string[] = [];\n\n for (const candidate of candidates) {\n // Scan every text surface that reaches durable Markdown: all candidate\n // fields plus the turn's provenance (verification, paths, agent/plan/session/commit).\n const sensitivity = scanFields([\n claimText(candidate),\n candidate.content,\n candidate.subject,\n candidate.predicate,\n candidate.object,\n ...candidate.paths,\n ...(input.verification ?? []),\n input.agentId,\n input.planId,\n input.sessionId,\n input.commitSha,\n ]);\n const decision = await gate({\n candidate,\n input,\n sensitivity,\n memoryStore,\n reviewStore,\n now,\n });\n reasons.push(`${candidate.class}: ${decision.outcome} — ${decision.reason}`);\n if (decision.outcome === \"saved\") saved.push(decision);\n else if (decision.outcome === \"queued\") queuedForReview.push(decision);\n else ignored.push(decision);\n }\n\n for (const revocation of input.revokedRules ?? []) {\n const decision = await revokeRule(revocation, input, memoryStore, reviewStore, now);\n reasons.push(`rule: ${decision.outcome} — ${decision.reason}`);\n // A matched revocation changes existing memory; only an unmatched one is new.\n if (decision.outcome === \"queued\") queuedForReview.push(decision);\n }\n\n const worklogId = await recordWorklog(\n input,\n saved,\n queuedForReview,\n repositoryRoot,\n now,\n reasons,\n );\n return { saved, queuedForReview, ignored, reasons, extractor: source, worklogId };\n}\n\n/**\n * One worklog entry per meaningful turn (files changed, memory saved, or\n * verification reported), so a later chat can recover the work. A worklog\n * failure never undoes or blocks the memory capture above.\n */\nasync function recordWorklog(\n input: ExtractionInput,\n saved: CandidateDecision[],\n queued: CandidateDecision[],\n repositoryRoot: string,\n now: () => Date,\n reasons: string[],\n): Promise<string | null> {\n const files = input.changedFiles ?? [];\n const verification = input.verification ?? [];\n if (files.length === 0 && saved.length === 0 && verification.length === 0 && !input.investigation)\n return null;\n try {\n return await new WorklogStore(repositoryRoot).record(\n {\n namespace: input.namespace,\n summary: input.summary,\n files,\n verification,\n savedMemory: saved.flatMap((decision) => (decision.ref ? [decision.ref] : [])),\n queuedForReview: queued.flatMap((decision) => (decision.ref ? [decision.ref] : [])),\n ...(input.sessionId !== undefined ? { sessionId: input.sessionId } : {}),\n ...(input.planId !== undefined ? { planId: input.planId } : {}),\n ...(input.commitSha !== undefined ? { commitSha: input.commitSha } : {}),\n ...(input.agentId !== undefined ? { agentId: input.agentId } : {}),\n },\n now(),\n );\n } catch (error) {\n reasons.push(`worklog: not recorded — ${(error as Error).message}`);\n return null;\n }\n}\n\nfunction ruleCandidate(rule: string): MemoryCandidate {\n return {\n class: \"decision\",\n content: rule,\n subject: \"rule\",\n predicate: \"rule\",\n object: rule,\n confidence: STATED_CONFIDENCE,\n paths: [],\n severity: null,\n };\n}\n\n/**\n * A verification command that passed this turn and in at least one earlier\n * captured turn becomes a procedure (\"Verify with: npm test\"). Dedupe is the\n * usual fingerprint, so it is saved once.\n */\nasync function procedureCandidates(\n input: ExtractionInput,\n repositoryRoot: string,\n): Promise<MemoryCandidate[]> {\n const passed = (input.verification ?? []).filter((line) => line.endsWith(\": passed\"));\n if (passed.length === 0) return [];\n let history: string[][];\n try {\n history = (await new WorklogStore(repositoryRoot).list(input.namespace)).map(\n (entry) => entry.verification,\n );\n } catch {\n return [];\n }\n return [...new Set(passed)]\n .filter((line) => history.some((verification) => verification.includes(line)))\n .map((line) => {\n const command = line.slice(0, -\": passed\".length);\n return {\n class: \"fact\" as const,\n content: `Verify with: ${command}`,\n subject: \"procedure\",\n predicate: \"procedure\",\n object: command,\n confidence: STATED_CONFIDENCE,\n paths: [],\n severity: null,\n };\n });\n}\n\n/** Supersede the live rules a user sentence withdraws; with no match, ask a human. */\nasync function revokeRule(\n revocation: string,\n input: ExtractionInput,\n memoryStore: MemoryFileStore,\n reviewStore: ReviewStore,\n now: () => Date,\n): Promise<CandidateDecision> {\n const candidate: MemoryCandidate = {\n class: \"note\",\n content: revocation,\n subject: \"rule\",\n predicate: \"revoke\",\n object: revocation,\n confidence: 0.4,\n paths: [],\n severity: null,\n };\n const matches = (await memoryStore.listFacts()).filter(\n (fact) =>\n fact.predicate === \"rule\" &&\n isEligibleMemory(fact, { namespace: input.namespace }) &&\n revokes(revocation, fact.object),\n );\n const base = { candidate, sensitive: false, sensitiveReasons: [] };\n if (matches.length === 0) {\n const sensitivity = scanFields([revocation]);\n const decision = await gate({ candidate, input, sensitivity, memoryStore, reviewStore, now });\n return { ...decision, reason: `revocation matched no rule; ${decision.reason}` };\n }\n const marker = `revoked:${now().toISOString()}`;\n for (const fact of matches) await memoryStore.markFactSuperseded(fact.id, marker);\n return {\n ...base,\n outcome: \"saved\",\n reason: `revoked ${matches.map((fact) => fact.id).join(\", \")}`,\n ref: matches[0]?.id as string,\n };\n}\n\nasync function gate(args: {\n candidate: MemoryCandidate;\n input: ExtractionInput;\n sensitivity: SensitivityResult;\n memoryStore: MemoryFileStore;\n reviewStore: ReviewStore;\n now: () => Date;\n}): Promise<CandidateDecision> {\n const { candidate, sensitivity } = args;\n const fingerprint = candidateFingerprint(args.input.namespace, candidate);\n const base = {\n candidate,\n sensitive: sensitivity.sensitive,\n sensitiveReasons: sensitivity.reasons,\n };\n\n if (candidate.class === \"ignored\") {\n return { ...base, outcome: \"ignored\", reason: \"classified as chatter\" };\n }\n\n if (sensitivity.sensitive) {\n const existing = (await args.reviewStore.list()).find(\n (item) => item.fingerprint === fingerprint,\n );\n const ref =\n existing?.id ?? (await queue(args, `sensitive content (${sensitivity.reasons.join(\", \")})`));\n return {\n ...base,\n outcome: \"queued\",\n reason: `sensitive: ${sensitivity.reasons.join(\", \")}`,\n ref,\n };\n }\n\n if (candidate.class === \"note\") {\n const existing = (await args.reviewStore.list()).find(\n (item) => item.fingerprint === fingerprint,\n );\n if (existing) {\n return { ...base, outcome: \"queued\", reason: \"duplicate review candidate\", ref: existing.id };\n }\n const ref = await queue(args, \"temporary note\");\n return { ...base, outcome: \"queued\", reason: \"temporary note held for review\", ref };\n }\n\n if (candidate.confidence < AUTO_SAVE_THRESHOLD) {\n const existing = (await args.reviewStore.list()).find(\n (item) => item.fingerprint === fingerprint,\n );\n if (existing) {\n return { ...base, outcome: \"queued\", reason: \"duplicate review candidate\", ref: existing.id };\n }\n const ref = await queue(args, `low confidence (${candidate.confidence.toFixed(2)})`);\n return {\n ...base,\n outcome: \"queued\",\n reason: `low confidence ${candidate.confidence.toFixed(2)} < ${AUTO_SAVE_THRESHOLD}`,\n ref,\n };\n }\n\n if (candidate.class === \"incident\") {\n const doubt = incidentDoubt(candidate.content);\n if (doubt) {\n const existing = (await args.reviewStore.list()).find(\n (item) => item.fingerprint === fingerprint,\n );\n const ref = existing?.id ?? (await queue(args, `uncertain incident: ${doubt}`));\n return { ...base, outcome: \"queued\", reason: `uncertain incident: ${doubt}`, ref };\n }\n }\n\n if (candidate.class === \"incident\" && isResolution(candidate.content)) {\n const unresolved = await args.memoryStore.listIncidentFacts({\n namespace: args.input.namespace,\n });\n const sharingPaths = await args.memoryStore.findIncidentFactsForPaths({\n namespace: args.input.namespace,\n paths: candidate.paths,\n });\n const match = matchResolution(candidate.content, sharingPaths, unresolved);\n if (match.kind === \"queue\") {\n const ref = await queue(\n args,\n `incident resolution not grounded: ${match.reason}`,\n match.candidates,\n );\n return {\n ...base,\n outcome: \"queued\",\n reason: `resolution not grounded: ${match.reason}`,\n ref,\n };\n }\n await args.memoryStore.markIncidentResolved(match.incident.id, fingerprint);\n return {\n ...base,\n outcome: \"saved\",\n reason: `resolved incident ${match.incident.id} (${match.reason})`,\n ref: match.incident.id,\n };\n }\n\n const superseded = candidate.content.match(/\\bsupersedes\\s+(fact_[a-z0-9]+)\\b/i)?.[1];\n // Mem0-style update check without an LLM: a reworded copy of a live fact is\n // dropped, and a partial overlap goes to review as a possible update rather\n // than being saved beside the fact it may replace. Incidents may recur, and\n // an explicit \"supersedes fact_x\" already says what it replaces.\n if (candidate.class !== \"incident\" && !superseded) {\n const similar = await nearestFact(\n args.memoryStore,\n args.input.namespace,\n candidate,\n fingerprint,\n );\n if (similar && similar.overlap >= DUPLICATE_OVERLAP) {\n return {\n ...base,\n outcome: \"ignored\",\n reason: `near-duplicate of ${similar.id} (${Math.round(similar.overlap * 100)}% shared words)`,\n ref: similar.id,\n };\n }\n if (similar && similar.overlap >= UPDATE_OVERLAP) {\n const existing = (await args.reviewStore.list()).find(\n (item) => item.fingerprint === fingerprint,\n );\n const ref = existing?.id ?? (await queue(args, `possible update of ${similar.id}`));\n return {\n ...base,\n outcome: \"queued\",\n reason: `overlaps ${similar.id} (${Math.round(similar.overlap * 100)}% shared words): review as a possible update`,\n ref,\n };\n }\n }\n\n const ref = await saveDurable(args);\n if (superseded && superseded !== ref) {\n try {\n await args.memoryStore.markFactSuperseded(superseded, ref);\n } catch {\n // A missing/invalid referenced fact does not invalidate the new decision.\n }\n }\n return { ...base, outcome: \"saved\", reason: `confident ${candidate.class} auto-saved`, ref };\n}\n\n/** At or above this word overlap a new fact restates a live one. */\nconst DUPLICATE_OVERLAP = 0.8;\n/** At or above this overlap a new fact may update a live one: a person decides. */\nconst UPDATE_OVERLAP = 0.5;\n\n/** The live fact of this namespace whose content overlaps the candidate most. */\nasync function nearestFact(\n memoryStore: MemoryFileStore,\n namespace: string,\n candidate: MemoryCandidate,\n fingerprint: string,\n): Promise<{ id: string; overlap: number } | null> {\n let best: { id: string; overlap: number } | null = null;\n for (const fact of await memoryStore.listFacts()) {\n // An exact repeat keeps its existing outcome (saveDurable returns that fact).\n if (fact.fingerprint === fingerprint || fact.category === \"incident\") continue;\n if (fact.predicate === \"rule\" || fact.predicate === \"procedure\") continue;\n if (!isEligibleMemory(fact, { namespace })) continue;\n const overlap = termOverlap(candidate.content, fact.content || fact.object);\n if (!best || overlap > best.overlap) best = { id: fact.id, overlap };\n }\n return best;\n}\n\nasync function saveDurable(args: {\n candidate: MemoryCandidate;\n input: ExtractionInput;\n memoryStore: MemoryFileStore;\n now: () => Date;\n}): Promise<string> {\n const { candidate, input, memoryStore, now } = args;\n const fingerprint = candidateFingerprint(input.namespace, candidate);\n const existing = (await memoryStore.listFacts()).find(\n (fact) => fact.namespace === input.namespace && fact.fingerprint === fingerprint,\n );\n if (existing) return existing.id;\n const id = generateEntityId(\"fact\");\n const isIncident = candidate.class === \"incident\";\n await memoryStore.writeFact({\n id,\n namespace: input.namespace,\n subject: candidate.subject,\n predicate: candidate.predicate,\n object: candidate.object,\n confidence: candidate.confidence,\n createdAt: now().toISOString(),\n createdByAgent: input.agentId ?? null,\n sourceInteractionId: null,\n sourceDeleted: false,\n content: candidate.content,\n category: isIncident ? \"incident\" : \"general\",\n paths: candidate.paths,\n severity: isIncident ? candidate.severity : null,\n fingerprint,\n sourcePlanId: input.planId ?? null,\n sourceSessionId: input.sessionId ?? null,\n verification: input.verification ?? [],\n introducedBy: isIncident ? (input.commitSha ?? null) : null,\n });\n return id;\n}\n\nasync function queue(\n args: {\n candidate: MemoryCandidate;\n input: ExtractionInput;\n sensitivity: SensitivityResult;\n reviewStore: ReviewStore;\n now: () => Date;\n },\n reason: string,\n resolvesIncidents: string[] | null = null,\n): Promise<string> {\n const { candidate, input, sensitivity, reviewStore, now } = args;\n const fingerprint = candidateFingerprint(input.namespace, candidate);\n const id = generateEntityId(\"rev\");\n await reviewStore.write({\n id,\n namespace: input.namespace,\n class: candidate.class,\n subject: candidate.subject,\n predicate: candidate.predicate,\n object: candidate.object,\n confidence: candidate.confidence,\n paths: candidate.paths,\n severity: candidate.severity,\n sensitive: sensitivity.sensitive,\n sensitiveReasons: sensitivity.reasons,\n reason,\n createdAt: now().toISOString(),\n createdByAgent: input.agentId ?? null,\n sourcePlanId: input.planId ?? null,\n fingerprint,\n sourceSessionId: input.sessionId ?? null,\n verification: input.verification ?? [],\n content: candidate.content,\n resolvesIncidents,\n });\n await reviewStore.enforceLimit();\n return id;\n}\n\nfunction isResolution(content: string): boolean {\n return /\\b(fixed|resolved|closed|no longer reproduces|verified the fix)\\b/i.test(content);\n}\n\nexport function candidateFingerprint(namespace: string, raw: MemoryCandidate): string {\n // Hash the redacted form so the persisted fingerprint never derives from a raw secret.\n const candidate = redactPersisted(raw);\n const canonical = JSON.stringify({\n namespace: namespace.trim().toLowerCase(),\n class: candidate.class,\n subject: candidate.subject.trim().toLowerCase(),\n predicate: candidate.predicate.trim().toLowerCase(),\n object: candidate.object.trim().replace(/\\s+/g, \" \").toLowerCase(),\n content: candidate.content.trim().replace(/\\s+/g, \" \").toLowerCase(),\n paths: [...new Set(candidate.paths.map((path) => path.replace(/\\\\/g, \"/\")))].sort(),\n });\n return createHash(\"sha256\").update(canonical).digest(\"hex\");\n}\n\n/**\n * Promote a queued review item to a durable fact and remove it from the queue.\n * A queued incident resolution instead resolves the chosen existing incident\n * (`incidentId`, or the single recorded candidate) and returns its id.\n * Powers `codebuddy memory review approve`.\n */\nexport async function approveReviewItem(\n id: string,\n options: { repositoryRoot?: string; now?: () => Date; incidentId?: string } = {},\n): Promise<string> {\n const repositoryRoot = resolve(options.repositoryRoot ?? process.cwd());\n const now = options.now ?? (() => new Date());\n const reviewStore = new ReviewStore(repositoryRoot);\n const memoryStore = new MemoryFileStore(repositoryRoot);\n\n const item = await reviewStore.read(id);\n\n // A queued resolution closes an existing incident; it never writes a new one.\n if (item.resolvesIncidents) {\n const unresolved = await memoryStore.listIncidentFacts({ namespace: item.namespace });\n const target =\n options.incidentId ??\n (item.resolvesIncidents.length === 1 ? item.resolvesIncidents[0] : undefined);\n if (!target) {\n throw new Error(\n item.resolvesIncidents.length === 0\n ? `Review item ${id} is an incident resolution with no candidate incident; pass an incident id to resolve.`\n : `Review item ${id} is an ambiguous incident resolution; pass one incident id. Candidates: ${item.resolvesIncidents.join(\", \")}`,\n );\n }\n if (!unresolved.some((incident) => incident.id === target)) {\n throw new Error(`${target} is not an unresolved incident in namespace ${item.namespace}.`);\n }\n await memoryStore.markIncidentResolved(target, item.fingerprint ?? id);\n await reviewStore.delete(id);\n return target;\n }\n\n const factId = generateEntityId(\"fact\");\n const isIncident = item.class === \"incident\";\n await memoryStore.writeFact({\n id: factId,\n namespace: item.namespace,\n subject: item.subject,\n predicate: item.predicate,\n object: item.object,\n confidence: item.confidence,\n createdAt: now().toISOString(),\n createdByAgent: item.createdByAgent,\n sourceInteractionId: null,\n sourceDeleted: false,\n content: item.content,\n category: isIncident ? \"incident\" : \"general\",\n paths: item.paths,\n severity: isIncident ? (item.severity ?? \"medium\") : null,\n fingerprint: item.fingerprint,\n sourcePlanId: item.sourcePlanId,\n sourceSessionId: item.sourceSessionId,\n verification: item.verification,\n });\n await reviewStore.delete(id);\n return factId;\n}\n","import type { IncidentSeverity } from \"../core/memory-file-store.js\";\nimport type { ExtractionInput, MemoryCandidate, MemoryClass } from \"./types.js\";\n\n/**\n * Deterministic, no-LLM extraction. This is the always-available baseline\n * (offline mode) and the fallback when LLM extraction fails validation. It\n * segments the turn summary into sentences and classifies each with ordered\n * keyword rules. The same input always yields the same candidates, which keeps\n * capture predictable and auditable.\n *\n * Rule order matters: a \"TODO: fix the crash\" is a note, not an incident, so\n * note markers are checked before incident markers.\n */\n\ntype Rule = {\n class: MemoryClass;\n regex: RegExp;\n confidence: number;\n predicate: string;\n subject: string;\n};\n\n/** \"Resolved fact_abc123\": names its incident, so it is unambiguous by construction. */\nconst EXPLICIT_RESOLUTION = /\\b(?:fixed|resolved|closed)\\b.*\\bfact_[a-z0-9]+\\b/i;\n\nconst RULES: Rule[] = [\n {\n class: \"note\",\n subject: \"note\",\n predicate: \"todo\",\n confidence: 0.4,\n regex:\n /\\b(todo|to-do|follow[- ]?up|later|remember to|revisit|temporary|tmp|next time|should probably)\\b/i,\n },\n {\n // Explicit resolution of a named incident (\"Resolved fact_abc123\").\n class: \"incident\",\n subject: \"incident\",\n predicate: \"resolved\",\n confidence: 0.8,\n regex: EXPLICIT_RESOLUTION,\n },\n {\n class: \"decision\",\n subject: \"decision\",\n predicate: \"made\",\n confidence: 0.8,\n regex:\n /\\b(decided|chose|choose|we will|going with|switched to|switch to|adopt(?:ed)?|agreed|settled on|opt(?:ed)? for)\\b/i,\n },\n {\n class: \"incident\",\n subject: \"incident\",\n predicate: \"occurred\",\n confidence: 0.75,\n regex:\n /\\b(bug|regression|broke|broken|crash(?:ed)?|outage|incident|root cause|failure|failed|null pointer|race condition|deadlock)\\b/i,\n },\n {\n class: \"fact\",\n subject: \"project\",\n predicate: \"fact\",\n confidence: 0.55,\n regex:\n /\\b(uses?|is|are|requires?|depends on|stores?|returns?|implemented|added|supports?|configured|lives in|located|handles?)\\b/i,\n },\n];\n\nconst INCIDENT_REGEX = (RULES.find((rule) => rule.predicate === \"occurred\") as Rule).regex;\nexport const SPECULATIVE =\n /\\b(might|maybe|possibly|could|consider(?:ing)?|planned|planning|should|if|would|unless|whether|suppose|hypothetical(?:ly)?|in theory|in case)\\b/i;\n// \"no longer reproduces\" is a resolution, not a negation.\nconst NEGATION =\n /\\b(no|not|never|none|nothing|nobody|without|zero|neither|nor|cannot)\\b(?!\\s+longer)|\\w+n['’]t\\b/i;\nconst EXAMPLE = /\\b(?:e\\.g|i\\.e|for example|for instance|such as|example|sample|hypothetical)\\b/i;\n// Balanced \"double\", \\u201ccurly\\u201d and `code` quotes.\nconst QUOTED = /\"[^\"]*\"|\\u201c[^\\u201d]*\\u201d|`[^`]*`/g;\n\n/**\n * Why an incident-looking sentence is not trustworthy enough to become a\n * durable incident: negated (\"no crash occurred\"), hypothetical (\"if it\n * crashes\"), or quoted/example text. Returns null when it reads as a real\n * event. Shared by the deterministic extractor and the capture gate so LLM\n * candidates get the same scrutiny.\n */\nexport function incidentDoubt(sentence: string): string | null {\n if (EXPLICIT_RESOLUTION.test(sentence)) return null;\n const unquoted = sentence.replace(QUOTED, \" \");\n const onlyQuoted = INCIDENT_REGEX.test(sentence) && !INCIDENT_REGEX.test(unquoted);\n const unbalanced = (sentence.match(/[\"\\u201c\\u201d]/g)?.length ?? 0) % 2 === 1;\n if (onlyQuoted || unbalanced || EXAMPLE.test(sentence)) return \"quoted or example text\";\n if (NEGATION.test(unquoted)) return \"negated statement\";\n if (SPECULATIVE.test(unquoted) && !EXPLICIT_DECISION.test(unquoted))\n return \"hypothetical statement\";\n return null;\n}\nconst EXPLICIT_DECISION = /\\b(decided|chose|agreed|settled on|adopted|switched to)\\b/i;\n\nconst SEVERITY_MARKERS: Array<{ severity: IncidentSeverity; regex: RegExp }> = [\n { severity: \"critical\", regex: /\\b(critical|outage|data loss|corruption|security)\\b/i },\n {\n severity: \"high\",\n regex: /\\b(high severity|regression|crash(?:ed)?|deadlock|broke production)\\b/i,\n },\n { severity: \"low\", regex: /\\b(minor|cosmetic|typo|trivial)\\b/i },\n];\n\nexport function deterministicExtract(input: ExtractionInput): MemoryCandidate[] {\n const changedFiles = (input.changedFiles ?? []).filter(Boolean);\n const candidates: MemoryCandidate[] = [];\n\n for (const sentence of splitSentences(input.summary)) {\n const classified = classify(sentence);\n const doubt = classified?.class === \"incident\" ? incidentDoubt(sentence) : null;\n const rule =\n doubt ||\n (SPECULATIVE.test(sentence) &&\n !EXPLICIT_DECISION.test(sentence) &&\n !EXPLICIT_RESOLUTION.test(sentence))\n ? {\n class: \"note\" as const,\n subject: \"speculation\",\n predicate: \"consider\",\n confidence: 0.3,\n regex: SPECULATIVE,\n }\n : classified;\n if (!rule) {\n candidates.push(ignoredCandidate(sentence));\n continue;\n }\n\n const isIncident = rule.class === \"incident\";\n let confidence = rule.confidence;\n if (isIncident && /\\broot cause\\b/i.test(sentence)) confidence = Math.min(1, confidence + 0.1);\n\n candidates.push({\n class: rule.class,\n content: sentence,\n subject: rule.subject,\n predicate: rule.predicate,\n object: sentence,\n confidence,\n // Incidents and decisions carry the change set so recall can link them to\n // the files they concern (the risk incident signal matches on paths).\n paths: rule.class === \"incident\" || rule.class === \"decision\" ? changedFiles : [],\n severity: isIncident ? guessSeverity(sentence) : null,\n });\n }\n\n return candidates;\n}\n\nfunction classify(sentence: string): Rule | null {\n for (const rule of RULES) {\n if (rule.regex.test(sentence)) return rule;\n }\n return null;\n}\n\nfunction ignoredCandidate(sentence: string): MemoryCandidate {\n return {\n class: \"ignored\",\n content: sentence,\n subject: \"chatter\",\n predicate: \"ignored\",\n object: sentence,\n confidence: 0.2,\n paths: [],\n severity: null,\n };\n}\n\nfunction guessSeverity(sentence: string): IncidentSeverity {\n for (const marker of SEVERITY_MARKERS) {\n if (marker.regex.test(sentence)) return marker.severity;\n }\n return \"medium\";\n}\n\n/** Split into trimmed sentences on terminators and newlines; drop tiny fragments. */\nexport function splitSentences(summary: string): string[] {\n return summary\n .split(/(?<=[.!?])(?<!\\b(?:e\\.g|i\\.e|vs|etc)\\.)\\s+|\\n+/)\n .map((sentence) => sentence.trim().replace(/^[-*•]\\s*/, \"\"))\n .filter((sentence) => sentence.length > 3);\n}\n","import { z } from \"zod\";\nimport { deterministicExtract } from \"./deterministic.js\";\nimport { type ExtractionInput, type MemoryCandidate, memoryCandidateSchema } from \"./types.js\";\n\n/**\n * LLM-assisted extraction is optional and never trusted blindly. An extractor\n * returns raw JSON; we validate it strictly against the candidate schema and\n * retry a bounded number of times. If it never produces valid output — or no\n * extractor is configured — we fall back to the deterministic parser rather\n * than inventing certainty. Raw LLM output is a suggestion, not a fact.\n */\n\n/** Pluggable model backend. Returns unvalidated candidate JSON. */\nexport type MemoryExtractor = {\n extract(input: ExtractionInput): Promise<unknown>;\n};\n\nconst candidateArraySchema = z.array(memoryCandidateSchema);\n\nexport type ExtractOptions = {\n extractor?: MemoryExtractor;\n retries?: number;\n};\n\nexport type ExtractOutcome = {\n candidates: MemoryCandidate[];\n source: \"deterministic\" | \"llm\";\n};\n\nexport async function extractCandidates(\n input: ExtractionInput,\n options: ExtractOptions = {},\n): Promise<ExtractOutcome> {\n if (options.extractor) {\n const validated = await tryLlmExtraction(input, options.extractor, options.retries ?? 2);\n if (validated) return { candidates: validated, source: \"llm\" };\n }\n return { candidates: deterministicExtract(input), source: \"deterministic\" };\n}\n\nasync function tryLlmExtraction(\n input: ExtractionInput,\n extractor: MemoryExtractor,\n retries: number,\n): Promise<MemoryCandidate[] | null> {\n for (let attempt = 0; attempt <= retries; attempt++) {\n try {\n const parsed = candidateArraySchema.safeParse(await extractor.extract(input));\n if (parsed.success) return parsed.data;\n } catch {\n // Swallow and retry; a throwing extractor is treated like invalid output.\n }\n }\n return null;\n}\n","import type { IncidentFactFile } from \"../core/memory-file-store.js\";\n\n/**\n * Deciding which unresolved incident a \"fixed X\" statement closes. A shared\n * file is never enough: resolution needs an explicit incident id, or fix text\n * that matches exactly one candidate's terms better than every other one.\n * Anything else is ambiguous and goes to review. Severity/recency never break\n * ties, so a generic fix can't close an unrelated higher-severity incident.\n *\n * Terms every candidate shares (e.g. the module name) say nothing about WHICH\n * incident was fixed, so only terms that tell candidates apart count, and the\n * fix must hit exactly one candidate's distinctive terms. A multi-topic fix\n * that touches two incidents is therefore ambiguous, however many terms match.\n */\n\nexport type ResolutionMatch =\n | { kind: \"resolved\"; incident: IncidentFactFile; reason: string }\n /** `candidates` are the unresolved incident ids a reviewer may pick from. */\n | { kind: \"queue\"; reason: string; candidates: string[] };\n\nconst FACT_ID = /\\bfact_[a-z0-9]+\\b/gi;\n\n// Words that carry no event identity: grammar plus generic fix/bug vocabulary.\nconst GENERIC = new Set(\n (\n \"a an the and or but of in on at to for from by with as is are was were be been it its this that these those \" +\n \"we i you they he she them there then than so not no also again now still just only into onto after before when while \" +\n \"fix fixed fixes fixing resolve resolved resolves resolving close closed closes verify verified verifies \" +\n \"bug bugs issue issues problem problems incident incidents error errors regression longer reproduce reproduces \" +\n \"test tests passed passing work works worked working change changed changes\"\n ).split(\" \"),\n);\n\n/** Lowercased content terms with a crude suffix stem (\"crashed\"/\"crashes\" -> \"crash\"). */\nexport function groundingTerms(text: string): Set<string> {\n const terms = new Set<string>();\n for (const word of text.toLowerCase().match(/[a-z][a-z0-9]+/g) ?? []) {\n if (GENERIC.has(word) || /^fact_/.test(word)) continue;\n terms.add(word.length > 4 ? word.replace(/(ing|ed|es|s)$/, \"\") : word);\n }\n return terms;\n}\n\nexport function matchResolution(\n fixText: string,\n pathCandidates: IncidentFactFile[],\n unresolved: IncidentFactFile[],\n): ResolutionMatch {\n const explicit = [...new Set(fixText.match(FACT_ID)?.map((id) => id.toLowerCase()))];\n if (explicit.length > 0) {\n const named = unresolved.filter((incident) => explicit.includes(incident.id));\n const [only] = named;\n if (named.length === 1 && only) {\n return { kind: \"resolved\", incident: only, reason: `explicit incident id ${only.id}` };\n }\n return {\n kind: \"queue\",\n candidates: named.map((incident) => incident.id),\n reason:\n named.length === 0\n ? \"explicit incident id does not name an unresolved incident\"\n : \"explicit ids name several incidents\",\n };\n }\n\n const candidates = pathCandidates.map((incident) => incident.id);\n const fixTerms = groundingTerms(fixText);\n if (pathCandidates.length === 0) {\n return {\n kind: \"queue\",\n candidates,\n reason: \"no unresolved incident touches the changed paths\",\n };\n }\n if (fixTerms.size === 0) {\n return { kind: \"queue\", candidates, reason: \"fix text names no specific event\" };\n }\n\n const incidentTerms = pathCandidates.map((incident) =>\n groundingTerms(`${incident.subject} ${incident.content}`),\n );\n // With several candidates, ignore terms all of them share (no discriminating power).\n const distinctive = (term: string) =>\n pathCandidates.length === 1 || incidentTerms.some((terms) => !terms.has(term));\n const hits = incidentTerms.map((terms) => [...fixTerms].filter((term) => terms.has(term)));\n const withDistinctive = hits\n .map((matched, index) => ({ index, matched, count: matched.filter(distinctive).length }))\n .filter((entry) => entry.count > 0 || pathCandidates.length === 1);\n\n const [best] = withDistinctive;\n if (!best || withDistinctive.length > 1) {\n return {\n kind: \"queue\",\n candidates,\n reason: best\n ? \"fix text matches distinctive terms of several unresolved incidents\"\n : \"fix text does not single out any unresolved incident\",\n };\n }\n const need = Math.min(2, fixTerms.size);\n if (best.matched.length < need) {\n return { kind: \"queue\", candidates, reason: \"fix text is too weakly grounded in the incident\" };\n }\n const incident = pathCandidates[best.index] as IncidentFactFile;\n return {\n kind: \"resolved\",\n incident,\n reason: `grounded match on ${best.matched.length} shared term${best.matched.length === 1 ? \"\" : \"s\"}`,\n };\n}\n","import { mkdir, readdir, readFile, rename, rm } from \"node:fs/promises\";\nimport { dirname, join, relative, resolve, sep } from \"node:path\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { z } from \"zod\";\nimport {\n assertNoSymlinkBetween,\n composeMarkdown,\n parseFrontMatter,\n writeAtomic,\n} from \"../core/markdown-store-fs.js\";\nimport { INCIDENT_SEVERITIES } from \"../core/memory-file-store.js\";\nimport { redactPersisted } from \"./sensitive.js\";\nimport { MEMORY_CLASSES } from \"./types.js\";\n\n/**\n * The review queue holds memory candidates that are not safe to auto-save —\n * low confidence, sensitive content, or an inherently temporary note. Items are\n * plain Markdown with YAML front matter under `.codebuddy/memory/review/`, so\n * they are inspectable, diffable, and deletable by hand. Approving an item\n * promotes it to a durable fact; rejecting deletes it. Nothing here is ever\n * committed automatically.\n */\n\nconst reviewSchema = z.object({\n schemaVersion: z.literal(1),\n id: z.string().regex(/^rev_[a-z0-9]+$/),\n namespace: z.string().min(1),\n class: z.enum(MEMORY_CLASSES),\n subject: z.string().min(1),\n predicate: z.string().min(1),\n object: z.string().min(1),\n confidence: z.number().min(0).max(1),\n paths: z.array(z.string().min(1)).default([]),\n severity: z.enum(INCIDENT_SEVERITIES).nullable().default(null),\n sensitive: z.boolean().default(false),\n sensitiveReasons: z.array(z.string()).default([]),\n reason: z.string(),\n createdAt: z.string(),\n createdByAgent: z.string().nullable(),\n sourcePlanId: z.string().nullable().default(null),\n fingerprint: z\n .string()\n .regex(/^[a-f0-9]{64}$/)\n .nullable()\n .default(null),\n sourceSessionId: z.string().nullable().default(null),\n verification: z.array(z.string()).default([]),\n /**\n * Set only on a queued incident *resolution* (\"Fixed X\") that could not be\n * grounded: the unresolved incident ids it might close. Approving it resolves\n * one of them instead of writing a new incident. null = ordinary item.\n */\n resolvesIncidents: z.array(z.string()).nullable().default(null),\n});\n\nexport type ReviewItemWrite = Omit<\n z.infer<typeof reviewSchema>,\n \"schemaVersion\" | \"fingerprint\" | \"sourceSessionId\" | \"verification\" | \"resolvesIncidents\"\n> & {\n resolvesIncidents?: string[] | null;\n fingerprint?: string | null;\n sourceSessionId?: string | null;\n verification?: string[];\n content: string;\n};\nexport type ReviewItem = z.infer<typeof reviewSchema> & { content: string; path: string };\n\nexport class ReviewStore {\n readonly repositoryRoot: string;\n readonly reviewDirectory: string;\n readonly archiveDirectory: string;\n\n constructor(repositoryRoot = process.cwd()) {\n this.repositoryRoot = resolve(repositoryRoot);\n this.reviewDirectory = join(this.repositoryRoot, \".codebuddy\", \"memory\", \"review\");\n this.archiveDirectory = join(this.repositoryRoot, \".codebuddy\", \"memory\", \"review-archive\");\n }\n\n async write(raw: ReviewItemWrite): Promise<string> {\n // Persistence boundary: nothing sensitive reaches disk, whatever the caller did.\n const input = redactPersisted(raw);\n const path = this.itemPath(input.id);\n await this.prepareDirectory();\n await assertNoSymlinkBetween(this.repositoryRoot, dirname(path));\n const frontMatter = stringifyYaml({\n schemaVersion: 1,\n id: input.id,\n namespace: input.namespace,\n class: input.class,\n subject: input.subject,\n predicate: input.predicate,\n object: input.object,\n confidence: input.confidence,\n paths: input.paths,\n severity: input.severity,\n sensitive: input.sensitive,\n sensitiveReasons: input.sensitiveReasons,\n reason: input.reason,\n createdAt: input.createdAt,\n createdByAgent: input.createdByAgent,\n sourcePlanId: input.sourcePlanId,\n fingerprint: input.fingerprint,\n sourceSessionId: input.sourceSessionId,\n verification: input.verification,\n resolvesIncidents: input.resolvesIncidents ?? null,\n });\n await writeAtomic(path, composeMarkdown(frontMatter, input.content));\n return path;\n }\n\n async read(id: string): Promise<ReviewItem> {\n const path = this.itemPath(id);\n await assertNoSymlinkBetween(this.repositoryRoot, path);\n const parsed = parseFrontMatter(await readFile(path, \"utf8\"));\n return {\n ...reviewSchema.parse(parseYaml(parsed.frontMatter)),\n content: parsed.content.trim(),\n path,\n };\n }\n\n async list(): Promise<ReviewItem[]> {\n try {\n await this.prepareDirectory();\n const entries = await readdir(this.reviewDirectory, { withFileTypes: true });\n const items: ReviewItem[] = [];\n for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {\n if (!entry.isFile() || !entry.name.endsWith(\".md\")) continue;\n // Only managed review files are queue items. A hand-written README.md\n // (or any non-rev_ markdown) must be ignored, not thrown on — one\n // stray file used to brick every future capture turn.\n if (!/^rev_[a-z0-9]+\\.md$/.test(entry.name)) continue;\n try {\n items.push(await this.read(entry.name.replace(/\\.md$/, \"\")));\n } catch {\n // A single corrupt item is skipped rather than poisoning the whole\n // queue; it stays on disk for manual inspection.\n }\n }\n return items;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return [];\n throw error;\n }\n }\n\n async delete(id: string): Promise<void> {\n await rm(this.itemPath(id), { force: true });\n }\n\n async archiveExpired(options: { olderThanDays?: number; now?: Date } = {}): Promise<number> {\n const cutoff =\n (options.now ?? new Date()).getTime() - (options.olderThanDays ?? 30) * 24 * 60 * 60 * 1000;\n const items = await this.list();\n let archived = 0;\n for (const item of items) {\n if (Date.parse(item.createdAt) >= cutoff) continue;\n await this.archive(item);\n archived++;\n }\n return archived;\n }\n\n async enforceLimit(maxItems = 500): Promise<number> {\n const items = (await this.list()).sort((left, right) =>\n left.createdAt.localeCompare(right.createdAt),\n );\n const overflow = Math.max(0, items.length - maxItems);\n for (const item of items.slice(0, overflow)) await this.archive(item);\n return overflow;\n }\n\n private async archive(item: ReviewItem): Promise<void> {\n await mkdir(this.archiveDirectory, { recursive: true, mode: 0o700 });\n await assertNoSymlinkBetween(this.repositoryRoot, this.archiveDirectory);\n await rename(item.path, join(this.archiveDirectory, `${item.id}.md`));\n }\n\n private itemPath(id: string): string {\n if (!/^rev_[a-z0-9]+$/.test(id)) throw new Error(`Invalid review id: ${id}`);\n return this.safePath(join(this.reviewDirectory, `${id}.md`));\n }\n\n private safePath(path: string): string {\n const absolute = resolve(path);\n const relativePath = relative(this.repositoryRoot, absolute);\n if (relativePath === \"..\" || relativePath.startsWith(`..${sep}`) || relativePath === \"\") {\n throw new Error(`Review path escapes repository root: ${path}`);\n }\n return absolute;\n }\n\n private async prepareDirectory(): Promise<void> {\n await assertNoSymlinkBetween(this.repositoryRoot, dirname(this.reviewDirectory));\n await mkdir(this.reviewDirectory, { recursive: true, mode: 0o700 });\n }\n}\n","import { SPECULATIVE } from \"./deterministic.js\";\n\n/**\n * Standing rules the user states (\"from now on…\", \"never…\", \"every PR\n * must…\") and revocations of them (\"stop…\", \"no longer…\"). A rule the user\n * stated is the most trustworthy memory there is, so it is read from the\n * user's own prompt, never from the assistant's paraphrase. Questions and\n * speculation are not rules.\n */\n\nconst MAX_RULE_CHARS = 300;\n/** CodeBuddy's injected context starts here; nothing after it is the user's. */\nconst INJECTED_BLOCK = /^##\\s*CodeBuddy\\b/m;\n/** Quoted or code material is never an instruction to this project. */\nconst FENCED_CODE = /```[\\s\\S]*?(?:```|$)/g;\nconst QUOTE_LINE = /^\\s*>.*$/gm;\n/** An explicit rule introduction: \"from now on\", \"going forward\", \"(a) rule (for …):\". */\nconst RULE_PREFIX =\n /^(?:also,?\\s+|please,?\\s+)?(?:from now on|going forward|(?:a\\s+)?rule\\b[^:.]{0,60}:)[,:]?\\s*/i;\n/** Imperative position: the sentence itself starts with the marker, or \"we/you always|never|must\". */\nconst IMPERATIVE =\n /^(?:please,?\\s+)?(?:always|never)\\s+\\S+\\s+\\S+|^(?:we|you)\\s+(?:always|never|must)\\b|^every\\s+(?!time\\b)\\S+.*\\bmust\\b/i;\nconst QUESTION_START =\n /^(?:why|how|what|when|where|which|who|can|could|would|will|do|does|did|is|are|should)\\b/i;\n/** Withdrawal of a rule: \"stop <verb>ing\", \"no longer\", \"don't … anymore\", \"forget the rule\". */\nconst REVOCATION_MARKER =\n /^(?:please,?\\s+)?stop\\s+\\w+ing\\b|\\bno longer\\b|\\b(?:don't|do not)\\b.*\\banymore\\b|\\b(?:forget|drop|remove)\\s+the\\s+rule\\b/i;\nconst STOPWORDS = new Set([\n \"the\",\n \"and\",\n \"for\",\n \"from\",\n \"now\",\n \"always\",\n \"never\",\n \"rule\",\n \"about\",\n \"longer\",\n \"don't\",\n \"anymore\",\n \"every\",\n \"must\",\n \"please\",\n \"with\",\n \"that\",\n \"this\",\n \"our\",\n \"you\",\n]);\n\nexport function extractUserRules(prompts: string[]): { rules: string[]; revocations: string[] } {\n const rules = new Map<string, string>();\n const revocations = new Map<string, string>();\n for (const prompt of prompts) {\n const own = (prompt.split(INJECTED_BLOCK)[0] ?? \"\")\n .replace(FENCED_CODE, \"\\n\")\n .replace(QUOTE_LINE, \"\");\n for (const raw of own.split(/(?<=[.!?])\\s+|\\n+/)) {\n const sentence = raw.trim();\n if (!sentence || sentence.length > MAX_RULE_CHARS || sentence.endsWith(\"?\")) continue;\n if (QUESTION_START.test(sentence)) continue;\n const key = sentence\n .toLowerCase()\n .replace(/\\s+/g, \" \")\n .replace(/[.!]+$/, \"\");\n if (REVOCATION_MARKER.test(sentence)) {\n if (!revocations.has(key)) revocations.set(key, sentence);\n } else if (isRule(sentence) && !SPECULATIVE.test(sentence)) {\n if (!rules.has(key)) rules.set(key, sentence);\n }\n }\n }\n return { rules: [...rules.values()], revocations: [...revocations.values()] };\n}\n\n/** A rule is explicitly introduced, or an imperative with at least a verb and an object. */\nfunction isRule(sentence: string): boolean {\n const rest = sentence.replace(RULE_PREFIX, \"\");\n if (rest !== sentence) return rest.split(/\\s+/).filter(Boolean).length >= 3;\n return IMPERATIVE.test(sentence);\n}\n\n/** Content words, crudely stemmed so \"running\"/\"run\" and \"committing\"/\"commit\" match. */\nexport function ruleWords(text: string): Set<string> {\n return new Set(\n (text.toLowerCase().match(/[a-z][a-z'-]+/g) ?? [])\n .filter((word) => word.length >= 3 && !STOPWORDS.has(word))\n .map((word) => word.replace(/(?:ing|ed|es|s)$/, \"\").replace(/([b-df-hj-np-tv-z])\\1$/, \"$1\")),\n );\n}\n\n/**\n * A revocation names a rule only when it repeats every content word of the\n * rule; anything looser goes to review instead of silently dropping a rule.\n */\nexport function revokes(revocation: string, rule: string): boolean {\n const ruleSet = ruleWords(rule);\n if (ruleSet.size === 0) return false;\n const words = ruleWords(revocation);\n return [...ruleSet].every((word) => words.has(word));\n}\n","import { appendFile, mkdir, readFile, stat, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\n\n/**\n * Local usage traces for `codebuddy dashboard`: one JSON line per MCP tool\n * call, prompt recall, capture and sync, in `.codebuddy/cache/traces.jsonl`\n * (gitignored, never leaves the machine). Recording is best-effort: it never\n * throws and never blocks a tool or hook on failure. `CODEBUDDY_TRACE=0`\n * turns it off. Token counts are cl100k estimates of the payload text.\n */\n\nexport type TraceKind = \"tool\" | \"recall\" | \"capture\" | \"sync\";\n\nexport type TraceEvent = {\n ts: string;\n kind: TraceKind;\n /** Tool name, or the hook step (`context`, `capture`, `sync`). */\n name: string;\n ms: number;\n ok: boolean;\n /** Estimated tokens the agent sent (tool arguments, prompt). */\n tokensIn?: number;\n /** Estimated tokens CodeBuddy returned or injected. */\n tokensOut?: number;\n session?: string;\n detail?: Record<string, string | number | boolean | string[]>;\n};\n\n/** Past this size the oldest half is dropped (~10k events). */\nconst MAX_BYTES = 4 * 1024 * 1024;\n\nexport function tracePath(repositoryRoot: string): string {\n return join(repositoryRoot, \".codebuddy\", \"cache\", \"traces.jsonl\");\n}\n\nexport async function recordTrace(\n repositoryRoot: string,\n event: Omit<TraceEvent, \"ts\"> & { ts?: string },\n): Promise<void> {\n if (process.env.CODEBUDDY_TRACE === \"0\") return;\n const path = tracePath(repositoryRoot);\n try {\n await mkdir(dirname(path), { recursive: true });\n await appendFile(path, `${JSON.stringify({ ts: new Date().toISOString(), ...event })}\\n`);\n if ((await stat(path)).size > MAX_BYTES) {\n const lines = (await readFile(path, \"utf8\")).split(\"\\n\").filter(Boolean);\n await writeFile(path, `${lines.slice(Math.floor(lines.length / 2)).join(\"\\n\")}\\n`);\n }\n } catch {\n // Tracing must never break a tool call or a hook.\n }\n}\n\n/** The newest `limit` events, oldest first. Malformed lines are skipped. */\nexport async function readTraces(repositoryRoot: string, limit = 2_000): Promise<TraceEvent[]> {\n let raw: string;\n try {\n raw = await readFile(tracePath(repositoryRoot), \"utf8\");\n } catch {\n return [];\n }\n return parseTraceLines(raw).slice(-limit);\n}\n\nexport function parseTraceLines(raw: string): TraceEvent[] {\n const events: TraceEvent[] = [];\n for (const line of raw.split(\"\\n\")) {\n if (!line.trim()) continue;\n try {\n const event = JSON.parse(line) as TraceEvent;\n if (typeof event.ts === \"string\" && typeof event.name === \"string\") events.push(event);\n } catch {\n // A torn write from a concurrent hook process; skip it.\n }\n }\n return events;\n}\n","import pTimeout from \"p-timeout\";\nimport type { ContextReranker, SemanticRelevanceRanker } from \"../context/engine.js\";\nimport { loadRuntimeConfig, readConfigFile } from \"../core/config-file.js\";\nimport type { RuntimeHandle } from \"../core/operations.js\";\nimport { DEFAULT_RERANK_MODELS } from \"../providers/models.js\";\n\n/**\n * The model side of per-prompt recall: dense evidence from PostgreSQL/pgvector,\n * the query embedded by the configured provider (local by default). Optional\n * and bounded: a slow or absent database or model leaves lexical recall intact.\n * `CODEBUDDY_SEMANTIC=0` turns it off (never connects to PostgreSQL).\n */\nexport type HookSemantics = {\n semanticRanker?: SemanticRelevanceRanker;\n reranker?: ContextReranker;\n close(): Promise<void>;\n};\n\n/** Connect + namespace lookup; a local PostgreSQL answers in milliseconds. */\nconst CONNECT_BUDGET_MS = 2_500;\n/** Query embedding + exact vector search (the first call also loads the model). */\nconst SEARCH_BUDGET_MS = 3_000;\nconst RERANK_BUDGET_MS = 2_000;\n\n/**\n * The cross-encoder chosen by `.codebuddy/config.json` `rerank` (off by\n * default). Hosted ones need OPENROUTER_API_KEY / HF_TOKEN; without a key\n * (or `CODEBUDDY_RERANK=0`) there is none and the fused order stands.\n */\nexport async function configuredReranker(\n repositoryRoot: string,\n): Promise<ContextReranker | undefined> {\n if (process.env.CODEBUDDY_RERANK === \"0\") return undefined;\n const file = await readConfigFile(repositoryRoot);\n const provider = file.rerank?.provider ?? \"off\";\n if (provider === \"off\") return undefined;\n const model = file.rerank?.model ?? DEFAULT_RERANK_MODELS[provider].id;\n const bounded = (scores: Promise<number[]>) =>\n pTimeout(scores, { milliseconds: RERANK_BUDGET_MS });\n if (provider === \"local\") {\n const revision =\n model === DEFAULT_RERANK_MODELS.local.id ? DEFAULT_RERANK_MODELS.local.revision : undefined;\n return async (task, documents) => {\n const { rerankLocally } = await import(\"../providers/local.js\");\n return bounded(\n rerankLocally({ id: model, ...(revision ? { revision } : {}) }, task, documents),\n );\n };\n }\n const apiKey =\n provider === \"openrouter\"\n ? process.env.OPENROUTER_API_KEY\n : (process.env.HF_TOKEN ?? file.provider?.apiKey);\n if (!apiKey) return undefined;\n const { rerankHuggingFace, rerankOpenRouter } = await import(\"../providers/cloud.js\");\n const call = provider === \"openrouter\" ? rerankOpenRouter : rerankHuggingFace;\n return (task, documents) => call({ apiKey, model, timeoutMs: RERANK_BUDGET_MS }, task, documents);\n}\n\nexport async function openHookSemantics(repositoryRoot: string): Promise<HookSemantics> {\n let runtime: Promise<RuntimeHandle | null> | null = null;\n const connect = async (): Promise<RuntimeHandle | null> => {\n const config = await loadRuntimeConfig(repositoryRoot, { requireDatabase: false });\n if (!config.postgresUrl) return null;\n const { createRuntime } = await import(\"../core/operations.js\");\n const opening = createRuntime(config, {\n repositoryRoot,\n startWorker: false,\n connectTimeoutSeconds: 2,\n });\n try {\n return await pTimeout(opening, { milliseconds: CONNECT_BUDGET_MS });\n } catch {\n // Too slow: release whatever eventually connects.\n void opening.then((handle) => handle.close()).catch(() => undefined);\n return null;\n }\n };\n\n const semanticRanker: SemanticRelevanceRanker | undefined =\n process.env.CODEBUDDY_SEMANTIC === \"0\"\n ? undefined\n : async (task, candidates) => {\n runtime ??= connect().catch(() => null);\n const handle = await runtime;\n if (!handle) return {};\n return handle.memory.rankContextFacts(\n task,\n candidates.map(({ id }) => id),\n { timeoutMs: SEARCH_BUDGET_MS },\n );\n };\n\n const reranker = await configuredReranker(repositoryRoot).catch(() => undefined);\n return {\n ...(semanticRanker ? { semanticRanker } : {}),\n ...(reranker ? { reranker } : {}),\n async close() {\n const handle = await runtime?.catch(() => null);\n await handle?.close().catch(() => undefined);\n },\n };\n}\n","import { mkdir, readFile, rename, rm, stat } from \"node:fs/promises\";\nimport { join, resolve } from \"node:path\";\nimport { writeAtomic } from \"../core/markdown-store-fs.js\";\n\n/**\n * Between the edit hook and the turn-end hook, CodeBuddy needs to remember which\n * files an agent actually changed. This staging store holds that set per session\n * under `.codebuddy/cache/hooks/` (rebuildable, local, gitignored). The turn-end\n * capture hook drains it, so capture works from the *real* change set rather\n * than a summary the model may or may not write.\n */\nexport class HookStagingStore {\n readonly directory: string;\n private operations = Promise.resolve();\n\n constructor(repositoryRoot = process.cwd()) {\n this.directory = join(resolve(repositoryRoot), \".codebuddy\", \"cache\", \"hooks\");\n }\n\n async add(sessionId: string, paths: string[]): Promise<void> {\n await this.serialize(async () => {\n const clean = paths.map(normalize).filter(Boolean);\n if (clean.length === 0) return;\n await mkdir(this.directory, { recursive: true, mode: 0o700 });\n await this.withFileLock(sessionId, async () => {\n const merged = [...new Set([...(await this.read(sessionId)), ...clean])].sort();\n await writeAtomic(\n this.filePath(sessionId),\n `${JSON.stringify({ paths: merged }, null, 2)}\\n`,\n );\n });\n });\n }\n\n async read(sessionId: string): Promise<string[]> {\n try {\n const parsed = JSON.parse(await readFile(this.filePath(sessionId), \"utf8\"));\n return Array.isArray(parsed?.paths)\n ? parsed.paths.filter((p: unknown) => typeof p === \"string\")\n : [];\n } catch {\n return [];\n }\n }\n\n /** Return the staged paths and clear them. */\n async drain(sessionId: string): Promise<string[]> {\n return this.serialize(async () => {\n await mkdir(this.directory, { recursive: true, mode: 0o700 });\n return this.withFileLock(sessionId, async () => {\n const path = this.filePath(sessionId);\n const draining = `${path}.${process.pid}.${Date.now()}.drain`;\n try {\n await rename(path, draining);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return [];\n throw error;\n }\n try {\n const parsed = JSON.parse(await readFile(draining, \"utf8\"));\n return Array.isArray(parsed?.paths)\n ? parsed.paths.filter((item: unknown) => typeof item === \"string\")\n : [];\n } finally {\n await rm(draining, { force: true });\n }\n });\n });\n }\n\n /** Claim a batch without consuming edits staged while capture runs. */\n async claim(sessionId: string): Promise<string[] | null> {\n await mkdir(this.directory, { recursive: true, mode: 0o700 });\n const captureLock = `${this.filePath(sessionId)}.capture-lock`;\n for (let attempt = 0; ; attempt++) {\n try {\n await mkdir(captureLock);\n break;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") throw error;\n const age =\n Date.now() - (await stat(captureLock).catch(() => ({ mtimeMs: Date.now() }))).mtimeMs;\n if (age > 60_000) {\n await rm(captureLock, { recursive: true, force: true });\n continue;\n }\n if (attempt >= 200) return null;\n await new Promise((resolveWait) => setTimeout(resolveWait, 10));\n }\n }\n try {\n return await this.withFileLock(sessionId, async () => {\n const claimed = this.claimPath(sessionId);\n try {\n return parsePaths(await readFile(claimed, \"utf8\"));\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n }\n try {\n await rename(this.filePath(sessionId), claimed);\n return parsePaths(await readFile(claimed, \"utf8\"));\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return [];\n throw error;\n }\n });\n } catch (error) {\n await rm(captureLock, { recursive: true, force: true });\n throw error;\n }\n }\n\n /** Acknowledge only the claimed batch; later edits remain staged. */\n async acknowledge(sessionId: string): Promise<void> {\n await this.withFileLock(sessionId, async () => {\n await rm(this.claimPath(sessionId), { force: true });\n });\n await rm(`${this.filePath(sessionId)}.capture-lock`, { recursive: true, force: true });\n }\n\n /** Restore the claimed batch for retry, merging edits that arrived during capture. */\n async rollback(sessionId: string): Promise<void> {\n await this.withFileLock(sessionId, async () => {\n const claimed = await readFile(this.claimPath(sessionId), \"utf8\")\n .then(parsePaths)\n .catch(() => []);\n const merged = [...new Set([...claimed, ...(await this.read(sessionId))])].sort();\n if (merged.length > 0)\n await writeAtomic(\n this.filePath(sessionId),\n `${JSON.stringify({ paths: merged }, null, 2)}\\n`,\n );\n await rm(this.claimPath(sessionId), { force: true });\n });\n await rm(`${this.filePath(sessionId)}.capture-lock`, { recursive: true, force: true });\n }\n\n private claimPath(sessionId: string): string {\n return `${this.filePath(sessionId)}.claimed`;\n }\n\n private async withFileLock<T>(sessionId: string, operation: () => Promise<T>): Promise<T> {\n const lock = `${this.filePath(sessionId)}.lock`;\n for (let attempt = 0; ; attempt++) {\n try {\n await mkdir(lock);\n break;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\" || attempt >= 200) throw error;\n await new Promise((resolveWait) => setTimeout(resolveWait, 10));\n }\n }\n try {\n return await operation();\n } finally {\n await rm(lock, { recursive: true, force: true });\n }\n }\n\n private async serialize<T>(operation: () => Promise<T>): Promise<T> {\n const previous = this.operations;\n let release!: () => void;\n this.operations = new Promise<void>((resolveOperation) => {\n release = resolveOperation;\n });\n await previous;\n try {\n return await operation();\n } finally {\n release();\n }\n }\n\n private filePath(sessionId: string): string {\n const safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, \"_\") || \"default\";\n return join(this.directory, `${safe}.json`);\n }\n}\n\nfunction normalize(path: string): string {\n return path.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\").trim();\n}\n\nfunction parsePaths(raw: string): string[] {\n const parsed = JSON.parse(raw);\n return Array.isArray(parsed?.paths)\n ? parsed.paths.filter((path: unknown): path is string => typeof path === \"string\")\n : [];\n}\n","import { constants } from \"node:fs\";\nimport { access } from \"node:fs/promises\";\nimport { extname, join, resolve } from \"node:path\";\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\"]);\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 *.test.* / *.spec.* sibling 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 return CODE_EXTENSIONS.has(extname(path).toLowerCase());\n}\n\nasync function hasSiblingTest(repositoryRoot: string, path: string): Promise<boolean> {\n const ext = extname(path);\n const base = path.slice(0, path.length - ext.length);\n const dir = base.includes(\"/\") ? base.slice(0, base.lastIndexOf(\"/\")) : \"\";\n const name = base.includes(\"/\") ? base.slice(base.lastIndexOf(\"/\") + 1) : base;\n const candidates = [\n `${base}.test${ext}`,\n `${base}.spec${ext}`,\n `${dir ? `${dir}/` : \"\"}__tests__/${name}${ext}`,\n `${dir ? `${dir}/` : \"\"}__tests__/${name}.test${ext}`,\n ];\n for (const candidate of candidates) {\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","/** 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 { VERSION } from \"../version.js\";\nimport { createLazyDatabase } from \"./database.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 const projectRoot = await resolveInitializedProjectRoot(\n options.config?.projectRoot ?? process.env.CODEBUDDY_PROJECT_ROOT,\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 const importMemory = async (memory: CodeBuddy) => {\n try {\n const result = await memory.reindexMemory();\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 });\n await importMemory(runtime.memory);\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 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\") await importMemory((await database.get()).memory);\n },\n });\n const server = new McpServer({ name: \"codebuddy\", version: VERSION });\n registerCodeBuddyTools(server, { config, database }, toolProfile);\n\n const shutdown = async () => {\n logger.info(\"codebuddy MCP server shutting down\");\n await server.close();\n await sync.close();\n await database.close();\n };\n let stopping: Promise<void> | undefined;\n const stop = () => {\n 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","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 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":["resolve","stat","resolve","readFile","join","parseYaml","z","spawn","relative","resolve","sep","resolve","normalizePath","relative","sep","runGit","spawn","z","createHash","createHash","readFile","join","resolve","createHash","mkdir","readdir","readFile","stat","dirname","join","relative","resolve","sep","parseYaml","stringifyYaml","z","z","resolve","join","normalizePath","createHash","dirname","mkdir","stringifyYaml","readFile","parseYaml","readdir","relative","sep","stat","LIMITS","resolve","fresh","join","neighbours","hit","readFile","readFile","relative","resolve","sep","pTimeout","createHash","resolve","z","z","incident","mkdir","readdir","readFile","rm","dirname","join","relative","resolve","sep","parseYaml","stringifyYaml","z","z","resolve","join","dirname","stringifyYaml","readFile","parseYaml","readdir","rm","mkdir","relative","sep","words","resolve","ref","createHash","mkdir","readFile","stat","dirname","join","createRuntime","mkdir","readFile","rename","rm","stat","join","resolve","join","resolve","normalize","mkdir","readFile","rename","rm","stat","resolve","createRuntime","pTimeout","relative","sep","readFile","join","resolve","resolve","resolveRelevantPlan","join","normalize","z","plannedFileSchema","plannedTestSchema","fsWatch","join","relative","resolve","sep","resolve","resolve","resolve","relative","sep","fsWatch","join","realpath","stat","isAbsolute","resolve","isAbsolute","resolve","realpath","stat"]}
|