UNPKG

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.

906 lines (857 loc) 49.1 kB
/** * # blotter/project — the pure Blotter projector (kestrel-a57.1 slice 2, ADR-0011) * * `project(bus)` is the **permanent, deterministic** fold from one canonical GRADED bus into a * {@link Blotter}. Its one invariant (ADR-0011): **it is a pure function of the bus** — the same bus * projects to a byte-identical Blotter, and no engine-state scrape is ever permitted. Everything the * Blotter carries is re-derived from bus bytes: * * • META (seq 0) → session identity / judge / fidelity / bus receipt * • JOURNAL events → journals[] (full body inline) + plan reasoning_ref (by seq) * • PLAN events → plans[] (lifecycle + final_state) * • ORDER + TELEMETRY events → orders[] (place ⋈ fill/cancel/reject ⋈ esc/reprice ⋈ settle) * • settle-outcome TELEMETRY → totals{floor, expected} + headline taint + orders[].support + * fill_claim[] (expected-$ partitioned calibrated|extrapolated, a57.4) * • settle_mark TELEMETRY → totals.settle_mark (the settle spot's provenance + staleness * verdict, kestrel-xwf; a stale mark taints the headline) * • META fill_model → fidelity.self_limitation (what the judge could NOT observe, a57.4) * * **Fail closed (ADR-0011).** The projector requires a GRADED bus: a bus whose opening META lacks the * judge self-description (`fill_model`/`instance`/`fidelity`) is a fill-model-agnostic INPUT tape, not a * graded bus — `project` refuses it with a logged reason rather than inventing a judge (the two-bus rule). * * **Scope.** The aggregated `fill_claim[]` rollup and the fidelity self-limitation stamp land in a57.4 * (this slice); the paper/live certification legs (a57.3) and all human/legible rendering (a57.13) remain * OUT — the projector never renders. The * report→Blotter unification (the existing {@link ../session EpisodeReport} still stands beside the * Blotter) is a LATER cleanup. */ import type { BusEvent, ExperimentalEnvelope, FillModelStamp, FillSupport, JournalEvent, MetaEvent, OrderEvent, PlanOutcome, PlanState, RankableReason, TelemetryGuardEvent, TelemetryOrderEvent, TelemetrySettleEvent, TelemetrySettleMarkEvent, TelemetryThetaBleedEvent, TokenAccounting, } from "../bus/index.ts"; import { CORPUS_TIERS, FACES, groupPlanInstances, serializeBus } from "../bus/index.ts"; // The support partition is OWNED by src/support (kestrel-dpy, ADR-0014): the projector CONSUMES it to // build the SIGNED fill_claim sub-cells rather than re-deriving a sign split here. import { partition } from "../support/index.ts"; // The headline policy is OWNED by src/grade/headline.ts (kestrel-9gu.12): the projector assembles the // gate evidence FROM BUS BYTES and selects through the one shared policy — never a fork of it. import { readSampledQualificationClaim, sampledQualified, selectHeadline } from "../grade/headline.ts"; // The disarm EVENT discriminant is owned by the one de-arm-rule home (kestrel-z473.5): the projector reads // the SAME constant the driver's emit sites use, so projection and emission agree by construction. import { DISARM_CONTROL_TYPE } from "../engine/disarm.ts"; import type { Blotter, BlotterLifecycleStep, BlotterSession, Certification, DeliberationTraceEntry, FidelitySelfLimitation, FillClaim, HeadlineFlag, DisarmRecord, JournalEntry, OrderFinalState, OrderRecord, PlanRecord, Rankability, RankableLeg, ReasoningRef, SettleMarkRecord, Totals, WakeTrace, } from "./types.ts"; import { sha256 } from "../crypto/sha256.ts"; import { roundToGrid } from "../protocol/grade.ts"; // The training_cutoff × MODEL_KNOWLEDGE_CUTOFF cross-check (kestrel-m9i.23): the ONE place the registry // fence + the pinned month-boundary rule live. A leaf module (no bus barrel import — kestrel-exx). m9i.25's // post-cutoff rankable leg consumes the SAME `isPostCutoff` boundary rule (never a second copy). import { checkTrainingCutoff, isPostCutoff, type TrainingCutoffCheck } from "./model-registry.ts"; // ───────────────────────────────────────────────────────────────────────────── // Determinism helpers (no wall clock, no RNG — RUNTIME §0) // ───────────────────────────────────────────────────────────────────────────── // sha256 (the portable, synchronous digest — Bun-native fast path, Worker-portable pure-JS fallback, // kestrel-alw.17) is imported from ../crypto/sha256.ts so a projected receipt hashes byte-identically // under `bun test`, the CLI, and a Cloudflare Worker isolate. /** The exact report/grader $-grid rounding, so a bus-derived sum rounds byte-identically to the report's * totals (RUNTIME §0). Re-homed onto the ONE grid the grader owns ({@link ../protocol/grade.ts REPORT_GRID} * / `roundToGrid`, kestrel-z473.6) — never a local `1e8` — so recomputation stays byte-stable. */ const round = roundToGrid; /** The maximum length of a {@link ReasoningRef} excerpt (ADR-0011 recommendation 2, "~120 chars"). */ const EXCERPT_CAP = 120; /** A mechanical, deterministic excerpt of a JOURNAL body: its first non-empty line, trimmed, capped to * {@link EXCERPT_CAP} chars with a single-char ellipsis on truncation. No markdown interpretation. */ function excerptOf(body: string): string { let first = ""; for (const line of body.split("\n")) { const t = line.trim(); if (t.length > 0) { first = t; break; } } if (first.length <= EXCERPT_CAP) return first; return first.slice(0, EXCERPT_CAP - 1) + "…"; } // ───────────────────────────────────────────────────────────────────────────── // Fidelity self-limitation — what the judge (fill model) could NOT observe (a57.4) // ───────────────────────────────────────────────────────────────────────────── /** The fail-closed self-limitation for a judge that DECLARED none (a legacy graded bus whose META `fill_model` * carries no `self_limitation`): rather than invent observability, declare it unstated so a consumer treats * the record as maximally limited (never over-claims, never a silent default to unlimited). */ const UNSTATED_LIMITS: readonly { code: string; note: string }[] = [ { code: "observability-unstated", note: "fill model declared no self-limitation; the judge's observability limits are unstated — treat all fills as maximally limited (fail-closed)" }, ]; /** * Read the judge's self-limitation off the graded META's `fill_model` stamp (a57.4) — the fill model * DECLARES what it structurally could not observe, so this is a verbatim projection, never a downstream * guess. Previously this keyed on `fill_model.name`, which silently mislabelled the calibrated * `maker-fair-v1+<version>` judge (it matched no key) as maximally limited (kestrel-o32). Now the * declaration rides the META. FAIL CLOSED: a legacy stamp carrying no declaration falls back to * {@link UNSTATED_LIMITS} — never a silent default to unlimited observability. Pure and deterministic. */ function selfLimitationOf(fillModel: FillModelStamp): FidelitySelfLimitation { const limits = fillModel.self_limitation ?? UNSTATED_LIMITS; return { fill_model: fillModel.name, limits: limits.map((l) => ({ code: l.code, note: l.note })) }; } // ───────────────────────────────────────────────────────────────────────────── // Fail-closed META gate — the projector requires a GRADED bus // ───────────────────────────────────────────────────────────────────────────── /** * The opening META of a graded bus, or a loud refusal. Fail-closed (ADR-0011): a bus with no META, or a * META lacking the judge self-description (`fill_model`/`instance`/`fidelity`), is not a graded bus — it * is a fill-model-agnostic INPUT tape (the two-bus rule) — so the projector refuses to invent a judge. */ function requireGradedMeta(bus: readonly BusEvent[]): MetaEvent { const meta = bus.find((e): e is MetaEvent => e.stream === "META"); if (meta === undefined) { throw new Error("blotter: no META header in bus (a well-formed bus opens with exactly one META, ADR-0011)"); } if (meta.fill_model === undefined || meta.instance === undefined || meta.fidelity === undefined) { throw new Error( "blotter: META lacks judge identity (fill_model/instance/fidelity) — the projector requires a GRADED bus, " + "not a fill-model-agnostic input tape (the two-bus rule, ADR-0011; fail-closed)", ); } return meta; } // ───────────────────────────────────────────────────────────────────────────── // Experimental envelope (kestrel-a57.14) — project the injected author identity, fail-closed // ───────────────────────────────────────────────────────────────────────────── /** * The fourteen REQUIRED identity fields of the experimental envelope (kestrel-a57.14; `face` + `adapter` * + `adapter_version` joined the original eleven per the m9i.2 owner tweaks — mandatory-for-certified * BEFORE the m9i.7 face/harness tournament). A declared envelope missing/empty/malformed on ANY one fails * the record closed to a PROVISIONAL verdict with a recorded reason NAMING the field — never a silent * default. Iterated in this fixed order so the recorded reasons are byte-stable across re-projection * (determinism, RUNTIME §0). */ const REQUIRED_ENVELOPE_IDENTITY = [ "provider", "model", "version", "training_cutoff", "prompt_hash", "tokenizer", "tool_policy", "rendering_identity", "wake_source", "token_accounting", "corpus_tier", "face", "adapter", "adapter_version", ] as const satisfies readonly (keyof ExperimentalEnvelope)[]; /** A real, finite magnitude (no NaN/±Infinity) — the token counters must be genuine injected numbers. */ function isFiniteNumber(v: unknown): v is number { return typeof v === "number" && Number.isFinite(v); } /** The injected token accounting, iff it is a well-formed `{input, output, thinking}` triple of finite * numbers; otherwise `undefined` (the caller records a fail-closed reason naming `token_accounting`). */ function readTokenAccounting(v: unknown): TokenAccounting | undefined { if (typeof v !== "object" || v === null) return undefined; const r = v as Record<string, unknown>; const input = r.input; const output = r.output; const thinking = r.thinking; if (!isFiniteNumber(input) || !isFiniteNumber(output) || !isFiniteNumber(thinking)) return undefined; return { input, output, thinking }; } /** The outcome of projecting the experimental envelope: the projected identity (present ONLY when * complete) plus any fail-closed reasons (present ONLY when a declared envelope was incomplete). */ interface EnvelopeProjection { readonly envelope?: ExperimentalEnvelope; readonly reasons: readonly string[]; } /** * Project the experimental envelope (kestrel-a57.14) from the graded META's INJECTED `envelope` — its * input half (the seam's `AgentConfig`/`ModelIdentity` descriptor) — fail-closed. PURE: a deterministic function of * the injected bytes (no wall clock/RNG), with `token_accounting` taken as the injected accounting (off * the deterministic record path — the owner-away conservative default), never re-derived. Three outcomes: * * • `raw === undefined` — the bus DECLARES no envelope (a pre-a57.14 / input-derived graded bus, exactly * like the optional v4 judge fields): nothing to project, nothing to fail closed on ⇒ `{ reasons: [] }` * and the verdict is unaffected (backward-compatible). * • a COMPLETE declared envelope (all fourteen identity fields present + well-formed, `face` inside the * closed http|sdk|cli|mcp vocabulary) ⇒ the envelope projected VERBATIM (each value traceable to the * injected input; the prompt HASH passed through, never content; exactly the fourteen fields — any * extra key is dropped, never fabricated). * • an INCOMPLETE declared envelope (any required field missing/empty/malformed) ⇒ NO projected envelope * (a broken identity is never stamped as identity) plus a recorded reason NAMING each absent field — * the caller flips the verdict to PROVISIONAL. No field is EVER silently defaulted to `""`/`"unknown"`. */ function projectExperimentalEnvelope(raw: unknown): EnvelopeProjection { if (raw === undefined) return { reasons: [] }; // no declared envelope — additive/optional, verdict unchanged if (typeof raw !== "object" || raw === null) { return { reasons: ["envelope: declared but not an object — no required identity field can be resolved (fail-closed, a57.14)"], }; } const rec = raw as Record<string, unknown>; const reasons: string[] = []; const tokenAccounting = readTokenAccounting(rec.token_accounting); for (const field of REQUIRED_ENVELOPE_IDENTITY) { if (field === "token_accounting") { if (tokenAccounting === undefined) { reasons.push("envelope: missing required identity field 'token_accounting' (injected accounting absent or malformed) — fail-closed, not defaulted (a57.14)"); } continue; } const v = rec[field]; if (typeof v !== "string" || v.length === 0) { reasons.push(`envelope: missing required identity field '${field}' — fail-closed, not defaulted (a57.14)`); continue; } // `face` is a CLOSED vocabulary (m9i.2 owner tweak): a declared-but-unknown face is a broken identity, // fail-closed exactly like a missing field — never coerced onto a known face, never passed through. if (field === "face" && !(FACES as readonly string[]).includes(v)) { reasons.push(`envelope: face '${v}' is outside the closed interface vocabulary (http|sdk|cli|mcp) — fail-closed, not coerced (m9i.2)`); } // `corpus_tier` is a CLOSED vocabulary (kestrel-m9i.26): a declared-but-unknown tier (a typo, or the // retired `public-baseline`) is a broken identity, fail-closed exactly like `face` — never coerced onto a // known tier, never passed through (the tier gates the practice-vs-holdback wall). if (field === "corpus_tier" && !(CORPUS_TIERS as readonly string[]).includes(v)) { reasons.push(`envelope: corpus_tier '${v}' is outside the closed corpus vocabulary (public|semi-private|private) — fail-closed, not coerced (m9i.26)`); } } if (reasons.length > 0) return { reasons }; // declared-but-incomplete — record the reasons, project no identity // COMPLETE — reconstruct EXACTLY the fourteen identity fields VERBATIM (drop extras; never fabricate). const envelope: ExperimentalEnvelope = { provider: rec.provider as string, model: rec.model as string, version: rec.version as string, training_cutoff: rec.training_cutoff as string, prompt_hash: rec.prompt_hash as string, tokenizer: rec.tokenizer as string, tool_policy: rec.tool_policy as string, rendering_identity: rec.rendering_identity as string, wake_source: rec.wake_source as string, token_accounting: tokenAccounting!, corpus_tier: rec.corpus_tier as string, face: rec.face as string, adapter: rec.adapter as string, adapter_version: rec.adapter_version as string, }; return { envelope, reasons: [] }; } // ───────────────────────────────────────────────────────────────────────────── // project // ───────────────────────────────────────────────────────────────────────────── /** * Project one GRADED bus into its canonical {@link Blotter}. Pure and deterministic (ADR-0011): no wall * clock, no RNG, no engine-state scrape — the same bus in ⇒ a byte-identical Blotter out (proven by * {@link ./certify.ts}). Refuses a non-graded bus loudly (fail-closed). */ export function project(bus: readonly BusEvent[]): Blotter { const meta = requireGradedMeta(bus); // The author's experimental envelope (a57.14): projected VERBATIM from the graded META's INJECTED // `envelope` when complete, else recorded as fail-closed reasons that flip the verdict to PROVISIONAL. // A graded bus that declared no envelope yields neither — additive/optional, backward-compatible. const envelopeProjection = projectExperimentalEnvelope(meta.envelope); // The training_cutoff × model-registry cross-check (kestrel-m9i.23), additive to the a57.14 envelope // reasons: ONLY a COMPLETE envelope (its `model` + `training_cutoff` both present + well-formed) is // cross-checked against the MODEL_KNOWLEDGE_CUTOFF fence keyed by model id. Fail-closed — an unknown model // id or a declared-vs-registry mismatch appends a typed reason (rendered from `reason.detail`) that flips // the verdict to PROVISIONAL exactly like a missing identity field, never a silent default and never a // rewrite of the declared cutoff. An incomplete/absent envelope already carries its own reasons (or // declares no identity to cross-check), so the registry is never consulted for one — the envelope stamp // (below) and the goldens stay byte-unchanged for every registered+matching run (NO-CHURN). const envelopeReasons: string[] = [...envelopeProjection.reasons]; // The cross-check result is HOISTED: it feeds BOTH the certification reasons (below) and the m9i.25 // post-cutoff rankable leg (a complete envelope whose cutoff verifies yields the `cutoffMonth` the // boundary rule needs; an absent/incomplete envelope or a failing check leaves the cutoff unverifiable). const cutoffCheck: TrainingCutoffCheck | undefined = envelopeProjection.envelope === undefined ? undefined : checkTrainingCutoff({ model: envelopeProjection.envelope.model, declaredCutoff: envelopeProjection.envelope.training_cutoff, }); if (cutoffCheck !== undefined && !cutoffCheck.ok) envelopeReasons.push(cutoffCheck.reason.detail); // ── session — identity / judge / fidelity / envelope / bus receipt ─────────── // The bus receipt pins the recorded truth (ADR-0010). determinism_hash re-pins the engine's OUTPUT — // every event after the opening META — a pure read of the bus (mirrors the report's determinism_hash). const output = bus.filter((e) => e !== meta); const session: BlotterSession = { instance: meta.instance!, instruments: meta.instruments, bus: { events: bus.length, sha256: sha256(serializeBus(bus)), schema: meta.bus_schema, }, determinism_hash: sha256(serializeBus(output)), fill_model: meta.fill_model!, // Fidelity (a57.4): the level pass-through PLUS the judge's self-limitation, read verbatim from the // fill model's DECLARED limits on the graded META — what it structurally could not observe, so a // consumer cannot over-claim (fail-closed to UNSTATED when a legacy stamp declared none). fidelity: { level: meta.fidelity!, self_limitation: selfLimitationOf(meta.fill_model!), }, // The projected experimental envelope (a57.14) — the author's identity, present ONLY when complete. ...(envelopeProjection.envelope !== undefined ? { envelope: envelopeProjection.envelope } : {}), // The FULL ConfigId (m9i.2 owner tweak) — projected VERBATIM from the graded META when stamped, the // sampling-axis-complete config identity the grid CellKey keys on. Additive/optional (absent on a // config-less or pre-tweak graded bus); never re-derived here (the driver stamped it at open). ...(typeof meta.config_id === "string" && meta.config_id.length > 0 ? { config_id: meta.config_id } : {}), // The cell config axis (fillSeed stripped — ADR-0016 §3) — projected VERBATIM when the driver stamped it // (a seeded run, where it diverges from config_id). The config axis the grid cellOf keys the cell on; // seed-only replicates share it. Additive/optional; never re-derived here (the driver stamped it at open). ...(typeof meta.cell_config_id === "string" && meta.cell_config_id.length > 0 ? { cell_config_id: meta.cell_config_id } : {}), }; // ── journals — folded straight from the JOURNAL stream (full body inline) ───── const journals: JournalEntry[] = []; for (const e of bus) { if (e.stream !== "JOURNAL") continue; const j = e as JournalEvent; journals.push({ seq: j.seq, kind: j.kind, ts: j.ts, body: j.body }); } // ── disarms — reason-carrying stand-down / de-arm audit (CONTROL `disarm`, kestrel-2pl) ──────── // The author's `standDown` reason (and a fail-closed supersede-parse-escape de-arm) becomes an // explicit Blotter record, not merely inferable from plans going `expired(superseded)`. A pure bus read. const disarms: DisarmRecord[] = []; for (const e of bus) { if (e.stream !== "CONTROL" || e.type !== DISARM_CONTROL_TYPE) continue; disarms.push({ seq: e.seq, ts: e.ts, ...(e.note !== undefined ? { reason: e.note } : {}) }); } // A plan references its pre-hoc author reasoning: the `author` JOURNAL with the greatest seq strictly // below the plan's first lifecycle transition (provable pre-hoc by seq, a57.11). Referenced by seq — // never copied (ADR-0011 recommendation 2). The JOURNAL-backed authoring FLOW itself is a57.2; this is // just the mechanical linkage a Blotter draws over whatever author records already ride the bus. const authorJournals = journals.filter((j) => j.kind === "author").sort((a, b) => a.seq - b.seq); const reasoningRefFor = (firstPlanSeq: number): ReasoningRef | undefined => { let ref: JournalEntry | undefined; for (const j of authorJournals) { if (j.seq < firstPlanSeq) ref = j; // ascending scan ⇒ last kept is the greatest seq below else break; } return ref === undefined ? undefined : { seq: ref.seq, excerpt: excerptOf(ref.body) }; }; // ── plans — lifecycle traces from the PLAN stream, ONE record per exact INSTANCE ── // Group BY INSTANCE first (kestrel-22j.15), not by name: a legal same-name replacement is a DISTINCT // instance, so it keeps its own lifecycle + terminal outcome instead of collapsing onto its predecessor. // Lineage aggregation stays a SEPARATE roll-up a consumer does over `plan` (the name). The grouping is a // pure fold shared with EpisodeReport (groupPlanInstances) so the two projections can never drift: it keys // on the explicit `plan_instance` (v5) and, for a pre-v5 bus, migrates EXPLICITLY by lifecycle // sessionization — never a silent mis-identify (RUNTIME §8). const plans: PlanRecord[] = groupPlanInstances(bus).map((g) => { const lifecycle: BlotterLifecycleStep[] = g.events.map((pe) => ({ seq: pe.seq, ts: pe.ts, state: pe.state, ...(pe.outcome !== undefined ? { outcome: pe.outcome } : {}), ...(pe.reason !== undefined ? { reason: pe.reason } : {}), })); const last = lifecycle[lifecycle.length - 1]!; const final_state: PlanState | PlanOutcome = last.outcome ?? last.state; const ref = reasoningRefFor(lifecycle[0]!.seq); return { plan: g.plan, plan_instance: g.instance, lifecycle, final_state, ...(ref !== undefined ? { reasoning_ref: ref } : {}) }; }); // ── orders — one record per placed order, ORDER ⋈ TELEMETRY ─────────────────── // esc rung (last-wins) + reprice tally from TELEMETRY `order`; probabilistic accounting + support from // TELEMETRY `settle`. All re-derived from the bus — never scraped from engine state (ADR-0011). const escByRef = new Map<string, number>(); const repriceByRef = new Map<string, number>(); const settleByRef = new Map<string, TelemetrySettleEvent>(); // Fill-guard evidence (kestrel-9gu.6): the far-OTM assessment inputs + cap decision, keyed by order. const guardByRef = new Map<string, TelemetryGuardEvent>(); for (const e of bus) { if (e.stream !== "TELEMETRY") continue; if (e.type === "order") { const t = e as TelemetryOrderEvent; escByRef.set(t.order_id, t.esc_stage); // last-wins ⇒ final rung if (t.reprice) repriceByRef.set(t.order_id, (repriceByRef.get(t.order_id) ?? 0) + 1); } else if (e.type === "settle") { const t = e as TelemetrySettleEvent; settleByRef.set(t.order_id, t); } else if (e.type === "guard") { const t = e as TelemetryGuardEvent; guardByRef.set(t.order_id, t); // last-wins (one per submission; a reprice mints a new ref) } } // Fold the ORDER stream: `place` seeds a record (first-seen order preserved); fill/cancel/reject set the // terminal disposition + reason. interface Acc { place: OrderEvent; final_state: OrderFinalState; filled: boolean; reason?: string; } const accByRef = new Map<string, Acc>(); const refOrder: string[] = []; for (const e of bus) { if (e.stream !== "ORDER") continue; const oe = e as OrderEvent; if (oe.type === "place") { if (!accByRef.has(oe.order_id)) { accByRef.set(oe.order_id, { place: oe, final_state: "working", filled: false }); refOrder.push(oe.order_id); } continue; } const acc = accByRef.get(oe.order_id); if (acc === undefined) continue; // a terminal event with no place is not a projectable order if (oe.type === "fill") { acc.filled = true; acc.final_state = "filled"; } else if (oe.type === "reject") { acc.final_state = "rejected"; if (oe.reason !== undefined) acc.reason = oe.reason; } else if (oe.type === "cancel") { // A fill already made this order terminal; a later cancel/expire does not undo it. if (!acc.filled) acc.final_state = oe.reason === "expired-unfilled" ? "expired" : "cancelled"; if (oe.reason !== undefined) acc.reason = oe.reason; } } const orders: OrderRecord[] = refOrder.map((ref) => { const acc = accByRef.get(ref)!; const p = acc.place; const settle = settleByRef.get(ref); const guard = guardByRef.get(ref); const filled = settle?.floor_filled ?? acc.filled; const support: FillSupport = settle?.support ?? "calibrated"; return { order_id: p.order_id, ...(p.plan !== undefined ? { plan: p.plan } : {}), ...(p.plan_instance !== undefined ? { plan_instance: p.plan_instance } : {}), instrument: p.instrument, side: p.side, qty: p.qty, // ADR-0017: an equity/spot order carries NEITHER a strike NOR a right; only an option leg does. // Omit both for a spot order (mirrors the frame's isSpotLeg boundary) rather than substituting a // fictional `strike: 0`/`right: "C"` — a phantom zero-strike CALL contract in the machine record // (report.json/ledger) that an outsider recomputing the benchmark would misread (kestrel-ldqt). ...(p.strike !== undefined ? { strike: p.strike } : {}), ...(p.right !== undefined ? { right: p.right } : {}), px: round(p.px ?? 0), esc_stage: escByRef.get(ref) ?? 0, reprice_count: repriceByRef.get(ref) ?? 0, final_state: acc.final_state, filled, pFill: round(settle?.expected_fill_prob ?? (filled ? 1 : 0)), support, floor_pnl: round(settle?.floor_pnl ?? 0), expected_pnl: round(settle?.expected_pnl ?? 0), ...(acc.reason !== undefined ? { reason: acc.reason } : {}), // Fill-guard evidence (kestrel-9gu.6), when a far-OTM leg carried a `guard` record. ...(guard !== undefined ? { moneyness: guard.moneyness, covered: guard.covered, directional_cap: guard.directional_cap } : {}), }; }); // ── totals — the floor/expected accounting, re-derived from settle telemetry ── // Sum the UNROUNDED per-order P&L then round once (the report's discipline) so the totals byte-match // EpisodeReport.totals. The headline is tainted when any non-zero `expected` contribution rode on // `extrapolated` support — a cell a grader refuses to bank (CONTEXT: Support flag). // The same settle stream also drives fill_claim (a57.4): partition the expected-$ by support so the two // claims reconstruct totals.expected exactly. Fail-closed: anything not `calibrated` (an `extrapolated` // or unstated flag) buckets as non-bankable — a grader refuses to bank it (bankableEv, 9gu.3). let floorSum = 0; let expectedSum = 0; let calibratedExpected = 0; let extrapolatedExpected = 0; let calibratedOrders = 0; let extrapolatedOrders = 0; // The SAMPLED channel (kestrel-9gu.12): present on the settle telemetry ONLY for a seeded run // (`sampled_pnl` rides ⇔ the sampler was armed). Folded exactly like floor/expected — sum the // unrounded per-order P&L, round once — so `totals.sampled` byte-matches the report's `sampled_usd`. let sampledSum = 0; let sampledArmed = false; let sampledExtrapolated = false; const taintReasons: string[] = []; // The per-cell expected-$ + support, collected in bus order for the SIGNED partition (kestrel-dpy). const claimCells: { support: FillSupport | undefined; ev: number }[] = []; // The settle-mark provenance record (kestrel-xwf) — at most one per graded bus (last-wins). let settleMarkEv: TelemetrySettleMarkEvent | undefined; for (const e of bus) { if (e.stream !== "TELEMETRY") continue; if (e.type === "settle_mark") { settleMarkEv = e as TelemetrySettleMarkEvent; continue; } // The per-wake THETA-BLEED record (theta-cell seam b) — the intra-session mark-to-model of held // option legs a cell opts into via `markToModel`. Folded into the floor EXACTLY like a `settle` // record's `floor_pnl` (so `totals.floor` carries the stand-down bleed), but it is NOT a per-order // settle: it never touches the expected/sampled channels or the support partition. A bus from a // cell that did not opt in carries none ⇒ byte-identical (additive-optional, like `settle_mark`). if (e.type === "theta_bleed") { floorSum += (e as TelemetryThetaBleedEvent).floor_pnl; continue; } if (e.type !== "settle") continue; const s = e as TelemetrySettleEvent; floorSum += s.floor_pnl; expectedSum += s.expected_pnl; if (s.sampled_pnl !== undefined) { sampledArmed = true; sampledSum += s.sampled_pnl; // A sampled REALIZATION on non-calibrated support can never be the headline (bankableEv, // ADR-0016 §5) — evidence for the gate, judged below through the one shared policy. if (s.sampled_filled === true && s.support !== "calibrated") sampledExtrapolated = true; } claimCells.push({ support: s.support, ev: s.expected_pnl }); if (s.support === "calibrated") { calibratedExpected += s.expected_pnl; calibratedOrders += 1; } else { extrapolatedExpected += s.expected_pnl; extrapolatedOrders += 1; if (s.expected_pnl !== 0) taintReasons.push(`${s.order_id}: expected banked on extrapolated support`); } } // Settle-mark staleness taint (kestrel-xwf): a stale mark taints the headline — the settled P&L // compares against a spot the tape stopped supporting (the 2025-04-09 frozen-underlier phantom // loss), so it is NON-BANKABLE. A closing put-call-parity recovery (`source: "parity"`) is an // ANNOTATED recovery — the book settled against an honest recovered spot and the reason says so — // but the primary feed still died, so the staleness taint stands (fail-closed core, kestrel-pez // unification); an unrecovered mark (`mark_uncertain`) is the loudest case, naming the retained // frozen level. Re-derived purely from the bus's `settle_mark` TELEMETRY record; a pre-xwf bus // carries none ⇒ no record, no retroactive taint (additive-optional, like `guard`). const settle_mark: SettleMarkRecord | undefined = settleMarkEv === undefined ? undefined : { px: settleMarkEv.px, as_of_ts: settleMarkEv.as_of_ts ?? null, last_observed_ts: settleMarkEv.last_observed_ts ?? null, age_ms: settleMarkEv.age_ms ?? null, stale_after_ms: settleMarkEv.stale_after_ms, stale: settleMarkEv.stale, source: settleMarkEv.source, mark_uncertain: settleMarkEv.mark_uncertain, note: settleMarkEv.note ?? null, }; if (settle_mark !== undefined && settle_mark.stale) { const staleness = settle_mark.age_ms === null ? `settle mark ${settle_mark.px} has unstated provenance (no spot observation on the tape)` : `settle mark ${settle_mark.px} is stale: value last established ${settle_mark.age_ms}ms before settle (> ${settle_mark.stale_after_ms}ms threshold)`; taintReasons.push( settle_mark.source === "parity" ? `${staleness}; recovered via closing put-call parity (annotated recovery) — P&L settled against it is non-bankable (kestrel-xwf)` : settle_mark.mark_uncertain ? `${staleness}; settle mark uncertain — no closing put-call parity derivable, last-known mark retained — P&L settled against it is non-bankable (kestrel-xwf, fail-closed)` : `${staleness} — P&L settled against it is non-bankable (kestrel-xwf)`, ); } const totalsFloor = round(floorSum); const totalsExpected = round(expectedSum); const totalsSampled = sampledArmed ? round(sampledSum) : undefined; // ── the headline (kestrel-9gu.12) — selected through the ONE gate policy, from bus bytes alone ── // The qualification claim is read fail-closed off the graded META (`sampled_qualification`, stamped by // the driver only for a consistent seeded+calibrated run); a malformed or absent claim ⇒ not qualified // ⇒ the strict-cross floor stays the headline (9gu.8 AC#7). The taints accumulated above (extrapolated // expected-$ + the xwf staleness verdict — parity recovery ANNOTATES but never pardons, so a stale // parity mark still taints) ride the selected channel — they never switch it. const qualification = readSampledQualificationClaim(meta.sampled_qualification); const gate = sampledQualified({ sampledArmed, sampledExtrapolated, ...(qualification !== undefined ? { qualification } : {}), }); const selected = selectHeadline( { floor: totalsFloor, expected: totalsExpected, ...(totalsSampled !== undefined ? { sampled: totalsSampled } : {}) }, gate, taintReasons, ); const headline: HeadlineFlag = { channel: selected.channel, usd: selected.usd, gate: selected.gate, tainted: selected.tainted, reasons: selected.reasons, }; const totals: Totals = { floor: totalsFloor, expected: totalsExpected, ...(totalsSampled !== undefined ? { sampled: totalsSampled } : {}), headline, ...(settle_mark !== undefined ? { settle_mark } : {}), }; // fill_claim — the expected-$ partitioned by support (a57.4), now carrying the SIGNED sub-cells written // ONCE (kestrel-dpy, ADR-0014). Fixed order [calibrated, extrapolated] so the array is byte-stable // across re-projection. Two invariants held together: // • EXACT reconstruction: Σ slices.expected === totals.expected. The extrapolated slice's `expected` // is DERIVED from totals.expected − calibrated (both on the 1e-8 grid) rather than rounding each raw // sum independently — otherwise double-rounding could let Σ slices disagree by one grid unit on // fine-grained residuals, breaking the reconstruct contract. // • SIGNED sub-cells: `gain` is the honest rounded Σ of non-negative expected-$ (what a subtracting // consumer removes to re-bank, so extrapolated LOSSES survive — ADR-0014's anti-erasure fix), and // `loss` is DERIVED as expected − gain so `expected === gain + loss` holds EXACTLY per slice (any // sub-grid double-rounding lands on the loss cell, which only ever makes bankable more conservative // — fail-closed-safe, never flattering). const part = partition(claimCells); const calibratedClaim = round(calibratedExpected); const extrapolatedClaim = round(totalsExpected - calibratedClaim); const calibratedGain = round(part.calibrated.gain); const extrapolatedGain = round(part.extrapolated.gain); const fill_claim: FillClaim[] = [ { support: "calibrated", orders: calibratedOrders, expected: calibratedClaim, gain: calibratedGain, loss: round(calibratedClaim - calibratedGain), }, { support: "extrapolated", orders: extrapolatedOrders, expected: extrapolatedClaim, gain: extrapolatedGain, loss: round(extrapolatedClaim - extrapolatedGain), }, ]; // ── certification — the determinism leg (sim); paper/live legs na (a57.3) ───── // A declared-but-incomplete experimental envelope (a57.14) — or a complete envelope whose declared // training_cutoff fails the model-registry cross-check (kestrel-m9i.23) — fails the record closed to // PROVISIONAL with the reasons recorded; a missing/unverifiable identity is never certified-by-implication. const certification = certificationOf(session.instance.mode, envelopeReasons); // ── rankability — the DERIVED leaderboard-eligibility axis (kestrel-m9i.25) ──── // A DISTINCT axis from certification: derived HERE from the certification verdict, the m9i.23 cutoff // cross-check, and the three governance/Layer-3 attestations off the graded META — never a // producer-stamped field (a bogus `meta.rankable`/`meta.rankability` is ignored; the conjunction is // recomputed from legs). The clock_honest attestation (ADR-0040 / kestrel-w7la.3) is the fifth leg. const rankability = deriveRankability({ certification, cutoffCheck, sessionDate: meta.session_date, dateBlind: meta.date_blind, seasonFrozen: meta.season_frozen, clockHonest: meta.clock_honest, }); // ── wake_trace — the clock-honest deliberation record (ADR-0040 / kestrel-w7la.1) ────────────── // A pure fold of the bus's WAKE/`deliberation` records (bus_schema v6): per-wake cost + the session // total. Record completeness, NOT a score — latency is already priced inside alpha by the fills // landing at return-time prices (clock-honest wakes §6). Absent on a latency-blind bus (which // carries none), so every existing projected Blotter is byte-identical. const deliberations: DeliberationTraceEntry[] = []; for (const e of bus) { if (e.stream !== "WAKE" || e.type !== "deliberation") continue; deliberations.push({ seq: e.seq, wake_seq: e.wake_seq, ts: e.ts, measured_ms: e.measured_ms, buffer_ms: e.buffer_ms, }); } const wake_trace: WakeTrace | undefined = deliberations.length > 0 ? { deliberations, deliberation_ms_total: deliberations.reduce((s, d) => s + d.measured_ms + d.buffer_ms, 0), } : undefined; return { session, certification, rankability, journals, disarms, plans, orders, totals, fill_claim, ...(wake_trace !== undefined ? { wake_trace } : {}), }; } /** * The certification block project() stamps (ADR-0011). The **determinism** leg claims the projection is * reproducible; {@link ./certify.ts} is the EXECUTABLE PROOF of that claim (re-project + byte-compare) — * a bug that broke purity makes `certify` refuse, so the embedded claim and the audit agree in a correct * system. In `sim` the three paper/live legs are `na` ⇒ `certified`; paper/live carry `provisional` until * a57.3 lands those legs (this slice does not evaluate them). * * FAIL-CLOSED (kestrel-a57.14): a declared-but-incomplete experimental envelope supplies `envelopeReasons` * (each naming a missing identity field). ANY such reason forces the verdict to `provisional` regardless of * mode and records the reasons — a missing author identity is an explicit PROVISIONAL result, never * certified-by-implication and never a silent default. `reasons` is omitted entirely when there are none, * so a clean `certified` record stays byte-minimal. */ function certificationOf(mode: string, envelopeReasons: readonly string[]): Certification { const isSim = mode === "sim"; const legs = { determinism: "pass", detectors_bit_for_bit: "na", fills_subset_of_live: "na", lifecycle_divergence_explained: "na", } as const; if (envelopeReasons.length > 0) { return { legs, verdict: "provisional", reasons: envelopeReasons }; } return { legs, verdict: isSim ? "certified" : "provisional" }; } /** Read an ATT boolean attestation off the graded META FAIL-CLOSED (kestrel-m9i.25): strictly `true` passes, * strictly `false` is a hard-false, ANYTHING else (absent / malformed) is UNKNOWN — never a silent pass on an * unstated attestation. */ function attestationLeg(v: unknown): RankableLeg { if (v === true) return "pass"; if (v === false) return "fail"; return "unknown"; } /** * Derive the {@link Rankability} axis (kestrel-m9i.25) — leaderboard ELIGIBILITY, a DISTINCT axis from * {@link Certification}. A CONJUNCTION of five legs computed PURELY from already-stamped fields (never a * producer-trusted `rankable`): the certification verdict, the m9i.23 cutoff cross-check on the a57.14 * envelope (consuming the SAME {@link isPostCutoff} boundary rule, never a second copy), the two ATT * governance attestations, and the ADR-0040 clock-honest attestation (kestrel-w7la.3). FAIL-CLOSED — an * UNKNOWN leg input ⇒ that leg is `unknown`, the row is NOT rankable, and a NAMED `*-unknown` reason is * recorded (never a silent `rankable: true`). Reasons are collected in a FIXED leg order * (certified → post_cutoff → date_blind → season_frozen → clock_honest — the fifth leg appended LAST so * every pre-w7la.3 reason ordering is byte-stable) for byte-stability (determinism, RUNTIME §0), and are * present ONLY when the row is not rankable. Pure and deterministic. */ function deriveRankability(input: { certification: Certification; cutoffCheck: TrainingCutoffCheck | undefined; sessionDate: string; dateBlind: unknown; seasonFrozen: unknown; clockHonest: unknown; }): Rankability { const reasons: RankableReason[] = []; // Leg 1 — CERTIFIED: the existing a57.14/m9i.23 verdict is `certified` (not `provisional`). Always a // definite verdict (never `unknown`) — a non-certified record is simply not leaderboard-comparable. const certified: RankableLeg = input.certification.verdict === "certified" ? "pass" : "fail"; if (certified === "fail") { reasons.push({ kind: "not-certified", detail: "rankable: certification verdict is 'provisional', not 'certified' — a non-certified record is not " + "leaderboard-comparable (kestrel-m9i.25)", }); } // Leg 2 — POST-CUTOFF: the tape date is STRICTLY after the model's knowledge cutoff (m9i.23 isPostCutoff), // where the cutoff month comes from the registry cross-check on the declared envelope. UNKNOWN (fail-closed) // when the cutoff is unverifiable — no complete envelope, an unknown model id, or a declared-registry // mismatch (the cross-check already flipped certification to provisional, but the cutoff still cannot gate, // so post-cutoff is neither asserted nor denied — it is UNKNOWN, never silently pre- or post-cutoff). let post_cutoff: RankableLeg; if (input.cutoffCheck === undefined || !input.cutoffCheck.ok) { post_cutoff = "unknown"; reasons.push({ kind: "cutoff-unknown", detail: "rankable: the model knowledge cutoff is unverifiable (no complete envelope, an unknown model id, or a " + "declared-vs-registry mismatch) — the post-cutoff leg cannot be established, so the row is not rankable " + "(fail-closed, kestrel-m9i.25)", }); } else if (isPostCutoff(input.cutoffCheck.cutoffMonth, input.sessionDate)) { post_cutoff = "pass"; } else { post_cutoff = "fail"; reasons.push({ kind: "pre-cutoff", detail: `rankable: tape date '${input.sessionDate}' is NOT strictly after the model knowledge cutoff ` + `'${input.cutoffCheck.cutoffMonth}' — the model may have known how the day ended, so a PRE-cutoff row is ` + "not rankable (kestrel-m9i.25)", }); } // Leg 3 — DATE-BLIND: the ATT attestation `meta.date_blind`, read fail-closed. const date_blind = attestationLeg(input.dateBlind); if (date_blind === "fail") { reasons.push({ kind: "not-date-blind", detail: "rankable: the run is attested NOT date-blind (meta.date_blind=false) — the agent could read the calendar " + "date off the tape, so the row is not rankable (kestrel-m9i.25)", }); } else if (date_blind === "unknown") { reasons.push({ kind: "date-blind-unknown", detail: "rankable: the date-blind attestation (meta.date_blind) is absent or malformed — UNKNOWN, so the row is " + "not rankable (fail-closed, kestrel-m9i.25)", }); } // Leg 4 — SEASON-FROZEN: the ATT attestation `meta.season_frozen`, read fail-closed (same as date-blind). const season_frozen = attestationLeg(input.seasonFrozen); if (season_frozen === "fail") { reasons.push({ kind: "season-not-frozen", detail: "rankable: the benchmark season is attested NOT frozen (meta.season_frozen=false) — the scenario set is " + "not sealed (ADR-0018), so the row is not rankable (kestrel-m9i.25)", }); } else if (season_frozen === "unknown") { reasons.push({ kind: "season-unknown", detail: "rankable: the season-frozen attestation (meta.season_frozen) is absent or malformed — UNKNOWN, so the " + "row is not rankable (fail-closed, kestrel-m9i.25)", }); } // Leg 5 — CLOCK-HONEST (ADR-0040 / kestrel-w7la.3, appended LAST): the Layer-3 attestation // `meta.clock_honest`, read fail-closed via the SAME attestationLeg rule. The driver stamps `true` or // NOTHING — so `unknown` is the latency-blind/unattested session ("…can never ground a latency claim", // CONTEXT.md), and `fail` is reachable only via a platform-side revocation (`false`). "No governed // season runs latency-blind" (AGENTS.md) made mechanical. const clock_honest = attestationLeg(input.clockHonest); if (clock_honest === "fail") { reasons.push({ kind: "not-clock-honest", detail: "rankable: the clock-honest attestation is REVOKED (meta.clock_honest=false, a platform-side revocation " + "value the driver never stamps) — the session's latency accounting is marked defective, so the row is " + "not rankable (ADR-0040, kestrel-w7la.3)", }); } else if (clock_honest === "unknown") { reasons.push({ kind: "clock-honest-unknown", detail: "rankable: the clock-honest attestation (meta.clock_honest) is absent or malformed — the session is " + "latency-blind or unattested, so the row is not rankable and can never ground a latency claim " + "(fail-closed, ADR-0040, kestrel-w7la.3)", }); } const rankable = certified === "pass" && post_cutoff === "pass" && date_blind === "pass" && season_frozen === "pass" && clock_honest === "pass"; return { legs: { certified, post_cutoff, date_blind, season_frozen, clock_honest }, rankable, // Byte-minimal: reasons present ONLY when the row is not rankable (mirrors a clean certified record). ...(reasons.length > 0 ? { reasons } : {}), }; }