The single-file ledger had grown to 2968 lines / ~42k tokens, mixing current design law with accreted history: 59 cycle-stamped realization blocks, 18 [HISTORY] passages, 22 supersession markers, and the C10 / C22 / C24 reframe sagas layered several supersessions deep. A code-grounding audit (31 agents, adversarially verified) confirmed 11 defects stated as current truth: stale crate homes from the C28 #288 roster split (cost nodes, PositionManagement, PositionEvent, Session), the renamed InputSpec->PortSpec, the pre-#241 project model in C16 and the open-threads section, a stale HarnessKind retirement deferral in C24, and three C28-internal inconsistencies. New shape, per the ailang precedent: - INDEX.md stays the sole addressable entry point: foundation, external components, a C-id-keyed contract map (one line per contract), and only the genuinely open architectural threads. - contracts/cNN-<slug>.md carries each contract's current truth only: Guarantee / Forbids / Why with ratified refinements integrated, plus a code-anchored Current state. All confirmed defects are fixed here; crate anchors were re-verified against the tree. - contracts/cNN-<slug>.history.md (18 sidecars) and INDEX.history.md preserve every superseded block verbatim, stamps and issue refs intact, under a frozen-record banner. Nothing was deleted: superseded design intent remains an addressable working-tree artifact, off the per-cycle audit walk. - Ledger discipline is now stated in INDEX.md: live files are edited in place at cycle close, superseded text moves verbatim to the sidecar, and a supersession marker in a live file is itself an audit finding. Every contract file was verified against its old text by an independent zero-loss pass (statement-by-statement) plus a code-accuracy spot check; C-ids and contract titles are unchanged, so existing C-id citations in code, tests, and issues resolve as before.
14 KiB
aura design ledger — INDEX
The ledger records the load-bearing design contracts and their rationale. Each contract states what it guarantees, what it forbids, and why. A change that breaks a contract is a design decision (amend the contract with its new rationale), never a silent refactor.
This file is the sole addressable entry point. Each contract lives in its own
file under contracts/ as cNN-<slug>.md; durable artifacts
cite contracts by C-id (C10), which resolves here. Contracts C1–C18 were
settled in the initial design interview (2026-06-03); later contracts carry
their ratification refs inline. The CLAUDE.md Domain invariants section
is the compressed, always-loaded summary of the subset agents must never
violate; the contract files are the fuller form with rationale.
Ledger discipline (adopted with the 2026-07-21 refactor):
- A live contract file carries current truth only — present-tense design
law plus a code-anchored Current state. A supersession marker
(
[HISTORY], "superseded", "pre-reframe") appearing in a live file is itself an audit finding: it signals a move to the history sidecar was skipped. - At cycle close, realization notes are edited in place in the
contract's Current state; text they supersede moves verbatim (stamps
and issue refs intact) to the contract's
cNN-<slug>.history.mdsidecar, appended newest-last. The sidecars — not specs, plans, or git archaeology — are the durable record of superseded design intent. - The audit walk is this file plus every
contracts/cNN-*.md. History sidecars are read on demand (why-questions, retired-design lookups), never as part of the per-cycle drift walk, and are never a grounding surface.
Foundation — what aura is
aura is a framework and a playground for traders. A human and (primarily) LLMs author trading nodes directly in Rust; the engine backtests them deterministically and massively in parallel, composes them fractally, validates them (sweep / Monte-Carlo / walk-forward), and freezes a validated strategy into a standalone bot with a broker connection.
The predecessor RustAst (myc) tried this as a custom DSL and failed: too slow,
too buggy, and LLMs author far better in Rust than in an unfamiliar DSL. aura
inverts it — engine in Rust, strategies in Rust — but keeps RustAst's concepts
(synchronous reactive streams, bounded-lookback series, run-counting, SoA).
What sets aura apart is not the single backtest — every quant system does that — but the World: the meta-level where harnesses are dynamically constructed and families of them orchestrated and explored (walk-forward, sweeps, Monte-Carlo, comparison). The deterministic single-harness engine is the substrate; the World is the product (C20–C22, C24).
External components
Two sibling projects live outside this repo. Their location is recorded here so the repo, not session memory, is the source of truth.
data-server—~/dev/libs/data-server, GiteaBrummel/data-server(http://192.168.178.103:3000/Brummel/data-server.git). aura's first data source: a standalone leaf crate that loads Pepperstone M1/tick binary archives and shares them lock-free asArc<[T]>chunks; records are AoS with Unix-ms timestamps, transposed to aura's SoA columns and normalized to canonical epoch-ns at the ingestion boundary (C3/C7). It enters the workspace as a cargo git dependency at exactly the seams C28 pins: the ingestion edge (aura-ingest), the assembly position (aura-runner), and the shell.- RustAst (
myc) —~/dev/RustAst, GiteaBrummel/RustAst. The predecessor DSL attempt: a conceptual reference, never a dependency — its DSL authoring surface andValue/HM-inference machinery are exactly what aura rejects (C17). Itssrc/ast/rtl/layer served as the reference implementation foraura-core's streaming substrate; the file-by-file reading list from the pre-authoring era is preserved in INDEX.history.md.
Contracts
- C1 — Determinism and disjoint parallelism — A backtest is a deterministic, synchronous, non-concurrent event loop — same (inputs, seed) yields per-run bit-identical output; parallelism runs across disjoint sims (and campaign cells), never within one.
- C2 — Causality / no look-ahead — A node sees only the past: input windows are read-only and end at the cursor, and a resampler emits a bar only once complete — the future is physically absent, not merely discouraged.
- C3 — One merge, at ingestion only — Heterogeneous timestamped sources are k-way-merged by timestamp into one chronological cycle stream at the ingestion boundary (normalized to canonical epoch-ns there); no merge or as-of join inside the graph.
- C4 — Cycle granularity —
The clock is data-driven — one input record equals one cycle in global
timestamp order with a monotonic
cycle_id, ties breaking by source declaration order. - C5 — Freshness-gated recompute and sample-and-hold —
cycle_idadvances everywhere, but a node re-evaluates only when at least one of its inputs is fresh this cycle; otherwise it holds its last output. - C6 — Firing policy A and B, per input group — A node declares per input group one of two firing policies — A (fire-on-any-fresh + hold, as-of join) or B (all-fresh barrier synchronized on the cycle timestamp) — and may mix them freely.
- C7 — Four scalar base types, streamed as SoA —
Only
i64/f64/bool/timestampstream, as columnar SoA type-erased at the edge (kind checked once at wiring): the hot-path carrier is the tag-free 64-bitCell; the self-describingScalarserves the dynamic boundaries. - C8 — The node contract —
A node's static signature (typed input ports, a one-port output record of
base-scalar columns, typed param knobs) is declared once pre-build on the
value-empty recipe; the engine provides zero-copy input windows,
evalreturns a borrowed row orNone, andlookbacks/finalize/labelcomplete the lifecycle. - C9 — Fractal, acyclic composition —
A composite is an authoring-level Node (typed inputs + one output port
carrying a 1..K-field record) that inlines away at compile into the flat,
acyclic
FlatGraph; feedback only via an explicit delay node; topology round-trips both ways as World-owned data. - C10 — Bias stream; signal quality in R; cost model; money at the deploy edge —
A strategy emits an unsized signed bias
f64 ∈ [-1,+1]; a decoupled downstream executor (stop-rule → position-management, the stop defining the risk unit R) turns it into a managed trade in R; signal quality is measured in R (gross → net via a composable cost-model graph, pure feed-forward, no Sizer); money and real-broker fill live only at the live deploy edge. - C11 — Generalized sources; record-then-replay — Anything nondeterministic, external, or slow is materialized into a recorded, timestamped stream before it enters the engine; a backtest replays the recording and never makes a live call mid-replay.
- C12 — The atomic sim unit and the four orchestration axes —
The atomic unit is
(frozen topology + param-set + data-window + RNG-seed) → deterministic run → metrics, orchestrated by param-sweep, optimization, walk-forward, and Monte-Carlo (= sweep over seeds) over read-onlyArc-shared data. - C13 — Hot-reload is authoring-only; deploy is frozen —
Research code hot-reloads as native Rust cdylibs through the two-tier
ABI-stamped
AURA_PROJECTdescriptor; the live bot is a statically-linked, versioned, frozen artifact — never hot-swapped. - C14 — Headless core, two faces — The engine is a UI-agnostic library with a primary programmatic/CLI face (a four-way exit-code automation contract) and a visual playground face; no UI knowledge inside the engine.
- C15 — Resampling-as-node; sessions/calendars —
A resampler is a clock-sensitive node emitting a completed bar only at the
boundary; calendars and instrument specs are metadata beside the hot path;
session context arrives as scalar streams via a
Sessionnode. - C16 — Engine / project separation; node reuse —
aura is the reusable engine each research project depends on via cargo, with
three-tier cargo-native node reuse and a two-tier project model (data-only
Aura.tomlproject, or a native node crate attached via[nodes]). - C17 — Authoring surface — All computational logic is authored in native Rust via Claude Code + the skills pipeline; topology is serializable World-owned data; aura ships no embedded coding-LLM.
- C18 — Project management and the run registry — One repo = one project (git + Gitea), plus an Aura-native run registry storing per-run manifests + metrics with content-addressed topology, re-deriving full results on demand; lineage lives in family/campaign stores.
- C19 — Bootstrap: blueprint → instance —
Construction is a distinct, recursive bootstrap phase compiling a
param-generic named blueprint into a frozen, raw-index-wired
FlatGraphinstance by binding params + data + seed. - C20 — Strategy ↔ harness — A strategy is a reusable, context-free composite blueprint; the harness is the closed root sim graph (sources + strategy + brokers + sinks under a clock) — C1's disjoint unit, not a node.
- C21 — The World: the meta-level is the product — The World — the program that dynamically constructs and orchestrates families of harnesses whose topology is World-owned data (C24) — is aura's product; the single-harness engine is its substrate.
- C22 — The playground is a trace explorer — The only durable, displayable substance is the recorded trace captured by sinks (declared taps, C27) persisted into the registry; the playground is an execution viewer, never a persistent scene editor.
- C23 — Graph compilation and behaviour-preserving optimisation —
The bootstrap is a compilation into a flat, index-wired
FlatGraphthat is the target of behaviour-preserving (bit-identical, C1) optimisation — intra-graph CSE/DCE and sweep-invariant hoisting (both still deferred). - C24 — The blueprint is a serializable, World-owned data value —
A blueprint is a first-class, canonically serialized, versioned data value
with an engine load path (data → blueprint →
FlatGraph), referencing nodes by compiled-in type identity and carrying topology but no node logic. - C25 — The role model: nine authoring roles — aura's user-facing design is organized by nine authoring roles cut by owned artifact + surface + iteration cost, all fillable by one actor; text-first / headless-first is an invariant, and every control surface is a projection over the canonical text-artifact vocabulary.
- C26 — Harness input binding: role names bind archive columns — A strategy declares its data needs as root input-role names from a closed column vocabulary, overridable per campaign without touching content identity, resolved into one canonically-ordered open-and-declare plan.
- C27 — Declared taps —
A blueprint may declare named, pure output-side taps (the twin of
input_roles) that compile intoFlatGraph.tapsand bind run-mode-aware to caller-built sinks; an unbound tap is inert, not a fault. - C28 — Internal stratification: ladder, process column, shell —
The workspace crates realize a domain-specificity ladder (engine → market →
measurement/strategy → backtest → execution) beside a process column, an
assembly position, and an import-only shell — the import direction enforced
structurally by the full-workspace
c28_layeringguard.
Open architectural threads
Genuinely open only; resolved threads live in the contracts that absorbed them (pre-refactor wording in INDEX.history.md).
- Playground & World UI surface — the visual face is a web frontend served from disk-persisted traces (C22); shipped: per-tap chart pages, the families-comparison view, decimation, run-context header. Open: richer comparison meta-views (sweep-surface heatmaps, cross-family comparison, multi-column tap selection #47), a local server, run/replay clock controls.
- Parameter-space search strategies (Bayesian/genetic) — pluggable policies atop the atomic sim unit (C12), not yet designed. Search over structure (graph mutation/crossover) additionally rides on topology-as-data (C24).
- Composable orchestration (#109 remainder) — the axes (sweep / MC / walk-forward) as composable tools a World program wires, beyond today's document-driven executor verbs; the campaign/process document layer (C18, C25) is the shipped substrate.
strategies/split — a later split, inside a project, of top-level strategies from reusable building blocks innodes/; not a day-1 cut.
History: INDEX.history.md