The cycle's design principle enters the ledger: every closed-vocabulary entry the binary exposes carries a one-line meaning behind one shared deterministic shape gate (doc_gate) at three seams -- compile/unit for engine-shipped entries, load for native node crates, register for the content-addressed store (documents: an additive-optional gated description). Forbids the engine evaluating description text (C17 / invariant 10), any influence on execution/identity/determinism (C1), retroactive invalidation of registered artifacts, and machine-invented meaning lines. Why: the audience is headless LLM agents (#319); field evidence #314 showed schema knowledge being recovered by CAS forensics from the release binary -- the removed failure class. All spec acceptance criteria are now met across the four iterations of this cycle (core carrier + std texts; domain threading; load seam; register seam + op-script doc slot + document description). closes #316
12 KiB
aura — project rules
aura is a "game engine for traders": a Rust framework and a playground to author trading nodes, backtest them deterministically and massively in parallel, compose them fractally, validate them (sweep / Monte-Carlo / walk-forward), and freeze a validated strategy into a standalone bot with a broker connection.
This file is the project sittenkodex. It imports the universal discipline from
~/dev/skills/templates/CLAUDE.md.fragment and adds aura's domain invariants.
The full architecture lives in the design ledger (docs/design/), not here.
Roles
I am the orchestrator, not the implementer. The skills-plugin agents are my workers: I plan, design, decide, and integrate; they implement, refactor, test, and diagnose. Trivial mechanical edits I may do directly; anything needing broad reading or judgement goes to an agent. Agent reports describe intent, not outcome — I verify the diff and the test output myself before committing.
Commit discipline and main-branch sanctity
- Only the orchestrator commits. No skill agent runs
git commit; agents leave their output as unstaged working-tree changes for me to inspect and shape into commits. - main HEAD is sacrosanct — with one narrow
/bossexception. As a rule, nogit reset/git reverton main: it moves forward only via my commits, and pushed or user-ratified history is never rewound (a bad landing there is fixed forward withgit revert, neverreset). Wrong agent output is discarded withgit checkout -- <paths>/git stash. The exception: under/boss, the orchestrator MAYgit reset --hardto wind back its own autonomous, unpushed commits made this run — those above the session anchor (main HEAD at the run's start) — when it has run a line of work into a genuine dead end. Never below the anchor; never a pushed commit; the discarded attempt is hard-dropped (its trace survives in the run's reference issue). This is the/bossrollback sandbox, not a licence to rewrite history. - When a commit closes a Gitea issue, reference it in the body:
closes #N(orrefs #Nfor non-final work).
Design rationale ≠ implementation effort
Design choices are justified by substance — semantics, structural fit, what the design permits vs forbids, compositional clarity, future-proofing. Implementation effort ("approach A touches 250 sites, B touches 1") is an observation about the current code, not a rationale. Effort is at most a named tiebreaker after substantive reasons tie.
Bug fixes — TDD, always
Bug fixes are RED-first and autonomous: the failing test exists in the working
tree before any fix. The debug skill is mandatory for any observable
misbehaviour (failing test, panic, wrong output).
Domain invariants (load-bearing — never silently violate)
These are the contracts the whole design rests on. A change that breaks one is a design decision, not a refactor, and belongs in the ledger.
- Determinism. A backtest is a deterministic, synchronous, non-concurrent event loop that reaches a unique state after each input tick. Same input → same run, reproducibly. Two backtests are fully disjoint → concurrently executable without locking. Parallelism is across sims, never within one.
- Causality / no look-ahead. A node sees only the past. Look-ahead is made structurally impossible (read-only input windows that end at the cursor; resamplers emit a bar only once it is complete), not merely discouraged.
- One merge, at ingestion only. Heterogeneous timestamped sources are k-way-merged into a single chronological cycle stream at the ingestion boundary. There is no merge / as-of join inside the graph.
- The four scalar base types, streamed as SoA. Only
i64,f64,bool,timestampare streamed, as columnar Structure-of-Arrays. Composite streams (e.g. OHLCV) are bundles of base columns. Non-scalars (String, Records, tables, calendars) exist as metadata beside the hot path, never in it. - Acyclic dataflow. The graph is a DAG; the only feedback path is an explicit delay/state node (the RTL "register"). The "cycle" of the research workflow is not a dataflow cycle.
- Record-then-replay determinism boundary. Anything non-deterministic,
external, or slow (LLM news agents, web sources) is materialized into a
recorded, timestamped stream before it enters the engine. The sim never
makes a live external call mid-replay. (See
~/.claude/CLAUDE.mdfor the IONOS consent rule: external LLM calls happen at the recording/live-source edge, with explicit per-session consent, never inside a backtest.) - Strategy output is a directional bias stream; risk-based execution is a
decoupled downstream layer; signal quality is measured in R. The DAG
expresses one state at t (C8: ≤1 record per
eval), so a strategy's primary, backtestable output is a signed, bounded biasf64 ∈ [-1,+1]per cycle — direction (sign) + conviction (magnitude, optional), unsized (not an equity curve, not a position, not a size). Sizing leaves the strategy: a decoupled risk-based execution layerbias → stop-rule → position-management(the RiskExecutor composite, per symbol; the Veto an optional documented pre-trade-gate seam) turns bias + a protective stop into a managed position, in R. The stop defines the risk unit R (1R = the loss if stopped). Signal quality is measured in R (R-multiples / expectancy), the account- and instrument-agnostic yardstick — the research loop is pure feed-forward: flat-1R, gross R → net R via the composable cost-model graph (C10), no Sizer, no equity feedback, noz⁻¹register. Money is a live/deploy-edge concern: currency P&L, fixed-fractional sizing, and compounding are post-hoc money-management transforms of the net-R sequence at the deploy/account layer, and the live broker is an I/O adapter at the recording/deploy edge (C11/C13), never part of the strategy. The broker-independent position-event table (event_ts, action[buy/sell/close], position_id, instrument_id, volume) survives as the decoupled, derived deploy/reconciliation audit artifact — the first difference of the book (deal = target − book − in_flight), a computed table (not a per-evaloutput, since one decision instant may yield >1 event). - Deploy artifacts are frozen. Hot-reload (cdylib) is an authoring-loop tool only. The live bot is a statically-linked, versioned, frozen artifact — never hot-swapped (audit trail: this bot = this commit).
- Engine / project separation. This repo is the reusable engine. Research
projects are separate external repos that depend on it. Project-specific
native nodes live in the project's attached node crate;
cross-project-reusable nodes in shared crates; universal blocks in
aura-std(shipped here). Reuse is cargo-native. No user/project signals in this repo (onlyexamples/fixtures for the engine's own tests); no multi-project manager or node registry inside aura. A project is a directory anchored by a staticAura.toml— data-only by default (blueprints + research documents over the std vocabulary, no build step), hosted byauraduring research and frozen to a standalone binary for deploy. Native node logic lives in node crates: separate cdylib crates referenced viaAura.toml [nodes], scaffolded/attached by a dedicated verb (the visible role-2 switch); the hot-reload unit is the referenced node-crate cdylib. (#241 amendment, 2026-07-12 — re-opened deliberately by the role model's diagnosis.) - Authoring surface — all logic is Rust. Node, strategy, and harness
logic is authored in native Rust via Claude Code + the skills pipeline,
using builder APIs. Declarative config (
Aura.toml) carries only static project context, never logic — no experiment/strategy DSL (the RustAst trap). Clarification (2026-07-03, #188/C25): a closed-vocabulary data artifact — an op-script, a blueprint, a process or campaign document — is NOT the forbidden DSL: what failed historically (RustAst) was an open, logic-bearing language; closed, typed vocabularies as serialized data (Blockly-litmus-clean, at most the total P1 construct tier) are the proven pattern, and experiment intent lives in them (C20/C25). Genuinely new logic escalates to a new Rust block (role 2), never to a freetext hole in an artifact. aura ships no embedded coding-LLM; IONOS LLMs are used only as a runtime data source (news bias), with per-session consent, never in the code path. - Construction is a bootstrap phase. Blueprints (param-generic graph-as-
data from a Rust builder) are bootstrapped into frozen instances (buffers
sized, topology fixed) by binding params + data + seed. Params configure and
size nodes but never change topology (a topology change is a different
blueprint). The harness — sources + strategy + broker node(s) + sinks — is
the root sim graph, itself bootstrapped, and is C1's disjoint unit; its
structural axes form the experiment matrix, its tuning params the sweep.
The bootstrap is a compilation to a flat, type-erased
FlatGraph, wired by raw index (composites inline — a composite is an authoring-level node, not a runtime object; names survive only as non-load-bearing debug symbols, as today). The flat graph is the target of behaviour-preserving optimisation, C1 the correctness invariant — intra-graph (CSE/DCE) and across a sweep family (sweep-invariant sub-graph computed once, shared via C11/C12). See C9/C19/C23. - The World is the product; the playground is a trace explorer. Three ontological tiers: a node is an open, composable fragment (at most one output, C8); a harness is the closed root graph that runs (sources + strategy + brokers + sinks + clock — C1's disjoint unit / root scope), not a node; the World is the program that dynamically constructs and orchestrates families of harnesses (walk-forward / sweep / MC / comparison) — aura's differentiator, not the single backtest. The World is a program: nothing is displayable until it runs, and what is displayable is exactly what a sink (C8) records into the registry (C18). The playground plays any harness and is an execution viewer / trace explorer (structure before, live streams during, recorded traces after) — never a scene editor; topology is grown in Rust + hot-reload, runtime params are UI-tunable.
- Self-description: every surface explains itself. Every closed-
vocabulary entry the binary exposes (nodes, metrics, tap slots, folds,
blocks) carries a one-line meaning, enforced at its entry seam —
compile/unit for engine-shipped entries, load for native node crates,
register for the content-addressed store (documents: an optional gated
description). The gate is deterministic string shape (doc_gate), never content judgement: the engine never evaluates description text (no freetext logic hole, invariant 10), descriptions never influence execution, determinism (C1), or identity ids, and registered artifacts are never retroactively invalidated. (C29)
HTML surfaces
Every HTML surface — runtime-rendered (chart/graph viewer) or ad-hoc generated
(demo/report pages) — embeds crates/aura-cli/assets/aura.css as its style
source; the palette tokens and shared components live only there. New components
extend that file; never fork the palette. Pages stay self-contained: all assets
inlined, no external requests. Design record: issue #209.
Skills plugin: project facts
The few facts the skills plugin needs that genuinely vary per project.
Everything else is a fixed convention (see ~/dev/skills/docs/conventions.md).
- Code roots —
crates - Build —
cargo build --workspace - Test —
cargo test --workspace - Lint —
cargo clippy --workspace --all-targets -- -D warnings - Doc build —
cargo doc --workspace --no-deps 2>&1 - Bench —
cargo run --release -p aura-bench -- run(cycle close; report-only — seecrates/aura-bench/README.md) - Design ledger —
docs/design/INDEX.md - Glossary —
docs/glossary.md - Issue tracker — Gitea, repo
Brummel/Aura:- browsable URL:
http://192.168.178.103:3000/Brummel/Aura/issues - list open issues:
tea issues ls --repo Brummel/Aura --state open
- browsable URL: