agentfootprint
Version:
The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.
96 lines • 4.72 kB
JavaScript
;
/**
* time/drift — the clock at dispatch (time design § 7.4, step T5b).
*
* Pattern: one pure decision per dispatched call. The turn's clock is frozen
* at the message (§ 4); a LOOK-BACK is evaluated by the tool, against
* its own clock, when it is handed the call. After a pause (or with
* an app `now` far from the wall clock) the two differ by
* `drift = dispatchedAt − now`. Within the tool's step nothing
* changes; past it, the library re-sends its OWN look-back fill as
* the asked range in the tool's first absolute form that holds it
* exactly, and records a look-back it cannot re-send — the model's
* own (never written over, § 7.3), or a tool with no absolute form —
* as shifted.
* Role: L0 leaf (the time layer). Imports `convert.ts` and `range.ts`
* types only. Asked by ToolCalls (`stages/toolCalls.ts` ·
* `timeAtDispatch`) at both execute sites, just before the tool
* runs; the answer rides the `call` row (`rows.ts` · `CallDrift`).
* Emits: N/A.
*
* | Drift | The call sent | Tool has an absolute form | Sent | Recorded |
* |-------|---------------|---------------------------|------|----------|
* | ≤ the tool's step (one minute when none) | — | — | as it was | nothing |
* | larger | the library's look-back fill | yes | the asked range in that form | `drift: { outcome: 'redrawn', form }` |
* | larger | the library's look-back fill | no | the look-back | `drift: { outcome: 'shifted' }` |
* | larger | the model's look-back | — | the look-back, as sent | `drift: { outcome: 'shifted' }` |
*
* @example
* ```ts
* driftAtDispatch(
* { how: 'filled', form: 0, asked: { from: '2026-10-09T14:40:00Z', to: '2026-10-09T15:40:00.001Z' } },
* [{ kind: 'lookback', argument: 'window', signed: false },
* { kind: 'bounds', from: { argument: 'start', as: 'epoch-ms' },
* to: { argument: 'end', as: 'epoch-ms', edge: 'exclusive' } }],
* { now: '2026-10-09T15:40:00Z', dispatchedAt: '2026-10-09T16:10:00.000Z', granularityMs: 60_000 },
* );
* // { byMs: 1_800_000, outcome: 'redrawn', form: 1,
* // values: { start: 1791556800000, end: 1791560400001 } }
* ```
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.driftAtDispatch = exports.sentLookback = void 0;
const convert_js_1 = require("./convert.js");
const instant_js_1 = require("./instant.js");
/**
* Whether the call SENT a look-back: its `call-window` row names a form, that
* form is a `lookback`, and the call dispatched with a window in it (filled,
* bound, or the model's). The one reading of it — the drift decision here and
* the result checks' step allowance (`check.ts` · `differsOf`) both ask it.
*/
function sentLookback(window, forms) {
if (window.form === undefined || forms[window.form]?.kind !== 'lookback')
return false;
return (window.how === 'filled' ||
window.how === 'bound' ||
window.how === 'model-chosen' ||
window.how === 'model');
}
exports.sentLookback = sentLookback;
/**
* The drift decision for one dispatched call (the module table), or
* `undefined` when the call sent no look-back or the drift is within the
* tool's step. Pure.
*/
function driftAtDispatch(window, forms, clock) {
if (window === undefined || !sentLookback(window, forms))
return undefined;
const now = (0, instant_js_1.instantOf)(clock.now, 'strict');
const at = (0, instant_js_1.instantOf)(clock.dispatchedAt, 'strict');
if (now === undefined || at === undefined)
return undefined;
const byMs = at.ms - now.ms;
if (Math.abs(byMs) <= clock.granularityMs)
return undefined;
// Only the library's own fill is re-sent; the model's value is never written over (§ 7.3).
if (window.how === 'filled' && window.asked !== undefined && clock.zone !== undefined) {
const absolute = forms.map((f, i) => ({ f, i })).filter(({ f }) => f.kind !== 'lookback');
const conversion = (0, convert_js_1.convertExact)({ range: window.asked }, absolute.map(({ f }) => f), {
now: clock.now,
zone: clock.zone,
...(clock.appZone !== undefined && { appZone: clock.appZone }),
granularityMs: clock.granularityMs,
});
if (conversion !== undefined) {
return {
byMs,
outcome: 'redrawn',
form: absolute[conversion.form].i,
values: conversion.values,
};
}
}
return { byMs, outcome: 'shifted' };
}
exports.driftAtDispatch = driftAtDispatch;
//# sourceMappingURL=drift.js.map