/**
 * # blotter/types — the Blotter v1 typed record (kestrel-a57.1, ADR-0011; epic a57 schema)
 *
 * The **Blotter** is the deterministic projection of one Session {@link ../bus Bus} into the canonical
 * typed record of that Session (CONTEXT: Blotter). The Bus is the truth; the Blotter is its projection —
 * regenerable, byte-stable, never a second writer (ADR-0010). This file is the SHAPE only; the fold that
 * produces it is {@link ./project.ts}, its canonical bytes are {@link ./serialize.ts}, and the
 * determinism leg that proves the fold is pure is {@link ./certify.ts}.
 *
 * Two orthogonal stamps ride a Blotter and must never be conflated (ADR-0011):
 * **Certification** — is this record faithful and reproducible? (a set of pass/fail/na legs; the
 * determinism leg is a57.1's, the paper/live legs land in a57.3) — and **Fidelity** — how real are its
 * fills? (the `modeled|realized` level from the graded META, plus the judge's self-limitation stamp — what
 * it could NOT observe — derived from the fill model in a57.4). Certified never means good.
 */

import type {
  DirectionalCap,
  ExperimentalEnvelope,
  Fidelity,
  FillModelStamp,
  FillSupport,
  InstanceIdentity,
  MoneynessBucket,
  PlanOutcome,
  PlanState,
  RankableReason,
  Right,
  SessionInstrument,
} from "../bus/index.ts";
import type { PnlChannel, SampledQualification } from "../grade/headline.ts";

export type { ExperimentalEnvelope, TokenAccounting } from "../bus/index.ts";

// ─────────────────────────────────────────────────────────────────────────────
// session — identity, judge, fidelity, and the bus receipt this record projects from
// ─────────────────────────────────────────────────────────────────────────────

/** The bus receipt: how many events the graded bus held, the sha256 over its canonical JSONL
 * serialization (the truth this Blotter projects from), and the bus schema it was written at. */
export interface BusReceipt {
  readonly events: number;
  readonly sha256: string;
  readonly schema: number;
}

// ─────────────────────────────────────────────────────────────────────────────
// fidelity — the level (modeled|realized) + a SELF-LIMITATION the judge stamps (a57.4)
// ─────────────────────────────────────────────────────────────────────────────

/**
 * One thing the judge (the fill model that produced this graded bus's fills) **structurally could NOT
 * observe** — a stable machine `code` plus an honest human `note` (a57.4). These are not fabricated: each
 * is a documented structural fact of the named fill model (e.g. a strict-cross judge credits a fill only
 * on a tape cross; no judge in this build sees queue position), so a consumer cannot OVER-CLAIM realism the
 * judge never had.
 */
export interface FidelityLimit {
  /** A stable, lexical machine token for the limit (e.g. `no-queue-position`). */
  readonly code: string;
  /** The honest human phrasing of what the judge could not see. */
  readonly note: string;
}

/**
 * The judge's self-limitation declaration (a57.4): the fill model that produced the fills, and the ordered
 * list of what it structurally could NOT observe. Sourced deterministically from the graded META's
 * `fill_model` — never fabricated — so it re-projects byte-identically. An unrecognized fill model
 * fails closed to a single `observability-unstated` limit rather than inventing observability the judge may
 * not have (a consumer then treats the record as maximally limited).
 */
export interface FidelitySelfLimitation {
  /** The fill model these limits belong to (`fill_model.name` on the graded META — the judge). */
  readonly fill_model: string;
  /** What the judge could not observe, in a stable order (byte-stable across re-projection). */
  readonly limits: readonly FidelityLimit[];
}

/**
 * The Blotter's Fidelity stamp (CONTEXT: Fidelity; a57.4): the realism `level` a session may CLAIM
 * (`modeled` in sim/paper, `realized` in live — a META pass-through), PLUS a `self_limitation` declaring
 * what the judge could not see. The two together are how a consumer reads fill realism WITHOUT over-claiming
 * it: the level says how real the fills are, the self-limitation bounds what "real" even means for this judge.
 * Orthogonal to Certification (a sim Blotter can be certified yet low-fidelity).
 */
