codebrief 1.1.1 → 1.2.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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils.ts","../src/index.ts","../src/detect.ts","../src/prompts.ts","../src/snapshot.ts","../src/graph.ts","../src/generate.ts","../src/templates/framework-hints.ts","../src/templates/main-context.ts","../src/templates/cursor-rules.ts","../src/templates/claude-skills.ts","../src/templates/aider-context.ts","../src/summary.ts","../src/config.ts","../src/refresh.ts","../src/git-analysis.ts"],"sourcesContent":["import fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\n/**\n * Check if a file exists.\n */\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Read a file's contents, returning null if it doesn't exist.\n */\nexport async function readFileOr(filePath: string): Promise<string | null> {\n try {\n return await fs.readFile(filePath, \"utf-8\");\n } catch {\n return null;\n }\n}\n\n/**\n * Read and parse a JSON file, returning null on failure.\n */\nexport async function readJsonFile(filePath: string): Promise<Record<string, unknown> | null> {\n const content = await readFileOr(filePath);\n if (!content) return null;\n try {\n return JSON.parse(content);\n } catch {\n return null;\n }\n}\n\n/**\n * Estimate tokens from a string using a code-density-aware heuristic.\n * Code averages ~3.2-3.5 chars/token (more symbols than prose).\n * If the symbol ratio exceeds 8%, we assume code-heavy text.\n */\nexport function estimateTokens(text: string): number {\n if (text.length === 0) return 0;\n const symbolCount = text.replace(/[\\w\\s]/g, \"\").length;\n const symbolRatio = symbolCount / text.length;\n const charsPerToken = symbolRatio > 0.08 ? 3.2 : 3.5;\n return Math.ceil(text.length / charsPerToken);\n}\n\n/**\n * Format bytes as human-readable (e.g. \"4.2 KB\").\n */\nexport function formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n return `${(bytes / 1024).toFixed(1)} KB`;\n}\n\n/**\n * Ensure a directory exists, creating it recursively if needed.\n */\nexport async function ensureDir(dirPath: string): Promise<void> {\n await fs.mkdir(dirPath, { recursive: true });\n}\n\n/**\n * Write a file, creating parent directories if needed.\n */\nexport async function writeFileSafe(filePath: string, content: string): Promise<void> {\n await ensureDir(path.dirname(filePath));\n await fs.writeFile(filePath, content, \"utf-8\");\n}\n\n/**\n * Get all entries of a directory (names only), returning empty array if dir doesn't exist.\n */\nexport async function readDirSafe(dirPath: string): Promise<string[]> {\n try {\n return await fs.readdir(dirPath);\n } catch {\n return [];\n }\n}\n","import path from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\nimport { fileExists } from \"./utils.js\";\nimport { detectContext, enrichFrameworksWithUsage } from \"./detect.js\";\nimport { runPrompts } from \"./prompts.js\";\nimport { generateSnapshot } from \"./snapshot.js\";\nimport { generateFiles } from \"./generate.js\";\nimport { printSummary } from \"./summary.js\";\nimport {\n loadConfig,\n saveConfig,\n configToAnswers,\n computeSnapshotHash,\n} from \"./config.js\";\nimport { refreshSnapshot } from \"./refresh.js\";\nimport {\n buildImportGraph,\n getHubFiles,\n findCircularDeps,\n detectArchitecturalLayers,\n computeInstability,\n detectCommunities,\n computeExportCoverage,\n} from \"./graph.js\";\nimport { analyzeGitActivity } from \"./git-analysis.js\";\nimport { formatBytes } from \"./utils.js\";\nimport type { ContextAnalysis, ProgressCallback } from \"./types.js\";\n\nasync function main() {\n const startTime = performance.now();\n const args = process.argv.slice(2);\n const force = args.includes(\"--force\");\n const dryRun = args.includes(\"--dry-run\");\n const refresh = args.includes(\"--refresh-snapshot\");\n const reconfigure = args.includes(\"--reconfigure\");\n const check = args.includes(\"--check\");\n const verbose = args.includes(\"--verbose\") || args.includes(\"-v\");\n const generateSkills = args.includes(\"--generate-skills\");\n const maxTokensArg = args.find((a) => a.startsWith(\"--max-tokens=\"));\n const maxTokens = maxTokensArg ? parseInt(maxTokensArg.split(\"=\")[1], 10) : undefined;\n const targetDir = args.find((a) => !a.startsWith(\"-\") && a !== \"-v\") ?? process.cwd();\n const rootDir = path.resolve(targetDir);\n\n // Early validation: ensure this looks like a project directory\n const PROJECT_MARKERS = [\"package.json\", \"go.mod\", \"Cargo.toml\", \"pyproject.toml\", \"requirements.txt\"];\n const hasProjectMarker = (await Promise.all(\n PROJECT_MARKERS.map(f => fileExists(path.join(rootDir, f)))\n )).some(Boolean);\n\n if (!hasProjectMarker) {\n console.log(\"\");\n p.intro(pc.bold(\" codebrief \"));\n p.log.error(`No project found at ${pc.cyan(rootDir)}`);\n p.log.info(`Run ${pc.bold(\"npx codebrief\")} from a project directory, or pass a path:\\n ${pc.dim(\"npx codebrief ./my-project\")}`);\n p.outro(\"\");\n process.exit(1);\n }\n\n // Verbose logger: persists messages on screen (not swallowed by spinner)\n const verboseLog: ProgressCallback = (msg) => {\n if (verbose) p.log.info(pc.dim(msg));\n };\n\n // --check: fast path for shell integration (silent, exit code only)\n if (check) {\n const config = await loadConfig(rootDir);\n if (!config?.snapshotHash) {\n process.exit(0); // No config or no hash — nothing to check\n }\n const lang = config.language ?? \"other\";\n const currentHash = await computeSnapshotHash(rootDir, lang);\n if (currentHash !== config.snapshotHash) {\n const daysSince = config.snapshotGeneratedAt\n ? Math.floor((Date.now() - config.snapshotGeneratedAt) / (1000 * 60 * 60 * 24))\n : 0;\n const staleMsg = daysSince > 0 ? ` (last generated ${daysSince}d ago)` : \"\";\n console.log(`codebrief: snapshot is stale${staleMsg}. Run npx codebrief --refresh-snapshot`);\n process.exit(1);\n }\n process.exit(0);\n }\n\n console.log(\"\");\n p.intro(pc.bold(\" codebrief \"));\n\n // --refresh-snapshot: fast path — update snapshot in existing context file\n if (refresh) {\n await refreshSnapshot(rootDir);\n p.outro(pc.green(\"Snapshot refreshed!\"));\n return;\n }\n\n if (dryRun) {\n p.log.warn(pc.yellow(\"DRY RUN — no files will be written\"));\n }\n\n p.log.info(`Analyzing ${pc.cyan(rootDir)}`);\n\n // Step 1: Auto-detect\n const spinner = p.spinner();\n const spinnerProgress: ProgressCallback = (msg) => spinner.message(msg);\n\n spinner.start(\"Detecting tech stack...\");\n const detected = await detectContext(rootDir, spinnerProgress);\n spinner.stop(\"Detection complete.\");\n\n // Step 1.5: Build import graph\n spinner.start(`Building import graph (${detected.sourceFileCount} files)...`);\n const graph = await buildImportGraph(rootDir, detected.language, verbose ? verboseLog : spinnerProgress);\n const topHub = getHubFiles(graph, 1)[0];\n spinner.stop(\n `Import graph: ${graph.edges.length} edges, ${graph.externalImportCounts.size} packages.` +\n (topHub ? ` Top hub: ${topHub.path}` : \"\"),\n );\n\n // Step 1.6: Enrich framework detection with actual import usage\n detected.frameworks = enrichFrameworksWithUsage(\n detected.frameworks,\n graph.externalImportCounts,\n );\n\n // Discovery log (enhanced stack box)\n {\n const lines: string[] = [];\n const lang = detected.hasTypeScript ? \"TypeScript\" : detected.language !== \"other\" ? detected.language.charAt(0).toUpperCase() + detected.language.slice(1) : \"\";\n if (lang) lines.push(` Language: ${lang}`);\n if (detected.frameworks.length > 0) {\n lines.push(` Frameworks: ${detected.frameworks.map((f) => f.name).join(\", \")}`);\n }\n if (detected.linter !== \"none\") {\n lines.push(` Linter: ${detected.linter.charAt(0).toUpperCase() + detected.linter.slice(1)}`);\n }\n if (detected.packageManager !== \"none\") {\n lines.push(` Pkg mgr: ${detected.packageManager}`);\n }\n if (detected.testFramework) {\n lines.push(` Testing: ${detected.testFramework}`);\n }\n if (detected.ciProvider) {\n lines.push(` CI: ${detected.ciProvider}`);\n }\n if (detected.monorepo) {\n lines.push(` Monorepo: ${detected.monorepo.type} (${detected.monorepo.packages.length} package${detected.monorepo.packages.length === 1 ? \"\" : \"s\"})`);\n }\n if (detected.sourceFileCount > 0) {\n lines.push(` Files: ${detected.sourceFileCount} (${formatBytes(detected.totalSourceBytes)})`);\n }\n if (lines.length > 0) {\n p.note(lines.join(\"\\n\"), \"Detected Stack\");\n }\n }\n\n // Step 1.7: Structural analysis (per-algorithm messages)\n const fileCount = graph.centrality.size;\n\n spinner.start(`Running PageRank on ${fileCount} files...`);\n const hubFiles = getHubFiles(graph);\n verboseLog(`PageRank: found ${hubFiles.length} hub files`);\n\n spinner.message(\"Finding circular dependencies...\");\n const circularDeps = findCircularDeps(graph);\n verboseLog(`Tarjan SCC: ${circularDeps.length === 0 ? \"no cycles found\" : `${circularDeps.length} cycle(s)`}`);\n\n spinner.message(\"Detecting architecture layers...\");\n const { layers, layerEdges } = detectArchitecturalLayers(graph);\n verboseLog(`Layers: ${layers.map((l) => l.name).join(\", \") || \"none detected\"}`);\n\n spinner.message(\"Computing instability metrics...\");\n const instabilities = computeInstability(graph);\n verboseLog(`Instability: ${instabilities.length} high-risk file(s)`);\n\n spinner.message(\"Detecting module communities...\");\n const communities = detectCommunities(graph);\n verboseLog(`Communities: ${communities.length} cluster(s)`);\n\n spinner.message(\"Computing export coverage...\");\n const exportCoverage = computeExportCoverage(graph);\n verboseLog(`Export coverage: ${exportCoverage.length} files analyzed`);\n\n spinner.message(\"Analyzing git history...\");\n const gitActivity = detected.isGitRepo ? analyzeGitActivity(rootDir, verbose ? verboseLog : spinnerProgress) : null;\n if (gitActivity) verboseLog(`Git: ${gitActivity.hotFiles.length} active files, ${gitActivity.changeCoupling.length} coupled pairs`);\n\n const analysis: ContextAnalysis = { hubFiles, circularDeps, layers, layerEdges, gitActivity, instabilities, communities, exportCoverage };\n\n const analysisParts: string[] = [];\n if (hubFiles.length > 0) analysisParts.push(`${hubFiles.length} hub files`);\n if (layers.length > 0) analysisParts.push(`${layers.length} layers`);\n if (circularDeps.length > 0) analysisParts.push(`${circularDeps.length} circular dep${circularDeps.length === 1 ? \"\" : \"s\"}`);\n if (communities.length > 0) analysisParts.push(`${communities.length} module cluster${communities.length === 1 ? \"\" : \"s\"}`);\n if (gitActivity) analysisParts.push(`${gitActivity.hotFiles.length} active files`);\n spinner.stop(\n analysisParts.length > 0\n ? `Analysis: ${analysisParts.join(\", \")}.`\n : \"Analysis complete.\",\n );\n\n // Step 1.8: Check for saved config + staleness\n const savedConfig = await loadConfig(rootDir);\n\n if (savedConfig?.snapshotHash) {\n const currentHash = await computeSnapshotHash(rootDir, detected.language);\n if (currentHash !== savedConfig.snapshotHash && savedConfig.snapshotGeneratedAt) {\n const daysSince = Math.floor(\n (Date.now() - savedConfig.snapshotGeneratedAt) / (1000 * 60 * 60 * 24),\n );\n p.log.warn(\n pc.yellow(\n `Code snapshot may be stale (source files changed${daysSince > 0 ? `, last generated ${daysSince}d ago` : \"\"}). ` +\n `Run with ${pc.bold(\"--refresh-snapshot\")} to update.`,\n ),\n );\n }\n }\n\n let answers;\n\n if (savedConfig && !reconfigure) {\n // Use saved config — skip prompts\n p.log.info(\n `Using saved config from ${pc.cyan(\".codebrief.json\")} ` +\n pc.dim(\"(run with --reconfigure to change)\"),\n );\n answers = configToAnswers(savedConfig);\n\n // Re-check monorepo (structure may have changed)\n if (\n detected.monorepo &&\n detected.monorepo.packages.length > 0 &&\n !savedConfig.generatePerPackage\n ) {\n // Monorepo exists but wasn't configured — keep saved value\n }\n } else {\n // Step 2: Interactive prompts (with defaults from saved config if --reconfigure)\n answers = await runPrompts(detected, reconfigure ? savedConfig : null);\n\n // Save config for future runs\n if (!dryRun) {\n const hash = await computeSnapshotHash(rootDir, detected.language);\n await saveConfig(rootDir, answers, hash, detected.language);\n p.log.info(\n pc.dim(\"Saved config to .codebrief.json for future runs.\"),\n );\n }\n }\n\n // Step 3: Code snapshot (if requested)\n let snapshot = null;\n if (answers.generateSnapshot) {\n spinner.start(\"Scanning source files for code snapshot...\");\n snapshot = await generateSnapshot(detected, answers.snapshotPaths, graph, maxTokens, verbose ? verboseLog : spinnerProgress, gitActivity);\n const count = snapshot.entries.length;\n const budgetNote = snapshot.budgetExcluded\n ? ` (${snapshot.budgetExcluded} excluded by token budget)`\n : \"\";\n spinner.stop(\n count > 0\n ? `Found ${count} type${count === 1 ? \"\" : \"s\"}/signature${count === 1 ? \"\" : \"s\"}.${budgetNote}`\n : \"No extractable types found (snapshot will be skipped).\",\n );\n\n if (count === 0) {\n snapshot = null;\n }\n }\n\n // Step 4: Generate files\n spinner.start(\n dryRun ? \"Preparing context files...\" : \"Generating context files...\",\n );\n const shouldGenerateSkills = generateSkills || answers.ide === \"claude\";\n const files = await generateFiles(detected, answers, snapshot, force, dryRun, analysis, shouldGenerateSkills, verbose ? verboseLog : undefined);\n spinner.stop(\n dryRun\n ? `Would generate ${files.length} file${files.length === 1 ? \"\" : \"s\"}.`\n : `Generated ${files.length} file${files.length === 1 ? \"\" : \"s\"}.`,\n );\n\n if (files.length === 0) {\n p.outro(\"Nothing to write. Done!\");\n return;\n }\n\n // Step 5: Summary + token estimate\n printSummary(files, detected, snapshot, analysis);\n\n // Elapsed time\n const elapsed = ((performance.now() - startTime) / 1000).toFixed(1);\n\n if (dryRun) {\n p.outro(\n pc.yellow(\"DRY RUN complete — \") +\n pc.dim(`no files were written. Remove --dry-run to generate. (${elapsed}s)`),\n );\n return;\n }\n\n // Step 6: Done!\n p.outro(\n pc.green(`Done in ${elapsed}s! `) +\n pc.dim(\n \"Your context files are ready. They are living documents — keep them up to date as your project evolves.\",\n ),\n );\n}\n\nmain().catch((err) => {\n console.error(pc.red(\"Fatal error:\"), err);\n process.exit(1);\n});\n","import path from \"node:path\";\nimport fg from \"fast-glob\";\nimport type {\n DetectedContext,\n DetectedFramework,\n Language,\n Linter,\n MonorepoInfo,\n MonorepoPackage,\n PackageManager,\n ProgressCallback,\n} from \"./types.js\";\nimport { fileExists, readFileOr, readJsonFile, readDirSafe } from \"./utils.js\";\n\n/** Well-known directories to look for */\nconst KNOWN_DIRS = [\n \"src\",\n \"app\",\n \"pages\",\n \"components\",\n \"services\",\n \"stores\",\n \"store\",\n \"lib\",\n \"utils\",\n \"hooks\",\n \"api\",\n \"tests\",\n \"__tests__\",\n \"test\",\n \"public\",\n \"assets\",\n \"styles\",\n \"config\",\n \"scripts\",\n \"docs\",\n \"types\",\n];\n\n/** Framework detection rules: dependency name -> framework info */\nexport const FRAMEWORK_MAP: Record<string, string> = {\n // JS/TS\n expo: \"Expo\",\n \"react-native\": \"React Native\",\n next: \"Next.js\",\n react: \"React\",\n vue: \"Vue\",\n nuxt: \"Nuxt\",\n svelte: \"Svelte\",\n \"@sveltejs/kit\": \"SvelteKit\",\n angular: \"Angular\",\n \"@angular/core\": \"Angular\",\n express: \"Express\",\n fastify: \"Fastify\",\n hono: \"Hono\",\n \"nestjs/core\": \"NestJS\",\n \"@nestjs/core\": \"NestJS\",\n electron: \"Electron\",\n tauri: \"Tauri\",\n // State management\n zustand: \"Zustand\",\n redux: \"Redux\",\n \"@reduxjs/toolkit\": \"Redux Toolkit\",\n pinia: \"Pinia\",\n mobx: \"MobX\",\n jotai: \"Jotai\",\n recoil: \"Recoil\",\n // Testing\n jest: \"Jest\",\n vitest: \"Vitest\",\n playwright: \"Playwright\",\n cypress: \"Cypress\",\n // Styling\n tailwindcss: \"Tailwind CSS\",\n nativewind: \"NativeWind\",\n \"styled-components\": \"styled-components\",\n \"@emotion/react\": \"Emotion\",\n // ORM/DB\n prisma: \"Prisma\",\n \"@prisma/client\": \"Prisma\",\n drizzle: \"Drizzle\",\n \"drizzle-orm\": \"Drizzle\",\n typeorm: \"TypeORM\",\n mongoose: \"Mongoose\",\n};\n\n/** Python framework detection */\nconst PYTHON_FRAMEWORK_MAP: Record<string, string> = {\n django: \"Django\",\n flask: \"Flask\",\n fastapi: \"FastAPI\",\n starlette: \"Starlette\",\n sqlalchemy: \"SQLAlchemy\",\n pydantic: \"Pydantic\",\n pytest: \"pytest\",\n celery: \"Celery\",\n};\n\n/**\n * Auto-detect the tech stack of a project at the given root directory.\n */\nexport async function detectContext(rootDir: string, onProgress?: ProgressCallback): Promise<DetectedContext> {\n const ctx: DetectedContext = {\n rootDir,\n language: \"other\",\n hasTypeScript: false,\n packageManager: \"none\",\n linter: \"none\",\n frameworks: [],\n directories: [],\n dependencies: [],\n isGitRepo: false,\n totalSourceBytes: 0,\n sourceFileCount: 0,\n monorepo: null,\n };\n\n // Parallel checks for common project markers\n onProgress?.(\"Checking project markers...\");\n const [\n hasGit,\n hasPackageJson,\n hasGoMod,\n hasCargo,\n hasPyproject,\n hasRequirements,\n hasTsConfig,\n hasBiome,\n hasPnpmLock,\n hasYarnLock,\n hasBunLock,\n topEntries,\n ] = await Promise.all([\n fileExists(path.join(rootDir, \".git\")),\n readJsonFile(path.join(rootDir, \"package.json\")),\n fileExists(path.join(rootDir, \"go.mod\")),\n fileExists(path.join(rootDir, \"Cargo.toml\")),\n readJsonFile(path.join(rootDir, \"pyproject.toml\")), // won't parse TOML but that's ok\n fileExists(path.join(rootDir, \"requirements.txt\")),\n fileExists(path.join(rootDir, \"tsconfig.json\")),\n fileExists(path.join(rootDir, \"biome.json\")),\n fileExists(path.join(rootDir, \"pnpm-lock.yaml\")),\n fileExists(path.join(rootDir, \"yarn.lock\")),\n fileExists(path.join(rootDir, \"bun.lockb\")),\n readDirSafe(rootDir),\n ]);\n\n ctx.isGitRepo = hasGit;\n\n // -- Detect language + package manager --\n\n if (hasPackageJson) {\n const pkg = hasPackageJson;\n ctx.language = hasTsConfig ? \"typescript\" : \"javascript\";\n ctx.hasTypeScript = hasTsConfig;\n\n // Package manager\n if (hasPnpmLock) ctx.packageManager = \"pnpm\";\n else if (hasYarnLock) ctx.packageManager = \"yarn\";\n else if (hasBunLock) ctx.packageManager = \"bun\";\n else ctx.packageManager = \"npm\";\n\n // Collect all dependency names\n const deps = {\n ...(pkg.dependencies as Record<string, string> | undefined),\n ...(pkg.devDependencies as Record<string, string> | undefined),\n };\n ctx.dependencies = Object.keys(deps);\n\n // Detect frameworks\n const seen = new Set<string>();\n for (const dep of ctx.dependencies) {\n const framework = FRAMEWORK_MAP[dep];\n if (framework && !seen.has(framework)) {\n seen.add(framework);\n const version = deps[dep]?.replace(/^[\\^~>=<]/, \"\");\n ctx.frameworks.push({ name: framework, version });\n }\n }\n\n // Detect linter\n if (hasBiome) {\n ctx.linter = \"biome\";\n } else {\n const hasEslint = ctx.dependencies.includes(\"eslint\") ||\n topEntries.some((e) => e.startsWith(\".eslintrc\"));\n const hasPrettier = ctx.dependencies.includes(\"prettier\") ||\n topEntries.some((e) => e.startsWith(\".prettierrc\"));\n if (hasEslint) ctx.linter = \"eslint\";\n else if (hasPrettier) ctx.linter = \"prettier\";\n }\n } else if (hasGoMod) {\n ctx.language = \"go\";\n ctx.packageManager = \"go\";\n ctx.linter = \"gofmt\";\n } else if (hasCargo) {\n ctx.language = \"rust\";\n ctx.packageManager = \"cargo\";\n ctx.linter = \"rustfmt\";\n } else if (hasPyproject || hasRequirements) {\n ctx.language = \"python\";\n // Try to detect pip vs poetry\n if (topEntries.includes(\"poetry.lock\")) ctx.packageManager = \"poetry\";\n else ctx.packageManager = \"pip\";\n\n // Detect Python frameworks from requirements.txt\n if (hasRequirements) {\n const { readFileOr } = await import(\"./utils.js\");\n const reqContent = await readFileOr(path.join(rootDir, \"requirements.txt\"));\n if (reqContent) {\n const pkgs = reqContent\n .split(\"\\n\")\n .map((l) => l.trim().split(/[=<>!~[]/)[0].toLowerCase())\n .filter(Boolean);\n for (const pkg of pkgs) {\n const framework = PYTHON_FRAMEWORK_MAP[pkg];\n if (framework) {\n ctx.frameworks.push({ name: framework });\n }\n }\n ctx.dependencies = pkgs;\n }\n }\n\n // Detect Python linter\n const hasRuff = topEntries.includes(\"ruff.toml\") ||\n topEntries.some((e) => e === \"pyproject.toml\");\n if (hasRuff) ctx.linter = \"ruff\";\n else ctx.linter = \"none\";\n }\n\n // Report detected stack\n if (ctx.frameworks.length > 0) {\n const fwNames = ctx.frameworks.map((f) => f.name).join(\", \");\n const lang = ctx.hasTypeScript ? \"TypeScript\" : ctx.language !== \"other\" ? ctx.language : \"\";\n const parts = [lang, fwNames].filter(Boolean);\n onProgress?.(`Detected: ${parts.join(\" + \")}`);\n }\n\n // -- Detect directories --\n onProgress?.(\"Scanning directories...\");\n\n for (const dir of KNOWN_DIRS) {\n if (topEntries.includes(dir)) {\n ctx.directories.push(dir);\n }\n }\n\n // Also check inside src/ for nested structure\n if (topEntries.includes(\"src\")) {\n const srcEntries = await readDirSafe(path.join(rootDir, \"src\"));\n for (const entry of srcEntries) {\n if (KNOWN_DIRS.includes(entry)) {\n ctx.directories.push(`src/${entry}`);\n }\n }\n }\n\n // -- Count source files and total size --\n\n try {\n const extensions = getExtensionsForLanguage(ctx.language);\n const sourceFiles = await fg(\n extensions.map((ext) => `**/*${ext}`),\n {\n cwd: rootDir,\n ignore: [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n \"**/.next/**\",\n \"**/target/**\",\n \"**/vendor/**\",\n \"**/__pycache__/**\",\n \"**/venv/**\",\n \"**/.venv/**\",\n \"**/.Trash/**\",\n \"**/Library/**\",\n \"**/.git/**\",\n ],\n stats: true,\n },\n );\n\n ctx.sourceFileCount = sourceFiles.length;\n onProgress?.(`Counting ${sourceFiles.length} source files...`);\n ctx.totalSourceBytes = sourceFiles.reduce(\n (sum, f) => sum + (f.stats?.size ?? 0),\n 0,\n );\n } catch {\n // Non-critical, leave at 0\n }\n\n // -- Detect testing framework --\n ctx.testFramework = detectTestFramework(ctx.dependencies);\n\n // -- Detect CI provider --\n ctx.ciProvider = await detectCiProvider(rootDir, topEntries);\n\n // -- Detect monorepo --\n\n ctx.monorepo = await detectMonorepo(rootDir, topEntries);\n\n return ctx;\n}\n\n/** Test framework detection: dependency name -> display name */\nconst TEST_FRAMEWORK_MAP: Record<string, string> = {\n vitest: \"Vitest\",\n jest: \"Jest\",\n playwright: \"Playwright\",\n cypress: \"Cypress\",\n mocha: \"Mocha\",\n pytest: \"pytest\",\n};\n\nfunction detectTestFramework(dependencies: string[]): string | undefined {\n for (const [dep, name] of Object.entries(TEST_FRAMEWORK_MAP)) {\n if (dependencies.includes(dep)) return name;\n }\n return undefined;\n}\n\n/** CI provider detection: file/dir pattern -> display name */\nconst CI_PATTERNS: Array<{ path: string; name: string; isDir?: boolean }> = [\n { path: \".github/workflows\", name: \"GitHub Actions\", isDir: true },\n { path: \".gitlab-ci.yml\", name: \"GitLab CI\" },\n { path: \".circleci\", name: \"CircleCI\", isDir: true },\n { path: \"Jenkinsfile\", name: \"Jenkins\" },\n { path: \".travis.yml\", name: \"Travis CI\" },\n];\n\nasync function detectCiProvider(rootDir: string, topEntries: string[]): Promise<string | undefined> {\n for (const ci of CI_PATTERNS) {\n if (ci.isDir) {\n // Check if directory exists\n if (await fileExists(path.join(rootDir, ci.path))) return ci.name;\n } else {\n if (topEntries.includes(ci.path)) return ci.name;\n }\n }\n return undefined;\n}\n\nfunction getExtensionsForLanguage(lang: Language): string[] {\n switch (lang) {\n case \"typescript\":\n return [\".ts\", \".tsx\"];\n case \"javascript\":\n return [\".js\", \".jsx\", \".mjs\"];\n case \"python\":\n return [\".py\"];\n case \"go\":\n return [\".go\"];\n case \"rust\":\n return [\".rs\"];\n case \"java\":\n return [\".java\"];\n default:\n return [\".ts\", \".tsx\", \".js\", \".jsx\", \".py\", \".go\", \".rs\"];\n }\n}\n\n/**\n * Detect monorepo tooling and enumerate packages.\n */\nasync function detectMonorepo(\n rootDir: string,\n topEntries: string[],\n): Promise<MonorepoInfo | null> {\n // Determine monorepo type\n const hasTurboJson = topEntries.includes(\"turbo.json\");\n const hasNxJson = topEntries.includes(\"nx.json\");\n const hasPnpmWorkspace = topEntries.includes(\"pnpm-workspace.yaml\");\n\n let type: MonorepoInfo[\"type\"] | null = null;\n if (hasTurboJson) type = \"turborepo\";\n else if (hasNxJson) type = \"nx\";\n else if (hasPnpmWorkspace) type = \"pnpm-workspaces\";\n\n if (!type) return null;\n\n // Resolve workspace package globs\n let packageGlobs: string[] = [];\n\n if (hasPnpmWorkspace || hasTurboJson) {\n // pnpm-workspace.yaml (also used by Turborepo)\n const yamlContent = await readFileOr(\n path.join(rootDir, \"pnpm-workspace.yaml\"),\n );\n if (yamlContent) {\n // Simple YAML parse: extract lines under \"packages:\"\n const lines = yamlContent.split(\"\\n\");\n let inPackages = false;\n for (const line of lines) {\n if (/^packages:/i.test(line.trim())) {\n inPackages = true;\n continue;\n }\n if (inPackages) {\n const match = line.match(/^\\s+-\\s+['\"]?([^'\"]+)['\"]?/);\n if (match) {\n packageGlobs.push(match[1].trim());\n } else if (line.trim() && !line.startsWith(\" \") && !line.startsWith(\"\\t\")) {\n break; // new top-level key\n }\n }\n }\n }\n }\n\n if (packageGlobs.length === 0 && hasNxJson) {\n // Nx: check for packages/ or libs/ directories\n for (const dir of [\"packages\", \"libs\", \"apps\"]) {\n if (topEntries.includes(dir)) {\n packageGlobs.push(`${dir}/*`);\n }\n }\n }\n\n // Fallback: try workspaces field from package.json\n if (packageGlobs.length === 0) {\n const pkg = await readJsonFile(path.join(rootDir, \"package.json\"));\n if (pkg) {\n const workspaces = pkg.workspaces;\n if (Array.isArray(workspaces)) {\n packageGlobs = workspaces as string[];\n } else if (\n workspaces &&\n typeof workspaces === \"object\" &&\n Array.isArray((workspaces as Record<string, unknown>).packages)\n ) {\n packageGlobs = (workspaces as Record<string, unknown>)\n .packages as string[];\n }\n }\n }\n\n if (packageGlobs.length === 0) return null;\n\n // Resolve globs to actual directories\n const resolvedDirs = await fg(packageGlobs, {\n cwd: rootDir,\n onlyDirectories: true,\n ignore: [\"**/node_modules/**\"],\n absolute: false,\n });\n\n // Build package info for each directory\n const packages: MonorepoPackage[] = [];\n\n for (const dir of resolvedDirs) {\n const pkgJsonPath = path.join(rootDir, dir, \"package.json\");\n const pkgJson = await readJsonFile(pkgJsonPath);\n if (!pkgJson) continue; // Not a valid package\n\n const deps = {\n ...(pkgJson.dependencies as Record<string, string> | undefined),\n ...(pkgJson.devDependencies as Record<string, string> | undefined),\n };\n const depNames = Object.keys(deps);\n\n // Detect frameworks for this package\n const frameworks: DetectedFramework[] = [];\n const seen = new Set<string>();\n for (const dep of depNames) {\n const framework = FRAMEWORK_MAP[dep];\n if (framework && !seen.has(framework)) {\n seen.add(framework);\n const version = deps[dep]?.replace(/^[\\^~>=<]/, \"\");\n frameworks.push({ name: framework, version });\n }\n }\n\n packages.push({\n name: (pkgJson.name as string) ?? path.basename(dir),\n path: dir,\n dependencies: depNames,\n frameworks,\n });\n }\n\n if (packages.length === 0) return null;\n\n return { type, packages };\n}\n\n/**\n * Build a reverse map: framework display name -> dependency names.\n */\nfunction buildReverseFrameworkMap(): Map<string, string[]> {\n const reverse = new Map<string, string[]>();\n for (const [dep, name] of Object.entries(FRAMEWORK_MAP)) {\n const deps = reverse.get(name) ?? [];\n deps.push(dep);\n reverse.set(name, deps);\n }\n return reverse;\n}\n\n/**\n * Enrich detected frameworks with actual import counts from the import graph.\n * Filters out frameworks with 0 imports (detected in package.json but never used).\n */\nexport function enrichFrameworksWithUsage(\n frameworks: DetectedFramework[],\n externalImportCounts: Map<string, number>,\n): DetectedFramework[] {\n const reverseMap = buildReverseFrameworkMap();\n\n return frameworks\n .map((fw) => {\n const depNames = reverseMap.get(fw.name) ?? [];\n let totalCount = 0;\n for (const dep of depNames) {\n totalCount += externalImportCounts.get(dep) ?? 0;\n }\n return { ...fw, importCount: totalCount };\n })\n .filter((fw) => fw.importCount === undefined || fw.importCount > 0);\n}\n\n/**\n * Produce a short human-readable summary of the detected stack.\n */\nexport function summarizeDetection(ctx: DetectedContext): string {\n const parts: string[] = [];\n\n if (ctx.frameworks.length > 0) {\n parts.push(ctx.frameworks.map((f) => f.name).join(\" + \"));\n }\n\n if (ctx.hasTypeScript) {\n parts.push(\"TypeScript\");\n } else if (ctx.language !== \"other\") {\n parts.push(ctx.language.charAt(0).toUpperCase() + ctx.language.slice(1));\n }\n\n if (ctx.linter !== \"none\") {\n parts.push(ctx.linter.charAt(0).toUpperCase() + ctx.linter.slice(1));\n }\n\n if (ctx.packageManager !== \"none\") {\n parts.push(ctx.packageManager);\n }\n\n return parts.join(\" + \");\n}\n","import * as p from \"@clack/prompts\";\nimport type {\n DetectedContext,\n IDETarget,\n ProjectConfig,\n UserAnswers,\n} from \"./types.js\";\nimport { summarizeDetection } from \"./detect.js\";\n\n/**\n * Run the interactive prompt flow. Takes the auto-detected context\n * and asks the user to fill in what couldn't be auto-detected.\n *\n * When `defaults` is provided (from .codebrief.json + --reconfigure),\n * prompt values are pre-filled so the user can just press Enter to keep them.\n */\nexport async function runPrompts(\n detected: DetectedContext,\n defaults?: ProjectConfig | null,\n): Promise<UserAnswers> {\n // 1. IDE/tool selection\n const ideOptions = [\n { value: \"claude\" as const, label: \"Claude Code\" },\n { value: \"cursor\" as const, label: \"Cursor\" },\n { value: \"opencode\" as const, label: \"OpenCode\" },\n { value: \"copilot\" as const, label: \"GitHub Copilot\" },\n { value: \"windsurf\" as const, label: \"Windsurf\" },\n { value: \"cline\" as const, label: \"Cline\" },\n { value: \"continue\" as const, label: \"Continue.dev\" },\n { value: \"aider\" as const, label: \"Aider\" },\n { value: \"generic\" as const, label: \"Other (generic CONTEXT.md)\" },\n ];\n\n const ide = (await p.select({\n message: \"Which AI coding tool are you using?\",\n options: ideOptions,\n initialValue: defaults?.ide,\n })) as IDETarget | symbol;\n\n if (p.isCancel(ide)) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n\n // 2. Confirm detected stack\n const stackSummary = summarizeDetection(detected);\n let stackConfirmed = true;\n let stackCorrections = defaults?.stackCorrections ?? \"\";\n\n if (stackSummary) {\n const confirm = await p.confirm({\n message: `Detected: ${stackSummary}. Correct?`,\n });\n\n if (p.isCancel(confirm)) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n\n stackConfirmed = confirm;\n\n if (!confirm) {\n const corrections = await p.text({\n message: \"What should I correct? (describe your actual stack)\",\n placeholder: \"e.g. It's actually Next.js 15 + Prisma, not plain React\",\n defaultValue: defaults?.stackCorrections || undefined,\n });\n\n if (p.isCancel(corrections)) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n\n stackCorrections = corrections;\n }\n }\n\n // 3. Project purpose\n const projectPurpose = await p.text({\n message: \"What does this project do? (1-2 sentences)\",\n placeholder:\n \"e.g. A mobile AI chat app connecting to OpenAI, Anthropic, and Google APIs\",\n defaultValue: defaults?.projectPurpose || undefined,\n validate: (value) => {\n if (!value?.trim()) return \"Please describe your project briefly.\";\n },\n });\n\n if (p.isCancel(projectPurpose)) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n\n // 4. Key patterns / conventions\n const keyPatterns = await p.text({\n message:\n \"Any key coding patterns or conventions? (optional, press Enter to skip)\",\n placeholder:\n \"e.g. Zustand slices for state, NativeWind for styling, expo/fetch for SSE\",\n defaultValue: defaults?.keyPatterns || \"\",\n });\n\n if (p.isCancel(keyPatterns)) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n\n // 5. Gotchas / anti-patterns\n const gotchas = await p.text({\n message: \"Any critical gotchas or anti-patterns to avoid? (optional)\",\n placeholder:\n \"e.g. Never use FadeIn/FadeOut on ternary components, no @expo/vector-icons\",\n defaultValue: defaults?.gotchas || \"\",\n });\n\n if (p.isCancel(gotchas)) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n\n // 6. Code snapshot depth (only for TS/JS projects)\n let generateSnapshot = false;\n let snapshotPaths: string[] = defaults?.snapshotPaths ?? [];\n\n if (\n detected.language === \"typescript\" ||\n detected.language === \"javascript\"\n ) {\n const snapshotChoice = (await p.select({\n message:\n \"Generate a code snapshot? (extracts types, store shapes, component props)\",\n options: [\n { value: \"auto\" as const, label: \"Yes, auto-detect key files\" },\n { value: \"no\" as const, label: \"No, skip code snapshot\" },\n { value: \"custom\" as const, label: \"Yes, but let me specify paths\" },\n ],\n initialValue: defaults?.generateSnapshot\n ? defaults.snapshotPaths.length > 0\n ? (\"custom\" as const)\n : (\"auto\" as const)\n : undefined,\n })) as \"auto\" | \"no\" | \"custom\" | symbol;\n\n if (p.isCancel(snapshotChoice)) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n\n if (snapshotChoice === \"auto\") {\n generateSnapshot = true;\n snapshotPaths = [];\n } else if (snapshotChoice === \"custom\") {\n generateSnapshot = true;\n const paths = await p.text({\n message: \"Paths to scan (comma-separated, relative to project root)\",\n placeholder: \"e.g. src/types, src/stores, src/components\",\n defaultValue:\n defaults?.snapshotPaths.length\n ? defaults.snapshotPaths.join(\", \")\n : undefined,\n });\n\n if (p.isCancel(paths)) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n\n snapshotPaths = paths\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n }\n }\n\n // 7. Monorepo: per-package context files\n let generatePerPackage = false;\n\n if (detected.monorepo && detected.monorepo.packages.length > 0) {\n const mono = detected.monorepo;\n const pkgNames = mono.packages.map((pkg) => pkg.name).join(\", \");\n\n const perPkg = await p.confirm({\n message: `Monorepo detected (${mono.type}, ${mono.packages.length} packages: ${pkgNames}). Generate per-package context files?`,\n initialValue: defaults?.generatePerPackage ?? false,\n });\n\n if (p.isCancel(perPkg)) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n\n generatePerPackage = perPkg;\n }\n\n return {\n ide,\n projectPurpose,\n keyPatterns: keyPatterns ?? \"\",\n gotchas: gotchas ?? \"\",\n generateSnapshot,\n snapshotPaths,\n stackConfirmed,\n stackCorrections,\n generatePerPackage,\n };\n}\n","import path from \"node:path\";\nimport fg from \"fast-glob\";\nimport { estimateTokens, readFileOr } from \"./utils.js\";\nimport { findUsedExports } from \"./graph.js\";\nimport type { CodeSnapshot, DetectedContext, GitAnalysis, ImportGraph, ProgressCallback, SnapshotEntry } from \"./types.js\";\n\n/**\n * Auto-detect which directories to scan for code snapshots.\n */\nfunction getDefaultScanPaths(ctx: DetectedContext): string[] {\n const paths: string[] = [];\n const dirs = ctx.directories;\n\n // Types directories\n for (const d of dirs) {\n if (d.endsWith(\"types\") || d.endsWith(\"typings\")) paths.push(d);\n }\n\n // Store directories\n for (const d of dirs) {\n if (d.endsWith(\"stores\") || d.endsWith(\"store\")) paths.push(d);\n }\n\n // Service/API directories\n for (const d of dirs) {\n if (d.endsWith(\"services\") || d.endsWith(\"api\")) paths.push(d);\n }\n\n // Hook directories\n for (const d of dirs) {\n if (d.endsWith(\"hooks\")) paths.push(d);\n }\n\n // Component directories\n for (const d of dirs) {\n if (d.endsWith(\"components\")) paths.push(d);\n }\n\n // Lib/utils\n for (const d of dirs) {\n if (d.endsWith(\"lib\") || d.endsWith(\"utils\")) paths.push(d);\n }\n\n // Fallback: scan common type file patterns at root\n if (paths.length === 0) {\n paths.push(\"src\", \"app\", \"lib\");\n }\n\n return paths;\n}\n\n/**\n * Regex patterns for extracting TypeScript/JavaScript declarations.\n */\nconst PATTERNS = {\n /** export interface Foo { ... } or export type Foo = ... */\n exportedType: /^export\\s+(interface|type)\\s+(\\w+)/,\n /** interface FooProps { ... } (component props, even if not exported) */\n propsInterface: /^(?:export\\s+)?interface\\s+(\\w+Props)\\s*\\{/,\n /** export function foo(...) or export const foo = */\n exportedFunction: /^export\\s+(?:async\\s+)?(?:function|const)\\s+(\\w+)/,\n /** StateCreator<...> pattern (Zustand slices) */\n zustandSlice: /StateCreator<\\s*(\\w+)/,\n /** export interface FooSlice { ... } */\n sliceInterface: /^export\\s+interface\\s+(\\w+Slice)\\s*\\{/,\n};\n\n/**\n * Extract snapshot entries from a single file.\n */\nasync function extractFromFile(\n filePath: string,\n relPath: string,\n): Promise<SnapshotEntry[]> {\n const content = await readFileOr(filePath);\n if (!content) return [];\n\n const entries: SnapshotEntry[] = [];\n const lines = content.split(\"\\n\");\n\n // Determine category hints from path\n const isStore = /stores?[/\\\\]/.test(relPath);\n const isHook = /hooks?[/\\\\]/.test(relPath) || relPath.includes(\"use\");\n const isComponent = /components?[/\\\\]/.test(relPath);\n const isService = /services?[/\\\\]|api[/\\\\]/.test(relPath);\n const isType = /types?[/\\\\]/.test(relPath) || relPath.endsWith(\".types.ts\");\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const trimmed = line.trimStart();\n\n // -- Exported interfaces / types --\n const typeMatch = trimmed.match(PATTERNS.exportedType);\n if (typeMatch) {\n const [, kind, name] = typeMatch;\n const category =\n name.endsWith(\"Slice\")\n ? \"store\"\n : name.endsWith(\"Props\")\n ? \"component\"\n : kind === \"interface\"\n ? \"interface\"\n : \"type\";\n\n // Grab the full declaration (until closing brace or semicolon for type aliases)\n const block = extractBlock(lines, i);\n entries.push({ file: relPath, category, signature: block });\n continue;\n }\n\n // -- Non-exported Props interfaces (common in components) --\n if (isComponent) {\n const propsMatch = trimmed.match(PATTERNS.propsInterface);\n if (propsMatch && !trimmed.startsWith(\"export\")) {\n const block = extractBlock(lines, i);\n entries.push({ file: relPath, category: \"component\", signature: block });\n continue;\n }\n }\n\n // -- Exported functions --\n const funcMatch = trimmed.match(PATTERNS.exportedFunction);\n if (funcMatch) {\n const [, name] = funcMatch;\n\n // Skip React component default exports like `export function MyComponent(`\n // unless it's clearly a hook or service\n if (isComponent && name[0] === name[0].toUpperCase() && !name.startsWith(\"use\")) {\n // This is likely a component — we only care about its Props, not its body\n continue;\n }\n\n let category: SnapshotEntry[\"category\"] = \"function\";\n if (isHook || name.startsWith(\"use\")) category = \"hook\";\n else if (isStore) category = \"store\";\n\n // Extract just the signature line (not the full body)\n const sig = extractSignatureLine(lines, i);\n entries.push({ file: relPath, category, signature: sig });\n }\n }\n\n return entries;\n}\n\n/**\n * Extract a block from the current line until the closing brace at the same depth.\n * For type aliases (no brace), captures until the next semicolon or blank line.\n */\nfunction extractBlock(lines: string[], startIdx: number): string {\n const firstLine = lines[startIdx];\n\n // Type alias (no opening brace on first line, usually single-line or multi-line with |)\n if (!firstLine.includes(\"{\")) {\n // Collect until semicolon\n let result = \"\";\n for (let i = startIdx; i < lines.length && i < startIdx + 10; i++) {\n result += (result ? \"\\n\" : \"\") + lines[i];\n if (lines[i].includes(\";\")) break;\n }\n return result.trim();\n }\n\n // Block with braces — capture until matching depth\n let depth = 0;\n let result = \"\";\n const maxLines = 30; // Cap to avoid capturing massive blocks\n\n for (let i = startIdx; i < lines.length && i < startIdx + maxLines; i++) {\n const line = lines[i];\n result += (result ? \"\\n\" : \"\") + line;\n\n for (const ch of line) {\n if (ch === \"{\") depth++;\n if (ch === \"}\") depth--;\n }\n\n if (depth <= 0 && i > startIdx) break;\n }\n\n return result.trim();\n}\n\n/**\n * Extract a function signature (everything up to the opening brace or arrow).\n */\nfunction extractSignatureLine(lines: string[], startIdx: number): string {\n let sig = \"\";\n for (let i = startIdx; i < lines.length && i < startIdx + 5; i++) {\n sig += (sig ? \" \" : \"\") + lines[i].trim();\n // Stop at opening brace, arrow, or if it looks complete\n if (sig.includes(\"{\") || sig.includes(\"=>\")) {\n // Trim everything after the opening brace / arrow\n const braceIdx = sig.indexOf(\"{\");\n const arrowIdx = sig.indexOf(\"=>\");\n const cutIdx =\n braceIdx >= 0 && arrowIdx >= 0\n ? Math.min(braceIdx, arrowIdx)\n : braceIdx >= 0\n ? braceIdx\n : arrowIdx >= 0\n ? arrowIdx + 2\n : sig.length;\n sig = sig.slice(0, cutIdx).trim();\n break;\n }\n }\n return sig;\n}\n\n/**\n * Append an \"imported by N files\" comment to signatures of highly-imported entries.\n */\nfunction annotateSignature(entry: SnapshotEntry): string {\n if (entry.importedByCount && entry.importedByCount > 2) {\n // Add comment to first line of the signature\n const firstLine = entry.signature.split(\"\\n\")[0];\n const rest = entry.signature.split(\"\\n\").slice(1);\n const annotated = `${firstLine} // imported by ${entry.importedByCount} files`;\n return rest.length > 0 ? [annotated, ...rest].join(\"\\n\") : annotated;\n }\n return entry.signature;\n}\n\n/**\n * Condense snapshot entries into a readable markdown block.\n */\nfunction renderSnapshot(entries: SnapshotEntry[]): string {\n if (entries.length === 0) return \"\";\n\n // Group by file\n const byFile = new Map<string, SnapshotEntry[]>();\n for (const e of entries) {\n const list = byFile.get(e.file) ?? [];\n list.push(e);\n byFile.set(e.file, list);\n }\n\n let md = \"\";\n\n // Group by category for cleaner output\n const types = entries.filter((e) => e.category === \"type\" || e.category === \"interface\");\n const stores = entries.filter((e) => e.category === \"store\");\n const hooks = entries.filter((e) => e.category === \"hook\");\n const components = entries.filter((e) => e.category === \"component\");\n const functions = entries.filter((e) => e.category === \"function\");\n\n if (types.length > 0) {\n md += \"### Core Types\\n\\n```ts\\n\";\n md += types.map((e) => annotateSignature(e)).join(\"\\n\\n\");\n md += \"\\n```\\n\\n\";\n }\n\n if (stores.length > 0) {\n md += \"### Store Shape\\n\\n```ts\\n\";\n md += stores.map((e) => annotateSignature(e)).join(\"\\n\\n\");\n md += \"\\n```\\n\\n\";\n }\n\n if (components.length > 0) {\n md += \"### Component Props\\n\\n```ts\\n\";\n md += components.map((e) => annotateSignature(e)).join(\"\\n\\n\");\n md += \"\\n```\\n\\n\";\n }\n\n if (hooks.length > 0) {\n md += \"### Hooks\\n\\n```ts\\n\";\n md += hooks.map((e) => annotateSignature(e)).join(\"\\n\\n\");\n md += \"\\n```\\n\\n\";\n }\n\n if (functions.length > 0) {\n md += \"### Key Functions\\n\\n```ts\\n\";\n md += functions.map((e) => annotateSignature(e)).join(\"\\n\\n\");\n md += \"\\n```\\n\\n\";\n }\n\n return md.trimEnd();\n}\n\n/**\n * Generate a code snapshot for the project.\n */\nexport async function generateSnapshot(\n ctx: DetectedContext,\n customPaths: string[],\n graph?: ImportGraph,\n maxTokens?: number,\n onProgress?: ProgressCallback,\n gitActivity?: GitAnalysis | null,\n): Promise<CodeSnapshot> {\n const scanPaths =\n customPaths.length > 0 ? customPaths : getDefaultScanPaths(ctx);\n\n if (scanPaths.length === 0) {\n return { entries: [], markdown: \"\" };\n }\n\n // Report which directories we're scanning\n const dirNames = scanPaths.map((p) => p.split(\"/\").pop() ?? p);\n onProgress?.(`Scanning ${scanPaths.length} directories: ${dirNames.join(\", \")}...`);\n\n // Find all TS/JS files in the scan paths\n const patterns = scanPaths.map((p) => `${p}/**/*.{ts,tsx,js,jsx}`);\n\n const files = await fg(patterns, {\n cwd: ctx.rootDir,\n ignore: [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n \"**/*.test.*\",\n \"**/*.spec.*\",\n \"**/__tests__/**\",\n \"**/.Trash/**\",\n \"**/Library/**\",\n \"**/.git/**\",\n ],\n absolute: false,\n });\n\n const allEntries: SnapshotEntry[] = [];\n\n for (let i = 0; i < files.length; i++) {\n const file = files[i];\n\n if ((i + 1) % 20 === 0 || i === files.length - 1) {\n const dir = path.dirname(file).split(\"/\").pop() ?? \"\";\n onProgress?.(`Extracting signatures... ${i + 1}/${files.length} files (${dir}/)`);\n }\n\n const absPath = path.join(ctx.rootDir, file);\n const entries = await extractFromFile(absPath, file);\n allEntries.push(...entries);\n }\n\n // Populate importedByCount from graph\n if (graph) {\n for (const entry of allEntries) {\n const count = graph.inDegree.get(entry.file) ?? 0;\n if (count > 0) {\n entry.importedByCount = count;\n }\n }\n }\n\n // Filter dead exports using import graph\n onProgress?.(\"Filtering dead exports...\");\n const liveEntries = filterDeadExports(allEntries, graph);\n\n // Apply token budget if graph is available\n const budget =\n maxTokens ??\n Math.min(16000, 4000 + Math.floor(ctx.sourceFileCount / 25) * 500);\n onProgress?.(`Applying token budget (${budget.toLocaleString()} tokens)...`);\n const { selected, excluded } = applyTokenBudget(liveEntries, budget, graph, gitActivity);\n\n const markdown = renderSnapshot(selected);\n\n return {\n entries: selected,\n markdown,\n budgetExcluded: excluded,\n estimatedTokens: estimateTokens(markdown),\n };\n}\n\n/** Entry-point patterns — files that are never filtered as dead exports */\nconst ENTRY_POINT_PATTERNS = [\n /(?:^|\\/)index\\.[jt]sx?$/,\n /(?:^|\\/)App\\.[jt]sx?$/,\n /(?:^|\\/)main\\.[jt]sx?$/,\n /(?:^|\\/)pages\\//,\n /(?:^|\\/)app\\//,\n /(?:^|\\/)routes?\\//,\n /(?:^|\\/)middleware\\//,\n];\n\n/**\n * Extract the identifier name from a signature string.\n * e.g. \"export interface Foo {\" -> \"Foo\"\n * \"export const bar =\" -> \"bar\"\n * \"export type Baz =\" -> \"Baz\"\n */\nfunction extractNameFromSignature(sig: string): string | null {\n const m = sig.match(\n /export\\s+(?:default\\s+)?(?:async\\s+)?(?:interface|type|function|const|let|var|class|enum)\\s+(\\w+)/,\n );\n return m?.[1] ?? null;\n}\n\n/**\n * Check if a file is an entry point (never filtered).\n */\nfunction isEntryPoint(filePath: string): boolean {\n return ENTRY_POINT_PATTERNS.some((p) => p.test(filePath));\n}\n\n/**\n * Filter out exports that are never imported anywhere in the project.\n * Entry-point files and barrel re-exports are always kept.\n */\nfunction filterDeadExports(\n entries: SnapshotEntry[],\n graph?: ImportGraph,\n): SnapshotEntry[] {\n if (!graph || graph.edges.length === 0) return entries;\n\n const usedExports = findUsedExports(graph.edges);\n\n return entries.filter((entry) => {\n // Always keep entry-point files\n if (isEntryPoint(entry.file)) return true;\n\n // Extract the export name from the signature\n const name = extractNameFromSignature(entry.signature);\n if (!name) return true; // Can't determine name, keep it\n\n // Check if this export is used somewhere\n return usedExports.has(`${entry.file}::${name}`);\n });\n}\n\n/**\n * Greedy knapsack: prioritize entries by centrality-weighted value per token.\n */\nfunction applyTokenBudget(\n entries: SnapshotEntry[],\n budget: number,\n graph?: ImportGraph,\n gitActivity?: GitAnalysis | null,\n): { selected: SnapshotEntry[]; excluded: number } {\n if (entries.length === 0) return { selected: [], excluded: 0 };\n\n // Score each entry\n const scored = entries.map((entry) => {\n const tokens = Math.max(1, estimateTokens(entry.signature));\n const centrality = graph?.centrality.get(entry.file) ?? 0.5;\n\n // Category boost: types/interfaces are more valuable for context\n let categoryBoost = 1.0;\n if (entry.category === \"type\" || entry.category === \"interface\") categoryBoost = 1.3;\n\n // Git boost: files changed recently get priority\n let gitBoost = 1.0;\n if (gitActivity) {\n const commits = gitActivity.commitCounts.get(entry.file) ?? 0;\n gitBoost = 1.0 + Math.min(0.5, commits / 20);\n }\n\n const value = (centrality * categoryBoost * gitBoost) / tokens;\n return { entry, tokens, value };\n });\n\n // Sort by value descending\n scored.sort((a, b) => b.value - a.value);\n\n // Greedily select\n let remaining = budget;\n const selected: SnapshotEntry[] = [];\n\n for (const { entry, tokens } of scored) {\n if (tokens <= remaining) {\n selected.push(entry);\n remaining -= tokens;\n }\n }\n\n return {\n selected,\n excluded: entries.length - selected.length,\n };\n}\n","import path from \"node:path\";\nimport fg from \"fast-glob\";\nimport { readFileOr } from \"./utils.js\";\nimport type {\n ArchitecturalLayer,\n CircularDependency,\n Community,\n ExportCoverage,\n FileInstability,\n HubFile,\n ImportEdge,\n ImportGraph,\n Language,\n LayerEdge,\n ProgressCallback,\n} from \"./types.js\";\n\n// ── Import regex patterns per language ────────────────────────────────\n\n/** JS/TS: import ... from '...' (including type-only and namespace imports) */\nconst JS_IMPORT_FROM = /import\\s+(?:type\\s+)?(?:\\{([^}]*)\\}|(\\*\\s+as\\s+\\w+|\\w+)(?:\\s*,\\s*\\{([^}]*)\\})?)\\s+from\\s+['\"]([^'\"]+)['\"]/g;\n/** JS/TS: import '...' (side-effect) */\nconst JS_IMPORT_SIDE = /import\\s+['\"]([^'\"]+)['\"]/g;\n/** JS/TS: require('...') */\nconst JS_REQUIRE = /require\\(\\s*['\"]([^'\"]+)['\"]\\s*\\)/g;\n/** JS/TS: dynamic import('...') */\nconst JS_DYNAMIC = /import\\(\\s*['\"]([^'\"]+)['\"]\\s*\\)/g;\n\n/** Python: from foo.bar import baz, qux (including relative imports like from . import x) */\nconst PY_FROM_IMPORT = /^from\\s+(\\.+[\\w.]*|[\\w][\\w.]*)\\s+import\\s+(.+)/gm;\n/** Python: import foo, bar */\nconst PY_IMPORT = /^import\\s+([\\w., ]+)/gm;\n\n/** Go: import \"pkg\" or import ( \"pkg\" ) */\nconst GO_IMPORT_SINGLE = /import\\s+\"([^\"]+)\"/g;\nconst GO_IMPORT_BLOCK = /import\\s*\\(([^)]+)\\)/gs;\n\n/** Rust: use crate::foo::bar (including pub use and glob imports) */\nconst RUST_USE = /(?:pub\\s+)?use\\s+((?:crate|super|self)(?:::\\w+)*(?:::\\{[^}]*\\})?)/g;\n/** Rust: mod foo; */\nconst RUST_MOD = /mod\\s+(\\w+)\\s*;/g;\n\n// ── File extensions to try when resolving relative imports ────────────\n\nconst JS_EXTENSIONS = [\".ts\", \".tsx\", \".js\", \".jsx\", \".mjs\"];\nconst INDEX_FILES = JS_EXTENSIONS.map((e) => `/index${e}`);\n\n// ── Language-specific source file globs ───────────────────────────────\n\nfunction getSourceGlob(lang: Language): string[] {\n switch (lang) {\n case \"typescript\":\n case \"javascript\":\n return [\"**/*.{ts,tsx,js,jsx,mjs}\"];\n case \"python\":\n return [\"**/*.py\"];\n case \"go\":\n return [\"**/*.go\"];\n case \"rust\":\n return [\"**/*.rs\"];\n default:\n return [\"**/*.{ts,tsx,js,jsx,py,go,rs}\"];\n }\n}\n\n// ── Parse imports from a single file ──────────────────────────────────\n\nexport interface RawImport {\n specifier: string;\n importedNames: string[];\n}\n\nexport function parseJsImports(content: string): RawImport[] {\n const imports: RawImport[] = [];\n\n // import { a, b } from '...' / import Foo from '...' / import Foo, { a } from '...' / import * as Foo from '...'\n for (const m of content.matchAll(JS_IMPORT_FROM)) {\n const names: string[] = [];\n if (m[1]) names.push(...m[1].split(\",\").map((n) => n.trim().split(/\\s+as\\s+/)[0].trim()).filter(Boolean));\n if (m[2]) {\n const group2 = m[2].trim();\n // Namespace import (* as foo) — edge is valid but no named import to extract\n if (!group2.startsWith(\"*\")) {\n names.push(group2);\n }\n }\n if (m[3]) names.push(...m[3].split(\",\").map((n) => n.trim().split(/\\s+as\\s+/)[0].trim()).filter(Boolean));\n imports.push({ specifier: m[4], importedNames: names });\n }\n\n // import '...' (side-effect)\n for (const m of content.matchAll(JS_IMPORT_SIDE)) {\n // Skip if already captured by JS_IMPORT_FROM (side-effect imports have no bindings)\n if (!content.includes(`from '${m[1]}'`) && !content.includes(`from \"${m[1]}\"`)) {\n imports.push({ specifier: m[1], importedNames: [] });\n }\n }\n\n // require('...')\n for (const m of content.matchAll(JS_REQUIRE)) {\n imports.push({ specifier: m[1], importedNames: [] });\n }\n\n // dynamic import('...')\n for (const m of content.matchAll(JS_DYNAMIC)) {\n imports.push({ specifier: m[1], importedNames: [] });\n }\n\n return imports;\n}\n\nexport function parsePythonImports(content: string): RawImport[] {\n const imports: RawImport[] = [];\n\n for (const m of content.matchAll(PY_FROM_IMPORT)) {\n const module = m[1];\n const names = m[2].split(\",\").map((n) => n.trim().split(/\\s+as\\s+/)[0].trim()).filter(Boolean);\n imports.push({ specifier: module, importedNames: names });\n }\n\n for (const m of content.matchAll(PY_IMPORT)) {\n const modules = m[1].split(\",\").map((n) => n.trim().split(/\\s+as\\s+/)[0].trim()).filter(Boolean);\n for (const mod of modules) {\n imports.push({ specifier: mod, importedNames: [] });\n }\n }\n\n return imports;\n}\n\nexport function parseGoImports(content: string): RawImport[] {\n const imports: RawImport[] = [];\n\n for (const m of content.matchAll(GO_IMPORT_SINGLE)) {\n imports.push({ specifier: m[1], importedNames: [] });\n }\n\n for (const m of content.matchAll(GO_IMPORT_BLOCK)) {\n const block = m[1];\n for (const line of block.split(\"\\n\")) {\n // Skip comment lines\n if (line.trim().startsWith(\"//\")) continue;\n const match = line.match(/[\"']([^\"']+)[\"']/);\n if (match) {\n imports.push({ specifier: match[1], importedNames: [] });\n }\n }\n }\n\n return imports;\n}\n\nexport function parseRustImports(content: string): RawImport[] {\n const imports: RawImport[] = [];\n\n for (const m of content.matchAll(RUST_USE)) {\n const usePath = m[1];\n // Check for glob imports like crate::foo::{Bar, Baz}\n const globMatch = usePath.match(/::\\{([^}]*)\\}$/);\n if (globMatch) {\n const names = globMatch[1].split(\",\").map((n) => n.trim()).filter(Boolean);\n imports.push({ specifier: usePath, importedNames: names });\n } else {\n const parts = usePath.split(\"::\");\n const name = parts[parts.length - 1];\n imports.push({ specifier: usePath, importedNames: name ? [name] : [] });\n }\n }\n\n for (const m of content.matchAll(RUST_MOD)) {\n imports.push({ specifier: m[1], importedNames: [] });\n }\n\n return imports;\n}\n\nfunction parseImports(content: string, lang: Language): RawImport[] {\n switch (lang) {\n case \"typescript\":\n case \"javascript\":\n return parseJsImports(content);\n case \"python\":\n return parsePythonImports(content);\n case \"go\":\n return parseGoImports(content);\n case \"rust\":\n return parseRustImports(content);\n default:\n return parseJsImports(content);\n }\n}\n\n// ── Resolve relative imports to file paths ────────────────────────────\n\nfunction isRelativeSpecifier(spec: string, lang: Language): boolean {\n if (lang === \"typescript\" || lang === \"javascript\") {\n return spec.startsWith(\"./\") || spec.startsWith(\"../\");\n }\n if (lang === \"python\") {\n return spec.startsWith(\".\");\n }\n if (lang === \"rust\") {\n return spec.startsWith(\"crate::\") || spec.startsWith(\"super::\") || spec.startsWith(\"self::\");\n }\n return spec.startsWith(\"./\") || spec.startsWith(\"../\");\n}\n\n/**\n * Try to resolve a JS/TS relative import to an actual file path.\n * Returns the resolved relative path or null.\n */\nfunction resolveJsImport(\n specifier: string,\n fromFile: string,\n allFiles: Set<string>,\n): string | null {\n const dir = path.dirname(fromFile);\n const raw = path.join(dir, specifier).replace(/\\\\/g, \"/\");\n\n // Try with original path, then with JS extension stripped (TS ESM convention:\n // source uses `.js` specifiers but actual files are `.ts`)\n const stripped = raw.replace(/\\.(jsx?|mjs)$/, \"\");\n const bases = stripped !== raw ? [raw, stripped] : [raw];\n\n for (const base of bases) {\n if (allFiles.has(base)) return base;\n for (const ext of JS_EXTENSIONS) {\n if (allFiles.has(base + ext)) return base + ext;\n }\n for (const idx of INDEX_FILES) {\n if (allFiles.has(base + idx)) return base + idx;\n }\n }\n\n return null;\n}\n\n/**\n * Try to resolve a Python relative import to a file path.\n */\nfunction resolvePythonImport(\n specifier: string,\n fromFile: string,\n allFiles: Set<string>,\n): string | null {\n if (!specifier.startsWith(\".\")) return null;\n const dir = path.dirname(fromFile);\n // Count leading dots\n let dots = 0;\n while (specifier[dots] === \".\") dots++;\n const modulePath = specifier.slice(dots).replace(/\\./g, \"/\");\n let baseDir = dir;\n for (let i = 1; i < dots; i++) {\n baseDir = path.dirname(baseDir);\n }\n const base = modulePath ? path.join(baseDir, modulePath).replace(/\\\\/g, \"/\") : baseDir;\n\n // Try as file\n if (allFiles.has(base + \".py\")) return base + \".py\";\n // Try as package\n if (allFiles.has(base + \"/__init__.py\")) return base + \"/__init__.py\";\n\n return null;\n}\n\nfunction resolveImport(\n specifier: string,\n fromFile: string,\n lang: Language,\n allFiles: Set<string>,\n): string | null {\n switch (lang) {\n case \"typescript\":\n case \"javascript\":\n return resolveJsImport(specifier, fromFile, allFiles);\n case \"python\":\n return resolvePythonImport(specifier, fromFile, allFiles);\n default:\n // Go and Rust: module paths are harder to resolve reliably\n // without a full build system. Skip resolution for now.\n return null;\n }\n}\n\n// ── PageRank centrality ───────────────────────────────────────────────\n\nfunction computePageRank(\n files: string[],\n edges: ImportEdge[],\n iterations = 5,\n damping = 0.85,\n): Map<string, number> {\n const n = files.length;\n if (n === 0) return new Map();\n\n // Build adjacency: from -> [to, ...]\n const outLinks = new Map<string, string[]>();\n for (const file of files) outLinks.set(file, []);\n for (const edge of edges) {\n if (!edge.isExternal && outLinks.has(edge.from)) {\n outLinks.get(edge.from)!.push(edge.to);\n }\n }\n\n // Init scores\n let scores = new Map<string, number>();\n const init = 1 / n;\n for (const file of files) scores.set(file, init);\n\n // Iterate\n for (let iter = 0; iter < iterations; iter++) {\n const next = new Map<string, number>();\n for (const file of files) next.set(file, (1 - damping) / n);\n\n for (const file of files) {\n const links = outLinks.get(file) ?? [];\n if (links.length === 0) continue;\n const share = (damping * (scores.get(file) ?? 0)) / links.length;\n for (const target of links) {\n next.set(target, (next.get(target) ?? 0) + share);\n }\n }\n scores = next;\n }\n\n // Normalize to 0–1\n let max = 0;\n for (const v of scores.values()) {\n if (v > max) max = v;\n }\n if (max > 0) {\n for (const [k, v] of scores) {\n scores.set(k, v / max);\n }\n }\n\n return scores;\n}\n\n// ── Public API ────────────────────────────────────────────────────────\n\n/**\n * Build the import graph for a project.\n */\nexport async function buildImportGraph(\n rootDir: string,\n language: Language,\n onProgress?: ProgressCallback,\n): Promise<ImportGraph> {\n const globs = getSourceGlob(language);\n let files: string[];\n try {\n files = await fg(globs, {\n cwd: rootDir,\n ignore: [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n \"**/.next/**\",\n \"**/target/**\",\n \"**/vendor/**\",\n \"**/__pycache__/**\",\n \"**/venv/**\",\n \"**/.venv/**\",\n \"**/.Trash/**\",\n \"**/Library/**\",\n \"**/.git/**\",\n ],\n absolute: false,\n });\n } catch (err: unknown) {\n // Gracefully degrade on permission errors (e.g. scanning ~/ on macOS)\n const code = (err as NodeJS.ErrnoException).code;\n if (code === \"EPERM\" || code === \"EACCES\") {\n onProgress?.(\"Warning: permission error scanning files — returning empty graph\");\n return { edges: [], inDegree: new Map(), centrality: new Map(), externalImportCounts: new Map() };\n }\n throw err;\n }\n\n onProgress?.(`Found ${files.length} source files to analyze`);\n\n const fileSet = new Set(files);\n const edges: ImportEdge[] = [];\n const inDegree = new Map<string, number>();\n const externalImportCounts = new Map<string, number>();\n\n // Init in-degree\n for (const file of files) inDegree.set(file, 0);\n\n for (let i = 0; i < files.length; i++) {\n const file = files[i];\n\n if ((i + 1) % 50 === 0 || i === files.length - 1) {\n onProgress?.(`Parsing imports... ${i + 1}/${files.length} files`);\n }\n\n const absPath = path.join(rootDir, file);\n const content = await readFileOr(absPath);\n if (!content) continue;\n\n const rawImports = parseImports(content, language);\n\n for (const raw of rawImports) {\n const isRelative = isRelativeSpecifier(raw.specifier, language);\n\n if (isRelative) {\n const resolved = resolveImport(raw.specifier, file, language, fileSet);\n if (resolved) {\n edges.push({\n from: file,\n to: resolved,\n isExternal: false,\n specifier: raw.specifier,\n importedNames: raw.importedNames,\n });\n inDegree.set(resolved, (inDegree.get(resolved) ?? 0) + 1);\n }\n } else {\n // External package\n // Normalize specifier to package name (e.g. @scope/pkg/path -> @scope/pkg)\n const pkgName = getPackageName(raw.specifier);\n edges.push({\n from: file,\n to: pkgName,\n isExternal: true,\n specifier: raw.specifier,\n importedNames: raw.importedNames,\n });\n externalImportCounts.set(\n pkgName,\n (externalImportCounts.get(pkgName) ?? 0) + 1,\n );\n }\n }\n }\n\n onProgress?.(\"Computing centrality (PageRank)...\");\n const centrality = computePageRank(files, edges);\n\n return { edges, inDegree, centrality, externalImportCounts };\n}\n\n/**\n * Extract the package name from an import specifier.\n * e.g. \"@tanstack/react-query\" -> \"@tanstack/react-query\"\n * \"react/jsx-runtime\" -> \"react\"\n * \"zustand\" -> \"zustand\"\n */\nfunction getPackageName(specifier: string): string {\n if (specifier.startsWith(\"@\")) {\n const parts = specifier.split(\"/\");\n return parts.slice(0, 2).join(\"/\");\n }\n return specifier.split(\"/\")[0];\n}\n\n/**\n * Build a set of \"filepath::ExportName\" pairs that are actually imported\n * somewhere in the project. Used for dead export filtering.\n */\nexport function findUsedExports(edges: ImportEdge[]): Set<string> {\n const used = new Set<string>();\n for (const edge of edges) {\n if (edge.isExternal) continue;\n for (const name of edge.importedNames) {\n used.add(`${edge.to}::${name}`);\n }\n }\n return used;\n}\n\n/**\n * Get the most interconnected files (hub files) sorted by centrality.\n */\nexport function getHubFiles(graph: ImportGraph, limit = 8): HubFile[] {\n // Count outgoing internal imports per file\n const outCount = new Map<string, number>();\n for (const edge of graph.edges) {\n if (!edge.isExternal) {\n outCount.set(edge.from, (outCount.get(edge.from) ?? 0) + 1);\n }\n }\n\n // Build list of all files with their scores\n const files: HubFile[] = [];\n for (const [filePath, centrality] of graph.centrality) {\n const importedBy = graph.inDegree.get(filePath) ?? 0;\n const imports = outCount.get(filePath) ?? 0;\n // Only include files that have some connectivity\n if (importedBy > 0 || imports > 0) {\n files.push({ path: filePath, centrality, importedBy, imports });\n }\n }\n\n // Sort by centrality descending\n files.sort((a, b) => b.centrality - a.centrality);\n\n return files.slice(0, limit);\n}\n\n/**\n * Find all strongly connected components using Tarjan's algorithm.\n * Returns SCCs with size > 1 (i.e. actual cycles).\n */\nexport function findSCCs(graph: ImportGraph): string[][] {\n // Build adjacency list from internal edges only\n const adj = new Map<string, string[]>();\n const allFiles = new Set<string>();\n for (const edge of graph.edges) {\n if (edge.isExternal) continue;\n allFiles.add(edge.from);\n allFiles.add(edge.to);\n const list = adj.get(edge.from) ?? [];\n list.push(edge.to);\n adj.set(edge.from, list);\n }\n\n let index = 0;\n const indices = new Map<string, number>();\n const lowlinks = new Map<string, number>();\n const onStack = new Set<string>();\n const stack: string[] = [];\n const sccs: string[][] = [];\n\n function strongconnect(v: string): void {\n indices.set(v, index);\n lowlinks.set(v, index);\n index++;\n stack.push(v);\n onStack.add(v);\n\n for (const w of adj.get(v) ?? []) {\n if (!indices.has(w)) {\n strongconnect(w);\n lowlinks.set(v, Math.min(lowlinks.get(v)!, lowlinks.get(w)!));\n } else if (onStack.has(w)) {\n lowlinks.set(v, Math.min(lowlinks.get(v)!, indices.get(w)!));\n }\n }\n\n if (lowlinks.get(v) === indices.get(v)) {\n const scc: string[] = [];\n let w: string;\n do {\n w = stack.pop()!;\n onStack.delete(w);\n scc.push(w);\n } while (w !== v);\n if (scc.length > 1) {\n sccs.push(scc);\n }\n }\n }\n\n for (const file of allFiles) {\n if (!indices.has(file)) {\n strongconnect(file);\n }\n }\n\n return sccs;\n}\n\n/**\n * Detect circular dependencies using Tarjan's SCC algorithm.\n * Each SCC with size > 1 is reported as a circular dependency chain.\n * Returns up to maxCycles results.\n */\nexport function findCircularDeps(\n graph: ImportGraph,\n maxCycles = 10,\n): CircularDependency[] {\n const sccs = findSCCs(graph);\n\n // Convert SCCs to circular dependency chains\n // Sort by size (smallest first — more actionable)\n sccs.sort((a, b) => a.length - b.length);\n\n const cycles: CircularDependency[] = [];\n for (const scc of sccs) {\n if (cycles.length >= maxCycles) break;\n // Create a chain by closing the loop\n cycles.push({ chain: [...scc, scc[0]] });\n }\n\n return cycles;\n}\n\n/** Directory patterns for classifying files into architectural layers */\nconst LAYER_PATTERNS: Array<{ name: string; pattern: RegExp }> = [\n { name: \"types\", pattern: /(?:^|\\/)types?\\// },\n { name: \"stores\", pattern: /(?:^|\\/)stores?\\// },\n { name: \"hooks\", pattern: /(?:^|\\/)hooks?\\// },\n { name: \"services\", pattern: /(?:^|\\/)(?:services?|api)\\// },\n { name: \"components\", pattern: /(?:^|\\/)components?\\// },\n { name: \"pages\", pattern: /(?:^|\\/)(?:pages?|app|routes?)\\// },\n { name: \"utils\", pattern: /(?:^|\\/)(?:utils?|lib|helpers?)\\// },\n { name: \"config\", pattern: /(?:^|\\/)config\\// },\n];\n\n/**\n * Classify files into architectural layers and determine their dependency ordering.\n * Returns both the layers and directed edges between them.\n */\nexport function detectArchitecturalLayers(graph: ImportGraph): { layers: ArchitecturalLayer[]; layerEdges: LayerEdge[] } {\n // Classify each internal file into a layer\n const layerFiles = new Map<string, string[]>();\n const fileToLayer = new Map<string, string>();\n\n for (const [filePath] of graph.centrality) {\n for (const { name, pattern } of LAYER_PATTERNS) {\n if (pattern.test(filePath)) {\n const files = layerFiles.get(name) ?? [];\n files.push(filePath);\n layerFiles.set(name, files);\n fileToLayer.set(filePath, name);\n break; // First match wins\n }\n }\n }\n\n // Track both directions: who imports each layer, and who each layer depends on\n const layerImportedBy = new Map<string, Set<string>>();\n const layerDependsOn = new Map<string, Set<string>>();\n for (const name of layerFiles.keys()) {\n layerImportedBy.set(name, new Set());\n layerDependsOn.set(name, new Set());\n }\n\n for (const edge of graph.edges) {\n if (edge.isExternal) continue;\n const fromLayer = fileToLayer.get(edge.from);\n const toLayer = fileToLayer.get(edge.to);\n if (fromLayer && toLayer && fromLayer !== toLayer) {\n layerImportedBy.get(toLayer)?.add(fromLayer);\n layerDependsOn.get(fromLayer)?.add(toLayer);\n }\n }\n\n // Build layer edges from dependsOn data\n const layerEdges: LayerEdge[] = [];\n const edgeSet = new Set<string>();\n for (const [from, deps] of layerDependsOn) {\n for (const to of deps) {\n const key = `${from}->${to}`;\n if (!edgeSet.has(key)) {\n edgeSet.add(key);\n layerEdges.push({ from, to });\n }\n }\n }\n\n // Build result sorted by importedByLayers descending (most foundational first)\n const layers: ArchitecturalLayer[] = [];\n for (const [name, files] of layerFiles) {\n layers.push({\n name,\n files,\n importedByLayers: layerImportedBy.get(name)?.size ?? 0,\n dependsOn: [...(layerDependsOn.get(name) ?? [])],\n });\n }\n\n // Sort: most imported layers first (foundational), then by name\n layers.sort((a, b) => b.importedByLayers - a.importedByLayers || a.name.localeCompare(b.name));\n\n return { layers, layerEdges };\n}\n\n/**\n * Compute instability metric (Robert C. Martin) for each file.\n * instability = fanOut / (fanIn + fanOut)\n * Returns files with instability > 0.7 and fanIn >= 3 (high-risk zones).\n */\nexport function computeInstability(graph: ImportGraph): FileInstability[] {\n // Count outgoing internal edges per file\n const fanOutMap = new Map<string, number>();\n for (const edge of graph.edges) {\n if (!edge.isExternal) {\n fanOutMap.set(edge.from, (fanOutMap.get(edge.from) ?? 0) + 1);\n }\n }\n\n const results: FileInstability[] = [];\n for (const [filePath, fanIn] of graph.inDegree) {\n const fanOut = fanOutMap.get(filePath) ?? 0;\n const total = fanIn + fanOut;\n if (total === 0) continue;\n const instability = fanOut / total;\n if (instability > 0.7 && fanIn >= 3) {\n results.push({ path: filePath, fanIn, fanOut, instability });\n }\n }\n\n // Sort by instability descending\n results.sort((a, b) => b.instability - a.instability);\n return results;\n}\n\n/**\n * Detect communities of tightly-connected files using label propagation.\n * Each file starts with a unique label; iteratively adopts the most common\n * label among its neighbors (both directions). Returns communities with size >= 3.\n */\nexport function detectCommunities(graph: ImportGraph): Community[] {\n // Build undirected adjacency from internal edges\n const adj = new Map<string, Set<string>>();\n const allFiles = new Set<string>();\n\n for (const edge of graph.edges) {\n if (edge.isExternal) continue;\n allFiles.add(edge.from);\n allFiles.add(edge.to);\n\n if (!adj.has(edge.from)) adj.set(edge.from, new Set());\n if (!adj.has(edge.to)) adj.set(edge.to, new Set());\n adj.get(edge.from)!.add(edge.to);\n adj.get(edge.to)!.add(edge.from);\n }\n\n const files = [...allFiles];\n if (files.length === 0) return [];\n\n // Initialize: each file gets its own numeric label\n const labels = new Map<string, number>();\n for (let i = 0; i < files.length; i++) {\n labels.set(files[i], i);\n }\n\n // Iterate label propagation (~10 rounds)\n for (let iter = 0; iter < 10; iter++) {\n let changed = false;\n // Shuffle order for better convergence\n const shuffled = [...files];\n for (let i = shuffled.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];\n }\n\n for (const file of shuffled) {\n const neighbors = adj.get(file);\n if (!neighbors || neighbors.size === 0) continue;\n\n // Count neighbor labels\n const labelCounts = new Map<number, number>();\n for (const neighbor of neighbors) {\n const lbl = labels.get(neighbor)!;\n labelCounts.set(lbl, (labelCounts.get(lbl) ?? 0) + 1);\n }\n\n // Find most common label\n let maxCount = 0;\n let bestLabel = labels.get(file)!;\n for (const [lbl, count] of labelCounts) {\n if (count > maxCount) {\n maxCount = count;\n bestLabel = lbl;\n }\n }\n\n if (bestLabel !== labels.get(file)) {\n labels.set(file, bestLabel);\n changed = true;\n }\n }\n\n if (!changed) break;\n }\n\n // Group files by label\n const groups = new Map<number, string[]>();\n for (const [file, label] of labels) {\n const group = groups.get(label) ?? [];\n group.push(file);\n groups.set(label, group);\n }\n\n // Filter to communities with size >= 3, derive labels from common dir prefix\n const communities: Community[] = [];\n let id = 0;\n for (const files of groups.values()) {\n if (files.length < 3) continue;\n const label = deriveLabel(files);\n communities.push({ id: id++, files: files.sort(), label });\n }\n\n // Sort by size descending\n communities.sort((a, b) => b.files.length - a.files.length);\n return communities;\n}\n\n/**\n * Derive a human-readable label from a group of file paths\n * by finding their common directory prefix.\n */\nfunction deriveLabel(files: string[]): string {\n if (files.length === 0) return \"unknown\";\n\n const dirs = files.map((f) => {\n const parts = f.split(\"/\");\n return parts.slice(0, -1).join(\"/\");\n });\n\n // Find common prefix\n const first = dirs[0];\n let prefixLen = first.length;\n for (const dir of dirs) {\n let i = 0;\n while (i < prefixLen && i < dir.length && first[i] === dir[i]) i++;\n prefixLen = i;\n }\n\n let common = first.slice(0, prefixLen);\n // Trim to last full directory segment\n if (common.includes(\"/\")) {\n common = common.slice(0, common.lastIndexOf(\"/\") + 1);\n }\n common = common.replace(/\\/$/, \"\");\n\n return common || files[0].split(\"/\")[0] || \"root\";\n}\n\n/**\n * Compute export coverage for each file — how many of its exports\n * are actually imported by other files in the project.\n */\nexport function computeExportCoverage(graph: ImportGraph): ExportCoverage[] {\n const usedExports = findUsedExports(graph.edges);\n\n // Count total named exports per file (from outgoing edges' importedNames at target)\n // We know a file exports a name if any edge targets it with that name\n const allExportsByFile = new Map<string, Set<string>>();\n\n for (const edge of graph.edges) {\n if (edge.isExternal) continue;\n for (const name of edge.importedNames) {\n if (!allExportsByFile.has(edge.to)) allExportsByFile.set(edge.to, new Set());\n allExportsByFile.get(edge.to)!.add(name);\n }\n }\n\n const results: ExportCoverage[] = [];\n for (const [file, exports] of allExportsByFile) {\n const totalExports = exports.size;\n if (totalExports === 0) continue;\n let usedCount = 0;\n for (const name of exports) {\n if (usedExports.has(`${file}::${name}`)) usedCount++;\n }\n results.push({\n file,\n totalExports,\n usedExports: usedCount,\n coverage: usedCount / totalExports,\n });\n }\n\n // Sort by coverage ascending (worst coverage first)\n results.sort((a, b) => a.coverage - b.coverage);\n return results;\n}\n","import path from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport type {\n CodeSnapshot,\n ContextAnalysis,\n DetectedContext,\n GeneratedFile,\n ProgressCallback,\n UserAnswers,\n} from \"./types.js\";\nimport { fileExists, readJsonFile, writeFileSafe } from \"./utils.js\";\nimport {\n buildMainContext,\n getMainContextFilename,\n} from \"./templates/main-context.js\";\nimport {\n buildCursorRules,\n renderCursorRule,\n} from \"./templates/cursor-rules.js\";\nimport {\n buildClaudeSkills,\n renderClaudeSkill,\n} from \"./templates/claude-skills.js\";\nimport { buildAiderContext } from \"./templates/aider-context.js\";\nimport { detectContext } from \"./detect.js\";\nimport { generateSnapshot } from \"./snapshot.js\";\n\n/**\n * Generate all context files based on detection, user answers, and snapshot.\n * Returns the list of files that were generated.\n * When dryRun is true, no files are written to disk.\n */\nexport async function generateFiles(\n ctx: DetectedContext,\n answers: UserAnswers,\n snapshot: CodeSnapshot | null,\n force: boolean = false,\n dryRun: boolean = false,\n analysis?: ContextAnalysis,\n generateSkills: boolean = false,\n onVerbose?: ProgressCallback,\n): Promise<GeneratedFile[]> {\n const files: GeneratedFile[] = [];\n\n // 1. Main context file\n const mainFilename = getMainContextFilename(answers.ide);\n const mainPath = path.join(ctx.rootDir, mainFilename);\n\n // Aider uses YAML format, everything else uses markdown\n const mainContent =\n answers.ide === \"aider\"\n ? buildAiderContext(ctx, answers, snapshot, analysis)\n : buildMainContext(ctx, answers, snapshot, analysis);\n\n files.push({\n path: mainFilename,\n content: mainContent,\n existed: await fileExists(mainPath),\n });\n onVerbose?.(`Prepared ${mainFilename} (${mainContent.length} bytes)`);\n\n // 2. Cursor-specific scoped rules\n if (answers.ide === \"cursor\") {\n const rules = buildCursorRules(ctx, answers, analysis);\n for (const rule of rules) {\n const rulePath = `.cursor/rules/${rule.filename}`;\n const absPath = path.join(ctx.rootDir, rulePath);\n const ruleContent = renderCursorRule(rule);\n files.push({\n path: rulePath,\n content: ruleContent,\n existed: await fileExists(absPath),\n });\n onVerbose?.(`Prepared ${rulePath} (${ruleContent.length} bytes)`);\n }\n }\n\n // 3. Claude Code skills\n if (generateSkills) {\n const pkgJson = await readJsonFile(path.join(ctx.rootDir, \"package.json\"));\n const scripts = (pkgJson?.scripts as Record<string, string>) ?? undefined;\n const skills = buildClaudeSkills(ctx, answers, analysis, scripts);\n for (const skill of skills) {\n const skillPath = `.claude/skills/${skill.name}/SKILL.md`;\n const absPath = path.join(ctx.rootDir, skillPath);\n const skillContent = renderClaudeSkill(skill);\n files.push({\n path: skillPath,\n content: skillContent,\n existed: await fileExists(absPath),\n });\n onVerbose?.(`Prepared ${skillPath} (${skillContent.length} bytes)`);\n }\n }\n\n // For OpenCode, also generate CLAUDE.md as fallback if main file is AGENTS.md\n if (answers.ide === \"opencode\") {\n const claudePath = path.join(ctx.rootDir, \"CLAUDE.md\");\n const claudeExists = await fileExists(claudePath);\n if (!claudeExists) {\n files.push({\n path: \"CLAUDE.md\",\n content: `# ${path.basename(ctx.rootDir)}\\n\\n> See AGENTS.md for full project context.\\n`,\n existed: false,\n });\n }\n }\n\n // Monorepo per-package context files\n if (\n answers.generatePerPackage &&\n ctx.monorepo &&\n ctx.monorepo.packages.length > 0\n ) {\n const pkgMainFilename =\n answers.ide === \"aider\" ? \".aider.conf.yml\" : getMainContextFilename(answers.ide);\n\n for (const pkg of ctx.monorepo.packages) {\n const pkgRootDir = path.join(ctx.rootDir, pkg.path);\n\n // Detect context for this specific package\n const pkgCtx = await detectContext(pkgRootDir);\n\n // Generate snapshot scoped to this package\n let pkgSnapshot: CodeSnapshot | null = null;\n if (answers.generateSnapshot) {\n pkgSnapshot = await generateSnapshot(pkgCtx, []);\n if (pkgSnapshot.entries.length === 0) pkgSnapshot = null;\n }\n\n // Build scoped answers for this package\n const pkgAnswers: UserAnswers = {\n ...answers,\n projectPurpose: `${pkg.name} — part of the ${path.basename(ctx.rootDir)} monorepo. ${answers.projectPurpose}`,\n generatePerPackage: false, // don't recurse\n };\n\n const pkgContent =\n answers.ide === \"aider\"\n ? buildAiderContext(pkgCtx, pkgAnswers, pkgSnapshot)\n : buildMainContext(pkgCtx, pkgAnswers, pkgSnapshot);\n\n const pkgFilePath = path.join(pkg.path, pkgMainFilename);\n const pkgAbsPath = path.join(ctx.rootDir, pkgFilePath);\n\n files.push({\n path: pkgFilePath,\n content: pkgContent,\n existed: await fileExists(pkgAbsPath),\n });\n }\n }\n\n // Dry run: return files without writing anything\n if (dryRun) {\n return files;\n }\n\n // Check for existing files and ask before overwriting\n const existingFiles = files.filter((f) => f.existed);\n if (existingFiles.length > 0 && !force) {\n p.log.warn(\n `The following files already exist:\\n${existingFiles.map((f) => ` - ${f.path}`).join(\"\\n\")}`,\n );\n\n const overwrite = await p.confirm({\n message: \"Overwrite existing files?\",\n });\n\n if (p.isCancel(overwrite) || !overwrite) {\n // Only write new files\n const newFiles = files.filter((f) => !f.existed);\n if (newFiles.length === 0) {\n p.log.info(\"No new files to write. Exiting.\");\n return [];\n }\n p.log.info(`Writing ${newFiles.length} new file(s), skipping existing.`);\n for (const file of newFiles) {\n await writeFileSafe(path.join(ctx.rootDir, file.path), file.content);\n }\n return newFiles;\n }\n }\n\n // Write all files\n for (const file of files) {\n await writeFileSafe(path.join(ctx.rootDir, file.path), file.content);\n onVerbose?.(`Wrote ${file.path}`);\n }\n\n return files;\n}\n","import type { DetectedContext } from \"../types.js\";\n\ninterface FrameworkHint {\n /** Framework name (matches DetectedFramework.name) */\n name: string;\n /** Markdown conventions to include in context files */\n conventions: string[];\n}\n\n/**\n * Get framework-specific conventions based on detected context.\n * Returns markdown lines (bullet points) to embed in context files.\n */\nexport function getFrameworkHints(ctx: DetectedContext): string[] {\n const hints: string[] = [];\n const frameworkNames = new Set(ctx.frameworks.map((f) => f.name));\n\n for (const gen of HINT_GENERATORS) {\n if (frameworkNames.has(gen.name)) {\n const lines = gen.getHints(ctx);\n if (lines.length > 0) hints.push(...lines);\n }\n }\n\n return hints;\n}\n\n/**\n * Get framework hints as a rendered markdown section.\n * Returns empty string if no hints are applicable.\n */\nexport function getFrameworkHintsSection(ctx: DetectedContext): string {\n const hints = getFrameworkHints(ctx);\n if (hints.length === 0) return \"\";\n\n const lines = [\"## Framework Conventions\", \"\"];\n for (const h of hints) {\n lines.push(h);\n }\n lines.push(\"\");\n return lines.join(\"\\n\");\n}\n\n// --- Hint generators ---\n\ninterface HintGenerator {\n name: string;\n getHints: (ctx: DetectedContext) => string[];\n}\n\nconst HINT_GENERATORS: HintGenerator[] = [\n {\n name: \"Next.js\",\n getHints: (ctx) => {\n const hints: string[] = [];\n const hasAppDir = ctx.directories.some(\n (d) => d === \"app\" || d.startsWith(\"app/\") || d === \"src/app\",\n );\n const hasPagesDir = ctx.directories.some(\n (d) => d === \"pages\" || d.startsWith(\"pages/\") || d === \"src/pages\",\n );\n\n if (hasAppDir && !hasPagesDir) {\n hints.push(\"### Next.js (App Router)\");\n hints.push(\"\");\n hints.push(\n \"- **App Router** — all routes in `app/` use React Server Components by default\",\n );\n hints.push(\n '- Add `\"use client\"` directive at the top of files that need browser APIs, hooks, or event handlers',\n );\n hints.push(\n \"- `layout.tsx` wraps child routes; `page.tsx` is the route's UI; `loading.tsx` / `error.tsx` for boundaries\",\n );\n hints.push(\n \"- Data fetching: `async` server components with direct `fetch()` or DB calls (no `getServerSideProps`)\",\n );\n hints.push(\n \"- Route handlers: `app/api/*/route.ts` with exported `GET`, `POST`, etc. functions\",\n );\n hints.push(\n \"- Middleware in `middleware.ts` at project root for auth, redirects, rewrites\",\n );\n hints.push(\n \"- Use `next/image` for optimized images, `next/font` for font loading\",\n );\n } else if (hasPagesDir && !hasAppDir) {\n hints.push(\"### Next.js (Pages Router)\");\n hints.push(\"\");\n hints.push(\"- **Pages Router** — routes in `pages/` directory\");\n hints.push(\n \"- `getServerSideProps` for server-side data fetching, `getStaticProps` for static generation\",\n );\n hints.push(\n \"- `_app.tsx` for global layout/providers, `_document.tsx` for HTML customization\",\n );\n hints.push(\"- API routes in `pages/api/`\");\n } else if (hasAppDir && hasPagesDir) {\n hints.push(\"### Next.js (Hybrid — App + Pages Router)\");\n hints.push(\"\");\n hints.push(\n \"- Both `app/` (App Router) and `pages/` (Pages Router) coexist — new routes should use App Router\",\n );\n hints.push(\n '- App Router components are server components by default; add `\"use client\"` for client components',\n );\n hints.push(\n \"- Pages Router uses `getServerSideProps` / `getStaticProps` for data fetching\",\n );\n } else {\n hints.push(\"### Next.js\");\n hints.push(\"\");\n hints.push(\n \"- Use `next/image` for optimized images, `next/font` for font loading\",\n );\n hints.push(\n \"- Middleware in `middleware.ts` at project root for auth, redirects, rewrites\",\n );\n }\n return hints;\n },\n },\n {\n name: \"Express\",\n getHints: () => [\n \"### Express\",\n \"\",\n \"- Middleware chain: `app.use()` for global, router-level for scoped. Order matters.\",\n \"- Error handling: define a 4-arg middleware `(err, req, res, next)` at the end of the chain\",\n \"- Organize routes with `express.Router()` in separate files, mount with `app.use('/prefix', router)`\",\n \"- Validate request bodies/params at the route level (e.g. with zod, joi, or express-validator)\",\n \"- Use `async` handlers with try/catch or an async wrapper to avoid unhandled promise rejections\",\n \"- Set `res.status()` before `res.json()` — don't rely on defaults for error responses\",\n ],\n },\n {\n name: \"Fastify\",\n getHints: () => [\n \"### Fastify\",\n \"\",\n \"- Plugin architecture: register plugins with `fastify.register()` for encapsulation\",\n \"- Schema-based validation: use JSON Schema for request/response validation (built-in)\",\n \"- Hooks: `onRequest`, `preHandler`, `onSend` etc. for request lifecycle\",\n \"- Use `fastify-plugin` for plugins that should not be encapsulated\",\n \"- Serialization: define response schemas for 2x faster JSON serialization\",\n ],\n },\n {\n name: \"Hono\",\n getHints: () => [\n \"### Hono\",\n \"\",\n \"- Middleware with `app.use()` — compose with `c.next()` pattern\",\n \"- Validators: use `hono/validator` or `@hono/zod-validator` for type-safe request parsing\",\n \"- Context (`c`): `c.json()`, `c.text()`, `c.html()` for responses; `c.req` for request\",\n \"- Supports multiple runtimes (Node, Deno, Bun, Cloudflare Workers) — avoid Node-specific APIs\",\n ],\n },\n {\n name: \"NestJS\",\n getHints: () => [\n \"### NestJS\",\n \"\",\n \"- **Modules** organize the app into cohesive blocks; every feature gets a module\",\n \"- **Controllers** handle HTTP requests (decorators: `@Get()`, `@Post()`, etc.)\",\n \"- **Providers** (services) hold business logic — injected via constructor DI\",\n \"- **Guards** for auth (`@UseGuards()`), **Pipes** for validation (`@UsePipes()`)\",\n \"- **Interceptors** for response transformation, logging, caching\",\n \"- DTOs with `class-validator` decorators for request validation\",\n \"- Use `@Injectable()` on all services/providers\",\n ],\n },\n {\n name: \"Expo\",\n getHints: (ctx) => {\n const hasRN = ctx.frameworks.some((f) => f.name === \"React Native\");\n const hints = [\"### Expo / React Native\", \"\"];\n hints.push(\n \"- **expo-router** for file-based routing (if using); Stack, Tabs, Drawer navigators\",\n );\n hints.push(\n \"- Expo Go has limited native module support — some packages require a dev build (`npx expo run:ios`)\",\n );\n hints.push(\n \"- Use `expo-constants`, `expo-device` etc. instead of raw RN APIs when available\",\n );\n hints.push(\n \"- Platform-specific files: `*.ios.tsx` / `*.android.tsx` or `Platform.select()`\",\n );\n if (hasRN) {\n hints.push(\n \"- **Reanimated**: worklet functions need the `\\\"worklet\\\"` directive on the first line\",\n );\n hints.push(\n \"- Avoid `FadeIn`/`FadeOut` entering/exiting animations on conditionally rendered components — they cause flashes\",\n );\n }\n return hints;\n },\n },\n {\n name: \"React Native\",\n getHints: (ctx) => {\n // Only emit if Expo is NOT also detected (Expo handler covers RN+Expo)\n if (ctx.frameworks.some((f) => f.name === \"Expo\")) return [];\n return [\n \"### React Native\",\n \"\",\n \"- Use `StyleSheet.create()` for styles — avoid inline style objects in render\",\n \"- Platform-specific: `*.ios.tsx` / `*.android.tsx` or `Platform.select()`\",\n \"- **Reanimated**: worklet functions need the `\\\"worklet\\\"` directive\",\n \"- Navigation: React Navigation with Stack/Tab/Drawer navigators\",\n \"- Test with both iOS and Android — layout behavior differs\",\n ];\n },\n },\n {\n name: \"React\",\n getHints: (ctx) => {\n // Skip if Next.js, Expo, or React Native is detected (they have their own hints)\n const skip = [\"Next.js\", \"Expo\", \"React Native\"];\n if (ctx.frameworks.some((f) => skip.includes(f.name))) return [];\n return [\n \"### React\",\n \"\",\n \"- Functional components with hooks — no class components\",\n \"- Use `React.memo()` for expensive renders, `useMemo`/`useCallback` for referential stability\",\n \"- Lift state up or use context for shared state; avoid prop drilling beyond 2-3 levels\",\n \"- Prefer controlled components for forms\",\n \"- Use `Suspense` boundaries with `lazy()` for code splitting\",\n ];\n },\n },\n {\n name: \"Vue\",\n getHints: () => [\n \"### Vue\",\n \"\",\n \"- Composition API with `<script setup>` for new components\",\n \"- Reactive state: `ref()` for primitives, `reactive()` for objects\",\n \"- `computed()` for derived state, `watch()` / `watchEffect()` for side effects\",\n \"- Props: define with `defineProps<T>()`, emits with `defineEmits<T>()`\",\n \"- Use `provide` / `inject` for deep dependency injection\",\n ],\n },\n {\n name: \"Nuxt\",\n getHints: () => [\n \"### Nuxt\",\n \"\",\n \"- Auto-imports: components, composables, and utils are auto-imported — no manual import needed\",\n \"- File-based routing in `pages/` — dynamic params with `[id].vue` syntax\",\n \"- Data fetching: `useFetch()` / `useAsyncData()` — they handle SSR hydration automatically\",\n \"- Server routes in `server/api/` — auto-registered, use `defineEventHandler()`\",\n \"- Middleware in `middleware/` — `defineNuxtRouteMiddleware()` for route guards\",\n \"- State: `useState()` for SSR-safe shared state, Pinia for complex stores\",\n ],\n },\n {\n name: \"Svelte\",\n getHints: (ctx) => {\n if (ctx.frameworks.some((f) => f.name === \"SvelteKit\")) return [];\n return [\n \"### Svelte\",\n \"\",\n \"- Reactive declarations with `$:` for derived state\",\n \"- Props: `export let propName` in component script\",\n \"- Stores: `writable()`, `readable()`, `derived()` — auto-subscribe with `$store` syntax\",\n \"- Use `{#if}`, `{#each}`, `{#await}` blocks for conditional/list/async rendering\",\n ];\n },\n },\n {\n name: \"SvelteKit\",\n getHints: () => [\n \"### SvelteKit\",\n \"\",\n \"- File-based routing in `src/routes/` — `+page.svelte`, `+layout.svelte`, `+server.ts`\",\n \"- `+page.ts` (universal) or `+page.server.ts` (server-only) for `load` functions\",\n \"- Form actions in `+page.server.ts` with `actions` export for progressive enhancement\",\n \"- Hooks in `src/hooks.server.ts` for auth, session, error handling\",\n \"- Use `$app/stores` for page, navigating, updated stores\",\n ],\n },\n {\n name: \"Angular\",\n getHints: () => [\n \"### Angular\",\n \"\",\n \"- Components, services, pipes, directives all use decorators (`@Component`, `@Injectable`, etc.)\",\n \"- Dependency injection: provide services in module or component `providers` array\",\n \"- RxJS Observables for async data — use `async` pipe in templates, unsubscribe on destroy\",\n \"- Lazy-load feature modules with `loadChildren` in routes\",\n \"- Use Angular CLI (`ng generate`) for scaffolding\",\n ],\n },\n {\n name: \"Django\",\n getHints: () => [\n \"### Django\",\n \"\",\n \"- Apps structure: each feature is a Django app with `models.py`, `views.py`, `urls.py`, `admin.py`\",\n \"- Models: define in `models.py`, create migrations with `python manage.py makemigrations`\",\n \"- Views: function-based (FBV) or class-based (CBV) — CBV for CRUD, FBV for custom logic\",\n \"- URL routing in `urls.py` using `path()` and `include()` for app-level URLs\",\n \"- Templates in `templates/` — use template inheritance with `{% extends %}` and `{% block %}`\",\n \"- Management commands in `management/commands/` for custom CLI tasks\",\n \"- Settings: use `django-environ` or `python-decouple` for environment-based config\",\n ],\n },\n {\n name: \"Flask\",\n getHints: () => [\n \"### Flask\",\n \"\",\n \"- Blueprints for modular route organization — register with `app.register_blueprint()`\",\n \"- Use application factory pattern (`create_app()`) for testing and config flexibility\",\n \"- Error handlers with `@app.errorhandler(404)` etc.\",\n \"- Use Flask-SQLAlchemy for ORM, Flask-Migrate for database migrations\",\n \"- Request context: `request`, `g`, `session` globals — available inside request handlers\",\n ],\n },\n {\n name: \"FastAPI\",\n getHints: () => [\n \"### FastAPI\",\n \"\",\n \"- **Dependency injection**: use `Depends()` for shared logic (auth, DB sessions, validation)\",\n \"- **Pydantic models** for request/response schemas — automatic validation and OpenAPI docs\",\n \"- Async endpoints by default (`async def`); use sync `def` only for blocking I/O with threadpool\",\n \"- Routers: `APIRouter()` for modular route organization, mount with `app.include_router()`\",\n \"- Middleware with `@app.middleware(\\\"http\\\")` or Starlette middleware classes\",\n \"- Background tasks with `BackgroundTasks` parameter for fire-and-forget work\",\n \"- Auto-generated docs at `/docs` (Swagger) and `/redoc`\",\n ],\n },\n {\n name: \"Prisma\",\n getHints: () => [\n \"### Prisma\",\n \"\",\n \"- Schema in `prisma/schema.prisma` — run `npx prisma generate` after changes\",\n \"- Migrations: `npx prisma migrate dev` for development, `npx prisma migrate deploy` for production\",\n \"- Use `prisma.$transaction()` for atomic operations\",\n \"- Relation queries: use `include` for eager loading, `select` for field filtering\",\n ],\n },\n {\n name: \"Drizzle\",\n getHints: () => [\n \"### Drizzle\",\n \"\",\n \"- Schema defined in TypeScript — type-safe queries with no code generation step\",\n \"- Migrations: `drizzle-kit generate` then `drizzle-kit migrate`\",\n \"- Use `db.select()`, `db.insert()`, `db.update()`, `db.delete()` for queries\",\n \"- Relations: define with `relations()` helper for type-safe joins\",\n ],\n },\n {\n name: \"Tailwind CSS\",\n getHints: (ctx) => {\n // Skip if NativeWind is detected (Expo/RN handles it)\n if (ctx.frameworks.some((f) => f.name === \"NativeWind\")) return [];\n return [\n \"### Tailwind CSS\",\n \"\",\n \"- Utility-first: compose styles with `className` — avoid custom CSS unless truly needed\",\n \"- Use `@apply` sparingly in CSS modules for repeated patterns\",\n \"- Responsive: mobile-first with `sm:`, `md:`, `lg:` breakpoint prefixes\",\n \"- Dark mode: `dark:` variant (class or media strategy per `tailwind.config`)\",\n \"- Extract reusable component classes into shared components, not `@apply` blocks\",\n ];\n },\n },\n {\n name: \"Electron\",\n getHints: () => [\n \"### Electron\",\n \"\",\n \"- **Main process** (Node.js) and **renderer process** (Chromium) — communicate via IPC\",\n \"- Use `contextBridge` + `preload.js` to expose safe APIs to renderer (no `nodeIntegration`)\",\n \"- `ipcMain.handle()` / `ipcRenderer.invoke()` for async request-response patterns\",\n \"- Package with `electron-builder` or `electron-forge`\",\n ],\n },\n];\n","import type { ArchitecturalLayer, CodeSnapshot, ContextAnalysis, DetectedContext, LayerEdge, UserAnswers } from \"../types.js\";\nimport { summarizeDetection } from \"../detect.js\";\nimport { getFrameworkHintsSection } from \"./framework-hints.js\";\n\n/**\n * Build the main context file content (CLAUDE.md, AGENTS.md, or CONTEXT.md).\n */\nexport function buildMainContext(\n ctx: DetectedContext,\n answers: UserAnswers,\n snapshot: CodeSnapshot | null,\n analysis?: ContextAnalysis,\n): string {\n const projectName = getProjectName(ctx);\n const stackSummary = answers.stackConfirmed\n ? summarizeDetection(ctx)\n : answers.stackCorrections || summarizeDetection(ctx);\n\n const sections: string[] = [];\n\n // -- Header --\n sections.push(`# ${projectName}`);\n sections.push(\"\");\n\n // -- Maintenance directive --\n sections.push(\n \"> **Keep this file up to date.** When you change the architecture, add a dependency, create a new pattern, or learn a gotcha, update this file in the same step. This is the source of truth for how the project works.\",\n );\n\n if (answers.ide === \"cursor\") {\n sections.push(\n \"> Scoped rules are in `.cursor/rules/` -- update them when conventions change.\",\n );\n }\n\n sections.push(\"\");\n\n // -- What Is This --\n sections.push(\"## What Is This\");\n sections.push(\"\");\n sections.push(answers.projectPurpose);\n sections.push(\"\");\n\n // -- Tech Stack --\n sections.push(\"## Tech Stack\");\n sections.push(\"\");\n sections.push(buildTechStackSection(ctx, stackSummary));\n sections.push(\"\");\n\n // -- Framework Conventions --\n const fwHints = getFrameworkHintsSection(ctx);\n if (fwHints) {\n sections.push(fwHints);\n }\n\n // -- Project Structure --\n if (ctx.directories.length > 0) {\n sections.push(\"## Project Structure\");\n sections.push(\"\");\n sections.push(\"```\");\n sections.push(buildStructureTree(ctx));\n sections.push(\"```\");\n sections.push(\"\");\n }\n\n // -- Monorepo Structure --\n if (ctx.monorepo && ctx.monorepo.packages.length > 0) {\n sections.push(\"## Monorepo Structure\");\n sections.push(\"\");\n sections.push(\n `${ctx.monorepo.type} workspace with ${ctx.monorepo.packages.length} packages:`,\n );\n sections.push(\"\");\n for (const pkg of ctx.monorepo.packages) {\n const fws =\n pkg.frameworks.length > 0\n ? ` — ${pkg.frameworks.map((f) => f.name).join(\", \")}`\n : \"\";\n sections.push(`- **${pkg.name}** (\\`${pkg.path}\\`)${fws}`);\n }\n sections.push(\"\");\n }\n\n // -- Code Snapshot --\n if (snapshot?.markdown) {\n sections.push(\"## Code Snapshot\");\n sections.push(\"\");\n sections.push(\n \"<!-- CODE SNAPSHOT (auto-generated, update when types/stores/services change) -->\",\n );\n sections.push(\"\");\n sections.push(snapshot.markdown);\n sections.push(\"\");\n sections.push(\"<!-- /CODE SNAPSHOT -->\");\n sections.push(\"\");\n }\n\n // -- Key Files (hub files) --\n if (analysis?.hubFiles && analysis.hubFiles.length > 0) {\n // Build instability lookup for flagging risky files\n const instabilityMap = new Map<string, number>();\n if (analysis.instabilities) {\n for (const inst of analysis.instabilities) {\n instabilityMap.set(inst.path, inst.instability);\n }\n }\n\n sections.push(\"## Key Files\");\n sections.push(\"\");\n sections.push(\n \"These are the most interconnected files. Read these first for architectural understanding.\",\n );\n sections.push(\"\");\n sections.push(\"| File | Imported By | Stability |\");\n sections.push(\"|------|-------------|-----------|\");\n for (const hub of analysis.hubFiles) {\n const inst = instabilityMap.get(hub.path);\n const stabilityCell = inst != null\n ? `${(inst * 100).toFixed(0)}% unstable ⚠️`\n : \"stable\";\n sections.push(\n `| \\`${hub.path}\\` | ${hub.importedBy} file${hub.importedBy === 1 ? \"\" : \"s\"} | ${stabilityCell} |`,\n );\n }\n sections.push(\"\");\n }\n\n // -- Architecture (layer ordering) --\n if (analysis?.layers && analysis.layers.length > 1) {\n sections.push(\"## Architecture\");\n sections.push(\"\");\n const diagram = renderArchitectureDiagram(analysis.layers, analysis.layerEdges ?? []);\n sections.push(diagram);\n sections.push(\"\");\n }\n\n // -- Recently Active Files --\n if (analysis?.gitActivity && analysis.gitActivity.hotFiles.length > 0) {\n sections.push(\"## Recently Active Files\");\n sections.push(\"\");\n sections.push(\"| File | Commits (90d) | Last Changed |\");\n sections.push(\"|------|--------------|--------------|\");\n for (const hot of analysis.gitActivity.hotFiles.slice(0, 10)) {\n sections.push(\n `| \\`${hot.path}\\` | ${hot.commits} | ${hot.lastChanged} |`,\n );\n }\n sections.push(\"\");\n }\n\n // -- Change Coupling --\n if (analysis?.gitActivity?.changeCoupling && analysis.gitActivity.changeCoupling.length > 0) {\n sections.push(\"## Change Coupling\");\n sections.push(\"\");\n sections.push(\n \"Files that frequently change together. Consider whether they should be colocated or decoupled.\",\n );\n sections.push(\"\");\n sections.push(\"| File A | File B | Co-changes | Confidence |\");\n sections.push(\"|--------|--------|------------|------------|\");\n for (const pair of analysis.gitActivity.changeCoupling) {\n sections.push(\n `| \\`${pair.fileA}\\` | \\`${pair.fileB}\\` | ${pair.coChangeCount} | ${(pair.confidence * 100).toFixed(0)}% |`,\n );\n }\n sections.push(\"\");\n }\n\n // -- Circular Dependencies --\n if (analysis?.circularDeps && analysis.circularDeps.length > 0) {\n sections.push(\"## Circular Dependencies\");\n sections.push(\"\");\n sections.push(\n \"> These circular import chains may cause unexpected behavior when modified.\",\n );\n sections.push(\"\");\n for (const dep of analysis.circularDeps) {\n sections.push(`- ${dep.chain.map((f) => `\\`${f}\\``).join(\" -> \")}`);\n }\n sections.push(\"\");\n }\n\n // -- Export Coverage --\n if (analysis?.exportCoverage && analysis.exportCoverage.length > 0) {\n const underCovered = analysis.exportCoverage.filter((e) => e.coverage < 1);\n if (underCovered.length > 0) {\n sections.push(\"## Export Coverage\");\n sections.push(\"\");\n sections.push(\n \"Files with unused exports. Consider removing dead exports to reduce surface area.\",\n );\n sections.push(\"\");\n sections.push(\"| File | Used | Total | Coverage |\");\n sections.push(\"|------|------|-------|----------|\");\n for (const entry of underCovered.slice(0, 10)) {\n sections.push(\n `| \\`${entry.file}\\` | ${entry.usedExports} | ${entry.totalExports} | ${(entry.coverage * 100).toFixed(0)}% |`,\n );\n }\n sections.push(\"\");\n }\n }\n\n // -- Module Clusters --\n if (analysis?.communities && analysis.communities.length > 0) {\n sections.push(\"## Module Clusters\");\n sections.push(\"\");\n sections.push(\n \"Automatically detected groups of tightly-connected files.\",\n );\n sections.push(\"\");\n for (const community of analysis.communities) {\n sections.push(`- **${community.label}** (${community.files.length} files): ${community.files.map((f) => `\\`${f}\\``).join(\", \")}`);\n }\n sections.push(\"\");\n }\n\n // -- Key Patterns --\n if (answers.keyPatterns) {\n sections.push(\"## Key Patterns\");\n sections.push(\"\");\n // Split on newlines or periods to create bullet points\n const patterns = answers.keyPatterns\n .split(/[.\\n]/)\n .map((s) => s.trim())\n .filter(Boolean);\n for (const p of patterns) {\n sections.push(`- ${p}`);\n }\n sections.push(\"\");\n }\n\n // -- Gotchas --\n if (answers.gotchas) {\n sections.push(\"## Gotchas\");\n sections.push(\"\");\n const gotchas = answers.gotchas\n .split(/[.\\n]/)\n .map((s) => s.trim())\n .filter(Boolean);\n for (const g of gotchas) {\n sections.push(`- ${g}`);\n }\n sections.push(\"\");\n }\n\n // -- Development --\n sections.push(\"## Development\");\n sections.push(\"\");\n sections.push(buildDevSection(ctx));\n sections.push(\"\");\n\n return sections.join(\"\\n\").trimEnd() + \"\\n\";\n}\n\n/**\n * Render an ASCII architecture diagram using Unicode box-drawing characters.\n * Falls back to inline `types → stores → ...` if >6 layers or 0 edges.\n */\nfunction renderArchitectureDiagram(layers: ArchitecturalLayer[], layerEdges: LayerEdge[]): string {\n // Fallback to inline rendering for edge cases\n if (layers.length > 6 || layerEdges.length === 0) {\n const layerNames = layers.map((l) => `\\`${l.name}\\``);\n return \"Dependency flow (foundational → consumer):\\n\\n\" + layerNames.join(\" → \");\n }\n\n // Assign layers to rows: foundational layers first (most importedByLayers),\n // max 3 per row\n const maxPerRow = 3;\n const rows: ArchitecturalLayer[][] = [];\n for (let i = 0; i < layers.length; i += maxPerRow) {\n rows.push(layers.slice(i, i + maxPerRow));\n }\n\n // Build the box diagram\n const boxWidth = 14; // Fixed box inner width\n const boxOuter = boxWidth + 2; // +2 for side borders\n const gap = 4; // Space between boxes\n\n const layerSet = new Set(layers.map((l) => l.name));\n const layerRowIndex = new Map<string, number>();\n const layerColIndex = new Map<string, number>();\n for (let r = 0; r < rows.length; r++) {\n for (let c = 0; c < rows[r].length; c++) {\n layerRowIndex.set(rows[r][c].name, r);\n layerColIndex.set(rows[r][c].name, c);\n }\n }\n\n // Classify edges as same-row (horizontal) or cross-row (vertical)\n const horizontalEdges: LayerEdge[] = [];\n const verticalEdges: LayerEdge[] = [];\n for (const edge of layerEdges) {\n if (!layerSet.has(edge.from) || !layerSet.has(edge.to)) continue;\n const fromRow = layerRowIndex.get(edge.from)!;\n const toRow = layerRowIndex.get(edge.to)!;\n if (fromRow === toRow) {\n horizontalEdges.push(edge);\n } else {\n verticalEdges.push(edge);\n }\n }\n\n const lines: string[] = [];\n lines.push(\"```\");\n\n for (let r = 0; r < rows.length; r++) {\n const row = rows[r];\n\n // Top border: ┌──────────────┐\n const topLine = row\n .map((l) => {\n const name = l.name;\n const pad = boxWidth - name.length;\n return \"┌\" + \"─\".repeat(boxWidth) + \"┐\";\n })\n .join(\" \".repeat(gap));\n lines.push(topLine);\n\n // Content: │ types │\n const midLine = row\n .map((l) => {\n const name = l.name;\n const padLeft = Math.floor((boxWidth - name.length) / 2);\n const padRight = boxWidth - name.length - padLeft;\n return \"│\" + \" \".repeat(padLeft) + name + \" \".repeat(padRight) + \"│\";\n })\n .join(\" \".repeat(gap));\n lines.push(midLine);\n\n // Bottom border: └──────────────┘\n const botLine = row\n .map(() => \"└\" + \"─\".repeat(boxWidth) + \"┘\")\n .join(\" \".repeat(gap));\n lines.push(botLine);\n\n // Draw vertical arrows between rows\n if (r < rows.length - 1) {\n const nextRow = rows[r + 1];\n // Find vertical edges from this row to next row\n const downEdges = verticalEdges.filter((e) => {\n const fromR = layerRowIndex.get(e.from)!;\n const toR = layerRowIndex.get(e.to)!;\n return (fromR === r && toR === r + 1) || (fromR === r + 1 && toR === r);\n });\n\n if (downEdges.length > 0) {\n // Draw connector lines (│ and ▼)\n const rowWidth = row.length * boxOuter + (row.length - 1) * gap;\n const arrowLine1 = buildArrowLine(row, \"│\", boxOuter, gap, rowWidth);\n const arrowLine2 = buildArrowLine(nextRow.length > row.length ? nextRow : row, \"▼\", boxOuter, gap, rowWidth);\n lines.push(arrowLine1);\n lines.push(arrowLine2);\n }\n }\n }\n\n // Add horizontal arrow legend for same-row dependencies\n if (horizontalEdges.length > 0) {\n lines.push(\"\");\n for (const edge of horizontalEdges) {\n lines.push(` ${edge.from} ────▶ ${edge.to}`);\n }\n }\n\n lines.push(\"```\");\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Build a line with a character centered under each box in a row.\n */\nfunction buildArrowLine(row: ArchitecturalLayer[], char: string, boxOuter: number, gap: number, _totalWidth: number): string {\n const parts: string[] = [];\n for (let c = 0; c < row.length; c++) {\n const center = Math.floor(boxOuter / 2);\n if (c > 0) {\n // Add gap spacing\n parts.push(\" \".repeat(gap));\n }\n parts.push(\" \".repeat(center) + char + \" \".repeat(boxOuter - center - 1));\n }\n return parts.join(\"\");\n}\n\nfunction getProjectName(ctx: DetectedContext): string {\n // Extract from directory name\n const dirName = ctx.rootDir.split(\"/\").pop() ?? \"Project\";\n // Capitalize first letter\n return dirName.charAt(0).toUpperCase() + dirName.slice(1);\n}\n\nfunction buildTechStackSection(ctx: DetectedContext, summary: string): string {\n const lines: string[] = [];\n\n if (ctx.frameworks.length > 0) {\n for (const fw of ctx.frameworks) {\n const ver = fw.version ? ` ${fw.version}` : \"\";\n const usage = fw.importCount != null ? ` (used in ${fw.importCount} file${fw.importCount === 1 ? \"\" : \"s\"})` : \"\";\n lines.push(`- **${fw.name}**${ver}${usage}`);\n }\n }\n\n if (ctx.hasTypeScript) {\n lines.push(\"- **TypeScript**\");\n }\n\n if (ctx.linter !== \"none\") {\n const name = ctx.linter.charAt(0).toUpperCase() + ctx.linter.slice(1);\n lines.push(`- **${name}** (linter/formatter)`);\n }\n\n if (ctx.packageManager !== \"none\") {\n lines.push(`- **${ctx.packageManager}** (package manager)`);\n }\n\n if (lines.length === 0) {\n lines.push(`Stack: ${summary}`);\n }\n\n return lines.join(\"\\n\");\n}\n\nfunction buildStructureTree(ctx: DetectedContext): string {\n // Group directories by top-level\n const lines: string[] = [];\n const grouped = new Map<string, string[]>();\n\n for (const dir of ctx.directories) {\n const parts = dir.split(\"/\");\n if (parts.length === 1) {\n if (!grouped.has(dir)) grouped.set(dir, []);\n } else {\n const parent = parts[0];\n const child = parts.slice(1).join(\"/\");\n const children = grouped.get(parent) ?? [];\n children.push(child);\n grouped.set(parent, children);\n }\n }\n\n for (const [dir, children] of grouped) {\n lines.push(`${dir}/`);\n for (const child of children) {\n lines.push(` ${child}/`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n\nfunction buildDevSection(ctx: DetectedContext): string {\n const lines: string[] = [];\n\n // Run command\n switch (ctx.packageManager) {\n case \"pnpm\":\n lines.push(\"```bash\");\n lines.push(\"pnpm install\");\n lines.push(\"pnpm dev\");\n lines.push(\"```\");\n break;\n case \"yarn\":\n lines.push(\"```bash\");\n lines.push(\"yarn install\");\n lines.push(\"yarn dev\");\n lines.push(\"```\");\n break;\n case \"bun\":\n lines.push(\"```bash\");\n lines.push(\"bun install\");\n lines.push(\"bun dev\");\n lines.push(\"```\");\n break;\n case \"npm\":\n lines.push(\"```bash\");\n lines.push(\"npm install\");\n lines.push(\"npm run dev\");\n lines.push(\"```\");\n break;\n case \"pip\":\n case \"poetry\":\n lines.push(\"```bash\");\n lines.push(\n ctx.packageManager === \"poetry\"\n ? \"poetry install\"\n : \"pip install -r requirements.txt\",\n );\n lines.push(\"```\");\n break;\n case \"cargo\":\n lines.push(\"```bash\");\n lines.push(\"cargo build\");\n lines.push(\"cargo run\");\n lines.push(\"```\");\n break;\n case \"go\":\n lines.push(\"```bash\");\n lines.push(\"go build ./...\");\n lines.push(\"go run .\");\n lines.push(\"```\");\n break;\n default:\n lines.push(\"(add your build/run commands here)\");\n }\n\n // Lint command\n if (ctx.linter !== \"none\") {\n lines.push(\"\");\n lines.push(`Linter: **${ctx.linter}**`);\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Get the filename for the main context file based on IDE target.\n */\nexport function getMainContextFilename(ide: UserAnswers[\"ide\"]): string {\n switch (ide) {\n case \"claude\":\n return \"CLAUDE.md\";\n case \"cursor\":\n return \"CLAUDE.md\";\n case \"opencode\":\n return \"AGENTS.md\";\n case \"copilot\":\n return \".github/copilot-instructions.md\";\n case \"windsurf\":\n return \".windsurfrules\";\n case \"cline\":\n return \".clinerules\";\n case \"continue\":\n return \".continuerules\";\n case \"aider\":\n return \".aider.conf.yml\";\n case \"generic\":\n return \"CONTEXT.md\";\n }\n}\n","import type { ContextAnalysis, DetectedContext, UserAnswers } from \"../types.js\";\nimport { getFrameworkHints } from \"./framework-hints.js\";\n\ninterface CursorRule {\n /** Filename (without path) */\n filename: string;\n /** Frontmatter description */\n description: string;\n /** Glob patterns for file matching */\n globs: string;\n /** Rule body content */\n body: string;\n}\n\n/**\n * Generate .cursor/rules/*.md files based on detected project structure.\n */\nexport function buildCursorRules(\n ctx: DetectedContext,\n answers: UserAnswers,\n analysis?: ContextAnalysis,\n): CursorRule[] {\n const rules: CursorRule[] = [];\n\n // Always create a global rule\n rules.push(buildGlobalRule(ctx, answers, analysis));\n\n // Component rule (if components/ directory exists)\n const hasComponents = ctx.directories.some(\n (d) => d.endsWith(\"components\") || d.includes(\"components/\"),\n );\n if (hasComponents) {\n rules.push(buildComponentsRule(ctx));\n }\n\n // Services rule (if services/ or api/ exists)\n const hasServices = ctx.directories.some(\n (d) =>\n d.endsWith(\"services\") ||\n d.endsWith(\"api\") ||\n d.includes(\"services/\") ||\n d.includes(\"api/\"),\n );\n if (hasServices) {\n rules.push(buildServicesRule(ctx));\n }\n\n // Stores rule (if stores/ or store/ exists)\n const hasStores = ctx.directories.some(\n (d) =>\n d.endsWith(\"stores\") ||\n d.endsWith(\"store\") ||\n d.includes(\"stores/\") ||\n d.includes(\"store/\"),\n );\n if (hasStores) {\n rules.push(buildStoresRule(ctx));\n }\n\n return rules;\n}\n\nfunction buildGlobalRule(ctx: DetectedContext, answers: UserAnswers, analysis?: ContextAnalysis): CursorRule {\n const bodyLines: string[] = [\n \"# Global Rules\",\n \"\",\n `> Update this rule and the main context file after any architectural or convention change.`,\n \"\",\n ];\n\n // Add gotchas if provided\n if (answers.gotchas) {\n bodyLines.push(\"## Gotchas\");\n bodyLines.push(\"\");\n const gotchas = answers.gotchas\n .split(/[.\\n]/)\n .map((s) => s.trim())\n .filter(Boolean);\n for (const g of gotchas) {\n bodyLines.push(`- ${g}`);\n }\n bodyLines.push(\"\");\n }\n\n // Instability warnings\n if (analysis?.instabilities && analysis.instabilities.length > 0) {\n bodyLines.push(\"## High-Instability Files\");\n bodyLines.push(\"\");\n bodyLines.push(\n \"> These files have many dependents but also many dependencies (unstable). Changes here have high blast radius.\",\n );\n bodyLines.push(\"\");\n for (const inst of analysis.instabilities) {\n bodyLines.push(`- \\`${inst.path}\\` — ${(inst.instability * 100).toFixed(0)}% unstable (${inst.fanIn} dependents, ${inst.fanOut} dependencies)`);\n }\n bodyLines.push(\"\");\n }\n\n // Change coupling warnings\n if (analysis?.gitActivity?.changeCoupling && analysis.gitActivity.changeCoupling.length > 0) {\n bodyLines.push(\"## Change Coupling\");\n bodyLines.push(\"\");\n bodyLines.push(\n \"> These file pairs frequently change together. When modifying one, check the other.\",\n );\n bodyLines.push(\"\");\n for (const pair of analysis.gitActivity.changeCoupling.slice(0, 5)) {\n bodyLines.push(`- \\`${pair.fileA}\\` ↔ \\`${pair.fileB}\\` (${pair.coChangeCount} co-changes, ${(pair.confidence * 100).toFixed(0)}% confidence)`);\n }\n bodyLines.push(\"\");\n }\n\n // Circular dependency warnings\n if (analysis?.circularDeps && analysis.circularDeps.length > 0) {\n bodyLines.push(\"## Circular Dependencies\");\n bodyLines.push(\"\");\n bodyLines.push(\n \"> These circular import chains may cause unexpected behavior. Avoid adding to them.\",\n );\n bodyLines.push(\"\");\n for (const dep of analysis.circularDeps) {\n bodyLines.push(`- ${dep.chain.join(\" -> \")}`);\n }\n bodyLines.push(\"\");\n }\n\n // Module clusters\n if (analysis?.communities && analysis.communities.length > 0) {\n bodyLines.push(\"## Module Clusters\");\n bodyLines.push(\"\");\n bodyLines.push(\n \"> Tightly-connected file groups. Changes in one file likely affect others in the same cluster.\",\n );\n bodyLines.push(\"\");\n for (const community of analysis.communities.slice(0, 5)) {\n bodyLines.push(`- **${community.label}** (${community.files.length} files): ${community.files.map((f) => `\\`${f}\\``).join(\", \")}`);\n }\n bodyLines.push(\"\");\n }\n\n // Framework conventions\n const fwHints = getFrameworkHints(ctx);\n if (fwHints.length > 0) {\n bodyLines.push(\"## Framework Conventions\");\n bodyLines.push(\"\");\n for (const hint of fwHints) {\n bodyLines.push(hint);\n }\n bodyLines.push(\"\");\n }\n\n // Linter info\n if (ctx.linter !== \"none\") {\n bodyLines.push(\n `- Linter: **${ctx.linter}**. Run lint before committing.`,\n );\n }\n\n // Keep context files updated\n bodyLines.push(\n \"- After any architectural or convention change, update the relevant context files.\",\n );\n\n const ext = getExtGlob(ctx);\n\n return {\n filename: \"global.md\",\n description: \"Universal project rules\",\n globs: `**/*.${ext}`,\n body: bodyLines.join(\"\\n\"),\n };\n}\n\nfunction buildComponentsRule(ctx: DetectedContext): CursorRule {\n const compDir = ctx.directories.find(\n (d) => d.endsWith(\"components\") || d.includes(\"components/\"),\n ) ?? \"src/components\";\n\n const bodyLines: string[] = [\n \"# UI Components\",\n \"\",\n \"> Update this rule when component conventions change.\",\n \"\",\n \"## Conventions\",\n \"\",\n ];\n\n // Add framework-specific hints\n const hasReact = ctx.frameworks.some(\n (f) => f.name === \"React\" || f.name === \"React Native\",\n );\n const hasTailwind = ctx.frameworks.some(\n (f) => f.name === \"Tailwind CSS\" || f.name === \"NativeWind\",\n );\n\n if (hasReact) {\n bodyLines.push(\"- Functional components with hooks (no class components)\");\n bodyLines.push(\"- Use `memo()` for expensive renders\");\n }\n\n if (hasTailwind) {\n bodyLines.push(\n \"- Use `className` for layout/styling via Tailwind. Inline `style` only for dynamic/theme values.\",\n );\n }\n\n bodyLines.push(\n \"- Props interfaces defined adjacent to the component\",\n );\n bodyLines.push(\"- Keep components focused -- extract sub-components when complexity grows\");\n\n // Also glob the app screens if they exist\n const appGlob = ctx.directories.includes(\"app\") ? \", app/**/*.tsx\" : \"\";\n\n return {\n filename: \"ui-components.md\",\n description: \"Component conventions and patterns\",\n globs: `${compDir}/**/*.{ts,tsx,js,jsx}${appGlob}`,\n body: bodyLines.join(\"\\n\"),\n };\n}\n\nfunction buildServicesRule(ctx: DetectedContext): CursorRule {\n const svcDir = ctx.directories.find(\n (d) =>\n d.endsWith(\"services\") ||\n d.endsWith(\"api\") ||\n d.includes(\"services/\") ||\n d.includes(\"api/\"),\n ) ?? \"src/services\";\n\n // Check if hooks dir exists (for useChat-like patterns)\n const hooksGlob = ctx.directories.some((d) => d.endsWith(\"hooks\"))\n ? `, ${ctx.directories.find((d) => d.endsWith(\"hooks\"))}/**/*.{ts,js}`\n : \"\";\n\n const bodyLines: string[] = [\n \"# Services & API Layer\",\n \"\",\n \"> Update this rule when service patterns or API conventions change.\",\n \"\",\n \"## Conventions\",\n \"\",\n \"- Services should be pure functions or classes, not React hooks\",\n \"- Error handling: always catch and provide meaningful error messages\",\n \"- Keep service functions focused on a single responsibility\",\n ];\n\n return {\n filename: \"services.md\",\n description: \"Service and API layer patterns\",\n globs: `${svcDir}/**/*.{ts,js}${hooksGlob}`,\n body: bodyLines.join(\"\\n\"),\n };\n}\n\nfunction buildStoresRule(ctx: DetectedContext): CursorRule {\n const storeDir = ctx.directories.find(\n (d) =>\n d.endsWith(\"stores\") ||\n d.endsWith(\"store\") ||\n d.includes(\"stores/\") ||\n d.includes(\"store/\"),\n ) ?? \"src/stores\";\n\n const bodyLines: string[] = [\n \"# State Management\",\n \"\",\n \"> Update this rule when state patterns change.\",\n \"\",\n \"## Conventions\",\n \"\",\n ];\n\n // Detect state management library\n const hasZustand = ctx.frameworks.some((f) => f.name === \"Zustand\");\n const hasRedux = ctx.frameworks.some(\n (f) => f.name === \"Redux\" || f.name === \"Redux Toolkit\",\n );\n const hasPinia = ctx.frameworks.some((f) => f.name === \"Pinia\");\n\n if (hasZustand) {\n bodyLines.push(\n \"- **Zustand** slice architecture: each slice is a `StateCreator` accessing full state via `get()`\",\n );\n bodyLines.push(\"- Immutable updates: always spread state\");\n bodyLines.push(\"- Cross-slice access via `get()` (not separate store imports)\");\n } else if (hasRedux) {\n bodyLines.push(\"- **Redux Toolkit** slices with `createSlice`\");\n bodyLines.push(\"- Async logic in thunks (`createAsyncThunk`)\");\n bodyLines.push(\"- Selectors for reading state, dispatches for writing\");\n } else if (hasPinia) {\n bodyLines.push(\"- **Pinia** stores with composition API\");\n bodyLines.push(\"- Getters for derived state, actions for mutations\");\n } else {\n bodyLines.push(\"- Keep state updates immutable\");\n bodyLines.push(\"- Separate concerns into distinct store modules\");\n }\n\n bodyLines.push(\"- Silent failures for persistence (app should work even if storage fails)\");\n\n return {\n filename: \"stores.md\",\n description: \"State management patterns\",\n globs: `${storeDir}/**/*.{ts,js}`,\n body: bodyLines.join(\"\\n\"),\n };\n}\n\n/**\n * Get the right file extension glob for the project's language.\n */\nfunction getExtGlob(ctx: DetectedContext): string {\n switch (ctx.language) {\n case \"typescript\":\n return \"{ts,tsx}\";\n case \"javascript\":\n return \"{js,jsx}\";\n case \"python\":\n return \"py\";\n case \"go\":\n return \"go\";\n case \"rust\":\n return \"rs\";\n default:\n return \"{ts,tsx,js,jsx}\";\n }\n}\n\n/**\n * Format a CursorRule as the full file content with frontmatter.\n */\nexport function renderCursorRule(rule: CursorRule): string {\n return [\n \"---\",\n `description: ${rule.description}`,\n `globs: ${rule.globs}`,\n \"---\",\n \"\",\n rule.body,\n \"\",\n ].join(\"\\n\");\n}\n","import type { ClaudeSkill, ContextAnalysis, DetectedContext, UserAnswers } from \"../types.js\";\n\n/**\n * Build Claude Code skills based on detected project context.\n * @param scripts - Record of script name -> command from package.json (or equivalent)\n */\nexport function buildClaudeSkills(\n ctx: DetectedContext,\n answers: UserAnswers,\n analysis?: ContextAnalysis,\n scripts?: Record<string, string>,\n): ClaudeSkill[] {\n const skills: ClaudeSkill[] = [];\n\n // Script-based skills from package.json\n if (scripts) {\n skills.push(...buildScriptSkills(ctx, scripts));\n }\n\n // Architecture exploration skill\n const archSkill = buildArchitectureSkill(analysis);\n if (archSkill) skills.push(archSkill);\n\n return skills;\n}\n\n/**\n * Scan package.json scripts for common commands and generate skills.\n */\nfunction buildScriptSkills(ctx: DetectedContext, scripts: Record<string, string>): ClaudeSkill[] {\n const skills: ClaudeSkill[] = [];\n\n const scriptMap: Record<string, { description: string; keywords: string[] }> = {\n test: { description: \"Run the test suite\", keywords: [\"test\", \"test:unit\", \"test:e2e\"] },\n build: { description: \"Build the project\", keywords: [\"build\", \"build:prod\"] },\n lint: { description: \"Run linter\", keywords: [\"lint\", \"lint:fix\"] },\n dev: { description: \"Start development server\", keywords: [\"dev\", \"start:dev\"] },\n typecheck: { description: \"Run type checking\", keywords: [\"typecheck\", \"type-check\", \"check-types\"] },\n };\n\n const runCmd = getRunCommand(ctx);\n\n for (const [skillName, config] of Object.entries(scriptMap)) {\n const matchedScript = config.keywords.find((kw) => kw in scripts);\n if (!matchedScript) continue;\n\n const command = `${runCmd} ${matchedScript}`;\n skills.push({\n name: skillName,\n description: config.description,\n disableModelInvocation: true,\n body: [\n `# ${config.description}`,\n \"\",\n `Run: \\`${command}\\``,\n ].join(\"\\n\"),\n });\n }\n\n return skills;\n}\n\nfunction getRunCommand(ctx: DetectedContext): string {\n switch (ctx.packageManager) {\n case \"pnpm\": return \"pnpm\";\n case \"yarn\": return \"yarn\";\n case \"bun\": return \"bun run\";\n case \"npm\": return \"npm run\";\n case \"cargo\": return \"cargo\";\n case \"go\": return \"go\";\n default: return \"npm run\";\n }\n}\n\n/**\n * Build an architecture exploration skill with hub files, layers, and circular deps.\n */\nfunction buildArchitectureSkill(analysis?: ContextAnalysis): ClaudeSkill | null {\n if (!analysis) return null;\n\n const bodyLines: string[] = [\n \"# Architecture Explorer\",\n \"\",\n \"Use this skill to understand the project architecture before making changes.\",\n \"\",\n ];\n\n if (analysis.hubFiles.length > 0) {\n bodyLines.push(\"## Key Files (by centrality)\");\n bodyLines.push(\"\");\n for (const hub of analysis.hubFiles) {\n bodyLines.push(`- \\`${hub.path}\\` — imported by ${hub.importedBy} file${hub.importedBy === 1 ? \"\" : \"s\"}`);\n }\n bodyLines.push(\"\");\n }\n\n if (analysis.layers.length > 0) {\n bodyLines.push(\"## Architecture Layers\");\n bodyLines.push(\"\");\n bodyLines.push(\"Dependency flow (foundational → consumer):\");\n bodyLines.push(\"\");\n bodyLines.push(analysis.layers.map((l) => `\\`${l.name}\\``).join(\" → \"));\n bodyLines.push(\"\");\n }\n\n if (analysis.circularDeps.length > 0) {\n bodyLines.push(\"## Circular Dependencies\");\n bodyLines.push(\"\");\n for (const dep of analysis.circularDeps) {\n bodyLines.push(`- ${dep.chain.map((f) => `\\`${f}\\``).join(\" -> \")}`);\n }\n bodyLines.push(\"\");\n }\n\n if (analysis.communities.length > 0) {\n bodyLines.push(\"## Module Clusters\");\n bodyLines.push(\"\");\n for (const community of analysis.communities) {\n bodyLines.push(`- **${community.label}** (${community.files.length} files)`);\n }\n bodyLines.push(\"\");\n }\n\n // Only create the skill if there's meaningful content\n if (analysis.hubFiles.length === 0 && analysis.layers.length === 0) {\n return null;\n }\n\n return {\n name: \"architecture\",\n description: \"Explore project architecture and key files\",\n disableModelInvocation: false,\n allowedTools: \"Read, Grep, Glob\",\n body: bodyLines.join(\"\\n\"),\n };\n}\n\n/**\n * Render a ClaudeSkill as YAML frontmatter + markdown body.\n */\nexport function renderClaudeSkill(skill: ClaudeSkill): string {\n const lines: string[] = [\n \"---\",\n `description: ${skill.description}`,\n ];\n\n if (skill.disableModelInvocation) {\n lines.push(\"disable-model-invocation: true\");\n }\n\n if (skill.allowedTools) {\n lines.push(`allowed-tools: ${skill.allowedTools}`);\n }\n\n lines.push(\"---\");\n lines.push(\"\");\n lines.push(skill.body);\n lines.push(\"\");\n\n return lines.join(\"\\n\");\n}\n","import type { CodeSnapshot, ContextAnalysis, DetectedContext, UserAnswers } from \"../types.js\";\nimport { summarizeDetection } from \"../detect.js\";\nimport { getFrameworkHints } from \"./framework-hints.js\";\n\n/**\n * Build an Aider config file (.aider.conf.yml) with project conventions.\n * Aider uses YAML format with a `conventions` key containing a list of strings.\n */\nexport function buildAiderContext(\n ctx: DetectedContext,\n answers: UserAnswers,\n snapshot: CodeSnapshot | null,\n analysis?: ContextAnalysis,\n): string {\n const lines: string[] = [];\n\n lines.push(\"# .aider.conf.yml — Generated by codebrief\");\n lines.push(\"# Keep this file up to date as the project evolves.\");\n lines.push(\"\");\n\n const stackSummary = answers.stackConfirmed\n ? summarizeDetection(ctx)\n : answers.stackCorrections || summarizeDetection(ctx);\n\n // Conventions as a YAML list\n lines.push(\"conventions:\");\n lines.push(` - \"Project: ${escapeYaml(answers.projectPurpose)}\"`);\n lines.push(` - \"Stack: ${escapeYaml(stackSummary)}\"`);\n\n // Frameworks\n if (ctx.frameworks.length > 0) {\n const fws = ctx.frameworks\n .map((f) => `${f.name}${f.version ? ` ${f.version}` : \"\"}`)\n .join(\", \");\n lines.push(` - \"Frameworks: ${escapeYaml(fws)}\"`);\n }\n\n // Package manager + linter\n if (ctx.packageManager !== \"none\") {\n lines.push(` - \"Package manager: ${ctx.packageManager}\"`);\n }\n if (ctx.linter !== \"none\") {\n lines.push(` - \"Linter: ${ctx.linter}\"`);\n }\n\n // Project structure\n if (ctx.directories.length > 0) {\n const dirs = ctx.directories.join(\", \");\n lines.push(` - \"Key directories: ${escapeYaml(dirs)}\"`);\n }\n\n // Key patterns\n if (answers.keyPatterns) {\n const patterns = answers.keyPatterns\n .split(/[.\\n]/)\n .map((s) => s.trim())\n .filter(Boolean);\n for (const p of patterns) {\n lines.push(` - \"${escapeYaml(p)}\"`);\n }\n }\n\n // Gotchas\n if (answers.gotchas) {\n const gotchas = answers.gotchas\n .split(/[.\\n]/)\n .map((s) => s.trim())\n .filter(Boolean);\n for (const g of gotchas) {\n lines.push(` - \"GOTCHA: ${escapeYaml(g)}\"`);\n }\n }\n\n // Framework conventions\n const fwHints = getFrameworkHints(ctx);\n if (fwHints.length > 0) {\n // Filter to just the bullet-point lines (skip headers and blank lines)\n for (const hint of fwHints) {\n const trimmed = hint.trim();\n if (trimmed && trimmed.startsWith(\"- \")) {\n lines.push(` - \"${escapeYaml(trimmed.slice(2))}\"`);\n }\n }\n }\n\n // Monorepo info\n if (ctx.monorepo && ctx.monorepo.packages.length > 0) {\n lines.push(\n ` - \"Monorepo: ${ctx.monorepo.type} with ${ctx.monorepo.packages.length} packages\"`,\n );\n for (const pkg of ctx.monorepo.packages) {\n const fws =\n pkg.frameworks.length > 0\n ? ` (${pkg.frameworks.map((f) => f.name).join(\", \")})`\n : \"\";\n lines.push(` - \"Package: ${escapeYaml(pkg.name)} at ${escapeYaml(pkg.path)}${escapeYaml(fws)}\"`);\n }\n }\n\n // Key files\n if (analysis?.hubFiles && analysis.hubFiles.length > 0) {\n lines.push(` - \"Key files (read these first for architecture): ${escapeYaml(analysis.hubFiles.map((h) => h.path).join(\", \"))}\"`);\n }\n\n // Architecture\n if (analysis?.layers && analysis.layers.length > 1) {\n const flow = analysis.layers.map((l) => l.name).join(\" → \");\n lines.push(` - \"Architecture dependency flow: ${escapeYaml(flow)}\"`);\n }\n\n // Instability warnings\n if (analysis?.instabilities && analysis.instabilities.length > 0) {\n for (const inst of analysis.instabilities) {\n lines.push(` - \"UNSTABLE: ${escapeYaml(inst.path)} — ${(inst.instability * 100).toFixed(0)}% unstable (${inst.fanIn} dependents, ${inst.fanOut} deps)\"`);\n }\n }\n\n // Change coupling\n if (analysis?.gitActivity?.changeCoupling && analysis.gitActivity.changeCoupling.length > 0) {\n for (const pair of analysis.gitActivity.changeCoupling.slice(0, 5)) {\n lines.push(` - \"CO-CHANGE: ${escapeYaml(pair.fileA)} <-> ${escapeYaml(pair.fileB)} (${pair.coChangeCount} co-changes, ${(pair.confidence * 100).toFixed(0)}% confidence)\"`);\n }\n }\n\n // Circular dependencies\n if (analysis?.circularDeps && analysis.circularDeps.length > 0) {\n for (const dep of analysis.circularDeps) {\n lines.push(` - \"CIRCULAR DEP: ${escapeYaml(dep.chain.join(\" -> \"))}\"`);\n }\n }\n\n // Recently active files\n if (analysis?.gitActivity && analysis.gitActivity.hotFiles.length > 0) {\n const hot = analysis.gitActivity.hotFiles\n .slice(0, 5)\n .map((h) => `${h.path} (${h.commits} commits)`)\n .join(\", \");\n lines.push(` - \"Recently active: ${escapeYaml(hot)}\"`);\n }\n\n // Code snapshot\n if (snapshot?.markdown) {\n lines.push(\"\");\n lines.push(\n \"# CODE SNAPSHOT (auto-generated, update when types/stores/services change)\",\n );\n lines.push(\"# Formatted as a multi-line read block for Aider context.\");\n lines.push(\"read:\");\n // We can't inline markdown directly into YAML conventions cleanly.\n // Instead, write a companion markdown file and reference it.\n // For now, include the snapshot as a YAML comment block.\n lines.push(\n \" # To include the code snapshot, create a file and add it here:\",\n );\n lines.push(\" # - .aider.context.md\");\n\n // Also add the snapshot as commented YAML for reference\n lines.push(\"\");\n lines.push(\"# --- Code Snapshot (for reference) ---\");\n for (const line of snapshot.markdown.split(\"\\n\")) {\n lines.push(`# ${line}`);\n }\n lines.push(\"# --- /Code Snapshot ---\");\n }\n\n lines.push(\"\");\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Escape a string for use inside double-quoted YAML values.\n */\nfunction escapeYaml(s: string): string {\n return s.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n}\n","import pc from \"picocolors\";\nimport type { CodeSnapshot, ContextAnalysis, DetectedContext, GeneratedFile } from \"./types.js\";\nimport { estimateTokens, formatBytes } from \"./utils.js\";\n\n/**\n * Print a summary of generated files with token estimates.\n */\nexport function printSummary(\n files: GeneratedFile[],\n ctx: DetectedContext,\n snapshot?: CodeSnapshot | null,\n analysis?: ContextAnalysis,\n): void {\n if (files.length === 0) return;\n\n console.log(\"\");\n console.log(pc.bold(\" Files created:\"));\n console.log(\"\");\n\n // Track totals\n let totalBytes = 0;\n let totalTokens = 0;\n let alwaysOnTokens = 0;\n let scopedRuleTokens: number[] = [];\n\n // Group files: main context vs scoped rules\n const mainFiles = files.filter((f) => !f.path.includes(\".cursor/rules/\"));\n const ruleFiles = files.filter((f) => f.path.includes(\".cursor/rules/\"));\n\n // Pre-compute row data for aligned output\n const fileRows: Array<{\n indent: string;\n name: string;\n size: string;\n tokens: string;\n isUpdated: boolean;\n isHeader: boolean;\n }> = [];\n\n for (const file of mainFiles) {\n const bytes = Buffer.byteLength(file.content, \"utf-8\");\n const tokens = estimateTokens(file.content);\n totalBytes += bytes;\n totalTokens += tokens;\n alwaysOnTokens += tokens;\n\n fileRows.push({\n indent: \" \",\n name: file.path,\n size: formatBytes(bytes),\n tokens: `(~${formatNumber(tokens)} tokens)`,\n isUpdated: !!file.existed,\n isHeader: false,\n });\n }\n\n if (ruleFiles.length > 0) {\n fileRows.push({\n indent: \" \",\n name: \".cursor/rules/\",\n size: \"\",\n tokens: \"\",\n isUpdated: false,\n isHeader: true,\n });\n\n // global.md is always-on, others are scoped\n for (const file of ruleFiles) {\n const bytes = Buffer.byteLength(file.content, \"utf-8\");\n const tokens = estimateTokens(file.content);\n totalBytes += bytes;\n totalTokens += tokens;\n\n const filename = file.path.split(\"/\").pop() ?? file.path;\n const isGlobal = filename === \"global.md\";\n\n if (isGlobal) {\n alwaysOnTokens += tokens;\n } else {\n scopedRuleTokens.push(tokens);\n }\n\n fileRows.push({\n indent: \" \",\n name: filename,\n size: formatBytes(bytes),\n tokens: `(~${formatNumber(tokens)} tokens)`,\n isUpdated: !!file.existed,\n isHeader: false,\n });\n }\n }\n\n // Derive column widths from row data\n const dataFileRows = fileRows.filter((r) => !r.isHeader);\n const maxNameCol = Math.max(...fileRows.map((r) => r.indent.length + r.name.length));\n const maxSizeWidth = Math.max(...dataFileRows.map((r) => r.size.length));\n const maxTokenWidth = Math.max(...dataFileRows.map((r) => r.tokens.length));\n\n // Print aligned rows\n for (const row of fileRows) {\n if (row.isHeader) {\n console.log(`${row.indent}${pc.cyan(row.name)}`);\n } else {\n const status = row.isUpdated ? pc.yellow(\"(updated)\") : pc.green(\"(new)\");\n const paddedName = row.name.padEnd(maxNameCol - row.indent.length);\n console.log(\n `${row.indent}${pc.cyan(paddedName)} ${row.size.padStart(maxSizeWidth)} ${pc.dim(row.tokens.padEnd(maxTokenWidth))} ${status}`,\n );\n }\n }\n\n console.log(\"\");\n console.log(\n pc.dim(\n ` Total: ${formatBytes(totalBytes)}, ~${formatNumber(totalTokens)} tokens`,\n ),\n );\n\n if (snapshot?.budgetExcluded && snapshot.budgetExcluded > 0) {\n console.log(\n pc.dim(\n ` (${snapshot.budgetExcluded} snapshot entries excluded by token budget)`,\n ),\n );\n }\n\n // Analysis summary\n if (analysis) {\n const parts: string[] = [];\n if (analysis.hubFiles.length > 0) parts.push(`${analysis.hubFiles.length} key files`);\n if (analysis.layers.length > 0) parts.push(`${analysis.layers.length} architecture layers`);\n if (analysis.circularDeps.length > 0) parts.push(`${analysis.circularDeps.length} circular deps`);\n if (analysis.communities.length > 0) parts.push(`${analysis.communities.length} module clusters`);\n if (analysis.gitActivity) parts.push(`${analysis.gitActivity.hotFiles.length} recently active files`);\n if (parts.length > 0) {\n console.log(\n pc.dim(` Includes: ${parts.join(\", \")}`),\n );\n }\n }\n\n // -- Token estimate comparison --\n console.log(\"\");\n console.log(pc.bold(\" Estimated context cost per conversation:\"));\n console.log(\"\");\n\n // Before: estimate exploration cost from source file count + size\n const explorationTokens = estimateExplorationCost(ctx);\n\n // After\n const avgScopedTokens =\n scopedRuleTokens.length > 0\n ? Math.round(\n scopedRuleTokens.reduce((a, b) => a + b, 0) /\n scopedRuleTokens.length,\n )\n : 0;\n\n const residualExploration = Math.round(explorationTokens * 0.05);\n const afterTotal = alwaysOnTokens + avgScopedTokens + residualExploration;\n const savings = Math.round(\n ((explorationTokens - afterTotal) / explorationTokens) * 100,\n );\n\n // Build cost rows for dynamic alignment\n const costRows: Array<{ label: string; desc: string; value: string }> = [\n { label: \"Always loaded\", desc: \"main context + global rule\", value: `~${formatNumber(alwaysOnTokens)} tokens` },\n ];\n\n if (avgScopedTokens > 0) {\n costRows.push({ label: \"Per-task (avg)\", desc: \"1 scoped rule\", value: `~${formatNumber(avgScopedTokens)} tokens` });\n }\n\n costRows.push({ label: \"Exploration\", desc: \"mostly eliminated\", value: `~${formatNumber(residualExploration)} tokens` });\n\n const maxCostLabel = Math.max(...costRows.map((r) => r.label.length));\n const maxCostDesc = Math.max(...costRows.map((r) => r.desc.length));\n const maxCostValue = Math.max(...costRows.map((r) => r.value.length));\n const afterContentWidth = maxCostLabel + 3 + maxCostDesc + 2 + maxCostValue;\n\n // \"Before\" section — right-align value with After's value column\n const beforeValue = `~${formatNumber(explorationTokens)} tokens`;\n const beforeLabel = \"Exploration to understand codebase\";\n const beforeGap = afterContentWidth - beforeLabel.length - beforeValue.length;\n\n console.log(pc.dim(\" Before (no context files):\"));\n if (beforeGap >= 2) {\n console.log(\n ` ${beforeLabel}${\" \".repeat(beforeGap)}${pc.red(beforeValue)}`,\n );\n } else {\n console.log(\n ` ${beforeLabel} ${pc.red(beforeValue)}`,\n );\n }\n console.log(\"\");\n\n // \"After\" section\n console.log(pc.dim(\" After:\"));\n for (const row of costRows) {\n console.log(\n ` ${row.label.padEnd(maxCostLabel)} ${row.desc.padEnd(maxCostDesc)} ${pc.green(row.value.padStart(maxCostValue))}`,\n );\n }\n\n const totalText = `Total: ~${formatNumber(afterTotal)} tokens`;\n const totalPad = afterContentWidth > totalText.length\n ? \" \".repeat(afterContentWidth - totalText.length)\n : \"\";\n console.log(\n ` ${totalPad}${pc.bold(totalText)}`,\n );\n\n console.log(\"\");\n\n if (savings > 0) {\n console.log(\n pc.green(\n ` Estimated savings: ~${savings}% fewer tokens before real work begins`,\n ),\n );\n }\n\n // \"What we analyzed\" recap\n if (analysis) {\n console.log(\"\");\n console.log(pc.bold(\" What we analyzed:\"));\n\n const recapRows: Array<{ label: string; result: string }> = [];\n\n if (analysis.hubFiles.length > 0) {\n recapRows.push({ label: \"PageRank hub detection\", result: `found ${analysis.hubFiles.length} key architectural files` });\n }\n\n recapRows.push({\n label: \"Tarjan cycle detection\",\n result: analysis.circularDeps.length === 0\n ? \"no circular dependencies found\"\n : `${analysis.circularDeps.length} circular dep${analysis.circularDeps.length === 1 ? \"\" : \"s\"} found`,\n });\n\n if (analysis.layers.length > 0) {\n const tierNames = analysis.layers.map((l) => l.name).join(\" → \");\n recapRows.push({ label: \"Layer analysis\", result: `${analysis.layers.length} tiers: ${tierNames}` });\n }\n\n if (analysis.gitActivity) {\n const coupledPairs = analysis.gitActivity.changeCoupling.length;\n recapRows.push({\n label: \"Git history (90 days)\",\n result: `${analysis.gitActivity.hotFiles.length} hot files, ${coupledPairs} change-coupled pair${coupledPairs === 1 ? \"\" : \"s\"}`,\n });\n }\n\n const ec = analysis.exportCoverage;\n if (ec && ec.length > 0) {\n const totalExports = ec.reduce((sum, e) => sum + e.totalExports, 0);\n const totalUsed = ec.reduce((sum, e) => sum + e.usedExports, 0);\n const coveragePct = totalExports > 0 ? Math.round((totalUsed / totalExports) * 100) : 100;\n const unused = totalExports - totalUsed;\n recapRows.push({ label: \"Export coverage\", result: `${coveragePct}% (${unused} unused export${unused === 1 ? \"\" : \"s\"})` });\n }\n\n if (analysis.communities.length > 0) {\n recapRows.push({ label: \"Community detection\", result: `${analysis.communities.length} module cluster${analysis.communities.length === 1 ? \"\" : \"s\"}` });\n }\n\n const maxRecapLabel = Math.max(...recapRows.map((r) => r.label.length));\n for (const row of recapRows) {\n console.log(\n pc.dim(` ${row.label.padEnd(maxRecapLabel)} → ${row.result}`),\n );\n }\n }\n\n // Export coverage summary\n const exportCoverage = analysis?.exportCoverage;\n if (exportCoverage && exportCoverage.length > 0) {\n const totalExports = exportCoverage.reduce((sum, e) => sum + e.totalExports, 0);\n const totalUsed = exportCoverage.reduce((sum, e) => sum + e.usedExports, 0);\n const unusedExports = totalExports - totalUsed;\n const coveragePct = totalExports > 0 ? Math.round((totalUsed / totalExports) * 100) : 100;\n const filesWithUnused = exportCoverage.filter((e) => e.usedExports < e.totalExports).length;\n\n if (unusedExports > 0) {\n console.log(\"\");\n console.log(\n pc.dim(\n ` Export coverage: ${coveragePct}% of exports are used (${unusedExports} unused exports in ${filesWithUnused} file${filesWithUnused === 1 ? \"\" : \"s\"})`,\n ),\n );\n }\n }\n\n console.log(\"\");\n}\n\n/**\n * Estimate how many tokens an AI agent would spend exploring a codebase\n * without any context files.\n *\n * Heuristic: agents typically read 30-50% of source files to understand\n * architecture, plus overhead from search/grep operations.\n */\nfunction estimateExplorationCost(ctx: DetectedContext): number {\n if (ctx.totalSourceBytes === 0 || ctx.sourceFileCount === 0) {\n // Fallback for projects where we couldn't count\n return 15000;\n }\n\n // Agents typically read ~40% of source files to understand a project\n const bytesRead = ctx.totalSourceBytes * 0.4;\n // Convert to tokens — source code is typically symbol-heavy (~3.2 chars/token)\n const readTokens = Math.ceil(bytesRead / 3.2);\n\n // Add overhead for search commands, tool calls, etc (~30% overhead)\n const overhead = Math.ceil(readTokens * 0.3);\n\n // Minimum floor\n return Math.max(5000, readTokens + overhead);\n}\n\nfunction formatNumber(n: number): string {\n if (n >= 1000) {\n return `${(n / 1000).toFixed(1).replace(/\\.0$/, \"\")}k`;\n }\n return String(n);\n}\n","import { createHash } from \"node:crypto\";\nimport path from \"node:path\";\nimport fg from \"fast-glob\";\nimport type { Language, ProjectConfig, UserAnswers } from \"./types.js\";\nimport { readJsonFile, writeFileSafe } from \"./utils.js\";\n\nconst CONFIG_FILENAME = \".codebrief.json\";\nconst CONFIG_VERSION = 1;\n\ninterface ConfigFile extends ProjectConfig {\n /** Schema version for future migrations */\n _version: number;\n}\n\n/**\n * Load project config from .codebrief.json.\n * Returns null if the file doesn't exist or is invalid.\n */\nexport async function loadConfig(\n rootDir: string,\n): Promise<ProjectConfig | null> {\n const configPath = path.join(rootDir, CONFIG_FILENAME);\n const raw = await readJsonFile(configPath);\n if (!raw) return null;\n\n const cfg = raw as Partial<ConfigFile>;\n\n // Validate required fields\n if (!cfg.ide || !cfg.projectPurpose) return null;\n\n return {\n ide: cfg.ide,\n projectPurpose: cfg.projectPurpose,\n keyPatterns: cfg.keyPatterns ?? \"\",\n gotchas: cfg.gotchas ?? \"\",\n generateSnapshot: cfg.generateSnapshot ?? false,\n snapshotPaths: cfg.snapshotPaths ?? [],\n stackCorrections: cfg.stackCorrections ?? \"\",\n generatePerPackage: cfg.generatePerPackage ?? false,\n snapshotHash: cfg.snapshotHash,\n snapshotGeneratedAt: cfg.snapshotGeneratedAt,\n language: cfg.language,\n };\n}\n\n/**\n * Save project config to .codebrief.json.\n * Optionally includes snapshot hash and timestamp.\n */\nexport async function saveConfig(\n rootDir: string,\n answers: UserAnswers,\n snapshotHash?: string,\n language?: Language,\n): Promise<void> {\n const configPath = path.join(rootDir, CONFIG_FILENAME);\n const cfg: ConfigFile = {\n _version: CONFIG_VERSION,\n ide: answers.ide,\n projectPurpose: answers.projectPurpose,\n keyPatterns: answers.keyPatterns,\n gotchas: answers.gotchas,\n generateSnapshot: answers.generateSnapshot,\n snapshotPaths: answers.snapshotPaths,\n stackCorrections: answers.stackCorrections,\n generatePerPackage: answers.generatePerPackage,\n ...(snapshotHash\n ? { snapshotHash, snapshotGeneratedAt: Date.now() }\n : {}),\n ...(language ? { language } : {}),\n };\n await writeFileSafe(configPath, JSON.stringify(cfg, null, 2) + \"\\n\");\n}\n\n/**\n * Convert a loaded ProjectConfig into UserAnswers (filling in defaults\n * for fields that only come from the interactive prompts).\n */\nexport function configToAnswers(config: ProjectConfig): UserAnswers {\n return {\n ide: config.ide,\n projectPurpose: config.projectPurpose,\n keyPatterns: config.keyPatterns,\n gotchas: config.gotchas,\n generateSnapshot: config.generateSnapshot,\n snapshotPaths: config.snapshotPaths,\n stackConfirmed: true,\n stackCorrections: config.stackCorrections,\n generatePerPackage: config.generatePerPackage,\n };\n}\n\n/**\n * Compute a hash of all source files (path + mtime) to detect changes.\n * Returns a 16-char hex string.\n */\nexport async function computeSnapshotHash(\n rootDir: string,\n language: Language,\n): Promise<string> {\n const extMap: Record<string, string[]> = {\n typescript: [\"**/*.{ts,tsx}\"],\n javascript: [\"**/*.{js,jsx,mjs}\"],\n python: [\"**/*.py\"],\n go: [\"**/*.go\"],\n rust: [\"**/*.rs\"],\n java: [\"**/*.java\"],\n other: [\"**/*.{ts,tsx,js,jsx,py,go,rs}\"],\n };\n\n const files = await fg(extMap[language] ?? extMap.other, {\n cwd: rootDir,\n ignore: [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n \"**/.next/**\",\n \"**/target/**\",\n \"**/vendor/**\",\n ],\n stats: true,\n absolute: false,\n });\n\n // Sort by path for deterministic hashing\n const entries = files\n .map((f) => `${f.path}:${f.stats?.mtimeMs ?? 0}`)\n .sort();\n\n const hash = createHash(\"sha256\")\n .update(entries.join(\"\\n\"))\n .digest(\"hex\")\n .slice(0, 16);\n\n return hash;\n}\n","import path from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\nimport { detectContext } from \"./detect.js\";\nimport { generateSnapshot } from \"./snapshot.js\";\nimport { buildImportGraph } from \"./graph.js\";\nimport { loadConfig } from \"./config.js\";\nimport { fileExists, readFileOr, writeFileSafe } from \"./utils.js\";\nimport type { ProgressCallback } from \"./types.js\";\n\n/** Known context files in priority order */\nconst CONTEXT_FILES = [\n \"CLAUDE.md\",\n \"AGENTS.md\",\n \".github/copilot-instructions.md\",\n \".windsurfrules\",\n \".clinerules\",\n \".continuerules\",\n \"CONTEXT.md\",\n];\n\n/** Markdown snapshot markers */\nconst MD_START = /<!-- CODE SNAPSHOT[^>]*-->/;\nconst MD_END = /<!-- \\/CODE SNAPSHOT -->/;\n\n/** Aider YAML comment markers */\nconst AIDER_START = /^# --- Code Snapshot/m;\nconst AIDER_END = /^# --- \\/Code Snapshot ---$/m;\n\n/**\n * Find the first existing context file in the project root.\n * Also checks for .aider.conf.yml.\n */\nasync function findContextFile(\n rootDir: string,\n): Promise<{ path: string; isAider: boolean } | null> {\n // Check aider first since it has a unique format\n const aiderPath = path.join(rootDir, \".aider.conf.yml\");\n if (await fileExists(aiderPath)) {\n const content = await readFileOr(aiderPath);\n if (content && AIDER_START.test(content)) {\n return { path: \".aider.conf.yml\", isAider: true };\n }\n }\n\n // Check markdown context files\n for (const file of CONTEXT_FILES) {\n const absPath = path.join(rootDir, file);\n if (await fileExists(absPath)) {\n return { path: file, isAider: false };\n }\n }\n\n return null;\n}\n\n/**\n * Refresh the code snapshot section in an existing context file.\n * Auto-detects which file to update.\n */\nexport async function refreshSnapshot(rootDir: string): Promise<void> {\n const spinner = p.spinner();\n\n // 1. Find context file\n const found = await findContextFile(rootDir);\n if (!found) {\n p.log.error(\n \"No context file found. Run \" +\n pc.cyan(\"codebrief\") +\n \" first to generate one.\",\n );\n process.exit(1);\n }\n\n const absPath = path.join(rootDir, found.path);\n const content = await readFileOr(absPath);\n if (!content) {\n p.log.error(`Could not read ${found.path}`);\n process.exit(1);\n }\n\n // 2. Verify snapshot markers exist\n if (found.isAider) {\n if (!AIDER_START.test(content) || !AIDER_END.test(content)) {\n p.log.error(\n `No code snapshot markers found in ${found.path}. Re-generate the file with code snapshot enabled.`,\n );\n process.exit(1);\n }\n } else {\n if (!MD_START.test(content) || !MD_END.test(content)) {\n p.log.error(\n `No code snapshot markers found in ${found.path}. Re-generate the file with code snapshot enabled.`,\n );\n process.exit(1);\n }\n }\n\n p.log.info(`Refreshing snapshot in ${pc.cyan(found.path)}`);\n\n // 3. Detect context and generate new snapshot\n spinner.start(\"Scanning source files...\");\n const progress: ProgressCallback = (msg) => spinner.message(msg);\n const detected = await detectContext(rootDir, progress);\n\n // Build import graph for better snapshot quality\n const graph = await buildImportGraph(rootDir, detected.language, progress);\n\n // Load snapshot paths from config if available\n const config = await loadConfig(rootDir);\n const snapshotPaths = config?.snapshotPaths ?? [];\n\n const snapshot = await generateSnapshot(detected, snapshotPaths, graph, undefined, progress);\n spinner.stop(\n snapshot.entries.length > 0\n ? `Found ${snapshot.entries.length} type${snapshot.entries.length === 1 ? \"\" : \"s\"}/signature${snapshot.entries.length === 1 ? \"\" : \"s\"}.`\n : \"No extractable types found.\",\n );\n\n if (snapshot.entries.length === 0) {\n p.log.warn(\"No types found — snapshot section will be empty.\");\n }\n\n // 4. Replace the snapshot section\n let updated: string;\n\n if (found.isAider) {\n // Replace YAML comment block\n const startMatch = content.match(AIDER_START);\n const endMatch = content.match(AIDER_END);\n if (!startMatch || !endMatch) {\n p.log.error(\"Failed to parse snapshot markers.\");\n process.exit(1);\n }\n\n const startIdx = content.indexOf(startMatch[0]);\n const endIdx = content.indexOf(endMatch[0]) + endMatch[0].length;\n\n let newBlock = \"# --- Code Snapshot (for reference) ---\";\n if (snapshot.markdown) {\n for (const line of snapshot.markdown.split(\"\\n\")) {\n newBlock += `\\n# ${line}`;\n }\n }\n newBlock += \"\\n# --- /Code Snapshot ---\";\n\n updated = content.slice(0, startIdx) + newBlock + content.slice(endIdx);\n } else {\n // Replace markdown block\n const startMatch = content.match(MD_START);\n const endMatch = content.match(MD_END);\n if (!startMatch || !endMatch) {\n p.log.error(\"Failed to parse snapshot markers.\");\n process.exit(1);\n }\n\n const startIdx = content.indexOf(startMatch[0]);\n const endIdx = content.indexOf(endMatch[0]) + endMatch[0].length;\n\n let newBlock =\n \"<!-- CODE SNAPSHOT (auto-generated, update when types/stores/services change) -->\";\n if (snapshot.markdown) {\n newBlock += \"\\n\\n\" + snapshot.markdown + \"\\n\";\n }\n newBlock += \"\\n<!-- /CODE SNAPSHOT -->\";\n\n updated = content.slice(0, startIdx) + newBlock + content.slice(endIdx);\n }\n\n // 5. Write back\n await writeFileSafe(absPath, updated);\n p.log.success(`Updated snapshot in ${pc.cyan(found.path)}`);\n}\n","import { execSync } from \"node:child_process\";\nimport type { ChangeCoupling, GitAnalysis, ProgressCallback } from \"./types.js\";\n\n/**\n * Analyze git activity in the repository to identify recently active files.\n * Returns null if not a git repo or git is unavailable.\n */\nexport function analyzeGitActivity(\n rootDir: string,\n onProgress?: ProgressCallback,\n): GitAnalysis | null {\n try {\n onProgress?.(\"Analyzing git history (last 90 days)...\");\n\n // Get file change counts for the last 90 days\n const logOutput = execSync(\n 'git log --since=\"90 days ago\" --name-only --pretty=format:\"\"',\n { cwd: rootDir, encoding: \"utf-8\", timeout: 10000 },\n );\n\n const commitCounts = new Map<string, number>();\n for (const line of logOutput.split(\"\\n\")) {\n const file = line.trim();\n if (file && !file.startsWith(\"commit \")) {\n commitCounts.set(file, (commitCounts.get(file) ?? 0) + 1);\n }\n }\n\n if (commitCounts.size === 0) {\n return null;\n }\n\n onProgress?.(`Found activity in ${commitCounts.size} files`);\n\n // Get last changed date for top files\n const sorted = [...commitCounts.entries()].sort((a, b) => b[1] - a[1]);\n const hotFiles: GitAnalysis[\"hotFiles\"] = [];\n\n for (const [filePath, commits] of sorted.slice(0, 15)) {\n let lastChanged = \"\";\n try {\n lastChanged = execSync(\n `git log -1 --format=\"%ar\" -- \"${filePath}\"`,\n { cwd: rootDir, encoding: \"utf-8\", timeout: 5000 },\n ).trim();\n } catch {\n // Skip if can't get date\n }\n hotFiles.push({ path: filePath, commits, lastChanged });\n }\n\n // Analyze change coupling\n onProgress?.(\"Analyzing change coupling...\");\n const changeCoupling = analyzeChangeCoupling(rootDir);\n\n return { commitCounts, hotFiles, changeCoupling };\n } catch {\n // Not a git repo, git not available, or command failed\n return null;\n }\n}\n\n/**\n * Analyze change coupling — files that frequently change together in commits.\n * Uses co-occurrence analysis over the last 90 days of git history.\n */\nexport function analyzeChangeCoupling(rootDir: string): ChangeCoupling[] {\n try {\n // Get commit hashes from last 90 days\n const hashOutput = execSync(\n 'git log --format=\"%H\" --since=\"90 days ago\"',\n { cwd: rootDir, encoding: \"utf-8\", timeout: 10000 },\n ).trim();\n\n if (!hashOutput) return [];\n\n const hashes = hashOutput.split(\"\\n\").filter(Boolean);\n if (hashes.length === 0) return [];\n\n // Get files per commit (batch for efficiency)\n const filesPerCommit: string[][] = [];\n const commitCountPerFile = new Map<string, number>();\n\n for (const hash of hashes) {\n try {\n const filesOutput = execSync(\n `git show --name-only --format=\"\" ${hash}`,\n { cwd: rootDir, encoding: \"utf-8\", timeout: 5000 },\n ).trim();\n\n const files = filesOutput\n .split(\"\\n\")\n .map((f) => f.trim())\n .filter(Boolean);\n\n if (files.length >= 2 && files.length <= 20) {\n // Skip huge commits (merges) and single-file commits\n filesPerCommit.push(files);\n for (const file of files) {\n commitCountPerFile.set(file, (commitCountPerFile.get(file) ?? 0) + 1);\n }\n }\n } catch {\n // Skip individual commit errors\n }\n }\n\n // Build co-occurrence matrix\n const coChanges = new Map<string, number>();\n for (const files of filesPerCommit) {\n for (let i = 0; i < files.length; i++) {\n for (let j = i + 1; j < files.length; j++) {\n const key = [files[i], files[j]].sort().join(\"||\");\n coChanges.set(key, (coChanges.get(key) ?? 0) + 1);\n }\n }\n }\n\n // Compute coupling metrics\n const results: ChangeCoupling[] = [];\n const totalCommits = filesPerCommit.length;\n\n for (const [key, coChangeCount] of coChanges) {\n if (coChangeCount < 3) continue; // Minimum threshold\n\n const [fileA, fileB] = key.split(\"||\");\n const commitsA = commitCountPerFile.get(fileA) ?? 0;\n const commitsB = commitCountPerFile.get(fileB) ?? 0;\n const confidence = coChangeCount / Math.max(commitsA, commitsB);\n const support = coChangeCount / totalCommits;\n\n if (confidence >= 0.5) {\n results.push({ fileA, fileB, coChangeCount, support, confidence });\n }\n }\n\n // Sort by confidence descending, return top 10\n results.sort((a, b) => b.confidence - a.confidence);\n return results.slice(0, 10);\n } catch {\n return [];\n }\n}\n"],"mappings":"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","names":["text","path","p","pc","path","readFileOr","confirm","generateSnapshot","path","fg","path","fg","files","result","p","fg","path","path","p","p","p","path","path","fg","path","p","pc","path","spinner","pc","path","pc","spinner"]}
1
+ {"version":3,"sources":["../src/utils.ts","../src/index.ts","../src/detect.ts","../src/prompts.ts","../src/snapshot.ts","../src/graph.ts","../src/generate.ts","../src/templates/framework-hints.ts","../src/templates/main-context.ts","../src/templates/cursor-rules.ts","../src/templates/claude-skills.ts","../src/templates/aider-context.ts","../src/summary.ts","../src/config.ts","../src/refresh.ts","../src/git-analysis.ts"],"sourcesContent":["import fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\n/**\n * Check if a file exists.\n */\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Read a file's contents, returning null if it doesn't exist.\n */\nexport async function readFileOr(filePath: string): Promise<string | null> {\n try {\n return await fs.readFile(filePath, \"utf-8\");\n } catch {\n return null;\n }\n}\n\n/**\n * Read and parse a JSON file, returning null on failure.\n */\nexport async function readJsonFile(filePath: string): Promise<Record<string, unknown> | null> {\n const content = await readFileOr(filePath);\n if (!content) return null;\n try {\n return JSON.parse(content);\n } catch {\n return null;\n }\n}\n\n/**\n * Estimate tokens from a string using a code-density-aware heuristic.\n * Code averages ~3.2-3.5 chars/token (more symbols than prose).\n * If the symbol ratio exceeds 8%, we assume code-heavy text.\n */\nexport function estimateTokens(text: string): number {\n if (text.length === 0) return 0;\n const symbolCount = text.replace(/[\\w\\s]/g, \"\").length;\n const symbolRatio = symbolCount / text.length;\n const charsPerToken = symbolRatio > 0.08 ? 3.2 : 3.5;\n return Math.ceil(text.length / charsPerToken);\n}\n\n/**\n * Format bytes as human-readable (e.g. \"4.2 KB\").\n */\nexport function formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n return `${(bytes / 1024).toFixed(1)} KB`;\n}\n\n/**\n * Ensure a directory exists, creating it recursively if needed.\n */\nexport async function ensureDir(dirPath: string): Promise<void> {\n await fs.mkdir(dirPath, { recursive: true });\n}\n\n/**\n * Write a file, creating parent directories if needed.\n */\nexport async function writeFileSafe(filePath: string, content: string): Promise<void> {\n await ensureDir(path.dirname(filePath));\n await fs.writeFile(filePath, content, \"utf-8\");\n}\n\n/**\n * Get all entries of a directory (names only), returning empty array if dir doesn't exist.\n */\nexport async function readDirSafe(dirPath: string): Promise<string[]> {\n try {\n return await fs.readdir(dirPath);\n } catch {\n return [];\n }\n}\n","import path from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\nimport { fileExists } from \"./utils.js\";\nimport { detectContext, enrichFrameworksWithUsage } from \"./detect.js\";\nimport { runPrompts } from \"./prompts.js\";\nimport { generateSnapshot } from \"./snapshot.js\";\nimport { generateFiles } from \"./generate.js\";\nimport { printSummary } from \"./summary.js\";\nimport {\n loadConfig,\n saveConfig,\n configToAnswers,\n computeSnapshotHash,\n} from \"./config.js\";\nimport { refreshSnapshot } from \"./refresh.js\";\nimport {\n buildImportGraph,\n getHubFiles,\n findCircularDeps,\n detectArchitecturalLayers,\n computeInstability,\n detectCommunities,\n computeExportCoverage,\n} from \"./graph.js\";\nimport { analyzeGitActivity } from \"./git-analysis.js\";\nimport { formatBytes } from \"./utils.js\";\nimport type { ContextAnalysis, ProgressCallback } from \"./types.js\";\n\nasync function main() {\n const startTime = performance.now();\n const args = process.argv.slice(2);\n const force = args.includes(\"--force\");\n const dryRun = args.includes(\"--dry-run\");\n const refresh = args.includes(\"--refresh-snapshot\");\n const reconfigure = args.includes(\"--reconfigure\");\n const check = args.includes(\"--check\");\n const verbose = args.includes(\"--verbose\") || args.includes(\"-v\");\n const generateSkills = args.includes(\"--generate-skills\");\n const maxTokensArg = args.find((a) => a.startsWith(\"--max-tokens=\"));\n const maxTokens = maxTokensArg ? parseInt(maxTokensArg.split(\"=\")[1], 10) : undefined;\n const targetDir = args.find((a) => !a.startsWith(\"-\") && a !== \"-v\") ?? process.cwd();\n const rootDir = path.resolve(targetDir);\n\n // Early validation: ensure this looks like a project directory\n const PROJECT_MARKERS = [\"package.json\", \"go.mod\", \"Cargo.toml\", \"pyproject.toml\", \"requirements.txt\"];\n const hasProjectMarker = (await Promise.all(\n PROJECT_MARKERS.map(f => fileExists(path.join(rootDir, f)))\n )).some(Boolean);\n\n if (!hasProjectMarker) {\n console.log(\"\");\n p.intro(pc.bold(\" codebrief \"));\n p.log.error(`No project found at ${pc.cyan(rootDir)}`);\n p.log.info(`Run ${pc.bold(\"npx codebrief\")} from a project directory, or pass a path:\\n ${pc.dim(\"npx codebrief ./my-project\")}`);\n p.outro(\"\");\n process.exit(1);\n }\n\n // Verbose logger: persists messages on screen (not swallowed by spinner)\n const verboseLog: ProgressCallback = (msg) => {\n if (verbose) p.log.info(pc.dim(msg));\n };\n\n // --check: fast path for shell integration (silent, exit code only)\n if (check) {\n const config = await loadConfig(rootDir);\n if (!config?.snapshotHash) {\n process.exit(0); // No config or no hash — nothing to check\n }\n const lang = config.language ?? \"other\";\n const currentHash = await computeSnapshotHash(rootDir, lang);\n if (currentHash !== config.snapshotHash) {\n const daysSince = config.snapshotGeneratedAt\n ? Math.floor((Date.now() - config.snapshotGeneratedAt) / (1000 * 60 * 60 * 24))\n : 0;\n const staleMsg = daysSince > 0 ? ` (last generated ${daysSince}d ago)` : \"\";\n console.log(`codebrief: snapshot is stale${staleMsg}. Run npx codebrief --refresh-snapshot`);\n process.exit(1);\n }\n process.exit(0);\n }\n\n console.log(\"\");\n p.intro(pc.bold(\" codebrief \"));\n\n // --refresh-snapshot: fast path — update snapshot in existing context file\n if (refresh) {\n await refreshSnapshot(rootDir);\n p.outro(pc.green(\"Snapshot refreshed!\"));\n return;\n }\n\n if (dryRun) {\n p.log.warn(pc.yellow(\"DRY RUN — no files will be written\"));\n }\n\n p.log.info(`Analyzing ${pc.cyan(rootDir)}`);\n\n // Step 1: Auto-detect\n const spinner = p.spinner();\n const spinnerProgress: ProgressCallback = (msg) => spinner.message(msg);\n\n spinner.start(\"Detecting tech stack...\");\n const detected = await detectContext(rootDir, spinnerProgress);\n spinner.stop(\"Detection complete.\");\n\n // Step 1.5: Build import graph\n spinner.start(`Building import graph (${detected.sourceFileCount} files)...`);\n const graph = await buildImportGraph(rootDir, detected.language, verbose ? verboseLog : spinnerProgress);\n const topHub = getHubFiles(graph, 1)[0];\n spinner.stop(\n `Import graph: ${graph.edges.length} edges, ${graph.externalImportCounts.size} packages.` +\n (topHub ? ` Top hub: ${topHub.path}` : \"\"),\n );\n\n // Step 1.6: Enrich framework detection with actual import usage\n detected.frameworks = enrichFrameworksWithUsage(\n detected.frameworks,\n graph.externalImportCounts,\n );\n\n // Discovery log (enhanced stack box)\n {\n const lines: string[] = [];\n const lang = detected.hasTypeScript ? \"TypeScript\" : detected.language !== \"other\" ? detected.language.charAt(0).toUpperCase() + detected.language.slice(1) : \"\";\n if (lang) lines.push(` Language: ${lang}`);\n if (detected.frameworks.length > 0) {\n lines.push(` Frameworks: ${detected.frameworks.map((f) => f.name).join(\", \")}`);\n }\n if (detected.linter !== \"none\") {\n lines.push(` Linter: ${detected.linter.charAt(0).toUpperCase() + detected.linter.slice(1)}`);\n }\n if (detected.packageManager !== \"none\") {\n lines.push(` Pkg mgr: ${detected.packageManager}`);\n }\n if (detected.testFramework) {\n lines.push(` Testing: ${detected.testFramework}`);\n }\n if (detected.ciProvider) {\n lines.push(` CI: ${detected.ciProvider}`);\n }\n if (detected.monorepo) {\n lines.push(` Monorepo: ${detected.monorepo.type} (${detected.monorepo.packages.length} package${detected.monorepo.packages.length === 1 ? \"\" : \"s\"})`);\n }\n if (detected.sourceFileCount > 0) {\n lines.push(` Files: ${detected.sourceFileCount} (${formatBytes(detected.totalSourceBytes)})`);\n }\n if (lines.length > 0) {\n p.note(lines.join(\"\\n\"), \"Detected Stack\");\n }\n }\n\n // Step 1.7: Structural analysis (progressive reveal — one spinner per algorithm)\n const fileCount = graph.centrality.size;\n\n spinner.start(`Running PageRank on ${fileCount} files...`);\n const hubFiles = getHubFiles(graph);\n const topHubName = hubFiles[0]?.path ?? \"\";\n spinner.stop(\n hubFiles.length > 0\n ? `${pc.green(\"PageRank\")} found ${pc.bold(String(hubFiles.length))} hub files` +\n (topHubName ? pc.dim(` (top: ${topHubName})`) : \"\")\n : `${pc.green(\"PageRank\")} ${pc.dim(\"no hub files detected\")}`,\n );\n if (verbose && hubFiles.length > 0) {\n for (const h of hubFiles.slice(0, 5)) {\n p.log.info(pc.dim(` ${h.path} (centrality: ${h.centrality.toFixed(3)}, imported by ${h.importedBy})`));\n }\n }\n\n spinner.start(\"Finding circular dependencies...\");\n const circularDeps = findCircularDeps(graph);\n spinner.stop(\n circularDeps.length === 0\n ? `${pc.green(\"Tarjan SCC\")} no cycles found ${pc.green(\"✓\")}`\n : `${pc.yellow(\"Tarjan SCC\")} ${pc.bold(String(circularDeps.length))} cycle${circularDeps.length === 1 ? \"\" : \"s\"} found`,\n );\n if (verbose && circularDeps.length > 0) {\n for (const c of circularDeps.slice(0, 3)) {\n p.log.info(pc.dim(` ${c.chain.join(\" → \")}`));\n }\n }\n\n spinner.start(\"Detecting architecture layers...\");\n const { layers, layerEdges } = detectArchitecturalLayers(graph);\n spinner.stop(\n layers.length > 0\n ? `${pc.green(\"Layers\")} ${layers.map((l) => l.name).join(\" → \")}`\n : `${pc.green(\"Layers\")} ${pc.dim(\"no clear layers detected\")}`,\n );\n if (verbose && layers.length > 0) {\n for (const l of layers) {\n p.log.info(pc.dim(` ${l.name}: ${l.files.length} files, depends on: ${l.dependsOn.join(\", \") || \"none\"}`));\n }\n }\n\n spinner.start(\"Computing instability metrics...\");\n const instabilities = computeInstability(graph);\n const highInstability = instabilities.filter((f) => f.instability > 0.8);\n spinner.stop(\n highInstability.length > 0\n ? `${pc.yellow(\"Instability\")} ${pc.bold(String(highInstability.length))} high-risk file${highInstability.length === 1 ? \"\" : \"s\"}`\n : `${pc.green(\"Instability\")} ${pc.dim(\"all files within healthy range\")} ${pc.green(\"✓\")}`,\n );\n if (verbose && highInstability.length > 0) {\n for (const f of highInstability.slice(0, 5)) {\n p.log.info(pc.dim(` ${f.path} (I=${f.instability.toFixed(2)}, fan-in=${f.fanIn}, fan-out=${f.fanOut})`));\n }\n }\n\n spinner.start(\"Detecting module communities...\");\n const communities = detectCommunities(graph);\n spinner.stop(\n communities.length > 0\n ? `${pc.green(\"Communities\")} ${pc.bold(String(communities.length))} module cluster${communities.length === 1 ? \"\" : \"s\"}`\n : `${pc.green(\"Communities\")} ${pc.dim(\"single cohesive module\")}`,\n );\n if (verbose && communities.length > 0) {\n for (const c of communities.slice(0, 5)) {\n p.log.info(pc.dim(` ${c.label} (${c.files.length} files)`));\n }\n }\n\n spinner.start(\"Computing export coverage...\");\n const exportCoverage = computeExportCoverage(graph);\n {\n const totalExp = exportCoverage.reduce((s, e) => s + e.totalExports, 0);\n const totalUsed = exportCoverage.reduce((s, e) => s + e.usedExports, 0);\n const unusedCount = totalExp - totalUsed;\n const filesWithUnused = exportCoverage.filter((e) => e.usedExports < e.totalExports).length;\n spinner.stop(\n unusedCount > 0\n ? `${pc.yellow(\"Exports\")} ${pc.bold(String(unusedCount))} unused export${unusedCount === 1 ? \"\" : \"s\"} in ${filesWithUnused} file${filesWithUnused === 1 ? \"\" : \"s\"}`\n : `${pc.green(\"Exports\")} ${pc.dim(\"all exports used\")} ${pc.green(\"✓\")}`,\n );\n if (verbose && unusedCount > 0) {\n for (const e of exportCoverage.filter((e) => e.usedExports < e.totalExports).slice(0, 5)) {\n p.log.info(pc.dim(` ${e.file}: ${e.totalExports - e.usedExports} unused of ${e.totalExports}`));\n }\n }\n }\n\n spinner.start(\"Analyzing git history...\");\n const gitActivity = detected.isGitRepo ? analyzeGitActivity(rootDir, verbose ? verboseLog : spinnerProgress) : null;\n if (gitActivity) {\n const coupledPairs = gitActivity.changeCoupling.length;\n spinner.stop(\n `${pc.green(\"Git (90d)\")} ${pc.bold(String(gitActivity.hotFiles.length))} active file${gitActivity.hotFiles.length === 1 ? \"\" : \"s\"}, ${pc.bold(String(coupledPairs))} coupled pair${coupledPairs === 1 ? \"\" : \"s\"}`,\n );\n if (verbose) {\n for (const h of gitActivity.hotFiles.slice(0, 5)) {\n p.log.info(pc.dim(` ${h.path} (${h.commits} commits, last: ${h.lastChanged})`));\n }\n }\n } else {\n spinner.stop(`${pc.green(\"Git\")} ${pc.dim(\"not a git repo — skipped\")}`);\n }\n\n const analysis: ContextAnalysis = { hubFiles, circularDeps, layers, layerEdges, gitActivity, instabilities, communities, exportCoverage };\n\n // Analysis report box\n {\n const reportLines: string[] = [];\n reportLines.push(` Files analyzed: ${fileCount}`);\n reportLines.push(` Import edges: ${graph.edges.length}`);\n reportLines.push(` External pkgs: ${graph.externalImportCounts.size}`);\n if (hubFiles.length > 0) {\n reportLines.push(` Hub files: ${hubFiles.length}` + (hubFiles[0] ? ` (most connected: ${hubFiles[0].path})` : \"\"));\n }\n if (layers.length > 0) {\n reportLines.push(` Architecture: ${layers.map((l) => l.name).join(\" → \")}`);\n }\n reportLines.push(` Circular deps: ${circularDeps.length === 0 ? \"none\" : `${circularDeps.length} chain${circularDeps.length === 1 ? \"\" : \"s\"}`}`);\n if (gitActivity) {\n reportLines.push(` Hot files (90d): ${gitActivity.hotFiles.length}`);\n }\n p.note(reportLines.join(\"\\n\"), \"Analysis Report\");\n\n // Show cycle chains inline below the box (max 2)\n if (circularDeps.length > 0) {\n for (const c of circularDeps.slice(0, 2)) {\n const shortChain = c.chain.map((f) => f.split(\"/\").pop() ?? f);\n p.log.warn(pc.yellow(`Cycle: ${shortChain.join(\" → \")}`));\n }\n }\n }\n\n // Step 1.8: Check for saved config + staleness\n const savedConfig = await loadConfig(rootDir);\n\n if (savedConfig?.snapshotHash) {\n const currentHash = await computeSnapshotHash(rootDir, detected.language);\n if (currentHash !== savedConfig.snapshotHash && savedConfig.snapshotGeneratedAt) {\n const daysSince = Math.floor(\n (Date.now() - savedConfig.snapshotGeneratedAt) / (1000 * 60 * 60 * 24),\n );\n p.log.warn(\n pc.yellow(\n `Code snapshot may be stale (source files changed${daysSince > 0 ? `, last generated ${daysSince}d ago` : \"\"}). ` +\n `Run with ${pc.bold(\"--refresh-snapshot\")} to update.`,\n ),\n );\n }\n }\n\n let answers;\n\n if (savedConfig && !reconfigure) {\n // Use saved config — skip prompts\n p.log.info(\n `Using saved config from ${pc.cyan(\".codebrief.json\")} ` +\n pc.dim(\"(run with --reconfigure to change)\"),\n );\n answers = configToAnswers(savedConfig);\n\n // Re-check monorepo (structure may have changed)\n if (\n detected.monorepo &&\n detected.monorepo.packages.length > 0 &&\n !savedConfig.generatePerPackage\n ) {\n // Monorepo exists but wasn't configured — keep saved value\n }\n } else {\n // Step 2: Interactive prompts (with defaults from saved config if --reconfigure)\n answers = await runPrompts(detected, reconfigure ? savedConfig : null);\n\n // Save config for future runs\n if (!dryRun) {\n const hash = await computeSnapshotHash(rootDir, detected.language);\n await saveConfig(rootDir, answers, hash, detected.language);\n p.log.info(\n pc.dim(\"Saved config to .codebrief.json for future runs.\"),\n );\n }\n }\n\n // Step 3: Code snapshot (if requested)\n let snapshot = null;\n if (answers.generateSnapshot) {\n spinner.start(\"Scanning source files for code snapshot...\");\n snapshot = await generateSnapshot(detected, answers.snapshotPaths, graph, maxTokens, verbose ? verboseLog : spinnerProgress, gitActivity);\n const count = snapshot.entries.length;\n const budgetNote = snapshot.budgetExcluded\n ? ` (${snapshot.budgetExcluded} excluded by token budget)`\n : \"\";\n spinner.stop(\n count > 0\n ? `Found ${count} type${count === 1 ? \"\" : \"s\"}/signature${count === 1 ? \"\" : \"s\"}.${budgetNote}`\n : \"No extractable types found (snapshot will be skipped).\",\n );\n\n if (count === 0) {\n snapshot = null;\n }\n }\n\n // Step 4: Generate files\n spinner.start(\n dryRun ? \"Preparing context files...\" : \"Generating context files...\",\n );\n const shouldGenerateSkills = generateSkills || answers.ide === \"claude\";\n const files = await generateFiles(detected, answers, snapshot, force, dryRun, analysis, shouldGenerateSkills, verbose ? verboseLog : undefined);\n spinner.stop(\n dryRun\n ? `Would generate ${files.length} file${files.length === 1 ? \"\" : \"s\"}.`\n : `Generated ${files.length} file${files.length === 1 ? \"\" : \"s\"}.`,\n );\n\n if (files.length === 0) {\n p.outro(\"Nothing to write. Done!\");\n return;\n }\n\n // Step 5: Summary + token estimate\n printSummary(files, detected, snapshot, analysis);\n\n // Elapsed time\n const elapsed = ((performance.now() - startTime) / 1000).toFixed(1);\n\n if (dryRun) {\n p.outro(\n pc.yellow(\"DRY RUN complete — \") +\n pc.dim(`no files were written. Remove --dry-run to generate. (${elapsed}s)`),\n );\n return;\n }\n\n // Step 6: Done!\n p.outro(\n pc.green(`Done in ${elapsed}s! `) +\n pc.dim(\n \"Your context files are ready. They are living documents — keep them up to date as your project evolves.\",\n ),\n );\n}\n\nmain().catch((err) => {\n console.error(pc.red(\"Fatal error:\"), err);\n process.exit(1);\n});\n","import path from \"node:path\";\nimport fg from \"fast-glob\";\nimport type {\n DetectedContext,\n DetectedFramework,\n Language,\n Linter,\n MonorepoInfo,\n MonorepoPackage,\n PackageManager,\n ProgressCallback,\n} from \"./types.js\";\nimport { fileExists, readFileOr, readJsonFile, readDirSafe } from \"./utils.js\";\n\n/** Well-known directories to look for */\nconst KNOWN_DIRS = [\n \"src\",\n \"app\",\n \"pages\",\n \"components\",\n \"services\",\n \"stores\",\n \"store\",\n \"lib\",\n \"utils\",\n \"hooks\",\n \"api\",\n \"tests\",\n \"__tests__\",\n \"test\",\n \"public\",\n \"assets\",\n \"styles\",\n \"config\",\n \"scripts\",\n \"docs\",\n \"types\",\n];\n\n/** Framework detection rules: dependency name -> framework info */\nexport const FRAMEWORK_MAP: Record<string, string> = {\n // JS/TS\n expo: \"Expo\",\n \"react-native\": \"React Native\",\n next: \"Next.js\",\n react: \"React\",\n vue: \"Vue\",\n nuxt: \"Nuxt\",\n svelte: \"Svelte\",\n \"@sveltejs/kit\": \"SvelteKit\",\n angular: \"Angular\",\n \"@angular/core\": \"Angular\",\n express: \"Express\",\n fastify: \"Fastify\",\n hono: \"Hono\",\n \"nestjs/core\": \"NestJS\",\n \"@nestjs/core\": \"NestJS\",\n electron: \"Electron\",\n tauri: \"Tauri\",\n // State management\n zustand: \"Zustand\",\n redux: \"Redux\",\n \"@reduxjs/toolkit\": \"Redux Toolkit\",\n pinia: \"Pinia\",\n mobx: \"MobX\",\n jotai: \"Jotai\",\n recoil: \"Recoil\",\n // Testing\n jest: \"Jest\",\n vitest: \"Vitest\",\n playwright: \"Playwright\",\n cypress: \"Cypress\",\n // Styling\n tailwindcss: \"Tailwind CSS\",\n nativewind: \"NativeWind\",\n \"styled-components\": \"styled-components\",\n \"@emotion/react\": \"Emotion\",\n // ORM/DB\n prisma: \"Prisma\",\n \"@prisma/client\": \"Prisma\",\n drizzle: \"Drizzle\",\n \"drizzle-orm\": \"Drizzle\",\n typeorm: \"TypeORM\",\n mongoose: \"Mongoose\",\n};\n\n/** Python framework detection */\nconst PYTHON_FRAMEWORK_MAP: Record<string, string> = {\n django: \"Django\",\n flask: \"Flask\",\n fastapi: \"FastAPI\",\n starlette: \"Starlette\",\n sqlalchemy: \"SQLAlchemy\",\n pydantic: \"Pydantic\",\n pytest: \"pytest\",\n celery: \"Celery\",\n};\n\n/**\n * Auto-detect the tech stack of a project at the given root directory.\n */\nexport async function detectContext(rootDir: string, onProgress?: ProgressCallback): Promise<DetectedContext> {\n const ctx: DetectedContext = {\n rootDir,\n language: \"other\",\n hasTypeScript: false,\n packageManager: \"none\",\n linter: \"none\",\n frameworks: [],\n directories: [],\n dependencies: [],\n isGitRepo: false,\n totalSourceBytes: 0,\n sourceFileCount: 0,\n monorepo: null,\n };\n\n // Parallel checks for common project markers\n onProgress?.(\"Checking project markers...\");\n const [\n hasGit,\n hasPackageJson,\n hasGoMod,\n hasCargo,\n hasPyproject,\n hasRequirements,\n hasTsConfig,\n hasBiome,\n hasPnpmLock,\n hasYarnLock,\n hasBunLock,\n topEntries,\n ] = await Promise.all([\n fileExists(path.join(rootDir, \".git\")),\n readJsonFile(path.join(rootDir, \"package.json\")),\n fileExists(path.join(rootDir, \"go.mod\")),\n fileExists(path.join(rootDir, \"Cargo.toml\")),\n readJsonFile(path.join(rootDir, \"pyproject.toml\")), // won't parse TOML but that's ok\n fileExists(path.join(rootDir, \"requirements.txt\")),\n fileExists(path.join(rootDir, \"tsconfig.json\")),\n fileExists(path.join(rootDir, \"biome.json\")),\n fileExists(path.join(rootDir, \"pnpm-lock.yaml\")),\n fileExists(path.join(rootDir, \"yarn.lock\")),\n fileExists(path.join(rootDir, \"bun.lockb\")),\n readDirSafe(rootDir),\n ]);\n\n ctx.isGitRepo = hasGit;\n\n // -- Detect language + package manager --\n\n if (hasPackageJson) {\n const pkg = hasPackageJson;\n ctx.language = hasTsConfig ? \"typescript\" : \"javascript\";\n ctx.hasTypeScript = hasTsConfig;\n\n // Package manager\n if (hasPnpmLock) ctx.packageManager = \"pnpm\";\n else if (hasYarnLock) ctx.packageManager = \"yarn\";\n else if (hasBunLock) ctx.packageManager = \"bun\";\n else ctx.packageManager = \"npm\";\n\n // Collect all dependency names\n const deps = {\n ...(pkg.dependencies as Record<string, string> | undefined),\n ...(pkg.devDependencies as Record<string, string> | undefined),\n };\n ctx.dependencies = Object.keys(deps);\n\n // Detect frameworks\n const seen = new Set<string>();\n for (const dep of ctx.dependencies) {\n const framework = FRAMEWORK_MAP[dep];\n if (framework && !seen.has(framework)) {\n seen.add(framework);\n const version = deps[dep]?.replace(/^[\\^~>=<]/, \"\");\n ctx.frameworks.push({ name: framework, version });\n }\n }\n\n // Detect linter\n if (hasBiome) {\n ctx.linter = \"biome\";\n } else {\n const hasEslint = ctx.dependencies.includes(\"eslint\") ||\n topEntries.some((e) => e.startsWith(\".eslintrc\"));\n const hasPrettier = ctx.dependencies.includes(\"prettier\") ||\n topEntries.some((e) => e.startsWith(\".prettierrc\"));\n if (hasEslint) ctx.linter = \"eslint\";\n else if (hasPrettier) ctx.linter = \"prettier\";\n }\n } else if (hasGoMod) {\n ctx.language = \"go\";\n ctx.packageManager = \"go\";\n ctx.linter = \"gofmt\";\n } else if (hasCargo) {\n ctx.language = \"rust\";\n ctx.packageManager = \"cargo\";\n ctx.linter = \"rustfmt\";\n } else if (hasPyproject || hasRequirements) {\n ctx.language = \"python\";\n // Try to detect pip vs poetry\n if (topEntries.includes(\"poetry.lock\")) ctx.packageManager = \"poetry\";\n else ctx.packageManager = \"pip\";\n\n // Detect Python frameworks from requirements.txt\n if (hasRequirements) {\n const { readFileOr } = await import(\"./utils.js\");\n const reqContent = await readFileOr(path.join(rootDir, \"requirements.txt\"));\n if (reqContent) {\n const pkgs = reqContent\n .split(\"\\n\")\n .map((l) => l.trim().split(/[=<>!~[]/)[0].toLowerCase())\n .filter(Boolean);\n for (const pkg of pkgs) {\n const framework = PYTHON_FRAMEWORK_MAP[pkg];\n if (framework) {\n ctx.frameworks.push({ name: framework });\n }\n }\n ctx.dependencies = pkgs;\n }\n }\n\n // Detect Python linter\n const hasRuff = topEntries.includes(\"ruff.toml\") ||\n topEntries.some((e) => e === \"pyproject.toml\");\n if (hasRuff) ctx.linter = \"ruff\";\n else ctx.linter = \"none\";\n }\n\n // Report detected stack\n if (ctx.frameworks.length > 0) {\n const fwNames = ctx.frameworks.map((f) => f.name).join(\", \");\n const lang = ctx.hasTypeScript ? \"TypeScript\" : ctx.language !== \"other\" ? ctx.language : \"\";\n const parts = [lang, fwNames].filter(Boolean);\n onProgress?.(`Detected: ${parts.join(\" + \")}`);\n }\n\n // -- Detect directories --\n onProgress?.(\"Scanning directories...\");\n\n for (const dir of KNOWN_DIRS) {\n if (topEntries.includes(dir)) {\n ctx.directories.push(dir);\n }\n }\n\n // Also check inside src/ for nested structure\n if (topEntries.includes(\"src\")) {\n const srcEntries = await readDirSafe(path.join(rootDir, \"src\"));\n for (const entry of srcEntries) {\n if (KNOWN_DIRS.includes(entry)) {\n ctx.directories.push(`src/${entry}`);\n }\n }\n }\n\n // -- Count source files and total size --\n\n try {\n const extensions = getExtensionsForLanguage(ctx.language);\n const sourceFiles = await fg(\n extensions.map((ext) => `**/*${ext}`),\n {\n cwd: rootDir,\n ignore: [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n \"**/.next/**\",\n \"**/target/**\",\n \"**/vendor/**\",\n \"**/__pycache__/**\",\n \"**/venv/**\",\n \"**/.venv/**\",\n \"**/.Trash/**\",\n \"**/Library/**\",\n \"**/.git/**\",\n ],\n stats: true,\n },\n );\n\n ctx.sourceFileCount = sourceFiles.length;\n onProgress?.(`Counting ${sourceFiles.length} source files...`);\n ctx.totalSourceBytes = sourceFiles.reduce(\n (sum, f) => sum + (f.stats?.size ?? 0),\n 0,\n );\n } catch {\n // Non-critical, leave at 0\n }\n\n // -- Detect testing framework --\n ctx.testFramework = detectTestFramework(ctx.dependencies);\n\n // -- Detect CI provider --\n ctx.ciProvider = await detectCiProvider(rootDir, topEntries);\n\n // -- Detect monorepo --\n\n ctx.monorepo = await detectMonorepo(rootDir, topEntries);\n\n return ctx;\n}\n\n/** Test framework detection: dependency name -> display name */\nconst TEST_FRAMEWORK_MAP: Record<string, string> = {\n vitest: \"Vitest\",\n jest: \"Jest\",\n playwright: \"Playwright\",\n cypress: \"Cypress\",\n mocha: \"Mocha\",\n pytest: \"pytest\",\n};\n\nfunction detectTestFramework(dependencies: string[]): string | undefined {\n for (const [dep, name] of Object.entries(TEST_FRAMEWORK_MAP)) {\n if (dependencies.includes(dep)) return name;\n }\n return undefined;\n}\n\n/** CI provider detection: file/dir pattern -> display name */\nconst CI_PATTERNS: Array<{ path: string; name: string; isDir?: boolean }> = [\n { path: \".github/workflows\", name: \"GitHub Actions\", isDir: true },\n { path: \".gitlab-ci.yml\", name: \"GitLab CI\" },\n { path: \".circleci\", name: \"CircleCI\", isDir: true },\n { path: \"Jenkinsfile\", name: \"Jenkins\" },\n { path: \".travis.yml\", name: \"Travis CI\" },\n];\n\nasync function detectCiProvider(rootDir: string, topEntries: string[]): Promise<string | undefined> {\n for (const ci of CI_PATTERNS) {\n if (ci.isDir) {\n // Check if directory exists\n if (await fileExists(path.join(rootDir, ci.path))) return ci.name;\n } else {\n if (topEntries.includes(ci.path)) return ci.name;\n }\n }\n return undefined;\n}\n\nfunction getExtensionsForLanguage(lang: Language): string[] {\n switch (lang) {\n case \"typescript\":\n return [\".ts\", \".tsx\"];\n case \"javascript\":\n return [\".js\", \".jsx\", \".mjs\"];\n case \"python\":\n return [\".py\"];\n case \"go\":\n return [\".go\"];\n case \"rust\":\n return [\".rs\"];\n case \"java\":\n return [\".java\"];\n default:\n return [\".ts\", \".tsx\", \".js\", \".jsx\", \".py\", \".go\", \".rs\"];\n }\n}\n\n/**\n * Detect monorepo tooling and enumerate packages.\n */\nasync function detectMonorepo(\n rootDir: string,\n topEntries: string[],\n): Promise<MonorepoInfo | null> {\n // Determine monorepo type\n const hasTurboJson = topEntries.includes(\"turbo.json\");\n const hasNxJson = topEntries.includes(\"nx.json\");\n const hasPnpmWorkspace = topEntries.includes(\"pnpm-workspace.yaml\");\n\n let type: MonorepoInfo[\"type\"] | null = null;\n if (hasTurboJson) type = \"turborepo\";\n else if (hasNxJson) type = \"nx\";\n else if (hasPnpmWorkspace) type = \"pnpm-workspaces\";\n\n if (!type) return null;\n\n // Resolve workspace package globs\n let packageGlobs: string[] = [];\n\n if (hasPnpmWorkspace || hasTurboJson) {\n // pnpm-workspace.yaml (also used by Turborepo)\n const yamlContent = await readFileOr(\n path.join(rootDir, \"pnpm-workspace.yaml\"),\n );\n if (yamlContent) {\n // Simple YAML parse: extract lines under \"packages:\"\n const lines = yamlContent.split(\"\\n\");\n let inPackages = false;\n for (const line of lines) {\n if (/^packages:/i.test(line.trim())) {\n inPackages = true;\n continue;\n }\n if (inPackages) {\n const match = line.match(/^\\s+-\\s+['\"]?([^'\"]+)['\"]?/);\n if (match) {\n packageGlobs.push(match[1].trim());\n } else if (line.trim() && !line.startsWith(\" \") && !line.startsWith(\"\\t\")) {\n break; // new top-level key\n }\n }\n }\n }\n }\n\n if (packageGlobs.length === 0 && hasNxJson) {\n // Nx: check for packages/ or libs/ directories\n for (const dir of [\"packages\", \"libs\", \"apps\"]) {\n if (topEntries.includes(dir)) {\n packageGlobs.push(`${dir}/*`);\n }\n }\n }\n\n // Fallback: try workspaces field from package.json\n if (packageGlobs.length === 0) {\n const pkg = await readJsonFile(path.join(rootDir, \"package.json\"));\n if (pkg) {\n const workspaces = pkg.workspaces;\n if (Array.isArray(workspaces)) {\n packageGlobs = workspaces as string[];\n } else if (\n workspaces &&\n typeof workspaces === \"object\" &&\n Array.isArray((workspaces as Record<string, unknown>).packages)\n ) {\n packageGlobs = (workspaces as Record<string, unknown>)\n .packages as string[];\n }\n }\n }\n\n if (packageGlobs.length === 0) return null;\n\n // Resolve globs to actual directories\n const resolvedDirs = await fg(packageGlobs, {\n cwd: rootDir,\n onlyDirectories: true,\n ignore: [\"**/node_modules/**\"],\n absolute: false,\n });\n\n // Build package info for each directory\n const packages: MonorepoPackage[] = [];\n\n for (const dir of resolvedDirs) {\n const pkgJsonPath = path.join(rootDir, dir, \"package.json\");\n const pkgJson = await readJsonFile(pkgJsonPath);\n if (!pkgJson) continue; // Not a valid package\n\n const deps = {\n ...(pkgJson.dependencies as Record<string, string> | undefined),\n ...(pkgJson.devDependencies as Record<string, string> | undefined),\n };\n const depNames = Object.keys(deps);\n\n // Detect frameworks for this package\n const frameworks: DetectedFramework[] = [];\n const seen = new Set<string>();\n for (const dep of depNames) {\n const framework = FRAMEWORK_MAP[dep];\n if (framework && !seen.has(framework)) {\n seen.add(framework);\n const version = deps[dep]?.replace(/^[\\^~>=<]/, \"\");\n frameworks.push({ name: framework, version });\n }\n }\n\n packages.push({\n name: (pkgJson.name as string) ?? path.basename(dir),\n path: dir,\n dependencies: depNames,\n frameworks,\n });\n }\n\n if (packages.length === 0) return null;\n\n return { type, packages };\n}\n\n/**\n * Build a reverse map: framework display name -> dependency names.\n */\nfunction buildReverseFrameworkMap(): Map<string, string[]> {\n const reverse = new Map<string, string[]>();\n for (const [dep, name] of Object.entries(FRAMEWORK_MAP)) {\n const deps = reverse.get(name) ?? [];\n deps.push(dep);\n reverse.set(name, deps);\n }\n return reverse;\n}\n\n/**\n * Enrich detected frameworks with actual import counts from the import graph.\n * Filters out frameworks with 0 imports (detected in package.json but never used).\n */\nexport function enrichFrameworksWithUsage(\n frameworks: DetectedFramework[],\n externalImportCounts: Map<string, number>,\n): DetectedFramework[] {\n const reverseMap = buildReverseFrameworkMap();\n\n return frameworks\n .map((fw) => {\n const depNames = reverseMap.get(fw.name) ?? [];\n let totalCount = 0;\n for (const dep of depNames) {\n totalCount += externalImportCounts.get(dep) ?? 0;\n }\n return { ...fw, importCount: totalCount };\n })\n .filter((fw) => fw.importCount === undefined || fw.importCount > 0);\n}\n\n/**\n * Produce a short human-readable summary of the detected stack.\n */\nexport function summarizeDetection(ctx: DetectedContext): string {\n const parts: string[] = [];\n\n if (ctx.frameworks.length > 0) {\n parts.push(ctx.frameworks.map((f) => f.name).join(\" + \"));\n }\n\n if (ctx.hasTypeScript) {\n parts.push(\"TypeScript\");\n } else if (ctx.language !== \"other\") {\n parts.push(ctx.language.charAt(0).toUpperCase() + ctx.language.slice(1));\n }\n\n if (ctx.linter !== \"none\") {\n parts.push(ctx.linter.charAt(0).toUpperCase() + ctx.linter.slice(1));\n }\n\n if (ctx.packageManager !== \"none\") {\n parts.push(ctx.packageManager);\n }\n\n return parts.join(\" + \");\n}\n","import * as p from \"@clack/prompts\";\nimport type {\n DetectedContext,\n IDETarget,\n ProjectConfig,\n UserAnswers,\n} from \"./types.js\";\nimport { summarizeDetection } from \"./detect.js\";\n\n/**\n * Run the interactive prompt flow. Takes the auto-detected context\n * and asks the user to fill in what couldn't be auto-detected.\n *\n * When `defaults` is provided (from .codebrief.json + --reconfigure),\n * prompt values are pre-filled so the user can just press Enter to keep them.\n */\nexport async function runPrompts(\n detected: DetectedContext,\n defaults?: ProjectConfig | null,\n): Promise<UserAnswers> {\n // 1. IDE/tool selection\n const ideOptions = [\n { value: \"claude\" as const, label: \"Claude Code\" },\n { value: \"cursor\" as const, label: \"Cursor\" },\n { value: \"opencode\" as const, label: \"OpenCode\" },\n { value: \"copilot\" as const, label: \"GitHub Copilot\" },\n { value: \"windsurf\" as const, label: \"Windsurf\" },\n { value: \"cline\" as const, label: \"Cline\" },\n { value: \"continue\" as const, label: \"Continue.dev\" },\n { value: \"aider\" as const, label: \"Aider\" },\n { value: \"generic\" as const, label: \"Other (generic CONTEXT.md)\" },\n ];\n\n const ide = (await p.select({\n message: \"Which AI coding tool are you using?\",\n options: ideOptions,\n initialValue: defaults?.ide,\n })) as IDETarget | symbol;\n\n if (p.isCancel(ide)) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n\n // 2. Confirm detected stack\n const stackSummary = summarizeDetection(detected);\n let stackConfirmed = true;\n let stackCorrections = defaults?.stackCorrections ?? \"\";\n\n if (stackSummary) {\n const confirm = await p.confirm({\n message: `Detected: ${stackSummary}. Correct?`,\n });\n\n if (p.isCancel(confirm)) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n\n stackConfirmed = confirm;\n\n if (!confirm) {\n const corrections = await p.text({\n message: \"What should I correct? (describe your actual stack)\",\n placeholder: \"e.g. It's actually Next.js 15 + Prisma, not plain React\",\n defaultValue: defaults?.stackCorrections || undefined,\n });\n\n if (p.isCancel(corrections)) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n\n stackCorrections = corrections;\n }\n }\n\n // 3. Project purpose\n const projectPurpose = await p.text({\n message: \"What does this project do? (1-2 sentences)\",\n placeholder:\n \"e.g. A mobile AI chat app connecting to OpenAI, Anthropic, and Google APIs\",\n defaultValue: defaults?.projectPurpose || undefined,\n validate: (value) => {\n if (!value?.trim()) return \"Please describe your project briefly.\";\n },\n });\n\n if (p.isCancel(projectPurpose)) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n\n // 4. Key patterns / conventions\n const keyPatterns = await p.text({\n message:\n \"Any key coding patterns or conventions? (optional, press Enter to skip)\",\n placeholder:\n \"e.g. Zustand slices for state, NativeWind for styling, expo/fetch for SSE\",\n defaultValue: defaults?.keyPatterns || \"\",\n });\n\n if (p.isCancel(keyPatterns)) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n\n // 5. Gotchas / anti-patterns\n const gotchas = await p.text({\n message: \"Any critical gotchas or anti-patterns to avoid? (optional)\",\n placeholder:\n \"e.g. Never use FadeIn/FadeOut on ternary components, no @expo/vector-icons\",\n defaultValue: defaults?.gotchas || \"\",\n });\n\n if (p.isCancel(gotchas)) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n\n // 6. Code snapshot depth (only for TS/JS projects)\n let generateSnapshot = false;\n let snapshotPaths: string[] = defaults?.snapshotPaths ?? [];\n\n if (\n detected.language === \"typescript\" ||\n detected.language === \"javascript\"\n ) {\n const snapshotChoice = (await p.select({\n message:\n \"Generate a code snapshot? (extracts types, store shapes, component props)\",\n options: [\n { value: \"auto\" as const, label: \"Yes, auto-detect key files\" },\n { value: \"no\" as const, label: \"No, skip code snapshot\" },\n { value: \"custom\" as const, label: \"Yes, but let me specify paths\" },\n ],\n initialValue: defaults?.generateSnapshot\n ? defaults.snapshotPaths.length > 0\n ? (\"custom\" as const)\n : (\"auto\" as const)\n : undefined,\n })) as \"auto\" | \"no\" | \"custom\" | symbol;\n\n if (p.isCancel(snapshotChoice)) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n\n if (snapshotChoice === \"auto\") {\n generateSnapshot = true;\n snapshotPaths = [];\n } else if (snapshotChoice === \"custom\") {\n generateSnapshot = true;\n const paths = await p.text({\n message: \"Paths to scan (comma-separated, relative to project root)\",\n placeholder: \"e.g. src/types, src/stores, src/components\",\n defaultValue:\n defaults?.snapshotPaths.length\n ? defaults.snapshotPaths.join(\", \")\n : undefined,\n });\n\n if (p.isCancel(paths)) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n\n snapshotPaths = paths\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n }\n }\n\n // 7. Monorepo: per-package context files\n let generatePerPackage = false;\n\n if (detected.monorepo && detected.monorepo.packages.length > 0) {\n const mono = detected.monorepo;\n const pkgNames = mono.packages.map((pkg) => pkg.name).join(\", \");\n\n const perPkg = await p.confirm({\n message: `Monorepo detected (${mono.type}, ${mono.packages.length} packages: ${pkgNames}). Generate per-package context files?`,\n initialValue: defaults?.generatePerPackage ?? false,\n });\n\n if (p.isCancel(perPkg)) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n\n generatePerPackage = perPkg;\n }\n\n return {\n ide,\n projectPurpose,\n keyPatterns: keyPatterns ?? \"\",\n gotchas: gotchas ?? \"\",\n generateSnapshot,\n snapshotPaths,\n stackConfirmed,\n stackCorrections,\n generatePerPackage,\n };\n}\n","import path from \"node:path\";\nimport fg from \"fast-glob\";\nimport { estimateTokens, readFileOr } from \"./utils.js\";\nimport { findUsedExports } from \"./graph.js\";\nimport type { CodeSnapshot, DetectedContext, GitAnalysis, ImportGraph, ProgressCallback, SnapshotEntry } from \"./types.js\";\n\n/**\n * Auto-detect which directories to scan for code snapshots.\n */\nfunction getDefaultScanPaths(ctx: DetectedContext): string[] {\n const paths: string[] = [];\n const dirs = ctx.directories;\n\n // Types directories\n for (const d of dirs) {\n if (d.endsWith(\"types\") || d.endsWith(\"typings\")) paths.push(d);\n }\n\n // Store directories\n for (const d of dirs) {\n if (d.endsWith(\"stores\") || d.endsWith(\"store\")) paths.push(d);\n }\n\n // Service/API directories\n for (const d of dirs) {\n if (d.endsWith(\"services\") || d.endsWith(\"api\")) paths.push(d);\n }\n\n // Hook directories\n for (const d of dirs) {\n if (d.endsWith(\"hooks\")) paths.push(d);\n }\n\n // Component directories\n for (const d of dirs) {\n if (d.endsWith(\"components\")) paths.push(d);\n }\n\n // Lib/utils\n for (const d of dirs) {\n if (d.endsWith(\"lib\") || d.endsWith(\"utils\")) paths.push(d);\n }\n\n // Fallback: scan common type file patterns at root\n if (paths.length === 0) {\n paths.push(\"src\", \"app\", \"lib\");\n }\n\n return paths;\n}\n\n/**\n * Regex patterns for extracting TypeScript/JavaScript declarations.\n */\nconst PATTERNS = {\n /** export interface Foo { ... } or export type Foo = ... */\n exportedType: /^export\\s+(interface|type)\\s+(\\w+)/,\n /** interface FooProps { ... } (component props, even if not exported) */\n propsInterface: /^(?:export\\s+)?interface\\s+(\\w+Props)\\s*\\{/,\n /** export function foo(...) or export const foo = */\n exportedFunction: /^export\\s+(?:async\\s+)?(?:function|const)\\s+(\\w+)/,\n /** StateCreator<...> pattern (Zustand slices) */\n zustandSlice: /StateCreator<\\s*(\\w+)/,\n /** export interface FooSlice { ... } */\n sliceInterface: /^export\\s+interface\\s+(\\w+Slice)\\s*\\{/,\n};\n\n/**\n * Extract snapshot entries from a single file.\n */\nasync function extractFromFile(\n filePath: string,\n relPath: string,\n): Promise<SnapshotEntry[]> {\n const content = await readFileOr(filePath);\n if (!content) return [];\n\n const entries: SnapshotEntry[] = [];\n const lines = content.split(\"\\n\");\n\n // Determine category hints from path\n const isStore = /stores?[/\\\\]/.test(relPath);\n const isHook = /hooks?[/\\\\]/.test(relPath) || relPath.includes(\"use\");\n const isComponent = /components?[/\\\\]/.test(relPath);\n const isService = /services?[/\\\\]|api[/\\\\]/.test(relPath);\n const isType = /types?[/\\\\]/.test(relPath) || relPath.endsWith(\".types.ts\");\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const trimmed = line.trimStart();\n\n // -- Exported interfaces / types --\n const typeMatch = trimmed.match(PATTERNS.exportedType);\n if (typeMatch) {\n const [, kind, name] = typeMatch;\n const category =\n name.endsWith(\"Slice\")\n ? \"store\"\n : name.endsWith(\"Props\")\n ? \"component\"\n : kind === \"interface\"\n ? \"interface\"\n : \"type\";\n\n // Grab the full declaration (until closing brace or semicolon for type aliases)\n const block = extractBlock(lines, i);\n entries.push({ file: relPath, category, signature: block });\n continue;\n }\n\n // -- Non-exported Props interfaces (common in components) --\n if (isComponent) {\n const propsMatch = trimmed.match(PATTERNS.propsInterface);\n if (propsMatch && !trimmed.startsWith(\"export\")) {\n const block = extractBlock(lines, i);\n entries.push({ file: relPath, category: \"component\", signature: block });\n continue;\n }\n }\n\n // -- Exported functions --\n const funcMatch = trimmed.match(PATTERNS.exportedFunction);\n if (funcMatch) {\n const [, name] = funcMatch;\n\n // Skip React component default exports like `export function MyComponent(`\n // unless it's clearly a hook or service\n if (isComponent && name[0] === name[0].toUpperCase() && !name.startsWith(\"use\")) {\n // This is likely a component — we only care about its Props, not its body\n continue;\n }\n\n let category: SnapshotEntry[\"category\"] = \"function\";\n if (isHook || name.startsWith(\"use\")) category = \"hook\";\n else if (isStore) category = \"store\";\n\n // Extract just the signature line (not the full body)\n const sig = extractSignatureLine(lines, i);\n entries.push({ file: relPath, category, signature: sig });\n }\n }\n\n return entries;\n}\n\n/**\n * Extract a block from the current line until the closing brace at the same depth.\n * For type aliases (no brace), captures until the next semicolon or blank line.\n */\nfunction extractBlock(lines: string[], startIdx: number): string {\n const firstLine = lines[startIdx];\n\n // Type alias (no opening brace on first line, usually single-line or multi-line with |)\n if (!firstLine.includes(\"{\")) {\n // Collect until semicolon\n let result = \"\";\n for (let i = startIdx; i < lines.length && i < startIdx + 10; i++) {\n result += (result ? \"\\n\" : \"\") + lines[i];\n if (lines[i].includes(\";\")) break;\n }\n return result.trim();\n }\n\n // Block with braces — capture until matching depth\n let depth = 0;\n let result = \"\";\n const maxLines = 30; // Cap to avoid capturing massive blocks\n\n for (let i = startIdx; i < lines.length && i < startIdx + maxLines; i++) {\n const line = lines[i];\n result += (result ? \"\\n\" : \"\") + line;\n\n for (const ch of line) {\n if (ch === \"{\") depth++;\n if (ch === \"}\") depth--;\n }\n\n if (depth <= 0 && i > startIdx) break;\n }\n\n return result.trim();\n}\n\n/**\n * Extract a function signature (everything up to the opening brace or arrow).\n */\nfunction extractSignatureLine(lines: string[], startIdx: number): string {\n let sig = \"\";\n for (let i = startIdx; i < lines.length && i < startIdx + 5; i++) {\n sig += (sig ? \" \" : \"\") + lines[i].trim();\n // Stop at opening brace, arrow, or if it looks complete\n if (sig.includes(\"{\") || sig.includes(\"=>\")) {\n // Trim everything after the opening brace / arrow\n const braceIdx = sig.indexOf(\"{\");\n const arrowIdx = sig.indexOf(\"=>\");\n const cutIdx =\n braceIdx >= 0 && arrowIdx >= 0\n ? Math.min(braceIdx, arrowIdx)\n : braceIdx >= 0\n ? braceIdx\n : arrowIdx >= 0\n ? arrowIdx + 2\n : sig.length;\n sig = sig.slice(0, cutIdx).trim();\n break;\n }\n }\n return sig;\n}\n\n/**\n * Append an \"imported by N files\" comment to signatures of highly-imported entries.\n */\nfunction annotateSignature(entry: SnapshotEntry): string {\n if (entry.importedByCount && entry.importedByCount > 2) {\n // Add comment to first line of the signature\n const firstLine = entry.signature.split(\"\\n\")[0];\n const rest = entry.signature.split(\"\\n\").slice(1);\n const annotated = `${firstLine} // imported by ${entry.importedByCount} files`;\n return rest.length > 0 ? [annotated, ...rest].join(\"\\n\") : annotated;\n }\n return entry.signature;\n}\n\n/**\n * Condense snapshot entries into a readable markdown block.\n */\nfunction renderSnapshot(entries: SnapshotEntry[]): string {\n if (entries.length === 0) return \"\";\n\n // Group by file\n const byFile = new Map<string, SnapshotEntry[]>();\n for (const e of entries) {\n const list = byFile.get(e.file) ?? [];\n list.push(e);\n byFile.set(e.file, list);\n }\n\n let md = \"\";\n\n // Group by category for cleaner output\n const types = entries.filter((e) => e.category === \"type\" || e.category === \"interface\");\n const stores = entries.filter((e) => e.category === \"store\");\n const hooks = entries.filter((e) => e.category === \"hook\");\n const components = entries.filter((e) => e.category === \"component\");\n const functions = entries.filter((e) => e.category === \"function\");\n\n if (types.length > 0) {\n md += \"### Core Types\\n\\n```ts\\n\";\n md += types.map((e) => annotateSignature(e)).join(\"\\n\\n\");\n md += \"\\n```\\n\\n\";\n }\n\n if (stores.length > 0) {\n md += \"### Store Shape\\n\\n```ts\\n\";\n md += stores.map((e) => annotateSignature(e)).join(\"\\n\\n\");\n md += \"\\n```\\n\\n\";\n }\n\n if (components.length > 0) {\n md += \"### Component Props\\n\\n```ts\\n\";\n md += components.map((e) => annotateSignature(e)).join(\"\\n\\n\");\n md += \"\\n```\\n\\n\";\n }\n\n if (hooks.length > 0) {\n md += \"### Hooks\\n\\n```ts\\n\";\n md += hooks.map((e) => annotateSignature(e)).join(\"\\n\\n\");\n md += \"\\n```\\n\\n\";\n }\n\n if (functions.length > 0) {\n md += \"### Key Functions\\n\\n```ts\\n\";\n md += functions.map((e) => annotateSignature(e)).join(\"\\n\\n\");\n md += \"\\n```\\n\\n\";\n }\n\n return md.trimEnd();\n}\n\n/**\n * Generate a code snapshot for the project.\n */\nexport async function generateSnapshot(\n ctx: DetectedContext,\n customPaths: string[],\n graph?: ImportGraph,\n maxTokens?: number,\n onProgress?: ProgressCallback,\n gitActivity?: GitAnalysis | null,\n): Promise<CodeSnapshot> {\n const scanPaths =\n customPaths.length > 0 ? customPaths : getDefaultScanPaths(ctx);\n\n if (scanPaths.length === 0) {\n return { entries: [], markdown: \"\" };\n }\n\n // Report which directories we're scanning\n const dirNames = scanPaths.map((p) => p.split(\"/\").pop() ?? p);\n onProgress?.(`Scanning ${scanPaths.length} directories: ${dirNames.join(\", \")}...`);\n\n // Find all TS/JS files in the scan paths\n const patterns = scanPaths.map((p) => `${p}/**/*.{ts,tsx,js,jsx}`);\n\n const files = await fg(patterns, {\n cwd: ctx.rootDir,\n ignore: [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n \"**/*.test.*\",\n \"**/*.spec.*\",\n \"**/__tests__/**\",\n \"**/.Trash/**\",\n \"**/Library/**\",\n \"**/.git/**\",\n ],\n absolute: false,\n });\n\n const allEntries: SnapshotEntry[] = [];\n\n for (let i = 0; i < files.length; i++) {\n const file = files[i];\n\n if ((i + 1) % 20 === 0 || i === files.length - 1) {\n const dir = path.dirname(file).split(\"/\").pop() ?? \"\";\n onProgress?.(`Extracting signatures... ${i + 1}/${files.length} files (${dir}/)`);\n }\n\n const absPath = path.join(ctx.rootDir, file);\n const entries = await extractFromFile(absPath, file);\n allEntries.push(...entries);\n }\n\n // Populate importedByCount from graph\n if (graph) {\n for (const entry of allEntries) {\n const count = graph.inDegree.get(entry.file) ?? 0;\n if (count > 0) {\n entry.importedByCount = count;\n }\n }\n }\n\n // Filter dead exports using import graph\n onProgress?.(\"Filtering dead exports...\");\n const liveEntries = filterDeadExports(allEntries, graph);\n\n // Apply token budget if graph is available\n const budget =\n maxTokens ??\n Math.min(16000, 4000 + Math.floor(ctx.sourceFileCount / 25) * 500);\n onProgress?.(`Applying token budget (${budget.toLocaleString()} tokens)...`);\n const { selected, excluded } = applyTokenBudget(liveEntries, budget, graph, gitActivity);\n\n const markdown = renderSnapshot(selected);\n\n return {\n entries: selected,\n markdown,\n budgetExcluded: excluded,\n estimatedTokens: estimateTokens(markdown),\n };\n}\n\n/** Entry-point patterns — files that are never filtered as dead exports */\nconst ENTRY_POINT_PATTERNS = [\n /(?:^|\\/)index\\.[jt]sx?$/,\n /(?:^|\\/)App\\.[jt]sx?$/,\n /(?:^|\\/)main\\.[jt]sx?$/,\n /(?:^|\\/)pages\\//,\n /(?:^|\\/)app\\//,\n /(?:^|\\/)routes?\\//,\n /(?:^|\\/)middleware\\//,\n];\n\n/**\n * Extract the identifier name from a signature string.\n * e.g. \"export interface Foo {\" -> \"Foo\"\n * \"export const bar =\" -> \"bar\"\n * \"export type Baz =\" -> \"Baz\"\n */\nfunction extractNameFromSignature(sig: string): string | null {\n const m = sig.match(\n /export\\s+(?:default\\s+)?(?:async\\s+)?(?:interface|type|function|const|let|var|class|enum)\\s+(\\w+)/,\n );\n return m?.[1] ?? null;\n}\n\n/**\n * Check if a file is an entry point (never filtered).\n */\nfunction isEntryPoint(filePath: string): boolean {\n return ENTRY_POINT_PATTERNS.some((p) => p.test(filePath));\n}\n\n/**\n * Filter out exports that are never imported anywhere in the project.\n * Entry-point files and barrel re-exports are always kept.\n */\nfunction filterDeadExports(\n entries: SnapshotEntry[],\n graph?: ImportGraph,\n): SnapshotEntry[] {\n if (!graph || graph.edges.length === 0) return entries;\n\n const usedExports = findUsedExports(graph.edges);\n\n return entries.filter((entry) => {\n // Always keep entry-point files\n if (isEntryPoint(entry.file)) return true;\n\n // Extract the export name from the signature\n const name = extractNameFromSignature(entry.signature);\n if (!name) return true; // Can't determine name, keep it\n\n // Check if this export is used somewhere\n return usedExports.has(`${entry.file}::${name}`);\n });\n}\n\n/**\n * Greedy knapsack: prioritize entries by centrality-weighted value per token.\n */\nfunction applyTokenBudget(\n entries: SnapshotEntry[],\n budget: number,\n graph?: ImportGraph,\n gitActivity?: GitAnalysis | null,\n): { selected: SnapshotEntry[]; excluded: number } {\n if (entries.length === 0) return { selected: [], excluded: 0 };\n\n // Score each entry\n const scored = entries.map((entry) => {\n const tokens = Math.max(1, estimateTokens(entry.signature));\n const centrality = graph?.centrality.get(entry.file) ?? 0.5;\n\n // Category boost: types/interfaces are more valuable for context\n let categoryBoost = 1.0;\n if (entry.category === \"type\" || entry.category === \"interface\") categoryBoost = 1.3;\n\n // Git boost: files changed recently get priority\n let gitBoost = 1.0;\n if (gitActivity) {\n const commits = gitActivity.commitCounts.get(entry.file) ?? 0;\n gitBoost = 1.0 + Math.min(0.5, commits / 20);\n }\n\n const value = (centrality * categoryBoost * gitBoost) / tokens;\n return { entry, tokens, value };\n });\n\n // Sort by value descending\n scored.sort((a, b) => b.value - a.value);\n\n // Greedily select\n let remaining = budget;\n const selected: SnapshotEntry[] = [];\n\n for (const { entry, tokens } of scored) {\n if (tokens <= remaining) {\n selected.push(entry);\n remaining -= tokens;\n }\n }\n\n return {\n selected,\n excluded: entries.length - selected.length,\n };\n}\n","import path from \"node:path\";\nimport fg from \"fast-glob\";\nimport { readFileOr } from \"./utils.js\";\nimport type {\n ArchitecturalLayer,\n CircularDependency,\n Community,\n ExportCoverage,\n FileInstability,\n HubFile,\n ImportEdge,\n ImportGraph,\n Language,\n LayerEdge,\n ProgressCallback,\n} from \"./types.js\";\n\n// ── Import regex patterns per language ────────────────────────────────\n\n/** JS/TS: import ... from '...' (including type-only and namespace imports) */\nconst JS_IMPORT_FROM = /import\\s+(?:type\\s+)?(?:\\{([^}]*)\\}|(\\*\\s+as\\s+\\w+|\\w+)(?:\\s*,\\s*\\{([^}]*)\\})?)\\s+from\\s+['\"]([^'\"]+)['\"]/g;\n/** JS/TS: import '...' (side-effect) */\nconst JS_IMPORT_SIDE = /import\\s+['\"]([^'\"]+)['\"]/g;\n/** JS/TS: require('...') */\nconst JS_REQUIRE = /require\\(\\s*['\"]([^'\"]+)['\"]\\s*\\)/g;\n/** JS/TS: dynamic import('...') */\nconst JS_DYNAMIC = /import\\(\\s*['\"]([^'\"]+)['\"]\\s*\\)/g;\n\n/** Python: from foo.bar import baz, qux (including relative imports like from . import x) */\nconst PY_FROM_IMPORT = /^from\\s+(\\.+[\\w.]*|[\\w][\\w.]*)\\s+import\\s+(.+)/gm;\n/** Python: import foo, bar */\nconst PY_IMPORT = /^import\\s+([\\w., ]+)/gm;\n\n/** Go: import \"pkg\" or import ( \"pkg\" ) */\nconst GO_IMPORT_SINGLE = /import\\s+\"([^\"]+)\"/g;\nconst GO_IMPORT_BLOCK = /import\\s*\\(([^)]+)\\)/gs;\n\n/** Rust: use crate::foo::bar (including pub use and glob imports) */\nconst RUST_USE = /(?:pub\\s+)?use\\s+((?:crate|super|self)(?:::\\w+)*(?:::\\{[^}]*\\})?)/g;\n/** Rust: mod foo; */\nconst RUST_MOD = /mod\\s+(\\w+)\\s*;/g;\n\n// ── File extensions to try when resolving relative imports ────────────\n\nconst JS_EXTENSIONS = [\".ts\", \".tsx\", \".js\", \".jsx\", \".mjs\"];\nconst INDEX_FILES = JS_EXTENSIONS.map((e) => `/index${e}`);\n\n// ── Language-specific source file globs ───────────────────────────────\n\nfunction getSourceGlob(lang: Language): string[] {\n switch (lang) {\n case \"typescript\":\n case \"javascript\":\n return [\"**/*.{ts,tsx,js,jsx,mjs}\"];\n case \"python\":\n return [\"**/*.py\"];\n case \"go\":\n return [\"**/*.go\"];\n case \"rust\":\n return [\"**/*.rs\"];\n default:\n return [\"**/*.{ts,tsx,js,jsx,py,go,rs}\"];\n }\n}\n\n// ── Parse imports from a single file ──────────────────────────────────\n\nexport interface RawImport {\n specifier: string;\n importedNames: string[];\n}\n\nexport function parseJsImports(content: string): RawImport[] {\n const imports: RawImport[] = [];\n\n // import { a, b } from '...' / import Foo from '...' / import Foo, { a } from '...' / import * as Foo from '...'\n for (const m of content.matchAll(JS_IMPORT_FROM)) {\n const names: string[] = [];\n if (m[1]) names.push(...m[1].split(\",\").map((n) => n.trim().split(/\\s+as\\s+/)[0].trim()).filter(Boolean));\n if (m[2]) {\n const group2 = m[2].trim();\n // Namespace import (* as foo) — edge is valid but no named import to extract\n if (!group2.startsWith(\"*\")) {\n names.push(group2);\n }\n }\n if (m[3]) names.push(...m[3].split(\",\").map((n) => n.trim().split(/\\s+as\\s+/)[0].trim()).filter(Boolean));\n imports.push({ specifier: m[4], importedNames: names });\n }\n\n // import '...' (side-effect)\n for (const m of content.matchAll(JS_IMPORT_SIDE)) {\n // Skip if already captured by JS_IMPORT_FROM (side-effect imports have no bindings)\n if (!content.includes(`from '${m[1]}'`) && !content.includes(`from \"${m[1]}\"`)) {\n imports.push({ specifier: m[1], importedNames: [] });\n }\n }\n\n // require('...')\n for (const m of content.matchAll(JS_REQUIRE)) {\n imports.push({ specifier: m[1], importedNames: [] });\n }\n\n // dynamic import('...')\n for (const m of content.matchAll(JS_DYNAMIC)) {\n imports.push({ specifier: m[1], importedNames: [] });\n }\n\n return imports;\n}\n\nexport function parsePythonImports(content: string): RawImport[] {\n const imports: RawImport[] = [];\n\n for (const m of content.matchAll(PY_FROM_IMPORT)) {\n const module = m[1];\n const names = m[2].split(\",\").map((n) => n.trim().split(/\\s+as\\s+/)[0].trim()).filter(Boolean);\n imports.push({ specifier: module, importedNames: names });\n }\n\n for (const m of content.matchAll(PY_IMPORT)) {\n const modules = m[1].split(\",\").map((n) => n.trim().split(/\\s+as\\s+/)[0].trim()).filter(Boolean);\n for (const mod of modules) {\n imports.push({ specifier: mod, importedNames: [] });\n }\n }\n\n return imports;\n}\n\nexport function parseGoImports(content: string): RawImport[] {\n const imports: RawImport[] = [];\n\n for (const m of content.matchAll(GO_IMPORT_SINGLE)) {\n imports.push({ specifier: m[1], importedNames: [] });\n }\n\n for (const m of content.matchAll(GO_IMPORT_BLOCK)) {\n const block = m[1];\n for (const line of block.split(\"\\n\")) {\n // Skip comment lines\n if (line.trim().startsWith(\"//\")) continue;\n const match = line.match(/[\"']([^\"']+)[\"']/);\n if (match) {\n imports.push({ specifier: match[1], importedNames: [] });\n }\n }\n }\n\n return imports;\n}\n\nexport function parseRustImports(content: string): RawImport[] {\n const imports: RawImport[] = [];\n\n for (const m of content.matchAll(RUST_USE)) {\n const usePath = m[1];\n // Check for glob imports like crate::foo::{Bar, Baz}\n const globMatch = usePath.match(/::\\{([^}]*)\\}$/);\n if (globMatch) {\n const names = globMatch[1].split(\",\").map((n) => n.trim()).filter(Boolean);\n imports.push({ specifier: usePath, importedNames: names });\n } else {\n const parts = usePath.split(\"::\");\n const name = parts[parts.length - 1];\n imports.push({ specifier: usePath, importedNames: name ? [name] : [] });\n }\n }\n\n for (const m of content.matchAll(RUST_MOD)) {\n imports.push({ specifier: m[1], importedNames: [] });\n }\n\n return imports;\n}\n\nfunction parseImports(content: string, lang: Language): RawImport[] {\n switch (lang) {\n case \"typescript\":\n case \"javascript\":\n return parseJsImports(content);\n case \"python\":\n return parsePythonImports(content);\n case \"go\":\n return parseGoImports(content);\n case \"rust\":\n return parseRustImports(content);\n default:\n return parseJsImports(content);\n }\n}\n\n// ── Resolve relative imports to file paths ────────────────────────────\n\nfunction isRelativeSpecifier(spec: string, lang: Language): boolean {\n if (lang === \"typescript\" || lang === \"javascript\") {\n return spec.startsWith(\"./\") || spec.startsWith(\"../\");\n }\n if (lang === \"python\") {\n return spec.startsWith(\".\");\n }\n if (lang === \"rust\") {\n return spec.startsWith(\"crate::\") || spec.startsWith(\"super::\") || spec.startsWith(\"self::\");\n }\n return spec.startsWith(\"./\") || spec.startsWith(\"../\");\n}\n\n/**\n * Try to resolve a JS/TS relative import to an actual file path.\n * Returns the resolved relative path or null.\n */\nfunction resolveJsImport(\n specifier: string,\n fromFile: string,\n allFiles: Set<string>,\n): string | null {\n const dir = path.dirname(fromFile);\n const raw = path.join(dir, specifier).replace(/\\\\/g, \"/\");\n\n // Try with original path, then with JS extension stripped (TS ESM convention:\n // source uses `.js` specifiers but actual files are `.ts`)\n const stripped = raw.replace(/\\.(jsx?|mjs)$/, \"\");\n const bases = stripped !== raw ? [raw, stripped] : [raw];\n\n for (const base of bases) {\n if (allFiles.has(base)) return base;\n for (const ext of JS_EXTENSIONS) {\n if (allFiles.has(base + ext)) return base + ext;\n }\n for (const idx of INDEX_FILES) {\n if (allFiles.has(base + idx)) return base + idx;\n }\n }\n\n return null;\n}\n\n/**\n * Try to resolve a Python relative import to a file path.\n */\nfunction resolvePythonImport(\n specifier: string,\n fromFile: string,\n allFiles: Set<string>,\n): string | null {\n if (!specifier.startsWith(\".\")) return null;\n const dir = path.dirname(fromFile);\n // Count leading dots\n let dots = 0;\n while (specifier[dots] === \".\") dots++;\n const modulePath = specifier.slice(dots).replace(/\\./g, \"/\");\n let baseDir = dir;\n for (let i = 1; i < dots; i++) {\n baseDir = path.dirname(baseDir);\n }\n const base = modulePath ? path.join(baseDir, modulePath).replace(/\\\\/g, \"/\") : baseDir;\n\n // Try as file\n if (allFiles.has(base + \".py\")) return base + \".py\";\n // Try as package\n if (allFiles.has(base + \"/__init__.py\")) return base + \"/__init__.py\";\n\n return null;\n}\n\nfunction resolveImport(\n specifier: string,\n fromFile: string,\n lang: Language,\n allFiles: Set<string>,\n): string | null {\n switch (lang) {\n case \"typescript\":\n case \"javascript\":\n return resolveJsImport(specifier, fromFile, allFiles);\n case \"python\":\n return resolvePythonImport(specifier, fromFile, allFiles);\n default:\n // Go and Rust: module paths are harder to resolve reliably\n // without a full build system. Skip resolution for now.\n return null;\n }\n}\n\n// ── PageRank centrality ───────────────────────────────────────────────\n\nfunction computePageRank(\n files: string[],\n edges: ImportEdge[],\n iterations = 5,\n damping = 0.85,\n): Map<string, number> {\n const n = files.length;\n if (n === 0) return new Map();\n\n // Build adjacency: from -> [to, ...]\n const outLinks = new Map<string, string[]>();\n for (const file of files) outLinks.set(file, []);\n for (const edge of edges) {\n if (!edge.isExternal && outLinks.has(edge.from)) {\n outLinks.get(edge.from)!.push(edge.to);\n }\n }\n\n // Init scores\n let scores = new Map<string, number>();\n const init = 1 / n;\n for (const file of files) scores.set(file, init);\n\n // Iterate\n for (let iter = 0; iter < iterations; iter++) {\n const next = new Map<string, number>();\n for (const file of files) next.set(file, (1 - damping) / n);\n\n for (const file of files) {\n const links = outLinks.get(file) ?? [];\n if (links.length === 0) continue;\n const share = (damping * (scores.get(file) ?? 0)) / links.length;\n for (const target of links) {\n next.set(target, (next.get(target) ?? 0) + share);\n }\n }\n scores = next;\n }\n\n // Normalize to 0–1\n let max = 0;\n for (const v of scores.values()) {\n if (v > max) max = v;\n }\n if (max > 0) {\n for (const [k, v] of scores) {\n scores.set(k, v / max);\n }\n }\n\n return scores;\n}\n\n// ── Public API ────────────────────────────────────────────────────────\n\n/**\n * Build the import graph for a project.\n */\nexport async function buildImportGraph(\n rootDir: string,\n language: Language,\n onProgress?: ProgressCallback,\n): Promise<ImportGraph> {\n const globs = getSourceGlob(language);\n let files: string[];\n try {\n files = await fg(globs, {\n cwd: rootDir,\n ignore: [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n \"**/.next/**\",\n \"**/target/**\",\n \"**/vendor/**\",\n \"**/__pycache__/**\",\n \"**/venv/**\",\n \"**/.venv/**\",\n \"**/.Trash/**\",\n \"**/Library/**\",\n \"**/.git/**\",\n ],\n absolute: false,\n });\n } catch (err: unknown) {\n // Gracefully degrade on permission errors (e.g. scanning ~/ on macOS)\n const code = (err as NodeJS.ErrnoException).code;\n if (code === \"EPERM\" || code === \"EACCES\") {\n onProgress?.(\"Warning: permission error scanning files — returning empty graph\");\n return { edges: [], inDegree: new Map(), centrality: new Map(), externalImportCounts: new Map() };\n }\n throw err;\n }\n\n onProgress?.(`Found ${files.length} source files to analyze`);\n\n const fileSet = new Set(files);\n const edges: ImportEdge[] = [];\n const inDegree = new Map<string, number>();\n const externalImportCounts = new Map<string, number>();\n\n // Init in-degree\n for (const file of files) inDegree.set(file, 0);\n\n for (let i = 0; i < files.length; i++) {\n const file = files[i];\n\n if ((i + 1) % 50 === 0 || i === files.length - 1) {\n onProgress?.(`Parsing imports... ${i + 1}/${files.length} files`);\n }\n\n const absPath = path.join(rootDir, file);\n const content = await readFileOr(absPath);\n if (!content) continue;\n\n const rawImports = parseImports(content, language);\n\n for (const raw of rawImports) {\n const isRelative = isRelativeSpecifier(raw.specifier, language);\n\n if (isRelative) {\n const resolved = resolveImport(raw.specifier, file, language, fileSet);\n if (resolved) {\n edges.push({\n from: file,\n to: resolved,\n isExternal: false,\n specifier: raw.specifier,\n importedNames: raw.importedNames,\n });\n inDegree.set(resolved, (inDegree.get(resolved) ?? 0) + 1);\n }\n } else {\n // External package\n // Normalize specifier to package name (e.g. @scope/pkg/path -> @scope/pkg)\n const pkgName = getPackageName(raw.specifier);\n edges.push({\n from: file,\n to: pkgName,\n isExternal: true,\n specifier: raw.specifier,\n importedNames: raw.importedNames,\n });\n externalImportCounts.set(\n pkgName,\n (externalImportCounts.get(pkgName) ?? 0) + 1,\n );\n }\n }\n }\n\n onProgress?.(\"Computing centrality (PageRank)...\");\n const centrality = computePageRank(files, edges);\n\n return { edges, inDegree, centrality, externalImportCounts };\n}\n\n/**\n * Extract the package name from an import specifier.\n * e.g. \"@tanstack/react-query\" -> \"@tanstack/react-query\"\n * \"react/jsx-runtime\" -> \"react\"\n * \"zustand\" -> \"zustand\"\n */\nfunction getPackageName(specifier: string): string {\n if (specifier.startsWith(\"@\")) {\n const parts = specifier.split(\"/\");\n return parts.slice(0, 2).join(\"/\");\n }\n return specifier.split(\"/\")[0];\n}\n\n/**\n * Build a set of \"filepath::ExportName\" pairs that are actually imported\n * somewhere in the project. Used for dead export filtering.\n */\nexport function findUsedExports(edges: ImportEdge[]): Set<string> {\n const used = new Set<string>();\n for (const edge of edges) {\n if (edge.isExternal) continue;\n for (const name of edge.importedNames) {\n used.add(`${edge.to}::${name}`);\n }\n }\n return used;\n}\n\n/**\n * Get the most interconnected files (hub files) sorted by centrality.\n */\nexport function getHubFiles(graph: ImportGraph, limit = 8): HubFile[] {\n // Count outgoing internal imports per file\n const outCount = new Map<string, number>();\n for (const edge of graph.edges) {\n if (!edge.isExternal) {\n outCount.set(edge.from, (outCount.get(edge.from) ?? 0) + 1);\n }\n }\n\n // Build list of all files with their scores\n const files: HubFile[] = [];\n for (const [filePath, centrality] of graph.centrality) {\n const importedBy = graph.inDegree.get(filePath) ?? 0;\n const imports = outCount.get(filePath) ?? 0;\n // Only include files that have some connectivity\n if (importedBy > 0 || imports > 0) {\n files.push({ path: filePath, centrality, importedBy, imports });\n }\n }\n\n // Sort by centrality descending\n files.sort((a, b) => b.centrality - a.centrality);\n\n return files.slice(0, limit);\n}\n\n/**\n * Find all strongly connected components using Tarjan's algorithm.\n * Returns SCCs with size > 1 (i.e. actual cycles).\n */\nexport function findSCCs(graph: ImportGraph): string[][] {\n // Build adjacency list from internal edges only\n const adj = new Map<string, string[]>();\n const allFiles = new Set<string>();\n for (const edge of graph.edges) {\n if (edge.isExternal) continue;\n allFiles.add(edge.from);\n allFiles.add(edge.to);\n const list = adj.get(edge.from) ?? [];\n list.push(edge.to);\n adj.set(edge.from, list);\n }\n\n let index = 0;\n const indices = new Map<string, number>();\n const lowlinks = new Map<string, number>();\n const onStack = new Set<string>();\n const stack: string[] = [];\n const sccs: string[][] = [];\n\n function strongconnect(v: string): void {\n indices.set(v, index);\n lowlinks.set(v, index);\n index++;\n stack.push(v);\n onStack.add(v);\n\n for (const w of adj.get(v) ?? []) {\n if (!indices.has(w)) {\n strongconnect(w);\n lowlinks.set(v, Math.min(lowlinks.get(v)!, lowlinks.get(w)!));\n } else if (onStack.has(w)) {\n lowlinks.set(v, Math.min(lowlinks.get(v)!, indices.get(w)!));\n }\n }\n\n if (lowlinks.get(v) === indices.get(v)) {\n const scc: string[] = [];\n let w: string;\n do {\n w = stack.pop()!;\n onStack.delete(w);\n scc.push(w);\n } while (w !== v);\n if (scc.length > 1) {\n sccs.push(scc);\n }\n }\n }\n\n for (const file of allFiles) {\n if (!indices.has(file)) {\n strongconnect(file);\n }\n }\n\n return sccs;\n}\n\n/**\n * Detect circular dependencies using Tarjan's SCC algorithm.\n * Each SCC with size > 1 is reported as a circular dependency chain.\n * Returns up to maxCycles results.\n */\nexport function findCircularDeps(\n graph: ImportGraph,\n maxCycles = 10,\n): CircularDependency[] {\n const sccs = findSCCs(graph);\n\n // Convert SCCs to circular dependency chains\n // Sort by size (smallest first — more actionable)\n sccs.sort((a, b) => a.length - b.length);\n\n const cycles: CircularDependency[] = [];\n for (const scc of sccs) {\n if (cycles.length >= maxCycles) break;\n // Create a chain by closing the loop\n cycles.push({ chain: [...scc, scc[0]] });\n }\n\n return cycles;\n}\n\n/** Directory patterns for classifying files into architectural layers */\nconst LAYER_PATTERNS: Array<{ name: string; pattern: RegExp }> = [\n { name: \"types\", pattern: /(?:^|\\/)types?\\// },\n { name: \"stores\", pattern: /(?:^|\\/)stores?\\// },\n { name: \"hooks\", pattern: /(?:^|\\/)hooks?\\// },\n { name: \"services\", pattern: /(?:^|\\/)(?:services?|api)\\// },\n { name: \"components\", pattern: /(?:^|\\/)components?\\// },\n { name: \"pages\", pattern: /(?:^|\\/)(?:pages?|app|routes?)\\// },\n { name: \"utils\", pattern: /(?:^|\\/)(?:utils?|lib|helpers?)\\// },\n { name: \"config\", pattern: /(?:^|\\/)config\\// },\n];\n\n/**\n * Classify files into architectural layers and determine their dependency ordering.\n * Returns both the layers and directed edges between them.\n */\nexport function detectArchitecturalLayers(graph: ImportGraph): { layers: ArchitecturalLayer[]; layerEdges: LayerEdge[] } {\n // Classify each internal file into a layer\n const layerFiles = new Map<string, string[]>();\n const fileToLayer = new Map<string, string>();\n\n for (const [filePath] of graph.centrality) {\n for (const { name, pattern } of LAYER_PATTERNS) {\n if (pattern.test(filePath)) {\n const files = layerFiles.get(name) ?? [];\n files.push(filePath);\n layerFiles.set(name, files);\n fileToLayer.set(filePath, name);\n break; // First match wins\n }\n }\n }\n\n // Track both directions: who imports each layer, and who each layer depends on\n const layerImportedBy = new Map<string, Set<string>>();\n const layerDependsOn = new Map<string, Set<string>>();\n for (const name of layerFiles.keys()) {\n layerImportedBy.set(name, new Set());\n layerDependsOn.set(name, new Set());\n }\n\n for (const edge of graph.edges) {\n if (edge.isExternal) continue;\n const fromLayer = fileToLayer.get(edge.from);\n const toLayer = fileToLayer.get(edge.to);\n if (fromLayer && toLayer && fromLayer !== toLayer) {\n layerImportedBy.get(toLayer)?.add(fromLayer);\n layerDependsOn.get(fromLayer)?.add(toLayer);\n }\n }\n\n // Build layer edges from dependsOn data\n const layerEdges: LayerEdge[] = [];\n const edgeSet = new Set<string>();\n for (const [from, deps] of layerDependsOn) {\n for (const to of deps) {\n const key = `${from}->${to}`;\n if (!edgeSet.has(key)) {\n edgeSet.add(key);\n layerEdges.push({ from, to });\n }\n }\n }\n\n // Build result sorted by importedByLayers descending (most foundational first)\n const layers: ArchitecturalLayer[] = [];\n for (const [name, files] of layerFiles) {\n layers.push({\n name,\n files,\n importedByLayers: layerImportedBy.get(name)?.size ?? 0,\n dependsOn: [...(layerDependsOn.get(name) ?? [])],\n });\n }\n\n // Sort: most imported layers first (foundational), then by name\n layers.sort((a, b) => b.importedByLayers - a.importedByLayers || a.name.localeCompare(b.name));\n\n return { layers, layerEdges };\n}\n\n/**\n * Compute instability metric (Robert C. Martin) for each file.\n * instability = fanOut / (fanIn + fanOut)\n * Returns files with instability > 0.7 and fanIn >= 3 (high-risk zones).\n */\nexport function computeInstability(graph: ImportGraph): FileInstability[] {\n // Count outgoing internal edges per file\n const fanOutMap = new Map<string, number>();\n for (const edge of graph.edges) {\n if (!edge.isExternal) {\n fanOutMap.set(edge.from, (fanOutMap.get(edge.from) ?? 0) + 1);\n }\n }\n\n const results: FileInstability[] = [];\n for (const [filePath, fanIn] of graph.inDegree) {\n const fanOut = fanOutMap.get(filePath) ?? 0;\n const total = fanIn + fanOut;\n if (total === 0) continue;\n const instability = fanOut / total;\n if (instability > 0.7 && fanIn >= 3) {\n results.push({ path: filePath, fanIn, fanOut, instability });\n }\n }\n\n // Sort by instability descending\n results.sort((a, b) => b.instability - a.instability);\n return results;\n}\n\n/**\n * Detect communities of tightly-connected files using label propagation.\n * Each file starts with a unique label; iteratively adopts the most common\n * label among its neighbors (both directions). Returns communities with size >= 3.\n */\nexport function detectCommunities(graph: ImportGraph): Community[] {\n // Build undirected adjacency from internal edges\n const adj = new Map<string, Set<string>>();\n const allFiles = new Set<string>();\n\n for (const edge of graph.edges) {\n if (edge.isExternal) continue;\n allFiles.add(edge.from);\n allFiles.add(edge.to);\n\n if (!adj.has(edge.from)) adj.set(edge.from, new Set());\n if (!adj.has(edge.to)) adj.set(edge.to, new Set());\n adj.get(edge.from)!.add(edge.to);\n adj.get(edge.to)!.add(edge.from);\n }\n\n const files = [...allFiles];\n if (files.length === 0) return [];\n\n // Initialize: each file gets its own numeric label\n const labels = new Map<string, number>();\n for (let i = 0; i < files.length; i++) {\n labels.set(files[i], i);\n }\n\n // Iterate label propagation (~10 rounds)\n for (let iter = 0; iter < 10; iter++) {\n let changed = false;\n // Shuffle order for better convergence\n const shuffled = [...files];\n for (let i = shuffled.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];\n }\n\n for (const file of shuffled) {\n const neighbors = adj.get(file);\n if (!neighbors || neighbors.size === 0) continue;\n\n // Count neighbor labels\n const labelCounts = new Map<number, number>();\n for (const neighbor of neighbors) {\n const lbl = labels.get(neighbor)!;\n labelCounts.set(lbl, (labelCounts.get(lbl) ?? 0) + 1);\n }\n\n // Find most common label\n let maxCount = 0;\n let bestLabel = labels.get(file)!;\n for (const [lbl, count] of labelCounts) {\n if (count > maxCount) {\n maxCount = count;\n bestLabel = lbl;\n }\n }\n\n if (bestLabel !== labels.get(file)) {\n labels.set(file, bestLabel);\n changed = true;\n }\n }\n\n if (!changed) break;\n }\n\n // Group files by label\n const groups = new Map<number, string[]>();\n for (const [file, label] of labels) {\n const group = groups.get(label) ?? [];\n group.push(file);\n groups.set(label, group);\n }\n\n // Filter to communities with size >= 3, derive labels from common dir prefix\n const communities: Community[] = [];\n let id = 0;\n for (const files of groups.values()) {\n if (files.length < 3) continue;\n const label = deriveLabel(files);\n communities.push({ id: id++, files: files.sort(), label });\n }\n\n // Sort by size descending\n communities.sort((a, b) => b.files.length - a.files.length);\n return communities;\n}\n\n/**\n * Derive a human-readable label from a group of file paths\n * by finding their common directory prefix.\n */\nfunction deriveLabel(files: string[]): string {\n if (files.length === 0) return \"unknown\";\n\n const dirs = files.map((f) => {\n const parts = f.split(\"/\");\n return parts.slice(0, -1).join(\"/\");\n });\n\n // Find common prefix\n const first = dirs[0];\n let prefixLen = first.length;\n for (const dir of dirs) {\n let i = 0;\n while (i < prefixLen && i < dir.length && first[i] === dir[i]) i++;\n prefixLen = i;\n }\n\n let common = first.slice(0, prefixLen);\n // Trim to last full directory segment\n if (common.includes(\"/\")) {\n common = common.slice(0, common.lastIndexOf(\"/\") + 1);\n }\n common = common.replace(/\\/$/, \"\");\n\n return common || files[0].split(\"/\")[0] || \"root\";\n}\n\n/**\n * Compute export coverage for each file — how many of its exports\n * are actually imported by other files in the project.\n */\nexport function computeExportCoverage(graph: ImportGraph): ExportCoverage[] {\n const usedExports = findUsedExports(graph.edges);\n\n // Count total named exports per file (from outgoing edges' importedNames at target)\n // We know a file exports a name if any edge targets it with that name\n const allExportsByFile = new Map<string, Set<string>>();\n\n for (const edge of graph.edges) {\n if (edge.isExternal) continue;\n for (const name of edge.importedNames) {\n if (!allExportsByFile.has(edge.to)) allExportsByFile.set(edge.to, new Set());\n allExportsByFile.get(edge.to)!.add(name);\n }\n }\n\n const results: ExportCoverage[] = [];\n for (const [file, exports] of allExportsByFile) {\n const totalExports = exports.size;\n if (totalExports === 0) continue;\n let usedCount = 0;\n for (const name of exports) {\n if (usedExports.has(`${file}::${name}`)) usedCount++;\n }\n results.push({\n file,\n totalExports,\n usedExports: usedCount,\n coverage: usedCount / totalExports,\n });\n }\n\n // Sort by coverage ascending (worst coverage first)\n results.sort((a, b) => a.coverage - b.coverage);\n return results;\n}\n","import path from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport type {\n CodeSnapshot,\n ContextAnalysis,\n DetectedContext,\n GeneratedFile,\n ProgressCallback,\n UserAnswers,\n} from \"./types.js\";\nimport { fileExists, readJsonFile, writeFileSafe } from \"./utils.js\";\nimport {\n buildMainContext,\n getMainContextFilename,\n} from \"./templates/main-context.js\";\nimport {\n buildCursorRules,\n renderCursorRule,\n} from \"./templates/cursor-rules.js\";\nimport {\n buildClaudeSkills,\n renderClaudeSkill,\n} from \"./templates/claude-skills.js\";\nimport { buildAiderContext } from \"./templates/aider-context.js\";\nimport { detectContext } from \"./detect.js\";\nimport { generateSnapshot } from \"./snapshot.js\";\n\n/**\n * Generate all context files based on detection, user answers, and snapshot.\n * Returns the list of files that were generated.\n * When dryRun is true, no files are written to disk.\n */\nexport async function generateFiles(\n ctx: DetectedContext,\n answers: UserAnswers,\n snapshot: CodeSnapshot | null,\n force: boolean = false,\n dryRun: boolean = false,\n analysis?: ContextAnalysis,\n generateSkills: boolean = false,\n onVerbose?: ProgressCallback,\n): Promise<GeneratedFile[]> {\n const files: GeneratedFile[] = [];\n\n // 1. Main context file\n const mainFilename = getMainContextFilename(answers.ide);\n const mainPath = path.join(ctx.rootDir, mainFilename);\n\n // Aider uses YAML format, everything else uses markdown\n const mainContent =\n answers.ide === \"aider\"\n ? buildAiderContext(ctx, answers, snapshot, analysis)\n : buildMainContext(ctx, answers, snapshot, analysis);\n\n files.push({\n path: mainFilename,\n content: mainContent,\n existed: await fileExists(mainPath),\n });\n onVerbose?.(`Prepared ${mainFilename} (${mainContent.length} bytes)`);\n\n // 2. Cursor-specific scoped rules\n if (answers.ide === \"cursor\") {\n const rules = buildCursorRules(ctx, answers, analysis);\n for (const rule of rules) {\n const rulePath = `.cursor/rules/${rule.filename}`;\n const absPath = path.join(ctx.rootDir, rulePath);\n const ruleContent = renderCursorRule(rule);\n files.push({\n path: rulePath,\n content: ruleContent,\n existed: await fileExists(absPath),\n });\n onVerbose?.(`Prepared ${rulePath} (${ruleContent.length} bytes)`);\n }\n }\n\n // 3. Claude Code skills\n if (generateSkills) {\n const pkgJson = await readJsonFile(path.join(ctx.rootDir, \"package.json\"));\n const scripts = (pkgJson?.scripts as Record<string, string>) ?? undefined;\n const skills = buildClaudeSkills(ctx, answers, analysis, scripts);\n for (const skill of skills) {\n const skillPath = `.claude/skills/${skill.name}/SKILL.md`;\n const absPath = path.join(ctx.rootDir, skillPath);\n const skillContent = renderClaudeSkill(skill);\n files.push({\n path: skillPath,\n content: skillContent,\n existed: await fileExists(absPath),\n });\n onVerbose?.(`Prepared ${skillPath} (${skillContent.length} bytes)`);\n }\n }\n\n // For OpenCode, also generate CLAUDE.md as fallback if main file is AGENTS.md\n if (answers.ide === \"opencode\") {\n const claudePath = path.join(ctx.rootDir, \"CLAUDE.md\");\n const claudeExists = await fileExists(claudePath);\n if (!claudeExists) {\n files.push({\n path: \"CLAUDE.md\",\n content: `# ${path.basename(ctx.rootDir)}\\n\\n> See AGENTS.md for full project context.\\n`,\n existed: false,\n });\n }\n }\n\n // Monorepo per-package context files\n if (\n answers.generatePerPackage &&\n ctx.monorepo &&\n ctx.monorepo.packages.length > 0\n ) {\n const pkgMainFilename =\n answers.ide === \"aider\" ? \".aider.conf.yml\" : getMainContextFilename(answers.ide);\n\n for (const pkg of ctx.monorepo.packages) {\n const pkgRootDir = path.join(ctx.rootDir, pkg.path);\n\n // Detect context for this specific package\n const pkgCtx = await detectContext(pkgRootDir);\n\n // Generate snapshot scoped to this package\n let pkgSnapshot: CodeSnapshot | null = null;\n if (answers.generateSnapshot) {\n pkgSnapshot = await generateSnapshot(pkgCtx, []);\n if (pkgSnapshot.entries.length === 0) pkgSnapshot = null;\n }\n\n // Build scoped answers for this package\n const pkgAnswers: UserAnswers = {\n ...answers,\n projectPurpose: `${pkg.name} — part of the ${path.basename(ctx.rootDir)} monorepo. ${answers.projectPurpose}`,\n generatePerPackage: false, // don't recurse\n };\n\n const pkgContent =\n answers.ide === \"aider\"\n ? buildAiderContext(pkgCtx, pkgAnswers, pkgSnapshot)\n : buildMainContext(pkgCtx, pkgAnswers, pkgSnapshot);\n\n const pkgFilePath = path.join(pkg.path, pkgMainFilename);\n const pkgAbsPath = path.join(ctx.rootDir, pkgFilePath);\n\n files.push({\n path: pkgFilePath,\n content: pkgContent,\n existed: await fileExists(pkgAbsPath),\n });\n }\n }\n\n // Dry run: return files without writing anything\n if (dryRun) {\n return files;\n }\n\n // Check for existing files and ask before overwriting\n const existingFiles = files.filter((f) => f.existed);\n if (existingFiles.length > 0 && !force) {\n p.log.warn(\n `The following files already exist:\\n${existingFiles.map((f) => ` - ${f.path}`).join(\"\\n\")}`,\n );\n\n const overwrite = await p.confirm({\n message: \"Overwrite existing files?\",\n });\n\n if (p.isCancel(overwrite) || !overwrite) {\n // Only write new files\n const newFiles = files.filter((f) => !f.existed);\n if (newFiles.length === 0) {\n p.log.info(\"No new files to write. Exiting.\");\n return [];\n }\n p.log.info(`Writing ${newFiles.length} new file(s), skipping existing.`);\n for (const file of newFiles) {\n await writeFileSafe(path.join(ctx.rootDir, file.path), file.content);\n }\n return newFiles;\n }\n }\n\n // Write all files\n for (const file of files) {\n await writeFileSafe(path.join(ctx.rootDir, file.path), file.content);\n onVerbose?.(`Wrote ${file.path}`);\n }\n\n return files;\n}\n","import type { DetectedContext } from \"../types.js\";\n\ninterface FrameworkHint {\n /** Framework name (matches DetectedFramework.name) */\n name: string;\n /** Markdown conventions to include in context files */\n conventions: string[];\n}\n\n/**\n * Get framework-specific conventions based on detected context.\n * Returns markdown lines (bullet points) to embed in context files.\n */\nexport function getFrameworkHints(ctx: DetectedContext): string[] {\n const hints: string[] = [];\n const frameworkNames = new Set(ctx.frameworks.map((f) => f.name));\n\n for (const gen of HINT_GENERATORS) {\n if (frameworkNames.has(gen.name)) {\n const lines = gen.getHints(ctx);\n if (lines.length > 0) hints.push(...lines);\n }\n }\n\n return hints;\n}\n\n/**\n * Get framework hints as a rendered markdown section.\n * Returns empty string if no hints are applicable.\n */\nexport function getFrameworkHintsSection(ctx: DetectedContext): string {\n const hints = getFrameworkHints(ctx);\n if (hints.length === 0) return \"\";\n\n const lines = [\"## Framework Conventions\", \"\"];\n for (const h of hints) {\n lines.push(h);\n }\n lines.push(\"\");\n return lines.join(\"\\n\");\n}\n\n// --- Hint generators ---\n\ninterface HintGenerator {\n name: string;\n getHints: (ctx: DetectedContext) => string[];\n}\n\nconst HINT_GENERATORS: HintGenerator[] = [\n {\n name: \"Next.js\",\n getHints: (ctx) => {\n const hints: string[] = [];\n const hasAppDir = ctx.directories.some(\n (d) => d === \"app\" || d.startsWith(\"app/\") || d === \"src/app\",\n );\n const hasPagesDir = ctx.directories.some(\n (d) => d === \"pages\" || d.startsWith(\"pages/\") || d === \"src/pages\",\n );\n\n if (hasAppDir && !hasPagesDir) {\n hints.push(\"### Next.js (App Router)\");\n hints.push(\"\");\n hints.push(\n \"- **App Router** — all routes in `app/` use React Server Components by default\",\n );\n hints.push(\n '- Add `\"use client\"` directive at the top of files that need browser APIs, hooks, or event handlers',\n );\n hints.push(\n \"- `layout.tsx` wraps child routes; `page.tsx` is the route's UI; `loading.tsx` / `error.tsx` for boundaries\",\n );\n hints.push(\n \"- Data fetching: `async` server components with direct `fetch()` or DB calls (no `getServerSideProps`)\",\n );\n hints.push(\n \"- Route handlers: `app/api/*/route.ts` with exported `GET`, `POST`, etc. functions\",\n );\n hints.push(\n \"- Middleware in `middleware.ts` at project root for auth, redirects, rewrites\",\n );\n hints.push(\n \"- Use `next/image` for optimized images, `next/font` for font loading\",\n );\n } else if (hasPagesDir && !hasAppDir) {\n hints.push(\"### Next.js (Pages Router)\");\n hints.push(\"\");\n hints.push(\"- **Pages Router** — routes in `pages/` directory\");\n hints.push(\n \"- `getServerSideProps` for server-side data fetching, `getStaticProps` for static generation\",\n );\n hints.push(\n \"- `_app.tsx` for global layout/providers, `_document.tsx` for HTML customization\",\n );\n hints.push(\"- API routes in `pages/api/`\");\n } else if (hasAppDir && hasPagesDir) {\n hints.push(\"### Next.js (Hybrid — App + Pages Router)\");\n hints.push(\"\");\n hints.push(\n \"- Both `app/` (App Router) and `pages/` (Pages Router) coexist — new routes should use App Router\",\n );\n hints.push(\n '- App Router components are server components by default; add `\"use client\"` for client components',\n );\n hints.push(\n \"- Pages Router uses `getServerSideProps` / `getStaticProps` for data fetching\",\n );\n } else {\n hints.push(\"### Next.js\");\n hints.push(\"\");\n hints.push(\n \"- Use `next/image` for optimized images, `next/font` for font loading\",\n );\n hints.push(\n \"- Middleware in `middleware.ts` at project root for auth, redirects, rewrites\",\n );\n }\n return hints;\n },\n },\n {\n name: \"Express\",\n getHints: () => [\n \"### Express\",\n \"\",\n \"- Middleware chain: `app.use()` for global, router-level for scoped. Order matters.\",\n \"- Error handling: define a 4-arg middleware `(err, req, res, next)` at the end of the chain\",\n \"- Organize routes with `express.Router()` in separate files, mount with `app.use('/prefix', router)`\",\n \"- Validate request bodies/params at the route level (e.g. with zod, joi, or express-validator)\",\n \"- Use `async` handlers with try/catch or an async wrapper to avoid unhandled promise rejections\",\n \"- Set `res.status()` before `res.json()` — don't rely on defaults for error responses\",\n ],\n },\n {\n name: \"Fastify\",\n getHints: () => [\n \"### Fastify\",\n \"\",\n \"- Plugin architecture: register plugins with `fastify.register()` for encapsulation\",\n \"- Schema-based validation: use JSON Schema for request/response validation (built-in)\",\n \"- Hooks: `onRequest`, `preHandler`, `onSend` etc. for request lifecycle\",\n \"- Use `fastify-plugin` for plugins that should not be encapsulated\",\n \"- Serialization: define response schemas for 2x faster JSON serialization\",\n ],\n },\n {\n name: \"Hono\",\n getHints: () => [\n \"### Hono\",\n \"\",\n \"- Middleware with `app.use()` — compose with `c.next()` pattern\",\n \"- Validators: use `hono/validator` or `@hono/zod-validator` for type-safe request parsing\",\n \"- Context (`c`): `c.json()`, `c.text()`, `c.html()` for responses; `c.req` for request\",\n \"- Supports multiple runtimes (Node, Deno, Bun, Cloudflare Workers) — avoid Node-specific APIs\",\n ],\n },\n {\n name: \"NestJS\",\n getHints: () => [\n \"### NestJS\",\n \"\",\n \"- **Modules** organize the app into cohesive blocks; every feature gets a module\",\n \"- **Controllers** handle HTTP requests (decorators: `@Get()`, `@Post()`, etc.)\",\n \"- **Providers** (services) hold business logic — injected via constructor DI\",\n \"- **Guards** for auth (`@UseGuards()`), **Pipes** for validation (`@UsePipes()`)\",\n \"- **Interceptors** for response transformation, logging, caching\",\n \"- DTOs with `class-validator` decorators for request validation\",\n \"- Use `@Injectable()` on all services/providers\",\n ],\n },\n {\n name: \"Expo\",\n getHints: (ctx) => {\n const hasRN = ctx.frameworks.some((f) => f.name === \"React Native\");\n const hints = [\"### Expo / React Native\", \"\"];\n hints.push(\n \"- **expo-router** for file-based routing (if using); Stack, Tabs, Drawer navigators\",\n );\n hints.push(\n \"- Expo Go has limited native module support — some packages require a dev build (`npx expo run:ios`)\",\n );\n hints.push(\n \"- Use `expo-constants`, `expo-device` etc. instead of raw RN APIs when available\",\n );\n hints.push(\n \"- Platform-specific files: `*.ios.tsx` / `*.android.tsx` or `Platform.select()`\",\n );\n if (hasRN) {\n hints.push(\n \"- **Reanimated**: worklet functions need the `\\\"worklet\\\"` directive on the first line\",\n );\n hints.push(\n \"- Avoid `FadeIn`/`FadeOut` entering/exiting animations on conditionally rendered components — they cause flashes\",\n );\n }\n return hints;\n },\n },\n {\n name: \"React Native\",\n getHints: (ctx) => {\n // Only emit if Expo is NOT also detected (Expo handler covers RN+Expo)\n if (ctx.frameworks.some((f) => f.name === \"Expo\")) return [];\n return [\n \"### React Native\",\n \"\",\n \"- Use `StyleSheet.create()` for styles — avoid inline style objects in render\",\n \"- Platform-specific: `*.ios.tsx` / `*.android.tsx` or `Platform.select()`\",\n \"- **Reanimated**: worklet functions need the `\\\"worklet\\\"` directive\",\n \"- Navigation: React Navigation with Stack/Tab/Drawer navigators\",\n \"- Test with both iOS and Android — layout behavior differs\",\n ];\n },\n },\n {\n name: \"React\",\n getHints: (ctx) => {\n // Skip if Next.js, Expo, or React Native is detected (they have their own hints)\n const skip = [\"Next.js\", \"Expo\", \"React Native\"];\n if (ctx.frameworks.some((f) => skip.includes(f.name))) return [];\n return [\n \"### React\",\n \"\",\n \"- Functional components with hooks — no class components\",\n \"- Use `React.memo()` for expensive renders, `useMemo`/`useCallback` for referential stability\",\n \"- Lift state up or use context for shared state; avoid prop drilling beyond 2-3 levels\",\n \"- Prefer controlled components for forms\",\n \"- Use `Suspense` boundaries with `lazy()` for code splitting\",\n ];\n },\n },\n {\n name: \"Vue\",\n getHints: () => [\n \"### Vue\",\n \"\",\n \"- Composition API with `<script setup>` for new components\",\n \"- Reactive state: `ref()` for primitives, `reactive()` for objects\",\n \"- `computed()` for derived state, `watch()` / `watchEffect()` for side effects\",\n \"- Props: define with `defineProps<T>()`, emits with `defineEmits<T>()`\",\n \"- Use `provide` / `inject` for deep dependency injection\",\n ],\n },\n {\n name: \"Nuxt\",\n getHints: () => [\n \"### Nuxt\",\n \"\",\n \"- Auto-imports: components, composables, and utils are auto-imported — no manual import needed\",\n \"- File-based routing in `pages/` — dynamic params with `[id].vue` syntax\",\n \"- Data fetching: `useFetch()` / `useAsyncData()` — they handle SSR hydration automatically\",\n \"- Server routes in `server/api/` — auto-registered, use `defineEventHandler()`\",\n \"- Middleware in `middleware/` — `defineNuxtRouteMiddleware()` for route guards\",\n \"- State: `useState()` for SSR-safe shared state, Pinia for complex stores\",\n ],\n },\n {\n name: \"Svelte\",\n getHints: (ctx) => {\n if (ctx.frameworks.some((f) => f.name === \"SvelteKit\")) return [];\n return [\n \"### Svelte\",\n \"\",\n \"- Reactive declarations with `$:` for derived state\",\n \"- Props: `export let propName` in component script\",\n \"- Stores: `writable()`, `readable()`, `derived()` — auto-subscribe with `$store` syntax\",\n \"- Use `{#if}`, `{#each}`, `{#await}` blocks for conditional/list/async rendering\",\n ];\n },\n },\n {\n name: \"SvelteKit\",\n getHints: () => [\n \"### SvelteKit\",\n \"\",\n \"- File-based routing in `src/routes/` — `+page.svelte`, `+layout.svelte`, `+server.ts`\",\n \"- `+page.ts` (universal) or `+page.server.ts` (server-only) for `load` functions\",\n \"- Form actions in `+page.server.ts` with `actions` export for progressive enhancement\",\n \"- Hooks in `src/hooks.server.ts` for auth, session, error handling\",\n \"- Use `$app/stores` for page, navigating, updated stores\",\n ],\n },\n {\n name: \"Angular\",\n getHints: () => [\n \"### Angular\",\n \"\",\n \"- Components, services, pipes, directives all use decorators (`@Component`, `@Injectable`, etc.)\",\n \"- Dependency injection: provide services in module or component `providers` array\",\n \"- RxJS Observables for async data — use `async` pipe in templates, unsubscribe on destroy\",\n \"- Lazy-load feature modules with `loadChildren` in routes\",\n \"- Use Angular CLI (`ng generate`) for scaffolding\",\n ],\n },\n {\n name: \"Django\",\n getHints: () => [\n \"### Django\",\n \"\",\n \"- Apps structure: each feature is a Django app with `models.py`, `views.py`, `urls.py`, `admin.py`\",\n \"- Models: define in `models.py`, create migrations with `python manage.py makemigrations`\",\n \"- Views: function-based (FBV) or class-based (CBV) — CBV for CRUD, FBV for custom logic\",\n \"- URL routing in `urls.py` using `path()` and `include()` for app-level URLs\",\n \"- Templates in `templates/` — use template inheritance with `{% extends %}` and `{% block %}`\",\n \"- Management commands in `management/commands/` for custom CLI tasks\",\n \"- Settings: use `django-environ` or `python-decouple` for environment-based config\",\n ],\n },\n {\n name: \"Flask\",\n getHints: () => [\n \"### Flask\",\n \"\",\n \"- Blueprints for modular route organization — register with `app.register_blueprint()`\",\n \"- Use application factory pattern (`create_app()`) for testing and config flexibility\",\n \"- Error handlers with `@app.errorhandler(404)` etc.\",\n \"- Use Flask-SQLAlchemy for ORM, Flask-Migrate for database migrations\",\n \"- Request context: `request`, `g`, `session` globals — available inside request handlers\",\n ],\n },\n {\n name: \"FastAPI\",\n getHints: () => [\n \"### FastAPI\",\n \"\",\n \"- **Dependency injection**: use `Depends()` for shared logic (auth, DB sessions, validation)\",\n \"- **Pydantic models** for request/response schemas — automatic validation and OpenAPI docs\",\n \"- Async endpoints by default (`async def`); use sync `def` only for blocking I/O with threadpool\",\n \"- Routers: `APIRouter()` for modular route organization, mount with `app.include_router()`\",\n \"- Middleware with `@app.middleware(\\\"http\\\")` or Starlette middleware classes\",\n \"- Background tasks with `BackgroundTasks` parameter for fire-and-forget work\",\n \"- Auto-generated docs at `/docs` (Swagger) and `/redoc`\",\n ],\n },\n {\n name: \"Prisma\",\n getHints: () => [\n \"### Prisma\",\n \"\",\n \"- Schema in `prisma/schema.prisma` — run `npx prisma generate` after changes\",\n \"- Migrations: `npx prisma migrate dev` for development, `npx prisma migrate deploy` for production\",\n \"- Use `prisma.$transaction()` for atomic operations\",\n \"- Relation queries: use `include` for eager loading, `select` for field filtering\",\n ],\n },\n {\n name: \"Drizzle\",\n getHints: () => [\n \"### Drizzle\",\n \"\",\n \"- Schema defined in TypeScript — type-safe queries with no code generation step\",\n \"- Migrations: `drizzle-kit generate` then `drizzle-kit migrate`\",\n \"- Use `db.select()`, `db.insert()`, `db.update()`, `db.delete()` for queries\",\n \"- Relations: define with `relations()` helper for type-safe joins\",\n ],\n },\n {\n name: \"Tailwind CSS\",\n getHints: (ctx) => {\n // Skip if NativeWind is detected (Expo/RN handles it)\n if (ctx.frameworks.some((f) => f.name === \"NativeWind\")) return [];\n return [\n \"### Tailwind CSS\",\n \"\",\n \"- Utility-first: compose styles with `className` — avoid custom CSS unless truly needed\",\n \"- Use `@apply` sparingly in CSS modules for repeated patterns\",\n \"- Responsive: mobile-first with `sm:`, `md:`, `lg:` breakpoint prefixes\",\n \"- Dark mode: `dark:` variant (class or media strategy per `tailwind.config`)\",\n \"- Extract reusable component classes into shared components, not `@apply` blocks\",\n ];\n },\n },\n {\n name: \"Electron\",\n getHints: () => [\n \"### Electron\",\n \"\",\n \"- **Main process** (Node.js) and **renderer process** (Chromium) — communicate via IPC\",\n \"- Use `contextBridge` + `preload.js` to expose safe APIs to renderer (no `nodeIntegration`)\",\n \"- `ipcMain.handle()` / `ipcRenderer.invoke()` for async request-response patterns\",\n \"- Package with `electron-builder` or `electron-forge`\",\n ],\n },\n];\n","import type { ArchitecturalLayer, CodeSnapshot, ContextAnalysis, DetectedContext, LayerEdge, UserAnswers } from \"../types.js\";\nimport { summarizeDetection } from \"../detect.js\";\nimport { getFrameworkHintsSection } from \"./framework-hints.js\";\n\n/**\n * Build the main context file content (CLAUDE.md, AGENTS.md, or CONTEXT.md).\n */\nexport function buildMainContext(\n ctx: DetectedContext,\n answers: UserAnswers,\n snapshot: CodeSnapshot | null,\n analysis?: ContextAnalysis,\n): string {\n const projectName = getProjectName(ctx);\n const stackSummary = answers.stackConfirmed\n ? summarizeDetection(ctx)\n : answers.stackCorrections || summarizeDetection(ctx);\n\n const sections: string[] = [];\n\n // -- Header --\n sections.push(`# ${projectName}`);\n sections.push(\"\");\n\n // -- Maintenance directive --\n sections.push(\n \"> **Keep this file up to date.** When you change the architecture, add a dependency, create a new pattern, or learn a gotcha, update this file in the same step. This is the source of truth for how the project works.\",\n );\n\n if (answers.ide === \"cursor\") {\n sections.push(\n \"> Scoped rules are in `.cursor/rules/` -- update them when conventions change.\",\n );\n }\n\n sections.push(\"\");\n\n // -- What Is This --\n sections.push(\"## What Is This\");\n sections.push(\"\");\n sections.push(answers.projectPurpose);\n sections.push(\"\");\n\n // -- Tech Stack --\n sections.push(\"## Tech Stack\");\n sections.push(\"\");\n sections.push(buildTechStackSection(ctx, stackSummary));\n sections.push(\"\");\n\n // -- Framework Conventions --\n const fwHints = getFrameworkHintsSection(ctx);\n if (fwHints) {\n sections.push(fwHints);\n }\n\n // -- Project Structure --\n if (ctx.directories.length > 0) {\n sections.push(\"## Project Structure\");\n sections.push(\"\");\n sections.push(\"```\");\n sections.push(buildStructureTree(ctx));\n sections.push(\"```\");\n sections.push(\"\");\n }\n\n // -- Monorepo Structure --\n if (ctx.monorepo && ctx.monorepo.packages.length > 0) {\n sections.push(\"## Monorepo Structure\");\n sections.push(\"\");\n sections.push(\n `${ctx.monorepo.type} workspace with ${ctx.monorepo.packages.length} packages:`,\n );\n sections.push(\"\");\n for (const pkg of ctx.monorepo.packages) {\n const fws =\n pkg.frameworks.length > 0\n ? ` — ${pkg.frameworks.map((f) => f.name).join(\", \")}`\n : \"\";\n sections.push(`- **${pkg.name}** (\\`${pkg.path}\\`)${fws}`);\n }\n sections.push(\"\");\n }\n\n // -- Code Snapshot --\n if (snapshot?.markdown) {\n sections.push(\"## Code Snapshot\");\n sections.push(\"\");\n sections.push(\n \"<!-- CODE SNAPSHOT (auto-generated, update when types/stores/services change) -->\",\n );\n sections.push(\"\");\n sections.push(snapshot.markdown);\n sections.push(\"\");\n sections.push(\"<!-- /CODE SNAPSHOT -->\");\n sections.push(\"\");\n }\n\n // -- Key Files (hub files) --\n if (analysis?.hubFiles && analysis.hubFiles.length > 0) {\n // Build instability lookup for flagging risky files\n const instabilityMap = new Map<string, number>();\n if (analysis.instabilities) {\n for (const inst of analysis.instabilities) {\n instabilityMap.set(inst.path, inst.instability);\n }\n }\n\n sections.push(\"## Key Files\");\n sections.push(\"\");\n sections.push(\n \"These are the most interconnected files. Read these first for architectural understanding.\",\n );\n sections.push(\"\");\n sections.push(\"| File | Imported By | Stability |\");\n sections.push(\"|------|-------------|-----------|\");\n for (const hub of analysis.hubFiles) {\n const inst = instabilityMap.get(hub.path);\n const stabilityCell = inst != null\n ? `${(inst * 100).toFixed(0)}% unstable ⚠️`\n : \"stable\";\n sections.push(\n `| \\`${hub.path}\\` | ${hub.importedBy} file${hub.importedBy === 1 ? \"\" : \"s\"} | ${stabilityCell} |`,\n );\n }\n sections.push(\"\");\n }\n\n // -- Architecture (layer ordering) --\n if (analysis?.layers && analysis.layers.length > 1) {\n sections.push(\"## Architecture\");\n sections.push(\"\");\n const diagram = renderArchitectureDiagram(analysis.layers, analysis.layerEdges ?? []);\n sections.push(diagram);\n sections.push(\"\");\n }\n\n // -- Recently Active Files --\n if (analysis?.gitActivity && analysis.gitActivity.hotFiles.length > 0) {\n sections.push(\"## Recently Active Files\");\n sections.push(\"\");\n sections.push(\"| File | Commits (90d) | Last Changed |\");\n sections.push(\"|------|--------------|--------------|\");\n for (const hot of analysis.gitActivity.hotFiles.slice(0, 10)) {\n sections.push(\n `| \\`${hot.path}\\` | ${hot.commits} | ${hot.lastChanged} |`,\n );\n }\n sections.push(\"\");\n }\n\n // -- Change Coupling --\n if (analysis?.gitActivity?.changeCoupling && analysis.gitActivity.changeCoupling.length > 0) {\n sections.push(\"## Change Coupling\");\n sections.push(\"\");\n sections.push(\n \"Files that frequently change together. Consider whether they should be colocated or decoupled.\",\n );\n sections.push(\"\");\n sections.push(\"| File A | File B | Co-changes | Confidence |\");\n sections.push(\"|--------|--------|------------|------------|\");\n for (const pair of analysis.gitActivity.changeCoupling) {\n sections.push(\n `| \\`${pair.fileA}\\` | \\`${pair.fileB}\\` | ${pair.coChangeCount} | ${(pair.confidence * 100).toFixed(0)}% |`,\n );\n }\n sections.push(\"\");\n }\n\n // -- Circular Dependencies --\n if (analysis?.circularDeps && analysis.circularDeps.length > 0) {\n sections.push(\"## Circular Dependencies\");\n sections.push(\"\");\n sections.push(\n \"> These circular import chains may cause unexpected behavior when modified.\",\n );\n sections.push(\"\");\n for (const dep of analysis.circularDeps) {\n sections.push(`- ${dep.chain.map((f) => `\\`${f}\\``).join(\" -> \")}`);\n }\n sections.push(\"\");\n }\n\n // -- Export Coverage --\n if (analysis?.exportCoverage && analysis.exportCoverage.length > 0) {\n const underCovered = analysis.exportCoverage.filter((e) => e.coverage < 1);\n if (underCovered.length > 0) {\n sections.push(\"## Export Coverage\");\n sections.push(\"\");\n sections.push(\n \"Files with unused exports. Consider removing dead exports to reduce surface area.\",\n );\n sections.push(\"\");\n sections.push(\"| File | Used | Total | Coverage |\");\n sections.push(\"|------|------|-------|----------|\");\n for (const entry of underCovered.slice(0, 10)) {\n sections.push(\n `| \\`${entry.file}\\` | ${entry.usedExports} | ${entry.totalExports} | ${(entry.coverage * 100).toFixed(0)}% |`,\n );\n }\n sections.push(\"\");\n }\n }\n\n // -- Module Clusters --\n if (analysis?.communities && analysis.communities.length > 0) {\n sections.push(\"## Module Clusters\");\n sections.push(\"\");\n sections.push(\n \"Automatically detected groups of tightly-connected files.\",\n );\n sections.push(\"\");\n for (const community of analysis.communities) {\n sections.push(`- **${community.label}** (${community.files.length} files): ${community.files.map((f) => `\\`${f}\\``).join(\", \")}`);\n }\n sections.push(\"\");\n }\n\n // -- Key Patterns --\n if (answers.keyPatterns) {\n sections.push(\"## Key Patterns\");\n sections.push(\"\");\n // Split on newlines or periods to create bullet points\n const patterns = answers.keyPatterns\n .split(/[.\\n]/)\n .map((s) => s.trim())\n .filter(Boolean);\n for (const p of patterns) {\n sections.push(`- ${p}`);\n }\n sections.push(\"\");\n }\n\n // -- Gotchas --\n if (answers.gotchas) {\n sections.push(\"## Gotchas\");\n sections.push(\"\");\n const gotchas = answers.gotchas\n .split(/[.\\n]/)\n .map((s) => s.trim())\n .filter(Boolean);\n for (const g of gotchas) {\n sections.push(`- ${g}`);\n }\n sections.push(\"\");\n }\n\n // -- Development --\n sections.push(\"## Development\");\n sections.push(\"\");\n sections.push(buildDevSection(ctx));\n sections.push(\"\");\n\n return sections.join(\"\\n\").trimEnd() + \"\\n\";\n}\n\n/**\n * Render an ASCII architecture diagram using Unicode box-drawing characters.\n * Falls back to inline `types → stores → ...` if >6 layers or 0 edges.\n */\nfunction renderArchitectureDiagram(layers: ArchitecturalLayer[], layerEdges: LayerEdge[]): string {\n // Fallback to inline rendering for edge cases\n if (layers.length > 6 || layerEdges.length === 0) {\n const layerNames = layers.map((l) => `\\`${l.name}\\``);\n return \"Dependency flow (foundational → consumer):\\n\\n\" + layerNames.join(\" → \");\n }\n\n // Assign layers to rows: foundational layers first (most importedByLayers),\n // max 3 per row\n const maxPerRow = 3;\n const rows: ArchitecturalLayer[][] = [];\n for (let i = 0; i < layers.length; i += maxPerRow) {\n rows.push(layers.slice(i, i + maxPerRow));\n }\n\n // Build the box diagram\n const boxWidth = 14; // Fixed box inner width\n const boxOuter = boxWidth + 2; // +2 for side borders\n const gap = 4; // Space between boxes\n\n const layerSet = new Set(layers.map((l) => l.name));\n const layerRowIndex = new Map<string, number>();\n const layerColIndex = new Map<string, number>();\n for (let r = 0; r < rows.length; r++) {\n for (let c = 0; c < rows[r].length; c++) {\n layerRowIndex.set(rows[r][c].name, r);\n layerColIndex.set(rows[r][c].name, c);\n }\n }\n\n // Classify edges as same-row (horizontal) or cross-row (vertical)\n const horizontalEdges: LayerEdge[] = [];\n const verticalEdges: LayerEdge[] = [];\n for (const edge of layerEdges) {\n if (!layerSet.has(edge.from) || !layerSet.has(edge.to)) continue;\n const fromRow = layerRowIndex.get(edge.from)!;\n const toRow = layerRowIndex.get(edge.to)!;\n if (fromRow === toRow) {\n horizontalEdges.push(edge);\n } else {\n verticalEdges.push(edge);\n }\n }\n\n const lines: string[] = [];\n lines.push(\"```\");\n\n for (let r = 0; r < rows.length; r++) {\n const row = rows[r];\n\n // Top border: ┌──────────────┐\n const topLine = row\n .map((l) => {\n const name = l.name;\n const pad = boxWidth - name.length;\n return \"┌\" + \"─\".repeat(boxWidth) + \"┐\";\n })\n .join(\" \".repeat(gap));\n lines.push(topLine);\n\n // Content: │ types │\n const midLine = row\n .map((l) => {\n const name = l.name;\n const padLeft = Math.floor((boxWidth - name.length) / 2);\n const padRight = boxWidth - name.length - padLeft;\n return \"│\" + \" \".repeat(padLeft) + name + \" \".repeat(padRight) + \"│\";\n })\n .join(\" \".repeat(gap));\n lines.push(midLine);\n\n // Bottom border: └──────────────┘\n const botLine = row\n .map(() => \"└\" + \"─\".repeat(boxWidth) + \"┘\")\n .join(\" \".repeat(gap));\n lines.push(botLine);\n\n // Draw vertical arrows between rows\n if (r < rows.length - 1) {\n const nextRow = rows[r + 1];\n // Find vertical edges from this row to next row\n const downEdges = verticalEdges.filter((e) => {\n const fromR = layerRowIndex.get(e.from)!;\n const toR = layerRowIndex.get(e.to)!;\n return (fromR === r && toR === r + 1) || (fromR === r + 1 && toR === r);\n });\n\n if (downEdges.length > 0) {\n // Draw connector lines (│ and ▼)\n const rowWidth = row.length * boxOuter + (row.length - 1) * gap;\n const arrowLine1 = buildArrowLine(row, \"│\", boxOuter, gap, rowWidth);\n const arrowLine2 = buildArrowLine(nextRow.length > row.length ? nextRow : row, \"▼\", boxOuter, gap, rowWidth);\n lines.push(arrowLine1);\n lines.push(arrowLine2);\n }\n }\n }\n\n // Add horizontal arrow legend for same-row dependencies\n if (horizontalEdges.length > 0) {\n lines.push(\"\");\n for (const edge of horizontalEdges) {\n lines.push(` ${edge.from} ────▶ ${edge.to}`);\n }\n }\n\n lines.push(\"```\");\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Build a line with a character centered under each box in a row.\n */\nfunction buildArrowLine(row: ArchitecturalLayer[], char: string, boxOuter: number, gap: number, _totalWidth: number): string {\n const parts: string[] = [];\n for (let c = 0; c < row.length; c++) {\n const center = Math.floor(boxOuter / 2);\n if (c > 0) {\n // Add gap spacing\n parts.push(\" \".repeat(gap));\n }\n parts.push(\" \".repeat(center) + char + \" \".repeat(boxOuter - center - 1));\n }\n return parts.join(\"\");\n}\n\nfunction getProjectName(ctx: DetectedContext): string {\n // Extract from directory name\n const dirName = ctx.rootDir.split(\"/\").pop() ?? \"Project\";\n // Capitalize first letter\n return dirName.charAt(0).toUpperCase() + dirName.slice(1);\n}\n\nfunction buildTechStackSection(ctx: DetectedContext, summary: string): string {\n const lines: string[] = [];\n\n if (ctx.frameworks.length > 0) {\n for (const fw of ctx.frameworks) {\n const ver = fw.version ? ` ${fw.version}` : \"\";\n const usage = fw.importCount != null ? ` (used in ${fw.importCount} file${fw.importCount === 1 ? \"\" : \"s\"})` : \"\";\n lines.push(`- **${fw.name}**${ver}${usage}`);\n }\n }\n\n if (ctx.hasTypeScript) {\n lines.push(\"- **TypeScript**\");\n }\n\n if (ctx.linter !== \"none\") {\n const name = ctx.linter.charAt(0).toUpperCase() + ctx.linter.slice(1);\n lines.push(`- **${name}** (linter/formatter)`);\n }\n\n if (ctx.packageManager !== \"none\") {\n lines.push(`- **${ctx.packageManager}** (package manager)`);\n }\n\n if (lines.length === 0) {\n lines.push(`Stack: ${summary}`);\n }\n\n return lines.join(\"\\n\");\n}\n\nfunction buildStructureTree(ctx: DetectedContext): string {\n // Group directories by top-level\n const lines: string[] = [];\n const grouped = new Map<string, string[]>();\n\n for (const dir of ctx.directories) {\n const parts = dir.split(\"/\");\n if (parts.length === 1) {\n if (!grouped.has(dir)) grouped.set(dir, []);\n } else {\n const parent = parts[0];\n const child = parts.slice(1).join(\"/\");\n const children = grouped.get(parent) ?? [];\n children.push(child);\n grouped.set(parent, children);\n }\n }\n\n for (const [dir, children] of grouped) {\n lines.push(`${dir}/`);\n for (const child of children) {\n lines.push(` ${child}/`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n\nfunction buildDevSection(ctx: DetectedContext): string {\n const lines: string[] = [];\n\n // Run command\n switch (ctx.packageManager) {\n case \"pnpm\":\n lines.push(\"```bash\");\n lines.push(\"pnpm install\");\n lines.push(\"pnpm dev\");\n lines.push(\"```\");\n break;\n case \"yarn\":\n lines.push(\"```bash\");\n lines.push(\"yarn install\");\n lines.push(\"yarn dev\");\n lines.push(\"```\");\n break;\n case \"bun\":\n lines.push(\"```bash\");\n lines.push(\"bun install\");\n lines.push(\"bun dev\");\n lines.push(\"```\");\n break;\n case \"npm\":\n lines.push(\"```bash\");\n lines.push(\"npm install\");\n lines.push(\"npm run dev\");\n lines.push(\"```\");\n break;\n case \"pip\":\n case \"poetry\":\n lines.push(\"```bash\");\n lines.push(\n ctx.packageManager === \"poetry\"\n ? \"poetry install\"\n : \"pip install -r requirements.txt\",\n );\n lines.push(\"```\");\n break;\n case \"cargo\":\n lines.push(\"```bash\");\n lines.push(\"cargo build\");\n lines.push(\"cargo run\");\n lines.push(\"```\");\n break;\n case \"go\":\n lines.push(\"```bash\");\n lines.push(\"go build ./...\");\n lines.push(\"go run .\");\n lines.push(\"```\");\n break;\n default:\n lines.push(\"(add your build/run commands here)\");\n }\n\n // Lint command\n if (ctx.linter !== \"none\") {\n lines.push(\"\");\n lines.push(`Linter: **${ctx.linter}**`);\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Get the filename for the main context file based on IDE target.\n */\nexport function getMainContextFilename(ide: UserAnswers[\"ide\"]): string {\n switch (ide) {\n case \"claude\":\n return \"CLAUDE.md\";\n case \"cursor\":\n return \"CLAUDE.md\";\n case \"opencode\":\n return \"AGENTS.md\";\n case \"copilot\":\n return \".github/copilot-instructions.md\";\n case \"windsurf\":\n return \".windsurfrules\";\n case \"cline\":\n return \".clinerules\";\n case \"continue\":\n return \".continuerules\";\n case \"aider\":\n return \".aider.conf.yml\";\n case \"generic\":\n return \"CONTEXT.md\";\n }\n}\n","import type { ContextAnalysis, DetectedContext, UserAnswers } from \"../types.js\";\nimport { getFrameworkHints } from \"./framework-hints.js\";\n\ninterface CursorRule {\n /** Filename (without path) */\n filename: string;\n /** Frontmatter description */\n description: string;\n /** Glob patterns for file matching */\n globs: string;\n /** Rule body content */\n body: string;\n}\n\n/**\n * Generate .cursor/rules/*.md files based on detected project structure.\n */\nexport function buildCursorRules(\n ctx: DetectedContext,\n answers: UserAnswers,\n analysis?: ContextAnalysis,\n): CursorRule[] {\n const rules: CursorRule[] = [];\n\n // Always create a global rule\n rules.push(buildGlobalRule(ctx, answers, analysis));\n\n // Component rule (if components/ directory exists)\n const hasComponents = ctx.directories.some(\n (d) => d.endsWith(\"components\") || d.includes(\"components/\"),\n );\n if (hasComponents) {\n rules.push(buildComponentsRule(ctx));\n }\n\n // Services rule (if services/ or api/ exists)\n const hasServices = ctx.directories.some(\n (d) =>\n d.endsWith(\"services\") ||\n d.endsWith(\"api\") ||\n d.includes(\"services/\") ||\n d.includes(\"api/\"),\n );\n if (hasServices) {\n rules.push(buildServicesRule(ctx));\n }\n\n // Stores rule (if stores/ or store/ exists)\n const hasStores = ctx.directories.some(\n (d) =>\n d.endsWith(\"stores\") ||\n d.endsWith(\"store\") ||\n d.includes(\"stores/\") ||\n d.includes(\"store/\"),\n );\n if (hasStores) {\n rules.push(buildStoresRule(ctx));\n }\n\n return rules;\n}\n\nfunction buildGlobalRule(ctx: DetectedContext, answers: UserAnswers, analysis?: ContextAnalysis): CursorRule {\n const bodyLines: string[] = [\n \"# Global Rules\",\n \"\",\n `> Update this rule and the main context file after any architectural or convention change.`,\n \"\",\n ];\n\n // Add gotchas if provided\n if (answers.gotchas) {\n bodyLines.push(\"## Gotchas\");\n bodyLines.push(\"\");\n const gotchas = answers.gotchas\n .split(/[.\\n]/)\n .map((s) => s.trim())\n .filter(Boolean);\n for (const g of gotchas) {\n bodyLines.push(`- ${g}`);\n }\n bodyLines.push(\"\");\n }\n\n // Instability warnings\n if (analysis?.instabilities && analysis.instabilities.length > 0) {\n bodyLines.push(\"## High-Instability Files\");\n bodyLines.push(\"\");\n bodyLines.push(\n \"> These files have many dependents but also many dependencies (unstable). Changes here have high blast radius.\",\n );\n bodyLines.push(\"\");\n for (const inst of analysis.instabilities) {\n bodyLines.push(`- \\`${inst.path}\\` — ${(inst.instability * 100).toFixed(0)}% unstable (${inst.fanIn} dependents, ${inst.fanOut} dependencies)`);\n }\n bodyLines.push(\"\");\n }\n\n // Change coupling warnings\n if (analysis?.gitActivity?.changeCoupling && analysis.gitActivity.changeCoupling.length > 0) {\n bodyLines.push(\"## Change Coupling\");\n bodyLines.push(\"\");\n bodyLines.push(\n \"> These file pairs frequently change together. When modifying one, check the other.\",\n );\n bodyLines.push(\"\");\n for (const pair of analysis.gitActivity.changeCoupling.slice(0, 5)) {\n bodyLines.push(`- \\`${pair.fileA}\\` ↔ \\`${pair.fileB}\\` (${pair.coChangeCount} co-changes, ${(pair.confidence * 100).toFixed(0)}% confidence)`);\n }\n bodyLines.push(\"\");\n }\n\n // Circular dependency warnings\n if (analysis?.circularDeps && analysis.circularDeps.length > 0) {\n bodyLines.push(\"## Circular Dependencies\");\n bodyLines.push(\"\");\n bodyLines.push(\n \"> These circular import chains may cause unexpected behavior. Avoid adding to them.\",\n );\n bodyLines.push(\"\");\n for (const dep of analysis.circularDeps) {\n bodyLines.push(`- ${dep.chain.join(\" -> \")}`);\n }\n bodyLines.push(\"\");\n }\n\n // Module clusters\n if (analysis?.communities && analysis.communities.length > 0) {\n bodyLines.push(\"## Module Clusters\");\n bodyLines.push(\"\");\n bodyLines.push(\n \"> Tightly-connected file groups. Changes in one file likely affect others in the same cluster.\",\n );\n bodyLines.push(\"\");\n for (const community of analysis.communities.slice(0, 5)) {\n bodyLines.push(`- **${community.label}** (${community.files.length} files): ${community.files.map((f) => `\\`${f}\\``).join(\", \")}`);\n }\n bodyLines.push(\"\");\n }\n\n // Framework conventions\n const fwHints = getFrameworkHints(ctx);\n if (fwHints.length > 0) {\n bodyLines.push(\"## Framework Conventions\");\n bodyLines.push(\"\");\n for (const hint of fwHints) {\n bodyLines.push(hint);\n }\n bodyLines.push(\"\");\n }\n\n // Linter info\n if (ctx.linter !== \"none\") {\n bodyLines.push(\n `- Linter: **${ctx.linter}**. Run lint before committing.`,\n );\n }\n\n // Keep context files updated\n bodyLines.push(\n \"- After any architectural or convention change, update the relevant context files.\",\n );\n\n const ext = getExtGlob(ctx);\n\n return {\n filename: \"global.md\",\n description: \"Universal project rules\",\n globs: `**/*.${ext}`,\n body: bodyLines.join(\"\\n\"),\n };\n}\n\nfunction buildComponentsRule(ctx: DetectedContext): CursorRule {\n const compDir = ctx.directories.find(\n (d) => d.endsWith(\"components\") || d.includes(\"components/\"),\n ) ?? \"src/components\";\n\n const bodyLines: string[] = [\n \"# UI Components\",\n \"\",\n \"> Update this rule when component conventions change.\",\n \"\",\n \"## Conventions\",\n \"\",\n ];\n\n // Add framework-specific hints\n const hasReact = ctx.frameworks.some(\n (f) => f.name === \"React\" || f.name === \"React Native\",\n );\n const hasTailwind = ctx.frameworks.some(\n (f) => f.name === \"Tailwind CSS\" || f.name === \"NativeWind\",\n );\n\n if (hasReact) {\n bodyLines.push(\"- Functional components with hooks (no class components)\");\n bodyLines.push(\"- Use `memo()` for expensive renders\");\n }\n\n if (hasTailwind) {\n bodyLines.push(\n \"- Use `className` for layout/styling via Tailwind. Inline `style` only for dynamic/theme values.\",\n );\n }\n\n bodyLines.push(\n \"- Props interfaces defined adjacent to the component\",\n );\n bodyLines.push(\"- Keep components focused -- extract sub-components when complexity grows\");\n\n // Also glob the app screens if they exist\n const appGlob = ctx.directories.includes(\"app\") ? \", app/**/*.tsx\" : \"\";\n\n return {\n filename: \"ui-components.md\",\n description: \"Component conventions and patterns\",\n globs: `${compDir}/**/*.{ts,tsx,js,jsx}${appGlob}`,\n body: bodyLines.join(\"\\n\"),\n };\n}\n\nfunction buildServicesRule(ctx: DetectedContext): CursorRule {\n const svcDir = ctx.directories.find(\n (d) =>\n d.endsWith(\"services\") ||\n d.endsWith(\"api\") ||\n d.includes(\"services/\") ||\n d.includes(\"api/\"),\n ) ?? \"src/services\";\n\n // Check if hooks dir exists (for useChat-like patterns)\n const hooksGlob = ctx.directories.some((d) => d.endsWith(\"hooks\"))\n ? `, ${ctx.directories.find((d) => d.endsWith(\"hooks\"))}/**/*.{ts,js}`\n : \"\";\n\n const bodyLines: string[] = [\n \"# Services & API Layer\",\n \"\",\n \"> Update this rule when service patterns or API conventions change.\",\n \"\",\n \"## Conventions\",\n \"\",\n \"- Services should be pure functions or classes, not React hooks\",\n \"- Error handling: always catch and provide meaningful error messages\",\n \"- Keep service functions focused on a single responsibility\",\n ];\n\n return {\n filename: \"services.md\",\n description: \"Service and API layer patterns\",\n globs: `${svcDir}/**/*.{ts,js}${hooksGlob}`,\n body: bodyLines.join(\"\\n\"),\n };\n}\n\nfunction buildStoresRule(ctx: DetectedContext): CursorRule {\n const storeDir = ctx.directories.find(\n (d) =>\n d.endsWith(\"stores\") ||\n d.endsWith(\"store\") ||\n d.includes(\"stores/\") ||\n d.includes(\"store/\"),\n ) ?? \"src/stores\";\n\n const bodyLines: string[] = [\n \"# State Management\",\n \"\",\n \"> Update this rule when state patterns change.\",\n \"\",\n \"## Conventions\",\n \"\",\n ];\n\n // Detect state management library\n const hasZustand = ctx.frameworks.some((f) => f.name === \"Zustand\");\n const hasRedux = ctx.frameworks.some(\n (f) => f.name === \"Redux\" || f.name === \"Redux Toolkit\",\n );\n const hasPinia = ctx.frameworks.some((f) => f.name === \"Pinia\");\n\n if (hasZustand) {\n bodyLines.push(\n \"- **Zustand** slice architecture: each slice is a `StateCreator` accessing full state via `get()`\",\n );\n bodyLines.push(\"- Immutable updates: always spread state\");\n bodyLines.push(\"- Cross-slice access via `get()` (not separate store imports)\");\n } else if (hasRedux) {\n bodyLines.push(\"- **Redux Toolkit** slices with `createSlice`\");\n bodyLines.push(\"- Async logic in thunks (`createAsyncThunk`)\");\n bodyLines.push(\"- Selectors for reading state, dispatches for writing\");\n } else if (hasPinia) {\n bodyLines.push(\"- **Pinia** stores with composition API\");\n bodyLines.push(\"- Getters for derived state, actions for mutations\");\n } else {\n bodyLines.push(\"- Keep state updates immutable\");\n bodyLines.push(\"- Separate concerns into distinct store modules\");\n }\n\n bodyLines.push(\"- Silent failures for persistence (app should work even if storage fails)\");\n\n return {\n filename: \"stores.md\",\n description: \"State management patterns\",\n globs: `${storeDir}/**/*.{ts,js}`,\n body: bodyLines.join(\"\\n\"),\n };\n}\n\n/**\n * Get the right file extension glob for the project's language.\n */\nfunction getExtGlob(ctx: DetectedContext): string {\n switch (ctx.language) {\n case \"typescript\":\n return \"{ts,tsx}\";\n case \"javascript\":\n return \"{js,jsx}\";\n case \"python\":\n return \"py\";\n case \"go\":\n return \"go\";\n case \"rust\":\n return \"rs\";\n default:\n return \"{ts,tsx,js,jsx}\";\n }\n}\n\n/**\n * Format a CursorRule as the full file content with frontmatter.\n */\nexport function renderCursorRule(rule: CursorRule): string {\n return [\n \"---\",\n `description: ${rule.description}`,\n `globs: ${rule.globs}`,\n \"---\",\n \"\",\n rule.body,\n \"\",\n ].join(\"\\n\");\n}\n","import type { ClaudeSkill, ContextAnalysis, DetectedContext, UserAnswers } from \"../types.js\";\n\n/**\n * Build Claude Code skills based on detected project context.\n * @param scripts - Record of script name -> command from package.json (or equivalent)\n */\nexport function buildClaudeSkills(\n ctx: DetectedContext,\n answers: UserAnswers,\n analysis?: ContextAnalysis,\n scripts?: Record<string, string>,\n): ClaudeSkill[] {\n const skills: ClaudeSkill[] = [];\n\n // Script-based skills from package.json\n if (scripts) {\n skills.push(...buildScriptSkills(ctx, scripts));\n }\n\n // Architecture exploration skill\n const archSkill = buildArchitectureSkill(analysis);\n if (archSkill) skills.push(archSkill);\n\n return skills;\n}\n\n/**\n * Scan package.json scripts for common commands and generate skills.\n */\nfunction buildScriptSkills(ctx: DetectedContext, scripts: Record<string, string>): ClaudeSkill[] {\n const skills: ClaudeSkill[] = [];\n\n const scriptMap: Record<string, { description: string; keywords: string[] }> = {\n test: { description: \"Run the test suite\", keywords: [\"test\", \"test:unit\", \"test:e2e\"] },\n build: { description: \"Build the project\", keywords: [\"build\", \"build:prod\"] },\n lint: { description: \"Run linter\", keywords: [\"lint\", \"lint:fix\"] },\n dev: { description: \"Start development server\", keywords: [\"dev\", \"start:dev\"] },\n typecheck: { description: \"Run type checking\", keywords: [\"typecheck\", \"type-check\", \"check-types\"] },\n };\n\n const runCmd = getRunCommand(ctx);\n\n for (const [skillName, config] of Object.entries(scriptMap)) {\n const matchedScript = config.keywords.find((kw) => kw in scripts);\n if (!matchedScript) continue;\n\n const command = `${runCmd} ${matchedScript}`;\n skills.push({\n name: skillName,\n description: config.description,\n disableModelInvocation: true,\n body: [\n `# ${config.description}`,\n \"\",\n `Run: \\`${command}\\``,\n ].join(\"\\n\"),\n });\n }\n\n return skills;\n}\n\nfunction getRunCommand(ctx: DetectedContext): string {\n switch (ctx.packageManager) {\n case \"pnpm\": return \"pnpm\";\n case \"yarn\": return \"yarn\";\n case \"bun\": return \"bun run\";\n case \"npm\": return \"npm run\";\n case \"cargo\": return \"cargo\";\n case \"go\": return \"go\";\n default: return \"npm run\";\n }\n}\n\n/**\n * Build an architecture exploration skill with hub files, layers, and circular deps.\n */\nfunction buildArchitectureSkill(analysis?: ContextAnalysis): ClaudeSkill | null {\n if (!analysis) return null;\n\n const bodyLines: string[] = [\n \"# Architecture Explorer\",\n \"\",\n \"Use this skill to understand the project architecture before making changes.\",\n \"\",\n ];\n\n if (analysis.hubFiles.length > 0) {\n bodyLines.push(\"## Key Files (by centrality)\");\n bodyLines.push(\"\");\n for (const hub of analysis.hubFiles) {\n bodyLines.push(`- \\`${hub.path}\\` — imported by ${hub.importedBy} file${hub.importedBy === 1 ? \"\" : \"s\"}`);\n }\n bodyLines.push(\"\");\n }\n\n if (analysis.layers.length > 0) {\n bodyLines.push(\"## Architecture Layers\");\n bodyLines.push(\"\");\n bodyLines.push(\"Dependency flow (foundational → consumer):\");\n bodyLines.push(\"\");\n bodyLines.push(analysis.layers.map((l) => `\\`${l.name}\\``).join(\" → \"));\n bodyLines.push(\"\");\n }\n\n if (analysis.circularDeps.length > 0) {\n bodyLines.push(\"## Circular Dependencies\");\n bodyLines.push(\"\");\n for (const dep of analysis.circularDeps) {\n bodyLines.push(`- ${dep.chain.map((f) => `\\`${f}\\``).join(\" -> \")}`);\n }\n bodyLines.push(\"\");\n }\n\n if (analysis.communities.length > 0) {\n bodyLines.push(\"## Module Clusters\");\n bodyLines.push(\"\");\n for (const community of analysis.communities) {\n bodyLines.push(`- **${community.label}** (${community.files.length} files)`);\n }\n bodyLines.push(\"\");\n }\n\n // Only create the skill if there's meaningful content\n if (analysis.hubFiles.length === 0 && analysis.layers.length === 0) {\n return null;\n }\n\n return {\n name: \"architecture\",\n description: \"Explore project architecture and key files\",\n disableModelInvocation: false,\n allowedTools: \"Read, Grep, Glob\",\n body: bodyLines.join(\"\\n\"),\n };\n}\n\n/**\n * Render a ClaudeSkill as YAML frontmatter + markdown body.\n */\nexport function renderClaudeSkill(skill: ClaudeSkill): string {\n const lines: string[] = [\n \"---\",\n `description: ${skill.description}`,\n ];\n\n if (skill.disableModelInvocation) {\n lines.push(\"disable-model-invocation: true\");\n }\n\n if (skill.allowedTools) {\n lines.push(`allowed-tools: ${skill.allowedTools}`);\n }\n\n lines.push(\"---\");\n lines.push(\"\");\n lines.push(skill.body);\n lines.push(\"\");\n\n return lines.join(\"\\n\");\n}\n","import type { CodeSnapshot, ContextAnalysis, DetectedContext, UserAnswers } from \"../types.js\";\nimport { summarizeDetection } from \"../detect.js\";\nimport { getFrameworkHints } from \"./framework-hints.js\";\n\n/**\n * Build an Aider config file (.aider.conf.yml) with project conventions.\n * Aider uses YAML format with a `conventions` key containing a list of strings.\n */\nexport function buildAiderContext(\n ctx: DetectedContext,\n answers: UserAnswers,\n snapshot: CodeSnapshot | null,\n analysis?: ContextAnalysis,\n): string {\n const lines: string[] = [];\n\n lines.push(\"# .aider.conf.yml — Generated by codebrief\");\n lines.push(\"# Keep this file up to date as the project evolves.\");\n lines.push(\"\");\n\n const stackSummary = answers.stackConfirmed\n ? summarizeDetection(ctx)\n : answers.stackCorrections || summarizeDetection(ctx);\n\n // Conventions as a YAML list\n lines.push(\"conventions:\");\n lines.push(` - \"Project: ${escapeYaml(answers.projectPurpose)}\"`);\n lines.push(` - \"Stack: ${escapeYaml(stackSummary)}\"`);\n\n // Frameworks\n if (ctx.frameworks.length > 0) {\n const fws = ctx.frameworks\n .map((f) => `${f.name}${f.version ? ` ${f.version}` : \"\"}`)\n .join(\", \");\n lines.push(` - \"Frameworks: ${escapeYaml(fws)}\"`);\n }\n\n // Package manager + linter\n if (ctx.packageManager !== \"none\") {\n lines.push(` - \"Package manager: ${ctx.packageManager}\"`);\n }\n if (ctx.linter !== \"none\") {\n lines.push(` - \"Linter: ${ctx.linter}\"`);\n }\n\n // Project structure\n if (ctx.directories.length > 0) {\n const dirs = ctx.directories.join(\", \");\n lines.push(` - \"Key directories: ${escapeYaml(dirs)}\"`);\n }\n\n // Key patterns\n if (answers.keyPatterns) {\n const patterns = answers.keyPatterns\n .split(/[.\\n]/)\n .map((s) => s.trim())\n .filter(Boolean);\n for (const p of patterns) {\n lines.push(` - \"${escapeYaml(p)}\"`);\n }\n }\n\n // Gotchas\n if (answers.gotchas) {\n const gotchas = answers.gotchas\n .split(/[.\\n]/)\n .map((s) => s.trim())\n .filter(Boolean);\n for (const g of gotchas) {\n lines.push(` - \"GOTCHA: ${escapeYaml(g)}\"`);\n }\n }\n\n // Framework conventions\n const fwHints = getFrameworkHints(ctx);\n if (fwHints.length > 0) {\n // Filter to just the bullet-point lines (skip headers and blank lines)\n for (const hint of fwHints) {\n const trimmed = hint.trim();\n if (trimmed && trimmed.startsWith(\"- \")) {\n lines.push(` - \"${escapeYaml(trimmed.slice(2))}\"`);\n }\n }\n }\n\n // Monorepo info\n if (ctx.monorepo && ctx.monorepo.packages.length > 0) {\n lines.push(\n ` - \"Monorepo: ${ctx.monorepo.type} with ${ctx.monorepo.packages.length} packages\"`,\n );\n for (const pkg of ctx.monorepo.packages) {\n const fws =\n pkg.frameworks.length > 0\n ? ` (${pkg.frameworks.map((f) => f.name).join(\", \")})`\n : \"\";\n lines.push(` - \"Package: ${escapeYaml(pkg.name)} at ${escapeYaml(pkg.path)}${escapeYaml(fws)}\"`);\n }\n }\n\n // Key files\n if (analysis?.hubFiles && analysis.hubFiles.length > 0) {\n lines.push(` - \"Key files (read these first for architecture): ${escapeYaml(analysis.hubFiles.map((h) => h.path).join(\", \"))}\"`);\n }\n\n // Architecture\n if (analysis?.layers && analysis.layers.length > 1) {\n const flow = analysis.layers.map((l) => l.name).join(\" → \");\n lines.push(` - \"Architecture dependency flow: ${escapeYaml(flow)}\"`);\n }\n\n // Instability warnings\n if (analysis?.instabilities && analysis.instabilities.length > 0) {\n for (const inst of analysis.instabilities) {\n lines.push(` - \"UNSTABLE: ${escapeYaml(inst.path)} — ${(inst.instability * 100).toFixed(0)}% unstable (${inst.fanIn} dependents, ${inst.fanOut} deps)\"`);\n }\n }\n\n // Change coupling\n if (analysis?.gitActivity?.changeCoupling && analysis.gitActivity.changeCoupling.length > 0) {\n for (const pair of analysis.gitActivity.changeCoupling.slice(0, 5)) {\n lines.push(` - \"CO-CHANGE: ${escapeYaml(pair.fileA)} <-> ${escapeYaml(pair.fileB)} (${pair.coChangeCount} co-changes, ${(pair.confidence * 100).toFixed(0)}% confidence)\"`);\n }\n }\n\n // Circular dependencies\n if (analysis?.circularDeps && analysis.circularDeps.length > 0) {\n for (const dep of analysis.circularDeps) {\n lines.push(` - \"CIRCULAR DEP: ${escapeYaml(dep.chain.join(\" -> \"))}\"`);\n }\n }\n\n // Recently active files\n if (analysis?.gitActivity && analysis.gitActivity.hotFiles.length > 0) {\n const hot = analysis.gitActivity.hotFiles\n .slice(0, 5)\n .map((h) => `${h.path} (${h.commits} commits)`)\n .join(\", \");\n lines.push(` - \"Recently active: ${escapeYaml(hot)}\"`);\n }\n\n // Code snapshot\n if (snapshot?.markdown) {\n lines.push(\"\");\n lines.push(\n \"# CODE SNAPSHOT (auto-generated, update when types/stores/services change)\",\n );\n lines.push(\"# Formatted as a multi-line read block for Aider context.\");\n lines.push(\"read:\");\n // We can't inline markdown directly into YAML conventions cleanly.\n // Instead, write a companion markdown file and reference it.\n // For now, include the snapshot as a YAML comment block.\n lines.push(\n \" # To include the code snapshot, create a file and add it here:\",\n );\n lines.push(\" # - .aider.context.md\");\n\n // Also add the snapshot as commented YAML for reference\n lines.push(\"\");\n lines.push(\"# --- Code Snapshot (for reference) ---\");\n for (const line of snapshot.markdown.split(\"\\n\")) {\n lines.push(`# ${line}`);\n }\n lines.push(\"# --- /Code Snapshot ---\");\n }\n\n lines.push(\"\");\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Escape a string for use inside double-quoted YAML values.\n */\nfunction escapeYaml(s: string): string {\n return s.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n}\n","import pc from \"picocolors\";\nimport type { CodeSnapshot, ContextAnalysis, DetectedContext, GeneratedFile } from \"./types.js\";\nimport { estimateTokens, formatBytes } from \"./utils.js\";\n\n/**\n * Print a summary of generated files with token estimates.\n */\nexport function printSummary(\n files: GeneratedFile[],\n ctx: DetectedContext,\n snapshot?: CodeSnapshot | null,\n analysis?: ContextAnalysis,\n): void {\n if (files.length === 0) return;\n\n console.log(\"\");\n console.log(pc.bold(\" Files created:\"));\n console.log(\"\");\n\n // Track totals\n let totalBytes = 0;\n let totalTokens = 0;\n let alwaysOnTokens = 0;\n let scopedRuleTokens: number[] = [];\n\n // Group files: main context vs scoped rules\n const mainFiles = files.filter((f) => !f.path.includes(\".cursor/rules/\"));\n const ruleFiles = files.filter((f) => f.path.includes(\".cursor/rules/\"));\n\n // Pre-compute row data for aligned output\n const fileRows: Array<{\n indent: string;\n name: string;\n size: string;\n tokens: string;\n isUpdated: boolean;\n isHeader: boolean;\n }> = [];\n\n for (const file of mainFiles) {\n const bytes = Buffer.byteLength(file.content, \"utf-8\");\n const tokens = estimateTokens(file.content);\n totalBytes += bytes;\n totalTokens += tokens;\n alwaysOnTokens += tokens;\n\n fileRows.push({\n indent: \" \",\n name: file.path,\n size: formatBytes(bytes),\n tokens: `(~${formatNumber(tokens)} tokens)`,\n isUpdated: !!file.existed,\n isHeader: false,\n });\n }\n\n if (ruleFiles.length > 0) {\n fileRows.push({\n indent: \" \",\n name: \".cursor/rules/\",\n size: \"\",\n tokens: \"\",\n isUpdated: false,\n isHeader: true,\n });\n\n // global.md is always-on, others are scoped\n for (const file of ruleFiles) {\n const bytes = Buffer.byteLength(file.content, \"utf-8\");\n const tokens = estimateTokens(file.content);\n totalBytes += bytes;\n totalTokens += tokens;\n\n const filename = file.path.split(\"/\").pop() ?? file.path;\n const isGlobal = filename === \"global.md\";\n\n if (isGlobal) {\n alwaysOnTokens += tokens;\n } else {\n scopedRuleTokens.push(tokens);\n }\n\n fileRows.push({\n indent: \" \",\n name: filename,\n size: formatBytes(bytes),\n tokens: `(~${formatNumber(tokens)} tokens)`,\n isUpdated: !!file.existed,\n isHeader: false,\n });\n }\n }\n\n // Derive column widths from row data\n const dataFileRows = fileRows.filter((r) => !r.isHeader);\n const maxNameCol = Math.max(...fileRows.map((r) => r.indent.length + r.name.length));\n const maxSizeWidth = Math.max(...dataFileRows.map((r) => r.size.length));\n const maxTokenWidth = Math.max(...dataFileRows.map((r) => r.tokens.length));\n\n // Print aligned rows\n for (const row of fileRows) {\n if (row.isHeader) {\n console.log(`${row.indent}${pc.cyan(row.name)}`);\n } else {\n const status = row.isUpdated ? pc.yellow(\"(updated)\") : pc.green(\"(new)\");\n const paddedName = row.name.padEnd(maxNameCol - row.indent.length);\n console.log(\n `${row.indent}${pc.cyan(paddedName)} ${row.size.padStart(maxSizeWidth)} ${pc.dim(row.tokens.padEnd(maxTokenWidth))} ${status}`,\n );\n }\n }\n\n console.log(\"\");\n console.log(\n pc.dim(\n ` Total: ${formatBytes(totalBytes)}, ~${formatNumber(totalTokens)} tokens`,\n ),\n );\n\n if (snapshot?.budgetExcluded && snapshot.budgetExcluded > 0) {\n console.log(\n pc.dim(\n ` (${snapshot.budgetExcluded} snapshot entries excluded by token budget)`,\n ),\n );\n }\n\n // Analysis summary\n if (analysis) {\n const parts: string[] = [];\n if (analysis.hubFiles.length > 0) parts.push(`${analysis.hubFiles.length} key files`);\n if (analysis.layers.length > 0) parts.push(`${analysis.layers.length} architecture layers`);\n if (analysis.circularDeps.length > 0) parts.push(`${analysis.circularDeps.length} circular deps`);\n if (analysis.communities.length > 0) parts.push(`${analysis.communities.length} module clusters`);\n if (analysis.gitActivity) parts.push(`${analysis.gitActivity.hotFiles.length} recently active files`);\n if (parts.length > 0) {\n console.log(\n pc.dim(` Includes: ${parts.join(\", \")}`),\n );\n }\n }\n\n // -- Token estimate comparison (bar chart) --\n console.log(\"\");\n console.log(pc.bold(\" Estimated context cost per conversation:\"));\n console.log(\"\");\n\n // Before: estimate exploration cost from source file count + size\n const explorationTokens = estimateExplorationCost(ctx);\n\n // After\n const avgScopedTokens =\n scopedRuleTokens.length > 0\n ? Math.round(\n scopedRuleTokens.reduce((a, b) => a + b, 0) /\n scopedRuleTokens.length,\n )\n : 0;\n\n const residualExploration = Math.round(explorationTokens * 0.05);\n const afterTotal = alwaysOnTokens + avgScopedTokens + residualExploration;\n const savings = Math.round(\n ((explorationTokens - afterTotal) / explorationTokens) * 100,\n );\n\n // Bar chart: proportional bars, max 40 chars wide\n const BAR_MAX = 40;\n const maxVal = Math.max(explorationTokens, afterTotal);\n const beforeBarLen = Math.max(1, Math.round((explorationTokens / maxVal) * BAR_MAX));\n const afterBarLen = Math.max(1, Math.round((afterTotal / maxVal) * BAR_MAX));\n const BLOCK = \"\\u2588\";\n\n const beforeBar = BLOCK.repeat(beforeBarLen);\n const afterBar = BLOCK.repeat(afterBarLen);\n const afterPad = \" \".repeat(Math.max(0, beforeBarLen - afterBarLen));\n\n console.log(` Before: ${pc.red(beforeBar)} ~${formatNumber(explorationTokens)} tokens`);\n console.log(` After: ${pc.green(afterBar)}${afterPad} ~${formatNumber(afterTotal)} tokens`);\n\n console.log(\"\");\n\n if (savings > 0) {\n console.log(\n pc.green(\n ` Estimated savings: ~${savings}% fewer tokens`,\n ),\n );\n }\n\n // \"What we analyzed\" recap\n if (analysis) {\n console.log(\"\");\n console.log(pc.bold(\" What we analyzed:\"));\n\n const recapRows: Array<{ label: string; result: string }> = [];\n\n if (analysis.hubFiles.length > 0) {\n recapRows.push({ label: \"PageRank hub detection\", result: `found ${analysis.hubFiles.length} key architectural files` });\n }\n\n recapRows.push({\n label: \"Tarjan cycle detection\",\n result: analysis.circularDeps.length === 0\n ? \"no circular dependencies found\"\n : `${analysis.circularDeps.length} circular dep${analysis.circularDeps.length === 1 ? \"\" : \"s\"} found`,\n });\n\n if (analysis.layers.length > 0) {\n const tierNames = analysis.layers.map((l) => l.name).join(\" → \");\n recapRows.push({ label: \"Layer analysis\", result: `${analysis.layers.length} tiers: ${tierNames}` });\n }\n\n if (analysis.gitActivity) {\n const coupledPairs = analysis.gitActivity.changeCoupling.length;\n recapRows.push({\n label: \"Git history (90 days)\",\n result: `${analysis.gitActivity.hotFiles.length} hot files, ${coupledPairs} change-coupled pair${coupledPairs === 1 ? \"\" : \"s\"}`,\n });\n }\n\n const ec = analysis.exportCoverage;\n if (ec && ec.length > 0) {\n const totalExports = ec.reduce((sum, e) => sum + e.totalExports, 0);\n const totalUsed = ec.reduce((sum, e) => sum + e.usedExports, 0);\n const coveragePct = totalExports > 0 ? Math.round((totalUsed / totalExports) * 100) : 100;\n const unused = totalExports - totalUsed;\n recapRows.push({ label: \"Export coverage\", result: `${coveragePct}% (${unused} unused export${unused === 1 ? \"\" : \"s\"})` });\n }\n\n if (analysis.communities.length > 0) {\n recapRows.push({ label: \"Community detection\", result: `${analysis.communities.length} module cluster${analysis.communities.length === 1 ? \"\" : \"s\"}` });\n }\n\n const maxRecapLabel = Math.max(...recapRows.map((r) => r.label.length));\n for (const row of recapRows) {\n console.log(\n pc.dim(` ${row.label.padEnd(maxRecapLabel)} → ${row.result}`),\n );\n }\n }\n\n // Findings summary — actionable issues worth fixing\n if (analysis) {\n const findings: string[] = [];\n\n // Circular dependencies (always a finding)\n if (analysis.circularDeps.length > 0) {\n for (const c of analysis.circularDeps.slice(0, 3)) {\n const names = c.chain.map((f) => f.split(\"/\").pop()?.replace(/\\.[jt]sx?$/, \"\") ?? f);\n findings.push(`${analysis.circularDeps.length > 1 ? \"\" : \"\"}1 circular dependency chain (${names.slice(0, 2).join(\" \\u2194 \")})`);\n }\n if (analysis.circularDeps.length > 1) {\n findings[0] = `${analysis.circularDeps.length} circular dependency chain${analysis.circularDeps.length === 1 ? \"\" : \"s\"}`;\n }\n }\n\n // High-instability files (instability > 0.8)\n const highInstabilityFiles = analysis.instabilities.filter((f) => f.instability > 0.8);\n if (highInstabilityFiles.length > 0) {\n findings.push(`${highInstabilityFiles.length} high-instability file${highInstabilityFiles.length === 1 ? \"\" : \"s\"}`);\n }\n\n // Unused exports\n const ec = analysis.exportCoverage;\n if (ec && ec.length > 0) {\n const totalExports = ec.reduce((sum, e) => sum + e.totalExports, 0);\n const totalUsed = ec.reduce((sum, e) => sum + e.usedExports, 0);\n const unusedExports = totalExports - totalUsed;\n const filesWithUnused = ec.filter((e) => e.usedExports < e.totalExports).length;\n if (unusedExports > 0) {\n findings.push(`${unusedExports} unused export${unusedExports === 1 ? \"\" : \"s\"} in ${filesWithUnused} file${filesWithUnused === 1 ? \"\" : \"s\"}`);\n }\n }\n\n console.log(\"\");\n if (findings.length > 0) {\n console.log(pc.yellow(` \\u26A0 ${findings.length} finding${findings.length === 1 ? \"\" : \"s\"}`));\n for (const f of findings) {\n console.log(pc.dim(` \\u25CF ${f}`));\n }\n } else {\n console.log(pc.green(` \\u2713 No structural issues detected`));\n }\n }\n\n console.log(\"\");\n}\n\n/**\n * Estimate how many tokens an AI agent would spend exploring a codebase\n * without any context files.\n *\n * Heuristic: agents typically read 30-50% of source files to understand\n * architecture, plus overhead from search/grep operations.\n */\nfunction estimateExplorationCost(ctx: DetectedContext): number {\n if (ctx.totalSourceBytes === 0 || ctx.sourceFileCount === 0) {\n // Fallback for projects where we couldn't count\n return 15000;\n }\n\n // Agents typically read ~40% of source files to understand a project\n const bytesRead = ctx.totalSourceBytes * 0.4;\n // Convert to tokens — source code is typically symbol-heavy (~3.2 chars/token)\n const readTokens = Math.ceil(bytesRead / 3.2);\n\n // Add overhead for search commands, tool calls, etc (~30% overhead)\n const overhead = Math.ceil(readTokens * 0.3);\n\n // Minimum floor\n return Math.max(5000, readTokens + overhead);\n}\n\nfunction formatNumber(n: number): string {\n if (n >= 1000) {\n return `${(n / 1000).toFixed(1).replace(/\\.0$/, \"\")}k`;\n }\n return String(n);\n}\n","import { createHash } from \"node:crypto\";\nimport path from \"node:path\";\nimport fg from \"fast-glob\";\nimport type { Language, ProjectConfig, UserAnswers } from \"./types.js\";\nimport { readJsonFile, writeFileSafe } from \"./utils.js\";\n\nconst CONFIG_FILENAME = \".codebrief.json\";\nconst CONFIG_VERSION = 1;\n\ninterface ConfigFile extends ProjectConfig {\n /** Schema version for future migrations */\n _version: number;\n}\n\n/**\n * Load project config from .codebrief.json.\n * Returns null if the file doesn't exist or is invalid.\n */\nexport async function loadConfig(\n rootDir: string,\n): Promise<ProjectConfig | null> {\n const configPath = path.join(rootDir, CONFIG_FILENAME);\n const raw = await readJsonFile(configPath);\n if (!raw) return null;\n\n const cfg = raw as Partial<ConfigFile>;\n\n // Validate required fields\n if (!cfg.ide || !cfg.projectPurpose) return null;\n\n return {\n ide: cfg.ide,\n projectPurpose: cfg.projectPurpose,\n keyPatterns: cfg.keyPatterns ?? \"\",\n gotchas: cfg.gotchas ?? \"\",\n generateSnapshot: cfg.generateSnapshot ?? false,\n snapshotPaths: cfg.snapshotPaths ?? [],\n stackCorrections: cfg.stackCorrections ?? \"\",\n generatePerPackage: cfg.generatePerPackage ?? false,\n snapshotHash: cfg.snapshotHash,\n snapshotGeneratedAt: cfg.snapshotGeneratedAt,\n language: cfg.language,\n };\n}\n\n/**\n * Save project config to .codebrief.json.\n * Optionally includes snapshot hash and timestamp.\n */\nexport async function saveConfig(\n rootDir: string,\n answers: UserAnswers,\n snapshotHash?: string,\n language?: Language,\n): Promise<void> {\n const configPath = path.join(rootDir, CONFIG_FILENAME);\n const cfg: ConfigFile = {\n _version: CONFIG_VERSION,\n ide: answers.ide,\n projectPurpose: answers.projectPurpose,\n keyPatterns: answers.keyPatterns,\n gotchas: answers.gotchas,\n generateSnapshot: answers.generateSnapshot,\n snapshotPaths: answers.snapshotPaths,\n stackCorrections: answers.stackCorrections,\n generatePerPackage: answers.generatePerPackage,\n ...(snapshotHash\n ? { snapshotHash, snapshotGeneratedAt: Date.now() }\n : {}),\n ...(language ? { language } : {}),\n };\n await writeFileSafe(configPath, JSON.stringify(cfg, null, 2) + \"\\n\");\n}\n\n/**\n * Convert a loaded ProjectConfig into UserAnswers (filling in defaults\n * for fields that only come from the interactive prompts).\n */\nexport function configToAnswers(config: ProjectConfig): UserAnswers {\n return {\n ide: config.ide,\n projectPurpose: config.projectPurpose,\n keyPatterns: config.keyPatterns,\n gotchas: config.gotchas,\n generateSnapshot: config.generateSnapshot,\n snapshotPaths: config.snapshotPaths,\n stackConfirmed: true,\n stackCorrections: config.stackCorrections,\n generatePerPackage: config.generatePerPackage,\n };\n}\n\n/**\n * Compute a hash of all source files (path + mtime) to detect changes.\n * Returns a 16-char hex string.\n */\nexport async function computeSnapshotHash(\n rootDir: string,\n language: Language,\n): Promise<string> {\n const extMap: Record<string, string[]> = {\n typescript: [\"**/*.{ts,tsx}\"],\n javascript: [\"**/*.{js,jsx,mjs}\"],\n python: [\"**/*.py\"],\n go: [\"**/*.go\"],\n rust: [\"**/*.rs\"],\n java: [\"**/*.java\"],\n other: [\"**/*.{ts,tsx,js,jsx,py,go,rs}\"],\n };\n\n const files = await fg(extMap[language] ?? extMap.other, {\n cwd: rootDir,\n ignore: [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n \"**/.next/**\",\n \"**/target/**\",\n \"**/vendor/**\",\n ],\n stats: true,\n absolute: false,\n });\n\n // Sort by path for deterministic hashing\n const entries = files\n .map((f) => `${f.path}:${f.stats?.mtimeMs ?? 0}`)\n .sort();\n\n const hash = createHash(\"sha256\")\n .update(entries.join(\"\\n\"))\n .digest(\"hex\")\n .slice(0, 16);\n\n return hash;\n}\n","import path from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\nimport { detectContext } from \"./detect.js\";\nimport { generateSnapshot } from \"./snapshot.js\";\nimport { buildImportGraph } from \"./graph.js\";\nimport { loadConfig } from \"./config.js\";\nimport { fileExists, readFileOr, writeFileSafe } from \"./utils.js\";\nimport type { ProgressCallback } from \"./types.js\";\n\n/** Known context files in priority order */\nconst CONTEXT_FILES = [\n \"CLAUDE.md\",\n \"AGENTS.md\",\n \".github/copilot-instructions.md\",\n \".windsurfrules\",\n \".clinerules\",\n \".continuerules\",\n \"CONTEXT.md\",\n];\n\n/** Markdown snapshot markers */\nconst MD_START = /<!-- CODE SNAPSHOT[^>]*-->/;\nconst MD_END = /<!-- \\/CODE SNAPSHOT -->/;\n\n/** Aider YAML comment markers */\nconst AIDER_START = /^# --- Code Snapshot/m;\nconst AIDER_END = /^# --- \\/Code Snapshot ---$/m;\n\n/**\n * Find the first existing context file in the project root.\n * Also checks for .aider.conf.yml.\n */\nasync function findContextFile(\n rootDir: string,\n): Promise<{ path: string; isAider: boolean } | null> {\n // Check aider first since it has a unique format\n const aiderPath = path.join(rootDir, \".aider.conf.yml\");\n if (await fileExists(aiderPath)) {\n const content = await readFileOr(aiderPath);\n if (content && AIDER_START.test(content)) {\n return { path: \".aider.conf.yml\", isAider: true };\n }\n }\n\n // Check markdown context files\n for (const file of CONTEXT_FILES) {\n const absPath = path.join(rootDir, file);\n if (await fileExists(absPath)) {\n return { path: file, isAider: false };\n }\n }\n\n return null;\n}\n\n/**\n * Refresh the code snapshot section in an existing context file.\n * Auto-detects which file to update.\n */\nexport async function refreshSnapshot(rootDir: string): Promise<void> {\n const spinner = p.spinner();\n\n // 1. Find context file\n const found = await findContextFile(rootDir);\n if (!found) {\n p.log.error(\n \"No context file found. Run \" +\n pc.cyan(\"codebrief\") +\n \" first to generate one.\",\n );\n process.exit(1);\n }\n\n const absPath = path.join(rootDir, found.path);\n const content = await readFileOr(absPath);\n if (!content) {\n p.log.error(`Could not read ${found.path}`);\n process.exit(1);\n }\n\n // 2. Verify snapshot markers exist\n if (found.isAider) {\n if (!AIDER_START.test(content) || !AIDER_END.test(content)) {\n p.log.error(\n `No code snapshot markers found in ${found.path}. Re-generate the file with code snapshot enabled.`,\n );\n process.exit(1);\n }\n } else {\n if (!MD_START.test(content) || !MD_END.test(content)) {\n p.log.error(\n `No code snapshot markers found in ${found.path}. Re-generate the file with code snapshot enabled.`,\n );\n process.exit(1);\n }\n }\n\n p.log.info(`Refreshing snapshot in ${pc.cyan(found.path)}`);\n\n // 3. Detect context and generate new snapshot\n spinner.start(\"Scanning source files...\");\n const progress: ProgressCallback = (msg) => spinner.message(msg);\n const detected = await detectContext(rootDir, progress);\n\n // Build import graph for better snapshot quality\n const graph = await buildImportGraph(rootDir, detected.language, progress);\n\n // Load snapshot paths from config if available\n const config = await loadConfig(rootDir);\n const snapshotPaths = config?.snapshotPaths ?? [];\n\n const snapshot = await generateSnapshot(detected, snapshotPaths, graph, undefined, progress);\n spinner.stop(\n snapshot.entries.length > 0\n ? `Found ${snapshot.entries.length} type${snapshot.entries.length === 1 ? \"\" : \"s\"}/signature${snapshot.entries.length === 1 ? \"\" : \"s\"}.`\n : \"No extractable types found.\",\n );\n\n if (snapshot.entries.length === 0) {\n p.log.warn(\"No types found — snapshot section will be empty.\");\n }\n\n // 4. Replace the snapshot section\n let updated: string;\n\n if (found.isAider) {\n // Replace YAML comment block\n const startMatch = content.match(AIDER_START);\n const endMatch = content.match(AIDER_END);\n if (!startMatch || !endMatch) {\n p.log.error(\"Failed to parse snapshot markers.\");\n process.exit(1);\n }\n\n const startIdx = content.indexOf(startMatch[0]);\n const endIdx = content.indexOf(endMatch[0]) + endMatch[0].length;\n\n let newBlock = \"# --- Code Snapshot (for reference) ---\";\n if (snapshot.markdown) {\n for (const line of snapshot.markdown.split(\"\\n\")) {\n newBlock += `\\n# ${line}`;\n }\n }\n newBlock += \"\\n# --- /Code Snapshot ---\";\n\n updated = content.slice(0, startIdx) + newBlock + content.slice(endIdx);\n } else {\n // Replace markdown block\n const startMatch = content.match(MD_START);\n const endMatch = content.match(MD_END);\n if (!startMatch || !endMatch) {\n p.log.error(\"Failed to parse snapshot markers.\");\n process.exit(1);\n }\n\n const startIdx = content.indexOf(startMatch[0]);\n const endIdx = content.indexOf(endMatch[0]) + endMatch[0].length;\n\n let newBlock =\n \"<!-- CODE SNAPSHOT (auto-generated, update when types/stores/services change) -->\";\n if (snapshot.markdown) {\n newBlock += \"\\n\\n\" + snapshot.markdown + \"\\n\";\n }\n newBlock += \"\\n<!-- /CODE SNAPSHOT -->\";\n\n updated = content.slice(0, startIdx) + newBlock + content.slice(endIdx);\n }\n\n // 5. Write back\n await writeFileSafe(absPath, updated);\n p.log.success(`Updated snapshot in ${pc.cyan(found.path)}`);\n}\n","import { execSync } from \"node:child_process\";\nimport type { ChangeCoupling, GitAnalysis, ProgressCallback } from \"./types.js\";\n\n/**\n * Analyze git activity in the repository to identify recently active files.\n * Returns null if not a git repo or git is unavailable.\n */\nexport function analyzeGitActivity(\n rootDir: string,\n onProgress?: ProgressCallback,\n): GitAnalysis | null {\n try {\n onProgress?.(\"Analyzing git history (last 90 days)...\");\n\n // Get file change counts for the last 90 days\n const logOutput = execSync(\n 'git log --since=\"90 days ago\" --name-only --pretty=format:\"\"',\n { cwd: rootDir, encoding: \"utf-8\", timeout: 10000 },\n );\n\n const commitCounts = new Map<string, number>();\n for (const line of logOutput.split(\"\\n\")) {\n const file = line.trim();\n if (file && !file.startsWith(\"commit \")) {\n commitCounts.set(file, (commitCounts.get(file) ?? 0) + 1);\n }\n }\n\n if (commitCounts.size === 0) {\n return null;\n }\n\n onProgress?.(`Found activity in ${commitCounts.size} files`);\n\n // Get last changed date for top files\n const sorted = [...commitCounts.entries()].sort((a, b) => b[1] - a[1]);\n const hotFiles: GitAnalysis[\"hotFiles\"] = [];\n\n for (const [filePath, commits] of sorted.slice(0, 15)) {\n let lastChanged = \"\";\n try {\n lastChanged = execSync(\n `git log -1 --format=\"%ar\" -- \"${filePath}\"`,\n { cwd: rootDir, encoding: \"utf-8\", timeout: 5000 },\n ).trim();\n } catch {\n // Skip if can't get date\n }\n hotFiles.push({ path: filePath, commits, lastChanged });\n }\n\n // Analyze change coupling\n onProgress?.(\"Analyzing change coupling...\");\n const changeCoupling = analyzeChangeCoupling(rootDir);\n\n return { commitCounts, hotFiles, changeCoupling };\n } catch {\n // Not a git repo, git not available, or command failed\n return null;\n }\n}\n\n/**\n * Analyze change coupling — files that frequently change together in commits.\n * Uses co-occurrence analysis over the last 90 days of git history.\n */\nexport function analyzeChangeCoupling(rootDir: string): ChangeCoupling[] {\n try {\n // Get commit hashes from last 90 days\n const hashOutput = execSync(\n 'git log --format=\"%H\" --since=\"90 days ago\"',\n { cwd: rootDir, encoding: \"utf-8\", timeout: 10000 },\n ).trim();\n\n if (!hashOutput) return [];\n\n const hashes = hashOutput.split(\"\\n\").filter(Boolean);\n if (hashes.length === 0) return [];\n\n // Get files per commit (batch for efficiency)\n const filesPerCommit: string[][] = [];\n const commitCountPerFile = new Map<string, number>();\n\n for (const hash of hashes) {\n try {\n const filesOutput = execSync(\n `git show --name-only --format=\"\" ${hash}`,\n { cwd: rootDir, encoding: \"utf-8\", timeout: 5000 },\n ).trim();\n\n const files = filesOutput\n .split(\"\\n\")\n .map((f) => f.trim())\n .filter(Boolean);\n\n if (files.length >= 2 && files.length <= 20) {\n // Skip huge commits (merges) and single-file commits\n filesPerCommit.push(files);\n for (const file of files) {\n commitCountPerFile.set(file, (commitCountPerFile.get(file) ?? 0) + 1);\n }\n }\n } catch {\n // Skip individual commit errors\n }\n }\n\n // Build co-occurrence matrix\n const coChanges = new Map<string, number>();\n for (const files of filesPerCommit) {\n for (let i = 0; i < files.length; i++) {\n for (let j = i + 1; j < files.length; j++) {\n const key = [files[i], files[j]].sort().join(\"||\");\n coChanges.set(key, (coChanges.get(key) ?? 0) + 1);\n }\n }\n }\n\n // Compute coupling metrics\n const results: ChangeCoupling[] = [];\n const totalCommits = filesPerCommit.length;\n\n for (const [key, coChangeCount] of coChanges) {\n if (coChangeCount < 3) continue; // Minimum threshold\n\n const [fileA, fileB] = key.split(\"||\");\n const commitsA = commitCountPerFile.get(fileA) ?? 0;\n const commitsB = commitCountPerFile.get(fileB) ?? 0;\n const confidence = coChangeCount / Math.max(commitsA, commitsB);\n const support = coChangeCount / totalCommits;\n\n if (confidence >= 0.5) {\n results.push({ fileA, fileB, coChangeCount, support, confidence });\n }\n }\n\n // Sort by confidence descending, return top 10\n results.sort((a, b) => b.confidence - a.confidence);\n return results.slice(0, 10);\n } catch {\n return [];\n }\n}\n"],"mappings":"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","names":["text","path","p","pc","path","readFileOr","confirm","generateSnapshot","path","fg","path","fg","files","result","p","fg","path","path","p","p","p","path","path","fg","path","p","pc","path","spinner","pc","path","pc","spinner","e"]}