937257e368
Bind a sweep's axes by name instead of by a positional GridSpace:
bp.axis("sma_cross.fast", [2, 3]).axis("sma_cross.slow", [4, 5]).axis("scale", [0.5]).sweep(run)
The sweep half of spec 0030, completing the named-binding feature (#35). A pure
authoring layer over the existing GridSpace::new / sweep primitives; engine core
untouched (C1/C12/C19/C23).
This iteration:
- resolve_axes(): shares resolve's name->slot mapping (iter 1), adds the EmptyAxis
check (the variant defined in iter 1 is now first constructed here) and a
per-element axis kind-check (every element of each axis, first offending element
in axis order). Its validation is a strict superset of GridSpace::new's
(arity / non-empty / per-element kind), so SweepBinder::sweep's downstream
GridSpace::new(...).expect(...) is infallible by construction — it can never
panic on author input.
- Composite::axis -> SweepBinder -> SweepBinder::sweep (Result<SweepFamily, BindError>).
- The CLI sample sweep converted to the named form (behaviour-preserving).
Plan correction (verified by the orchestrator): the iteration plan said only the
GridSpace import was orphaned by the CLI conversion, but replacing the free
sweep(&grid, ..) call with the .sweep(..) method also orphans the free `sweep`
import — both were dropped from aura-cli to satisfy clippy -D warnings. The Scalar
import (from aura_core) stays used and was untouched.
Verified (run by the orchestrator): 6 new aura-engine tests green —
resolve_axes round-trip, EmptyAxis, MissingKnob, the per-element KindMismatch on a
mixed axis (the superset/no-panic guarantee), a builder no-panic wrong-kind test,
and a GridSpace .points() parity test; the two sweep JSON goldens
(sweep_report_renders_four_points_in_odometer_order + the cli_run integration
golden) green unchanged (name/value/order-preserving conversion); full
`cargo test --workspace` green and `cargo clippy --workspace --all-targets
-- -D warnings` clean.
refs #35
67 lines
3.1 KiB
Rust
67 lines
3.1 KiB
Rust
//! `aura-engine` — the headless, UI-agnostic reactive SoA engine.
|
|
//!
|
|
//! Delivered across cycles 0003-0004 — the harness and its deterministic run
|
|
//! loop:
|
|
//!
|
|
//! - [`Harness`] — the closed root graph that runs (a flat node array + an index
|
|
//! edge table, topologically ordered) and its deterministic `run` loop: a
|
|
//! k-way merge of timestamped sources (C3/C4) driven through a wired DAG of
|
|
//! nodes, cycle by cycle, with freshness-gated recompute and the two firing
|
|
//! policies (C5/C6) deciding when each node re-evaluates and what it holds.
|
|
//! - [`Edge`] / [`Target`] / [`SourceSpec`] — producer->consumer wiring,
|
|
//! source->consumer wiring, and a declared source (its kind + target slots).
|
|
//! - [`BootstrapError`] — wiring faults caught once, at bootstrap (kind
|
|
//! mismatch, bad index, directed cycle).
|
|
//!
|
|
//! Delivered in cycle 0009 — the run report surface:
|
|
//!
|
|
//! - [`RunMetrics`] / [`RunManifest`] / [`RunReport`] — the `(manifest, metrics)`
|
|
//! pair C18 mandates per run, with [`RunReport::to_json`] for the structured
|
|
//! C14 face;
|
|
//! - [`summarize`] — the post-run pure reduction over a run's recorded
|
|
//! pip-equity + exposure streams into [`RunMetrics`]; [`f64_field`] bridges a
|
|
//! recording sink's `Vec<Scalar>` rows to it.
|
|
//!
|
|
//! Still to come (subsequent cycles): the `Source` trait + data-server ingestion
|
|
//! and source-native time normalization (C3/C11), the broker-independent
|
|
//! position-event output and downstream broker nodes (C10), and the param
|
|
//! injection + orchestration axes of the atomic sim unit
|
|
//! (`(topology + params + data-window + seed)`, swept by optimize / walk-forward
|
|
//! / Monte-Carlo) — its `-> metrics` reduction now ships via [`summarize`].
|
|
//!
|
|
//! Visualization is never here: it is a downstream consumer node on the streams.
|
|
|
|
mod blueprint;
|
|
mod graph_model;
|
|
mod harness;
|
|
mod report;
|
|
mod sweep;
|
|
|
|
pub use blueprint::{
|
|
aliases_on, signature_of, BindError, Binder, BlueprintNode, CompileError, Composite, OutField,
|
|
ParamAlias, Role, SweepBinder,
|
|
};
|
|
pub use graph_model::model_to_json;
|
|
pub use harness::{BootstrapError, Edge, FlatGraph, Harness, SourceSpec, Target};
|
|
pub use report::{f64_field, summarize, RunManifest, RunMetrics, RunReport};
|
|
pub use sweep::{sweep, GridSpace, SweepError, SweepFamily, SweepPoint};
|
|
// #29: re-export the core scalar vocabulary a Blueprint builder needs
|
|
// (SourceSpec.kind is a ScalarKind; sources/Recorder columns are Scalar /
|
|
// Firing / Timestamp) so a graph builder has one import surface, not two.
|
|
pub use aura_core::{Firing, NodeSchema, ParamSpec, PortSpec, Scalar, ScalarKind, Timestamp};
|
|
|
|
#[cfg(test)]
|
|
mod reexport_tests {
|
|
// #29: the core scalar vocabulary a Blueprint builder needs is reachable
|
|
// from aura-engine alone (crate::X == external aura_engine::X), so a
|
|
// downstream author does not add a second aura-core import for ScalarKind.
|
|
#[test]
|
|
fn core_scalar_vocabulary_is_reexported_from_crate_root() {
|
|
use crate::{Firing, Scalar, ScalarKind, Timestamp};
|
|
let _k: ScalarKind = ScalarKind::F64;
|
|
let _f: Firing = Firing::Any;
|
|
let _s: Scalar = Scalar::F64(0.0);
|
|
let _t: Timestamp = Timestamp(0);
|
|
}
|
|
}
|