export interface BlotterFidelity {
  /** The fill realism level (`modeled` | `realized`) — the graded META pass-through. */
  readonly level: Fidelity;
  /** What the judge structurally could not observe — sourced from the fill model, never fabricated. */
  readonly self_limitation: FidelitySelfLimitation;
}

/** The Session header of a Blotter — its Instance identity + judge + fidelity + the bus it projects
 * from. Every field is a pure read of the graded bus's opening META (ADR-0011 part B). */
export interface BlotterSession {
  /** Instance identity (lineage/version/mode, pod when a Pod document ran) — ADR-0011 recommendation 1. */
  readonly instance: InstanceIdentity;
  /** The session's instruments (from the input META, carried through the graded META). */
  readonly instruments: readonly SessionInstrument[];
  /** The bus this Blotter projects from — the recorded truth (ADR-0010). */
  readonly bus: BusReceipt;
  /** sha256 over the graded bus's ENGINE-OUTPUT events (everything after the opening META) — pins the
   * engine's decisions, mirroring {@link ../session EpisodeReport}'s `determinism_hash`. A pure function
   * of the bus. (It re-pins the output from the graded bus, whose seq are re-stamped from the META, so it
   * need not byte-equal the report's hash — see the report→Blotter unification note in project.ts.) */
  readonly determinism_hash: string;
  /** The fill model that produced this graded bus's fills (the judge). */
  readonly fill_model: FillModelStamp;
  /** The fill realism this session may claim — the `modeled|realized` level PLUS the judge's
   * self-limitation (what it could not observe). Orthogonal to Certification (a57.4). */
  readonly fidelity: BlotterFidelity;
  /**
   * The author's experimental envelope (kestrel-a57.14): the agent/model identity that produced this
   * session, projected VERBATIM from the graded META's injected `envelope` (symmetric with `fill_model`,
   * the judge). Present ONLY when the graded bus declared a COMPLETE envelope; a bus that declared none
   * (a pre-a57.14 / input-derived graded bus) carries no envelope, and a declared-but-INCOMPLETE envelope
   * is NOT recorded here — a broken identity is never stamped as identity; it fails the record closed to a
   * PROVISIONAL {@link Certification} with the missing field named in `certification.reasons` instead.
   */
  readonly envelope?: ExperimentalEnvelope;
  /**
   * The FULL `ConfigId` of the run's config descriptor (`sha256(canonical AgentConfig)`, kestrel-5zl.6),
   * projected VERBATIM from the graded META's `config_id` (m9i.2 owner tweak). A SUPERSET identity of the
   * envelope — it additionally folds the sampling axis (`temperature`/`thinkingLevel`), `format`, and
   * `label` — so temperature-only config variants carry DISTINCT ids: the config axis the grid CellKey
   * keys on (`cellOf`, run-identity.ts). Additive/OPTIONAL: absent on a config-less graded bus and on a
   * pre-tweak graded bus (whose cell falls back to the envelope identity — a legacy cell, never pooled
   * with a ConfigId-keyed cell).
   */
  readonly config_id?: string;
  /**
   * The **cell config axis** — the full ConfigId with the `fillSeed` REPLICATE axis STRIPPED (kestrel-9gu.8.1 /
   * ADR-0016 §3), projected VERBATIM from the graded META's `cell_config_id`. This is the config axis `cellOf`
   * keys the cell on: seed-only variants share it (replicates in one cell, each a distinct `SimRunId`), while
   * temperature/behavioral variants still split. Present ONLY when it DIVERGES from `config_id` (the config
   * carried a `fillSeed`); a seedless run's cell axis EQUALS `config_id`, so `cellOf` reads `config_id`
   * directly. Additive/OPTIONAL: absent on a config-less, pre-tweak, or seedless graded bus.
   */
  readonly cell_config_id?: string;
}

// ─────────────────────────────────────────────────────────────────────────────
// certification — record honesty (a set of legs → a verdict)
// ─────────────────────────────────────────────────────────────────────────────

