/** * Worktree-sync on-disk store: coordination state shared by EVERY process working on one repo. * * Lives under `/pi-worktree-sync/` -- all worktrees of a repository share the git * common dir, so the store is repo-scoped and cross-process by construction, survives `/reload` * and crashes, is invisible to `git status`, and needs no gitignore entry. * * The store is an INDEX, not the truth: freshness/dirtiness/progress are always re-derived from * git by the engine (`git-engine.ts`). A deleted or corrupt store is rebuildable via reconcile -- * every reader here treats missing/corrupt files as "absent", never as an error. * * Writes are tmp+rename atomic (`util/atomic-file.ts`); the audit log uses the shared bounded JSONL * sink, which serializes concurrent writers and atomically rotates to its newest low-water tail. * The integration lock is a mkdir-atomic directory with an owner manifest: mkdir either succeeds * (lock acquired) or fails EEXIST (held), with takeover ONLY for a provably-dead same-host owner. */ import type { IntegrationLockAcquisition, IntegrationLockOwner, LandingTransaction, LaneRegistration, WorktreeSyncEpoch } from "./codes.ts"; export interface SyncStorePaths { root: string; epochFile: string; landingTransactionFile: string; lanesDir: string; lockDir: string; lockOwnerFile: string; lockGuardFile: string; lifecycleLockFile: string; eventsFile: string; } /** Grace window after which an ownerless lock dir (crash between mkdir and owner write) counts as * dead and may be taken over. Fresh ownerless dirs are conservatively treated as held. */ export declare const OWNERLESS_LOCK_STALE_MS = 30000; export declare function syncStorePaths(gitCommonDir: string): SyncStorePaths; /** * Stable per-repo slug for the lane-worktree checkout root: sanitized repo basename plus 8 hex of * sha256 over the REALPATH of the git common dir -- same-named repos in different places cannot * collide, and every worktree of one repo resolves the same slug. */ export declare function repoSlug(repoTopLevel: string, gitCommonDir: string): string; export declare function readEpoch(paths: SyncStorePaths): Promise; export declare function writeEpoch(paths: SyncStorePaths, epoch: WorktreeSyncEpoch): Promise; export declare function readLandingTransaction(paths: SyncStorePaths): Promise; export declare function writeLandingTransaction(paths: SyncStorePaths, transaction: LandingTransaction): Promise; export declare function clearLandingTransaction(paths: SyncStorePaths): Promise; export declare function readLane(paths: SyncStorePaths, laneKey: string): Promise; export declare function writeLane(paths: SyncStorePaths, lane: LaneRegistration): Promise; export declare function listLanes(paths: SyncStorePaths): Promise; /** Append one audit event as a single JSON line. `at` is stamped here so every event carries it. */ export declare function appendAuditEvent(paths: SyncStorePaths, event: { event: string; } & Record, at: string): Promise; export interface IntegrationLockDeps { /** Injectable liveness probe (deterministic tests). Default: same-host `process.kill(pid, 0)`. */ isPidAlive?: (owner: IntegrationLockOwner) => boolean; now?: () => string; nowMs?: () => number; } /** Same-host pid liveness. A foreign-host owner is ALWAYS treated as alive -- never taken over. */ export declare function defaultIsPidAlive(owner: IntegrationLockOwner): boolean; /** * Acquire the single integration lock (G1: landing is serialized). Non-blocking: a held lock * returns `{acquired:false, holder, holderAlive}` immediately -- callers surface `lock_busy` and * retry on their own cadence rather than spinning here. Takeover happens ONLY when the recorded * owner is provably dead on this host (or the lock dir is ownerless and older than * {@link OWNERLESS_LOCK_STALE_MS}); every takeover is audited. */ export declare function acquireIntegrationLock(paths: SyncStorePaths, owner: Omit, deps?: IntegrationLockDeps): Promise; export declare function releaseIntegrationLock(paths: SyncStorePaths, token: string, deps?: IntegrationLockDeps): Promise; export declare function readLockHolder(paths: SyncStorePaths): Promise; //# sourceMappingURL=store.d.ts.map