/** * #2661 root-fix — one repository-level supervisor. * * Ten worktree daemons of the same repository independently deciding "is it * time to run audit/optimize/testgaps" every tick is the redundant-scheduler * half of the original cardinality bug — the budget ledger and job dedup * (global-ai-budget.ts, ai-job-dedup.ts) already bound and dedupe the actual * `claude --print` spend, but every daemon still runs its own timer and its * own "should I launch" decision. This module elects exactly ONE daemon per * repositoryId to own the recurring AI-worker schedule; every other worktree * of that repository stays a lease-only participant (workspace-lease.ts) — * it keeps running its cheap, $0 local-only workers (map/consolidate/backup) * on its own schedule, but does not attempt headless (`claude --print`) * execution for its recurring ticks. An explicit `daemon trigger --headless` * in a non-supervisor worktree is still honored (still budget/dedup-gated) — * this module only governs the unattended recurring schedule. * * Election is a simple lock-protected takeover, same pattern as * global-ai-budget.ts: * - No record, a dead PID, or a stale heartbeat (>SUPERVISOR_STALE_MS) → * the calling daemon takes over. * - A live supervisor with a fresh heartbeat → the calling daemon is not * elected; it does nothing (never overwrites a healthy supervisor). * * The registry lives under the user's home directory so every worktree's * daemon can see it: * * ~/.claude-flow/supervisors/.json */ export declare const SUPERVISOR_STALE_MS: number; export interface SupervisorRecord { worktreeRoot: string; pid: number; electedAt: number; lastHeartbeat: number; } export interface SupervisorElectionResult { isSupervisor: boolean; record: SupervisorRecord | null; } export declare class RepoSupervisorRegistry { private readonly dir; constructor(options?: { baseDir?: string; }); private fileFor; private ensureDir; private withLock; private readRecord; private writeRecord; private isStale; /** * Attempt election (or renewal, if this process already holds it). Safe * and cheap to call on every daemon tick — a no-op write when nothing * needs to change would still cost a lock+read+write, so callers should * still throttle to their own heartbeat cadence rather than calling this * per-worker-tick. */ electOrRenew(repositoryId: string, worktreeRoot: string): Promise; /** Cheap read-only check — does NOT renew or elect. */ isSupervisor(repositoryId: string, worktreeRoot: string): boolean; /** Release supervisor status on graceful shutdown, so the next tick elsewhere can take over promptly. Best-effort. */ release(repositoryId: string, worktreeRoot: string): Promise; /** Snapshot for `daemon status --all`. Read-only, never mutates. */ getRecord(repositoryId: string): SupervisorRecord | null; } export declare function getRepoSupervisorRegistry(): RepoSupervisorRegistry; /** Test hook: reset the singleton (e.g. after changing RUFLO_AI_BUDGET_DIR). */ export declare function resetRepoSupervisorRegistryForTests(): void; //# sourceMappingURL=repo-supervisor.d.ts.map