/** One certification leg's state (CONTEXT: Certification). `na` = not applicable to this mode. */
export type CertLeg = "pass" | "fail" | "na";

/** The certification verdict: `certified` only when every APPLICABLE leg passes, else `provisional`
 * (CONTEXT: Certification). Numbers always render with the verdict attached. */
export type Verdict = "certified" | "provisional";

/**
 * Certification — the verdict on whether this Blotter is a faithful, reproducible record of its Session.
 * a57.1 owns the SHAPE of all four legs and implements the **determinism** leg (re-project + byte-compare,
 * {@link ./certify.ts}); the paper/live legs (`detectors_bit_for_bit`, `fills_subset_of_live`,
 * `lifecycle_divergence_explained`) are `na` in sim and land as real legs with paper/live in a57.3.
 */
export interface Certification {
  readonly legs: {
    /** Re-project the Bus → byte-identical Blotter (the projector's core invariant, sim-applicable). */
    readonly determinism: CertLeg;
    /** Detectors reproduce bit-for-bit under replay (paper/live; `na` in sim — a57.3). */
    readonly detectors_bit_for_bit: CertLeg;
    /** Simulated fills are a subset of live fills (paper/live; `na` in sim — a57.3). */
    readonly fills_subset_of_live: CertLeg;
    /** Lifecycle divergence from live is explained (paper/live; `na` in sim — a57.3). */
    readonly lifecycle_divergence_explained: CertLeg;
  };
  readonly verdict: Verdict;
  /**
   * The recorded reasons a verdict is `provisional` — fail-closed, never silent (kestrel-a57.14). Parallel
   * to {@link HeadlineFlag.reasons}: each reason NAMES the cause (e.g. an experimental-envelope identity
   * field that was declared-missing), so a `provisional` number never renders without its cause attached.
   * Present ONLY when there ARE reasons (a byte-minimal `certified` record carries none). Byte-stable:
   * derived deterministically, in a fixed order, from the bus.
   */
  readonly reasons?: readonly string[];
}

// ─────────────────────────────────────────────────────────────────────────────
// rankability — leaderboard ELIGIBILITY, a DISTINCT axis from certification (kestrel-m9i.25)
// ─────────────────────────────────────────────────────────────────────────────

/** One rankable leg's state (kestrel-m9i.25). `pass`/`fail` mirror {@link CertLeg}; `unknown` is the
 * fail-closed state — an ABSENT or malformed leg input is UNKNOWN, never silently passed. There is no `na`:
 * every leg is applicable to leaderboard eligibility. */
export type RankableLeg = "pass" | "fail" | "unknown";

/**
 * Rankability — the DERIVED leaderboard-ELIGIBILITY axis (kestrel-m9i.25), a sibling of {@link Certification}
 * but an ORTHOGONAL question. Certification asks "is this record honest + reproducible?"; rankability asks
 * "is this row COMPARABLE on the leaderboard?". It is a CONJUNCTION of five legs —
 *
 *     rankable = CERTIFIED ∧ POST-CUTOFF ∧ DATE-BLIND ∧ (SEASON) FROZEN ∧ CLOCK-HONEST
 *
 * — DERIVED at projection from already-stamped fields (the certification verdict, the kestrel-m9i.23 cutoff
 * cross-check on the a57.14 envelope, and the three ATT/Layer-3 attestations `date_blind`/`season_frozen`/
 * `clock_honest`), NEVER a field a producer stamps (a producer-stamped `rankable` on the bus is ignored —
 * the projector recomputes the conjunction from the legs). It ENDS "certified" doing double duty: a
 * CERTIFIED run on a PRE-CUTOFF tape (the model already knew the outcome) is
 * `certification.verdict === "certified"` yet `rankable === false`. FAIL-CLOSED: an UNKNOWN leg input ⇒ not
 * rankable + a NAMED reason, never a silent `rankable: true`.
 *
 * The CLOCK-HONEST leg (ADR-0040 / kestrel-w7la.3, appended LAST so every pre-existing reason ordering is
 * byte-stable) is "no governed season runs latency-blind" (AGENTS.md) made mechanical: a latency-blind
 * session stays VALID — certified, gradable, comparable in exploratory grids — but is never
 * governed-leaderboard-rankable and can never ground a latency claim ({@link ./claims.ts latencyClaimGate}).
 */
