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.
380 lines • 30.2 kB
TypeScript
/**
* # session/simulate — the frozen-at-wake Simulate driver (the Agent seam's companion to `./day.ts`)
*
* The **wake-driven, agent-in-loop** driver (RUNTIME §7). Where {@link import("./day.ts").runDaySession}
* pauses at each wake and hands an external author a Frame through a FILE handshake, this drives the SAME
* {@link SessionCore} — the same bus-stepping, the same {@link import("../engine").Gate}, the same
* fills-before-sweep ordering — but hands the frozen vantage to the {@link Agent} seam IN-PROCESS and
* consumes the {@link AgentTurn} it returns. Between wakes the standing Plans fire autonomously
* (fire-then-inform); at a wake the driver freezes market time, assembles a date-blind {@link ActingFrame},
* `await`s `agent.decide(frame)`, and serializes every returned {@link Action} onto the graded Bus.
*
* ## Where the determinism boundary sits (RUNTIME §0, the whole point)
* The single value that crosses the boundary is the returned {@link AgentTurn}; BELOW it everything is a
* pure function of Bus bytes (ADR-0011). Every Action is stamped at the **injected wake ts** (no wall
* clock, no unseeded RNG on the record path), so `project(gradedBus)` re-derives a byte-identical Blotter
* and a captured run re-runs as a Backtest through {@link recordedAgent}. The delivered {@link ActingFrame}
* (Rendering, model call, sampling) sits ABOVE the line — the recorded/fixed adapters ignore it entirely.
*
* ## Action → Bus routing (fail-closed, bounded-risk)
* - `supersede` → parse the Kestrel document; the FIRST is the initial arm (no CONTROL, `day.ts` plans-0
* parity), a later one emits a CONTROL `supersede` + de-arm + arm. A parse escape de-arms
* clean with a logged reason (never a crash — RUNTIME §8).
* - `standDown` → a CONTROL `disarm` + de-arm clean (inventory rides its TP/EXIT — never liquidates).
* - `journal` → a **pre-hoc** JOURNAL `author` record, emitted BEFORE the turn's other actions (provably
* pre-hoc by `seq`).
* - `scheduleWake` → recorded as a WAKE `scheduled` record AND unioned onto the agent-driven wake
* frontier (kestrel-5zl.4): the agent's own cadence drives, floored (never replaced) by
* the staleness backstop + optional structural cadence, coalesced/downgraded past the
* attention budget (the squelch stays visible — never a silent drop).
* - `placeOrder` / `cancelOrder` → routed through the **SAME Gate** a fired Plan uses (`core.gate`): an
* order is expressed as a one-shot Plan and armed, so it crosses the identical
* engine→Gate→fill path — SELL≥intrinsic, the budget clamp, and never-naked are enforced by
* the engine, never re-implemented here (bounded risk by construction).
*
* Scope: this is the tracer-bullet slice — the thinnest deterministic Simulate path exercised by
* {@link fixedPlanAgent} + {@link recordedAgent}. The live adapter body, the config matrix, and
* wire-capture are later slices; the full Wake-grammar authoring (subscriptions/Views, the budget
* algebra, per-session structural re-anchoring) is the b3l Wake-router epic — see `armStaleness`/
* `resolveWakeAt` for the conservative defaults taken here.
*/
import type { BusEvent } from "../bus/index.ts";
import { type Module, type PlanStatement } from "../lang/index.ts";
import type { InstrumentSpec } from "../engine/index.ts";
import type { EpisodeSigmoidParams } from "../fill/index.ts";
import type { Blotter } from "../blotter/index.ts";
import type { Kernel, Mandate, Brief, PriorSessionTape, PriorVantage } from "../frame/types.ts";
import { type FairTauProvider } from "./clock.ts";
import { type FillModelName, type SessionReport } from "./sim.ts";
import { type AuthorFrame, type TimeOfDay } from "./day.ts";
import { type ActingFrame, type Agent, type AgentConfig, type CapturedTurns } from "./agent.ts";
import { type ViewSelection } from "../frame/pane-catalog.ts";
import type { OptionsAnalytics } from "../frame/options-analytics.ts";
import { type SessionCarry } from "./carry.ts";
import { type VehicleBook } from "./vehicle-health.ts";
import { type OptionsOverlayConfig } from "./market-pane.ts";
import { type EmergenceRecord } from "./authoring-loop.ts";
import { type WakeCtx } from "./wake-frontier.ts";
export { marketPaneOf, SERVED_TAPE_BUCKET_MIN, type ChainFairContext, type OptionsOverlayConfig } from "./market-pane.ts";
export { vehicleHealthOf, vehicleBookFromSpot, type VehicleBook } from "./vehicle-health.ts";
export { sizingHeadroomOf } from "./sizing.ts";
export { viewSelectionOfDocument, DEFAULT_VIEW_REQUEST_CAP, DEFAULT_AUTHORING_TOKEN_BUDGET, type EmergenceRecord, } from "./authoring-loop.ts";
export { type WakeCtx } from "./wake-frontier.ts";
/**
* The DAY-COMPAT side-channel (kestrel-5zl.3) — the narrow bridge the {@link import("./day.ts").runDaySession}
* fileHandshakeAgent and the driver share so the day agent can render its inspectable artifacts + validate
* revisions against the LIVE core WITHOUT a forked progression path. It carries NOTHING onto the graded
* stream (it sits entirely ABOVE the determinism line): the driver sets `vantage` at each vantage BEFORE
* calling `agent.open`/`agent.decide`, and binds `previewSupersede` once to the live engine's pure collision
* preview. Present ONLY on the actual day file agent; a plain {@link dayCompat} run (e.g. a recordedAgent
* replay) passes no bridge and the driver never touches it.
*/
export interface DayCompatBridge {
/** The raw date-blind {@link AuthorFrame} for THIS vantage (OPEN briefing / each wake), set by the driver
* before the corresponding `agent.open`/`agent.decide`. The day agent names each wake artifact from it
* (`frame-<n>-<HHMM>.txt`) and serializes it as the `state-<n>.json` machine channel; the TEXT frames
* render through the canonical `src/frame` renderer over the driver's typed frames (kestrel-wa0j.2). */
vantage?: AuthorFrame;
/** The engine's PURE supersede-then-arm collision preview ({@link import("../engine/index.ts").PlanEngine}
* `supersedeArmRejection`), bound once by the driver to the live core: a rejection reason or `null`. The
* day agent's reject-retry consults it so the standing book is NEVER torn down for a doomed revision
* (fail-closed blast-radius, RUNTIME §8) — the collision preview guarantees the driver's subsequent
* supersede+arm cannot reject. */
previewSupersede?: (mod: Module) => string | null;
}
/** Options for {@link runSimulateSession}. Exactly one of `busPath`/`events` supplies the bus; the
* {@link Agent} seam supplies the decisions. The fill/tau/budget knobs mirror {@link import("./sim.ts").RunSimOptions}. */
export interface RunSimulateOptions {
readonly busPath?: string;
readonly events?: readonly BusEvent[];
/** The agent under test — live, recorded, fixed-plan, or file-handshake (the ONE seam). */
readonly agent: Agent;
/** Authored wake vantages (ET times-of-day), strictly inside the driven window. */
readonly wakes?: readonly TimeOfDay[];
/** The author acting cutoff (an ET wall-clock time-of-day). The OPEN briefing is built ONLY from
* observations watermarked at or before this instant; defaults to the canonical benchmark's T-5
* (09:25 ET). Injected + explicit so no post-cutoff print leaks to the agent (kestrel-m9i.11). */
readonly authorCutoff?: TimeOfDay;
/** Present the OPEN authoring vantage as an INTRADAY keyframe carrying the observed range
* (kestrel-1vw): when `true`, the OPEN briefing folds every exec observation at/before {@link
* authorCutoff} into the range (`hod`/`lod`/`tape` + the current spot) instead of the pre-open
* keyframe — so an ORB cell authoring at its opening-range close sees the range it must break out of.
* The causal cutoff fence is unchanged (no post-cutoff print leaks); this ONLY changes whether the
* admitted prefix is collapsed to the opening keyframe or presented as the range. Absent / `false` ⇒
* today's pre-open briefing, byte-identical. Set together with an intraday {@link authorCutoff}. */
readonly authorFromRange?: boolean;
/** Add the structural cadence into the close (T-2h…T-5m) — see {@link computeWakes}. */
readonly structural?: boolean;
readonly fillModel: FillModelName;
readonly rUsd: number;
/** The cell-sourced hard {@link Mandate} (ADR-0026) — the objective + R-definition + success
* criterion + bounded-risk rule the agent is graded against. Rendered in the kernel; the ONLY
* admission input. A GRADED run must declare one ({@link import("../frame/types.ts").assertGradedMandate});
* an ungraded/dev run may omit it (the frame renders unchanged). NOT hardcoded — the cell owns it. */
readonly mandate?: Mandate;
/** The cell-sourced soft {@link Brief} (ADR-0026) — directional English (goal/approach/persona),
* rendered as standing context, hashed + attributed, but NEVER an admission input (the hard guard). */
readonly brief?: Brief;
readonly instruments?: readonly InstrumentSpec[];
readonly fairTauYears?: FairTauProvider;
readonly makerFairParams?: EpisodeSigmoidParams;
/** The prior session's {@link SessionCarry} (the multi-session horizon design, kestrel-5zl.16). Its `positions` seed this
* session's opening book and its `document` is re-armed fresh (new plan-instance ids) BEFORE the OPEN
* turn. Absent — or an `emptyCarry()` — is today's flat open, byte-identical. */
readonly openingCarry?: SessionCarry;
/** `true` for a NON-final session of a multi-session Instance: settle carry-marks held inventory (it
* survives into the returned {@link SimulateResult.carry}) instead of forcing it to intrinsic. Absent /
* `false` — a standalone or the final session — is today's terminal intrinsic settle exactly. */
readonly carryClose?: boolean;
/** This session's ordinal `k` in its Instance (the multi-session horizon design, kestrel-5zl.16.4) — the relative-day
* coordinate `d{k}`. Absent for a standalone run ⇒ today's coordinate (no `d{k}` prefix), byte-identical. */
readonly sessionOrdinal?: number;
/** The bounded OPEN authoring loop's dual budget (ADR-0029 §2). Consulted ONLY when the agent
* exposes {@link Agent.authoringOpen} (the viewshop arm); a baseline/recorded/fixed run ignores it
* entirely (single-shot open, byte-identical). Both fields are config axes — a different budget is a
* different grid column. Absent ⇒ the conservative defaults ({@link DEFAULT_VIEW_REQUEST_CAP} /
* {@link DEFAULT_AUTHORING_TOKEN_BUDGET}). */
readonly authoring?: {
/** Max non-terminal iterations (view-requests + repairs, shared) before fail-closed standDown. */
readonly viewRequestCap?: number;
/** Cumulative model-token ceiling (input + output + thinking, summed across iterations). */
readonly authoringTokenBudget?: number;
};
/** The Percept v5 EMERGENCE LOG sink (ADR-0029 §5) — OFF the graded path. When supplied, the driver
* appends one {@link EmergenceRecord} per non-terminal authoring iteration (BOTH view-requests AND
* parse-error/repair events), keyed by `(OPEN_ORDINAL, iteration)`. Private application data (the raw
* data for the emergence study AND the grammar-evolution signal, ADR-0030); never a graded input. */
readonly emergenceLog?: EmergenceRecord[];
/**
* DAY-COMPAT MODE (kestrel-5zl.3 re-run) — the CALLER-OWNS-CADENCE path the {@link import("./day.ts").runDaySession}
* fileHandshakeAgent refactor drives through. When the caller owns the wake cadence (the day's structural
* offsets), the driver reproduces the STEPPED runner's cadence + byte stream EXACTLY:
* - NO injected platform-default staleness/backstop wakes for this path — the day's own structural wakes
* provide the coverage, so the delivered wake set is exactly `computeWakes(...)` (no 30-min DAY backstop
* churn), reproducing the frozen day determinism_hash 44cf2cbf;
* - CONTROL supersede carries the day's `{target:"wake-N", note:"revision-N"}` byte shape (not the bare
* `{note?}` the agent-driven path emits), so `serializeEvent` bytes match the stepped runner.
*
* This is NARROW: it is NOT "silence the backstop". It never weakens the band fail-closed logic (16.7) for a
* normal band run — {@link wakeFloorForBand}/{@link armStaleness} still floor every agent-driven session and
* {@link tests/simulate.wake-band.test.ts} stays green. Absent / `false` ⇒ today's full agent-driven frontier,
* byte-identical. (Threaded by the green step; declared here as the contract the TDD-red test targets.)
*/
readonly dayCompat?: boolean;
/** The DAY-COMPAT {@link DayCompatBridge} (kestrel-5zl.3) — present ONLY when the caller is the
* {@link import("./day.ts").runDaySession} file agent (it renders artifacts from `vantage` + validates
* revisions through `previewSupersede`). Off the graded line: the driver sets `vantage` before each
* `open`/`decide` and binds `previewSupersede` to the live core, but emits NOTHING from it. A plain
* `dayCompat` run (a recordedAgent replay) omits it and the driver never touches it. */
readonly dayBridge?: DayCompatBridge;
/** The options-analytics OVERLAY (kestrel-4gl.13.13) — the perception arm's OPRA surface, folded
* causally into `market.options` at every frame cutoff so the `gex`/`iv-skew`/`implied-realized`
* panes render in a LIVE run. **Config-gated: supplied ONLY for the perception arm** (a View that
* selects the options-analytics panes). Absent — the minimal arm — leaves `market.options`
* undefined and every frame byte-identical to before (the panes are off-default; the fold is never
* paid). Folded per-cutoff with the T-5m guard (only events at/before the cutoff, no look-ahead) and
* relabeled date-blind before it reaches the agent frame ({@link buildFrameOptions}). */
readonly optionsOverlay?: OptionsOverlayConfig;
/**
* THE MULTIDAY TAPE SEAM (kestrel-wa0j.20 — the DATA half of Train 1B's `tape d-N` address). The
* PRIOR sessions' tapes (date-blind: relative ordinals + HH:MM clocks, NEVER dates), threaded onto
* every frame this session serves so a View naming `tape d-N` (N ≥ 1) renders ordinal N's OWN
* single-session block instead of the Train 1B absence line. Each ordinal renders SEPARATELY — no
* cross-session folding (that is wa0j.20b, behind PR #194's render unification).
*
* INJECTABLE seam: the v1 single-day sim carries no multi-session tape state, so this is typically
* ABSENT (honestly — `tape d-N` then renders absent-with-reason, byte-identical). A multi-day harness
* (or a future day/backtest path that has the prior sessions' rows cheaply available) INJECTS them
* here; the driver threads them, unchanged, into both the OPEN briefing and every wake frame. Absent
* ⇒ no `priorSessions` field on any frame, byte-identical to today. */
readonly priorSessions?: readonly PriorSessionTape[];
/**
* THE THETA GATE (theta-cell seam b, {@link import("../fill/held-position.ts").heldPositionAsOfGradedBus}).
* When `true`, after settle the driver asks the held-position owner for the position held as of the
* graded bus — it reconstructs the net HELD option legs + their blended basis, re-marks them against the
* tape's own option book at every DELIVERED wake (theta decay between wakes), and returns ONE graded
* `TELEMETRY theta_bleed` record carrying the stand-down floor (the mark at the LAST wake), which the
* driver emits verbatim. The Blotter folds that into `totals.floor` (ADR-0011), so a watcher that STANDS PAT on a
* bleeding straddle realizes a graded NEGATIVE floor instead of paying no running cost for doing nothing
* — the whole point of the theta cell (it dissolves the doing-nothing-wins degenerate reward).
*
* Threaded from the FOMC-OPTIONS {@link import("./harness/plan-fixture.ts").FanFrame} `markToModel`.
* Absent / `false` (every other cell) ⇒ no reconstruction, no record, no fold — every existing pinned
* floor is byte-identical. Only binds when a position is actually HELD across ≥1 wake (a flat book, or a
* watcher that closed out, emits nothing). CLEAN BOUNDARY: the bleed rides the graded Bus / Blotter as a
* mark-to-model GRADING penalty; it is deliberately NOT folded into the engine-native SessionReport
* `realized_floor_usd` or the multi-session carry cash (that report/ledger integration is separate work).
*/
readonly markToModel?: boolean;
/**
* The injectable wall clock the driver measures a clock-honest Seat turn with (ADR-0040 /
* clock-honest wakes §7 — the ONE minting seam, the `opts.now ?? Date.now` idiom of `liveAgent`).
* Consulted ONLY in a LIVE-shaped clock-honest run: a latency-blind session never measures (its
* captures stay costless-deterministic), and a REPLAY (an agent exposing `recordedCostMs`) reads
* recorded costs and never touches this — a replay path that reads a clock is a defect by
* definition (the poisoned-clock fixture). Defaults to `Date.now`.
*/
readonly now?: () => number;
/**
* The session's DECLARED data rung (ADR-0040 data floor / clock-honest wakes §4) — the tape's
* observability provenance (`"tick" | "second" | "minute" | "session"`, the `GradingFidelity`
* lattice), declared on the run options / session catalog and carried with the tape like
* `fill_model`. Typed loosely (injected provenance bytes) and VERIFIED fail-closed via the isRung
* discipline: `tick`/`second` ⇒ clock-honest eligible; `minute`/`session` ⇒ latency-blind; an
* off-lattice or ABSENT rung ⇒ latency-blind (an untrusted rung never compares as eligible).
* Requesting `clockHonest: true` over an ineligible/undeclared rung REFUSES the run loudly at open —
* never a silent downgrade to latency-blind. Irrelevant to a latency-blind run (may be omitted).
*/
readonly dataRung?: string;
}
/** The result of a Simulate session: the graded {@link Blotter} (a PURE projection of the graded Bus,
* ADR-0011), the {@link CapturedTurns} the run consumed (the deterministic replay input for
* {@link recordedAgent}), and the agent's {@link AgentConfig} (the comparison axis). */
export interface SimulateResult {
readonly blotter: Blotter;
/**
* The native graded {@link SessionReport} of this run (kestrel-m9i.7.4) — the SAME `core.buildReport`
* projection {@link import("./day.ts").runDaySession} returns, computed here from the finalized core so a
* live/handshake Simulate run lands in the run {@link import("../ledger").ledger} WITHOUT a Blotter→report
* bridge (the tournament runner records this verbatim; `session.settle_ts` is the injected `recorded_at`).
* A PURE read of the finalized session — no wall clock, no RNG, and byte-identical to a `runDaySession`
* report of the same graded bus (RUNTIME §0).
*/
readonly report: SessionReport;
readonly captured: CapturedTurns;
readonly config: AgentConfig;
/** The canonical GRADED bus of this run (`core.gradedBus()` — the judge-stamped META + every emitted
* engine reaction, re-stamped gap-free): the record itself, surfaced so a caller (and the w7la.1
* clocked fixtures) can assert bus-level facts — deliberation records, checkpoints, refusal
* stamping — without any engine-state scrape (ADR-0010: the Bus is the truth). A PURE read of the
* finalized core; `project(gradedBus)` is byte-identical to {@link SimulateResult.blotter}. */
readonly gradedBus: readonly BusEvent[];
/** The {@link SessionCarry} this session hands to the next (the multi-session horizon design, kestrel-5zl.16) — a PURE read of
* the finalised session. On a final / standalone session (`carryClose` absent) its `positions` are
* empty (inventory settled at intrinsic). The runner ({@link import("./instance.ts").runInstance})
* threads it into the next session's `openingCarry`. */
readonly carry: SessionCarry;
}
/**
* Why a declared data rung CANNOT ground a clock-honest session, or `null` when it is eligible
* (clock-honest wakes §4). PURE and fail-closed — declared-then-verified is not trust:
* - `"tick"` / `"second"` → eligible (`null`);
* - `"minute"` / `"session"` → too coarse (the ADR-0040 data floor) — such a session stays VALID but
* latency-blind, and may never claim clock-honesty;
* - absent → undeclared provenance — refuse (never a silent default);
* - off-lattice → an untrusted rung — refuse (never compared as coarser/finer than anything).
* The caller (the driver, at open) REFUSES a `clockHonest: true` run whose rung returns non-null —
* never a silent downgrade to latency-blind (a producer must never *believe* it bought a
* latency-honest result it didn't get).
*/
export declare function clockHonestIneligibility(declaredRung: string | undefined): string | null;
/**
* SCHEDULE-TIME View value/budget validation (kestrel-wa0j.19 §1b): the checks that are KNOWABLE when a
* `scheduleWake` is accepted — BEFORE the View ever reaches an (otherwise unguarded) delivery render.
* Returns a refusal reason when the resolved View carries a defect the constant session context can prove
* NOW, else `null`. Two checks, both mirroring the exact guards `materializePanes` applies at delivery so
* the two can never drift:
* • **window-arg value** — the served tape bucket is a session constant ({@link SERVED_TAPE_BUCKET_MIN}),
* so a `tape <window>` that is sub-resolution or a non-multiple of it is refusable now via the SHARED
* {@link windowServableBy} predicate (the same one the arged tape builder enforces at materialization).
* • **budget sanity** — if the View declares a token budget already below the SUM of its selected panes'
* catalog `tokenCostEstimate`s, it can never fit; refuse now. (The exact per-tokenizer measurement at
* materialization stays the precise guard — the delivery seam §1a is the fail-closed backstop for a
* View that fits the estimate yet overruns the real count.)
* PURE. Distinct from the STRUCTURAL/date-leak refusals (unknown pane / reserved id / calendar leak), which
* stay whole-wake refusals: a structurally-broken or unsafe View is nonsense to honor, whereas a sound View
* that this session's resolution simply cannot serve drops to the default panes while the wake still fires.
*/
export declare function scheduleTimeViewDefect(sel: ViewSelection): string | null;
/** The plan-lifecycle HALF of the {@link Kernel} superset (positions / resting / fills / budget /
* plan states), scraped from the date-blind snapshot. The WAKE frame layers the enriched 4gl.3
* cockpit lead block on top of this base ({@link enrichedKernelOf}); the OPEN briefing carries the
* base alone (the enriched cockpit at OPEN is out of scope for this slice — m9i.11 briefing). */
/** The cell-sourced STANDING context (ADR-0026) layered onto every frame's kernel: the hard
* {@link Mandate} (the only admission input) + the soft, directional {@link Brief}. Sourced from
* the SESSION/CELL ({@link RunSimulateOptions}), NOT hardcoded — different cells declare different
* objectives. Frame content sits ABOVE the determinism line, so this never perturbs the graded bus. */
export interface KernelStanding {
readonly mandate?: Mandate;
readonly brief?: Brief;
}
export declare function kernelOf(af: AuthorFrame, instrument: string, standing?: KernelStanding, multiplier?: number): Kernel;
/** The `[prevWakeSeq, thisWakeSeq)` bus-seq window the engine-actions-since-last-wake ride. Both are
* WAKE-checkpoint `seq`s (an ordinal, never a wall-clock/date); the half-open window is the gap
* between the previous vantage and this one. */
export interface SeqWindow {
readonly prevWakeSeq: number;
readonly thisWakeSeq: number;
}
/** The pure inputs {@link projectWakeFrame} consumes beyond the graded bus + the seq window: the
* date-blind vantage projection (market pane + plan-lifecycle base), the exec instrument, the
* per-vehicle books for the cockpit data-health, and the wake ctx (ordinal / reason / deadlines /
* attention). Everything here is a pure derivation of the injected bus (no wall clock, no RNG). */
export interface WakeFrameConfig {
readonly af: AuthorFrame;
readonly instrument: string;
/** The exec instrument's contract multiplier (kestrel-m9i.32) — `1` for equity/spot, `100` for a
* listed option. Drives the cost-basis sizing headroom (equity basis = spot × mult; option basis =
* premium × mult, ADR-0017). Absent ⇒ treated as `1` (equity/spot). */
readonly execMultiplier?: number;
readonly vehicles: readonly VehicleBook[];
readonly ctx: WakeCtx;
/** The cell-sourced standing context (ADR-0026 mandate + brief) layered onto the wake kernel. */
readonly standing?: KernelStanding;
/** The options-analytics projection for THIS wake's cutoff (kestrel-4gl.13.13) — already folded
* causally + date-blind by the driver ({@link buildFrameOptions}). Present only for the perception
* arm; absent leaves `market.options` undefined (the minimal arm, byte-identical). */
readonly options?: OptionsAnalytics;
/** The injected time-to-expiry resolver (`fairTauYears`) the chain's `fair` column is priced through
* (kestrel-121) — the SAME source the fill engine prices `@fair` with, evaluated at THIS wake's cutoff
* (`ctx.wakeTs`). Absent ⇒ the chain `fair` stays `—` (byte-identical to a pre-fair frame). */
readonly fairTauYears?: FairTauProvider;
/** kestrel-wcnd: the exec chain's OWN expiry token at this wake (from the RAW snapshot — the
* date-blind `af` cannot carry it). Feeds `fairTauYears`'s 2nd argument ONLY; never rendered. */
readonly fairExpiry?: string;
/** The prior author vantage's SERVED values (kestrel-wa0j.48) — the typed snapshot the driver served
* at the PREVIOUS vantage, so the `delta` pane can state what MOVED under stateless-redraw. Present
* only on a wake AFTER the first (the driver captures it from the prior frame's served levels/book);
* absent ⇒ the frame carries no `priorVantage` (byte-identical, and the delta pane fails closed). */
readonly priorVantage?: PriorVantage;
/** The PRIOR sessions' tapes (kestrel-wa0j.20) — the injected multiday tape (`opts.priorSessions`),
* threaded so `tape d-N` serves ordinal N's rows as its own block. Absent in the v1 single-day sim ⇒
* the frame carries no `priorSessions` (byte-identical, and `tape d-N` renders the Train 1B absence). */
readonly priorSessions?: readonly PriorSessionTape[];
/** Every armed plan STATEMENT the driver holds, in arm order (kestrel-wa0j.29) — the typed ASTs the
* `armed-plan` pane's terms are captured from. The seam filters these to the plans in an ENFORCED
* lifecycle state (per this wake's kernel plan set) and prints each clause through the canonical
* printer. Absent (or no enforced plan) ⇒ the frame carries no `armedPlan` and the pane fails closed
* to absent-with-reason, byte-identical to a frame without the field. */
readonly armedPlanAsts?: readonly PlanStatement[];
/** The tape's `session_date` (kestrel-wa0j.74) — the reference an ABSOLUTE per-leg `exp 2026-08-21`
* is date-blinded to a relative `<n>dte` against when the `armed-plan` pane captures the plan's terms.
* Required so an authored iso-date tenor cannot leak into the acting Frame and trip {@link
* assertFrameDateBlind}; unused when no plan carries an absolute per-leg expiry (byte-identical). */
readonly sessionDate: string;
}
/**
* **The pure WAKE-frame builder** (kestrel-5zl.11): `(graded bus, seq window, config) → ActingFrame`.
* Assembles the date-blind {@link ActingFrame} handed to the agent at one wake, whose `kernel` is the
* REAL enriched 4gl.3 cockpit lead block — positions / resting / budget / data-health / owner-acts /
* the engine-actions-since-last-wake / predictor-regime claims — that {@link renderKernel} consumes,
* NOT the partial stub. The engine log is the `[prevWakeSeq, thisWakeSeq)` bus-window slice
* ({@link engineActionsInWindow}), so it is the since-LAST-wake delta, frozen-at-wake (only
* `seq < thisWakeSeq`) with no look-ahead.
*
* PURE: no wall clock, no unseeded RNG — the output is a byte-identical function of its inputs, so the
* same bus + same seq window + same config projects an identical frame (the determinism the tracer's
* replay rides on). Frame content sits ABOVE the determinism line (recorded/fixed adapters ignore it),
* so it never perturbs the graded bus. DATE-BLIND: only relative time, the `HHMM` ET clock, and
* ordinals reach the frame; {@link assertFrameDateBlind} is the fail-closed backstop at the seam.
*/
export declare function projectWakeFrame(emitted: readonly BusEvent[], window: SeqWindow, config: WakeFrameConfig): ActingFrame;
/**
* Drive one frozen-at-wake Simulate session through the {@link Agent} seam and return its graded
* {@link Blotter} + the {@link CapturedTurns} it consumed. Reuses the SAME {@link SessionCore} the stepped
* day drives (bus-stepping, Gate, `projectAuthorFrame`); the ONE behavioral change is that the wake set is
* answered by `agent.decide` rather than a file handshake. `async` because the live loop is deliberately
* non-deterministic; the recorded/fixed adapters resolve synchronously.
*/
export declare function runSimulateSession(opts: RunSimulateOptions): Promise<SimulateResult>;
//# sourceMappingURL=simulate.d.ts.map