/** * Session state-machine vocabulary. Exactly 5 string literals; no other * members. D-54-04 + REQ-54-01 acceptance. */ export type SessionState = "active" | "ready" | "paused" | "detached" | "failed"; /** * The 9-field on-disk record persisted for every tracked session. The shape * is forward-compatible: `schemaVersion: 1` (numeric literal, NOT string) * permits future migration. D-54-03 + REQ-54-01 acceptance. */ export interface PersistedSession { schemaVersion: 1; sessionId: string; agent: string; delegationId: string; directory: string; paneId: string; spawnTime: number; state: SessionState; lastTransitionAt: number; } /** * Options for {@link createSessionPersistence}. */ export interface SessionPersistenceOptions { /** Absolute path to the project root; the state root is derived as a subdir. */ projectDirectory: string; /** * Optional warn logger. Defaults to `console.warn` with the * `[Hivemind] persistence:` prefix. P53 D-04 mirror. */ logWarn?: (msg: string, err?: unknown) => void; } /** * Persistence handle returned by {@link createSessionPersistence}. * * The four public methods (plus one read-only test seam) form the * persistence API surface consumed by `SessionManager` (the 7th * optional constructor parameter) and the BATS L1 evidence scenario * (slot 56 — kill-parent-restart-recovery). */ export interface SessionPersistence { /** Persist a single session record to disk. */ persist(record: PersistedSession): Promise; /** Remove a session record by id. Idempotent — no throw if missing. */ remove(sessionId: string): Promise; /** * Restore all session records whose state is `paused` or `detached`, * sorted by `spawnTime` ascending. Returns `[]` for missing or empty * state root. Malformed records are skipped with `logWarn`. */ restoreAll(): Promise; /** * Generate a fresh UUIDv7 string. RFC 9562 — 48-bit timestamp + * 80 random bits, version 7 + variant 10xx. Lexicographic sort * matches creation order. P20 invariant — no `uuid` package. */ generateId(): string; /** Read-only test seam exposing the resolved state root for vitest/BATS. */ readonly __stateRoot: string; } /** * Generate an RFC-9562 UUIDv7 string. Format: `xxxxxxxx-xxxx-7xxx-yxxx- * xxxxxxxxxxxx` where the 3rd group starts with `7` (version bits * 48-51 = `0b0111`) and the 4th group starts with `8`, `9`, `a`, or `b` * (variant bits 64-65 = `0b10`). The 48 most-significant bits hold * `Date.now()` (Unix ms), making the IDs sortable by creation time. * * P20 invariant: no `uuid` package; uses `node:crypto.getRandomValues` * (Node 20+ built-in). * * @returns A fresh UUIDv7 string in lowercase canonical form. */ export declare function generateUuidV7(): string; /** * Create a session-persistence handle that writes per-session JSON records * to `/.hivemind/state/tmux-sessions/.json`. * * The factory mirrors the P53 `createPaneMonitorHook(opts)` shape: * closure-captured `logWarn` with the `[Hivemind] persistence:` prefix, * `mkdir({recursive: true})` on first call, and a returned handle with * the persistence API surface. * * All four public methods follow D-04 silent-fallback: filesystem * errors are caught and routed to `logWarn`; the `Promise` resolves * normally. The in-memory `TrackedSession` map in `SessionManager` * remains the source of truth during the process lifetime; the disk * records are best-effort. * * @param opts - {@link SessionPersistenceOptions}. * @returns A {@link SessionPersistence} handle. * * @example * ```typescript * const p = createSessionPersistence({ projectDirectory: process.cwd() }) * await p.persist({ * schemaVersion: 1, * sessionId: p.generateId(), * agent: "gsd-executor", * delegationId: "del-1", * directory: process.cwd(), * paneId: "%1", * spawnTime: Date.now(), * state: "ready", * lastTransitionAt: Date.now(), * }) * const alive = await p.restoreAll() // paused + detached only * ``` */ export declare function createSessionPersistence(opts: SessionPersistenceOptions): SessionPersistence; //# sourceMappingURL=persistence.d.ts.map