export interface Rankability {
  readonly legs: {
    /** The certification verdict is `certified` (not `provisional`). */
    readonly certified: RankableLeg;
    /** The tape date is STRICTLY after the model's knowledge cutoff (m9i.23 `isPostCutoff`); `unknown` when
     * the cutoff is unverifiable (no complete envelope / unknown model id / declared-registry mismatch). */
    readonly post_cutoff: RankableLeg;
    /** The run is attested date-blind (`meta.date_blind`); `unknown` when the attestation is absent/malformed. */
    readonly date_blind: RankableLeg;
    /** The benchmark season is frozen (`meta.season_frozen`); `unknown` when the attestation is absent/malformed. */
    readonly season_frozen: RankableLeg;
    /** The session is attested clock-honest (`meta.clock_honest`, ADR-0040 / kestrel-w7la.3): deliberation
     * consumed tape time on eligible (sub-minute) ground truth. The driver stamps `true` or NOTHING — so
     * `unknown` (absent/malformed) is the latency-blind/unattested case, and `fail` is reachable only via a
     * platform-side revocation (`false`). This is the leg the platform's FORBIDDEN-CLAIMS lint reads
     * ({@link ./claims.ts latencyClaimGate}): a latency claim may cite only a `pass` session. */
    readonly clock_honest: RankableLeg;
  };
  /** The headline conjunction: `true` iff EVERY leg passes. */
  readonly rankable: boolean;
  /**
   * The recorded reasons `rankable` is false — fail-closed, never silent, one per non-passing leg, in a
   * FIXED leg order (certified → post_cutoff → date_blind → season_frozen → clock_honest; the fifth leg is
   * appended LAST so every pre-w7la.3 ordering is byte-stable) for byte-stability. Each NAMES which leg
   * failed (and whether it was a hard-false or a fail-closed UNKNOWN). Present ONLY when `rankable` is
   * false (a rankable row is byte-minimal, carrying none).
   */
  readonly reasons?: readonly RankableReason[];
}

// ─────────────────────────────────────────────────────────────────────────────
// journals — the author's reasoning, inline (folded straight from the JOURNAL stream)
// ─────────────────────────────────────────────────────────────────────────────

/** One JOURNAL record projected into the Blotter — full markdown `body` inline (text is truth,
 * ADR-0010). `seq` is the source of truth a plan's {@link ReasoningRef} references. */
export interface JournalEntry {
  readonly seq: number;
  readonly kind: string;
  readonly ts: number;
  readonly body: string;
}

// ─────────────────────────────────────────────────────────────────────────────
// disarms — reason-carrying stand-down / de-arm audit records (CONTROL `disarm`)
// ─────────────────────────────────────────────────────────────────────────────

/** One reason-carrying de-arm on the Blotter, projected from a CONTROL `disarm` record (kestrel-2pl).
 * The author's `standDown` (inventory rides its TP/EXIT, never liquidates) and a fail-closed
 * supersede-parse-escape de-arm both emit this — so the WHY of a stand-down is an explicit audit record,
 * not merely INFERABLE from plans going `expired(superseded)`. `reason` is the note the CONTROL carried.
 * The de-arm discriminant + reason vocabulary this projects from live in `src/engine/disarm.ts`
 * (`DISARM_CONTROL_TYPE`, kestrel-z473.5). */
export interface DisarmRecord {
  readonly seq: number;
  readonly ts: number;
  readonly reason?: string;
}

// ─────────────────────────────────────────────────────────────────────────────
// plans — lifecycle + final state + a reference (never a copy) to the author's reasoning
// ─────────────────────────────────────────────────────────────────────────────

/** One transition in a plan's lifecycle, reconstructed from the PLAN stream — carrying the `seq`
 * so the trace is anchored to the bus. */
