/**
 * absent — an absence that names its own coverage.
 *
 * Pattern: minted by a helper, RECOGNIZED by the framework (the tool-effects
 *          envelope precedent). A return shape the framework does not
 *          understand is a convention, and a convention cannot set a status,
 *          keep a value out of the evidence corpus, or stop a retry loop.
 * Role:    core/ layer, pure. The dispatch loop calls `readAbsence` at the
 *          execute boundary; `absent()` is what a tool author writes.
 * Emits:   N/A (the caller emits `agentfootprint.tools.absent`).
 *
 * ## The direction-of-error argument — the whole point of this file
 *
 * A tool that finds nothing returns *something*: an empty array, a `null`, a
 * sentence. From any of those a model cannot tell **"I looked and there is
 * nothing"** from **"I could not look"**. That confusion is not symmetric,
 * and the asymmetry is what makes it worth a primitive:
 *
 *   • a *nothing-found* misread as an *outage* sends someone to investigate a
 *     collector that is working perfectly — expensive, and self-correcting.
 *   • an *outage* misread as *nothing-found* declares a system healthy that
 *     was never checked — cheap, silent, and wrong in the direction that
 *     hurts.
 *
 * So the two must not share a shape. An error is a `role: 'tool'` result with
 * `error: true`, a message, and no coverage. An absence is this: a result
 * that RAN, carries the ground it covered, and says out loud that asking
 * again changes nothing.
 *
 * ## Why the note is never interpolated
 *
 * Tool results are the evidence gate's corpus, so an absence that echoed the
 * model's own arguments into that corpus would GROUND every identifier a model
 * invented, as long as it handed the invention to one tool that found nothing.
 * That is laundering an invention through a failed lookup — the same bug
 * `evidence/frames.ts` exists to stop on the other side of the conversation.
 *
 * The gate therefore withholds `looked_for` (see `coverage/evidence.ts`): it
 * is the one field whose job is to quote the request. The record-only item
 * keys `short` and `kind` are withheld with it — a short form restates
 * `what`, so nothing is lost, and it is the field an author is most tempted to
 * personalise. Everything else the absence carries — the coverage lists, the
 * author's `tryInstead` and `tryInsteadTool`, any extra key the tool attached
 * to the envelope — is the TOOL speaking about the world and does ground,
 * because an answer that follows the absence's own advice must not be called
 * ungrounded for doing so.
 * The note is kept free of interpolation for the same reason the exclusion
 * exists: static library text has nothing of the caller's to leak.
 *
 * ## A suggestion to try another tool is typed, never parsed (9.113.0)
 *
 * `tryInstead` is ONE sentence, for the model; nothing in this library reads
 * a tool name out of it. When the sentence points at another tool, the author
 * names that tool beside it — `tryInsteadTool: { tool, why? }` — and the
 * envelope carries it under its OWN key, `try_instead_tool`. Its own key, not
 * `try_instead`: that field has been a string since it shipped and every
 * reader typed against `ToolAbsence` reads it as one, so a second shape there
 * would be dropped by each of them without a word. `tools.absent` carries
 * both, as declared. ONE rule set decides what each is ({@link readSentence},
 * {@link readToolSuggestion}): `absent()` refuses by it and the recognizer
 * reads by it, so a mint and a read cannot disagree.
 */
import type { AbsenceAmongDeclaration, AbsenceDeclaration, Coverage, DeclaredAbsenceDeclaration, DeclaredToolAbsence, ToolAbsence, TryInsteadTool } from './types.js';
import { ABSENCE_MARKER, readAbsence } from './recognize.js';
export { ABSENCE_MARKER, readAbsence };
/**
 * The static sentence every absence carries. Says the three things the field
 * implementation proved a model needs: that the call SUCCEEDED, that nothing
 * was substituted, and that a retry is futile. The third clause is the one
 * that ends the loop.
 */
export declare const ABSENCE_NOTE = "The search ran and matched nothing. This is an ANSWER, not an error: nothing failed, nothing was substituted for what was asked, and calling this tool again with the same arguments returns this same result. `checked` is the ground this answer covers; anything under `not_checked` or `cannot_cover` is ground it does NOT cover, and reaching that needs a different question, not a retry.";
/**
 * The note a COMPOSED absence is served (`Tool.search`): `checked` there is
 * what the library composed from the call's arguments and the tool's declared
 * defaults, so the note cannot say "nothing was substituted for what was
 * asked" — a declared default, or an argument the call left out, may have
 * narrowed the search. It keeps what stays true (the call ran, a retry
 * returns the same) and points at the gaps. Static, never interpolated.
 */
