UNPKG

agentfootprint

Version:

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

98 lines • 5.3 kB
/** * delivered — one declared claim of an answer about to be DELIVERED, judged * for answer validation (`answer-validation/agentChecks.ts` turns the verdict * into a report row). * * Pattern: pure function over one `check.ts` · `compareClaim` result. * Role: the claim seam's verdict when it can WITHHOLD an answer. It reads * the detector's own selection (`compareClaim`: every row this run * settled for the declared `(entity, field)`) and adds the rules a * verdict that governs delivery needs, because that contract is * unscoped: rows from ANY tool result, with no scope or age check, * and any result carrying the semantics marker settles a fact — so * any row may be forged, foreign or stale. * * THE LAW — a reading can only withhold. With no reading the claim is not * checked (`uncollected`, `not-applicable`), and ONE more reading of the fact, * wherever it lands, never makes the verdict more permissive: a forged or * stale row can at most withhold an answer, never deliver one or make it * read "known". Pinned by the monotonicity property in * `test/answer-validation/agentChecks.test.ts`. That is why: * - AGREEMENT IS NEVER SUPPORT. It is `agrees` — `not-applicable`, exactly as * silent as no reading at all — and only the app's own checks can pass a * report. A contradiction still withholds. * - EVERY READING COUNTS, never the latest alone. A reading that settled * nothing (an `unknown(…)` Claim, a bare `null` or doubt word) beside the * answer's value, readings that disagree, and a reading that is not a * well-formed Claim each withhold, whatever else the run read. * - A CONTRADICTION FOUND IS REPORTED AS ONE. If the answer contradicts ANY * value the run read, the verdict is a contradiction — `contradicts` when * it contradicts every value read, `contradicts-a-reading` when the * readings themselves differ — never relabelled "could not tell" by * whatever else was read (a forged `null` beside a real reading included). * Withheld either way; only the label is at stake, and the label is honest. * - DOUBT IS NEVER AGREEMENT. Doubt on both sides (`null` or `'unknown'` — * in any case or spacing — or an unknown Claim) withholds; only an absence * a tool DECLARED (`known(null)`) agrees with the answer's doubt. * - VALUES COMPARE UNDER THE DECLARED NORMALIZATION (`evaluate.ts` · * `compareClaimValues`), never by exact JSON: `'Settled '` agrees with * `'settled'`, `42.5` with `'42.50'`. Kinds that cannot be compared safely * are `incomparable`, never `contradicts`. */ import { claimShapeOf, claimValueKey, compareClaimValues } from './evaluate.js'; /** Readings that are values: more than one exact key (or one with none) is a dispute. */ function disputed(values) { if (values.length < 2) return false; const keys = values.map((value) => claimValueKey(value)); return keys.includes(undefined) || new Set(keys).size > 1; } /** A declared absence (`known(null)`, or a declared doubt word): the one doubt a value settles. */ const declaredAbsence = (shape) => shape.kind === 'value' && shape.declared && claimShapeOf(shape.face).kind === 'doubt'; /** * Judge one compared claim for delivery, over EVERY reading of the fact this * run made. Pure and monotone: a reading added anywhere never turns a * withholding verdict into `agrees`, `declined` or `uncollected`. */ export function judgeDeliveredClaim(comparison) { if (comparison.kind === 'omitted') return 'omitted'; if (comparison.kind === 'uncollected') return 'uncollected'; const answer = claimShapeOf(comparison.claimed); const readings = comparison.rows.map((row) => ({ value: row.value, shape: claimShapeOf(row.value), })); if (answer.kind === 'malformed') return 'incomparable'; const malformed = readings.some((r) => r.shape.kind === 'malformed'); const doubts = readings.filter((r) => r.shape.kind === 'doubt'); const values = readings.filter((r) => r.shape.kind === 'value'); if (answer.kind === 'doubt') { // The answer claims nothing: only a reading that ALSO settled nothing // makes this agreement on doubt, which verifies nothing. if (malformed) return 'incomparable'; if (doubts.length > 0) return 'doubt-on-both-sides'; return values.every((r) => declaredAbsence(r.shape)) ? 'agrees' : 'declined'; } // A contradiction of any value read is the verdict, whatever else was read. const results = values.map((r) => compareClaimValues(r.value, comparison.claimed)); if (results.includes('contradicts')) { return results.every((result) => result === 'contradicts') ? 'contradicts' : 'contradicts-a-reading'; } if (malformed) return 'incomparable'; if (disputed(values.map((r) => r.value))) return 'disputed'; if (doubts.some((r) => r.shape.kind === 'doubt' && r.shape.declared)) return 'settled-unknown'; if (doubts.length > 0) return 'settled-doubt'; return results.every((result) => result === 'agrees') ? 'agrees' : 'incomparable'; } //# sourceMappingURL=delivered.js.map