export interface BlotterLifecycleStep {
  readonly seq: number;
  readonly ts: number;
  readonly state: PlanState;
  readonly outcome?: PlanOutcome;
  readonly reason?: string;
}

/**
 * A reference (never a copy) to the author's reasoning for a plan (ADR-0011 recommendation 2): the
 * `seq` into {@link Blotter.journals} is the source of truth, and `excerpt` is a mechanical,
 * deterministic preview — the body's first non-empty line, trimmed, capped ~120 chars with an ellipsis.
 * No markdown interpretation.
 */
export interface ReasoningRef {
  readonly seq: number;
  readonly excerpt: string;
}

/** A plan's lifecycle trace + terminal state, plus a reference to its pre-hoc author reasoning when a
 * JOURNAL precedes its first lifecycle transition. One record is one exact Plan **instance** (kestrel-22j.15):
 * a legal same-name replacement projects as its OWN record beside its predecessor, never collapsed into it. */
export interface PlanRecord {
  /** The authored plan NAME — the Lineage aggregation key (a consumer rolls instances up BY this; a name may
   * legally recur, so it is NOT the instance identity). */
  readonly plan: string;
  /** The exact Plan-instance identity this record traces (kestrel-22j.15): the `plan_instance` minted by the
   * engine on a v5 bus, or a deterministic sessionized key migrated from a pre-v5 bus. Distinct per instance,
   * so two same-name instances are two records. */
  readonly plan_instance: string;
  readonly lifecycle: readonly BlotterLifecycleStep[];
  /** The terminal outcome when `done`, else the last lifecycle state. */
  readonly final_state: PlanState | PlanOutcome;
  /** The pre-hoc author JOURNAL this plan references (absent when none precedes it). */
  readonly reasoning_ref?: ReasoningRef;
}

// ─────────────────────────────────────────────────────────────────────────────
// orders — one record per placed order, joined across ORDER + TELEMETRY (never engine state)
// ─────────────────────────────────────────────────────────────────────────────

/** An order's terminal disposition, read from the ORDER stream. */
export type OrderFinalState = "filled" | "cancelled" | "expired" | "rejected" | "working";

/**
 * One placed order, projected by joining the ORDER stream (place/fill/cancel/reject) with the engine's
 * per-order TELEMETRY (`order` → esc rung + reprice tally; `settle` → the probabilistic accounting +
 * the 9gu.3 support flag). Every field is re-derived from bus bytes — never scraped from engine state
 * (ADR-0011). Per-order `support` is here; its session-level rollup is {@link Blotter.fill_claim} (a57.4).
 */
