codecortex-ai 0.4.2 → 0.4.4

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/mcp/server.ts","../src/mcp/tools/read.ts","../src/utils/files.ts","../src/utils/yaml.ts","../src/core/manifest.ts","../src/core/graph.ts","../src/utils/markdown.ts","../src/core/modules.ts","../src/core/sessions.ts","../src/core/decisions.ts","../src/core/search.ts","../src/git/diff.ts","../src/git/history.ts","../src/core/freshness.ts","../src/mcp/tools/write.ts","../src/types/schema.ts","../src/core/patterns.ts"],"sourcesContent":["/**\n * CodeCortex MCP Server\n *\n * Serves codebase knowledge to AI agents via Model Context Protocol.\n * 15 tools: 10 read (knowledge retrieval) + 5 write (knowledge creation).\n *\n * Usage:\n * codecortex serve\n *\n * Config for Claude Code / Claude Desktop:\n * {\n * \"mcpServers\": {\n * \"codecortex\": {\n * \"command\": \"codecortex\",\n * \"args\": [\"serve\"],\n * \"cwd\": \"/path/to/your-project\"\n * }\n * }\n * }\n */\n\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { registerReadTools } from './tools/read.js'\nimport { registerWriteTools } from './tools/write.js'\n\nexport function createServer(projectRoot: string): McpServer {\n const server = new McpServer({\n name: 'codecortex',\n version: '0.4.4',\n description: 'Persistent codebase knowledge layer. Pre-digested architecture, symbols, coupling, and patterns served to AI agents.',\n })\n\n registerReadTools(server, projectRoot)\n registerWriteTools(server, projectRoot)\n\n return server\n}\n\nexport async function startServer(projectRoot: string): Promise<void> {\n const server = createServer(projectRoot)\n const transport = new StdioServerTransport()\n await server.connect(transport)\n console.error(`CodeCortex MCP server running on stdio (root: ${projectRoot})`)\n}\n\n// Direct execution\nif (import.meta.url === `file://${process.argv[1]}`) {\n const root = process.cwd()\n startServer(root).catch((err) => {\n console.error('Fatal error:', err)\n process.exit(1)\n })\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { z } from 'zod'\nimport { readFile, cortexPath } from '../../utils/files.js'\nimport { readManifest } from '../../core/manifest.js'\nimport { readGraph, getModuleDependencies, getMostImportedFiles, getFileImporters } from '../../core/graph.js'\nimport { readModuleDoc, listModuleDocs } from '../../core/modules.js'\nimport { listSessions, readSession, getLatestSession } from '../../core/sessions.js'\nimport { listDecisions, readDecision } from '../../core/decisions.js'\nimport { searchKnowledge } from '../../core/search.js'\nimport { computeFreshness } from '../../core/freshness.js'\nimport type { TemporalData, SymbolIndex, FreshnessInfo } from '../../types/index.js'\n\nfunction textResult(data: unknown) {\n return { content: [{ type: 'text' as const, text: JSON.stringify(data, null, 2) }] }\n}\n\n/** Attach freshness metadata to any response object. */\nfunction withFreshness<T extends object>(data: T, freshness: FreshnessInfo | null): T & { _freshness?: FreshnessInfo } {\n if (!freshness) return data\n return { ...data, _freshness: freshness }\n}\n\nexport function registerReadTools(server: McpServer, projectRoot: string): void {\n // Cache freshness per MCP session to avoid repeated git calls.\n // Invalidated when null (first call) or after 60 seconds.\n let cachedFreshness: { info: FreshnessInfo | null; timestamp: number } | null = null\n const FRESHNESS_TTL_MS = 60_000\n\n async function getFreshness(): Promise<FreshnessInfo | null> {\n const now = Date.now()\n if (cachedFreshness && (now - cachedFreshness.timestamp) < FRESHNESS_TTL_MS) {\n return cachedFreshness.info\n }\n const info = await computeFreshness(projectRoot)\n cachedFreshness = { info, timestamp: now }\n return info\n }\n\n // --- Tool 1: get_project_overview ---\n server.registerTool(\n 'get_project_overview',\n {\n description: 'Get the full project overview: constitution (architecture, risk map, available knowledge), overview narrative, and dependency graph summary. This is the starting point for understanding any codebase. Always call this first.',\n inputSchema: {},\n },\n async () => {\n const constitution = await readFile(cortexPath(projectRoot, 'constitution.md'))\n const overview = await readFile(cortexPath(projectRoot, 'overview.md'))\n const manifest = await readManifest(projectRoot)\n\n const graph = await readGraph(projectRoot)\n let graphSummary = null\n if (graph) {\n graphSummary = {\n modules: graph.modules.length,\n imports: graph.imports.length,\n entryPoints: graph.entryPoints,\n mostImported: getMostImportedFiles(graph, 5),\n }\n }\n\n const freshness = await getFreshness()\n\n return textResult(withFreshness({\n constitution,\n overview,\n manifest,\n graphSummary,\n }, freshness))\n }\n )\n\n // --- Tool 2: get_module_context ---\n server.registerTool(\n 'get_module_context',\n {\n description: 'Get deep context for a specific module: purpose, data flow, public API, gotchas, dependencies, and temporal signals (churn, coupling, bug history). Use after get_project_overview when you need to work on a specific module.',\n inputSchema: {\n name: z.string().describe('Module name (e.g., \"scoring\", \"api\", \"indexer\")'),\n },\n },\n async ({ name }) => {\n const doc = await readModuleDoc(projectRoot, name)\n if (!doc) {\n const available = await listModuleDocs(projectRoot)\n return textResult({ found: false, name, available, message: `Module \"${name}\" not found. Available modules: ${available.join(', ')}` })\n }\n\n // Get graph info for this module\n const graph = await readGraph(projectRoot)\n let deps = null\n if (graph) {\n deps = getModuleDependencies(graph, name)\n }\n\n const freshness = await getFreshness()\n\n return textResult(withFreshness({ found: true, name, doc, dependencies: deps }, freshness))\n }\n )\n\n // --- Tool 3: get_session_briefing ---\n server.registerTool(\n 'get_session_briefing',\n {\n description: 'Get a briefing of what changed since the last session. Shows files changed, modules affected, and decisions recorded. Use at the start of a new session to catch up.',\n inputSchema: {},\n },\n async () => {\n const latestId = await getLatestSession(projectRoot)\n if (!latestId) {\n return textResult({ hasSession: false, message: 'No previous sessions recorded.' })\n }\n\n const session = await readSession(projectRoot, latestId)\n const allSessions = await listSessions(projectRoot)\n const freshness = await getFreshness()\n\n return textResult(withFreshness({\n hasSession: true,\n latest: session,\n totalSessions: allSessions.length,\n recentSessionIds: allSessions.slice(0, 5),\n }, freshness))\n }\n )\n\n // --- Tool 4: search_knowledge ---\n server.registerTool(\n 'search_knowledge',\n {\n description: 'Search across all CodeCortex knowledge files (modules, decisions, patterns, sessions, constitution) for a keyword or phrase. Returns matching lines with context.',\n inputSchema: {\n query: z.string().describe('Search term or phrase'),\n },\n },\n async ({ query }) => {\n const results = await searchKnowledge(projectRoot, query)\n const freshness = await getFreshness()\n\n return textResult(withFreshness({\n query,\n totalResults: results.length,\n results: results.slice(0, 20),\n }, freshness))\n }\n )\n\n // --- Tool 5: get_decision_history ---\n server.registerTool(\n 'get_decision_history',\n {\n description: 'Get architectural decision records. Shows WHY the codebase is built the way it is. Filter by topic keyword.',\n inputSchema: {\n topic: z.string().optional().describe('Optional keyword to filter decisions'),\n },\n },\n async ({ topic }) => {\n const ids = await listDecisions(projectRoot)\n const decisions: string[] = []\n\n for (const id of ids) {\n const content = await readDecision(projectRoot, id)\n if (content) {\n if (!topic || content.toLowerCase().includes(topic.toLowerCase())) {\n decisions.push(content)\n }\n }\n }\n\n const freshness = await getFreshness()\n\n return textResult(withFreshness({\n total: decisions.length,\n topic: topic || 'all',\n decisions,\n }, freshness))\n }\n )\n\n // --- Tool 6: get_dependency_graph ---\n server.registerTool(\n 'get_dependency_graph',\n {\n description: 'Get the import/export dependency graph. Shows which files import which, external dependencies, and entry points. Optionally filter to a specific file or module.',\n inputSchema: {\n file: z.string().optional().describe('Filter to edges involving this file path'),\n module: z.string().optional().describe('Filter to edges involving this module name'),\n },\n },\n async ({ file, module }) => {\n const graph = await readGraph(projectRoot)\n if (!graph) return textResult({ found: false, message: 'No graph data. Run codecortex init first.' })\n\n const freshness = await getFreshness()\n\n if (module) {\n const deps = getModuleDependencies(graph, module)\n return textResult(withFreshness({ module, ...deps }, freshness))\n }\n\n if (file) {\n const imports = graph.imports.filter(e => e.source.includes(file) || e.target.includes(file))\n const calls = graph.calls.filter(e => e.file.includes(file))\n return textResult(withFreshness({ file, imports, calls }, freshness))\n }\n\n return textResult(withFreshness(graph, freshness))\n }\n )\n\n // --- Tool 7: lookup_symbol ---\n server.registerTool(\n 'lookup_symbol',\n {\n description: 'Look up a symbol (function, class, type, interface, const) by name. Returns file path, line numbers, signature, and whether it\\'s exported. Use to find where something is defined.',\n inputSchema: {\n name: z.string().describe('Symbol name to search for'),\n kind: z.enum(['function', 'class', 'interface', 'type', 'const', 'enum', 'method', 'property', 'variable']).optional().describe('Filter by symbol kind'),\n file: z.string().optional().describe('Filter by file path (partial match)'),\n },\n },\n async ({ name, kind, file }) => {\n const content = await readFile(cortexPath(projectRoot, 'symbols.json'))\n if (!content) return textResult({ found: false, message: 'No symbol index. Run codecortex init first.' })\n\n const index: SymbolIndex = JSON.parse(content)\n let matches = index.symbols.filter(s =>\n s.name.toLowerCase().includes(name.toLowerCase())\n )\n\n if (kind) matches = matches.filter(s => s.kind === kind)\n if (file) matches = matches.filter(s => s.file.includes(file))\n\n const freshness = await getFreshness()\n\n return textResult(withFreshness({\n query: { name, kind, file },\n totalMatches: matches.length,\n symbols: matches.slice(0, 30),\n }, freshness))\n }\n )\n\n // --- Tool 8: get_change_coupling ---\n server.registerTool(\n 'get_change_coupling',\n {\n description: 'CRITICAL: Call this BEFORE editing any file. Shows files that historically change together. If file A is coupled with file B, editing A without B will likely cause a bug. Hidden couplings (no import between files) are especially dangerous.',\n inputSchema: {\n file: z.string().optional().describe('Show coupling for this specific file'),\n minStrength: z.number().min(0).max(1).default(0.3).describe('Minimum coupling strength (0-1). Default 0.3.'),\n },\n },\n async ({ file, minStrength }) => {\n const content = await readFile(cortexPath(projectRoot, 'temporal.json'))\n if (!content) return textResult({ found: false, message: 'No temporal data. Run codecortex init first.' })\n\n const temporal: TemporalData = JSON.parse(content)\n let coupling = temporal.coupling.filter(c => c.strength >= minStrength)\n\n if (file) {\n coupling = coupling.filter(c =>\n c.fileA.includes(file) || c.fileB.includes(file)\n )\n }\n\n const freshness = await getFreshness()\n\n return textResult(withFreshness({\n file: file || 'all',\n minStrength,\n couplings: coupling,\n warning: coupling.filter(c => !c.hasImport).length > 0\n ? 'HIDDEN DEPENDENCIES FOUND — some coupled files have NO import between them'\n : null,\n }, freshness))\n }\n )\n\n // --- Tool 9: get_hotspots ---\n server.registerTool(\n 'get_hotspots',\n {\n description: 'Get files ranked by risk: change frequency (churn), coupling count, and bug history. Volatile files with many couplings need extra care when editing.',\n inputSchema: {\n limit: z.number().int().min(1).max(50).default(10).describe('Number of files to return'),\n },\n },\n async ({ limit }) => {\n const content = await readFile(cortexPath(projectRoot, 'temporal.json'))\n if (!content) return textResult({ found: false, message: 'No temporal data. Run codecortex init first.' })\n\n const temporal: TemporalData = JSON.parse(content)\n\n // Calculate risk score: churn + coupling count + bug count\n const riskMap = new Map<string, { churn: number; couplings: number; bugs: number; risk: number }>()\n\n for (const h of temporal.hotspots) {\n riskMap.set(h.file, { churn: h.changes, couplings: 0, bugs: 0, risk: h.changes })\n }\n\n for (const c of temporal.coupling) {\n for (const f of [c.fileA, c.fileB]) {\n const entry = riskMap.get(f) || { churn: 0, couplings: 0, bugs: 0, risk: 0 }\n entry.couplings++\n entry.risk += c.strength * 2\n riskMap.set(f, entry)\n }\n }\n\n for (const b of temporal.bugHistory) {\n const entry = riskMap.get(b.file) || { churn: 0, couplings: 0, bugs: 0, risk: 0 }\n entry.bugs = b.fixCommits\n entry.risk += b.fixCommits * 3\n riskMap.set(b.file, entry)\n }\n\n const ranked = [...riskMap.entries()]\n .sort((a, b) => b[1].risk - a[1].risk)\n .slice(0, limit)\n .map(([file, data]) => ({ file, ...data, risk: Math.round(data.risk * 100) / 100 }))\n\n const freshness = await getFreshness()\n\n return textResult(withFreshness({\n period: `${temporal.periodDays} days`,\n totalCommits: temporal.totalCommits,\n hotspots: ranked,\n }, freshness))\n }\n )\n\n // --- Tool 10: get_edit_briefing ---\n server.registerTool(\n 'get_edit_briefing',\n {\n description: 'CALL THIS BEFORE EDITING FILES. Takes a list of files you plan to edit and returns everything you need to know: co-change warnings (files you must also update), risk assessment, who imports these files, relevant patterns, and recent change history. Prevents bugs from hidden dependencies.',\n inputSchema: {\n files: z.array(z.string()).min(1).describe('File paths you plan to edit (relative to project root)'),\n },\n },\n async ({ files }) => {\n const temporalContent = await readFile(cortexPath(projectRoot, 'temporal.json'))\n if (!temporalContent) return textResult({ found: false, message: 'No temporal data. Run codecortex init first.' })\n\n const temporal: TemporalData = JSON.parse(temporalContent)\n const graph = await readGraph(projectRoot)\n const patternsContent = await readFile(cortexPath(projectRoot, 'patterns.md'))\n\n const briefings = files.map(file => {\n // 1. Co-change warnings\n const couplings = temporal.coupling\n .filter(c => c.fileA.includes(file) || c.fileB.includes(file))\n .map(c => {\n const other = c.fileA.includes(file) ? c.fileB : c.fileA\n return {\n file: other,\n cochanges: c.cochanges,\n strength: c.strength,\n hasImport: c.hasImport,\n warning: c.warning || null,\n }\n })\n .sort((a, b) => b.strength - a.strength)\n\n // 2. Risk assessment\n const hotspot = temporal.hotspots.find(h => h.file.includes(file))\n const bugs = temporal.bugHistory.find(b => b.file.includes(file))\n const couplingCount = couplings.length\n const hiddenDeps = couplings.filter(c => !c.hasImport).length\n\n let riskLevel: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL' = 'LOW'\n const riskScore = (hotspot?.changes || 0) + (couplingCount * 2) + ((bugs?.fixCommits || 0) * 3) + (hiddenDeps * 4)\n\n if (riskScore >= 20) riskLevel = 'CRITICAL'\n else if (riskScore >= 12) riskLevel = 'HIGH'\n else if (riskScore >= 6) riskLevel = 'MEDIUM'\n\n // 3. Who imports this file\n let importedBy: string[] = []\n if (graph) {\n importedBy = getFileImporters(graph, file)\n }\n\n // 4. Recent changes\n const recentChange = hotspot ? {\n lastChanged: hotspot.lastChanged,\n daysSinceChange: hotspot.daysSinceChange,\n totalChanges: hotspot.changes,\n stability: hotspot.stability,\n } : null\n\n // 5. Bug history\n const bugHistory = bugs ? {\n fixCommits: bugs.fixCommits,\n lessons: bugs.lessons,\n } : null\n\n return {\n file,\n risk: {\n level: riskLevel,\n score: Math.round(riskScore * 100) / 100,\n reason: buildRiskReason(riskLevel, hotspot, couplingCount, hiddenDeps, bugs),\n },\n cochangeWarnings: couplings,\n importedBy,\n recentChange,\n bugHistory,\n }\n })\n\n // Files you should also consider editing (coupled but not in the input list)\n const inputSet = new Set(files)\n const alsoConsider = new Set<string>()\n for (const b of briefings) {\n for (const c of b.cochangeWarnings) {\n // Check if coupled file is NOT in the files being edited\n const coupledFile = c.file\n const isInInput = files.some(f => coupledFile.includes(f) || f.includes(coupledFile))\n if (!isInInput && c.strength >= 0.5) {\n alsoConsider.add(`${coupledFile} (${Math.round(c.strength * 100)}% co-change with ${b.file}${c.hasImport ? '' : ', NO import — hidden dep'})`)\n }\n }\n }\n\n const freshness = await getFreshness()\n\n return textResult(withFreshness({\n briefings,\n alsoConsiderEditing: [...alsoConsider],\n patterns: patternsContent || null,\n }, freshness))\n }\n )\n}\n\nfunction buildRiskReason(\n level: string,\n hotspot: { changes: number; stability: string } | undefined,\n couplings: number,\n hiddenDeps: number,\n bugs: { fixCommits: number } | undefined,\n): string {\n if (level === 'LOW') return 'Low change frequency, few couplings.'\n const parts: string[] = []\n if (hotspot && hotspot.changes >= 5) parts.push(`${hotspot.changes} changes (${hotspot.stability})`)\n if (couplings > 0) parts.push(`${couplings} coupled file${couplings === 1 ? '' : 's'}`)\n if (hiddenDeps > 0) parts.push(`${hiddenDeps} hidden dep${hiddenDeps === 1 ? '' : 's'}`)\n if (bugs && bugs.fixCommits > 0) parts.push(`${bugs.fixCommits} bug-fix commit${bugs.fixCommits === 1 ? '' : 's'}`)\n return parts.join(', ') + '.'\n}\n","import { readFile as fsRead, writeFile as fsWrite, mkdir, readdir, stat } from 'node:fs/promises'\nimport { existsSync, createWriteStream } from 'node:fs'\nimport { join, dirname } from 'node:path'\n\nexport async function readFile(path: string): Promise<string | null> {\n try {\n return await fsRead(path, 'utf-8')\n } catch {\n return null\n }\n}\n\nexport async function writeFile(path: string, content: string): Promise<void> {\n await ensureDir(dirname(path))\n await fsWrite(path, content, 'utf-8')\n}\n\nexport async function ensureDir(dir: string): Promise<void> {\n if (!existsSync(dir)) {\n await mkdir(dir, { recursive: true })\n }\n}\n\nexport async function listFiles(dir: string, extension?: string): Promise<string[]> {\n if (!existsSync(dir)) return []\n const entries = await readdir(dir, { withFileTypes: true })\n const files: string[] = []\n for (const entry of entries) {\n if (entry.isFile()) {\n if (!extension || entry.name.endsWith(extension)) {\n files.push(join(dir, entry.name))\n }\n }\n }\n return files\n}\n\nexport async function fileExists(path: string): Promise<boolean> {\n try {\n await stat(path)\n return true\n } catch {\n return false\n }\n}\n\nexport function cortexDir(projectRoot: string): string {\n return join(projectRoot, '.codecortex')\n}\n\nexport function cortexPath(projectRoot: string, ...segments: string[]): string {\n return join(projectRoot, '.codecortex', ...segments)\n}\n\nexport async function countLines(path: string): Promise<number> {\n const content = await readFile(path)\n if (!content) return 0\n return content.split('\\n').length\n}\n\n/** Stream-write a large array-based JSON object to avoid V8 string length limits. */\nexport async function writeJsonStream<T extends object>(path: string, obj: T, arrayKey: string & keyof T): Promise<void> {\n await ensureDir(dirname(path))\n const arr = obj[arrayKey] as unknown[]\n const stream = createWriteStream(path)\n stream.setMaxListeners(0)\n\n // Single error handler for the entire operation\n let streamError: Error | null = null\n stream.on('error', (err) => { streamError = err })\n\n function waitDrain(): Promise<void> {\n return new Promise((resolve) => stream.once('drain', resolve))\n }\n\n // Write non-array fields as header\n const header: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(obj)) {\n if (k !== arrayKey) header[k] = v\n }\n const headerJson = JSON.stringify(header)\n stream.write(headerJson.slice(0, -1) + `,\"${arrayKey}\":[`)\n\n // Write array elements in batches to reduce await overhead\n const BATCH_SIZE = 1000\n for (let i = 0; i < arr.length; i += BATCH_SIZE) {\n if (streamError) throw streamError\n const end = Math.min(i + BATCH_SIZE, arr.length)\n const chunks: string[] = []\n for (let j = i; j < end; j++) {\n chunks.push((j > 0 ? ',' : '') + JSON.stringify(arr[j]))\n }\n if (!stream.write(chunks.join(''))) {\n await waitDrain()\n }\n }\n\n stream.write(']}')\n\n return new Promise((resolve, reject) => {\n if (streamError) { reject(streamError); return }\n stream.on('finish', resolve)\n stream.on('error', reject)\n stream.end()\n })\n}\n\nexport async function fileSize(path: string): Promise<number> {\n try {\n const s = await stat(path)\n return s.size\n } catch {\n return 0\n }\n}\n","import { parse, stringify } from 'yaml'\n\nexport function parseYaml<T = unknown>(content: string): T {\n return parse(content) as T\n}\n\nexport function stringifyYaml(data: unknown): string {\n return stringify(data, { lineWidth: 120 })\n}\n","import type { CortexManifest } from '../types/index.js'\nimport { readFile, writeFile, cortexPath } from '../utils/files.js'\nimport { parseYaml, stringifyYaml } from '../utils/yaml.js'\n\nexport async function readManifest(projectRoot: string): Promise<CortexManifest | null> {\n const content = await readFile(cortexPath(projectRoot, 'cortex.yaml'))\n if (!content) return null\n return parseYaml<CortexManifest>(content)\n}\n\nexport async function writeManifest(projectRoot: string, manifest: CortexManifest): Promise<void> {\n const content = stringifyYaml(manifest)\n await writeFile(cortexPath(projectRoot, 'cortex.yaml'), content)\n}\n\nexport function createManifest(opts: {\n project: string\n root: string\n languages: string[]\n totalFiles: number\n totalSymbols: number\n totalModules: number\n}): CortexManifest {\n const now = new Date().toISOString()\n return {\n version: '1.0.0',\n project: opts.project,\n root: opts.root,\n generated: now,\n lastUpdated: now,\n languages: opts.languages,\n totalFiles: opts.totalFiles,\n totalSymbols: opts.totalSymbols,\n totalModules: opts.totalModules,\n tiers: {\n hot: ['cortex.yaml', 'constitution.md', 'overview.md', 'graph.json', 'symbols.json', 'temporal.json'],\n warm: ['modules/'],\n cold: ['decisions/', 'sessions/', 'patterns.md'],\n },\n }\n}\n\nexport async function updateManifest(\n projectRoot: string,\n updates: Partial<Pick<CortexManifest, 'totalFiles' | 'totalSymbols' | 'totalModules' | 'languages'>>\n): Promise<CortexManifest | null> {\n const manifest = await readManifest(projectRoot)\n if (!manifest) return null\n\n const updated: CortexManifest = {\n ...manifest,\n ...updates,\n lastUpdated: new Date().toISOString(),\n }\n\n await writeManifest(projectRoot, updated)\n return updated\n}\n","import type { DependencyGraph, ImportEdge, CallEdge, ModuleNode, ChangeCoupling } from '../types/index.js'\nimport { readFile, writeFile, ensureDir, cortexPath } from '../utils/files.js'\nimport { createWriteStream } from 'node:fs'\nimport { dirname } from 'node:path'\n\nexport async function readGraph(projectRoot: string): Promise<DependencyGraph | null> {\n const content = await readFile(cortexPath(projectRoot, 'graph.json'))\n if (!content) return null\n return JSON.parse(content) as DependencyGraph\n}\n\nexport async function writeGraph(projectRoot: string, graph: DependencyGraph): Promise<void> {\n const path = cortexPath(projectRoot, 'graph.json')\n await ensureDir(dirname(path))\n const stream = createWriteStream(path)\n stream.setMaxListeners(0)\n\n function waitDrain(): Promise<void> {\n return new Promise((resolve) => stream.once('drain', resolve))\n }\n\n async function writeArray(arr: unknown[]): Promise<void> {\n stream.write('[')\n const BATCH = 1000\n for (let i = 0; i < arr.length; i += BATCH) {\n const end = Math.min(i + BATCH, arr.length)\n const chunks: string[] = []\n for (let j = i; j < end; j++) {\n chunks.push((j > 0 ? ',' : '') + JSON.stringify(arr[j]))\n }\n if (!stream.write(chunks.join(''))) await waitDrain()\n }\n stream.write(']')\n }\n\n // Write scalar fields\n stream.write(`{\"generated\":${JSON.stringify(graph.generated)},\"modules\":`)\n await writeArray(graph.modules)\n stream.write(',\"imports\":')\n await writeArray(graph.imports)\n stream.write(',\"calls\":')\n await writeArray(graph.calls)\n stream.write(`,\"entryPoints\":${JSON.stringify(graph.entryPoints)}`)\n stream.write(`,\"externalDeps\":${JSON.stringify(graph.externalDeps)}`)\n stream.write('}')\n\n return new Promise((resolve, reject) => {\n stream.on('finish', resolve)\n stream.on('error', reject)\n stream.end()\n })\n}\n\nexport function buildGraph(opts: {\n modules: ModuleNode[]\n imports: ImportEdge[]\n calls: CallEdge[]\n entryPoints: string[]\n externalDeps: Record<string, string[]>\n}): DependencyGraph {\n return {\n generated: new Date().toISOString(),\n modules: opts.modules,\n imports: opts.imports,\n calls: opts.calls,\n entryPoints: opts.entryPoints,\n externalDeps: opts.externalDeps,\n }\n}\n\nexport function getModuleDependencies(graph: DependencyGraph, moduleName: string): {\n imports: ImportEdge[]\n importedBy: ImportEdge[]\n calls: CallEdge[]\n} {\n const moduleFiles = new Set(\n graph.modules.find(m => m.name === moduleName)?.files || []\n )\n\n return {\n imports: graph.imports.filter(e => moduleFiles.has(e.source)),\n importedBy: graph.imports.filter(e => moduleFiles.has(e.target)),\n calls: graph.calls.filter(e => moduleFiles.has(e.file)),\n }\n}\n\nexport function getFileImporters(graph: DependencyGraph, file: string): string[] {\n return graph.imports\n .filter(e => e.target.includes(file))\n .map(e => e.source)\n}\n\nexport function getMostImportedFiles(graph: DependencyGraph, limit: number = 10): { file: string; importCount: number }[] {\n const counts = new Map<string, number>()\n for (const edge of graph.imports) {\n counts.set(edge.target, (counts.get(edge.target) || 0) + 1)\n }\n\n return [...counts.entries()]\n .sort((a, b) => b[1] - a[1])\n .slice(0, limit)\n .map(([file, importCount]) => ({ file, importCount }))\n}\n\nexport function enrichCouplingWithImports(\n graph: DependencyGraph,\n coupling: ChangeCoupling[]\n): void {\n const importPairs = new Set<string>()\n for (const edge of graph.imports) {\n importPairs.add([edge.source, edge.target].sort().join('|'))\n }\n\n for (const pair of coupling) {\n const key = [pair.fileA, pair.fileB].sort().join('|')\n pair.hasImport = importPairs.has(key)\n if (pair.strength >= 0.7 && !pair.hasImport) {\n pair.warning = `HIDDEN DEPENDENCY — ${Math.round(pair.strength * 100)}% co-change rate`\n }\n }\n}\n","import type { ModuleAnalysis, DecisionRecord, CodingPattern } from '../types/index.js'\n\nexport function generateModuleDoc(analysis: ModuleAnalysis): string {\n const lines: string[] = [\n `# Module: ${analysis.name}`,\n '',\n `## Purpose`,\n analysis.purpose,\n '',\n `## Data Flow`,\n analysis.dataFlow,\n '',\n `## Public API`,\n ...analysis.publicApi.map(api => `- \\`${api}\\``),\n '',\n `## Dependencies`,\n ...analysis.dependencies.map(dep => `- ${dep}`),\n ]\n\n if (analysis.gotchas.length > 0) {\n lines.push('', `## Gotchas`, ...analysis.gotchas.map(g => `- ${g}`))\n }\n\n if (analysis.temporalSignals) {\n const t = analysis.temporalSignals\n lines.push(\n '',\n `## Temporal Signals`,\n `- **Churn:** ${t.churn}`,\n `- **Coupled with:** ${t.coupledWith.join(', ') || 'none'}`,\n `- **Stability:** ${t.stability}`,\n )\n if (t.bugHistory.length > 0) {\n lines.push(`- **Bug history:** ${t.bugHistory.join('; ')}`)\n }\n lines.push(`- **Last changed:** ${t.lastChanged}`)\n }\n\n return lines.join('\\n') + '\\n'\n}\n\nexport function generateDecisionDoc(decision: DecisionRecord): string {\n const lines: string[] = [\n `# Decision: ${decision.title}`,\n '',\n `**Date:** ${decision.date}`,\n `**Status:** ${decision.status}`,\n '',\n `## Context`,\n decision.context,\n '',\n `## Decision`,\n decision.decision,\n ]\n\n if (decision.alternatives.length > 0) {\n lines.push('', `## Alternatives Considered`, ...decision.alternatives.map(a => `- ${a}`))\n }\n\n if (decision.consequences.length > 0) {\n lines.push('', `## Consequences`, ...decision.consequences.map(c => `- ${c}`))\n }\n\n return lines.join('\\n') + '\\n'\n}\n\nexport function generatePatternEntry(pattern: CodingPattern): string {\n const lines: string[] = [\n `### ${pattern.name}`,\n '',\n pattern.description,\n '',\n '```',\n pattern.example,\n '```',\n ]\n\n if (pattern.files.length > 0) {\n lines.push('', `Files: ${pattern.files.map(f => `\\`${f}\\``).join(', ')}`)\n }\n\n return lines.join('\\n')\n}\n","import type { ModuleAnalysis } from '../types/index.js'\nimport { readFile, writeFile, listFiles, cortexPath, ensureDir } from '../utils/files.js'\nimport { generateModuleDoc } from '../utils/markdown.js'\n\nexport async function readModuleDoc(projectRoot: string, moduleName: string): Promise<string | null> {\n return readFile(cortexPath(projectRoot, 'modules', `${moduleName}.md`))\n}\n\nexport async function writeModuleDoc(projectRoot: string, analysis: ModuleAnalysis): Promise<void> {\n const dir = cortexPath(projectRoot, 'modules')\n await ensureDir(dir)\n const content = generateModuleDoc(analysis)\n await writeFile(cortexPath(projectRoot, 'modules', `${analysis.name}.md`), content)\n}\n\nexport async function listModuleDocs(projectRoot: string): Promise<string[]> {\n const dir = cortexPath(projectRoot, 'modules')\n const files = await listFiles(dir, '.md')\n return files.map(f => {\n const name = f.split('/').pop() || ''\n return name.replace('.md', '')\n })\n}\n\nexport function buildAnalysisPrompt(moduleName: string, sourceFiles: { path: string; content: string }[]): string {\n const fileList = sourceFiles.map(f => `### ${f.path}\\n\\`\\`\\`\\n${f.content}\\n\\`\\`\\``).join('\\n\\n')\n\n return `Analyze the \"${moduleName}\" module. Return a JSON object with this exact structure:\n\n{\n \"name\": \"${moduleName}\",\n \"purpose\": \"One paragraph describing what this module does and why it exists\",\n \"dataFlow\": \"How data flows through this module — inputs, transformations, outputs\",\n \"publicApi\": [\"list\", \"of\", \"exported\", \"functions\", \"and\", \"types\"],\n \"gotchas\": [\"Things that are surprising or could cause bugs\"],\n \"dependencies\": [\"What this module depends on and why\"]\n}\n\nSource files:\n\n${fileList}`\n}\n","import type { SessionLog } from '../types/index.js'\nimport { readFile, writeFile, listFiles, cortexPath, ensureDir } from '../utils/files.js'\n\nexport async function writeSession(projectRoot: string, session: SessionLog): Promise<void> {\n const dir = cortexPath(projectRoot, 'sessions')\n await ensureDir(dir)\n\n const lines = [\n `# Session: ${session.date}`,\n '',\n `**ID:** ${session.id}`,\n session.previousSession ? `**Previous:** ${session.previousSession}` : null,\n '',\n `## Summary`,\n session.summary,\n '',\n `## Files Changed`,\n ...session.filesChanged.map(f => `- \\`${f}\\``),\n '',\n `## Modules Affected`,\n ...session.modulesAffected.map(m => `- ${m}`),\n ].filter(Boolean) as string[]\n\n if (session.decisionsRecorded.length > 0) {\n lines.push('', `## Decisions Recorded`, ...session.decisionsRecorded.map(d => `- ${d}`))\n }\n\n await writeFile(cortexPath(projectRoot, 'sessions', `${session.id}.md`), lines.join('\\n') + '\\n')\n}\n\nexport async function readSession(projectRoot: string, id: string): Promise<string | null> {\n return readFile(cortexPath(projectRoot, 'sessions', `${id}.md`))\n}\n\nexport async function listSessions(projectRoot: string): Promise<string[]> {\n const dir = cortexPath(projectRoot, 'sessions')\n const files = await listFiles(dir, '.md')\n return files\n .map(f => (f.split('/').pop() || '').replace('.md', ''))\n .sort()\n .reverse()\n}\n\nexport async function getLatestSession(projectRoot: string): Promise<string | null> {\n const sessions = await listSessions(projectRoot)\n return sessions[0] ?? null\n}\n\nexport function createSession(opts: {\n filesChanged: string[]\n modulesAffected: string[]\n decisionsRecorded?: string[]\n summary: string\n previousSession?: string\n}): SessionLog {\n const now = new Date()\n const id = now.toISOString().replace(/[:.]/g, '-').slice(0, 19)\n\n return {\n id,\n date: now.toISOString(),\n previousSession: opts.previousSession,\n filesChanged: opts.filesChanged,\n modulesAffected: opts.modulesAffected,\n decisionsRecorded: opts.decisionsRecorded || [],\n summary: opts.summary,\n }\n}\n","import type { DecisionRecord } from '../types/index.js'\nimport { readFile, writeFile, listFiles, cortexPath, ensureDir } from '../utils/files.js'\nimport { generateDecisionDoc } from '../utils/markdown.js'\n\nexport async function readDecision(projectRoot: string, id: string): Promise<string | null> {\n return readFile(cortexPath(projectRoot, 'decisions', `${id}.md`))\n}\n\nexport async function writeDecision(projectRoot: string, decision: DecisionRecord): Promise<void> {\n const dir = cortexPath(projectRoot, 'decisions')\n await ensureDir(dir)\n const content = generateDecisionDoc(decision)\n await writeFile(cortexPath(projectRoot, 'decisions', `${decision.id}.md`), content)\n}\n\nexport async function listDecisions(projectRoot: string): Promise<string[]> {\n const dir = cortexPath(projectRoot, 'decisions')\n const files = await listFiles(dir, '.md')\n return files.map(f => {\n const name = f.split('/').pop() || ''\n return name.replace('.md', '')\n })\n}\n\nexport function createDecision(input: {\n title: string\n context: string\n decision: string\n alternatives?: string[]\n consequences?: string[]\n}): DecisionRecord {\n const id = input.title\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '')\n .slice(0, 60)\n\n return {\n id,\n date: new Date().toISOString().split('T')[0] ?? '',\n title: input.title,\n context: input.context,\n decision: input.decision,\n alternatives: input.alternatives || [],\n consequences: input.consequences || [],\n status: 'accepted',\n }\n}\n","import { readFile, listFiles, cortexPath } from '../utils/files.js'\nimport { readdir } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { existsSync } from 'node:fs'\n\nexport interface SearchResult {\n file: string\n line: number\n content: string\n context: string\n}\n\nexport async function searchKnowledge(projectRoot: string, query: string): Promise<SearchResult[]> {\n const cortexRoot = cortexPath(projectRoot)\n if (!existsSync(cortexRoot)) return []\n\n const results: SearchResult[] = []\n const queryLower = query.toLowerCase()\n\n const allFiles = await getAllCortexFiles(cortexRoot)\n\n for (const filePath of allFiles) {\n const content = await readFile(filePath)\n if (!content) continue\n\n const lines = content.split('\\n')\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]\n if (line?.toLowerCase().includes(queryLower)) {\n // Get surrounding context (2 lines before and after)\n const start = Math.max(0, i - 2)\n const end = Math.min(lines.length - 1, i + 2)\n const context = lines.slice(start, end + 1).join('\\n')\n\n results.push({\n file: filePath.replace(cortexRoot + '/', ''),\n line: i + 1,\n content: line.trim(),\n context,\n })\n }\n }\n }\n\n return results\n}\n\nasync function getAllCortexFiles(dir: string): Promise<string[]> {\n const files: string[] = []\n\n if (!existsSync(dir)) return files\n\n const entries = await readdir(dir, { withFileTypes: true })\n for (const entry of entries) {\n const fullPath = join(dir, entry.name)\n if (entry.isDirectory()) {\n const subFiles = await getAllCortexFiles(fullPath)\n files.push(...subFiles)\n } else if (entry.isFile() && (entry.name.endsWith('.md') || entry.name.endsWith('.json') || entry.name.endsWith('.yaml'))) {\n files.push(fullPath)\n }\n }\n\n return files\n}\n","import simpleGit from 'simple-git'\n\nexport interface DiffResult {\n filesChanged: string[]\n insertions: number\n deletions: number\n summary: string\n}\n\nexport async function getUncommittedDiff(root: string): Promise<DiffResult> {\n const git = simpleGit(root)\n const diff = await git.diffSummary()\n\n return {\n filesChanged: diff.files.map(f => f.file),\n insertions: diff.insertions,\n deletions: diff.deletions,\n summary: `${diff.files.length} files changed, +${diff.insertions} -${diff.deletions}`,\n }\n}\n\nexport async function getDiffSinceCommit(root: string, commitHash: string): Promise<DiffResult> {\n const git = simpleGit(root)\n const diff = await git.diffSummary([commitHash, 'HEAD'])\n\n return {\n filesChanged: diff.files.map(f => f.file),\n insertions: diff.insertions,\n deletions: diff.deletions,\n summary: `${diff.files.length} files changed since ${commitHash.slice(0, 7)}, +${diff.insertions} -${diff.deletions}`,\n }\n}\n\nexport async function getChangedFilesSinceDate(root: string, sinceDate: string): Promise<string[]> {\n const git = simpleGit(root)\n const log = await git.log({ '--since': sinceDate, '--name-only': null })\n\n const files = new Set<string>()\n for (const commit of log.all) {\n const diff = commit.diff\n if (diff) {\n for (const file of diff.files) {\n files.add(file.file)\n }\n }\n }\n\n return [...files]\n}\n\nexport function mapFilesToModules(files: string[]): Map<string, string[]> {\n const moduleMap = new Map<string, string[]>()\n\n for (const file of files) {\n const parts = file.split('/')\n let module = 'root'\n\n if (parts[0] === 'src' && parts.length >= 3 && parts[1]) {\n module = parts[1]\n } else if (parts[0] === 'lib' && parts.length >= 3 && parts[1]) {\n module = parts[1]\n }\n\n const existing = moduleMap.get(module) || []\n existing.push(file)\n moduleMap.set(module, existing)\n }\n\n return moduleMap\n}\n","import simpleGit from 'simple-git'\n\nexport interface CommitInfo {\n hash: string\n date: string\n message: string\n author: string\n filesChanged: string[]\n}\n\nexport async function getCommitHistory(root: string, days: number = 90): Promise<CommitInfo[]> {\n const git = simpleGit(root)\n const since = new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString().split('T')[0]\n\n const log = await git.log({\n '--since': since,\n '--stat': null,\n maxCount: 500,\n })\n\n return log.all.map(commit => ({\n hash: commit.hash,\n date: commit.date,\n message: commit.message,\n author: commit.author_name,\n filesChanged: parseStatFiles(commit.diff),\n }))\n}\n\nfunction parseStatFiles(diff: { files?: { file: string }[] } | null | undefined): string[] {\n if (!diff || !diff.files) return []\n return diff.files.map((f) => f.file)\n}\n\nexport async function getLastCommitDate(root: string, file: string): Promise<string | null> {\n const git = simpleGit(root)\n try {\n const log = await git.log({ file, maxCount: 1 })\n return log.latest?.date || null\n } catch {\n return null\n }\n}\n\nexport async function isGitRepo(root: string): Promise<boolean> {\n const git = simpleGit(root)\n try {\n await git.status()\n return true\n } catch {\n return false\n }\n}\n\nexport async function getHeadCommit(root: string): Promise<string | null> {\n const git = simpleGit(root)\n try {\n const log = await git.log({ maxCount: 1 })\n return log.latest?.hash || null\n } catch {\n return null\n }\n}\n","import { readManifest } from './manifest.js'\nimport { getChangedFilesSinceDate } from '../git/diff.js'\nimport { isGitRepo } from '../git/history.js'\n\nexport type FreshnessStatus = 'fresh' | 'slightly_stale' | 'stale' | 'very_stale'\n\nexport interface FreshnessInfo {\n status: FreshnessStatus\n lastAnalyzed: string\n daysSinceAnalysis: number\n filesChangedSince: number\n changedFiles: string[]\n message: string\n}\n\n/**\n * Compute freshness of .codecortex/ knowledge relative to the actual codebase.\n * Compares manifest.lastUpdated against git changes since that date.\n */\nexport async function computeFreshness(projectRoot: string): Promise<FreshnessInfo | null> {\n const manifest = await readManifest(projectRoot)\n if (!manifest) return null\n\n const lastUpdated = manifest.lastUpdated\n if (!lastUpdated) return null\n\n const isRepo = await isGitRepo(projectRoot)\n let changedFiles: string[] = []\n\n if (isRepo) {\n try {\n changedFiles = await getChangedFilesSinceDate(projectRoot, lastUpdated)\n // Filter out noise files that don't affect knowledge quality\n changedFiles = changedFiles.filter(f => {\n const base = f.split('/').pop() ?? ''\n return !base.endsWith('.lock') &&\n base !== 'package-lock.json' &&\n base !== 'yarn.lock' &&\n base !== 'pnpm-lock.yaml' &&\n base !== 'CHANGELOG.md' &&\n !f.startsWith('.codecortex/')\n })\n } catch {\n // Git operation failed — can't determine freshness from git\n changedFiles = []\n }\n }\n\n const now = new Date()\n const analyzed = new Date(lastUpdated)\n const daysSinceAnalysis = Math.floor((now.getTime() - analyzed.getTime()) / (1000 * 60 * 60 * 24))\n\n const count = changedFiles.length\n let status: FreshnessStatus\n let message: string\n\n if (count === 0 && daysSinceAnalysis <= 7) {\n status = 'fresh'\n message = 'Knowledge is up to date.'\n } else if (count <= 2 && daysSinceAnalysis <= 7) {\n status = 'slightly_stale'\n message = `${count} file${count === 1 ? '' : 's'} changed since last analysis. Minor drift.`\n } else if (count <= 5 || daysSinceAnalysis <= 14) {\n status = 'stale'\n message = `${count} file${count === 1 ? '' : 's'} changed since last analysis. Consider running \\`codecortex update\\`.`\n } else {\n status = 'very_stale'\n message = `${count} files changed over ${daysSinceAnalysis} days since last analysis. Run \\`codecortex update\\` before trusting this knowledge.`\n }\n\n return {\n status,\n lastAnalyzed: lastUpdated,\n daysSinceAnalysis,\n filesChangedSince: count,\n changedFiles: changedFiles.slice(0, 20), // Cap to avoid bloating response\n message,\n }\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { z } from 'zod'\nimport { readFile as readFileUtil, cortexPath } from '../../utils/files.js'\nimport { ModuleAnalysisSchema, DecisionInputSchema, PatternInputSchema, FeedbackInputSchema } from '../../types/schema.js'\nimport { writeModuleDoc, buildAnalysisPrompt, listModuleDocs } from '../../core/modules.js'\nimport { writeDecision, createDecision } from '../../core/decisions.js'\nimport { addPattern } from '../../core/patterns.js'\nimport { writeFile, ensureDir } from '../../utils/files.js'\nimport { readGraph } from '../../core/graph.js'\nimport type { ModuleAnalysis, TemporalData, Hotspot, ChangeCoupling, BugRecord } from '../../types/index.js'\nimport { readFile } from 'node:fs/promises'\nimport { join } from 'node:path'\n\nfunction textResult(data: unknown) {\n return { content: [{ type: 'text' as const, text: JSON.stringify(data, null, 2) }] }\n}\n\nexport function registerWriteTools(server: McpServer, projectRoot: string): void {\n // --- Tool 10: analyze_module ---\n server.registerTool(\n 'analyze_module',\n {\n description: 'Prepares a module for analysis. Returns the source files and a structured prompt. You should read the source files, analyze them, then call save_module_analysis with the result.',\n inputSchema: {\n name: z.string().describe('Module name (e.g., \"scoring\", \"api\")'),\n },\n },\n async ({ name }) => {\n const graph = await readGraph(projectRoot)\n if (!graph) {\n return textResult({ error: 'No graph data. Run codecortex init first.' })\n }\n\n const module = graph.modules.find(m => m.name === name)\n if (!module) {\n const available = graph.modules.map(m => m.name)\n return textResult({ error: `Module \"${name}\" not found`, available })\n }\n\n // Read source files for this module\n const sourceFiles: { path: string; content: string }[] = []\n for (const filePath of module.files) {\n try {\n const content = await readFile(join(projectRoot, filePath), 'utf-8')\n sourceFiles.push({ path: filePath, content })\n } catch {\n // Skip files that can't be read\n }\n }\n\n const prompt = buildAnalysisPrompt(name, sourceFiles)\n\n return textResult({\n module: name,\n files: module.files,\n prompt,\n instruction: 'Analyze the source files above and call save_module_analysis with the JSON result.',\n })\n }\n )\n\n // --- Tool 11: save_module_analysis ---\n server.registerTool(\n 'save_module_analysis',\n {\n description: 'Save the result of a module analysis. Provide the structured analysis (purpose, dataFlow, publicApi, gotchas, dependencies) and it will be persisted to modules/*.md.',\n inputSchema: {\n analysis: ModuleAnalysisSchema.describe('The structured module analysis'),\n },\n },\n async ({ analysis }) => {\n const moduleAnalysis: ModuleAnalysis = {\n ...analysis,\n }\n\n // Enrich with temporal data if available\n const temporalContent = await readFileUtil(cortexPath(projectRoot, 'temporal.json'))\n if (temporalContent) {\n const temporal: TemporalData = JSON.parse(temporalContent)\n const hotspot = temporal.hotspots?.find((h: Hotspot) =>\n h.file.includes(`/${analysis.name}/`) || h.file.includes(`${analysis.name}.`)\n )\n const couplings = temporal.coupling?.filter((c: ChangeCoupling) =>\n c.fileA.includes(`/${analysis.name}/`) || c.fileB.includes(`/${analysis.name}/`)\n ) || []\n const bugs = temporal.bugHistory?.filter((b: BugRecord) =>\n b.file.includes(`/${analysis.name}/`)\n ) || []\n\n if (hotspot || couplings.length > 0 || bugs.length > 0) {\n moduleAnalysis.temporalSignals = {\n churn: hotspot ? `${hotspot.changes} changes (${hotspot.stability})` : 'unknown',\n coupledWith: couplings.map((c: ChangeCoupling) => {\n const other = c.fileA.includes(`/${analysis.name}/`) ? c.fileB : c.fileA\n return `${other} (${c.cochanges} co-changes)`\n }),\n stability: hotspot?.stability || 'unknown',\n bugHistory: bugs.flatMap((b: BugRecord) => b.lessons),\n lastChanged: hotspot?.lastChanged || 'unknown',\n }\n }\n }\n\n await writeModuleDoc(projectRoot, moduleAnalysis)\n\n return textResult({\n saved: true,\n module: analysis.name,\n path: `.codecortex/modules/${analysis.name}.md`,\n })\n }\n )\n\n // --- Tool 12: record_decision ---\n server.registerTool(\n 'record_decision',\n {\n description: 'Record an architectural decision. Documents WHY something is built a certain way, what alternatives were considered, and consequences. Use whenever a non-obvious technical choice is made.',\n inputSchema: {\n title: z.string().describe('Decision title (e.g., \"Use tree-sitter for parsing\")'),\n context: z.string().describe('What situation led to this decision'),\n decision: z.string().describe('What was decided'),\n alternatives: z.array(z.string()).default([]).describe('What other options were considered'),\n consequences: z.array(z.string()).default([]).describe('Expected consequences of this decision'),\n },\n },\n async ({ title, context, decision, alternatives, consequences }) => {\n const record = createDecision({ title, context, decision, alternatives, consequences })\n await writeDecision(projectRoot, record)\n\n return textResult({\n recorded: true,\n id: record.id,\n path: `.codecortex/decisions/${record.id}.md`,\n })\n }\n )\n\n // --- Tool 13: update_patterns ---\n server.registerTool(\n 'update_patterns',\n {\n description: 'Add or update a coding pattern. Patterns document HOW code is written in this project (naming conventions, error handling, testing approaches). Returns \"added\", \"updated\", or \"noop\".',\n inputSchema: {\n name: z.string().describe('Pattern name (e.g., \"Error handling in API routes\")'),\n description: z.string().describe('What the pattern is and when to use it'),\n example: z.string().describe('Code example showing the pattern'),\n files: z.array(z.string()).default([]).describe('Files where this pattern is used'),\n },\n },\n async ({ name, description, example, files }) => {\n const result = await addPattern(projectRoot, { name, description, example, files })\n\n return textResult({\n action: result,\n pattern: name,\n path: '.codecortex/patterns.md',\n })\n }\n )\n\n // --- Tool 14: report_feedback ---\n server.registerTool(\n 'report_feedback',\n {\n description: 'Report incorrect or outdated knowledge. If you discover that a module doc, decision, or pattern is wrong, report it here. The feedback will be stored and used in the next analysis cycle.',\n inputSchema: {\n file: z.string().describe('Which knowledge file is incorrect (e.g., \"modules/scoring.md\")'),\n issue: z.string().describe('What is wrong or outdated'),\n reporter: z.string().default('agent').describe('Who is reporting (default: agent)'),\n },\n },\n async ({ file, issue, reporter }) => {\n const dir = cortexPath(projectRoot, 'feedback')\n await ensureDir(dir)\n\n const entry = {\n date: new Date().toISOString(),\n file,\n issue,\n reporter,\n }\n\n // Append to feedback log\n const feedbackPath = cortexPath(projectRoot, 'feedback', 'log.json')\n const existing = await readFileUtil(feedbackPath)\n const entries = existing ? JSON.parse(existing) : []\n entries.push(entry)\n await writeFile(feedbackPath, JSON.stringify(entries, null, 2))\n\n return textResult({\n recorded: true,\n totalFeedback: entries.length,\n message: 'Feedback recorded. Will be addressed in next codecortex update.',\n })\n }\n )\n}\n","import { z } from 'zod'\n\nexport const ModuleAnalysisSchema = z.object({\n name: z.string(),\n purpose: z.string(),\n dataFlow: z.string(),\n publicApi: z.array(z.string()),\n gotchas: z.array(z.string()),\n dependencies: z.array(z.string()),\n})\n\nexport const DecisionInputSchema = z.object({\n title: z.string(),\n context: z.string(),\n decision: z.string(),\n alternatives: z.array(z.string()).default([]),\n consequences: z.array(z.string()).default([]),\n})\n\nexport const PatternInputSchema = z.object({\n name: z.string(),\n description: z.string(),\n example: z.string(),\n files: z.array(z.string()).default([]),\n})\n\nexport const FeedbackInputSchema = z.object({\n file: z.string(),\n issue: z.string(),\n reporter: z.string().default('agent'),\n})\n","import type { CodingPattern } from '../types/index.js'\nimport { readFile, writeFile, cortexPath } from '../utils/files.js'\nimport { generatePatternEntry } from '../utils/markdown.js'\n\nexport async function readPatterns(projectRoot: string): Promise<string | null> {\n return readFile(cortexPath(projectRoot, 'patterns.md'))\n}\n\nexport async function addPattern(projectRoot: string, pattern: CodingPattern): Promise<'added' | 'updated' | 'noop'> {\n const existing = await readPatterns(projectRoot) || '# Coding Patterns\\n'\n\n // Check if pattern with same name already exists\n const nameRegex = new RegExp(`### ${escapeRegex(pattern.name)}`, 'i')\n if (nameRegex.test(existing)) {\n // Update: replace the existing pattern section\n const entry = generatePatternEntry(pattern)\n const sectionRegex = new RegExp(\n `### ${escapeRegex(pattern.name)}[\\\\s\\\\S]*?(?=### |$)`,\n 'i'\n )\n const updated = existing.replace(sectionRegex, entry + '\\n\\n')\n await writeFile(cortexPath(projectRoot, 'patterns.md'), updated)\n return 'updated'\n }\n\n // Add new pattern\n const entry = generatePatternEntry(pattern)\n const content = existing.trimEnd() + '\\n\\n' + entry + '\\n'\n await writeFile(cortexPath(projectRoot, 'patterns.md'), content)\n return 'added'\n}\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n"],"mappings":"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","names":["createWriteStream","dirname","readdir","join","existsSync","simpleGit","simpleGit","z","z","entry","readFile","join","textResult","z"]}
package/dist/cli/index.js CHANGED
@@ -6,11 +6,16 @@ import {
6
6
  createSession,
7
7
  enrichCouplingWithImports,
8
8
  ensureDir,
9
+ getCommitHistory,
10
+ getHeadCommit,
9
11
  getLatestSession,
10
12
  getModuleDependencies,
13
+ getUncommittedDiff,
14
+ isGitRepo,
11
15
  listDecisions,
12
16
  listModuleDocs,
13
17
  listSessions,
18
+ mapFilesToModules,
14
19
  readFile,
15
20
  readGraph,
16
21
  readManifest,
@@ -24,7 +29,7 @@ import {
24
29
  writeManifest,
25
30
  writeModuleDoc,
26
31
  writeSession
27
- } from "../chunk-PBYRGMCK.js";
32
+ } from "../chunk-4N3T43UG.js";
28
33
 
