/** * runbook/dispatch — the bridge's wrapper over `ctx.tools`. * * Pattern: decorator over {@link ToolDispatch}. The RAW dispatch (delivered * by the agent) returns every result untouched; POLICY about what a * result means belongs to the consumer — and this is the runbook's * policy: every inner outcome is RECORDED (for the coverage fold and * the provenance carry), and an inner ABSENCE short-circuits the * procedure unless the call site declared it survivable. * Role: core/runbook, pure. * Emits: N/A. * * WHY an absence short-circuits: "the inventory found nothing" IS the * runbook's answer, and it must go back EXACTLY as it arrived so the * framework still reads it as an absence — a verdict reached over a source * that answered "nothing here" would be the confident-partial-answer failure * this whole envelope exists to prevent. A stage that can genuinely carry on * without the source says so at the call site (`{ allowAbsent: true }`) and * owns stating the gap (usually as a coverage entry). */ import type { ToolAbsence } from '../agent/coverage/types.js'; import type { ToolDispatch } from '../tools.js'; /** One inner call, as the bridge recorded it. */ export interface InnerCallRecord { readonly tool: string; readonly outcome: 'ok' | 'absent' | 'error'; /** The raw returned value (`'ok'` and `'absent'` outcomes). */ readonly result?: unknown; } /** The marker property that survives any error wrapping between a stage and * the bridge's catch. */ declare const ABSENCE_SIGNAL: "af_runbook_absence"; /** * The control signal an un-survivable inner absence throws through the * chart. The engine commits staged state and rethrows (commit-on-error is * the law upstream), so the bridge catches this at `executor.run` and * returns the absence verbatim. */ export declare class RunbookAbsenceSignal extends Error { readonly absence: ToolAbsence; readonly [ABSENCE_SIGNAL] = true; constructor(absence: ToolAbsence, innerTool: string); } /** Recognize the signal on an error OR anywhere down its `cause` chain — an * engine layer that wraps the stage's throw must not defeat the pass-through. */ export declare function absenceSignalOf(err: unknown): RunbookAbsenceSignal | undefined; /** What `recordingDispatch` hands back: the dispatch the procedure closes * over, and the record the envelope folds. */ export interface RecordedDispatch { readonly tools: ToolDispatch; readonly records: readonly InnerCallRecord[]; } /** * Wrap the delivered dispatch (or its absence) for one runbook invocation. * * With NO dispatch delivered (`ctx.tools` absent — a hand-built context, a * door with no dispatch map) the wrapper is the fail-closed teacher: `has` * answers false and `call` refuses naming the fix, so a procedure that needs * inner tools fails loudly at its first call instead of half-running. */ export declare function recordingDispatch(delivered: ToolDispatch | undefined, runbookName: string): RecordedDispatch; /** * The definition-time probe dispatch — handed to the procedure factory ONCE * at `runbookAsTool(...)` so the bridge can read the chart's declared * contract. Stage bodies do not run at build; a factory that calls tools at * build time hears exactly why that cannot work. */ export declare function probeDispatch(runbookName: string): ToolDispatch; export {};