/** * empty-lookup — the run itself produced this identifier, and the lookup for * it found nothing. Filed at the WRITE seam, as an advisory, never an * accusation. * * Pattern: pure function over (one finished call, the results its declared * producers served); the domain check, one seam later than * `unsupported-argument`. * Role: the decidable fragment of "did this tool answer, or did it only * appear to answer?". * * THE MEASURED FAILURE. A triage agent's reverse-lookup tool filtered a * column before a pivot, so the column did not exist yet and EVERY reverse * lookup returned an empty result — for every identifier, always. The tool * then answered SUCCESSFULLY with an empty list, and the agent reported in a * table, with confidence, that the device was "not currently logged in to any * port on the collected switches" and advised checking physical cabling. It * was logged in the whole time. Nothing in the framework noticed, because an * empty result from a broken filter is byte-identical to an empty result from * a genuine absence. * * WHAT THE LIBRARY ALREADY KNOWS, and this check is nothing more than the * join of the two: * (a) the identifier was GROUNDED — it came out of an earlier tool result * in THIS run, from a tool the consumer's author named in * `Tool.argumentsFrom`; * (b) the lookup keyed on it came back EMPTY. * When the run produced the identifier and the lookup for it finds nothing, * that is worth filing. It is not worth accusing anyone of. * * THE CEILING, and it is the whole reason this is an advisory: an empty * answer can be perfectly true. The device may exist and simply have no * logins right now. NOTHING IN THIS FILE CAN TELL THOSE APART, and nothing in * this file pretends to — the finding says "here is a pair worth a look", the * record carries the ceiling sentence verbatim, and the same finding is filed * for the true absence and the broken filter alike. A check that guessed * which one it was looking at would be inventing the certainty the field * failure was made of. * * DECLARED, NEVER INFERRED — the `argumentsFrom` precedent, THIRD use. A tool * is this check's subject only because its author said its arguments come * from another tool's results. One declaration now arms three seams: * `dangling-reference` asks whether the ground is still in reach when the * tool is OFFERED, `unsupported-argument` whether the value the model chose * came from that ground when the tool was CALLED, and this whether the ground * the run really did serve then found anything when the tool ANSWERED. * * WHAT COUNTS AS EMPTY — and what this refuses to judge. See * {@link readLookupResult}. A rowset is counted, never interpreted; an * absence is read from the marker its own helper mints. Every other shape a * tool has ever returned — a sentence, an object, a `null`, a claim ticket — * is BESPOKE: the library cannot see whether it holds rows, so the encounter * is `not-applicable` and says so in the ledger. That row is the point. A * check that silently skipped what it could not read would be the decoration * the disposition family exists to make impossible. * * Detection only. Nothing here blocks, retries, rewrites or delays anything; * the result the model reads is the result the tool returned. */ import type { Disposition } from '../disposition/types.js'; import type { ContextError } from '../finding/types.js'; /** * THE CEILING, as one string with one owner. * * Quoted verbatim into every finding's message, into the check's README and * into its docs page, so the bound cannot drift out of one of them and leave * a reader thinking the library knows more than it does. */ export declare const EMPTY_LOOKUP_CEILING: string; /** What the library could read about a finished lookup's result. */ export interface LookupResultReading { /** `'rowset'` — an array, counted. `'absence'` — the `absent()` envelope. */ readonly shape: 'rowset' | 'absence'; readonly empty: boolean; /** Rows counted, for a rowset. Absent for an absence, which declares itself. */ readonly rows?: number; } /** * READ a finished result's shape, or decline to. * * The two readable shapes, and why only these two: * * • a **rowset** — an array. Its length is COUNTED, not interpreted: zero * rows is zero rows, and no judgement about what the tool meant is * involved. This is the shape the recorded failure actually returned. * • an **absence** — the `absent()` envelope, whose author said in so many * words "the search ran and matched nothing". * * Everything else returns `undefined`, which the caller files as * `not-applicable`. A prose sentence, a bespoke `{ rows: [...] }` wrapper, a * `null`, a placement claim ticket — the library cannot see rows in any of * them, and guessing is how a checker starts lying. * * @param value the tool's own answer, as it returned it. * @param declaredAbsence whether `readAbsence` recognized the value. PASSED * IN rather than re-derived here on purpose: the `af_absent` marker has * exactly one owner (`core/agent/coverage/absent.ts`), a second spelling of * a reserved word would eventually disagree with the first, and * `src/integrity/` stays a leaf that imports no agent code. */ export declare function readLookupResult(value: unknown, declaredAbsence: boolean): LookupResultReading | undefined; /** One finished call to a tool whose author declared where its arguments come from. */ export interface EmptyLookupCall { /** The CONSUMER — the tool that was called and answered. */ readonly toolName: string; /** The provider's id for this call — what the witness points a reader at. */ readonly toolCallId: string; readonly args: Readonly>; /** `Tool.argumentsFrom` — the tools whose results were meant to ground these arguments. */ readonly argumentsFrom: readonly string[]; /** What the library could read about the result — `undefined` = bespoke shape. */ readonly reading: LookupResultReading | undefined; } /** One earlier tool result this run served, with the tool that produced it. */ export interface ProducedResult { readonly toolName: string; /** The result exactly as the run served it into the conversation. */ readonly text: string; } /** One encounter's outcome: the findings, and the disposition it earns. */ export interface EmptyLookupEncounter { readonly findings: readonly ContextError[]; /** * The ledger row this encounter files — computed HERE, beside the rules * that decide it, so "the library refused to judge this shape" is provable * without a live agent. */ readonly disposition: Disposition; } /** * Judge one finished call to an armed tool. * * @param call the call and what the library could read of its result. The * caller has already established the tool declared `argumentsFrom`; * nothing here re-decides who is a subject. * @param produced every tool result this run served BEFORE this call, with * the tool that produced each. Filtered to the declared producers here. * @param epoch the run iteration, stamped on every witness. */ export declare function emptyLookupOf(call: EmptyLookupCall, produced: readonly ProducedResult[], epoch: number): EmptyLookupEncounter; //# sourceMappingURL=check.d.ts.map