kestrel.markets
Version:
A typed, token-efficient language + runtime for agentic trading: agents author bounded plans, the runtime fires them at the tick. CLI + typed library + MCP server.
112 lines (111 loc) • 7.2 kB
JavaScript
/**
* # bus/anchor-ledger — the SPOT-anchor UNKNOWN-window ledger + fail-closed under-report validator (ven.4)
*
* The de-arm PRIMITIVE already lives in the series layer: an unresolvable value anchor reads
* UNKNOWN (`CanonicalState.spot: number | Unknown`) and any statement/detector referencing it
* de-arms with a logged reason — it can never fire on a value it does not have (fail-closed,
* RUNTIME §3/§8). What was missing is a **LEDGER** of those value gaps: a past-only record a
* consumer can read so it is never misled into thinking a gapped/dead-feed window carried a real
* value.
*
* ## ONE TRUTH — the ledger records EXACTLY the de-arm's windows (never a forked concept)
* The value anchor is UNKNOWN precisely while no SPOT for the signal instrument has been folded —
* the exact condition `CanonicalState.applyEvent` uses to set `spotVal` (a `TICK`/`SPOT` event for
* the matching instrument; RUNTIME §2). This module re-derives THAT SAME predicate at the bus layer
* — it does not import the series layer (the module spine is `series → bus`, never the reverse), so
* the equivalence is proved event-by-event by the ven.4 suite rather than by a cross-layer call.
* The ledger's covered seqs therefore equal the seqs where `CanonicalState.spot === UNKNOWN`: the
* detectors de-arm across exactly the windows the ledger records. One truth, not two.
*
* ## PAST-ONLY / NO-LOOKAHEAD (RUNTIME §0)
* A window is derived by a single forward replay; every `{start,end,dur}` bound is an
* already-elapsed event. A window that resolves ends at the LAST still-UNKNOWN event — the event
* *before* the resolving SPOT — never the resolver and never a synthetic future sentinel. A window
* still open at end-of-tape ends at the last elapsed event. `dur = end.ts - start.ts`. No wall
* clock, no RNG: same bus ⇒ byte-identical ledger (the determinism invariant).
*
* ## NO UNDER-REPORT — honest BY CONSTRUCTION (kestrel-voy9)
* The ledger can never under-report the gaps, because {@link spotAnchorUnknownWindows} IS the sole
* derivation: it replays the de-arm predicate forward and records EXACTLY the seqs the anchor read
* UNKNOWN (a dropped window, a later start, an earlier end, a shortened `dur` are all unrepresentable
* — the derivation emits the real span or nothing). The ONE-TRUTH property is proved end-to-end in
* the ven.4 suite by driving this real derivation and asserting its covered seqs BYTE-MATCH the
* series-layer `CanonicalState.spot === UNKNOWN` primitive, event-by-event, across a resolving, a
* never-resolving, and a px-blind bus. There is NO standalone under-report validator: a guard that
* only ever re-checks this same constructor's own honest output is a tautology (it can never fire),
* and no production path SUPPLIES a foreign ledger to validate — so the honesty lives in the
* construction, not in an unreachable export.
*/
/**
* The de-arm predicate, re-derived at the bus layer to be BYTE-EQUAL to `CanonicalState.spot`'s fold
* condition (ONE TRUTH — not a forked concept that could diverge). The series primitive folds a value
* into the anchor via `onSpot(ev.ts, ev.px)` — reached only for a `TICK`/`SPOT` of the matching signal
* instrument — and then reads `spot === spotVal ?? UNKNOWN`. So the anchor RESOLVES iff such a SPOT
* carries a `px` that is neither `undefined` nor `null` (`spotVal ?? UNKNOWN` stays UNKNOWN when
* `spotVal` is nullish; a `NaN` or a real number both fold to a non-nullish `spotVal` and read known).
* The `ev.px != null` guard reproduces that exactly: a reader-accepted SPOT whose `px` is missing/null
* (a torn/partial TICK the envelope validator lets through — {@link ../bus/read.ts}) leaves the window
* OPEN, matching the primitive that stays UNKNOWN there; only a `px`-bearing (NaN/number) SPOT closes
* it. A SPOT for any OTHER instrument never reaches `onSpot` and so never resolves this anchor (it is
* instrument-scoped) — the window stays open, exactly as the series-layer primitive behaves.
*/
function isAnchorSpot(ev, instrument) {
return (ev.stream === "TICK" &&
ev.type === "SPOT" &&
ev.instrument === instrument &&
ev.px != null);
}
/**
* Derive the SPOT-anchor UNKNOWN-window ledger from a bus, purely and deterministically
* (RUNTIME §0). A single forward replay: the anchor is UNKNOWN until the first px-bearing SPOT for
* `instrument` is folded, at which point it resolves.
*
* The value anchor is **STICKY**: `CanonicalState.spotVal` is set once by `onSpot` and, on a
* well-formed tape, never reverts (barring a `CanonicalState` reset, which this replay does not
* model), so the `anchorKnown` latch below likewise never resets. This replay therefore records
* **exactly the LEADING window** — the pre-first-spot gap — and, when no SPOT ever resolves the
* anchor, the whole tape as one window. It does NOT record a mid-session lapse back to UNKNOWN: that
* "gapped/dead-feed mid-session staleness" is a SEPARATE primitive concern (a staleness/heartbeat
* backstop over `spotTs`, not the value-anchor de-arm this ledger mirrors) and is out of scope here —
* mirroring it would be forking a second window concept, which ONE TRUTH forbids. Every bound is
* past-only. The input is never mutated.
*
* @param events the bus, in `seq` order (as the writer emits it).
* @param instrument the signal instrument whose value anchor is tracked (mirrors
* `CanonicalStateConfig.instrument`).
* @returns the leading window the anchor was UNKNOWN (0 or 1 windows), in `seq` order — the same span
* the value-anchor de-arm covers.
*/
export function spotAnchorUnknownWindows(events, instrument) {
const windows = [];
let start; // the first event of the current open UNKNOWN run
let last; // the most recent still-UNKNOWN event of that run
let anchorKnown = false; // has a px-bearing SPOT for `instrument` been folded? (spotVal != null)
const close = () => {
if (start !== undefined && last !== undefined) {
windows.push({ start, end: last, dur: last.ts - start.ts });
}
start = undefined;
last = undefined;
};
for (const ev of events) {
// Fold this event FIRST — the resolving SPOT resolves the anchor AT its own seq, so it is KNOWN
// there and the window ended at the previous (last still-UNKNOWN) event. This matches the series
// primitive, where `state.spot` is already known once `applyEvent(spot)` returns.
if (isAnchorSpot(ev, instrument))
anchorKnown = true;
if (anchorKnown) {
close(); // the anchor is known at ev → close any run that was open through the previous event.
}
else {
const at = { seq: ev.seq, ts: ev.ts };
if (start === undefined)
start = at;
last = at;
}
}
// A run still open at end-of-tape never resolved — it ends at the last ELAPSED event (no future
// sentinel; past-only). A fully-UNKNOWN session is thus one window spanning the whole tape.
close();
return windows;
}