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.
51 lines (40 loc) • 2.5 kB
Markdown
# OSS-ADR-0053 — The paper progression unifies onto SessionCore
Status: accepted (2026-07-18, owner grill — 2026-07-17 depth review, G2).
Supersedes the isolation charter in `src/session/paper.ts`'s module docstring.
## Context
`runPaperSession` (`src/session/paper.ts`, ~1000 lines) is a third session
progression beside `runSimulateSession`/`runSimSession`. Its charter is
deliberate isolation — "nothing here imports, wraps, or re-enters
`SessionCore`/`SimGate`/`SimFillEngine`" — so it re-implements the
arm/wake/settle loop and re-emits the `TICK BOOK`/`HEARTBEAT` events
`SessionCore.step` already consumes. The consequence: none of the guard
fixtures that prove the sim path (the `simulate.*` corpus, driven through the
real driver per the repo's no-guard-without-a-red-fixture rule) cover the
paper path. Every guard on the road to real money must be independently
re-proven against a fake venue, forever — the opposite of the posture the
never-live doctrine wants.
## Decision
**One progression.** sim, paper, and live differ only by adapters at the
existing seams: the `Gate` seam (which already has two real adapters —
`SimGate` and the L0-clamped IBKR paper gate from `makeGate("paper")`) and the
feed source. `runPaperSession` becomes a driver configuration over
`SessionCore`; its hand-rolled loop is retired. Venue-specific concerns
(heartbeats, reconciliation, socket lifecycle) stay in the IBKR adapters —
they are adapter substance, not progression logic.
Sequenced **after** the driver extraction (kestrel-z473.1) shrinks
`simulate.ts` and clarifies what `SessionCore` owns; the unification is done
with that picture in hand, not before.
## Considered and rejected
- **Ratify the fork with an ADR** ("the live path must not share fate with sim
code"): honest, but it permanently doubles the guard-proof burden on
exactly the path where proof matters most, and the shared-fate risk it
guards against is better carried by the Gate seam's fail-closed clamps than
by a duplicate loop.
- **Status quo** — an unstated fork: the worst of both (the isolation is
neither enforced as a decision nor paid down as duplication).
## Consequences
- Guard fixtures through the real driver cover sim *and* paper; a wired guard
is wired everywhere the progression runs.
- The `simulate.*` fixture corpus becomes the paper path's regression net;
paper-only tests shrink to venue-adapter behaviour.
- `paper.ts`'s charter docstring is rewritten to point here.