docs: C19/C20 — bootstrap + strategy/harness; a project is a Rust program
Anchor the implementation-design branch: C19 (construction is a bootstrap phase — param-generic blueprint -> frozen instance; recursive up to the harness; params size/configure but never change topology). C20 (strategy = reusable context-free composite blueprint with role inputs + position-event output; harness = the root sim graph and C1's disjoint unit, with structural axes = experiment matrix vs tuning params = sweep; both strategy AND experiment authored in Rust via builder APIs, not a config DSL). Extend C8 (schema declares tunable params+ranges), C16 (a project is a Rust crate: cdylib of node/strategy/experiment blueprints + static Aura.toml; hosted by aura during research, frozen to a binary for deploy), C17 (all logic is Rust — nodes/strategies/experiments; Aura.toml = static context only), C12 (frozen topology = a harness instance; structural matrix is the outer axis). Add CLAUDE.md invariant 11; refresh project-layout.md (experiments/ dir, Rust experiments, day-in-the-life). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -92,8 +92,21 @@ design decision, not a refactor, and belongs in the ledger.
|
||||
crates; universal blocks in `aura-std` (shipped here). Reuse is cargo-native;
|
||||
the hot-reload unit is always the project-side `cdylib`. No user/project
|
||||
signals in this repo (only `examples/` fixtures for the engine's own tests);
|
||||
no multi-project manager or node registry inside aura.
|
||||
10. **Authoring surface.** Nodes are authored in native Rust via Claude Code +
|
||||
the skills pipeline. 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.
|
||||
no multi-project manager or node registry inside aura. **A project is always
|
||||
a Rust crate** (a cdylib library of node / strategy / experiment blueprints +
|
||||
a static `Aura.toml`), hosted by `aura` during research and frozen to a
|
||||
standalone binary for deploy.
|
||||
10. **Authoring surface — all logic is Rust.** Nodes, strategies, *and*
|
||||
experiments/harnesses are 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). 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.
|
||||
11. **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.
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
//! small and stable. It is the home of (to be specified):
|
||||
//!
|
||||
//! - the scalar base types streamed as SoA: `i64`, `f64`, `bool`, `timestamp`;
|
||||
//! - the `Node` trait — the contract an authored node implements (`schema` +
|
||||
//! - the `Node` trait — the contract an authored node implements (`schema` —
|
||||
//! inputs, lookback, firing group, and tunable params with ranges — plus
|
||||
//! `eval`), with engine-provided read-only input windows and node-internal
|
||||
//! series;
|
||||
//! - the evaluation context `Ctx` (zero-copy indexed access into input columns,
|
||||
|
||||
+75
-12
@@ -115,7 +115,9 @@ Type-erasure at the edge is also forced by the cdylib boundary (C13).
|
||||
|
||||
### C8 — The node contract
|
||||
**Guarantee.** A node implements `schema()` (declares each input's scalar type,
|
||||
required lookback depth, and firing group) + `eval(ctx) -> Option<Scalar>`. The
|
||||
required lookback depth, and firing group, **and the node's own tunable
|
||||
parameters — typed, with ranges**, which aggregate into the blueprint's
|
||||
param-space the optimizer sweeps, C12/C19/C20) + `eval(ctx) -> Option<Scalar>`. The
|
||||
engine provides read-only, zero-copy windows into each input's SoA ring buffer
|
||||
(`ctx.f64_in(x)[k]`, sized at wiring); a node may *additionally* keep its own
|
||||
mutable series for derived/intermediate state. `None`/Void return = filter /
|
||||
@@ -216,7 +218,10 @@ primitive — those are pluggable policies atop the atomic unit; recompiling on
|
||||
param change.
|
||||
**Why.** A stable primitive + orchestration axes keeps "wahnsinnig schnell"
|
||||
(embarrassingly parallel across the unit) cleanly separated from search policy.
|
||||
Seed-as-input reconciles Monte-Carlo with C1.
|
||||
Seed-as-input reconciles Monte-Carlo with C1. The "frozen topology" of the
|
||||
atomic unit is one harness instance, selected by the harness's **structural
|
||||
axes** (C20); the structural experiment matrix is the outer orchestration over
|
||||
this dimension, the tuning sweep the inner (C19/C20).
|
||||
|
||||
### C13 — Hot-reload is authoring-only; deploy is frozen
|
||||
**Guarantee.** A node/strategy is authored as a native Rust `cdylib`,
|
||||
@@ -261,7 +266,12 @@ blocks, ship with the engine) / **shared node crates** (cross-project-reusable,
|
||||
their own repos, pulled as cargo git deps) / **project-local `nodes/`**
|
||||
(experimental, project-specific). A reusable node is an `rlib` dependency; the
|
||||
hot-reload unit stays the project-side `cdylib` that composes it (consistent
|
||||
with C13).
|
||||
with C13). Concretely a project is a **Rust crate** — a cdylib library of node /
|
||||
strategy / experiment blueprints — plus a static `Aura.toml` (project context:
|
||||
data paths, instrument/pip metadata, default broker & window, runs dir). During
|
||||
research the `aura` host loads and runs it (C13 hot-reload); for deploy the
|
||||
chosen strategy + broker freeze into a standalone binary. **A project is
|
||||
therefore always a Rust program built on the engine.**
|
||||
**Forbids.** Project-specific signals in the aura repo (it keeps at most
|
||||
example/fixture nodes under `examples/` for its own tests); a multi-project
|
||||
manager inside aura; a bespoke node registry/marketplace (cargo + Gitea *is* the
|
||||
@@ -271,11 +281,14 @@ project versions its own research with its own forward-queue. Promotion
|
||||
(local → shared → std) is the ordinary Rust reuse gradient, no new mechanism.
|
||||
|
||||
### C17 — Authoring surface
|
||||
**Guarantee.** Nodes are authored in native Rust through **Claude Code + the
|
||||
skills pipeline**: the human describes, Claude writes the node crate, builds it,
|
||||
runs it via the `aura` CLI, and reports metrics. aura ships **no embedded
|
||||
coding-LLM**. IONOS LLMs are used only as a *runtime data source* (news-agent
|
||||
bias, C11), gated by per-session consent, never in the code path.
|
||||
**Guarantee.** All *logic* — nodes, strategies, **and experiments/harnesses** —
|
||||
is authored in native Rust through **Claude Code + the skills pipeline**: the
|
||||
human describes, Claude writes the Rust, builds it, runs it via the `aura` CLI,
|
||||
and reports metrics. Declarative config (`Aura.toml`) carries only **static
|
||||
project context** (data paths, instrument/pip metadata, defaults, runs dir),
|
||||
never logic. aura ships **no embedded coding-LLM**. IONOS LLMs are used only as a
|
||||
*runtime data source* (news-agent bias, C11), gated by per-session consent,
|
||||
never in the code path.
|
||||
**Forbids.** An in-app LLM chat that generates node code inside aura; using
|
||||
IONOS (weaker models) as the authoring brain.
|
||||
**Why.** LLMs author Rust well in Claude Code — that is the fix to RustAst's
|
||||
@@ -300,6 +313,54 @@ has no home in git/Gitea; determinism makes a structured registry cheap.
|
||||
Sequencing: the walking skeleton emits a manifest + metrics per run from day
|
||||
one; the registry/index is a later milestone over manifests that already exist.
|
||||
|
||||
### C19 — Bootstrap: blueprint → instance (recursive)
|
||||
**Guarantee.** Construction is a distinct phase, recursive at every level. Each
|
||||
node type has a **factory** `params → sized concrete node` (e.g. `SMA(length)`
|
||||
sizes its ring buffer). A **blueprint** is the param-generic, input-role-generic
|
||||
graph-as-data produced by running a Rust builder (C9); it carries *free* numeric
|
||||
params (declared ranges) and *free* input roles. The **bootstrap** binds
|
||||
`(blueprint + param-set + data bindings + seed)` into a concrete, **frozen
|
||||
instance** — buffers sized, topology fixed. This is precisely the "wiring /
|
||||
graph build" that C7 ("sized at wiring", "topology frozen per sim") and C12
|
||||
("params injected at graph build") already reference. The same machinery applies
|
||||
recursively up to the harness (C20). A sweep builds many instances from one
|
||||
blueprint; instances are disjoint (C1).
|
||||
**Forbids.** Params that change topology (a topology change is a *different*
|
||||
blueprint — Fork A, C7 "frozen"); resizing buffers after bootstrap; running a
|
||||
sim against an un-bootstrapped blueprint.
|
||||
**Why.** Separating the param-generic blueprint from the param-bound instance is
|
||||
what makes one strategy reusable across a whole sweep and lets the optimizer
|
||||
mutate "the 20" by *rebuilding* an instance (cheap; no recompile, C12) instead
|
||||
of rewriting code. Naming the build phase makes the implicit "wiring" of C7/C12
|
||||
explicit.
|
||||
|
||||
### C20 — Strategy ↔ harness; the harness is the root sim graph
|
||||
**Guarantee.** A **strategy** is a reusable composite-node blueprint (C9):
|
||||
broker-, data-, and viz-independent, with inputs declared as named **roles**
|
||||
(symbol-agnostic where possible) and the position-event stream (C10) as output.
|
||||
A **harness** (the experimental setup) is the **root sim graph** — sources bound
|
||||
to the strategy's input roles + the strategy + attached broker node(s) + sinks —
|
||||
and is itself produced by the bootstrap (C19). A harness *instance* is C1's
|
||||
disjoint unit (RustAst's "root scope"). The harness has **two kinds of
|
||||
parameterization**: **structural axes** (which strategy, which instrument(s),
|
||||
which broker(s), which window) whose variation selects *different* instances —
|
||||
the **experiment matrix**; and **tuning params** (the strategy's numeric params)
|
||||
swept *within* a fixed structure (Fork A). The same strategy blueprint is reused
|
||||
across backtest, sweep, visual workspaces, and the frozen live bot — each a
|
||||
different harness. **Both strategy and harness/experiment are authored in Rust**
|
||||
via builder APIs (C17); the experiment matrix is ordinary Rust control flow
|
||||
(loops/conditionals), not a config schema.
|
||||
**Forbids.** Embedding data sources / brokers / sinks inside a strategy; a
|
||||
declarative experiment mini-DSL (logic is Rust — C17); treating the harness as
|
||||
anything but a (root) graph.
|
||||
**Why.** Reusability needs the strategy to be a context-free blueprint that many
|
||||
harnesses embed. Modelling the harness as a root graph keeps it within the one
|
||||
Node/graph abstraction (C9) and makes "10 strategies in one environment" and
|
||||
"one strategy × N instruments" plain nested loops over the structural axes. Rust
|
||||
authoring (not config) preserves full programmatic power — conditional/adaptive
|
||||
matrices, generated axes, custom wiring — and avoids re-introducing the DSL trap
|
||||
C17 rejects.
|
||||
|
||||
---
|
||||
|
||||
## Open architectural threads not yet resolved
|
||||
@@ -308,10 +369,12 @@ one; the registry/index is a later milestone over manifests that already exist.
|
||||
(C14) makes deferring it free.
|
||||
- **Parameter-space search strategies** (Bayesian/genetic) — pluggable policies
|
||||
atop the atomic sim unit (C12), not yet designed.
|
||||
- **`aura new` scaffolder + `Aura.toml` schema** — the project-config surface
|
||||
(symbols in scope, default data-window, broker profile, runs dir) and the
|
||||
command that scaffolds a project repo against the engine (C16/C18); not yet
|
||||
designed.
|
||||
- **`aura new` scaffolder, the experiment-builder API, and `Aura.toml`'s
|
||||
static-context schema** — `aura new` scaffolds a Rust project *crate* (node /
|
||||
strategy / experiment blueprints) against the engine (C16/C20); the
|
||||
experiment-builder API surface (harness wiring, structural axes, sweep
|
||||
combinators) and `Aura.toml`'s schema (data paths, instrument/pip metadata,
|
||||
default broker & window, runs dir) are not yet designed.
|
||||
- **`aura-std` contents** — the crate exists (doc-only); which universal blocks
|
||||
land first follows the walking-skeleton's needs.
|
||||
- **`strategies/` split** — a later split, *inside a project*, of top-level
|
||||
|
||||
+27
-14
@@ -16,25 +16,30 @@ from the things built with it:
|
||||
signals.
|
||||
- **A research project** is its **own external repo** (e.g. `~/dev/ger40-lab/`),
|
||||
with its own git history, its own Gitea repo (its own forward-queue), and a
|
||||
cargo dependency on aura. This is where you and Claude author signals and where
|
||||
the runs live. (See contract **C16**.)
|
||||
cargo dependency on aura. **It is itself a Rust crate** (a `cdylib` library of
|
||||
node / strategy / experiment blueprints); the `aura` host loads and runs it
|
||||
during research (hot-reload), and freezes a chosen strategy + broker into a
|
||||
standalone binary for deploy. This is where you and Claude author signals *and
|
||||
experiments* — all in Rust — and where the runs live. (Contracts **C16**, **C20**.)
|
||||
|
||||
The `aura` CLI is a tool you run *inside* a project directory — it finds the
|
||||
project root by walking up to an `Aura.toml`, the way `cargo` finds `Cargo.toml`.
|
||||
A project is always a Rust program built on the engine.
|
||||
|
||||
## A project repo
|
||||
|
||||
```
|
||||
ger40-lab/ # your research project — a separate repo
|
||||
├── Aura.toml # project config: symbols in scope, default data
|
||||
│ # window, broker profile, runs dir (schema TBD)
|
||||
├── Cargo.toml # depends on aura-core (+ shared node crates)
|
||||
ger40-lab/ # your research project — a separate Rust crate (cdylib)
|
||||
├── Aura.toml # STATIC context only: data paths, instrument/pip
|
||||
│ # metadata, default broker & window, runs dir (no logic)
|
||||
├── Cargo.toml # cdylib; depends on aura-core/aura-std (+ shared node crates)
|
||||
├── CLAUDE.md # the project's own skills wiring (authoring discipline)
|
||||
├── .claude/dev-cycle-profile.yml
|
||||
├── nodes/ # project-local, experimental nodes (cdylib)
|
||||
├── nodes/ # project-local node & strategy blueprints (Rust)
|
||||
│ └── third-candle-long/
|
||||
├── experiments/ # experiment/harness definitions (Rust): matrices, sweeps
|
||||
├── runs/ # the run registry: manifest + metrics per run
|
||||
└── (frozen bots, results, …)
|
||||
└── (frozen bots, …)
|
||||
```
|
||||
|
||||
## Where reusable nodes live (three tiers)
|
||||
@@ -57,9 +62,11 @@ the dependent.
|
||||
## Authoring happens in Claude Code (contract C17)
|
||||
|
||||
aura has no built-in coding-LLM. You author by talking to Claude Code, which
|
||||
writes the node crate, builds it, runs it, and reports back. IONOS LLMs appear
|
||||
only as a *runtime data source* (e.g. a news-agent node emitting a bias),
|
||||
recorded before it enters a backtest, and only with your per-session consent.
|
||||
writes the Rust — nodes, strategies, *and experiments* — builds it, runs it, and
|
||||
reports back. Declarative config (`Aura.toml`) holds only static context, never
|
||||
logic. IONOS LLMs appear only as a *runtime data source* (e.g. a news-agent node
|
||||
emitting a bias), recorded before it enters a backtest, and only with your
|
||||
per-session consent.
|
||||
|
||||
## A day in the life
|
||||
|
||||
@@ -77,11 +84,17 @@ recorded before it enters a backtest, and only with your per-session consent.
|
||||
attached at once: add `--broker pepperstone` to get a realistic currency
|
||||
curve *alongside* the default sim-optimal pip curve — two comparable equity
|
||||
curves from the same position table. (Contract C10.)
|
||||
4. **Sweep + Monte-Carlo:** `aura sweep … --grid lookback=5..50,thresh=0.5..0.9
|
||||
--mc-seeds 1000` → a distribution of metrics, best params, robustness bands.
|
||||
4. **Sweep / Monte-Carlo / matrix — a Rust experiment.** Anything beyond a
|
||||
single backtest is an *experiment* in `experiments/` (Rust, builder API): a
|
||||
parameter sweep, Monte-Carlo over seeds, or a structural matrix like "these 10
|
||||
strategies × these 3 instruments × {sim-optimal, pepperstone}". The matrix is
|
||||
plain Rust loops, not a config schema (C20). `aura run experiments/compare`
|
||||
bootstraps the matrix, fans the disjoint sims over all cores (C1), and writes
|
||||
the comparable runs to `runs/`.
|
||||
5. **Compose:** "combine it with `momentum-filter` as a weighted sum" → Claude
|
||||
writes a composite node (fractal, C9).
|
||||
6. **Walk-forward:** `aura walkforward …` → an out-of-sample verdict.
|
||||
6. **Walk-forward:** another experiment kind (rolling in-sample optimize +
|
||||
out-of-sample test) → an out-of-sample verdict.
|
||||
7. **Freeze:** `aura freeze nodes/strategy-y --broker pepperstone
|
||||
--out bots/strategy-y` → a standalone, statically-linked bot (C13).
|
||||
8. **(Later) Look:** `aura play` opens the egui playground — equity curve, trade
|
||||
|
||||
Reference in New Issue
Block a user