/** * Durable TODO coordination engine. * * The TODO subsystem is a coordination and progress-reporting facility. It is * NOT execution authority. This engine provides: * * - optimistic concurrency with a monotonically increasing revision; * - deterministic state hashing; * - internal bounded stale-revision read/rebase/retry; * - idempotent mutation intents; * - typed error taxonomy; * - progress-aware loop detection; * - a bounded, sanitized event log for operability and replay. * * It deliberately does not introduce a second TODO authority: it coordinates * around a single set of items/revision owned by the session. */ /** Canonical status set. Tool surfaces expose the subset pending/in_progress/completed. */ export type TodoStatus = "pending" | "in_progress" | "completed" | "cancelled" | "blocked"; /** The runtime status stored on items (compatible with the existing session TodoItem). */ export type TodoItemStatus = "pending" | "in_progress" | "completed"; /** Item as stored/coordinated by the engine. Structurally compatible with the session TodoItem. */ export interface TodoItem { id?: string; content: string; activeForm: string; status: TodoItemStatus; version?: number; createdAt?: number; updatedAt?: number; completedAt?: number; ownerRunId?: string; ownerAgentId?: string; } /** Patch-style operation for todo_update. */ export interface TodoPatchOp { id: string; status?: TodoItemStatus; activeForm?: string; content?: string; } /** A fully-typed mutation intent. */ export interface TodoMutationIntent { intentId: string; idempotencyKey: string; scopeId: string; baseRevision: number; requestedBy: { toolCallId: string; }; operations: TodoPatchOp[]; kind: "patch" | "replace_all"; replaceItems?: TodoItem[]; replaceStateHash?: string; } /** Typed recovery action for a TODO error. */ export type TodoRecoveryAction = "internal_read_and_rebase" | "return_current_snapshot" | "manual_reconciliation" | "disable_todo_for_turn" | "none"; /** Typed TODO mutation error. */ export interface TodoMutationErrorInput { code: "TODO_REVISION_STALE" | "TODO_REBASE_REQUIRED" | "TODO_REBASE_CONFLICT" | "TODO_ITEM_NOT_FOUND" | "TODO_ITEM_VERSION_CONFLICT" | "TODO_INVALID_STATUS_TRANSITION" | "TODO_DUPLICATE_INTENT" | "TODO_ALREADY_APPLIED" | "TODO_STATE_CORRUPT" | "TODO_SCOPE_MISMATCH" | "TODO_PERMISSION_DENIED" | "TODO_NO_PROGRESS_LOOP" | "TODO_TOOL_TEMPORARILY_DEGRADED"; requestedRevision?: number; currentRevision?: number; intentId?: string; conflictItemIds?: string[]; message?: string; } export interface TodoMutationError { code: TodoMutationErrorInput["code"]; recoverable: boolean; runMustContinue: boolean; requestedRevision?: number; currentRevision?: number; intentId?: string; conflictItemIds?: string[]; recoveryAction?: TodoRecoveryAction; message?: string; } export interface TodoRebaseResult { status: "not_needed" | "rebased" | "already_applied" | "conflict"; originalRevision: number; currentRevision: number; appliedRevision?: number; preservedConcurrentChanges: string[]; conflictItemIds: string[]; reasonCodes: string[]; } export interface TodoFailureFingerprint { scopeId: string; errorCode: string; intentHash: string; requestedRevision?: number; currentRevision?: number; conflictItemIds?: string[]; } export type TodoEventType = "TODO_STATE_READ" | "TODO_MUTATION_INTENT_CREATED" | "TODO_MUTATION_APPLY_STARTED" | "TODO_REVISION_STALE_DETECTED" | "TODO_INTERNAL_READ_COMPLETED" | "TODO_REBASE_STARTED" | "TODO_REBASE_SUCCEEDED" | "TODO_REBASE_CONFLICT" | "TODO_INTENT_ALREADY_APPLIED" | "TODO_MUTATION_COMMITTED" | "TODO_MUTATION_REJECTED" | "TODO_LOOP_CHAIN_STARTED" | "TODO_LOOP_CHAIN_RESET_BY_PROGRESS" | "TODO_NO_PROGRESS_LOOP_DETECTED" | "TODO_TOOL_DEGRADED" | "TODO_PROJECTION_DRIFT_DETECTED" | "TODO_PROJECTION_RECONCILED"; export interface TodoEvent { type: TodoEventType; at: number; revision?: number; intentId?: string; requestedRevision?: number; currentRevision?: number; conflictItemIds?: string[]; recoveryAction?: TodoRecoveryAction; } export interface TodoEngineState { currentRevision: number; progressEpoch: number; lastTodoReadRevision: number; snapshots: Array<{ revision: number; items: TodoItem[]; }>; ledger: Array<{ idempotencyKey: string; applicationRevision: number; applied: boolean; }>; events: TodoEvent[]; chain: { fingerprint: TodoFailureFingerprint; consecutive: number; lastAt: number; } | null; } export interface TodoEnginePersistence { load: () => TodoEngineState | undefined; save: (state: TodoEngineState) => void; } export interface TodoEngineLimits { /** Retained snapshot history (for rebase base lookup). */ maxSnapshots: number; /** Bounded idempotency ledger entries. */ maxLedger: number; /** Bounded event log length. */ maxEvents: number; /** Maximum internal rebase attempts per tool call. */ maxInternalRebaseAttempts: number; /** Bounded excessive-failure threshold for a single chain. */ maxNoProgressFailures: number; } export declare const DEFAULT_TODO_ENGINE_LIMITS: TodoEngineLimits; /** Deterministic state hash of a set of items. */ export declare function computeStateHash(items: TodoItem[]): string; /** Allowed transitions from a status. */ export declare function allowedTransitions(from: TodoStatus): ReadonlySet; /** * Validate a single status transition. * Repeating the current status is idempotent (allowed). */ export declare function validateTransition(from: TodoStatus, to: TodoStatus): { ok: boolean; reason?: string; }; export declare function fingerprintError(fp: Omit & { intentHash?: string; }): TodoFailureFingerprint; export declare class TodoEngine { private readonly now; readonly scopeId: string; readonly limits: TodoEngineLimits; private snapshots; private lastTodoReadRevision; private ledger; private events; private chain; private progressEpoch; private currentRevision; private readonly persistence?; constructor(scopeId: string, limits?: Partial, now?: () => number, persistence?: TodoEnginePersistence); private restore; private persist; /** Record authoritative non-TODO progress; breaks any failure chain. */ recordProgress(): void; /** * Record a todo read. Only counts as progress if the read returned a * newer revision than the last observed revision (identical reads do not * reset the chain). */ recordTodoRead(revision: number): void; getProgressEpoch(): number; recordReadSnapshot(revision: number, items: TodoItem[]): void; recordState(revision: number, items: TodoItem[]): void; getCurrentRevision(): number; private getSnapshot; /** * Look up a previously applied intent by idempotency key. * Returns true if the exact key was already applied. */ lookupApplied(idempotencyKey: string): boolean; recordApplied(idempotencyKey: string, applicationRevision: number): void; emit(event: Omit | TodoEventType): void; getEvents(limit?: number): TodoEvent[]; /** * Register a failure and return whether the chain should be treated as a * genuine no-progress loop (model-requested, consecutive, same fingerprint). */ registerFailure(fp: TodoFailureFingerprint): { blocked: boolean; consecutive: number; }; /** Reset the failure chain (self-healing path, e.g. internal rebase success). */ resetFailureChain(): void; private sameFingerprint; isBlocked(): boolean; /** * Deterministic, operation-aware rebase of a patch intent against the * current state. Uses the retained base snapshot when available to avoid * clobbering concurrent edits; otherwise applies conservative rules. */ rebase(baseRevision: number, currentRevision: number, currentItems: TodoItem[], ops: TodoPatchOp[]): TodoRebaseResult; typedError(input: TodoMutationErrorInput): TodoMutationError; getDiagnostics(): { scopeId: string; progressEpoch: number; lastTodoReadRevision: number; snapshotCount: number; ledgerCount: number; eventCount: number; chainActive: boolean; chainConsecutive: number; isLoopBlocked: boolean; }; } /** Derive a stable intent hash from the operations for fingerprinting. */ export declare function hashIntent(ops: TodoPatchOp[]): string; /** Generate a bounded, non-secret intent id. */ export declare function generateIntentId(seed: string, now: number): string; //# sourceMappingURL=todo-engine.d.ts.map