compound-agent 1.0.0
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/CHANGELOG.md +412 -0
- package/LICENSE +21 -0
- package/README.md +331 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +5600 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +971 -0
- package/dist/index.js +1576 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp.d.ts +77 -0
- package/dist/mcp.js +1025 -0
- package/dist/mcp.js.map +1 -0
- package/dist/types--TsW4ZqX.d.ts +2601 -0
- package/package.json +80 -0
package/dist/mcp.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli-utils.ts","../src/memory/types.ts","../src/memory/storage/jsonl.ts","../src/memory/storage/sqlite/availability.ts","../src/memory/storage/sqlite/schema.ts","../src/memory/storage/sqlite/connection.ts","../src/memory/storage/sqlite/cache.ts","../src/memory/storage/sqlite/search.ts","../src/utils.ts","../src/memory/retrieval/session.ts","../src/compound/types.ts","../src/compound/io.ts","../src/memory/embeddings/model.ts","../src/memory/embeddings/nomic.ts","../src/memory/search/vector.ts","../src/memory/search/ranking.ts","../src/commands/management-prime.ts","../src/memory/capture/triggers.ts","../src/memory/capture/integration.ts","../src/rules/types.ts","../src/audit/types.ts","../src/index.ts","../src/mcp.ts"],"names":["require","join","dirname","createHash","z","readFile","getLlama","DEFAULT_LIMIT","SeveritySchema","createRequire"],"mappings":"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","file":"mcp.js","sourcesContent":["/**\n * CLI utility functions.\n *\n * Pure functions extracted from cli.ts for testability.\n */\n\n/**\n * Format bytes to human-readable string.\n *\n * @param bytes - Number of bytes\n * @returns Formatted string (e.g., \"1.5 KB\", \"2.0 MB\")\n */\nexport function formatBytes(bytes: number): string {\n if (bytes === 0) return '0 B';\n if (bytes < 1024) return `${bytes} B`;\n const kb = bytes / 1024;\n if (kb < 1024) return `${kb.toFixed(1)} KB`;\n const mb = kb / 1024;\n return `${mb.toFixed(1)} MB`;\n}\n\n/**\n * Parse limit option and validate it's a positive integer.\n *\n * @param value - String value from command option\n * @param name - Option name for error message\n * @returns Parsed integer\n * @throws Error if value is not a valid positive integer\n */\nexport function parseLimit(value: string, name: string): number {\n const parsed = parseInt(value, 10);\n if (Number.isNaN(parsed) || parsed <= 0) {\n throw new Error(`Invalid ${name}: must be a positive integer`);\n }\n return parsed;\n}\n\n/**\n * Get repository root from environment variable or current directory.\n *\n * @returns Repository root path for lesson storage\n */\nexport function getRepoRoot(): string {\n return process.env['COMPOUND_AGENT_ROOT'] ?? process.cwd();\n}\n","/**\n * Memory item type definitions using Zod schemas.\n *\n * Supports 4 memory item types via discriminated union:\n * - lesson: Knowledge learned from mistakes\n * - solution: Problem-resolution pairs\n * - pattern: Code pattern transformations (bad -> good)\n * - preference: User workflow preferences\n *\n * Deletion model:\n * - Set `deleted: true` and `deletedAt` on an item to mark it deleted\n * - LegacyTombstoneSchema handles backward-compat reads of old\n * minimal tombstone records { id, deleted: true, deletedAt }\n * - LegacyLessonSchema handles old quick/full type records\n */\n\nimport { createHash } from 'node:crypto';\nimport { z } from 'zod';\n\n// Source of lesson capture\nexport const SourceSchema = z.enum([\n 'user_correction',\n 'self_correction',\n 'test_failure',\n 'manual',\n]);\n\n// Context about when lesson was learned\nexport const ContextSchema = z.object({\n tool: z.string(),\n intent: z.string(),\n});\n\n// Code pattern (bad -> good)\nexport const PatternSchema = z.object({\n bad: z.string(),\n good: z.string(),\n});\n\n// Citation for lesson provenance tracking\nexport const CitationSchema = z.object({\n file: z.string().min(1), // Source file path (required, non-empty)\n line: z.number().int().positive().optional(), // Line number (optional, must be positive)\n commit: z.string().optional(), // Git commit hash (optional)\n});\n\n// Severity levels for lessons\nexport const SeveritySchema = z.enum(['high', 'medium', 'low']);\n\n// Compaction levels for age-based validity\nexport const CompactionLevelSchema = z.union([\n z.literal(0), // Active\n z.literal(1), // Flagged (>90 days)\n z.literal(2), // Archived\n]);\n\n/** @deprecated Use MemoryItemTypeSchema instead. Kept for parsing old JSONL records. */\nexport const LessonTypeSchema = z.enum(['quick', 'full']);\n\n/** Memory item type enum: lesson, solution, pattern, preference. */\nexport const MemoryItemTypeSchema = z.enum(['lesson', 'solution', 'pattern', 'preference']);\n\n// ---------------------------------------------------------------------------\n// Base fields shared by all memory item types\n// ---------------------------------------------------------------------------\n\nconst baseFields = {\n // Core identity (required)\n id: z.string(),\n trigger: z.string(),\n insight: z.string(),\n\n // Metadata (required)\n tags: z.array(z.string()),\n source: SourceSchema,\n context: ContextSchema,\n created: z.string(), // ISO8601\n confirmed: z.boolean(),\n\n // Relationships (required, can be empty arrays)\n supersedes: z.array(z.string()),\n related: z.array(z.string()),\n\n // Extended fields (optional)\n evidence: z.string().optional(),\n severity: SeveritySchema.optional(),\n\n // Lifecycle fields (optional)\n deleted: z.boolean().optional(),\n deletedAt: z.string().optional(),\n retrievalCount: z.number().optional(),\n\n // Provenance tracking (optional)\n citation: CitationSchema.optional(),\n\n // Age-based validity fields (optional)\n compactionLevel: CompactionLevelSchema.optional(),\n compactedAt: z.string().optional(),\n lastRetrieved: z.string().optional(),\n\n // Invalidation fields (optional)\n invalidatedAt: z.string().optional(),\n invalidationReason: z.string().optional(),\n} as const;\n\n// ---------------------------------------------------------------------------\n// Type-specific schemas\n// ---------------------------------------------------------------------------\n\n/**\n * Lesson memory item schema.\n * Replaces the old quick/full distinction with a single 'lesson' type.\n * Pattern field is optional for lessons.\n */\nexport const LessonItemSchema = z.object({\n ...baseFields,\n type: z.literal('lesson'),\n pattern: PatternSchema.optional(),\n});\n\n/**\n * Solution memory item schema.\n * Uses trigger as \"problem\" and insight as \"resolution\".\n * Pattern field is optional.\n */\nexport const SolutionItemSchema = z.object({\n ...baseFields,\n type: z.literal('solution'),\n pattern: PatternSchema.optional(),\n});\n\n/**\n * Pattern memory item schema.\n * Pattern field is REQUIRED (bad -> good code transformation).\n */\nexport const PatternItemSchema = z.object({\n ...baseFields,\n type: z.literal('pattern'),\n pattern: PatternSchema,\n});\n\n/**\n * Preference memory item schema.\n * Captures user workflow preferences.\n * Pattern field is optional.\n */\nexport const PreferenceItemSchema = z.object({\n ...baseFields,\n type: z.literal('preference'),\n pattern: PatternSchema.optional(),\n});\n\n// ---------------------------------------------------------------------------\n// Discriminated union of all memory item types\n// ---------------------------------------------------------------------------\n\n/**\n * Unified memory item schema (discriminated union on 'type' field).\n * Accepts: lesson, solution, pattern, preference.\n */\nexport const MemoryItemSchema = z.discriminatedUnion('type', [\n LessonItemSchema,\n SolutionItemSchema,\n PatternItemSchema,\n PreferenceItemSchema,\n]);\n\n// ---------------------------------------------------------------------------\n// Backward compatibility\n// ---------------------------------------------------------------------------\n\n/**\n * Legacy lesson schema for reading old JSONL records with type: 'quick' | 'full'.\n * Use this only for parsing existing data files; new records use MemoryItemSchema.\n */\nexport const LegacyLessonSchema = z.object({\n ...baseFields,\n type: LessonTypeSchema,\n pattern: PatternSchema.optional(),\n});\n\n/**\n * LessonSchema - now equivalent to LessonItemSchema.\n *\n * For backward compatibility, existing code that imports LessonSchema\n * continues to work. The type field is now z.literal('lesson').\n *\n * To parse old quick/full records, use LegacyLessonSchema.\n */\nexport const LessonSchema = LessonItemSchema;\n\n/**\n * Legacy tombstone format for backward-compatible reads.\n * Old JSONL files may contain minimal { id, deleted, deletedAt } records.\n */\nexport const LegacyTombstoneSchema = z.object({\n id: z.string(),\n deleted: z.literal(true),\n deletedAt: z.string(), // ISO8601\n});\n\n/**\n * LessonRecord schema - union for reading JSONL files.\n *\n * Accepts:\n * 1. Any new memory item type (lesson, solution, pattern, preference)\n * 2. A legacy lesson (type: 'quick' | 'full')\n * 3. A legacy tombstone (minimal: { id, deleted: true, deletedAt })\n */\nexport const LessonRecordSchema = z.union([\n MemoryItemSchema,\n LegacyLessonSchema,\n LegacyTombstoneSchema,\n]);\n\n/**\n * MemoryItemRecord schema - alias for LessonRecordSchema.\n * Parses all memory item types plus legacy formats.\n */\nexport const MemoryItemRecordSchema = LessonRecordSchema;\n\n// ---------------------------------------------------------------------------\n// Type exports\n// ---------------------------------------------------------------------------\n\nexport type Lesson = z.infer<typeof LessonSchema>;\n/** @deprecated Use MemoryItemType instead. */\nexport type LessonType = z.infer<typeof LessonTypeSchema>;\nexport type LessonRecord = z.infer<typeof LessonRecordSchema>;\nexport type Source = z.infer<typeof SourceSchema>;\nexport type Severity = z.infer<typeof SeveritySchema>;\nexport type Context = z.infer<typeof ContextSchema>;\nexport type Pattern = z.infer<typeof PatternSchema>;\nexport type Citation = z.infer<typeof CitationSchema>;\nexport type CompactionLevel = z.infer<typeof CompactionLevelSchema>;\n\n/** Unified memory item type (discriminated union). */\nexport type MemoryItem = z.infer<typeof MemoryItemSchema>;\n/** Memory item type enum: 'lesson' | 'solution' | 'pattern' | 'preference'. */\nexport type MemoryItemType = z.infer<typeof MemoryItemTypeSchema>;\n/** Solution memory item. */\nexport type Solution = z.infer<typeof SolutionItemSchema>;\n/** Pattern memory item (not to be confused with Pattern = {bad, good}). */\nexport type PatternItem = z.infer<typeof PatternItemSchema>;\n/** Preference memory item. */\nexport type Preference = z.infer<typeof PreferenceItemSchema>;\n/** Record type for reading JSONL files (all types + legacy). */\nexport type MemoryItemRecord = z.infer<typeof MemoryItemRecordSchema>;\n\n// ---------------------------------------------------------------------------\n// ID generation\n// ---------------------------------------------------------------------------\n\n/** Prefix mapping for memory item types. */\nconst TYPE_PREFIXES: Record<MemoryItemType, string> = {\n lesson: 'L',\n solution: 'S',\n pattern: 'P',\n preference: 'R',\n};\n\n/**\n * Generate deterministic memory item ID from insight text.\n * Format: {prefix} + 8 hex characters from SHA-256 hash.\n *\n * @param insight - The insight text to hash\n * @param type - Memory item type (default: 'lesson' for backward compat)\n * @returns ID string like L1a2b3c4d, S1a2b3c4d, P1a2b3c4d, or R1a2b3c4d\n */\nexport function generateId(insight: string, type?: MemoryItemType): string {\n const prefix = TYPE_PREFIXES[type ?? 'lesson'];\n const hash = createHash('sha256').update(insight).digest('hex');\n return `${prefix}${hash.slice(0, 8)}`;\n}\n","/**\n * JSONL storage layer for memory items\n *\n * Append-only storage with last-write-wins deduplication.\n * Source of truth - git trackable.\n *\n * Primary API:\n * appendMemoryItem() - Append any memory item type\n * readMemoryItems() - Read all non-deleted memory items\n *\n * Backward-compatible API:\n * appendLesson() - Append a lesson (delegates to appendMemoryItem)\n * readLessons() - Read lesson-type items only\n *\n * Deletion: append the item with `deleted: true` and `deletedAt`.\n * Read path also accepts old minimal tombstone records for backward compat.\n * Legacy type:'quick'/'full' records are converted to type:'lesson' on read.\n */\n\nimport { appendFile, mkdir, readFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport {\n MemoryItemRecordSchema,\n type Lesson,\n type LessonRecord,\n type MemoryItem,\n} from '../types.js';\n\n/** Relative path to lessons file from repo root */\nexport const LESSONS_PATH = '.claude/lessons/index.jsonl';\n\n/** Options for reading memory items */\nexport interface ReadLessonsOptions {\n /** If true, throw on first parse error. Default: false (skip errors) */\n strict?: boolean;\n /** Callback for each parse error in non-strict mode */\n onParseError?: (error: ParseError) => void;\n}\n\n/** Parse error details */\nexport interface ParseError {\n /** 1-based line number */\n line: number;\n /** Error message */\n message: string;\n /** Original error */\n cause: unknown;\n}\n\n/** Result of reading lessons (backward-compat) */\nexport interface ReadLessonsResult {\n /** Successfully parsed lessons */\n lessons: Lesson[];\n /** Number of lines skipped due to errors */\n skippedCount: number;\n}\n\n/** Result of reading memory items */\nexport interface ReadMemoryItemsResult {\n /** Successfully parsed memory items */\n items: MemoryItem[];\n /** Number of lines skipped due to errors */\n skippedCount: number;\n}\n\n\n/**\n * Append a memory item to the JSONL file.\n * Creates directory structure if missing.\n * Primary write function for all memory item types.\n *\n * @param repoRoot - Repository root directory\n * @param item - Memory item to append (any type: lesson, solution, pattern, preference)\n */\nexport async function appendMemoryItem(repoRoot: string, item: MemoryItem): Promise<void> {\n const filePath = join(repoRoot, LESSONS_PATH);\n await mkdir(dirname(filePath), { recursive: true });\n\n const line = JSON.stringify(item) + '\\n';\n await appendFile(filePath, line, 'utf-8');\n}\n\n/**\n * Append a lesson to the JSONL file.\n * Backward-compatible wrapper around appendMemoryItem.\n *\n * @param repoRoot - Repository root directory\n * @param lesson - Lesson to append\n */\nexport async function appendLesson(repoRoot: string, lesson: Lesson): Promise<void> {\n return appendMemoryItem(repoRoot, lesson);\n}\n\n/**\n * Parse and validate a single JSON line.\n *\n * Accepts:\n * - New memory item types (lesson, solution, pattern, preference)\n * - Legacy lessons (type: 'quick' | 'full')\n * - Canonical tombstones ({ id, deleted: true, deletedAt })\n * - Legacy tombstones (full record with deleted:true)\n *\n * @returns Parsed record or null if invalid\n */\nfunction parseJsonLine(\n line: string,\n lineNumber: number,\n strict: boolean,\n onParseError?: (error: ParseError) => void\n): LessonRecord | null {\n // Try to parse JSON\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch (err) {\n const parseError: ParseError = {\n line: lineNumber,\n message: `Invalid JSON: ${(err as Error).message}`,\n cause: err,\n };\n if (strict) {\n throw new Error(`Parse error on line ${lineNumber}: ${parseError.message}`);\n }\n onParseError?.(parseError);\n return null;\n }\n\n // Validate against MemoryItemRecordSchema (accepts all types + legacy)\n const result = MemoryItemRecordSchema.safeParse(parsed);\n if (!result.success) {\n const parseError: ParseError = {\n line: lineNumber,\n message: `Schema validation failed: ${result.error.message}`,\n cause: result.error,\n };\n if (strict) {\n throw new Error(`Parse error on line ${lineNumber}: ${parseError.message}`);\n }\n onParseError?.(parseError);\n return null;\n }\n\n return result.data;\n}\n\n/**\n * Convert a parsed record to a MemoryItem.\n * Legacy type:'quick'/'full' records are converted to type:'lesson'.\n * Returns null for tombstone-only records (no MemoryItem data).\n */\nfunction toMemoryItem(record: LessonRecord): MemoryItem | null {\n // Tombstone records that are minimal (no type field) cannot be converted\n if (record.deleted === true) {\n return null;\n }\n\n // Legacy type conversion: quick/full -> lesson\n if (record.type === 'quick' || record.type === 'full') {\n return { ...record, type: 'lesson' } as MemoryItem;\n }\n\n // Already a valid MemoryItem type\n return record as MemoryItem;\n}\n\n/**\n * Read all non-deleted memory items from the JSONL file.\n * Primary read function for the unified memory API.\n *\n * Applies last-write-wins deduplication by ID.\n * Converts legacy type:'quick'/'full' to type:'lesson'.\n *\n * Handles tombstone formats:\n * - Canonical: { id, deleted: true, deletedAt }\n * - Legacy: Full record with deleted:true field\n *\n * @param repoRoot - Repository root directory\n * @param options - Optional settings for error handling\n * @returns Result with items array and count of skipped lines\n */\nexport async function readMemoryItems(\n repoRoot: string,\n options: ReadLessonsOptions = {}\n): Promise<ReadMemoryItemsResult> {\n const { strict = false, onParseError } = options;\n const filePath = join(repoRoot, LESSONS_PATH);\n\n let content: string;\n try {\n content = await readFile(filePath, 'utf-8');\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n return { items: [], skippedCount: 0 };\n }\n throw err;\n }\n\n const items = new Map<string, MemoryItem>();\n let skippedCount = 0;\n\n const lines = content.split('\\n');\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i]!.trim();\n if (!trimmed) continue;\n\n const record = parseJsonLine(trimmed, i + 1, strict, onParseError);\n if (!record) {\n skippedCount++;\n continue;\n }\n\n // Check if record is a tombstone (canonical or legacy)\n if (record.deleted === true) {\n items.delete(record.id);\n } else {\n const item = toMemoryItem(record);\n if (item) {\n items.set(record.id, item);\n }\n }\n }\n\n return { items: Array.from(items.values()), skippedCount };\n}\n\n/**\n * Read all non-deleted lessons from the JSONL file.\n * Backward-compatible wrapper that filters to lesson-type items only.\n *\n * @param repoRoot - Repository root directory\n * @param options - Optional settings for error handling\n * @returns Result with lessons array and count of skipped lines\n */\nexport async function readLessons(\n repoRoot: string,\n options: ReadLessonsOptions = {}\n): Promise<ReadLessonsResult> {\n const result = await readMemoryItems(repoRoot, options);\n\n // Filter to lesson-type items only\n const lessons = result.items.filter((item): item is Lesson => item.type === 'lesson');\n\n return { lessons, skippedCount: result.skippedCount };\n}\n","/**\n * SQLite availability check.\n *\n * Verifies that better-sqlite3 can be loaded. If it cannot, an error\n * is thrown -- there is no silent fallback to JSONL-only mode.\n */\n\nimport { createRequire } from 'node:module';\nimport type { Database as DatabaseType } from 'better-sqlite3';\n\n// Create require function for ESM compatibility\nconst require = createRequire(import.meta.url);\n\n/** Cached availability state */\nlet checked = false;\nlet DatabaseConstructor: (new (path: string) => DatabaseType) | null = null;\n\n/**\n * Ensure SQLite (better-sqlite3) is loadable.\n * Throws a clear error if the native module cannot be loaded.\n */\nexport function ensureSqliteAvailable(): void {\n if (checked) return;\n\n try {\n const module = require('better-sqlite3');\n const Constructor = module.default || module;\n const testDb = new Constructor(':memory:');\n testDb.close();\n DatabaseConstructor = Constructor;\n checked = true;\n } catch (cause) {\n throw new Error(\n 'better-sqlite3 failed to load.\\n' +\n 'If using pnpm, add to your project\\'s package.json:\\n' +\n ' \"pnpm\": { \"onlyBuiltDependencies\": [\"better-sqlite3\"] }\\n' +\n 'Then run: pnpm install && pnpm rebuild better-sqlite3\\n' +\n 'For npm/yarn, run: npm rebuild better-sqlite3',\n { cause }\n );\n }\n}\n\n/**\n * Get the SQLite Database constructor.\n * @returns Database constructor (never null -- throws if unavailable)\n */\nexport function getDatabaseConstructor(): new (path: string) => DatabaseType {\n ensureSqliteAvailable();\n return DatabaseConstructor!;\n}\n","/**\n * SQLite schema definition for lessons database.\n *\n * The SQLite database is a rebuildable cache (JSONL is source of truth).\n * When SCHEMA_VERSION changes, the DB file is deleted and recreated.\n */\n\nimport type { Database as DatabaseType } from 'better-sqlite3';\n\n/**\n * Schema version for the SQLite cache.\n * Bump this when making incompatible schema changes.\n * The connection module auto-rebuilds when the DB version is older.\n */\nexport const SCHEMA_VERSION = 3;\n\n/** SQL schema for lessons database with FTS5 full-text search */\nconst SCHEMA_SQL = `\n CREATE TABLE IF NOT EXISTS lessons (\n id TEXT PRIMARY KEY,\n type TEXT NOT NULL,\n trigger TEXT NOT NULL,\n insight TEXT NOT NULL,\n evidence TEXT,\n severity TEXT,\n tags TEXT NOT NULL DEFAULT '',\n source TEXT NOT NULL,\n context TEXT NOT NULL DEFAULT '{}',\n supersedes TEXT NOT NULL DEFAULT '[]',\n related TEXT NOT NULL DEFAULT '[]',\n created TEXT NOT NULL,\n confirmed INTEGER NOT NULL DEFAULT 0,\n deleted INTEGER NOT NULL DEFAULT 0,\n retrieval_count INTEGER NOT NULL DEFAULT 0,\n last_retrieved TEXT,\n embedding BLOB,\n content_hash TEXT,\n invalidated_at TEXT,\n invalidation_reason TEXT,\n citation_file TEXT,\n citation_line INTEGER,\n citation_commit TEXT,\n compaction_level INTEGER DEFAULT 0,\n compacted_at TEXT,\n pattern_bad TEXT,\n pattern_good TEXT\n );\n\n CREATE VIRTUAL TABLE IF NOT EXISTS lessons_fts USING fts5(\n id, trigger, insight, tags, pattern_bad, pattern_good,\n content='lessons', content_rowid='rowid'\n );\n\n CREATE TRIGGER IF NOT EXISTS lessons_ai AFTER INSERT ON lessons BEGIN\n INSERT INTO lessons_fts(rowid, id, trigger, insight, tags, pattern_bad, pattern_good)\n VALUES (new.rowid, new.id, new.trigger, new.insight, new.tags, new.pattern_bad, new.pattern_good);\n END;\n\n CREATE TRIGGER IF NOT EXISTS lessons_ad AFTER DELETE ON lessons BEGIN\n INSERT INTO lessons_fts(lessons_fts, rowid, id, trigger, insight, tags, pattern_bad, pattern_good)\n VALUES ('delete', old.rowid, old.id, old.trigger, old.insight, old.tags, old.pattern_bad, old.pattern_good);\n END;\n\n CREATE TRIGGER IF NOT EXISTS lessons_au AFTER UPDATE ON lessons BEGIN\n INSERT INTO lessons_fts(lessons_fts, rowid, id, trigger, insight, tags, pattern_bad, pattern_good)\n VALUES ('delete', old.rowid, old.id, old.trigger, old.insight, old.tags, old.pattern_bad, old.pattern_good);\n INSERT INTO lessons_fts(rowid, id, trigger, insight, tags, pattern_bad, pattern_good)\n VALUES (new.rowid, new.id, new.trigger, new.insight, new.tags, new.pattern_bad, new.pattern_good);\n END;\n\n CREATE INDEX IF NOT EXISTS idx_lessons_created ON lessons(created);\n CREATE INDEX IF NOT EXISTS idx_lessons_confirmed ON lessons(confirmed);\n CREATE INDEX IF NOT EXISTS idx_lessons_severity ON lessons(severity);\n CREATE INDEX IF NOT EXISTS idx_lessons_type ON lessons(type);\n\n CREATE TABLE IF NOT EXISTS metadata (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n );\n`;\n\n/**\n * Create the database schema and set the version pragma.\n * @param database - SQLite database instance\n */\nexport function createSchema(database: DatabaseType): void {\n database.exec(SCHEMA_SQL);\n database.pragma(`user_version = ${SCHEMA_VERSION}`);\n}\n","/**\n * SQLite database connection management.\n */\n\nimport { mkdirSync, unlinkSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport type { Database as DatabaseType } from 'better-sqlite3';\n\nimport type { DbOptions } from './types.js';\nimport { getDatabaseConstructor } from './availability.js';\nimport { createSchema, SCHEMA_VERSION } from './schema.js';\n\n/** Relative path to database file from repo root */\nexport const DB_PATH = '.claude/.cache/lessons.sqlite';\n\n/** Database connections keyed by resolved DB path */\nconst dbMap = new Map<string, DatabaseType>();\n/** Last opened DB path for backward-compat getDb() */\nlet lastDbPath: string | null = null;\n\n/**\n * Check if the database has the expected schema version.\n * @param database - SQLite database instance\n * @returns true if the version matches SCHEMA_VERSION\n */\nfunction hasExpectedVersion(database: DatabaseType): boolean {\n const row = database.pragma('user_version', { simple: true }) as number;\n return row === SCHEMA_VERSION;\n}\n\n/**\n * Open the SQLite database connection.\n * If the database has an older schema version, it is deleted and recreated.\n * Throws if better-sqlite3 cannot be loaded.\n * @param repoRoot - Absolute path to repository root\n * @param options - Database options (e.g., inMemory for testing)\n * @returns Database instance\n */\nexport function openDb(repoRoot: string, options: DbOptions = {}): DatabaseType {\n const { inMemory = false } = options;\n\n // In-memory DBs are keyed by repoRoot so different repos stay isolated\n const key = inMemory ? `:memory:${repoRoot}` : join(repoRoot, DB_PATH);\n\n const cached = dbMap.get(key);\n if (cached) {\n lastDbPath = key;\n return cached;\n }\n\n const Database = getDatabaseConstructor();\n let database: DatabaseType;\n\n if (inMemory) {\n database = new Database(':memory:');\n } else {\n const dir = dirname(key);\n mkdirSync(dir, { recursive: true });\n database = new Database(key);\n\n if (!hasExpectedVersion(database)) {\n database.close();\n unlinkSync(key);\n database = new Database(key);\n }\n\n database.pragma('journal_mode = WAL');\n }\n\n createSchema(database);\n dbMap.set(key, database);\n lastDbPath = key;\n return database;\n}\n\n/**\n * Close the SQLite database connection.\n */\nexport function closeDb(): void {\n for (const database of dbMap.values()) {\n database.close();\n }\n dbMap.clear();\n lastDbPath = null;\n}\n\n/**\n * Get the current database instance (for internal use).\n * @deprecated Prefer openDb(repoRoot) for explicit repo-scoped access.\n * @returns Current database instance or null\n */\nexport function getDb(): DatabaseType | null {\n if (!lastDbPath) return null;\n return dbMap.get(lastDbPath) ?? null;\n}\n","/**\n * Embedding cache operations for SQLite storage.\n */\n\nimport { createHash } from 'node:crypto';\nimport type { Database as DatabaseType } from 'better-sqlite3';\n\nimport type { CachedEmbeddingData } from './types.js';\nimport { openDb } from './connection.js';\n\n/**\n * Compute content hash for a lesson's trigger and insight.\n * Used to detect content changes for embedding cache invalidation.\n * @param trigger - The lesson trigger text\n * @param insight - The lesson insight text\n * @returns SHA-256 hash of the combined content\n */\nexport function contentHash(trigger: string, insight: string): string {\n return createHash('sha256').update(`${trigger} ${insight}`).digest('hex');\n}\n\n/**\n * Get cached embedding for a lesson.\n * @param repoRoot - Absolute path to repository root\n * @param lessonId - ID of the lesson\n * @param expectedHash - Optional content hash to validate cache freshness\n * @returns Embedding array or null if not cached\n */\nexport function getCachedEmbedding(\n repoRoot: string,\n lessonId: string,\n expectedHash?: string\n): number[] | null {\n const database = openDb(repoRoot);\n\n const row = database\n .prepare('SELECT embedding, content_hash FROM lessons WHERE id = ?')\n .get(lessonId) as { embedding: Buffer | null; content_hash: string | null } | undefined;\n\n if (!row || !row.embedding || !row.content_hash) {\n return null;\n }\n\n if (expectedHash && row.content_hash !== expectedHash) {\n return null;\n }\n\n const float32 = new Float32Array(\n row.embedding.buffer,\n row.embedding.byteOffset,\n row.embedding.byteLength / 4\n );\n return Array.from(float32);\n}\n\n/**\n * Cache embedding for a lesson in SQLite.\n *\n * Uses UPDATE-only (not INSERT) — the row must already exist in the\n * lessons table. If the row hasn't been synced from JSONL yet, the\n * write is a silent no-op and the embedding will be recomputed on\n * next access. This is by-design: the cache is an optional\n * optimization, not the source of truth.\n *\n * @param repoRoot - Absolute path to repository root\n * @param lessonId - ID of the lesson\n * @param embedding - Embedding vector (Float32Array or number array)\n * @param hash - Content hash for cache validation\n */\nexport function setCachedEmbedding(\n repoRoot: string,\n lessonId: string,\n embedding: Float32Array | number[],\n hash: string\n): void {\n const database = openDb(repoRoot);\n\n const float32 = embedding instanceof Float32Array ? embedding : new Float32Array(embedding);\n const buffer = Buffer.from(float32.buffer, float32.byteOffset, float32.byteLength);\n\n database\n .prepare('UPDATE lessons SET embedding = ?, content_hash = ? WHERE id = ?')\n .run(buffer, hash, lessonId);\n}\n\n/**\n * Collect all cached embeddings from the database.\n * Used during index rebuild to preserve valid caches.\n * @param database - SQLite database instance\n * @returns Map of lesson ID to cached embedding data\n */\nexport function collectCachedEmbeddings(database: DatabaseType): Map<string, CachedEmbeddingData> {\n const cache = new Map<string, CachedEmbeddingData>();\n const rows = database\n .prepare('SELECT id, embedding, content_hash FROM lessons WHERE embedding IS NOT NULL')\n .all() as Array<{ id: string; embedding: Buffer; content_hash: string | null }>;\n\n for (const row of rows) {\n if (row.embedding && row.content_hash) {\n cache.set(row.id, { embedding: row.embedding, contentHash: row.content_hash });\n }\n }\n return cache;\n}\n","/**\n * SQLite search operations using FTS5 full-text search.\n */\n\nimport { MemoryItemSchema } from '../../types.js';\nimport type { MemoryItem, MemoryItemType } from '../../types.js';\n\nimport type { MemoryItemRow, RetrievalStat } from './types.js';\nimport { openDb } from './connection.js';\n\n/**\n * Convert a database row to a MemoryItem object.\n * @param row - Database row\n * @returns MemoryItem object\n */\nfunction rowToMemoryItem(row: MemoryItemRow): MemoryItem | null {\n const item = {\n id: row.id,\n type: row.type,\n trigger: row.trigger,\n insight: row.insight,\n tags: row.tags ? row.tags.split(',').filter(Boolean) : [],\n source: row.source,\n context: JSON.parse(row.context),\n supersedes: JSON.parse(row.supersedes),\n related: JSON.parse(row.related),\n created: row.created,\n confirmed: row.confirmed === 1,\n } as Record<string, unknown>;\n\n if (row.evidence !== null) item.evidence = row.evidence;\n if (row.severity !== null) item.severity = row.severity;\n if (row.deleted === 1) item.deleted = true;\n if (row.retrieval_count > 0) item.retrievalCount = row.retrieval_count;\n if (row.invalidated_at !== null) item.invalidatedAt = row.invalidated_at;\n if (row.invalidation_reason !== null) item.invalidationReason = row.invalidation_reason;\n if (row.citation_file !== null) {\n item.citation = {\n file: row.citation_file,\n ...(row.citation_line !== null && { line: row.citation_line }),\n ...(row.citation_commit !== null && { commit: row.citation_commit }),\n };\n }\n if (row.compaction_level !== null && row.compaction_level !== 0) {\n item.compactionLevel = row.compaction_level;\n }\n if (row.compacted_at !== null) item.compactedAt = row.compacted_at;\n if (row.last_retrieved !== null) item.lastRetrieved = row.last_retrieved;\n if (row.pattern_bad !== null && row.pattern_good !== null) {\n item.pattern = { bad: row.pattern_bad, good: row.pattern_good };\n }\n\n const result = MemoryItemSchema.safeParse(item);\n if (!result.success) return null;\n return result.data;\n}\n\n\n/** FTS5 operator tokens to remove */\nconst FTS_OPERATORS = new Set(['AND', 'OR', 'NOT', 'NEAR']);\n\n/**\n * Sanitize a query string for safe use with FTS5 MATCH.\n * Strips special FTS5 syntax characters and operators.\n * @param query - Raw user query\n * @returns Sanitized query safe for FTS5\n */\nexport function sanitizeFtsQuery(query: string): string {\n // Strip FTS5 special chars: \" * ^ - +\n const stripped = query.replace(/[\"*^+-]/g, '');\n // Tokenize by whitespace, remove FTS operators, filter empty\n const tokens = stripped\n .split(/\\s+/)\n .filter((t) => t.length > 0 && !FTS_OPERATORS.has(t));\n return tokens.join(' ');\n}\n\n/**\n * Increment retrieval count for lessons.\n * @param repoRoot - Absolute path to repository root\n * @param lessonIds - IDs of retrieved lessons\n */\nexport function incrementRetrievalCount(repoRoot: string, lessonIds: string[]): void {\n if (lessonIds.length === 0) return;\n\n const database = openDb(repoRoot);\n\n const now = new Date().toISOString();\n\n const update = database.prepare(`\n UPDATE lessons\n SET retrieval_count = retrieval_count + 1,\n last_retrieved = ?\n WHERE id = ?\n `);\n\n const updateMany = database.transaction((ids: string[]) => {\n for (const id of ids) {\n update.run(now, id);\n }\n });\n\n updateMany(lessonIds);\n}\n\n/**\n * Search lessons using FTS5 full-text search.\n * @param repoRoot - Absolute path to repository root\n * @param query - FTS5 query string\n * @param limit - Maximum number of results\n * @param typeFilter - Optional memory item type to filter by\n * @returns Matching lessons\n */\nexport async function searchKeyword(\n repoRoot: string,\n query: string,\n limit: number,\n typeFilter?: MemoryItemType\n): Promise<MemoryItem[]> {\n const database = openDb(repoRoot);\n\n const countResult = database.prepare('SELECT COUNT(*) as cnt FROM lessons').get() as {\n cnt: number;\n };\n if (countResult.cnt === 0) return [];\n\n const sanitized = sanitizeFtsQuery(query);\n if (sanitized === '') return [];\n\n try {\n if (typeFilter) {\n const rows = database\n .prepare(\n `\n SELECT l.*\n FROM lessons l\n JOIN lessons_fts fts ON l.rowid = fts.rowid\n WHERE lessons_fts MATCH ?\n AND l.invalidated_at IS NULL\n AND l.type = ?\n LIMIT ?\n `\n )\n .all(sanitized, typeFilter, limit) as MemoryItemRow[];\n return rows.map(rowToMemoryItem).filter((x): x is MemoryItem => x !== null);\n }\n\n const rows = database\n .prepare(\n `\n SELECT l.*\n FROM lessons l\n JOIN lessons_fts fts ON l.rowid = fts.rowid\n WHERE lessons_fts MATCH ?\n AND l.invalidated_at IS NULL\n LIMIT ?\n `\n )\n .all(sanitized, limit) as MemoryItemRow[];\n\n return rows.map(rowToMemoryItem).filter((x): x is MemoryItem => x !== null);\n } catch (err) {\n // Log for debugging — sanitization should prevent most FTS5 errors,\n // but real issues (e.g. DB corruption) should not be fully silent\n const message = err instanceof Error ? err.message : 'Unknown FTS5 error';\n console.error(`[compound-agent] search error: ${message}`);\n return [];\n }\n}\n\n/**\n * Get retrieval statistics for all lessons.\n * @param repoRoot - Absolute path to repository root\n * @returns Array of retrieval statistics\n */\nexport function getRetrievalStats(repoRoot: string): RetrievalStat[] {\n const database = openDb(repoRoot);\n\n const rows = database\n .prepare('SELECT id, retrieval_count, last_retrieved FROM lessons')\n .all() as Array<{ id: string; retrieval_count: number; last_retrieved: string | null }>;\n\n return rows.map((row) => ({\n id: row.id,\n count: row.retrieval_count,\n lastRetrieved: row.last_retrieved,\n }));\n}\n","/**\n * Shared utility functions for the Learning Agent.\n */\n\n/** Milliseconds per day for time calculations */\nexport const MS_PER_DAY = 24 * 60 * 60 * 1000;\n\n/**\n * Calculate the age of a lesson in days from its created date.\n *\n * @param lesson - Object with a created field (ISO8601 string)\n * @returns Age in days (integer, rounded down)\n */\nexport function getLessonAgeDays(lesson: { created: string }): number {\n const created = new Date(lesson.created).getTime();\n const now = Date.now();\n return Math.floor((now - created) / MS_PER_DAY);\n}\n","/**\n * Session-start lesson retrieval\n *\n * Loads high-severity lessons at the start of a session.\n * No vector search - just filter by severity and recency.\n */\n\nimport { incrementRetrievalCount, readMemoryItems } from '../storage/index.js';\nimport type { MemoryItem, Severity } from '../types.js';\n\n/** Default number of lessons to load at session start */\nconst DEFAULT_LIMIT = 5;\n\n/** A memory item with severity field present */\ntype LessonWithSeverity = MemoryItem & { severity: Severity };\n\n/**\n * Type guard to check if a memory item has severity set\n */\nfunction hasSeverity(item: MemoryItem): item is MemoryItem & { severity: Severity } {\n return item.severity !== undefined;\n}\n\n/**\n * Load high-severity lessons for session start.\n *\n * Returns confirmed, high-severity lessons sorted by recency.\n * These are the most important lessons to surface at the start\n * of a coding session.\n *\n * @param repoRoot - Repository root directory\n * @param limit - Maximum number of lessons to return (default: 5)\n * @returns Array of high-severity lessons, most recent first\n */\nexport async function loadSessionLessons(\n repoRoot: string,\n limit: number = DEFAULT_LIMIT\n): Promise<LessonWithSeverity[]> {\n const { items } = await readMemoryItems(repoRoot);\n\n // Filter for high-severity, confirmed items of any type (excluding invalidated)\n const highSeverityLessons = items.filter(\n (item): item is MemoryItem & { severity: Severity } =>\n hasSeverity(item) &&\n item.severity === 'high' &&\n item.confirmed &&\n !item.invalidatedAt\n );\n\n // Sort by recency (most recent first)\n highSeverityLessons.sort((a, b) => {\n const dateA = new Date(a.created).getTime();\n const dateB = new Date(b.created).getTime();\n return dateB - dateA;\n });\n\n // Return top N and track surfaced lessons as retrieved.\n const topLessons = highSeverityLessons.slice(0, limit);\n if (topLessons.length > 0) {\n incrementRetrievalCount(repoRoot, topLessons.map((lesson) => lesson.id));\n }\n\n return topLessons;\n}\n\n/**\n * @deprecated Use loadSessionMemory. Backward-compat alias.\n */\nexport const loadSessionMemory = loadSessionLessons;\n","/**\n * Types for the compounding module.\n *\n * CctPattern represents a cross-cutting pattern synthesized\n * from multiple similar lessons.\n */\n\nimport { createHash } from 'node:crypto';\nimport { z } from 'zod';\n\nimport type { MemoryItem } from '../memory/index.js';\n\n/** Relative path to CCT patterns file from repo root */\nexport const CCT_PATTERNS_PATH = '.claude/lessons/cct-patterns.jsonl';\n\n/** Schema for a cross-cutting pattern */\nexport const CctPatternSchema = z.object({\n id: z.string().regex(/^CCT-[a-f0-9]{8}$/),\n name: z.string().min(1),\n description: z.string().min(1),\n frequency: z.number().int().positive(),\n testable: z.boolean(),\n testApproach: z.string().optional(),\n sourceIds: z.array(z.string()).min(1),\n created: z.string(), // ISO8601\n});\n\n/** Inferred type from CctPatternSchema */\nexport type CctPattern = z.infer<typeof CctPatternSchema>;\n\n/** Result from clustering operation */\nexport interface ClusterResult {\n /** Groups of similar items */\n clusters: MemoryItem[][];\n /** Items that didn't fit any cluster */\n noise: MemoryItem[];\n}\n\n/**\n * Generate a CCT pattern ID from a cluster ID string.\n * Format: \"CCT-\" + first 8 hex chars of SHA-256 hash.\n */\nexport function generateCctId(input: string): string {\n const hash = createHash('sha256').update(input).digest('hex');\n return `CCT-${hash.slice(0, 8)}`;\n}\n","/**\n * I/O module for CctPattern persistence.\n *\n * Append-only JSONL storage, following the same pattern as\n * src/memory/storage/jsonl.ts.\n */\n\nimport { appendFile, mkdir, readFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\n\nimport { CCT_PATTERNS_PATH, CctPatternSchema, type CctPattern } from './types.js';\n\n/**\n * Read all CCT patterns from the JSONL file.\n *\n * @param repoRoot - Repository root directory\n * @returns Array of CctPattern objects\n */\nexport async function readCctPatterns(repoRoot: string): Promise<CctPattern[]> {\n const filePath = join(repoRoot, CCT_PATTERNS_PATH);\n\n let content: string;\n try {\n content = await readFile(filePath, 'utf-8');\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n return [];\n }\n throw err;\n }\n\n const patterns: CctPattern[] = [];\n const lines = content.split('\\n');\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n\n const parsed = JSON.parse(trimmed) as unknown;\n const result = CctPatternSchema.safeParse(parsed);\n if (result.success) {\n patterns.push(result.data);\n }\n }\n\n return patterns;\n}\n\n/**\n * Append CCT patterns to the JSONL file (append-only).\n *\n * @param repoRoot - Repository root directory\n * @param patterns - Patterns to append\n */\nexport async function writeCctPatterns(repoRoot: string, patterns: CctPattern[]): Promise<void> {\n const filePath = join(repoRoot, CCT_PATTERNS_PATH);\n await mkdir(dirname(filePath), { recursive: true });\n\n const lines = patterns.map((p) => JSON.stringify(p) + '\\n').join('');\n await appendFile(filePath, lines, 'utf-8');\n}\n","/**\n * Embedding model resolution using node-llama-cpp's built-in resolver.\n *\n * Uses resolveModelFile for automatic download and caching.\n * Model is stored in ~/.node-llama-cpp/models/ by default.\n */\n\nimport { existsSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { getLlama, resolveModelFile } from 'node-llama-cpp';\n\n/**\n * HuggingFace URI for EmbeddingGemma-300M (Q4_0 quantization).\n *\n * - Size: ~278MB\n * - Dimensions: 768 (default), supports MRL truncation to 512/256/128\n * - Context: 2048 tokens\n */\nexport const MODEL_URI = 'hf:ggml-org/embeddinggemma-300M-qat-q4_0-GGUF/embeddinggemma-300M-qat-Q4_0.gguf';\n\n/**\n * Expected model filename after download.\n * node-llama-cpp uses format: hf_{org}_{filename}\n */\nexport const MODEL_FILENAME = 'hf_ggml-org_embeddinggemma-300M-qat-Q4_0.gguf';\n\n/** Default model directory used by node-llama-cpp */\nconst DEFAULT_MODEL_DIR = join(homedir(), '.node-llama-cpp', 'models');\n\n/** Cached usability result (per-process) */\nlet cachedUsability: UsabilityResult | null = null;\n\n/**\n * Check if the embedding model is available locally.\n *\n * @returns true if model file exists\n */\nexport function isModelAvailable(): boolean {\n return existsSync(join(DEFAULT_MODEL_DIR, MODEL_FILENAME));\n}\n\n/**\n * Result of checking if the model is usable at runtime.\n *\n * A discriminated union where `usable` determines which fields are present:\n * - usable=true: Model can initialize and create embedding context\n * - usable=false: Model cannot be used, with reason and actionable fix\n */\nexport type UsabilityResult =\n | { usable: true; reason?: undefined; action?: undefined }\n | { usable: false; reason: string; action: string };\n\n/**\n * Check if the embedding model is usable at runtime.\n *\n * Goes beyond file existence to verify the model can actually initialize:\n * 1. Checks if model file exists (fast fail)\n * 2. Attempts to load llama runtime\n * 3. Attempts to load model\n * 4. Attempts to create embedding context\n * 5. Cleans up all resources after check\n *\n * @returns UsabilityResult with usable status and actionable error if failed\n */\nexport async function isModelUsable(): Promise<UsabilityResult> {\n // Return cached result if available (avoids double initialization)\n if (cachedUsability !== null) {\n return cachedUsability;\n }\n\n // Fast fail if model file doesn't exist\n if (!isModelAvailable()) {\n cachedUsability = {\n usable: false,\n reason: 'Embedding model file not found',\n action: 'Run: npx ca download-model',\n };\n return cachedUsability;\n }\n\n // Attempt runtime initialization\n let llama = null;\n let model = null;\n let context = null;\n\n try {\n const modelPath = join(DEFAULT_MODEL_DIR, MODEL_FILENAME);\n\n // Step 1: Get llama runtime\n llama = await getLlama();\n\n // Step 2: Load model\n model = await llama.loadModel({ modelPath });\n\n // Step 3: Create embedding context\n context = await model.createEmbeddingContext();\n\n // Success - cache and return\n cachedUsability = { usable: true };\n return cachedUsability;\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Unknown error';\n cachedUsability = {\n usable: false,\n reason: `Embedding model runtime initialization failed: ${message}`,\n action: 'Check system compatibility or reinstall: npx ca download-model',\n };\n return cachedUsability;\n } finally {\n // Clean up resources in reverse order\n if (context) {\n try {\n context.dispose();\n } catch {\n // Ignore cleanup errors\n }\n }\n // Note: model and llama don't have explicit dispose methods in node-llama-cpp\n // The GC will handle them when references are released\n }\n}\n\n/**\n * Clear the cached usability result.\n *\n * Primarily for testing purposes. Clears the cached result so the next\n * call to isModelUsable() will perform a fresh check.\n */\nexport function clearUsabilityCache(): void {\n cachedUsability = null;\n}\n\n/**\n * Resolve the embedding model path, downloading if necessary.\n *\n * Uses node-llama-cpp's resolveModelFile for automatic download with progress.\n *\n * @param options - Optional configuration\n * @param options.cli - Show download progress in console (default: true)\n * @returns Path to the resolved model file\n *\n * @example\n * ```typescript\n * const modelPath = await resolveModel();\n * const llama = await getLlama();\n * const model = await llama.loadModel({ modelPath });\n * ```\n */\nexport async function resolveModel(options: { cli?: boolean } = {}): Promise<string> {\n const { cli = true } = options;\n return resolveModelFile(MODEL_URI, { cli });\n}\n","/**\n * Text embedding via node-llama-cpp with EmbeddingGemma model\n *\n * **Resource lifecycle:**\n * - Model is loaded lazily on first embedding call (~150MB in memory)\n * - Once loaded, the model remains in memory until `unloadEmbedding()` is called\n * - Loading is slow (~1-3s); keeping loaded improves subsequent call performance\n *\n * **Memory usage:**\n * - Embedding model: ~150MB RAM when loaded\n * - Embeddings themselves: ~3KB per embedding (768 dimensions x 4 bytes)\n *\n * @see {@link unloadEmbedding} for releasing memory\n * @see {@link getEmbedding} for the lazy-loading mechanism\n */\n\nimport type { Llama, LlamaModel } from 'node-llama-cpp';\nimport { getLlama, LlamaEmbeddingContext } from 'node-llama-cpp';\n\nimport { isModelAvailable, resolveModel } from './model.js';\n\n/** Singleton embedding context */\nlet embeddingContext: LlamaEmbeddingContext | null = null;\n/** Pending initialization promise (prevents concurrent duplicate loads) */\nlet pendingInit: Promise<LlamaEmbeddingContext> | null = null;\n/** Native resource refs for proper cleanup */\nlet llamaInstance: Llama | null = null;\nlet modelInstance: LlamaModel | null = null;\n\n/**\n * Get the LlamaEmbeddingContext instance for generating embeddings.\n *\n * **Lazy loading behavior:**\n * - First call loads the embedding model (~150MB) into memory\n * - Loading takes ~1-3 seconds depending on hardware\n * - Subsequent calls return the cached instance immediately\n * - Downloads model automatically if not present\n *\n * **Resource lifecycle:**\n * - Once loaded, model stays in memory until `unloadEmbedding()` is called\n * - For CLI commands: typically load once, use, then unload on exit\n * - For long-running processes: keep loaded for performance\n *\n * @returns The singleton embedding context\n * @throws Error if model download fails\n *\n * @example\n * ```typescript\n * // Direct usage (prefer embedText for simple cases)\n * const ctx = await getEmbedding();\n * const result = await ctx.getEmbeddingFor('some text');\n *\n * // Ensure cleanup\n * process.on('exit', () => unloadEmbedding());\n * ```\n *\n * @see {@link embedText} for simpler text-to-vector conversion\n * @see {@link unloadEmbedding} for releasing memory\n */\nexport async function getEmbedding(): Promise<LlamaEmbeddingContext> {\n if (embeddingContext) return embeddingContext;\n if (pendingInit) return pendingInit;\n\n pendingInit = (async () => {\n try {\n const modelPath = await resolveModel({ cli: true });\n llamaInstance = await getLlama();\n modelInstance = await llamaInstance.loadModel({ modelPath });\n embeddingContext = await modelInstance.createEmbeddingContext();\n return embeddingContext;\n } catch (err) {\n pendingInit = null; // Allow retry on failure\n throw err;\n }\n })();\n\n return pendingInit;\n}\n\n/**\n * Unload the embedding context to free memory (~150MB).\n *\n * **Resource lifecycle:**\n * - Disposes the underlying LlamaEmbeddingContext\n * - Releases ~150MB of RAM used by the model\n * - After unloading, subsequent embedding calls will reload the model\n *\n * **When to call:**\n * - At the end of CLI commands to ensure clean process exit\n * - In memory-constrained environments after batch processing\n * - Before process exit in graceful shutdown handlers\n * - When switching to a different model (if supported in future)\n *\n * **Best practices:**\n * - For single-operation scripts: call before exit\n * - For daemon/server processes: call in shutdown handler\n * - Not needed between embedding calls in the same process\n *\n * @example\n * ```typescript\n * // CLI command pattern\n * try {\n * const embedding = await embedText('some text');\n * // ... use embedding\n * } finally {\n * unloadEmbedding();\n * closeDb();\n * }\n *\n * // Graceful shutdown pattern\n * process.on('SIGTERM', () => {\n * unloadEmbedding();\n * closeDb();\n * process.exit(0);\n * });\n * ```\n *\n * @see {@link getEmbedding} for loading the model\n * @see {@link closeDb} for database cleanup (often used together)\n */\nexport function unloadEmbedding(): void {\n if (embeddingContext) {\n embeddingContext.dispose();\n embeddingContext = null;\n }\n if (modelInstance) {\n modelInstance.dispose().catch(() => {});\n modelInstance = null;\n }\n if (llamaInstance) {\n llamaInstance.dispose().catch(() => {});\n llamaInstance = null;\n }\n pendingInit = null;\n}\n\n/**\n * Embed a single text string into a vector.\n *\n * **Lazy loading:** First call loads the embedding model (~150MB, ~1-3s).\n * Subsequent calls use the cached model and complete in milliseconds.\n *\n * @param text - The text to embed\n * @returns A 768-dimensional vector (number[])\n * @throws Error if model download fails\n *\n * @example\n * ```typescript\n * const vector = await embedText('TypeScript error handling');\n * console.log(vector.length); // 768\n *\n * // Remember to clean up when done\n * unloadEmbedding();\n * ```\n *\n * @see {@link embedTexts} for batch embedding\n * @see {@link unloadEmbedding} for releasing memory\n */\nexport async function embedText(text: string): Promise<number[]> {\n const ctx = await getEmbedding();\n const result = await ctx.getEmbeddingFor(text);\n return Array.from(result.vector);\n}\n\n/**\n * Embed multiple texts into vectors.\n *\n * **Lazy loading:** First call loads the embedding model (~150MB, ~1-3s).\n * Subsequent calls use the cached model.\n *\n * **Performance:** More efficient than calling `embedText` in a loop\n * when processing multiple texts, as model loading happens only once.\n *\n * @param texts - Array of texts to embed\n * @returns Array of 768-dimensional vectors, same order as input\n * @throws Error if model download fails\n *\n * @example\n * ```typescript\n * const texts = ['first text', 'second text'];\n * const vectors = await embedTexts(texts);\n * console.log(vectors.length); // 2\n * console.log(vectors[0].length); // 768\n *\n * // Remember to clean up when done\n * unloadEmbedding();\n * ```\n *\n * @see {@link embedText} for single text embedding\n * @see {@link unloadEmbedding} for releasing memory\n */\nexport async function embedTexts(texts: string[]): Promise<number[][]> {\n if (texts.length === 0) return [];\n\n const ctx = await getEmbedding();\n const results: number[][] = [];\n\n for (const text of texts) {\n const result = await ctx.getEmbeddingFor(text);\n results.push(Array.from(result.vector));\n }\n\n return results;\n}\n\n// Re-export isModelAvailable for test utilities\nexport { isModelAvailable };\n","/**\n * Vector search with cosine similarity\n *\n * Embeds query text and ranks lessons by semantic similarity.\n * Uses SQLite cache to avoid recomputing embeddings.\n */\n\nimport { readCctPatterns, type CctPattern } from '../../compound/index.js';\nimport { embedText } from '../embeddings/index.js';\nimport { contentHash, getCachedEmbedding, readMemoryItems, setCachedEmbedding } from '../storage/index.js';\nimport type { MemoryItem } from '../types.js';\n\n/**\n * Calculate cosine similarity between two vectors.\n * Returns value between -1 (opposite) and 1 (identical).\n */\nexport function cosineSimilarity(a: number[], b: number[]): number {\n if (a.length !== b.length) {\n throw new Error('Vectors must have same length');\n }\n\n let dotProduct = 0;\n let normA = 0;\n let normB = 0;\n\n for (let i = 0; i < a.length; i++) {\n dotProduct += a[i]! * b[i]!;\n normA += a[i]! * a[i]!;\n normB += b[i]! * b[i]!;\n }\n\n const magnitude = Math.sqrt(normA) * Math.sqrt(normB);\n if (magnitude === 0) return 0;\n\n return dotProduct / magnitude;\n}\n\n/**\n * Memory item with similarity score.\n * The `lesson` field holds any MemoryItem type (not just Lesson).\n * Field name kept for backward compatibility.\n */\nexport interface ScoredLesson {\n lesson: MemoryItem;\n score: number;\n}\n\n/** Alias for ScoredLesson for unified memory API consumers. */\nexport type ScoredMemoryItem = ScoredLesson;\n\n/** Options for vector search */\nexport interface SearchVectorOptions {\n /** Maximum number of results to return (default: 10) */\n limit?: number;\n}\n\n/** Default number of results to return */\nconst DEFAULT_LIMIT = 10;\n\n/**\n * Search lessons by vector similarity to query text.\n * Returns top N lessons sorted by similarity score (descending).\n * Uses embedding cache to avoid recomputing embeddings.\n */\n/**\n * Convert a CctPattern to a MemoryItem-like shape for search results.\n */\nfunction cctToMemoryItem(pattern: CctPattern): MemoryItem {\n return {\n id: pattern.id,\n type: 'lesson',\n trigger: pattern.name,\n insight: pattern.description,\n tags: [],\n source: 'manual',\n context: { tool: 'compound', intent: 'synthesis' },\n created: pattern.created,\n confirmed: true,\n supersedes: [],\n related: pattern.sourceIds,\n };\n}\n\nexport async function searchVector(\n repoRoot: string,\n query: string,\n options?: SearchVectorOptions\n): Promise<ScoredLesson[]> {\n const limit = options?.limit ?? DEFAULT_LIMIT;\n // Read all memory items (all types)\n const { items } = await readMemoryItems(repoRoot);\n\n // Read CCT patterns if available\n let cctPatterns: CctPattern[] = [];\n try {\n cctPatterns = await readCctPatterns(repoRoot);\n } catch {\n // File doesn't exist or is unreadable — proceed without CCT patterns\n }\n\n if (items.length === 0 && cctPatterns.length === 0) return [];\n\n // Embed the query\n const queryVector = await embedText(query);\n\n // Score each item, skipping invalidated ones\n const scored: ScoredLesson[] = [];\n for (const item of items) {\n // Skip invalidated items\n if (item.invalidatedAt) continue;\n\n try {\n const itemText = `${item.trigger} ${item.insight}`;\n const hash = contentHash(item.trigger, item.insight);\n\n // Try cache first\n let itemVector = getCachedEmbedding(repoRoot, item.id, hash);\n\n if (!itemVector) {\n // Cache miss - compute and store\n itemVector = await embedText(itemText);\n setCachedEmbedding(repoRoot, item.id, itemVector, hash);\n }\n\n const score = cosineSimilarity(queryVector, itemVector);\n scored.push({ lesson: item, score });\n } catch {\n // Skip items that fail embedding — return partial results\n continue;\n }\n }\n\n // Score CCT patterns\n for (const pattern of cctPatterns) {\n try {\n const text = `${pattern.name} ${pattern.description}`;\n const vec = await embedText(text);\n const score = cosineSimilarity(queryVector, vec);\n scored.push({ lesson: cctToMemoryItem(pattern), score });\n } catch {\n continue;\n }\n }\n\n // Sort by score descending and take top N\n scored.sort((a, b) => b.score - a.score);\n return scored.slice(0, limit);\n}\n","/**\n * Multi-factor memory item ranking system\n *\n * Combines vector similarity with semantic boosts:\n * - Severity: high=1.5, medium=1.0, low=0.8\n * - Recency: 1.2 for items ≤30 days old\n * - Confirmation: 1.3 for confirmed items\n */\n\nimport type { MemoryItem } from '../types.js';\nimport { getLessonAgeDays } from '../../utils.js';\n\nimport type { ScoredLesson } from './vector.js';\n\n/** Lesson/memory item with final ranked score */\nexport interface RankedLesson extends ScoredLesson {\n finalScore?: number;\n}\n\n/** Alias for RankedLesson for unified memory API consumers. */\nexport type RankedMemoryItem = RankedLesson;\n\nconst RECENCY_THRESHOLD_DAYS = 30;\nconst HIGH_SEVERITY_BOOST = 1.5;\nconst MEDIUM_SEVERITY_BOOST = 1.0;\nconst LOW_SEVERITY_BOOST = 0.8;\nconst RECENCY_BOOST = 1.2;\nconst CONFIRMATION_BOOST = 1.3;\n\n/**\n * Maximum combined boost multiplier.\n *\n * Without clamping, the max boost is 1.5 * 1.2 * 1.3 = 2.34x, which lets\n * a 0.4 similarity item outrank a 0.9 similarity item. With a 1.8 cap,\n * an item needs at least ~0.53 similarity with all boosts to beat a 0.95\n * unboosted match, keeping semantic relevance as the primary ranking signal.\n */\nconst MAX_COMBINED_BOOST = 1.8;\n\n/**\n * Calculate severity boost based on item severity.\n * Items without severity get 1.0 (medium boost).\n */\nexport function severityBoost(item: MemoryItem): number {\n switch (item.severity) {\n case 'high':\n return HIGH_SEVERITY_BOOST;\n case 'medium':\n return MEDIUM_SEVERITY_BOOST;\n case 'low':\n return LOW_SEVERITY_BOOST;\n default:\n return MEDIUM_SEVERITY_BOOST;\n }\n}\n\n/**\n * Calculate recency boost based on item age.\n * Items ≤30 days old get 1.2, older get 1.0.\n */\nexport function recencyBoost(item: MemoryItem): number {\n const ageDays = getLessonAgeDays(item);\n return ageDays <= RECENCY_THRESHOLD_DAYS ? RECENCY_BOOST : 1.0;\n}\n\n/**\n * Calculate confirmation boost.\n * Confirmed items get 1.3, unconfirmed get 1.0.\n */\nexport function confirmationBoost(item: MemoryItem): number {\n return item.confirmed ? CONFIRMATION_BOOST : 1.0;\n}\n\n/**\n * Calculate combined score for a memory item.\n * score = vectorSimilarity * min(severity * recency * confirmation, MAX_COMBINED_BOOST)\n */\nexport function calculateScore(item: MemoryItem, vectorSimilarity: number): number {\n const boost = Math.min(\n severityBoost(item) * recencyBoost(item) * confirmationBoost(item),\n MAX_COMBINED_BOOST,\n );\n return vectorSimilarity * boost;\n}\n\n/**\n * Rank lessons by combined score.\n * Returns new array sorted by finalScore descending.\n *\n * Works with ScoredLesson[] (backward compat, uses .lesson field).\n * For ScoredMemoryItem[], use the .item field — same underlying data.\n */\nexport function rankLessons(lessons: ScoredLesson[]): RankedLesson[] {\n return lessons\n .map((scored) => ({\n ...scored,\n finalScore: calculateScore(scored.lesson, scored.score),\n }))\n .sort((a, b) => (b.finalScore ?? 0) - (a.finalScore ?? 0));\n}\n\n/**\n * Rank memory items by combined score.\n * Primary API for unified memory types. Uses .item field.\n * Returns new array sorted by finalScore descending.\n */\nexport const rankMemoryItems = rankLessons;\n","/**\n * Prime command - Context recovery for Claude Code with Beads-style trust language.\n *\n * Generates trust language guidelines combined with high-severity lessons\n * for context recovery after compaction or session restart.\n */\n\nimport type { Command } from 'commander';\n\nimport { getRepoRoot } from '../cli-utils.js';\nimport { loadSessionLessons } from '../memory/retrieval/index.js';\nimport type { MemoryItem, Source } from '../memory/index.js';\n\n/**\n * Beads-style trust language template.\n *\n * Uses explicit prohibitions, workflow sequencing, and NEVER/MUST language\n * following Beads conventions for maximum adherence.\n *\n * IMPORTANT: Prioritizes MCP tools over CLI commands.\n */\nconst TRUST_LANGUAGE_TEMPLATE = `# Compound Agent Active\n\n> **Context Recovery**: Run \\`ca prime\\` after compaction, clear, or new session\n\n## MCP Tools (ALWAYS USE THESE)\n\n**You MUST use MCP tools, NOT CLI commands:**\n\n| Tool | Purpose |\n|------|---------|\n| \\`memory_search\\` | Search lessons - call BEFORE architectural decisions |\n| \\`memory_capture\\` | Capture lessons - call AFTER corrections or discoveries |\n\n## Core Constraints\n\n**Default**: Use MCP tools for lesson management\n**Prohibited**: NEVER edit .claude/lessons/ files directly\n\n**Default**: Propose lessons freely after corrections\n**Prohibited**: NEVER propose without quality gate (novel + specific; prefer actionable)\n\n## Retrieval Protocol\n\nYou MUST call \\`memory_search\\` BEFORE:\n- Architectural decisions or complex planning\n- Implementing patterns you've done before in this repo\n\n**NEVER skip memory_search for complex decisions.** Past mistakes will repeat.\n\n## Capture Protocol\n\nCall \\`memory_capture\\` AFTER:\n- User corrects you (\"no\", \"wrong\", \"actually...\")\n- You self-correct after iteration failures\n- Test fails then you fix it\n\n**Quality gate** (must pass before capturing):\n- Novel (not already stored)\n- Specific (clear guidance)\n- Actionable (preferred, not mandatory)\n\n**Workflow**: Search BEFORE deciding, capture AFTER learning.\n\n## CLI (fallback only)\n\nWhen MCP is unavailable: \\`ca search \"query\"\\`, \\`ca learn \"insight\"\\`, \\`ca list\\`\n`;\n\n/**\n * Format lesson source for human-readable display.\n */\nfunction formatSource(source: Source): string {\n switch (source) {\n case 'user_correction':\n return 'user correction';\n case 'self_correction':\n return 'self correction';\n case 'test_failure':\n return 'test failure';\n case 'manual':\n return 'manual';\n default:\n return source;\n }\n}\n\n/**\n * Format a single lesson for the Emergency Recall section.\n *\n * Format: - **{insight}** ({tags})\n * Learned: {date} via {source}\n */\nfunction formatLessonForPrime(lesson: MemoryItem): string {\n const date = lesson.created.slice(0, 10); // YYYY-MM-DD\n const tags = lesson.tags.length > 0 ? ` (${lesson.tags.join(', ')})` : '';\n const source = formatSource(lesson.source);\n return `- **${lesson.insight}**${tags}\\n Learned: ${date} via ${source}`;\n}\n\n/**\n * Generate prime context output for Claude Code.\n *\n * Combines Beads-style trust language guidelines with high-severity lessons\n * for context recovery after compaction or session restart.\n *\n * @param repoRoot - Repository root directory (defaults to getRepoRoot())\n * @returns Formatted markdown string (< 2K tokens)\n */\nexport async function getPrimeContext(repoRoot?: string): Promise<string> {\n const root = repoRoot ?? getRepoRoot();\n\n // Load high-severity lessons (top 5, sorted by recency)\n const lessons = await loadSessionLessons(root, 5);\n\n // Build output: trust language first\n let output = TRUST_LANGUAGE_TEMPLATE;\n\n // Add Emergency Recall section if we have high-severity lessons\n if (lessons.length > 0) {\n const formattedLessons = lessons.map(formatLessonForPrime).join('\\n\\n');\n output += `\n---\n\n# [CRITICAL] Mandatory Recall\n\nCritical lessons from past corrections:\n\n${formattedLessons}\n`;\n }\n\n return output;\n}\n\n/**\n * Register prime command on the program.\n */\nexport function registerPrimeCommand(program: Command): void {\n /**\n * Prime command - Output context recovery for Claude Code.\n *\n * Combines Beads-style trust language guidelines with high-severity lessons.\n * Used after compaction or context loss to remind Claude of the\n * compound-agent workflow, rules, and commands.\n *\n * @example npx ca prime\n */\n program\n .command('prime')\n .description('Output context for Claude Code (guidelines + top lessons)')\n .action(async () => {\n const output = await getPrimeContext();\n console.log(output);\n });\n}\n","/**\n * Trigger detection for automatic memory capture\n *\n * Detects patterns that indicate potential learning opportunities:\n * - User corrections\n * - Self-corrections\n * - Test failures\n *\n * Also infers memory item type from insight text:\n * - pattern: \"use X instead of Y\", \"prefer X over Y\"\n * - solution: \"when X, do Y\", \"if X then Y\", \"to fix X\"\n * - preference: \"always X\", \"never X\"\n * - lesson: default for unclassified insights\n */\n\nimport type { Context, MemoryItemType } from '../types.js';\n\n/** Signal data for correction detection */\nexport interface CorrectionSignal {\n messages: string[];\n context: Context;\n}\n\n/** Detected correction result */\nexport interface DetectedCorrection {\n trigger: string;\n correctionMessage: string;\n context: Context;\n}\n\n/** User correction patterns */\nconst USER_CORRECTION_PATTERNS = [\n /\\bno\\b[,.]?\\s/i, // \"no, ...\" or \"no ...\"\n /\\bwrong\\b/i, // \"wrong\"\n /\\bactually\\b/i, // \"actually...\"\n /\\bnot that\\b/i, // \"not that\"\n /\\bi meant\\b/i, // \"I meant\"\n];\n\n/**\n * Detect user correction signals in conversation.\n *\n * Looks for patterns that indicate the user is correcting Claude's\n * understanding or actions.\n *\n * @param signals - Messages and context to analyze\n * @returns Detected correction or null if none found\n */\nexport function detectUserCorrection(signals: CorrectionSignal): DetectedCorrection | null {\n const { messages, context } = signals;\n\n if (messages.length < 2) {\n return null;\n }\n\n // Check later messages for correction patterns\n for (let i = 1; i < messages.length; i++) {\n const message = messages[i];\n if (!message) continue;\n\n for (const pattern of USER_CORRECTION_PATTERNS) {\n if (pattern.test(message)) {\n return {\n trigger: `User correction during ${context.intent}`,\n correctionMessage: message,\n context,\n };\n }\n }\n }\n\n return null;\n}\n\n/** Edit history entry */\nexport interface EditEntry {\n file: string;\n success: boolean;\n timestamp: number;\n}\n\n/** Edit history for self-correction detection */\nexport interface EditHistory {\n edits: EditEntry[];\n}\n\n/** Detected self-correction */\nexport interface DetectedSelfCorrection {\n file: string;\n trigger: string;\n}\n\n/**\n * Detect self-correction patterns in edit history.\n *\n * Looks for edit→fail→re-edit patterns on the same file,\n * which indicate Claude had to correct its own work.\n *\n * @param history - Edit history to analyze\n * @returns Detected self-correction or null if none found\n */\nexport function detectSelfCorrection(history: EditHistory): DetectedSelfCorrection | null {\n const { edits } = history;\n\n if (edits.length < 3) {\n return null;\n }\n\n // Look for edit→fail→re-edit pattern on same file\n for (let i = 0; i <= edits.length - 3; i++) {\n const first = edits[i];\n const second = edits[i + 1];\n const third = edits[i + 2];\n\n if (!first || !second || !third) continue;\n\n // Pattern: success → fail → success on same file\n if (\n first.file === second.file &&\n second.file === third.file &&\n first.success &&\n !second.success &&\n third.success\n ) {\n return {\n file: first.file,\n trigger: `Self-correction on ${first.file}`,\n };\n }\n }\n\n return null;\n}\n\n/** Test result for failure detection */\nexport interface TestResult {\n passed: boolean;\n output: string;\n testFile: string;\n}\n\n/** Detected test failure */\nexport interface DetectedTestFailure {\n testFile: string;\n errorOutput: string;\n trigger: string;\n}\n\n/**\n * Detect test failure patterns.\n *\n * When tests fail, this creates a potential learning opportunity\n * if the failure is later fixed.\n *\n * @param testResult - Test result to analyze\n * @returns Detected test failure or null if tests passed\n */\nexport function detectTestFailure(testResult: TestResult): DetectedTestFailure | null {\n if (testResult.passed) {\n return null;\n }\n\n // Extract first meaningful error line for trigger\n const lines = testResult.output.split('\\n').filter((line) => line.trim().length > 0);\n const errorLine = lines.find((line) => /error|fail|assert/i.test(line)) ?? lines[0] ?? '';\n\n return {\n testFile: testResult.testFile,\n errorOutput: testResult.output,\n trigger: `Test failure in ${testResult.testFile}: ${errorLine.slice(0, 100)}`,\n };\n}\n\n/** Patterns indicating a code pattern (bad -> good transformation) */\nconst PATTERN_INDICATORS = [\n /\\buse\\s+.+\\s+instead\\s+of\\b/i,\n /\\bprefer\\s+.+\\s+(over|to)\\b/i,\n];\n\n/** Patterns indicating a solution (problem -> resolution) */\nconst SOLUTION_INDICATORS = [\n /\\bwhen\\s+.+,\\s/i,\n /\\bif\\s+.+\\bthen\\b/i,\n /\\bif\\s+.+,\\s/i,\n /\\bto\\s+fix\\b/i,\n];\n\n/** Patterns indicating a preference (user workflow choice) */\nconst PREFERENCE_INDICATORS = [\n /\\balways\\s+/i,\n /\\bnever\\s+/i,\n];\n\n/**\n * Infer the memory item type from insight text.\n *\n * Rules (checked in priority order):\n * - \"use X instead of Y\" / \"prefer X over Y\" → pattern\n * - \"when X, do Y\" / \"if X then Y\" / \"to fix X\" → solution\n * - \"always X\" / \"never X\" → preference\n * - Default → lesson\n *\n * @param insight - The insight text to classify\n * @returns The inferred memory item type\n */\nexport function inferMemoryItemType(insight: string): MemoryItemType {\n for (const pattern of PATTERN_INDICATORS) {\n if (pattern.test(insight)) return 'pattern';\n }\n\n for (const pattern of SOLUTION_INDICATORS) {\n if (pattern.test(insight)) return 'solution';\n }\n\n for (const pattern of PREFERENCE_INDICATORS) {\n if (pattern.test(insight)) return 'preference';\n }\n\n return 'lesson';\n}\n","/**\n * Trigger detection integration\n *\n * Orchestrates detection -> quality filter -> memory item proposal flow.\n * Infers memory item type from insight content.\n * Provides a high-level API for CLI and hooks.\n */\n\nimport * as fs from 'node:fs/promises';\n\nimport { z } from 'zod';\n\nimport { ContextSchema } from '../types.js';\nimport type { MemoryItemType, Source } from '../types.js';\nimport { shouldPropose } from './quality.js';\nimport {\n detectUserCorrection,\n detectSelfCorrection,\n detectTestFailure,\n inferMemoryItemType,\n} from './triggers.js';\nimport type {\n CorrectionSignal,\n EditHistory,\n TestResult,\n} from './triggers.js';\n\n/** Detection input types */\nexport type DetectionType = 'user' | 'self' | 'test';\n\n/** Input for user correction detection */\nexport interface UserDetectionInput {\n type: 'user';\n data: CorrectionSignal;\n}\n\n/** Input for self correction detection */\nexport interface SelfDetectionInput {\n type: 'self';\n data: EditHistory;\n}\n\n/** Input for test failure detection */\nexport interface TestDetectionInput {\n type: 'test';\n data: TestResult;\n}\n\n/** Union type for all detection inputs */\nexport type DetectionInput = UserDetectionInput | SelfDetectionInput | TestDetectionInput;\n\n/** Result of successful detection */\nexport interface DetectionResult {\n trigger: string;\n source: Source;\n proposedInsight: string;\n memoryItemType: MemoryItemType;\n}\n\n/**\n * Detect triggers and propose lessons.\n *\n * Runs the appropriate detector based on input type, then filters\n * through quality checks. Returns a proposal if detection passes\n * all quality filters.\n *\n * @param repoRoot - Repository root path\n * @param input - Detection input with type and data\n * @returns Detection result with proposed insight, or null\n */\nexport async function detectAndPropose(\n repoRoot: string,\n input: DetectionInput\n): Promise<DetectionResult | null> {\n const detected = runDetector(input);\n if (!detected) {\n return null;\n }\n\n const { trigger, source, proposedInsight } = detected;\n\n // Run quality filters on proposed insight\n const quality = await shouldPropose(repoRoot, proposedInsight);\n if (!quality.shouldPropose) {\n return null;\n }\n\n // Infer memory item type from insight content\n const memoryItemType = inferMemoryItemType(proposedInsight);\n\n return { trigger, source, proposedInsight, memoryItemType };\n}\n\n/** Internal detection result before quality filtering */\ninterface RawDetection {\n trigger: string;\n source: Source;\n proposedInsight: string;\n}\n\n/**\n * Run the appropriate detector based on input type.\n */\nfunction runDetector(input: DetectionInput): RawDetection | null {\n switch (input.type) {\n case 'user':\n return detectUserCorrectionFlow(input.data);\n case 'self':\n return detectSelfCorrectionFlow(input.data);\n case 'test':\n return detectTestFailureFlow(input.data);\n }\n}\n\n/**\n * Detect user correction and extract insight.\n */\nfunction detectUserCorrectionFlow(data: CorrectionSignal): RawDetection | null {\n const result = detectUserCorrection(data);\n if (!result) {\n return null;\n }\n\n return {\n trigger: result.trigger,\n source: 'user_correction',\n proposedInsight: result.correctionMessage,\n };\n}\n\n/**\n * Detect self correction and extract insight.\n */\nfunction detectSelfCorrectionFlow(data: EditHistory): RawDetection | null {\n const result = detectSelfCorrection(data);\n if (!result) {\n return null;\n }\n\n return {\n trigger: result.trigger,\n source: 'self_correction',\n // Self-corrections need context to form useful insights\n proposedInsight: `Check ${result.file} for common errors before editing`,\n };\n}\n\n/**\n * Detect test failure and extract insight.\n */\nfunction detectTestFailureFlow(data: TestResult): RawDetection | null {\n const result = detectTestFailure(data);\n if (!result) {\n return null;\n }\n\n return {\n trigger: result.trigger,\n source: 'test_failure',\n proposedInsight: result.errorOutput,\n };\n}\n\n/** Zod schema for CorrectionSignal */\nconst CorrectionSignalSchema = z.object({\n messages: z.array(z.string()),\n context: ContextSchema,\n});\n\n/** Zod schema for EditEntry */\nconst EditEntrySchema = z.object({\n file: z.string(),\n success: z.boolean(),\n timestamp: z.number(),\n});\n\n/** Zod schema for EditHistory */\nconst EditHistorySchema = z.object({\n edits: z.array(EditEntrySchema),\n});\n\n/** Zod schema for TestResult */\nconst TestResultSchema = z.object({\n passed: z.boolean(),\n output: z.string(),\n testFile: z.string(),\n});\n\n/** Zod discriminated union for DetectionInput */\nconst DetectionInputSchema = z.discriminatedUnion('type', [\n z.object({ type: z.literal('user'), data: CorrectionSignalSchema }),\n z.object({ type: z.literal('self'), data: EditHistorySchema }),\n z.object({ type: z.literal('test'), data: TestResultSchema }),\n]);\n\n/**\n * Parse detection input from a JSON file.\n *\n * @param filePath - Path to JSON input file\n * @returns Parsed detection input\n * @throws ZodError if file content doesn't match expected schema\n */\nexport async function parseInputFile(filePath: string): Promise<DetectionInput> {\n const content = await fs.readFile(filePath, 'utf-8');\n const data: unknown = JSON.parse(content);\n return DetectionInputSchema.parse(data);\n}\n","/**\n * Zod schemas for rule configuration.\n *\n * Rules are defined in .claude/rules.json and describe mechanical checks\n * that can be run against a codebase.\n */\n\nimport { z } from 'zod';\n\n/** Rule severity levels. */\nexport const SeveritySchema = z.enum(['error', 'warning', 'info']);\n\n/** File-pattern check: regex match on files matching a glob. */\nexport const FilePatternCheckSchema = z.object({\n type: z.literal('file-pattern'),\n glob: z.string(),\n pattern: z.string(),\n mustMatch: z.boolean().optional(),\n});\n\n/** File-size check: line count limit on files matching a glob. */\nexport const FileSizeCheckSchema = z.object({\n type: z.literal('file-size'),\n glob: z.string(),\n maxLines: z.number().int().positive(),\n});\n\n/** Script check: run a shell command and check exit code. */\nexport const ScriptCheckSchema = z.object({\n type: z.literal('script'),\n command: z.string(),\n expectExitCode: z.number().int().optional(),\n});\n\n/** Discriminated union of all check types. */\nexport const RuleCheckSchema = z.discriminatedUnion('type', [\n FilePatternCheckSchema,\n FileSizeCheckSchema,\n ScriptCheckSchema,\n]);\n\n/** A single rule definition. */\nexport const RuleSchema = z.object({\n id: z.string().min(1),\n description: z.string(),\n severity: SeveritySchema,\n check: RuleCheckSchema,\n remediation: z.string(),\n});\n\n/** Top-level rule configuration file schema. */\nexport const RuleConfigSchema = z.object({\n rules: z.array(RuleSchema),\n});\n\n// Type exports\nexport type Severity = z.infer<typeof SeveritySchema>;\nexport type FilePatternCheck = z.infer<typeof FilePatternCheckSchema>;\nexport type FileSizeCheck = z.infer<typeof FileSizeCheckSchema>;\nexport type ScriptCheck = z.infer<typeof ScriptCheckSchema>;\nexport type RuleCheck = z.infer<typeof RuleCheckSchema>;\nexport type Rule = z.infer<typeof RuleSchema>;\nexport type RuleConfig = z.infer<typeof RuleConfigSchema>;\n","/**\n * Audit module types and Zod schemas.\n */\n\nimport { z } from 'zod';\n\n/** Schema for a single audit finding. */\nexport const AuditFindingSchema = z.object({\n file: z.string(),\n issue: z.string(),\n severity: z.enum(['error', 'warning', 'info']),\n relatedLessonId: z.string().optional(),\n suggestedFix: z.string().optional(),\n source: z.enum(['rule', 'pattern', 'lesson']),\n});\n\n/** Schema for the audit summary. */\nexport const AuditSummarySchema = z.object({\n errors: z.number(),\n warnings: z.number(),\n infos: z.number(),\n filesChecked: z.number(),\n});\n\n/** Schema for a complete audit report. */\nexport const AuditReportSchema = z.object({\n findings: z.array(AuditFindingSchema),\n summary: AuditSummarySchema,\n timestamp: z.string(),\n});\n\nexport type AuditFinding = z.infer<typeof AuditFindingSchema>;\nexport type AuditSummary = z.infer<typeof AuditSummarySchema>;\nexport type AuditReport = z.infer<typeof AuditReportSchema>;\n\n/** Return type for individual audit check functions. */\nexport interface AuditCheckResult {\n findings: AuditFinding[];\n filesChecked: string[];\n}\n\n/** Options to toggle individual audit checks. */\nexport interface AuditOptions {\n includeRules?: boolean;\n includePatterns?: boolean;\n includeLessons?: boolean;\n}\n","/**\n * Compound Agent - Repository-scoped learning system for Claude Code\n *\n * This package helps Claude Code learn from mistakes and avoid repeating them.\n * It captures lessons during coding sessions and retrieves relevant lessons\n * when planning new work.\n *\n * ## Quick Start\n *\n * ```typescript\n * import { appendLesson, retrieveForPlan, loadSessionLessons } from 'compound-agent';\n *\n * // At session start, load high-severity lessons\n * const criticalLessons = await loadSessionLessons(repoRoot);\n *\n * // When planning, retrieve relevant lessons\n * const { lessons, message } = await retrieveForPlan(repoRoot, planText);\n *\n * // When capturing a lesson\n * await appendLesson(repoRoot, lesson);\n * ```\n *\n * ## Setup\n *\n * Run `npx ca init` in your project root to configure hooks and AGENTS.md.\n *\n * ## Resource Management\n *\n * This library manages two heavyweight resources that require cleanup:\n *\n * ### SQLite Database\n * - **Acquired:** Lazily on first database operation (search, rebuild, etc.)\n * - **Memory:** Minimal (~few KB for connection, index cached by OS)\n * - **Cleanup:** Call `closeDb()` before process exit\n *\n * ### Embedding Model\n * - **Acquired:** Lazily on first embedding call (embedText, embedTexts, searchVector)\n * - **Memory:** ~150MB RAM for the EmbeddingGemma model\n * - **Cleanup:** Call `unloadEmbedding()` before process exit\n *\n * ### Recommended Cleanup Pattern\n *\n * ```typescript\n * import { closeDb, unloadEmbedding } from 'compound-agent';\n *\n * // For CLI commands - use try/finally\n * async function main() {\n * try {\n * // ... your code that uses compound-agent\n * } finally {\n * unloadEmbedding();\n * closeDb();\n * }\n * }\n *\n * // For long-running processes - use shutdown handlers\n * process.on('SIGTERM', () => {\n * unloadEmbedding();\n * closeDb();\n * process.exit(0);\n * });\n * process.on('SIGINT', () => {\n * unloadEmbedding();\n * closeDb();\n * process.exit(0);\n * });\n * ```\n *\n * **Note:** Failing to clean up will not corrupt data, but may cause:\n * - Memory leaks in long-running processes\n * - Unclean process exits (warnings in some environments)\n *\n * @see {@link closeDb} for database cleanup\n * @see {@link unloadEmbedding} for embedding model cleanup\n * @module compound-agent\n */\n\nimport { createRequire } from 'node:module';\n\nconst _require = createRequire(import.meta.url);\nconst _pkg = _require('../package.json') as { version: string };\n\n/** Package version, read from package.json. */\nexport const VERSION: string = _pkg.version;\n\n// Storage API (JSONL source of truth + SQLite index)\nexport {\n appendLesson,\n appendMemoryItem,\n closeDb,\n DB_PATH,\n LESSONS_PATH,\n readLessons,\n readMemoryItems,\n rebuildIndex,\n searchKeyword,\n} from './memory/storage/index.js';\nexport type { ParseError, ReadLessonsOptions, ReadLessonsResult, ReadMemoryItemsResult } from './memory/storage/index.js';\n\n// Embeddings API\nexport {\n embedText,\n embedTexts,\n getEmbedding,\n isModelAvailable,\n isModelUsable,\n MODEL_FILENAME,\n MODEL_URI,\n resolveModel,\n unloadEmbedding,\n} from './memory/embeddings/index.js';\nexport type { UsabilityResult } from './memory/embeddings/index.js';\n\n// Search API (vector similarity + ranking)\nexport {\n calculateScore,\n confirmationBoost,\n cosineSimilarity,\n rankLessons,\n rankMemoryItems,\n recencyBoost,\n searchVector,\n severityBoost,\n} from './memory/search/index.js';\nexport type { RankedLesson, RankedMemoryItem, ScoredLesson, ScoredMemoryItem, SearchVectorOptions } from './memory/search/index.js';\n\n// Capture API (quality filters + trigger detection)\nexport {\n detectSelfCorrection,\n detectTestFailure,\n detectUserCorrection,\n isActionable,\n isNovel,\n isSpecific,\n shouldPropose,\n} from './memory/capture/index.js';\nexport type {\n ActionabilityResult,\n CorrectionSignal,\n DetectedCorrection,\n DetectedSelfCorrection,\n DetectedTestFailure,\n EditEntry,\n EditHistory,\n NoveltyOptions,\n NoveltyResult,\n ProposeResult,\n SpecificityResult,\n TestResult,\n} from './memory/capture/index.js';\n\n// Retrieval API (session + plan time)\nexport { formatLessonsCheck, formatMemoryCheck, loadSessionLessons, loadSessionMemory, retrieveForPlan } from './memory/retrieval/index.js';\nexport type { PlanRetrievalResult } from './memory/retrieval/index.js';\n\n// Context recovery API (for MCP server integration)\nexport { getPrimeContext } from './commands/index.js';\n\n// Audit API\nexport { runAudit, AuditFindingSchema, AuditReportSchema } from './audit/index.js';\nexport type { AuditFinding, AuditReport, AuditOptions } from './audit/index.js';\n\n// Compound API (clustering, synthesis, pattern I/O)\nexport {\n buildSimilarityMatrix,\n CCT_PATTERNS_PATH,\n CctPatternSchema,\n clusterBySimilarity,\n readCctPatterns,\n synthesizePattern,\n writeCctPatterns,\n} from './compound/index.js';\nexport type { CctPattern, ClusterResult } from './compound/index.js';\n\n// Types and schemas\nexport {\n generateId,\n LegacyLessonSchema,\n LegacyTombstoneSchema,\n LessonItemSchema,\n LessonRecordSchema,\n LessonSchema,\n LessonTypeSchema,\n MemoryItemRecordSchema,\n MemoryItemSchema,\n MemoryItemTypeSchema,\n PatternItemSchema,\n PreferenceItemSchema,\n SolutionItemSchema,\n} from './memory/types.js';\nexport type {\n Context,\n Lesson,\n LessonRecord,\n LessonType,\n MemoryItem,\n MemoryItemRecord,\n MemoryItemType,\n PatternItem,\n Preference,\n Severity,\n Solution,\n Source,\n} from './memory/types.js';\n","#!/usr/bin/env node\n/**\n * MCP Server for Compound Agent\n *\n * Exposes compound-agent functionality as MCP tools and resources:\n * - memory_search: Search memory items by semantic similarity\n * - memory_capture: Capture a new memory item\n * - memory://prime: Get workflow context with high-severity memory items\n *\n * This is a thin wrapper - all business logic is delegated to existing modules.\n */\n\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { z } from 'zod';\n\nimport { getPrimeContext } from './commands/management-prime.js';\nimport { VERSION } from './index.js';\nimport { inferMemoryItemType } from './memory/capture/triggers.js';\nimport { rankLessons, searchVector } from './memory/search/index.js';\nimport { appendMemoryItem, closeDb, incrementRetrievalCount } from './memory/storage/index.js';\nimport { generateId, MemoryItemTypeSchema, PatternSchema } from './memory/types.js';\nimport type { MemoryItem, MemoryItemType } from './memory/types.js';\n\n/** Default max results for search */\nconst DEFAULT_MAX_RESULTS = 5;\n\n/** Minimum insight length for quality */\nconst MIN_INSIGHT_LENGTH = 10;\n\n/** Search result with lesson and score */\ninterface SearchResult {\n lesson: MemoryItem;\n score: number;\n finalScore?: number;\n}\n\n/** Success result from memory_search tool */\ninterface SearchToolSuccess {\n lessons: SearchResult[];\n error?: undefined;\n action?: undefined;\n}\n\n/** Error result from memory_search tool */\ninterface SearchToolError {\n lessons: [];\n error: string;\n action: string;\n}\n\n/** Result from memory_search tool - typed union for success/failure */\nexport type SearchToolResult = SearchToolSuccess | SearchToolError;\n\n/**\n * Type guard to check if search result is an error.\n *\n * @param result - The search tool result\n * @returns true if the result is an error response\n */\nexport function isSearchError(result: SearchToolResult): result is SearchToolError {\n return 'error' in result && result.error !== undefined;\n}\n\n/** Result from memory_capture tool */\ninterface CaptureToolResult {\n /** Unified memory item (all types) */\n item: MemoryItem;\n /** Backward-compatible alias (same object as item) */\n lesson: MemoryItem;\n}\n\n/** Result from reading a resource */\ninterface ResourceResult {\n content: string;\n}\n\n/**\n * Shared search logic for both MCP protocol and typed API paths.\n */\nasync function handleSearch(\n repoRoot: string,\n query: string,\n maxResults?: number,\n typeFilter?: MemoryItemType\n): Promise<SearchToolResult> {\n try {\n const limit = maxResults ?? DEFAULT_MAX_RESULTS;\n const searchLimit = typeFilter ? limit * 3 : limit;\n const results = await searchVector(repoRoot, query, { limit: searchLimit });\n const ranked = rankLessons(results);\n let lessons: SearchResult[] = ranked.map((r) => ({\n lesson: r.lesson,\n score: r.score,\n finalScore: r.finalScore,\n }));\n if (typeFilter) {\n lessons = lessons.filter((r) => r.lesson.type === typeFilter);\n }\n lessons = lessons.slice(0, limit);\n const ids = lessons.map((r) => r.lesson.id);\n if (ids.length > 0) {\n incrementRetrievalCount(repoRoot, ids);\n }\n return { lessons };\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Unknown error';\n return {\n error: `Search failed: ${message}`,\n action: 'Run: npx ca download-model',\n lessons: [],\n };\n }\n}\n\n/**\n * Shared capture logic for both MCP protocol and typed API paths.\n */\nasync function handleCapture(\n repoRoot: string,\n insight: string,\n trigger?: string,\n tags?: string[],\n type?: MemoryItemType,\n pattern?: { bad: string; good: string },\n severity?: 'high' | 'medium' | 'low',\n confirmed?: boolean,\n supersedes?: string[],\n related?: string[]\n): Promise<CaptureToolResult> {\n let itemType = type ?? inferMemoryItemType(insight);\n if (type === 'pattern' && !pattern) {\n throw new Error('Pattern type requires a pattern field with { bad, good }');\n }\n if (itemType === 'pattern' && !pattern && !type) {\n itemType = 'lesson';\n }\n const item: MemoryItem = {\n type: itemType,\n id: generateId(insight, itemType),\n trigger: trigger ?? 'Manual capture via MCP',\n insight,\n tags: tags ?? [],\n source: 'manual',\n context: { tool: 'mcp', intent: 'memory capture' },\n created: new Date().toISOString(),\n ...(severity ? { severity } : {}),\n confirmed: confirmed ?? true,\n supersedes: supersedes ?? [],\n related: related ?? [],\n ...(pattern ? { pattern } : {}),\n } as MemoryItem;\n await appendMemoryItem(repoRoot, item);\n return { item, lesson: item };\n}\n\n/** MCP Server wrapper with typed tool/resource methods */\nexport interface CompoundAgentMcpServer {\n /** The underlying MCP server instance */\n server: McpServer;\n /** Repository root path (immutable after creation) */\n repoRoot: string;\n callTool<T = SearchToolResult | CaptureToolResult>(\n name: string,\n params: Record<string, unknown>\n ): Promise<T>;\n readResource(uri: string): Promise<ResourceResult>;\n}\n\n// ============================================================================\n// Tool/resource registration helpers\n// ============================================================================\n\nconst searchInputSchema = {\n query: z.string().min(1, 'Query must be non-empty'),\n maxResults: z.number().int().positive().max(100).optional(),\n type: MemoryItemTypeSchema.optional(),\n};\n\nconst captureInputSchema = {\n insight: z.string().min(MIN_INSIGHT_LENGTH, `Insight must be at least ${MIN_INSIGHT_LENGTH} characters`),\n trigger: z.string().min(1).optional(),\n tags: z.array(z.string().min(1)).optional(),\n type: MemoryItemTypeSchema.optional(),\n pattern: PatternSchema.optional(),\n severity: z.enum(['high', 'medium', 'low']).optional(),\n confirmed: z.boolean().optional(),\n supersedes: z.array(z.string()).optional(),\n related: z.array(z.string()).optional(),\n};\n\nfunction registerSearchTool(\n server: McpServer,\n repoRoot: string,\n toolHandlers: Record<string, (params: Record<string, unknown>) => Promise<unknown>>\n): void {\n server.registerTool(\n 'memory_search',\n {\n title: 'Search Memory',\n description: `Mandatory recall: search memory BEFORE:\n- Architectural decisions or complex planning\n- Patterns you've implemented before in this repo\n- After corrections (\"actually...\", \"wrong\", \"use X instead\")\n\nReturns relevant memory items ranked by similarity and severity.`,\n inputSchema: searchInputSchema,\n },\n async ({ query, maxResults, type: typeFilter }) => {\n const output = await handleSearch(repoRoot, query, maxResults, typeFilter);\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(output) }],\n };\n }\n );\n\n toolHandlers['memory_search'] = async (params): Promise<SearchToolResult> => {\n const parsed = z.object(searchInputSchema).parse(params);\n return handleSearch(repoRoot, parsed.query, parsed.maxResults, parsed.type);\n };\n}\n\nfunction registerCaptureTool(\n server: McpServer,\n repoRoot: string,\n toolHandlers: Record<string, (params: Record<string, unknown>) => Promise<unknown>>\n): void {\n server.registerTool(\n 'memory_capture',\n {\n title: 'Capture Memory',\n description: `Capture a memory item AFTER:\n- User corrects you (\"no\", \"actually...\", \"use X instead\")\n- Test fail -> fix -> pass cycles\n- Discovering project-specific knowledge\n\nTypes: lesson (default), solution, pattern (requires pattern field), preference.\nSaves immediately and shows what was captured.`,\n inputSchema: captureInputSchema,\n },\n async ({ insight, trigger, tags, type, pattern, severity, confirmed, supersedes, related }) => {\n const output = await handleCapture(repoRoot, insight, trigger, tags, type, pattern, severity, confirmed, supersedes, related);\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(output) }],\n };\n }\n );\n\n toolHandlers['memory_capture'] = async (params): Promise<CaptureToolResult> => {\n const parsed = z.object(captureInputSchema).parse(params);\n return handleCapture(repoRoot, parsed.insight, parsed.trigger, parsed.tags, parsed.type, parsed.pattern, parsed.severity, parsed.confirmed, parsed.supersedes, parsed.related);\n };\n}\n\nfunction registerPrimeResource(\n server: McpServer,\n repoRoot: string,\n resourceHandlers: Record<string, () => Promise<ResourceResult>>\n): void {\n server.registerResource(\n 'prime',\n 'memory://prime',\n {\n title: 'Prime Context',\n description: 'Workflow context with high-severity memory items for session start',\n mimeType: 'text/plain',\n },\n async (uri) => {\n const content = await getPrimeContext(repoRoot);\n return {\n contents: [{ uri: uri.href, text: content }],\n };\n }\n );\n\n resourceHandlers['memory://prime'] = async () => {\n const content = await getPrimeContext(repoRoot);\n return { content };\n };\n}\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * Create an MCP server for compound-agent.\n *\n * @param repoRoot - Repository root directory (immutable after creation)\n * @returns MCP server wrapper with typed tool/resource methods\n */\nexport function createMcpServer(repoRoot: string): CompoundAgentMcpServer {\n const server = new McpServer({\n name: 'compound-agent',\n version: VERSION,\n });\n\n const toolHandlers: Record<string, (params: Record<string, unknown>) => Promise<unknown>> = {};\n const resourceHandlers: Record<string, () => Promise<ResourceResult>> = {};\n\n registerSearchTool(server, repoRoot, toolHandlers);\n registerCaptureTool(server, repoRoot, toolHandlers);\n registerPrimeResource(server, repoRoot, resourceHandlers);\n\n return {\n server,\n repoRoot,\n\n async callTool<T = SearchToolResult | CaptureToolResult>(\n name: string,\n params: Record<string, unknown>\n ): Promise<T> {\n const handler = toolHandlers[name];\n if (!handler) {\n throw new Error(`Unknown tool: ${name}`);\n }\n return handler(params) as Promise<T>;\n },\n\n async readResource(uri: string): Promise<ResourceResult> {\n const handler = resourceHandlers[uri];\n if (!handler) {\n throw new Error(`Unknown resource: ${uri}`);\n }\n return handler();\n },\n };\n}\n\n/**\n * Register signal handlers for clean resource cleanup.\n * Mirrors the CLI pattern in src/cli.ts.\n */\nexport function registerMcpCleanup(): void {\n const cleanup = (): void => {\n try {\n closeDb();\n } catch {\n // Ignore errors - database may never have been opened\n }\n };\n process.on('SIGINT', () => { cleanup(); process.exit(0); });\n process.on('SIGTERM', () => { cleanup(); process.exit(0); });\n}\n\n/**\n * Start MCP server with stdio transport.\n * Called when this module is run directly.\n */\nasync function main(): Promise<void> {\n registerMcpCleanup();\n\n const repoRoot = process.cwd();\n const { server } = createMcpServer(repoRoot);\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n\n// Run if executed directly\nconst isMainModule = import.meta.url === `file://${process.argv[1]}`;\nif (isMainModule) {\n main().catch((err) => {\n console.error('MCP Server error:', err);\n process.exit(1);\n });\n}\n"]}
|