/** * ledger — what a clean result does NOT rule out. * * Pattern: a wrapper the framework recognizes, minted by a helper (the * `absent()` shape one level up: same vocabulary, different claim). * Role: core/ layer, pure. `coverage()` is what a tool author writes; * `readCoverageLedger` is what the dispatch loop calls. * Emits: N/A (the caller emits `agentfootprint.tools.coverage_declared`). * * ## The problem, stated as narrowly as it deserves * * An agent answers confidently from partial coverage. "Everything looks fine" * is produced from four checks that passed, and arrives with no way to tell * whether *fine* means **verified** or **unexamined** — whether the fifth * thing was healthy or was never looked at. The evidence gate (9.35.0) is the * sibling of this: the gate catches invented VALUES, this catches unstated * LIMITS. Both are ways an answer can be false while every token in it is * real. * * A ledger is not a caveat and not a disclaimer. It is three lists the TOOL * knows and the model does not: what it checked, what it did not check, and * what it can never cover. Only the tool knows the third one, which is why * this cannot be prompt engineering. * * ## Why the wrapper, and not a field on the result * * The alternative — teaching the framework to read a `coverage` key off any * returned object — would make every domain object that happens to have one * change behavior. The wrapper is opt-in by construction: `coverage(x, …)` * produces a shape that did not exist before, so nothing that ever ran can * become a ledger by accident. Same argument as the effects envelope's strict * recognizer, same guarantee. */ import type { Coverage, CoverageDeclaration, CoveredResult } from './types.js'; /** The reserved key that makes a ledger recognizable. */ export declare const COVERAGE_MARKER = "af_coverage"; /** * The static sentence every ledger carries. The last clause is the OFFER half * of survival — the model is told to carry the limits into its answer. The * ENFORCEMENT half (`.limitsTravelWithTheAnswer()`) does not depend on the * model obeying it; see `answer.ts` for why both exist. * * "the call this result answers", not "this call" (9.86.1): the note rides a * tool result, which is re-read on every later call of the turn, and a bare * `this call` there denotes whichever call is reading it. The container * deictic's own anchor names the call instead. */ export declare const COVERAGE_NOTE: string; /** * Return a verdict with its own boundary attached. * * The model reads `{ af_coverage: {…}, result: }` — boundary * first, deliberately: a limit placed after a long result is a limit that gets * skimmed past. The framework records the ledger and, with * `.limitsTravelWithTheAnswer()` configured, appends it to the run's final * answer where the model cannot drop it. * * @example the highest-stakes tool in a triage agent * defineTool({ * name: 'replication_health', * description: 'Replication health across the estate', * inputSchema: { type: 'object', properties: {} }, * execute: async () => { * const { verdict, ndmTimedOut } = await checkReplication(); * return coverage(verdict, { * checked: ['SRDF pair state on all 4 arrays (live query)'], * notChecked: ndmTimedOut * ? [{ what: 'NDM migration sessions', why: 'the API timed out — ask again' }] * : [], * cannotCover: [ * { what: 'host-side multipathing', why: 'no collector runs on the ESX hosts' }, * ], * }); * }, * }); */ export declare function coverage(content: T, decl: CoverageDeclaration): CoveredResult; /** * Recognize (or decline to recognize) a value as a covered result. STRICT for * the same reason `readAbsence` is: only a plain object carrying a plain * `af_coverage` object AND a `result` key qualifies. */ export declare function readCoverageLedger(value: unknown): CoveredResult | undefined; /** The ledger's coverage, in the normalized three-list shape. */ export declare function coverageOfLedger(covered: CoveredResult): Coverage;