agentfootprint
Version:
The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.
115 lines • 6.82 kB
TypeScript
/**
* ContextError — the ONE visible finding type, named in the words people
* already use for these defects.
*
* Pattern: plain data + identity-keyed dedup. Pure.
* Role: everything a Context Integrity check detects is filed as
* exactly this shape, at every seam — a uniform finding is what
* makes findings a CORPUS (each one a labelled instance carrying
* its check, seam, subjects and witnesses) and what keeps the
* disposition accounting honest across seams.
*
* NAMING LAW: the `kind` is the plain software-defect name, never the
* algebra term — the people reading a finding are not reading the
* mechanism. The one guardrail that outranks the naming: never use a
* familiar name that is subtly wrong. ("State loss" for the evicted-
* identifiers failure would send an engineer hunting a storage bug that
* does not exist; the ledger held every identifier — they stopped being
* SERVED. `dangling-reference` is what a linker means and what happened.)
*/
import type { Assertion, SubjectRef } from '../assertion/types.js';
import type { IntegritySeam } from '../disposition/types.js';
/**
* The nine defect classes, by their plain names:
*
* | kind | means | mechanism |
* |---|---|---|
* | `invariant-violation` | two things that cannot both be true were both asserted | exclusion |
* | `unsupported-argument` | acted on a value nothing served | domain |
* | `dangling-reference` | offered an action whose inputs are no longer available | closure |
* | `duplicate-execution` | did settled work again | once |
* | `unsupported-claim` | stated something the record does not support | grounding |
* | `empty-lookup` | the run produced this value, and the lookup for it found nothing | join |
* | `column-type-mismatch` | a column holds something other than the type its tool declared | type |
* | `missing-column` | a column the tool declared is in none of its rows | presence |
* | `prior-turn-evidence` | every value in the answer was served before this turn | recency |
*
* `empty-lookup` is the one class that is ADVISORY BY CONSTRUCTION (9.77.0) —
* every finding it files carries `advisory: true`, because an empty result
* can be perfectly true and nothing in the library can tell a true absence
* from a lookup that could never have matched. It is a place to look, not a
* defect that was proven. It is deliberately NOT `dangling-reference`, whose
* meaning is the opposite: there the ground has left reach, here the ground
* is in reach and the lookup came back with nothing.
*
* `column-type-mismatch` and `missing-column` (9.78.0) are two classes rather
* than one ON PURPOSE, and the field failure they come from is the argument:
* a LUN of 0 stored as `''` and a LUN column that was never delivered send a
* person to two different files, and a checker that said only "something is
* off with logical_unit_number" would have helped with neither. Unlike
* `empty-lookup`, neither is advisory: a column declared `number` that holds
* a string is not a place to look, it is a broken promise — though what the
* check can see about it is bounded, and the bound ships as
* `COLUMN_TYPE_CEILING` in every message.
*
* `prior-turn-evidence` (9.83.0) is the family's SECOND advisory-by-
* construction class, and for the same shape of reason as `empty-lookup`:
* referring back to an earlier result is ordinary conversation, so an answer
* built entirely from earlier turns is a place to look and never a proven
* defect. It is deliberately NOT `unsupported-claim`, which is the opposite
* fact — there the answer says something the record contradicts, here every
* value in it is in the record and the question is only WHEN it got there.
* Its bound ships as `PRIOR_TURN_EVIDENCE_CEILING` in every message.
*/
export type ContextErrorKind = 'invariant-violation' | 'unsupported-argument' | 'dangling-reference' | 'duplicate-execution' | 'unsupported-claim' | 'empty-lookup' | 'column-type-mismatch' | 'missing-column' | 'prior-turn-evidence';
/** One detected context error — a labelled instance, automatically. */
export interface ContextError {
readonly kind: ContextErrorKind;
readonly seam: IntegritySeam;
/** The stamped subjects this is about. */
readonly subjects: readonly SubjectRef[];
/** The two-or-more assertions that prove it — copies, plain data. */
readonly witnesses: readonly Assertion[];
/**
* WHICH RELATION the defect is about, when the subjects alone do not
* determine it (9.61.0).
*
* The substrate already treats the predicate as identity-bearing —
* `assertionKey` is `(subject, predicate, epoch)` — and a finding's
* identity was strictly coarser than the algebra key one file over. That
* gap lost real defects: two claims about two FIELDS of one entity
* rendered the same identity, so the second was deduplicated away and the
* event channel disagreed with the disposition ledger about the same run.
*
* Absent on the checks whose subjects already discriminate (a tool name
* is the whole story there), which keeps their identities byte-identical.
*/
readonly predicate?: string;
/** The epoch the conflict was judged at, when the witnesses carry one. */
readonly epoch?: number;
/** True when every witness is canary material — never mixed with real. */
readonly synthetic?: true;
/**
* A SOFTER CLASS (9.61.0): the finding reports doubt rather than
* contradiction — today, an answer that declines to claim (`null`,
* `'unknown'`) a fact the run verified. Presence-only, and counted apart
* from real defects: an advisory is a thing worth seeing, never a thing
* that was wrong. `contextErrorIdentity` does not read it, so an
* advisory and a contradiction about the same subjects would collapse to
* one finding — which is correct: they are the same disagreement, and
* the first filing wins.
*/
readonly advisory?: true;
/** One plain sentence a person can act on. States the defect, never a verdict on who is right. */
readonly message: string;
}
/**
* The identity a finding deduplicates by: the same defect about the same
* subjects at the same seam is ONE finding however many passes re-detect
* it — a findings channel that spams recreates the noise problem it
* exists to prevent.
*/
export declare function contextErrorIdentity(e: ContextError): string;
/** Keep the FIRST filing of each identity, in input order. */
export declare function dedupeContextErrors(errors: readonly ContextError[]): readonly ContextError[];
//# sourceMappingURL=types.d.ts.map