UNPKG

kestrel.markets

Version:

A typed, token-efficient language + runtime for agentic trading: agents author bounded plans, the runtime fires them at the tick. CLI + typed library + MCP server.

380 lines 30.2 kB
/** * # 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