/** SDK-owned platform module. This implementation is maintained in goodvibes-sdk. */ import { type OrchestrationEvent, type PhaseResult, type SerializedWorkstream, type Workstream, type WorkstreamSnapshot } from './types.js'; export declare function serializeWorkstream(workstream: Workstream): SerializedWorkstream; export declare function deserializeWorkstream(serialized: SerializedWorkstream): Workstream; /** Mirrors WrfcController.serializeChain: JSON.stringify a schema-versioned envelope. Returns null on serialization failure rather than throwing. */ export declare function serializeWorkstreamSnapshot(workstream: Workstream, completedResults: readonly PhaseResult[]): string | null; /** * Mirrors WrfcController.deserializeChain's future-schemaVersion-reject * guard: a snapshot written by a newer runtime is rejected (fail closed) * rather than partially trusted. */ export declare function deserializeWorkstreamSnapshot(json: string): WorkstreamSnapshot | null; /** Read + quarantine-on-corrupt (never throws, never crashes the caller on a bad file). */ export declare function loadWorkstreamSnapshot(projectRoot: string, workstreamId: string): WorkstreamSnapshot | null; /** * List the workstream ids with a snapshot on disk (recognized or not, callers * decide via loadWorkstreamSnapshot). * * This is the resume-enumeration path, so it is also the recovery point: a * housekeeping pass runs FIRST, so ids reclaimed by the reap are never handed * back to a caller that would then fail to load them. */ export declare function listSnapshotWorkstreamIds(projectRoot: string, options?: SnapshotReapOptions): string[]; export declare function writeWorkstreamSnapshot(projectRoot: string, workstream: Workstream, completedResults: readonly PhaseResult[]): void; /** Seams for the snapshot housekeeping pass. */ export interface SnapshotReapOptions { /** * "Is this workstream still running?", INJECTED so the reap can protect a * live workstream's snapshot without depending on the engine. Returning * `true` exempts the snapshot from every bound. When omitted, liveness is * inferred from the snapshot's own item states (an item that is not `passed` * or `failed` means the workstream is not finished), which is the * conservative reading. */ readonly isRunning?: ((workstreamId: string) => boolean) | undefined; /** Clock seam (tests). Defaults to `Date.now()`. */ readonly now?: number | undefined; } /** What one housekeeping pass reclaimed. Counts and byte totals only, snapshot contents are never logged. */ export interface OrchestrationSnapshotReapSummary { /** Terminal snapshots removed for exceeding {@link TERMINAL_SNAPSHOT_MAX_AGE_MS}. */ readonly terminalExpired: number; /** Terminal snapshots removed for exceeding {@link MAX_TERMINAL_SNAPSHOTS}. */ readonly terminalOverCap: number; /** Quarantine files removed for exceeding {@link QUARANTINE_MAX_AGE_MS}. */ readonly quarantineExpired: number; /** Quarantine files removed for exceeding {@link MAX_QUARANTINE_FILES}. */ readonly quarantineOverCap: number; /** Temp files from interrupted writes removed for exceeding {@link STALE_TEMP_MAX_AGE_MS}. */ readonly staleTempRemoved: number; /** Total bytes freed. */ readonly bytesReclaimed: number; /** Sum of every file count above. Zero means the pass reclaimed nothing. */ readonly total: number; } /** * Reap the orchestration snapshot directory: terminal snapshots past their TTL * or over the count cap, quarantine files past theirs, and temp files left by * an interrupted write. * * Idempotent, a second pass immediately after a first reclaims nothing, and * safe to run from two processes at once: every removal tolerates ENOENT, so * losing a race is a no-op rather than an error. */ export declare function reapOrchestrationSnapshots(projectRoot: string, options?: SnapshotReapOptions): OrchestrationSnapshotReapSummary; /** * Debounced trailing writer (250ms, exactly like wrfc-persistence.ts * DEBOUNCE_MS), subscribing to engine lifecycle events. Returns an * unsubscribe function that also flushes any pending timers. * * Also owns the PERIODIC housekeeping pass: an engine can stay attached for * days, so reaping only at resume would let a long-lived process accumulate * finished snapshots for its whole lifetime. The interval timer is unref'd, so * it never keeps a process alive, and it is cleared by the returned detach * function. * * @param sweepIntervalMs - Housekeeping interval; `0` disables the timer (tests, short-lived hosts). */ export declare function attachDebouncedWriter(projectRoot: string, getWorkstream: (workstreamId: string) => Workstream | null, getCompletedResults: (workstreamId: string) => readonly PhaseResult[], subscribe: (listener: (event: OrchestrationEvent) => void) => () => void, sweepIntervalMs?: number): () => void; //# sourceMappingURL=persistence.d.ts.map