29
34
  // src/cli/index.ts
30
35
  import { createRequire as createRequire2 } from "module";
@@ -37,7 +42,7 @@ import { resolve } from "path";
37
42
  import { execSync } from "child_process";
38
43
  import { readFile as fsRead2, stat } from "fs/promises";
39
44
  import { join, relative, basename, extname } from "path";
40
- import { existsSync } from "fs";
45
+ import { existsSync, readFileSync as readFileSyncFs } from "fs";
41
46
 
42
47
  // src/extraction/parser.ts
43
48
  import { createRequire } from "module";
@@ -218,7 +223,7 @@ function detectProjectName(root) {
218
223
  const pkgPath = join(root, "package.json");
219
224
  if (existsSync(pkgPath)) {
220
225
  try {
221
- const pkg = JSON.parse(execSync(`cat "${pkgPath}"`, { encoding: "utf-8" }));
226
+ const pkg = JSON.parse(readFileSyncFs(pkgPath, "utf-8"));
222
227
  if (pkg.name) return pkg.name;
223
228
  } catch {
224
229
  }
@@ -226,7 +231,7 @@ function detectProjectName(root) {
226
231
  const cargoPath = join(root, "Cargo.toml");
227
232
  if (existsSync(cargoPath)) {
228
233
  try {
229
- const cargo = execSync(`cat "${cargoPath}"`, { encoding: "utf-8" });
234
+ const cargo = readFileSyncFs(cargoPath, "utf-8");
230
235
  const match = cargo.match(/name\s*=\s*"(.+?)"/);
231
236
  if (match?.[1]) return match[1];
232
237
  } catch {
@@ -295,8 +300,8 @@ async function walkDirectory(root, baseRoot) {
295
300
  }
296
301
  return paths;
297
302
  }
303
+ var MODULE_ROOTS = /* @__PURE__ */ new Set(["src", "lib", "pkg", "packages", "apps", "extensions", "crates", "internal", "cmd", "scripts", "tools", "rust"]);
298
304
  function detectModules(root, files) {
299
- const MODULE_ROOTS = /* @__PURE__ */ new Set(["src", "lib", "pkg", "packages", "apps", "extensions", "crates", "internal", "cmd", "scripts", "tools", "rust"]);
300
305
  const srcDirs = /* @__PURE__ */ new Set();
301
306
  for (const file of files) {
302
307
  const parts = file.path.split("/");
@@ -311,13 +316,31 @@ function detectModules(root, files) {
311
316
  }
312
317
  return [...srcDirs].sort();
313
318
  }
319
+ function buildModuleNodes(modules, files, symbols) {
320
+ return modules.map((modName) => {
321
+ const modFiles = files.filter((f) => {
322
+ const parts = f.path.split("/");
323
+ const topDir2 = parts[0] ?? "";
324
+ return MODULE_ROOTS.has(topDir2) && parts[1] === modName || parts[0] === modName;
325
+ });
326
+ const topDir = modFiles[0]?.path.split("/")[0] ?? "src";
327
+ return {
328
+ path: `${topDir}/${modName}`,
329
+ name: modName,
330
+ files: modFiles.map((f) => f.path),
331
+ language: modFiles[0]?.language || "unknown",
332
+ lines: modFiles.reduce((sum, f) => sum + f.lines, 0),
333
+ symbols: symbols.filter((s) => modFiles.some((f) => f.path === s.file)).length
334
+ };
335
+ });
336
+ }
314
337
  function detectEntryPoints(root, files, type) {
315
338
  const entryPoints = [];
316
339
  if (type === "node") {
317
340
  const pkgPath = join(root, "package.json");
318
341
  if (existsSync(pkgPath)) {
319
342
  try {
320
- const pkg = JSON.parse(execSync(`cat "${pkgPath}"`, { encoding: "utf-8" }));
343
+ const pkg = JSON.parse(readFileSyncFs(pkgPath, "utf-8"));
321
344
  if (pkg.main) entryPoints.push(pkg.main);
322
345
  if (pkg.bin) {
323
346
  const bins = typeof pkg.bin === "string" ? [pkg.bin] : Object.values(pkg.bin);
@@ -449,47 +472,6 @@ async function generateConstitution(projectRoot, data) {
449
472
  return content;
450
473
  }
451
474
 
452
- // src/git/history.ts
453
- import simpleGit from "simple-git";
454
- async function getCommitHistory(root, days = 90) {
455
- const git = simpleGit(root);
456
- const since = new Date(Date.now() - days * 24 * 60 * 60 * 1e3).toISOString().split("T")[0];
457
- const log = await git.log({
458
- "--since": since,
459
- "--stat": null,
460
- maxCount: 500
461
- });
462
- return log.all.map((commit) => ({
463
- hash: commit.hash,
464
- date: commit.date,
465
- message: commit.message,
466
- author: commit.author_name,
467
- filesChanged: parseStatFiles(commit.diff)
468
- }));
469
- }
470
- function parseStatFiles(diff) {
471
- if (!diff || !diff.files) return [];
472
- return diff.files.map((f) => f.file);
473
- }
474
- async function isGitRepo(root) {
475
- const git = simpleGit(root);
476
- try {
477
- await git.status();
478
- return true;
479
- } catch {
480
- return false;
481
- }
482
- }
483
- async function getHeadCommit(root) {
484
- const git = simpleGit(root);
485
- try {
486
- const log = await git.log({ maxCount: 1 });
487
- return log.latest?.hash || null;
488
- } catch {
489
- return null;
490
- }
491
- }
492
-
493
475
  // src/git/temporal.ts
494
476
  var TEMPORAL_NOISE_FILES = /* @__PURE__ */ new Set([
495
477
  "CHANGELOG.md",
@@ -583,18 +565,14 @@ function getChangeCoupling(commits) {
583
565
  const fileB = parts[1] ?? "";
584
566
  const maxChanges = Math.max(fileCounts.get(fileA) || 0, fileCounts.get(fileB) || 0);
585
567
  const strength = maxChanges > 0 ? cochanges / maxChanges : 0;
586
- const coupling = {
568
+ results.push({
587
569
  fileA,
588
570
  fileB,
589
571
  cochanges,
590
572
  strength: Math.round(strength * 100) / 100,
591
573
  hasImport: false
592
574
  // Will be enriched by graph analysis
593
- };
594
- if (strength >= 0.7 && !coupling.hasImport) {
595
- coupling.warning = `HIDDEN DEPENDENCY \u2014 ${Math.round(strength * 100)}% co-change rate`;
596
- }
597
- results.push(coupling);
575
+ });
598
576
  }
599
577
  return results.sort((a, b) => b.cochanges - a.cochanges);
600
578
  }
@@ -1615,23 +1593,7 @@ async function initCommand(opts) {
1615
1593
  }
1616
1594
  console.log("");
1617
1595
  console.log("Step 3/6: Building dependency graph...");
1618
- const MODULE_ROOTS = /* @__PURE__ */ new Set(["src", "lib", "pkg", "packages", "apps", "extensions", "crates", "internal", "cmd", "scripts", "tools", "rust"]);
1619
- const moduleNodes = project.modules.map((modName) => {
1620
- const modFiles = project.files.filter((f) => {
1621
- const parts = f.path.split("/");
1622
- const topDir2 = parts[0] ?? "";
1623
- return MODULE_ROOTS.has(topDir2) && parts[1] === modName || parts[0] === modName;
1624
- });
1625
- const topDir = modFiles[0]?.path.split("/")[0] ?? "src";
1626
- return {
1627
- path: `${topDir}/${modName}`,
1628
- name: modName,
1629
- files: modFiles.map((f) => f.path),
1630
- language: modFiles[0]?.language || "unknown",
1631
- lines: modFiles.reduce((sum, f) => sum + f.lines, 0),
1632
- symbols: allSymbols.filter((s) => modFiles.some((f) => f.path === s.file)).length
1633
- };
1634
- });
1596
+ const moduleNodes = buildModuleNodes(project.modules, project.files, allSymbols);
1635
1597
  const externalDeps = {};
1636
1598
  for (const file of project.files) {
1637
1599
  try {
@@ -1785,37 +1747,6 @@ async function serveCommand(opts) {
1785
1747
  // src/cli/commands/update.ts
1786
1748
  import { resolve as resolve3 } from "path";
1787
1749
  import { existsSync as existsSync5 } from "fs";
1788
-
1789
- // src/git/diff.ts
1790
- import simpleGit2 from "simple-git";
1791
- async function getUncommittedDiff(root) {
1792
- const git = simpleGit2(root);
1793
- const diff = await git.diffSummary();
1794
- return {
1795
- filesChanged: diff.files.map((f) => f.file),
1796
- insertions: diff.insertions,
1797
- deletions: diff.deletions,
1798
- summary: `${diff.files.length} files changed, +${diff.insertions} -${diff.deletions}`
1799
- };
1800
- }
1801
- function mapFilesToModules(files) {
1802
- const moduleMap = /* @__PURE__ */ new Map();
1803
- for (const file of files) {
1804
- const parts = file.split("/");
1805
- let module = "root";
1806
- if (parts[0] === "src" && parts.length >= 3 && parts[1]) {
1807
- module = parts[1];
1808
- } else if (parts[0] === "lib" && parts.length >= 3 && parts[1]) {
1809
- module = parts[1];
1810
- }
1811
- const existing = moduleMap.get(module) || [];
1812
- existing.push(file);
1813
- moduleMap.set(module, existing);
1814
- }
1815
- return moduleMap;
1816
- }
1817
-
1818
- // src/cli/commands/update.ts
1819
1750
  import { readFile as fsRead3 } from "fs/promises";
1820
1751
  async function updateCommand(opts) {
1821
1752
  const root = resolve3(opts.root);
@@ -1846,23 +1777,7 @@ async function updateCommand(opts) {
1846
1777
  }
1847
1778
  }
1848
1779
  console.log("Rebuilding dependency graph...");
1849
- const MODULE_ROOTS = /* @__PURE__ */ new Set(["src", "lib", "pkg", "packages", "apps", "extensions", "crates", "internal", "cmd", "scripts", "tools", "rust"]);
1850
- const moduleNodes = project.modules.map((modName) => {
1851
- const modFiles = project.files.filter((f) => {
1852
- const parts = f.path.split("/");
1853
- const topDir2 = parts[0] ?? "";
1854
- return MODULE_ROOTS.has(topDir2) && parts[1] === modName || parts[0] === modName;
1855
- });
1856
- const topDir = modFiles[0]?.path.split("/")[0] ?? "src";
1857
- return {
1858
- path: `${topDir}/${modName}`,
1859
- name: modName,
1860
- files: modFiles.map((f) => f.path),
1861
- language: modFiles[0]?.language || "unknown",
1862
- lines: modFiles.reduce((sum, f) => sum + f.lines, 0),
1863
- symbols: allSymbols.filter((s) => modFiles.some((f) => f.path === s.file)).length
1864
- };
1865
- });
1780
+ const moduleNodes = buildModuleNodes(project.modules, project.files, allSymbols);
1866
1781
  const externalDeps = {};
1867
1782
  for (const file of project.files) {
1868
1783
  try {
@@ -2318,7 +2233,7 @@ function pad3(str, len) {
2318
2233
  import { resolve as resolve9, join as join3 } from "path";
2319
2234
  import { existsSync as existsSync11 } from "fs";
2320
2235
  import { readFile as readFile4, writeFile as writeFile2, chmod, unlink } from "fs/promises";
2321
- import simpleGit3 from "simple-git";
2236
+ import simpleGit from "simple-git";
2322
2237
  var HOOK_START = "# --- codecortex-hook-start ---";
2323
2238
  var HOOK_END = "# --- codecortex-hook-end ---";
2324
2239
  var HOOK_TYPES = ["post-commit", "post-merge"];
@@ -2355,7 +2270,7 @@ function isEmptyHook(content) {
2355
2270
  return stripped.length === 0;
2356
2271
  }
2357
2272
  async function getGitHooksDir(root) {
2358
- const git = simpleGit3(root);
2273
+ const git = simpleGit(root);
2359
2274
  const gitDir = (await git.revparse(["--git-dir"])).trim();
2360
2275
  const resolved = resolve9(root, gitDir);
2361
2276
  return join3(resolved, "hooks");