/** Source files longer than this count as oversized. */ export declare const OVERSIZED_LINES = 800; /** Files bigger than this (outside Git LFS) count as large committed files. */ export declare const LARGE_FILE_BYTES: number; /** How far back Git history counts toward a file's change count. */ export declare const HOTSPOT_DAYS = 90; /** Fewest changes within {@link HOTSPOT_DAYS} that can make an oversized file a hotspot. */ export declare const HOTSPOT_CHANGES = 5; /** * A hotspot is among the repo's most-changed files (this share of all files * changed in the period), so "changing often" means the same thing in a quiet * repo and a busy one. */ export declare const HOTSPOT_TOP_SHARE = 0.02; /** Changes that make a file a hotspot, given every changed file's change count. */ export declare function hotspotThreshold(changeCounts: Iterable): number; /** * How much an oversized file's excess lines count: a big file that keeps * changing is where bugs come from; a big file nobody touches costs little. * null (no usable history) counts as ordinary. */ export declare function churnWeight(changes: number | null, threshold?: number): number; export interface HealthFileLines { readonly path: string; readonly lines: number; /** Commits touching it in the last {@link HOTSPOT_DAYS} days; null without history. */ readonly changes: number | null; } export interface HealthFileBytes { readonly path: string; readonly bytes: number; } export interface HealthSecretFile { readonly path: string; /** Committed (true) or merely not covered by .gitignore (false). */ readonly tracked: boolean; /** * The kind of key found inside the file (e.g. "GitHub token"); null when the * file name alone marks it (`.env`, `id_rsa`). The value itself is never kept. */ readonly found: string | null; /** 1-based line of the key; null for name-only matches. */ readonly line: number | null; } export interface HealthDebt { readonly todos: number; readonly suppressions: number; readonly anyTypes: number; /** Non-test, non-generated source lines the markers were counted over. */ readonly lines: number; } export interface ProjectHealthScan { /** The file list hit the scan bound; the score covers part of the project. */ readonly truncated: boolean; /** App source only: tests and check scripts are left out of size. */ readonly sourceFiles: number; readonly sourceLines: number; /** Riskiest first (excess lines × {@link churnWeight}), at most {@link KEPT_OFFENDERS}. */ readonly oversized: readonly HealthFileLines[]; readonly oversizedCount: number; /** Oversized files changed often recently ({@link hotspotThreshold}). */ readonly hotspotCount: number; /** Lines beyond {@link OVERSIZED_LINES}, each file's weighted by {@link churnWeight}. */ readonly oversizedWeightedExcess: number; readonly secretFiles: readonly HealthSecretFile[]; /** Largest first, at most {@link KEPT_OFFENDERS}. */ readonly largeFiles: readonly HealthFileBytes[]; readonly largeFileCount: number; readonly hasGitignore: boolean; readonly missingLockfile: boolean; readonly hasTests: boolean; readonly hasLint: boolean; readonly hasFormat: boolean; /** null when no language here needs a separate type checker. */ readonly hasTypecheck: boolean | null; readonly hasCIWorkflow: boolean; readonly debt: HealthDebt; } export interface ProjectHealthScanner { /** null when `cwd` is not inside a Git work tree (or the listing failed). */ scan(cwd: string, now: Date, signal?: AbortSignal): Promise; } /** * The first real-looking key in `text`: its kind and 1-based line, never the * value. Exported for tests. */ export declare function findSecret(text: string): { label: string; line: number; } | null; /** Exported for tests. */ export declare function isTestPath(rel: string): boolean; /** Exported for tests. */ export declare function isSecretPath(rel: string): boolean; /** * Splits JS/TS source into code (with string, regex and comment contents * blanked) and the comment text. A small lexer, not a parser: template * `${}` nesting and regex literals are handled; an unterminated quote ends at * the line break (JSX text like `Don't` stays contained). Exported for tests. */ export declare function splitJsSource(text: string): { code: string; comments: string; }; /** * A scanner with a per-file cache (by mtime + size), so a rescan of an * unchanged project only stats files. Create one per polled project. */ export declare function createProjectHealthScanner(): ProjectHealthScanner;