export declare const ABSENCE_NOTE_COMPOSED = "The search ran and matched nothing \u2014 the call did not fail, and calling this tool again with the same arguments returns this same result. `checked` is the ground this answer covers, as the arguments of the call and the defaults the tool declares set it: where an argument was not sent, a default the tool applies may have narrowed the search. Anything under `not_checked` or `cannot_cover` is ground it does NOT cover, and reaching that needs a different question, not a retry.";
/**
 * The note the MODEL is served in place of {@link ABSENCE_NOTE} when the
 * absence's own period is `partly-held` or `not-held` (honesty step 7b, bench
 * round 1) — `coverage/read.ts` · `strip` swaps it in and appends the period's
 * one clause. It keeps what stays true (the call ran, a retry returns the same
 * result) and drops the two completeness claims that do not: "nothing was
 * substituted for what was asked" and `checked` as the whole ground. Static,
 * never interpolated, never minted — the tool's own output keeps
 * {@link ABSENCE_NOTE}.
 */
export declare const ABSENCE_NOTE_HELD_ONLY: string;
/**
 * Say "I looked, and there is nothing" in a way a model cannot read as a
 * failure — and cannot productively retry.
 *
 * Returns the value a tool's `execute` should return. The framework
 * recognizes it at the dispatch boundary and gives it a delivered status of
 * `'absent'` (routable by `onToolStatus`), a `tools.absent` event, and an
 * evidence-corpus rule of its own.
 *
 * Refuses (throws, where it is called) a declaration it cannot honor — and
 * any key the declaration does not have, naming the spelling meant when the
 * key is a casing slip (`not_checked` → `notChecked`), so a list declared
 * from plain JavaScript or JSON cannot vanish without a word. Every refusal
 * starts `refused: `: inside `execute` it becomes the call's error result,
 * which the model reads.
 *
 * Since honesty step 7b an absence also says WHERE it looked and WHEN —
 * `provenance: { measuredAt, source }`, the shape and rules `describedResult()`
 * uses — and what time its read covered — `period: { queried, held, readAt? }`,
 * ISO 8601 instants with a zone (`held` may be `'unknown'`). "Searched the 02:00
 * export — nothing" becomes data; the results layer judges the period.
 *
 * A name looked up in a known list is a search over that list: declare the
 * list as `among` (see {@link AbsenceAmongDeclaration}) and the mint composes
 * the names facet, the gap "names outside <source>" — which only
 * `among.authoritative` removes; a `partial` read also gets "not every name in
 * <source> was read", which nothing removes — and the `provenance`. The names are read only
 * to check `count`; none is served.
 *
 * @example a port-lookup tool that found no matching FLOGI
 *   defineTool({
 *     name: 'flogi_for_port',
 *     description: 'FLOGI entries for one interface',
 *     inputSchema: { type: 'object', properties: { switch: { type: 'string' },
 *       port: { type: 'string' } }, required: ['switch', 'port'] },
 *     execute: ({ switch: sw, port }) => {
 *       const rows = fcns.flogi(sw, port);
 *       if (rows.length > 0) return rows;
 *       return absent({
 *         what: `FLOGI entries on ${port}`,
 *         checked: [
 *           `${sw}: the live fcns database`,
 *           { what: 'window: the last 24h', why: 'FLOGI history retention on this fabric' },
 *         ],
 *         notChecked: [{ what: 'the archived FLOGI history', why: 'older than the 24h window' }],
 *         cannotCover: [{ what: 'ports on the peer fabric',
 *           why: 'this collector is scoped to one fabric' }],
 *         tryInstead: 'Ask for a different interface, or query the peer fabric by name.',
 *       });
 *     },
 *   });
 */
export declare function absent(decl: DeclaredAbsenceDeclaration): DeclaredToolAbsence;
export declare function absent(decl: AbsenceDeclaration | AbsenceAmongDeclaration): ToolAbsence;
/** The absence's coverage, in the normalized three-list shape everything
 *  downstream (the event, the answer block) reads. */
export declare function coverageOfAbsence(absence: ToolAbsence): Coverage;
/**
 * The absence's sentence, read by the rules `absent()` mints by. `undefined`
 * when it declared none, AND when it declared one those rules refuse: an
 * envelope minted elsewhere (a non-JS tool, a hand-built value) is read,
 * never repaired, and the absence itself is still an absence either way.
 */
export declare function tryInsteadOfAbsence(absence: ToolAbsence): string | undefined;
/**
 * The absence's typed tool, read by the same rules — a copy, never the
 * object the envelope holds. `undefined` when it declared none, or one those
 * rules refuse (see {@link tryInsteadOfAbsence}).
 */
export declare function tryInsteadToolOfAbsence(absence: ToolAbsence): TryInsteadTool | undefined;
//# sourceMappingURL=absent.d.ts.map