export interface OrderRecord {
  readonly order_id: string;
  readonly plan?: string;
  /** The exact Plan-instance identity that authored this order (kestrel-22j.15), when it came from a plan on a
   * v5 bus — so an order joins its exact instance, not merely its recurring name. */
  readonly plan_instance?: string;
  readonly instrument: string;
  readonly side: "buy" | "sell";
  readonly qty: number;
  /** The option strike, present IFF this order carries an option leg. ABSENT for an ADR-0017 equity/spot
   * order (which has NEITHER a strike NOR a right) — never a fictional zero-strike. The machine surface
   * mirrors the frame's spot/option boundary ({@link ../frame/format.ts}:isSpotLeg): both absent ⇒ spot.
   * A prior projection substituted `strike: 0` here, planting a phantom zero-strike CALL contract in the
   * recomputability substrate (report.json/ledger) that an agent parsing an equity order would misread
   * (kestrel-ldqt; same failure kestrel-1kp fixed on the frame surface). */
  readonly strike?: number;
  /** The option right, present IFF this order carries an option leg. ABSENT for an ADR-0017 equity/spot
   * order — never a fictional `"C"`. Rides in lockstep with {@link strike} (both present ⇒ option; both
   * absent ⇒ spot); a mixed presence is never emitted. */
  readonly right?: Right;
  /** Limit price at placement. */
  readonly px: number;
  /** The esc-ladder rung this order last occupied (last `esc_stage` on its TELEMETRY `order` records). */
  readonly esc_stage: number;
  /** Count of cancel/replace reprices for this order (sum of `reprice` on its TELEMETRY `order` records). */
  readonly reprice_count: number;
  readonly final_state: OrderFinalState;
  /** Did the strict-cross floor fire (a definite fill)? */
  readonly filled: boolean;
  /** Accrued expected fill probability `1 − survival` (`1` on a floor fill). */
  readonly pFill: number;
  /** The order-level fill-support flag (9gu.3): a grader refuses to bank `expected` from `extrapolated`. */
  readonly support: FillSupport;
  /** Realized $ under the strict-cross floor (0 unless floor-filled). */
  readonly floor_pnl: number;
  /** E[$] under `pFill`. */
  readonly expected_pnl: number;
  /** A cancel/reject reason, when the terminal ORDER event carried one. */
  readonly reason?: string;
  /** The coarse moneyness bucket the fill-guard assessed (kestrel-9gu.6), when this order was
   * submitted in the far-OTM wing (the only wing the directional guard acts on) — from the `guard`
   * TELEMETRY record. Absent for a near-the-money / unclassified order (no guard record). */
  readonly moneyness?: MoneynessBucket;
  /** The covered-state the guard threaded (kestrel-9gu.6): `true` = a covering wing (exempt from the
   * SELL far-OTM cap), `false` = a standalone offer. Present iff a `guard` record rode for this order. */
  readonly covered?: boolean;
  /** The directional far-OTM cap decision (kestrel-9gu.6): `applied` (standalone SELL floored to the
   * no-fill cap), `exempt` (covering wing left uncapped), or `na` (far-OTM BUY, unlocked not capped).
   * Present iff a `guard` record rode for this order. */
  readonly directional_cap?: DirectionalCap;
}

// ─────────────────────────────────────────────────────────────────────────────
// totals — the floor / expected accounting, re-derived from the settle telemetry
// ─────────────────────────────────────────────────────────────────────────────

/**
 * The headline record on the totals (kestrel-9gu.12): WHICH channel is the headline (`channel`/`usd`,
 * selected through the ONE gate policy in {@link ../grade/headline.ts} — `floor` until the sampled
 * channel's 9gu.8.6 qualification is on the record, never an extrapolated-support sampled result), the
 * `gate` verdict that made the selection (its reasons on the record when floor holds), and the honesty
 * taint: `tainted` is `true` when any non-zero `expected` contribution rode on `extrapolated` support
 * (a cell a grader refuses to bank, CONTEXT: Support flag) or the settle mark itself was untrustworthy
 * (kestrel-xwf) — a taint rides EVERY channel (all three settle against the same mark), so the headline
 * number always renders with its taint attached, never silently.
 */
export interface HeadlineFlag {
  /** The selected headline channel: `floor` (fail-closed default) or `sampled` (once qualified). */
  readonly channel: PnlChannel;
  /** The selected channel's $ value (the other channels stay beside it as honest bounds). */
  readonly usd: number;
  /** The qualification-gate verdict (kestrel-9gu.8.6 seam) that selected the channel. */
  readonly gate: SampledQualification;
  readonly tainted: boolean;
  readonly reasons: readonly string[];
}

/**
 * The settle mark's provenance + fail-closed staleness verdict (kestrel-xwf), re-derived from the
 * `settle_mark` TELEMETRY record: WHAT spot the book cash-settled against, WHEN that value was last
 * established on the input tape (`as_of_ts` — a frozen feed re-printing the same px does not refresh
 * it), and whether it was `stale` at the settle instant under the declared threshold.
 * `stale: true` taints {@link Totals.headline}: the settled P&L is graded against a mark the tape
 * stopped supporting (the 2025-04-09 frozen-underlier phantom loss), so it is NON-BANKABLE — honest
 * provenance, never an invented "true close". Explicit `null` = unstated (itself a stale verdict).
 *
 * `source`/`mark_uncertain`/`note` carry the ANNOTATED-RECOVERY layer (kestrel-xwf unification): a
 * STALE mark that could be recovered from closing put-call parity settles against the recovered spot
 * (`source: "parity"`, `px` = the recovered value) — but recovery ANNOTATES, it never PARDONS: the
 * staleness taint stands (`stale: true` still taints the headline, kestrel-9gu.12). One that could not
 * be recovered is retained (`source: "stale"`, `mark_uncertain: true` — the loudest taint). A live mark
 * is `source: "market"`.
 */
