import { Database } from '../runtime/sqlite'; import type { TopFileResult, FileDepResult, FileCoChangeResult, FileSymbolResult, SymbolSearchResult, SymbolSignatureResult, CallerResult, CalleeResult, UnusedExportResult, DuplicateStructureResult, NearDuplicateResult, ExternalPackageResult, GraphStats, PrepareScanResult, ScanBatchResult, OrphanFileResult, CircularDependencyResult, ChangeImpactResult, SymbolReferenceResult, SymbolBlastRadiusResult, CallGraphCycleResult } from './types'; interface RepoMapConfig { cwd: string; db: Database; } export declare class RepoMap { private db; private cwd; private treeSitter; private cache; private stmts; private scanFiles; private scanTotalFiles; constructor(config: RepoMapConfig); /** * Execute `fn` inside a DB transaction, retrying on SQLITE_BUSY with * bounded backoff. All write paths in this class must go through this * helper so that rare lock contention with concurrent followers' * readonly readers (or a cross-process checkpoint) doesn't surface as * a user-visible error. * * Reads continue to go through plain `this.stmts.*.get/all()` — under * WAL they never block and never get SQLITE_BUSY, so the retry * machinery is pure overhead for them. */ private txWrite; private prepareStatements; initialize(): Promise; private initSchema; scan(): Promise; /** * Prepare for a full scan by collecting all indexable files and resetting scan state. * Returns the total number of files to process and the batch size to use. */ prepareScan(): Promise; /** * Scan a batch of files starting at the given offset. * Returns progress info including whether scanning is complete. * * Each file is guarded by a per-file timeout so one pathological file * (e.g. very large, tree-sitter bug, syscall stall) cannot starve the * whole batch. Timed-out files are counted in `skippedTimeouts` and the * scan continues. */ scanBatch(offset: number, batchSize: number): Promise; /** * Race indexFile() against a wall-clock timeout. On timeout the indexing * promise is orphaned (tree-sitter parsing is CPU-bound and not * cancellable); the scan proceeds with the next file. The orphan's * eventual settle is swallowed to avoid unhandled rejections. */ private indexFileWithTimeout; /** * Finalize the scan by building all derived state (refs, edges, PageRank, etc). * Should be called once after all file batches have been processed. */ finalizeScan(): Promise; /** * Reset graph data tables before a fresh full scan. * This ensures stale file entries and derived data from previous scans are removed. */ private resetGraphDataForFullScan; indexFile(filePath: string): Promise; private resolveImportSource; resolveUnresolvedRefs(): Promise; buildEdges(): Promise; computePageRank(): Promise; computePageRankSync(): Promise; render(opts?: { maxFiles?: number; maxSymbols?: number; }): Promise<{ content: string; paths: string[]; }>; getStats(): GraphStats; getTopFiles(limit?: number): TopFileResult[]; getFileDependents(path: string): FileDepResult[]; getFileDependencies(path: string): FileDepResult[]; getFileCoChanges(path: string): FileCoChangeResult[]; getFileBlastRadius(path: string): number; getFileSymbols(path: string): FileSymbolResult[]; findSymbols(query: string, limit?: number): SymbolSearchResult[]; searchSymbolsFts(query: string, limit?: number): SymbolSearchResult[]; getSymbolSignature(path: string, line: number): SymbolSignatureResult | null; getCallers(path: string, line: number, minConfidence?: number): CallerResult[]; getCallees(path: string, line: number, minConfidence?: number): CalleeResult[]; /** * BFS traversal over the call graph starting from the symbol at (path, line). * * Budget-aware: stops on whichever of `maxDepth`, `maxNodes`, or * `maxTokens` hits first. `maxTokens` is a coarse cap on the cumulative * size of emitted node identifiers (`name + path`); it is not a real * LLM tokenizer, just a cheap proxy to bound output size for tooling. * * Edges below `minConfidence` (see Etap 9b) are skipped entirely, * so walking from an EXTRACTED-only perspective is just * `{ minConfidence: 1.0 }`. */ traverse(opts: { path: string; line: number; direction?: 'in' | 'out' | 'both'; maxDepth?: number; maxTokens?: number; minConfidence?: number; maxNodes?: number; }): import('./types').TraverseResult; /** * Produces a compact JSON snapshot of the current graph state suitable * for committing as a PR artefact or diffing against a later snapshot. * * The snapshot is intentionally schema-stable (see `GraphSnapshot.version`) * so older snapshots remain readable after schema migrations. */ snapshot(label: string): import('./types').GraphSnapshot; /** * Pure diff of two snapshots. Does not touch the DB — callers can * diff snapshots loaded from disk across commits/branches. */ static diffSnapshots(a: import('./types').GraphSnapshot, b: import('./types').GraphSnapshot): import('./types').GraphSnapshotDiff; /** * Loads all file-level edges into an adjacency list form and runs * community detection / bridge detection / surprise-edge analysis. * All three share the same in-memory edge list to avoid re-querying. */ getCommunityAnalysis(opts?: { surprisePercentile?: number; maxIterations?: number; }): { communities: import('./types').CommunityResult[]; bridges: import('./types').BridgeEdgeResult[]; surprises: import('./types').SurpriseEdgeResult[]; }; /** Convenience: communities only (no bridges/surprises). */ getCommunities(maxIterations?: number): import('./types').CommunityResult[]; /** Convenience: bridge edges only. */ getBridges(): import('./types').BridgeEdgeResult[]; /** Convenience: surprise cross-community edges only. */ getSurpriseEdges(percentile?: number): import('./types').SurpriseEdgeResult[]; /** * Heuristically picks "entry-point" symbols and walks the outgoing * call graph from each one to produce an ordered execution flow. * * Entry-point kinds: * - `main` — symbol named `main` or `run` * - `test` — any symbol defined in a `*.test.*` / `*.spec.*` file * - `handler` — symbols whose name matches handler-ish patterns * (`handle*`, `*Handler`, `GET/POST/PUT/DELETE`, `route*`) * - `export` — exported functions (fallback when nothing else matches) * * Flows are sorted by the entry's file PageRank descending, so the * most "load-bearing" flows surface first. */ getExecutionFlows(opts?: { maxDepth?: number; maxFlows?: number; }): import('./types').ExecutionFlow[]; /** * Returns high-PageRank symbols that are not covered by any test * file — candidates for writing new tests. Heuristic: * 1. Take all symbols whose file PageRank is at or above the `percentile` * cutoff (default p90) of the PageRank distribution across files * with at least one symbol. * 2. Drop any symbol that is transitively called from a test file. * 3. Sort by `pagerank desc, nonTestCallers desc`. */ getKnowledgeGaps(opts?: { percentile?: number; limit?: number; }): import('./types').KnowledgeGapResult[]; getUnusedExports(limit?: number): UnusedExportResult[]; getDuplicateStructures(limit?: number): DuplicateStructureResult[]; getNearDuplicates(threshold?: number, limit?: number): NearDuplicateResult[]; getExternalPackages(limit?: number): ExternalPackageResult[]; getOrphanFiles(limit?: number): OrphanFileResult[]; getCircularDependencies(limit?: number): CircularDependencyResult[]; getChangeImpact(paths: string[], maxDepth?: number): ChangeImpactResult; getSymbolReferences(name: string, limit?: number): SymbolReferenceResult[]; /** * Symbol-level blast radius — BFS through call edges from a given symbol. * Returns all symbols that are transitively reachable as callers. */ getSymbolBlastRadius(name: string, maxDepth?: number): SymbolBlastRadiusResult; /** * Detect cycles in the call graph (symbol-level). * Uses iterative DFS with back-edge detection. */ getCallGraphCycles(limit?: number): CallGraphCycleResult[]; onFileChanged(path: string): Promise<{ status: string; }>; private removeFile; buildCoChanges(): Promise; buildCallGraph(): Promise; linkTestFiles(): Promise; rescueOrphans(): Promise; } export {}; //# sourceMappingURL=repo-map.d.ts.map