agentfootprint
Version:
The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.
51 lines • 2.2 kB
JavaScript
/**
* 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.)
*/
/**
* 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 function contextErrorIdentity(e) {
const subjects = e.subjects
.map((s) => `${s.kind} ${s.id}`)
.sort()
.join(' + ');
const epoch = e.epoch === undefined ? '' : String(e.epoch);
// The predicate rides between the subjects and the epoch, mirroring
// `assertionKey`. Absent renders '', so every finding filed before this
// field existed keeps exactly the identity it had.
const predicate = e.predicate ?? '';
return `${e.kind} @${e.seam} [${subjects}] ${predicate} ${epoch}`;
}
/** Keep the FIRST filing of each identity, in input order. */
export function dedupeContextErrors(errors) {
const seen = new Set();
const kept = [];
for (const e of errors) {
const id = contextErrorIdentity(e);
if (seen.has(id))
continue;
seen.add(id);
kept.push(e);
}
return kept;
}
//# sourceMappingURL=types.js.map