/** * JSONL (newline-delimited) op log (P0). * Shared by integration journal and per-lane journals (ADR 0001, ADR 0005). * * On-disk format is one op per line (`JSON.stringify(op) + "\n"`). Appends use * `appendFileSync`, which is atomic for the small per-op payloads Trellis mints, * so two processes can never clobber each other's writes — each simply adds its * line. This replaces the old single-JSON-array format, whose `append()` rewrote * the *entire* array from whatever was in memory; a long-lived process holding a * stale in-memory copy could silently overwrite intervening appends from another * process (the lost-backfill / lost-epic bug). * * Legacy JSON-array files are still readable: `load()` detects the `[` prefix and * parses the array. The first `append()` after a legacy load migrates the file to * JSONL in one atomic step, then continues appending lines. */ import type { VcsOp } from './types.js'; export interface RepairOptions { confirmDestructive?: boolean; /** Human ack that remote backup may be stale (repair gate). */ iKnow?: boolean; /** Repo root for remote ack check (defaults from ops path). */ rootPath?: string; /** Attempt ~/.trellis/oplog-mirror restore before truncating local file */ preferMirror?: boolean; } export interface RepairResult { recovered: number; lost: number; /** Restored from local mirror before repair */ mirrorRestored?: number; } /** * Backend-agnostic op log surface. * * Implementations may persist to filesystem (`JsonOpLog`), IndexedDB * (`IdbOpLog`), or any other store. The contract: * * - `load()` returns `void | Promise` so filesystem backends can stay * synchronous while browser backends (IndexedDB, OPFS) are async. Callers * that may use either backend should `await opLog.load()`. * - `append()`, `readAll()`, `getLastOp()`, `count()` are sync — they * operate on an in-memory cache the backend maintains. Sync reads are * required by the engine, which does not await op-log access on hot paths. * - `flush()` is optional — when present, awaiting it guarantees durability * for backends with deferred writes (e.g. IndexedDB). Filesystem backends * that write synchronously may omit it. * * Implementations are responsible for hash-deduplication on `append`. */ export interface OpLog { load(): void | Promise; append(op: VcsOp): void; readAll(): VcsOp[]; getLastOp(): VcsOp | undefined; count(): number; flush?(): Promise; } export declare class JsonOpLog implements OpLog { private ops; private hashes; private filePath; private lockPath; /** True when the on-disk file is still the legacy single JSON array. */ private legacy; constructor(filePath: string); get path(): string; load(): void; append(op: VcsOp): void; readAll(): VcsOp[]; getLastOp(): VcsOp | undefined; count(): number; /** Parse either a legacy JSON array or a JSONL file into ops. */ private parseFile; private parseJsonl; /** Authoritative read of the on-disk journal (array or JSONL). */ private readDiskOps; /** One-time write of the legacy array as JSONL, atomically. */ private migrateToJsonl; private appendLineToDisk; private backupCurrentFile; private withLock; static repair(filePath: string, opts?: RepairOptions): RepairResult; /** Exposed for repair + tests */ static parseFileForRepair(raw: string): { valid: string[]; corrupt: boolean; dropped: number; }; } /** Lane journal op log — same implementation, distinct path (ADR 0001, ADR 0005). */ export declare class LaneOpLog extends JsonOpLog { constructor(laneDir: string); } //# sourceMappingURL=op-log.d.ts.map