export interface SettleMarkRecord {
  readonly px: number;
  readonly as_of_ts: number | null;
  readonly last_observed_ts: number | null;
  readonly age_ms: number | null;
  readonly stale_after_ms: number;
  readonly stale: boolean;
  readonly source: "market" | "parity" | "stale";
  readonly mark_uncertain: boolean;
  readonly note: string | null;
}

/** The session totals — the THREE-channel P&L contract (kestrel-9gu.12), re-derived from the
 * settle-outcome TELEMETRY (the sum of the unrounded per-order P&L, rounded once on the 1e-8 grid —
 * byte-matching {@link ../session EpisodeReport}'s totals). Floor and expected are always present;
 * `sampled` only on a seeded run — the headline is SELECTED among the realizations by the gate. */
export interface Totals {
  /** Definite-fill $ only — the conservative floor (`realized_floor_usd` in the report). */
  readonly floor: number;
  /** E[$] weighted by `1 − survival` (`expected_usd` in the report). */
  readonly expected: number;
  /** The seeded causal realization (`sampled_usd` in the report). ABSENT — not `0` — when the sampled
   * channel is off (an un-run channel is never conflated with a zero outcome, kestrel-9gu.12). */
  readonly sampled?: number;
  readonly headline: HeadlineFlag;
  /** The settle mark's provenance + staleness verdict (kestrel-xwf), when the graded bus carries the
   * `settle_mark` TELEMETRY record. ABSENT on a pre-xwf graded bus (provenance unrecorded — the
   * additive-optional convention, like `guard`); a stale record taints {@link headline}. */
  readonly settle_mark?: SettleMarkRecord;
}

// ─────────────────────────────────────────────────────────────────────────────
// fill_claim — the expected-$ partitioned by fill support (a57.4)
// ─────────────────────────────────────────────────────────────────────────────

/**
 * One support class's slice of the Blotter's expected-$ (a57.4) — the aggregate rollup deferred from a57.1
 * (`OrderRecord.support` is the per-order flag; this is its session-level partition). Derived PURELY from
 * the per-order `support` on the settle telemetry: it splits `totals.expected` into the portion resting on
 * `calibrated` support (which a grader banks) and the portion resting on `extrapolated` support (which a
 * grader **refuses to bank** — the bankableEv doctrine, 9gu.3). The two claims partition
 * the whole: `Σ fill_claim[i].expected` reconstructs `totals.expected`.
 *
 * SIGNED SUB-CELLS (kestrel-dpy, ADR-0014): each slice carries the partition WRITTEN ONCE — a `gain`
 * (Σ non-negative expected-$) and a `loss` (Σ negative), with `expected === gain + loss`. This closes
 * a fail-open gap: a consumer that re-banks by SUBTRACTING the extrapolated slice must subtract only its
 * `gain`, so extrapolated LOSSES survive (they are kept by the `bankableEv` doctrine, 9gu.3) and can
 * never be zeroed. Subtracting the unsigned `expected` (the old shape) would have erased extrapolated
 * gains and losses together — flattering the loss-parking strategy the doctrine exists to punish. Same
 * bus ⇒ byte-identical claims.
 */
export interface FillClaim {
  /** The support class this slice aggregates (CONTEXT: Support flag). */
  readonly support: FillSupport;
  /** How many settled orders rest on this support class. */
  readonly orders: number;
  /** Σ `expected_pnl` over those orders (rounded once on the 1e-8 grid, like {@link Totals}).
   * Equals `gain + loss` — the net of this slice's signed sub-cells. */
  readonly expected: number;
  /** The slice's GAINS: Σ non-negative `expected_pnl` (≥ 0, on the 1e-8 grid). A subtracting consumer
   * removes ONLY this to re-bank, so extrapolated losses are never erased (ADR-0014). */
  readonly gain: number;
  /** The slice's LOSSES: Σ negative `expected_pnl` (≤ 0, on the 1e-8 grid). KEPT for extrapolated cells
   * — `bankableEv` refuses extrapolated gains but never forgives a loss. */
  readonly loss: number;
}

