Anvil
Reference
The EngineEvent envelope, the event types, the journal and replay contract, and the typed domain model.
This page is the reference for Anvil's journal: the event envelope, the event
types, and the contract that makes a journal replayable. It summarizes the
formal journal specification that ships with the platform; the spec is the
normative source for exact field types and MUST/SHOULD requirements.
The EngineEvent envelope
Every journal record is an EngineEvent — a common envelope wrapping a typed
payload. The envelope carries the metadata that makes a run reproducible and
auditable; the event_type discriminates the payload.
{
"schema_version": 1,
"seq": 184213,
"ts": "2026-06-30T14:02:11.480Z",
"event_type": "Fill",
"correlation": "c-9f2a…",
"causation": "e-184211",
"prev_hash": "b3:1d88f0…",
"state_hash": "b3:7c41a9…",
"payload": { "…": "type-specific fields" }
}| Field | Meaning |
|---|---|
schema_version | Envelope/payload schema version for forward compatibility |
seq | Monotonic per-run sequence number; defines replay order |
ts | Event timestamp from the deterministic clock |
event_type | Payload discriminator (see the table below) |
correlation | Groups events belonging to one logical flow |
causation | The seq/id of the event that caused this one |
prev_hash | blake3 of the previous record — the hash chain |
state_hash | blake3 of state after applying this event |
State is the fold of the reducer over the envelope sequence, in seq order:
state = events.fold(genesis, reduce).
Event types
The payload is one of a fixed set of typed events spanning the runtime's full lifecycle:
| Event | Records |
|---|---|
RunMeta | Run identity, mode, and configuration fingerprint |
ModeChange | A transition between operating modes |
ConfigChange | A validated configuration change |
MarketEvent | Normalized market data input |
StrategyIntent | An order intent proposed by the strategy |
RiskDecision | The gateway's accept/reject of an intent, with reason |
ExecutionCommand | A command dispatched to an exchange adapter |
Ack | Venue acknowledgement of a command |
Reject | Venue or gateway rejection |
Fill | A (partial or full) execution |
OrderState | An order lifecycle transition |
Reconcile | Result of reconciling journal state against the venue |
RiskState | A risk stop-state transition |
Checkpoint | A state snapshot marker bounding replay |
Heartbeat | Liveness / time progress |
Encoding
The journal is encoded as newline-delimited JSON (NdJson) for inspection and
tooling, or CBOR for density. Both encodings carry the same envelope and are
interchangeable for replay.
The typed domain model
Anvil's domain types make illegal states unrepresentable:
- Money is exact.
Price,Quantity, and notional values arerust_decimal-backed newtypes — no rawf64, no silent rounding drift. - Identifiers are typed. Instrument, venue, side, and order ids are distinct types; mixing them is a compile error.
- Time is explicit. Timestamps come from the deterministic clock, never the wall clock, so replay reproduces them exactly.
Replay contract
A journal replays correctly when:
- Events are applied in strict
seqorder from the genesis state. - The reducer is pure —
reduce(state, event)has no I/O and no ambient inputs. - Each replayed
state_hashequals the hash recorded live; the first divergence halts replay.
Because live, paper, backtest, and recovery all use this contract, a verified replay is proof the run was deterministic end to end.
Integrity and tamper-evidence
The prev_hash / state_hash chain makes the journal tamper-evident: altering,
inserting, or dropping any record breaks the chain at that point, and the break
is detectable in O(1) at the next link. Checkpoints let recovery start from a
snapshot without replaying from genesis while preserving the same guarantee.
For the runtime that produces these events, see
Runtime architecture; for how strategies
emit StrategyIntent, see the Strategy SDK.