import type { WorkflowTodoEventClaimOutcome, WorkflowTodoEventFeed, WorkflowTodoStatusEvent } from "../work-items/workflow-event-feed.js"; import type { TriggerNode, WorkflowDefinition } from "./model.js"; /** * What becomes of a Todo event once the trigger filters have spoken: which * definitions are told why they did not run, and whether the event is sealed or * put back for the next drain. * * It sits beside the trigger service rather than inside it because the service's * own job is indexing triggers, claiming work, and starting runs, and none of * that needs to know how a decline is worded or when an event may be put back. */ export interface IndexedTrigger { definition: WorkflowDefinition; trigger: TriggerNode; } /** Which filter refused a Todo event, and why. The `filter` half exists because * `label` is the one refusal that can be a race rather than a decision. */ export interface TodoMismatch { filter: "label" | "other"; reason: string; } export interface TodoCandidate extends IndexedTrigger { mismatch: TodoMismatch | undefined; } /** Definition id to the newer event that superseded this one for that definition. */ export type SupersededBy = ReadonlyMap; export declare const NOTHING_SUPERSEDED: SupersededBy; /** Whether the Todo is still sitting where this event put it. Once it has moved * on the event is stale, whatever a later write does to the Todo. */ export declare function stillWhereTheEventLeftIt(event: WorkflowTodoStatusEvent): boolean; /** Record WHY a candidate did not run. A Todo event that a filter refused, or * that a newer event superseded, otherwise completes silently, which is * indistinguishable from a broken trigger. A `label` refusal is provisional: * `settle` may defer the event on it, and whatever settles the event later * overwrites what is recorded here. */ export declare function declinedOutcomes(event: WorkflowTodoStatusEvent, candidates: ReadonlyArray, superseded: SupersededBy, deferred: boolean): WorkflowTodoEventClaimOutcome[]; /** * Close the event, or put it back for the next drain. * * Labels are read when the event DRAINS, and the drain is kicked by the status * write, so a Todo labelled a moment after it moved is judged unlabelled — a * race, not a decision, and sealing the event there is what leaves the Todo * sitting at its arming status with nothing armed and nothing that will ever * look again. `todoMismatch` judges `label` last, so a label refusal means every * other filter on that definition was satisfied and the label alone is missing. * * Deferral therefore sits UPSTREAM of supersession: while a definition is * waiting on its label it is not in the running for this event, so it can * neither be declined as superseded nor beat a newer event. When the label * lands it re-enters the supersession gate on the next drain, as a fresh * arrival would. * * Only the definitions the label refused go back in. The event is shared by * every definition bound to the status, and the ones that just started must not * be considered again when the label lands, or they run twice. */ export declare function settle(feed: WorkflowTodoEventFeed, event: WorkflowTodoStatusEvent, candidates: ReadonlyArray, outcomes: WorkflowTodoEventClaimOutcome[]): void; /** Refuse every candidate that survived the filters for the same reason, and * close the event on it. What that reason can be is the caller's business. */ export declare function suppressAll(feed: WorkflowTodoEventFeed, event: WorkflowTodoStatusEvent, runnable: ReadonlyArray, outcomes: WorkflowTodoEventClaimOutcome[], reason: string): number; //# sourceMappingURL=todo-event-outcome.d.ts.map