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
text/typescript
/**
* # 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 } : {}),
};
}