UNPKG

agentfootprint

Version:

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

130 lines • 7.75 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.claimChecksOf = exports.evidenceCheckOf = exports.AGENT_CHECK_PREFIX = void 0; /** * The agent's own answer checks as rows of an answer-validation report * (`AnswerValidationOptions.agentChecks`). * * Pattern: pure adapters, one verdict in, `AnswerCheck` rows out. * Role: the one place the library's own checks speak the report's * vocabulary. `claimChecksOf` judges the candidate this validation * delivers through the claim seam's own selection * (`integrity/unsupported-claim/check.ts` · `compareClaim`) and its * delivery verdict (`integrity/unsupported-claim/delivered.ts` · * `judgeDeliveredClaim`), so a row can never accuse where the * detector does not. `evidenceCheckOf` reads the evidence gate's * verdict on that same candidate — asked of it through an * `EvidenceJudge`, never the verdict on the model's draft, which an * output transform may have changed. * * One law above all, from the standing fold (`core/agent/assessment/assess.ts`): * an agent row can WITHHOLD an answer and never VERIFY one. No row here is * ever `checked-pass` (`validate.ts` refuses one), so only the app's own * checks can make a report `passed`, which the fold reads as "known": * - The gate's clean verdict is a membership pass: `not-applicable`. * - A claim that agrees with the settled fact is `not-applicable` too. The * contract is unscoped — rows for `(entity, field)` from any tool, with no * scope or age check — so agreement verifies nothing. A contradiction * still fails the row. * - A reading can only withhold (`delivered.ts`): with no reading the claim * is not checked (`not-applicable`), and one more reading never makes the * row more permissive, so a forged or stale row can at most withhold. * - Doubt is never support. A field the answer leaves out, or declines * (`null` / `'unknown'`), is `not-applicable`. A value beside a reading * that settled nothing, doubt on both sides, a fact the run read two * ways, and anything not well formed are `unreachable`: enforce * withholds, observe delivers "not sure". * * And one from the redaction law: a row carries counts and the FIELD names the * app declared (the answer field, the fact's field), never a value from the * answer or from a tool result — and never the contract's `entity`, which an * app may build per user. `answerValidation` is not a name the redaction * vocabulary keeps out; the values stay on the records a policy already names * (`unsupportedValues`, `claimFacts`, the `integrity.context_error` event). */ const check_js_1 = require("../integrity/unsupported-claim/check.js"); const delivered_js_1 = require("../integrity/unsupported-claim/delivered.js"); /** Every agent row's id starts with this; a host check id may not while rows are on. */ exports.AGENT_CHECK_PREFIX = 'agent:'; /** * The `'names-and-numbers'` row. `undefined` (the gate never ran on the * run's final answer, so no judge was filed) is `unreachable`: a listed check * that did not run never reads as clean. */ function evidenceCheckOf(verdict) { const row = (disposition, reason) => Object.freeze({ id: `${exports.AGENT_CHECK_PREFIX}names-and-numbers`, disposition, reason }); if (verdict === undefined) { return row('unreachable', 'the evidence gate did not judge this answer'); } if (verdict.unsupported > 0) { return verdict.truncated ? row('unreachable', `the evidence index hit its ceiling, so ${verdict.unsupported} value(s) the answer ` + `states could not be looked up in every tool result`) : row('checked-fail', `${verdict.unsupported} value(s) the answer states appear in no tool result the run ` + `read${verdict.revised ? ', after the one repair turn' : ''}`); } // What the gate never read it cannot clear: an invented value may sit there. if (verdict.unread > 0) { return row('unreachable', `the answer is longer than the evidence gate reads: ${verdict.unread} more word(s) and ` + `number(s) were never looked up`); } return row('not-applicable', verdict.lookedUp === 0 ? 'the answer states no name or number to look up' : `none of the ${verdict.lookedUp} value(s) looked up is unsupported; ` + `clearing the gate does not verify the answer`); } exports.evidenceCheckOf = evidenceCheckOf; /** * The `'claims'` rows: one per declared claim, in declaration order, judged * on `candidate` against this run's ledger rows for each declared fact. * Throws what the claim comparison throws (a ledger value JSON cannot render). */ function claimChecksOf(declared, ledger, candidate, epoch) { return declared.map((claim) => claimRowOf(claim, (0, delivered_js_1.judgeDeliveredClaim)((0, check_js_1.compareClaim)(claim, ledger, candidate, epoch)))); } exports.claimChecksOf = claimChecksOf; function claimRowOf(claim, verdict) { const field = `'${claim.answerField}'`; // The fact by its FIELD only: an app may declare the entity per user. const fact = `the fact '${claim.field}'`; const row = (disposition, reason) => Object.freeze({ id: `${exports.AGENT_CHECK_PREFIX}claims:${claim.answerField}`, disposition, path: claim.answerField, reason, }); switch (verdict) { case 'omitted': return row('not-applicable', `the answer does not state ${field}`); case 'declined': return row('not-applicable', `the answer declines to state ${field}`); case 'agrees': return row('not-applicable', `the answer's ${field} agrees with ${fact} a tool settled, but agreement with a fact ` + `the contract does not scope is not verification`); case 'contradicts': return row('checked-fail', `the answer's ${field} contradicts ${fact} a tool settled`); case 'contradicts-a-reading': return row('checked-fail', `the answer's ${field} contradicts one tool result's reading of ${fact} (the readings ` + `the run made of it are not all the same)`); case 'incomparable': return row('unreachable', `could not compare the answer's ${field} with ${fact} a tool settled: they are ` + `different kinds of value (a list, an object, a number, text, or a number with a unit), ` + `or one is not a well-formed value`); case 'uncollected': // Never more permissive than any reading would be: silent, not withheld. return row('not-applicable', `no tool result the run read settled ${fact}, so the answer's ${field} is not checked`); case 'disputed': return row('unreachable', `the tool results the run read disagree about ${fact}, so the answer's ${field} cannot ` + `be checked against one of them`); case 'settled-unknown': return row('unreachable', `a tool result the run read settled ${fact} as unknown, so the answer's ${field} ` + `cannot be compared`); case 'settled-doubt': return row('unreachable', `a tool result the run read settled ${fact} only as null or 'unknown', so the ` + `answer's ${field} has nothing to agree with`); case 'doubt-on-both-sides': return row('unreachable', `${fact} was settled only as null or 'unknown', and the answer's ${field} gives no ` + `value either: agreement on doubt verifies nothing`); } } //# sourceMappingURL=agentChecks.js.map