// ─────────────────────────────────────────────────────────────────────────────
// wake_trace — the clock-honest deliberation record, projected (ADR-0040 / kestrel-w7la.1)
// ─────────────────────────────────────────────────────────────────────────────

/** One `WAKE`/`deliberation` record projected verbatim (bus_schema v6, CONTEXT "Deliberation record"):
 * the cost of one clocked Seat turn. `ts` IS the derived return time (`checkpoint.ts + measured_ms +
 * buffer_ms` — the reader enforces the identity); `wake_seq` names the WAKE checkpoint it prices. */
export interface DeliberationTraceEntry {
  /** The record's own `seq` on the graded bus. */
  readonly seq: number;
  /** The `seq` of the WAKE checkpoint this cost belongs to (the vantage the Seat answered). */
  readonly wake_seq: number;
  /** The derived return time — when the Seat's control landed back on the tape. */
  readonly ts: number;
  /** Measured wall time of the Seat's whole turn (bounded authoring loop + repairs included). */
  readonly measured_ms: number;
  /** The configured latency buffer added to every measured turn. */
  readonly buffer_ms: number;
}

/** The Blotter's wake trace (clock-honest wakes §6): the session's deliberation records — per-wake
 * cost and the session total. RECORD COMPLETENESS, not a score (ADR-0011: the Blotter is the whole
 * record) — latency is already priced inside alpha by the fills landing at return-time prices; there
 * is no separate latency score to game. Present ONLY when the graded bus carries deliberation records
 * (a clock-honest session); a latency-blind blotter omits it, byte-identical to before. */
export interface WakeTrace {
  readonly deliberations: readonly DeliberationTraceEntry[];
  /** Σ (`measured_ms + buffer_ms`) over the session — the total tape time deliberation consumed. */
  readonly deliberation_ms_total: number;
}

// ─────────────────────────────────────────────────────────────────────────────
// The Blotter
// ─────────────────────────────────────────────────────────────────────────────

/** Blotter v1 — the complete, replayable record of one Session, projected deterministically from its
 * Bus (CONTEXT: Blotter; a57 epic schema; ADR-0011). */
export interface Blotter {
  readonly session: BlotterSession;
  readonly certification: Certification;
  /** The DERIVED leaderboard-ELIGIBILITY axis (kestrel-m9i.25) — `certified ∧ post-cutoff ∧ date-blind ∧
   * (season) frozen`, computed at projection from stamped fields, a DISTINCT axis from `certification` (a
   * row can be `certification.verdict === "certified"` yet `rankability.rankable === false`). */
  readonly rankability: Rankability;
  readonly journals: readonly JournalEntry[];
  /** Reason-carrying stand-down / de-arm audit records (kestrel-2pl), in bus order. Empty when the
   * session never de-armed. Projected from CONTROL `disarm` — a pure bus read (ADR-0011). */
  readonly disarms: readonly DisarmRecord[];
  readonly plans: readonly PlanRecord[];
  readonly orders: readonly OrderRecord[];
  readonly totals: Totals;
  /** The session's expected-$ partitioned by fill support (a57.4): the `calibrated` slice a grader banks
   * and the `extrapolated` slice it refuses to bank (9gu.3). Always two entries, in the fixed order
   * `[calibrated, extrapolated]` — deterministic and byte-stable. Partitions {@link Totals.expected}. */
  readonly fill_claim: readonly FillClaim[];
  /** The clock-honest deliberation trace (ADR-0040 / kestrel-w7la.1) — per-wake cost + session total,
   * a pure fold of the bus's `WAKE`/`deliberation` records. ABSENT on a latency-blind bus (which
   * carries none), so every existing projected Blotter is byte-identical. */
  readonly wake_trace?: WakeTrace;
}
