agentfootprint
Version:
The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.
75 lines • 3.27 kB
JavaScript
;
/**
* Claim<T> — a value that says how it knows itself.
*
* Pattern: tagged union + tiny constructors. Pure, zero dependencies.
* Role: the library's honesty primitive — ONE vocabulary leaf, many doors.
* Every dynamic fact a subsystem states about the world is a Claim,
* never a bare value — so "unknown" carries its reason, and a count
* that nobody measured can never be rendered as a zero. It lives
* under lib/ (not under any one door) because two doors already need
* it: `agentfootprint/maps` (the mount kernel) and
* `agentfootprint/cache` (the hit-rate meter, 9.59.0). Both re-export
* THESE symbols, so `known` from either door is the same function.
*
* Why it exists: two recorded failures came from a system stating a value it
* did not hold — a final summary written from a trimmed memory, and a served
* list whose silent cap read as completeness. The type makes the third state
* (we do not know, and here is why) impossible to skip: a consumer must
* branch on `kind` to reach a value at all.
*
* @example
* import { known, unknown, isKnown } from 'agentfootprint/maps';
*
* const total = known(11, 'the app declared total on the choices block');
* const cache = unknown('the provider reported no cache fields', 'usage payload');
* if (isKnown(total)) render(total.value); // the only door to the value
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.describeClaim = exports.valueOr = exports.isKnown = exports.notApplicable = exports.unknown = exports.known = void 0;
/** State a value with the evidence that backs it. */
function known(value, evidence) {
return { kind: 'known', value, evidence };
}
exports.known = known;
/** State an absence with its reason — never render this as zero or empty. */
function unknown(reason, evidence) {
return { kind: 'unknown', reason, ...(evidence !== undefined && { evidence }) };
}
exports.unknown = unknown;
/** State that the question does not apply to this subject. */
function notApplicable(evidence) {
return { kind: 'not-applicable', evidence };
}
exports.notApplicable = notApplicable;
/** Type guard — the only door to `.value`. */
function isKnown(claim) {
return claim.kind === 'known';
}
exports.isKnown = isKnown;
/**
* The value when known, else the caller's stated fallback. The fallback is a
* REQUIRED argument on purpose: defaulting to `undefined` silently would put
* the shrug back into the type that exists to remove it.
*/
function valueOr(claim, fallback) {
return claim.kind === 'known' ? claim.value : fallback;
}
exports.valueOr = valueOr;
/**
* One plain sentence for a record or a prompt — states the value WITH its
* standing, so a rendered unknown reads as "unknown (reason)", never as a
* gap the reader fills in.
*/
function describeClaim(claim) {
switch (claim.kind) {
case 'known':
return `${String(claim.value)} (${claim.evidence})`;
case 'unknown':
return `unknown — ${claim.reason}`;
case 'not-applicable':
return `not applicable — ${claim.evidence}`;
}
}
exports.describeClaim = describeClaim;
//# sourceMappingURL=claim.js.map