/** In-memory lifecycle states. `interrupted` additionally exists in the * persistent ExecutionStore for executions found dead after a daemon restart — * a live registry never holds it (nothing survives in memory to interrupt). */ export type ExecutionState = 'pending' | 'complete' | 'failed' | 'cancelled'; export interface ExecutionEntry { executionId: string; cwd: string; state: ExecutionState; tool: string; /** `audit`'s criteria set (`plan` | `spec` | `skill` | `default`), null for every * other type. Carried so a running audit is as self-describing on the wire as it * is in the terminal envelope, which has always split `task.type` from * `task.subtype` — "audit" alone does not say whether a plan or a spec is under * review. */ subtype: string | null; /** The resolved Method identifier (SPEC-005), or `null` when no Method applies. Unlike * `subtype` (which is OMITTED from the wire shape when absent), `method` is * always present as `string | null` — see `executionIdentity()` in * `packages/server/src/application/task-identity.ts`, which mirrors this field into the * running snapshot the same way, and the terminal `execution` envelope built in * `execution-runtime.ts`. */ method: string | null; result: unknown; runningHeadline: string | null; /** * When each unit of provider activity landed, and which phase was live at the time. * * The execution monitor draws a run's shape from this. It has to come from the ENGINE, not * from the viewer: the panel used to accumulate its own history from the polls it personally * saw, so a re-mounted panel started blank, a second viewer disagreed with the first, and a * panel opened on an already-finished task had no history at all. The run's activity is a * fact about the run. * * Timestamps rather than pre-bucketed counts, so a reader can bucket at whatever resolution * it renders. Bounded — a long run must not grow this without limit. */ activity: Array<{ at: number; phase: 1 | 2; }>; startedAt: number; terminalAt: number | null; phase: 'implementing' | 'reviewing' | null; phaseStartedAt: number | null; totalTasks: number | null; /** Set when a caller requested cancellation (DELETE /execution/:id). A flag, * not a state: the entry stays `pending` until the runner confirms * termination and the terminal CAS decides between cancelled and a * completed/failed that won the race. */ cancellationRequestedAt: number | null; } export declare class ExecutionRegistry { private entries; private readonly ttlMs; constructor(opts?: { ttlMs?: number; }); /** Drop terminal entries whose result has been retrievable longer than the TTL. * In-flight (non-terminal) entries are never evicted regardless of age — a * slow task must never disappear mid-run. Runs lazily on register(), so a busy * server bounds its own memory without a background timer. */ private evictExpired; register(executionId: string, cwd: string, tool: string, subtype: string | null, method?: string | null): void; get(executionId: string): ExecutionEntry | undefined; complete(executionId: string, result: unknown): void; fail(executionId: string, result: unknown): void; /** Terminal transition to `cancelled`. Same CAS discipline as complete/fail: * a task that already reached a terminal state is never overwritten — if * completion won the race against cancellation, completed stands. */ cancel(executionId: string, result: unknown): void; /** Record a cancellation request on a non-terminal task. Returns the outcome * the caller reports: 'requested' (flag set now or already set — idempotent), * 'terminal' (too late; entry carries the final state), or 'not_found'. */ requestCancel(executionId: string): { outcome: 'requested' | 'terminal' | 'not_found'; entry?: ExecutionEntry; }; setPhase(executionId: string, phase: 'implementing' | 'reviewing'): void; setHeadline(executionId: string, headline: string): void; /** * Note that the worker did something. Cheap and lossy on purpose: this runs on every * provider event of every concurrent task, and it feeds a strip a few hundred pixels wide. * * The phase is stamped at record time and never revised, so the history is monotonic by * construction — an Act I sample can never appear after an Act II one, which is a sequence * the engine cannot actually produce. */ recordActivity(executionId: string, at?: number): void; countActive(cwd: string): number; allInFlight(): ExecutionEntry[]; isTerminal(executionId: string): boolean; } //# sourceMappingURL=task-registry.d.ts.map