UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

72 lines (71 loc) • 5.53 kB
/** * Why a resume could not run its approved action — ONE reading of the failure's code, shared by every * consumer that has to act on it: the reopen compensation (which {@link ReopenReason} a consumed * checkpoint returns to pending under) and the parked-resume receipt (the `cause` its caller branches on). * The answer is read from the failure's CODE — a thrown value's `cause` chain, or a failed result's * terminal code — never from its sentence; a code this table does not name reads as ABSENT (not known), * which each consumer answers in its own documented way rather than with a guessed cause. * * · `environment` — the leg's infrastructure failed (the workspace restore, an abort): the decision is * untouched, and a retry replays it; * · `session_gone` — the resumed agent's transcript session is missing; * · `transcript_corrupt` — the resumed agent's transcript session is THERE but cannot be read as a session: its log * has no header its store wrote (`corrupt_session`), or its entry tree is structurally unusable — a leaf or parent * entry that is not in the log (`invalid_session`). Distinct from `session_gone`: the bytes exist, so deleting or * restoring the transcript is the remedy, not re-creating a session; * · `tool_unavailable` — the approved tool is not available to the resumed leg (gone, replaced by a * different contract, or an inherited tool the drive cannot hand over): this approval cannot run, and a * fresh decision resolves it; * · `configuration` — the deployment's configuration refuses the resumed leg (a `config.*` door, the * pre-claim configuration screen, a re-supplied constraint chain that is missing or does not match its * installation record): a retry under the same configuration fails the same way; * · `decision_rejected` — the supplied decision does not fit the checkpoint (another gate's answer, an * unsafe payload, an input the constraints refuse): correct the decision and resubmit. */ import type { AssertAllKeysHandled } from "./ask-origin.js"; /** * design/80 D-1: why a consumed checkpoint was {@link import("./checkpoint-store.js").CheckpointStore.reopen | reopened} * (resolved → pending). The reason drives re-resume validation (§3 invariant #1): an `env_failed` reopen is a SYSTEM * RETRY of the ALREADY-APPROVED action — the re-resume MUST replay the persisted * {@link import("./checkpoint-store.js").ResolvedOutcome} winner, never a new vote — while a `tool_unavailable` reopen * (the action could not run, may now be invalid — P-7) lets a human RE-DECIDE with the tool present, so a fresh * operator decision IS allowed. * * `constraint_rejected` (F-012 L3) carries the same FRESH-REDECISION semantics as `tool_unavailable`: * a resolve was retracted because its decided INPUT failed a constraint re-adjudication (a frozen * ancestor projection / resume-edit policy denied the approver's edit) — the ask itself is unconsumed, * so the returned-to-pending row takes a fresh operator decision, never a forced replay of the * rejected one. Core's own edit re-adjudication runs PRE-CAS (nothing to reopen there); this reason * exists for a deployment lane that discovers the same rejection only after its own resolve landed * and must return the row to pending without inventing an out-of-vocabulary reason. * * `config_refused` carries the same FRESH-REDECISION semantics: the deployment's configuration refused * the resumed leg before its approved action started, so a retry under the same configuration fails the * same way — it is not a system retry, and the row takes a fresh decision (or the same one again once the * configuration is corrected). Which reason a failure reopens under is {@link reopenReasonOf}'s answer. */ export declare const REOPEN_REASONS: readonly ["env_failed", "tool_unavailable", "constraint_rejected", "config_refused"]; export type ReopenReason = (typeof REOPEN_REASONS)[number]; export declare const RESUME_STARTUP_CAUSES: readonly ["environment", "session_gone", "transcript_corrupt", "tool_unavailable", "configuration", "decision_rejected"]; export type ResumeStartupCause = (typeof RESUME_STARTUP_CAUSES)[number]; /** The cause a resume failure's code names; `undefined` when the code is absent or the table does not * name it. Every `config.*` code is a configuration door's refusal. */ export declare function resumeStartupCauseOf(code: string | undefined): ResumeStartupCause | undefined; declare const REOPEN_REASON_OF_CAUSE: { readonly environment: "env_failed"; readonly session_gone: "env_failed"; readonly transcript_corrupt: "env_failed"; readonly tool_unavailable: "tool_unavailable"; readonly configuration: "config_refused"; readonly decision_rejected: "constraint_rejected"; }; export type ReopenReasonTableCoversEveryCause = AssertAllKeysHandled<Exclude<ResumeStartupCause, keyof typeof REOPEN_REASON_OF_CAUSE>>; /** * The reason a consumed checkpoint whose approved action never started returns to pending under. A failure * whose cause is not known reopens as `env_failed`: the leg went away before the action ran, the human's * decision is untouched, and the retry replays it. */ export declare function reopenReasonOf(cause: ResumeStartupCause | undefined): ReopenReason; /** What the result of a returned resume leg says after its checkpoint was reopened, per reason. */ export declare function reopenedUnstartedSentence(reason: ReopenReason): string; export {};