/** * Process-matrix supervisor: PURE state-transition functions over `ProcessMatrixEntry`. Every * function here takes its notion of "now" and process liveness as an explicit argument/dependency * -- no `Date.now()`, no `process.kill` inside this module -- so the whole lifecycle (orphan * detection, wind-down, adoption, reconcile) is deterministically testable without real timers or * real processes. `runtime.ts` is the only caller that supplies real deps and real I/O. */ import type { AgentIdentityContract } from "../orchestration/contracts.ts"; import type { ProcessMatrixEntry, ProcessTerminalHandoff, ReconcileMatrixResult, ResumablePayload, WindDownReason, WorkerDirective } from "./codes.ts"; export interface BuildMasterEntryFacts { agent: AgentIdentityContract; pid: number; hostname: string; now: string; } export declare function buildMasterEntry(facts: BuildMasterEntryFacts): ProcessMatrixEntry; export interface BuildWorkerEntryFacts { agent: AgentIdentityContract; pid: number; hostname: string; now: string; parentPid: number; parentSessionId?: string; tmuxSession?: string; tmuxPanePid?: number; taskRef?: string; taskSummary?: string; } export declare function buildWorkerEntry(facts: BuildWorkerEntryFacts): ProcessMatrixEntry; export declare function applyHeartbeat(entry: ProcessMatrixEntry, now: string): ProcessMatrixEntry; export interface DetectOrphanedWorkersDeps { isPidAlive: (pid: number) => boolean; /** This session's own sessionId -- never treat yourself as an orphan you found. */ ownSessionId?: string; } /** * Worker entries whose `parentPid` is dead, excluding this session's own entry and anything * already `closed` (a closed worker isn't "orphaned", it's already done). */ export declare function detectOrphanedWorkers(entries: ProcessMatrixEntry[], deps: DetectOrphanedWorkersDeps): ProcessMatrixEntry[]; export declare function beginWindDown(entry: ProcessMatrixEntry, reason: WindDownReason, now: string): ProcessMatrixEntry; export declare function markResumable(entry: ProcessMatrixEntry, payload: ResumablePayload, now: string): ProcessMatrixEntry; export declare function markClosed(entry: ProcessMatrixEntry, now: string): ProcessMatrixEntry; export declare function markTerminal(entry: ProcessMatrixEntry, terminal: Pick, now: string): ProcessMatrixEntry; export declare function markTerminalNotificationDelivered(entry: ProcessMatrixEntry, now: string): ProcessMatrixEntry; export interface AdoptionFacts { parentPid: number; parentSessionId?: string; } /** Claim (or reclaim) an entry under a new parent: back to `running`, wind-down reason cleared. */ export declare function applyAdoption(entry: ProcessMatrixEntry, adoption: AdoptionFacts): ProcessMatrixEntry; export interface PollWorkerDirectiveDeps { isPidAlive: (pid: number) => boolean; } /** * A worker calls this against its OWN freshly re-read entry to learn whether a master wrote a * directive into it: an adoption (a new, live `parentPid` the worker didn't already know about) * or a cooperative cleanup request (`windDownReason === "user_cleanup"`). `knownParentPid` is the * parent the worker itself currently believes it has -- an unchanged, still-known parentPid never * counts as a new adoption. */ export declare function pollWorkerDirective(freshEntry: ProcessMatrixEntry, knownParentPid: number | undefined, deps: PollWorkerDirectiveDeps): WorkerDirective; export interface ReconcileMatrixDeps { isPidAlive: (pid: number) => boolean; /** Epoch ms "now", compared against a resumable/adopted entry's `heartbeatAt`. */ now: number; resumableTtlMs: number; } /** * Prune `closed` entries and unrecoverable dead processes. A dead Pi worker that was interrupted * before persisting its own resumable transition is repaired from its already-durable logical-agent * identity. `resumable`/`adopted` entries are kept until they age past `resumableTtlMs`. */ export declare function reconcileMatrix(entries: ProcessMatrixEntry[], deps: ReconcileMatrixDeps): ReconcileMatrixResult; //# sourceMappingURL=supervisor.d.ts.map