import { type TodoRun } from './runs.js'; /** * Pre-claim respawn guards (ICI-731). * * An automated re-dispatch — a workflow re-arm, a status-driven trigger, any * future auto-pickup — asks these four predicates before it takes the Todo's * claim. Each answers the same question from a different fact: would another * attempt right now actually help? Jinn has had repeat-worker storms, and every * one of them was a re-dispatch a cheap read could have refused. * * A hold is audited and takes NO claim, so a Todo the guards parked is still * free for a human to dispatch by hand. Human-initiated pickup never comes * through here at all: the operator pressing Dispatch, and `delegate_task`, are * somebody deciding to do this work, which is exactly the input these guards * are waiting for. */ export type RespawnGuard = 'rate_limit_cooldown' | 'blocker_auth' | 'recent_success' | 'active_pr'; export interface RespawnGuardHold { state: 'held'; guard: RespawnGuard; reason: string; } export type RespawnGuardVerdict = { state: 'allowed'; } | RespawnGuardHold; export interface RespawnGuardOptions { /** The caller has already settled when this quota window reopens, from a more * specific source than the clock below — the failure's own stated time, or * the engine's health record. Asking `rate_limit_cooldown` again would answer * that same question generically and override it, so it is skipped. The other * three guards read different facts and still apply. */ quotaWindowDecided?: boolean; } /** How long a quota window parks automated re-dispatch. The same grace the * engine backoff already gives a rate-limited attempt. */ export declare const RESPAWN_RATE_LIMIT_COOLDOWN_MS: number; /** What "recent" means to `recent_success` and `active_pr`. Longer would park * legitimate retries; shorter would not outlast a storm. */ export declare const RESPAWN_RECENT_WINDOW_MS: number; /** A run that reached an outcome, so its `endedAt` is a fact rather than a maybe. */ export type SettledRun = TodoRun & { endedAt: string; }; /** * Whether an automated re-dispatch of this Todo should proceed. * * `rate_limit_cooldown` is evaluated FIRST and that ordering is load-bearing: * one error text carries several classes, and quota vocabulary ("usage limit", * "exceeded limit") routinely arrives alongside the credential vocabulary that * makes it `auth-terminal` too. Losing that race parks the Todo behind a guard * only a human can clear — while the quota window clears itself. */ export declare function checkRespawnGuard(workItemId: string, now?: Date, opts?: RespawnGuardOptions): RespawnGuardVerdict; /** * Record a hold, so a Todo that was not picked up says why rather than going * quiet. Audit-only: a guard is a decision about a dispatch, not a change to * the Todo. */ export declare function appendRespawnGuardHold(workItemId: string, hold: RespawnGuardHold, actor: string): void; export declare function lastSettledRun(runs: TodoRun[]): SettledRun | undefined; //# sourceMappingURL=respawn-guards.d.ts.map