/** * Read a state file and validate its structure. * * - **Invalid JSON** → quarantined * - **Missing or non‑integer `version`** → quarantined * - **Version outside 1‑99** → quarantined * - **Valid file** → returned as‑is * - **File does not exist (ENOENT)** → `null` (not corrupt, not quarantined) * * @param filePath – Absolute path to the state file. * @param reason – Human‑readable context for the log warning. * @returns `filePath` on success, `null` if quarantined or missing. */ export declare function quarantineCorruptFile(filePath: string, reason: string): string | null; /** * Read a *versionless* state file (e.g. `recovery-*.json`) and validate only * that it is a JSON‑parseable object. No `version` field is required, so a file * with a different shape is not treated as corrupt. * * - **Invalid JSON** → quarantined * - **Not a JSON object (primitive / null)** → quarantined * - **Any JSON object** → returned as‑is (no version check) * - **File does not exist (ENOENT)** → `null` (not corrupt, not quarantined) * * @param filePath – Absolute path to the state file. * @param reason – Human‑readable context for the log warning. * @returns `filePath` on success, `null` if quarantined or missing. */ export declare function quarantineVersionlessFile(filePath: string, reason: string): string | null; /** * Scan `dir` for orphaned `.tmp` files left by interrupted atomic writes and * delete each one. Logs every deletion at `warn` level. * * If `dir` does not exist, the call is a silent no‑op. */ export declare function orphanTmpCleanup(dir: string): number; /** * Scan the given state directory for stale locks and break them. * * Two complementary passes: * * 1. **Direct `*.lock` scan** — read each lock file and delete it when its * recorded PID is dead (ESRCH) or the file is unparseable. This also * catches orphan lock files whose paired `*.json` no longer exists. * 2. **Acquire‑then‑release each state (`*.json`)** — {@link acquireStateLock} * reclaims any lock whose holder is dead or whose age exceeds the stale * timeout, and the immediate `release()` deletes the reclaimed lock file. * Only locks that already existed on disk are counted, so creating and * deleting a fresh lock for an otherwise unlocked file does not inflate the * count (the direct scan in pass 1 already handled the dead‑PID cases). * * Locks held by live processes are left untouched. * * @param stateDir – Absolute path to the `.rolebox/state/` directory. Passed * explicitly so callers control which workspace is checked. * @returns The number of stale locks broken. */ export declare function breakStaleLocks(stateDir: string): number; export interface StartupHealth { /** true when no state files were corrupted */ healthy: boolean; /** Filenames of state files that were quarantined */ quarantined: string[]; /** Number of stale/abandoned locks that were broken */ staleLocksBroken: number; /** Number of orphaned .tmp files cleaned up */ orphanTmpsRemoved: number; /** Human-readable warning messages collected during the check */ warnings: string[]; } /** * Run startup consistency checks on known state files and the workspace. * * Scans `stateDir` for known state file patterns, validates each via * {@link quarantineCorruptFile}, cleans orphaned `.tmp` files from `dir`, * and breaks stale/abandoned locks. */ export declare class StartupChecker { static checkAll(dir: string, stateDir: string): StartupHealth; } //# sourceMappingURL=startup-check.d.ts.map