/** * CheckpointGate — agenticow-backed checkpoint/rollback gate for autopilot * loops and long-horizon workflows (agenticow integration, step 3). * * ── The pattern ─────────────────────────────────────────────────────────── * Before a risky loop tick that mutates `.rvf` memory, take an O(1) agenticow * checkpoint (162 bytes, fixed cost — see mcp-tools/agenticow-tools.ts). Run * the tick. If it regresses — throws, or the caller's verdict says the outcome * got worse (verifier fail / error / worse metric) — roll the memory back to * the checkpoint. Rollback is O(edits-since-checkpoint), NOT an O(N) rebuild, * and the earlier history stays intact via the `.agenticow.json` lineage * manifest. On success the checkpoint is simply kept as the new good baseline. * * The three lifecycle verbs (checkpoint / rollback / promote) already exist in * the `agenticow` package and are surfaced as MCP tools in * `mcp-tools/agenticow-tools.ts`. This module is the *orchestration hook* that * calls them from inside a loop — the MCP surface is for agents, this is for * the in-process loop. * * ── Architectural constraint (ADR-150) ──────────────────────────────────── * `agenticow` lives in `optionalDependencies` and must NEVER be a hard runtime * dependency. This gate degrades gracefully in three ways, each of which runs * the tick UNGUARDED rather than failing: * 1. package missing → { degraded: true, reason: 'agenticow-not-found' } * 2. kill-switch env set → { degraded: true, reason: 'kill-switch' } * 3. no memory path configured → { degraded: true, reason: 'no-memory-path' } * The package is lazy-loaded on the first guard() call, so importing this * module has zero startup cost. * * The optional-dep loader + path/label/lineage helpers are the canonical ones * from `mcp-tools/agenticow-loader.ts` — one implementation shared across every * agenticow consumer (verbs, swarm branches, speculative, oracle, this gate). * * @module @claude-flow/cli/services/checkpoint-gate */ /** * Env var pointing at the `.rvf` memory file that a long-horizon loop mutates. * When set, the autopilot loop opts in to checkpoint/rollback around each tick. * When unset, the gate is a transparent pass-through. */ export declare const CHECKPOINT_MEM_ENV = "CLAUDE_FLOW_AUTOPILOT_CHECKPOINT_MEM"; /** * Kill switch. When truthy (`1`/`true`/`yes`), the gate never touches agenticow * and every guard() runs the tick unguarded. Lets an operator disable the * feature without changing config or code. */ export declare const KILL_SWITCH_ENV = "CLAUDE_FLOW_AGENTICOW_DISABLE"; /** Outcome of a guarded tick. `result` is undefined only when the tick threw * AND `rethrow` was disabled. */ export interface CheckpointGuardResult { /** The value fn() returned (undefined if it threw with rethrow:false). */ result: T | undefined; /** True when a checkpoint was actually taken before running fn. */ checkpointed: boolean; /** True when memory was rolled back to the checkpoint (throw or regression). */ rolledBack: boolean; /** True when the gate could not engage agenticow and ran fn unguarded. */ degraded: boolean; /** Machine-readable reason for degraded / rollback. */ reason?: string; /** The checkpoint label, when one was taken. */ checkpointLabel?: string; /** The error fn() threw, when rethrow was disabled. */ error?: unknown; } export interface GuardOptions { /** * Verdict function: return true when `result` represents a regression that * should trigger a rollback. Defaults to treating `{success:false}` / * `{ok:false}` / `{regressed:true}` as regressions. */ isRegression?: (result: T) => boolean; /** * When the tick throws: roll back, then re-throw the original error * (default true). Set false to swallow the error and return it on the * result object instead — useful when the loop must never crash. */ rethrow?: boolean; /** Optional checkpoint id to roll back to (defaults to most recent). */ checkpointId?: string; } export declare class CheckpointGate { /** True when the kill-switch env is set to a truthy value. */ static isKillSwitchSet(): boolean; /** The configured loop memory path, or undefined when the feature is off. */ static configuredMemPath(): string | undefined; /** * Lazy-load agenticow. Returns null when the package is absent (optional dep) * or the kill switch is set. Any *other* import error is re-thrown — a broken * install should be loud, a missing optional dep should be silent. */ private load; /** True when agenticow can be engaged (present + not killed). */ available(): Promise; /** * Take a checkpoint on the given `.rvf` memory file. Non-throwing except for * validation errors (path traversal, bad label) — those are surfaced so a * misconfiguration is caught early. */ checkpoint(memPath: string, label: string): Promise<{ ok: boolean; degraded: boolean; reason?: string; checkpoint?: unknown; }>; /** * Roll the given `.rvf` memory file back to a checkpoint. Discards edits made * since (O(edits-since-checkpoint)). Omit `checkpointId` to target the most * recent checkpoint. */ rollback(memPath: string, checkpointId?: string): Promise<{ ok: boolean; degraded: boolean; reason?: string; result?: unknown; }>; /** * Guard a risky loop tick with a checkpoint/rollback bracket. * * const outcome = await gate.guard(memPath, 'iter-7', async () => runTick()); * * Behaviour: * - No memPath / kill-switch / agenticow-absent → run fn unguarded, degraded:true. * - Checkpoint fails to engage (degraded) → run fn unguarded, degraded:true. * - fn throws → roll back to checkpoint, then re-throw (unless rethrow:false). * - fn returns a regression verdict → roll back, return result with rolledBack:true. * - fn succeeds → keep the checkpoint, return result with rolledBack:false. * * The gate is non-fatal: an internal agenticow failure never masks fn()'s own * result — if checkpointing throws, fn still runs unguarded. */ guard(memPath: string | undefined, label: string, fn: () => Promise, opts?: GuardOptions): Promise>; /** Roll back without throwing — used on the failure path so a rollback error * never masks the original tick failure. */ private safeRollback; } export declare function getCheckpointGate(): CheckpointGate; /** Reset the lazy-load cache — test-only. */ export declare function __resetCheckpointGateForTests(): void; //# sourceMappingURL=checkpoint-gate.d.ts.map