agentfootprint
Version:
The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.
64 lines • 3.07 kB
JavaScript
/**
* leases — the accepted transition proposal and the instruction leases a
* tool's `require-instruction` effect grants, as scope state, and the three
* pure functions over them (`tenantOf`, `activeLeaseIds`, `pruneLeases`).
*
* The effect GRAMMAR — the envelope, its two effect kinds, the delivery-lease
* words — is `semantics/toolEffects.ts`. What a granted lease MEANS across
* iterations is an injection concept: the injection engine's Evaluate stage
* serves and sweeps them, and the tool-calls stage appends new grants, so the
* carriers live here, beside their one reader.
*/
/** Who holds the tenure — the advanced cursor on graph agents, else the tail
* of `activatedInjectionIds` (the shipped `activeSkillId` notion the step
* pointer's re-key already uses). */
export function tenantOf(cursor, activatedInjectionIds) {
if (cursor !== undefined)
return cursor;
const activated = activatedInjectionIds ?? [];
return activated[activated.length - 1];
}
/**
* The lease-served injection ids for ONE Evaluate pass — pure. `iteration`
* is the pass being composed; `tenant` is who holds the tenure on it (the
* ADVANCED cursor — a lease dies the same pass its tenure ends).
*
* `skillId === tenant` is a sound "tenure still holds" test ONLY because the
* Evaluate tenure sweep (`pruneLeases`, every pass) removes a dead lease the
* pass its tenure ends — so a cursor that re-enters the granting skill later
* finds nothing to match, instead of resurrecting an ended grant.
*/
export function activeLeaseIds(leases, iteration, tenant) {
if (leases === undefined || leases.length === 0)
return [];
const ids = [];
for (const lease of leases) {
const live = lease.deliveryLease === 'next-call'
? lease.iteration + 1 === iteration
: lease.skillId === tenant;
if (live && !ids.includes(lease.instructionId))
ids.push(lease.instructionId);
}
return ids;
}
/**
* Drop leases that can never serve again. `iteration` is the CURRENT pass;
* a `'next-call'` lease older than the previous iteration is spent, and an
* `'until-skill-exit'` lease whose tenant is no longer current is dead.
*
* TWO call sites, one law. The Evaluate stage sweeps on EVERY pass (writing
* the survivors under `nextInstructionLeases`, the cursor's alias round
* trip) — that sweep is what makes death permanent: it records the death the
* same pass the tenure ends, before any later pass could see the cursor
* re-enter the granting skill and mistake re-entry for an unbroken tenure.
* The tool-calls stage also prunes when it appends a new grant, so a
* mid-batch array never carries spent leases into the commit.
*/
export function pruneLeases(leases, iteration, currentTenant) {
if (leases === undefined || leases.length === 0)
return [];
return leases.filter((lease) => lease.deliveryLease === 'next-call'
? lease.iteration + 1 > iteration
: lease.skillId === currentTenant);
}
//# sourceMappingURL=leases.js.map