agentfootprint
Version:
The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.
100 lines • 4.43 kB
JavaScript
;
/**
* judge — the typed door's rows: one row per entry of the app's negatives field, its verdict
* mapped to the disposition the validation door already reads (design § 5.4), and the
* library's statement beside an established one.
*
* Pattern: `citation.ts` decides; this file names the row (`agent:negative-claims:<field>#<n>`),
* maps the verdict to a disposition and composes the statement (`statement.ts`). An
* established claim CLEARS the claim (`not-applicable`) — it never verifies the answer,
* so no row is `checked-pass`.
* Role: integrity/ layer (L3). Not wired: PR 4 mounts it behind `.negativeClaims()` and
* `agentChecks: ['negative-claims']`.
*
* A row carries identities, tool names and codes — never a value and never a sentence; the
* statement travels beside it.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.judgeTypedNegatives = exports.dispositionOf = exports.MAX_NEGATIVE_CLAIMS = exports.MAX_CITED_READS = void 0;
const stableJson_js_1 = require("../../lib/stableJson.js");
const citation_js_1 = require("./citation.js");
Object.defineProperty(exports, "MAX_CITED_READS", { enumerable: true, get: function () { return citation_js_1.MAX_CITED_READS; } });
const limits_js_1 = require("./limits.js");
Object.defineProperty(exports, "MAX_NEGATIVE_CLAIMS", { enumerable: true, get: function () { return limits_js_1.MAX_NEGATIVE_CLAIMS; } });
const statement_js_1 = require("./statement.js");
const TOO_MANY = Object.freeze({
kind: 'unknown',
code: 'too-many-claims',
results: [],
tools: [],
reads: [],
});
const CHECKED_FAIL = new Set([
'contradicted-by-rows',
'wider-search-has-rows',
'search-incomplete',
'superseded-by-write',
'later-read-failed',
]);
/** The disposition a typed verdict files (§ 5.4). */
function dispositionOf(code) {
if (code === 'established')
return 'not-applicable';
return CHECKED_FAIL.has(code) ? 'checked-fail' : 'unreachable';
}
exports.dispositionOf = dispositionOf;
/** A repeated claim is judged once (its stable JSON is the key); a key that cannot be made, every time. */
function judgeOnce(cache, entry, judge) {
let key;
try {
key = (0, stableJson_js_1.stableJson)(entry);
}
catch {
key = undefined;
}
if (key === undefined)
return judge(entry);
const known = cache.get(key);
if (known !== undefined)
return known;
const verdict = judge(entry);
cache.set(key, verdict);
return verdict;
}
/**
* Judge every citation of the field. No field, or an empty list, is no claim. A field that is
* not a list is one unresolved citation; a field of more than {@link MAX_NEGATIVE_CLAIMS}
* claims withholds every one of them (`too-many-claims`).
*/
function judgeTypedNegatives(input) {
const { field, negatives, record, citable, interpretation } = input;
if (negatives === undefined || negatives === null)
return [];
const entries = Array.isArray(negatives) ? negatives : [negatives];
const tooMany = entries.length > limits_js_1.MAX_NEGATIVE_CLAIMS;
const cache = new Map();
return entries.map((entry, index) => {
const verdict = tooMany
? TOO_MANY
: Array.isArray(negatives)
? judgeOnce(cache, entry, (e) => (0, citation_js_1.judgeCitation)(e, record, citable, interpretation))
: (0, citation_js_1.judgeCitation)(undefined, record, citable, interpretation);
const row = {
id: `agent:negative-claims:${field}#${index}`,
path: `${field}[${index}]`,
index,
kind: verdict.kind,
code: verdict.code,
disposition: dispositionOf(verdict.code),
tools: verdict.tools,
results: verdict.results,
...(verdict.staleSince === undefined ? {} : { staleSince: verdict.staleSince }),
};
if (verdict.code !== 'established' || verdict.kind === 'unknown')
return { row };
const reads = verdict.reads.flatMap((call) => call.row === undefined ? [] : [{ call, row: call.row, tool: record.tools[call.toolName] }]);
return { row, statement: (0, statement_js_1.composeStatement)(verdict.kind, reads, record.clock) };
});
}
exports.judgeTypedNegatives = judgeTypedNegatives;
//# sourceMappingURL=judge.js.map