/** * worktree-lease — pure-function lease store for `peaks worktree spawn`. * * governance complement to Layer 3 (`permissions.deny` for the superpowers * chain) and Layer 1 (sub-agent dispatch prompt refusal). Together the * three layers close the superpowers-chain jailbreak that previously * bypassed peaks-loop's worktree posture. * * The store is a pure function module: every helper takes the lease * directory path as an argument and returns structured data. Atomic * filesystem writes happen at the call site (CLI command), keeping the * helpers trivially testable. The CLI surface lives in * * Why a separate lease (vs reusing `peaks worktree auth grant`): * - `auth grant` is a single-shot, short-lived token file consulted by * the PreToolUse hook BEFORE `git worktree add` runs. It answers * "is the LLM allowed to do this right now?" * - `lease` is a long-lived lifecycle object that owns the worktree * path, branch, expiry, and consumption log. It answers * "what worktrees does this session own, and which are still alive?" * The two coexist: `spawn` writes a lease; the lease's existence * implicitly authorizes worktree operations on its path (the hook * integration is Part 2 of this slice). */ import type { LeaseListResult, WorktreeLease, WorktreeLeaseDraft } from './worktree-lease-types.js'; export type { LeaseListResult, LeaseReadError, WorktreeLease, WorktreeLeaseDraft, WorktreeLeaseStatus } from './worktree-lease-types.js'; export declare const DEFAULT_TTL_BY_ROLE: Readonly>; export declare const DEFAULT_TTL_MS: number | undefined; /** * Compose a deterministic lease path under the per-session runtime dir. * The function is pure: same inputs → same output. The caller passes * `` (NOT a bare `` per the 2.7.1 single-scope-axis rule). * * Path layout: * .peaks/_runtime//worktree-leases/.json * * The `worktree-leases/` directory is gitignored per the .peaks/_runtime/ * rule (committed in .gitignore for all runtime artifacts). */ export declare function leaseStoreDir(sessionRuntimeDir: string): string; export declare function leaseFilePath(sessionRuntimeDir: string, leaseId: string): string; /** * Compose the absolute worktree path (the `git worktree add ` target). * Sits adjacent to the lease file under the same runtime dir. */ export declare function worktreePath(sessionRuntimeDir: string, leaseId: string): string; /** * Generate a 16-hex lease id (8 random bytes, hex-encoded). The id is * unique enough for the per-session scope; collisions across sessions * are irrelevant because each session has its own lease directory. */ export declare function generateLeaseId(): string; /** * Compute the TTL ms for a role, falling back to DEFAULT_TTL_MS for * unknown roles. The CLI overrides with `--ttl ` when the user * passes a positive value. */ export declare function ttlForRole(role: string): number; /** * Pure: produce a fresh `WorktreeLease` from a draft + status. * `status` defaults to `'active'`; `consumedBySubAgents` defaults to []. * Used by the CLI's atomicWriteJson call. */ export declare function finalizeLease(draft: WorktreeLeaseDraft): WorktreeLease; /** Pure: lease status transitions to 'released'. Returns a new lease. */ export declare function markReleased(lease: WorktreeLease): WorktreeLease; /** Pure: lease status transitions to 'expired'. Returns a new lease. */ export declare function markExpired(lease: WorktreeLease): WorktreeLease; /** Pure: lease status transitions to 'gc'. Returns a new lease. */ export declare function markGc(lease: WorktreeLease): WorktreeLease; /** Pure: append a sub-agent batch / dispatch id to the consumption log. Returns a new lease. */ export declare function recordConsumption(lease: WorktreeLease, subAgentId: string): WorktreeLease; /** * Pure: is the lease still active (status === 'active' AND not past expiry). * Expired leases are NOT auto-released; the gc CLI is the only path that * transitions them to 'gc'. Until then, the on-disk state stays 'active' * but `isLeaseActive` returns false so consumers skip the lease. */ export declare function isLeaseActive(lease: WorktreeLease, now?: number): boolean; /** * List every lease file under the session's lease store dir. * * Pure with respect to its inputs: it does NOT sort or filter, and it * does NOT mark anything expired. Callers (the `list` CLI) apply their * own sort/filter and run `markExpired` lazily. */ export declare function listLeasesSync(storeDir: string, fs: { readdir: (path: string) => ReadonlyArray; readFile: (path: string) => string; existsSync: (path: string) => boolean; }): LeaseListResult; /** * Pure: a lease is eligible for `gc` if its status is one of {released, * expired} AND its worktree path is no longer attached to git (`git * worktree list` would not include it). The CLI re-checks with git and * uses this helper as a coarse pre-filter. */ export declare function isLeaseGcEligible(lease: WorktreeLease, now?: number): boolean; /** * Pure: derive a new lease from an existing one with an extended * `expiresAt`. Other fields are preserved. The CLI writes the new lease * atomically. Used by `peaks worktree renew --lease-id --ttl `. */ export declare function renewLease(lease: WorktreeLease, newExpiresAt: number): WorktreeLease; /** * Pure: serialize a lease to JSON with stable field order (deterministic * output for diff-friendly audit logs). The CLI passes the result to * `atomicWriteJson`. The function does NOT mutate the input. */ export declare function serializeLease(lease: WorktreeLease): string; /** * Pure: deserialize a lease from JSON. Throws on malformed input — the * CLI catches and returns a `LEASE_FILE_INVALID` envelope (mirroring the * `peaks worktree auth` FILE_INVALID convention). */ export declare function deserializeLease(raw: string): WorktreeLease;