import type { BackgroundAgentRecord } from "./background-agent-store.js";
/**
 * The protocol's task states, as ONE list — the type is derived from it, so a value and its type can
 * never drift apart, and a consumer validating wire input iterates the same source the mapping does.
 */
export declare const A2A_TASK_STATES: readonly ["submitted", "working", "input-required", "completed", "canceled", "failed", "rejected", "auth-required", "unknown"];
/** One A2A task state (see {@link A2A_TASK_STATES}). */
export type A2ATaskState = (typeof A2A_TASK_STATES)[number];
/**
 * Durable row → protocol state. TOTAL and pure: every (status, stoppedBy) pair has an answer, and the
 * answer depends on nothing else.
 *
 * The four direct arms:
 * - `running` → `working`;
 * - `completed` → `completed`;
 * - `failed` → `failed`;
 * - `parked` → `input-required`. This engine's `parked` is durably suspended ON AN APPROVAL CHECKPOINT
 *   — a NARROWING of the protocol's "waiting for the caller to supply something": the something is an
 *   approval decision, and it is redeemed through the durable approval inbox, not by a message reply.
 *
 * `killed` splits on the attribution, because the protocol distinguishes what this engine records in a
 * second field: a stop by `user` or `parent` is a deliberate cancellation (`canceled`), while a
 * `system` stop, an unrecognized source, or NO attribution at all is not — those are terminations the
 * requester never asked for, and `canceled` would assert an intent nobody expressed. `failed` is the
 * honest terminal for them.
 *
 * FOUR PROTOCOL STATES HAVE NO ARM HERE, as a fact of the type rather than an omission:
 * - `submitted`, `rejected`, `auth-required` describe moments BEFORE a durable row exists (registration
 *   and start are one step in this engine; rejection and an authorization demand are admission-time
 *   outcomes of the serving layer, which has no row to project yet);
 * - `unknown` belongs to the READ-PROJECTION layer one level up — the poll face's `not_local` arm,
 *   where a `running` row was written by ANOTHER engine instance and this instance genuinely cannot
 *   speak to its outcome. That arm has no record-level answer to give and never calls this function; a
 *   caller holding a record, by contrast, always has the state. Keeping the two apart is the boundary
 *   this function is drawn on.
 * The switch is exhaustive over `status` with NO default arm, so tsc — not this comment — is what fails
 * when a sixth durable status is added.
 */
export declare function toA2ATaskState(record: Pick<BackgroundAgentRecord, "status" | "stoppedBy">): A2ATaskState;
/** A reversal that keeps everything the protocol state carried. */
export interface A2ATaskStateReversalFaithful {
    lossy: false;
    status: BackgroundAgentRecord["status"];
}
/**
 * A reversal that DROPPED something. `note` is required on this arm by construction: the whole purpose
 * of the discriminant is that a consumer which branches on `lossy` cannot reach the lossy case without
 * text describing what it lost.
 */
export interface A2ATaskStateReversalLossy {
    lossy: true;
    status: BackgroundAgentRecord["status"];
    note: string;
}
/** The result of {@link fromA2ATaskState}: discriminated on `lossy`. */
export type A2ATaskStateReversal = A2ATaskStateReversalFaithful | A2ATaskStateReversalLossy;
/**
 * Protocol state → durable row status. Nine onto five, so five arms lose information; each of those
 * says so (`lossy: true`) and names what it dropped, rather than returning a bare status that reads as
 * an exact translation.
 *
 * `lossy: false` holds EXACTLY for the states that survive `toA2ATaskState(fromA2ATaskState(s))`
 * unchanged — that biconditional is pinned as a property test (`test/a2a-task-state.test.ts`), so the
 * flag is tied to an observable fact and not to an author's intent.
 *
 * The exhaustive switch (no default arm) makes a newly-declared protocol state a compile error here.
 */
export declare function fromA2ATaskState(state: A2ATaskState): A2ATaskStateReversal;
