import { readdirSync, statSync } from 'fs'; import { join, relative } from 'path'; import ignore from 'ignore'; const DEFAULT_IGNORE = [ 'node_modules', '.git', 'dist', 'build', 'coverage', '.next', '.venv', '__pycache__', '.DS_Store', '*.log' ]; export interface DirectoryEntry { dirPath: string; relativePath: string; files: string[]; } export function discoverProject(rootPath: string): DirectoryEntry[] { const ig = ignore().add(DEFAULT_IGNORE); const gitignorePath = join(rootPath, '.gitignore'); try { const gitignoreContent = require('fs').readFileSync(gitignorePath, 'utf8'); ig.add(gitignoreContent); } catch { /* no .gitignore */ } const entries: DirectoryEntry[] = []; function walk(dir: string) { const relDir = relative(rootPath, dir) || '.'; if (ig.ignores(relDir)) return; const items = readdirSync(dir); const files: string[] = []; const subdirs: string[] = []; for (const item of items) { const relPath = join(relDir, item); if (ig.ignores(relPath)) continue; const fullPath = join(dir, item); const st = statSync(fullPath); if (st.isDirectory()) { subdirs.push(fullPath); } else { files.push(item); } } entries.push({ dirPath: dir, relativePath: relDir, files }); for (const subdir of subdirs) { walk(subdir); } } walk(rootPath); return entries; }