UNPKG

agentfootprint

Version:

The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.

81 lines (80 loc) • 4.33 kB
/** * Row "It understood" — how the question was routed to a skill, and whether the * decided skill reached the model. Also check 1, `decided-delivered`. * * Two vouchers, two lines: the SCORES are the app's (its scorer produced them), * the VERDICT is the library's (`skill.turn_routed`). Neither `decisive` nor * `relevance` is a confidence — confidence stays "not recorded" in v1. * * "Not delivered" is a claim of ABSENCE, so it needs proof: every system-prompt * composition of iterations 1..N is recorded and COMPLETE (the recorded skill * rows of that compose stage number exactly `sourceBreakdown.skill.count`). * Anything less and the check is unreachable — a missing row is never read as * "the skill was not given". * * The verdict has ONE reader, {@link routingVerdictOf}: the `skill.turn_routed` * event — or, on a RESUMED leg (whose recording holds that leg's events only), * the verdict the RouteTurn stage committed before the pause: `turnRoute` (by, * from, to, the rule's witness, the offered menu) and the scorer's * `entryScores` / `entryScorer`, carried in the state the run paused with * (`snapshot.initialState`) and on into the committed state the pointers land * in. Take 3 of the demo video: a resumed answer said "The routing happened * before the pause and is not in this record" while its record held the * verdict — the fold read the event only. What the state does NOT carry is * said by the lines that need it: the decider's model (the `noModel` line) and * whether the verdict was decisive (absent from the fact). */ import type { FactStatus, RecordPointer, RoutingFacts, Sentence } from '../types.js'; import { type ReadContext } from './common.js'; /** Refusals listed in `facts.routing.refusals`; refusal LINES (distinct rules) in the row. */ export declare const MAX_REFUSALS = 12; export declare const MAX_REFUSAL_LINES = 3; export type CheckState = 'reachable' | 'unreachable' | 'not-applicable'; export interface UnderstoodRead { readonly routing: RoutingFacts; readonly lines: readonly Sentence[]; readonly status: FactStatus; readonly check: CheckState; /** Set when the check is unreachable: the line that says why. */ readonly unreachable?: Sentence; /** Set when the decided skill was proven not delivered. */ readonly signal?: Sentence; /** Pointers behind a reachable check (for the "found nothing" line). */ readonly checkPointers: readonly RecordPointer[]; /** * On a resumed leg: `held` — the verdict was read from the state the run * paused with; `lost` — the graph routes, and neither an event nor that * state holds a verdict. Absent on a leg that was not resumed or that * routes nothing. */ readonly beforePause?: 'held' | 'lost'; } /** The routing verdict, as its one reader hands it to the row (see the file header). */ export interface RoutingVerdict { readonly by: string; readonly from?: string; readonly to?: string; readonly decisive?: boolean; readonly scorer?: string; /** The PERSON's words a tier-1 data rule matched. */ readonly witness?: string; /** How many skills the menu offered — absent when no menu was offered. */ readonly offered?: number; readonly deciderModel?: string; /** The scorer's ranked numbers, as recorded. */ readonly scores: readonly Readonly<Record<string, unknown>>[]; /** Where one verdict field lives on the record (`by`, `to`, `witness`, `deciderModel`). */ readonly at: (field: 'by' | 'to' | 'witness' | 'deciderModel') => RecordPointer; /** Where one score field lives on the record. */ readonly scoreAt: (index: number, field: 'id' | 'score') => RecordPointer; /** Read from the state the run paused with, not from an event of this leg. */ readonly held: boolean; } /** * The routing verdict this record holds: the `skill.turn_routed` event of * this leg, else — on a resumed leg — the verdict committed before the pause * ({@link heldVerdict}). `undefined` when neither holds one. An event whose * `by` cannot be read is passed over and counted, never read as "none". */ export declare function routingVerdictOf(ctx: ReadContext): RoutingVerdict | undefined; export declare function readUnderstood(ctx: ReadContext): UnderstoodRead;