2968fbef40f317e57bcfcf58bcf2e366fc9e8596
24 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
428f83c542 |
audit: cycle 0107 tidy (drift resolved by ledger/glossary lift)
Architect verdict: drift_found — the code holds its contracts (C1 determinism incl. lowest-index fault attribution and doc-seeded deflation; C16 seam: aura-campaign excludes ingest/std/composites, MemberRunner isolates the condemned CLI scaffolding; the walk_forward lockstep set moved together), the docs lagged the tree. All six drift items resolved in this commit: - C18: 'no executor exists' retired (0106 text now points forward); new cycle-0107 realization records the executor, the aura-campaign home, ListSpace, the campaign_runs.jsonl sibling store, zero-survivor exit-0 semantics, emit/persist_taps split, the #196 on-ramp, and the machinery-true std::walk_forward correction. - C16: aura-campaign added to the non-node crate enumeration (cycle-0107 realization; explicitly not C21's World). - Glossary: campaign document entry corrected (run verb, execution prose); new 'campaign run' entry; blueprint entry gains the on-ramp verbs. Carry-on debt (self-noted in code, tracked): metric-roster triplication #190, deflation-constant duplication #199; cross-cell fault orphans + nested-parallelism oversubscription noted in the tasks-6-7 commit body. Follow-ups filed on the milestone: #200 (mc/generalize stage execution), #201 (persist_taps wiring). Regression: cargo test --workspace 987/0; clippy -D warnings clean; cargo doc 0 warnings. Spec + plan removed at close per convention (durable rationale lives in the ledger; the canonical record is the git history). closes #198 |
||
|
|
e73aadae1e |
docs(ledger): #188 amendment package — C25 role model, C20/C22 refinements, invariant-10 clarification
C25 (new): the nine authoring roles cut by artifact + surface + iteration cost, the recognizability test, the 6a/6b split on invariant 12's tier boundary with the id machinery as interface, the text-first/headless-first invariant (visual surfaces = stateless projections, viewers over editors), and the Blockly litmus test as every vocabulary's acceptance criterion. C20: the 'plain Rust loops, not a config schema' clause and the mini-DSL forbid are scoped — they forbid an open logic-bearing language, not the closed-vocabulary campaign document that now carries experiment intent under the P1 construct tier; generators may stay Rust, what they yield is data. C22: stateless-projection refinement generalized to all artifact classes; the shipped face recorded as the web-from-disk front. Glossary playground entry aligned (the egui-native wording was stale against the 2026-06 revision). CLAUDE.md invariant 10: clarified that closed-vocabulary data artifacts (op-scripts, blueprints, process/campaign documents) are not the forbidden DSL — RustAst failed as an open logic-bearing language; new logic escalates to a Rust block, never a freetext hole. All content ratified on #188 (body + addenda + resolution comments); this commit is production of the durable record, no new design. closes #192 |
||
|
|
ebe85683c9 |
audit: cycle 0106 tidy — ledger/glossary lift, unwired-hint fix, spec/plan retired
Architect drift review (holds: C14 headless authoring, C16/C17 no-DSL with aura-research a true leaf, content-id move behaviour-preserving per the untouched id goldens). Resolution per item: - fix (docs): C18 gains the cycle-0106 realization note (processes/ + campaigns/ stores, document canonical form, the content-id primitive's library home, the referential tier, no-executor status); the #109 analysis-meta-level open thread records the artifact half shipped v1 and what stays open (executor question, verb dissolution 'once it carries', the remaining #188 amendment package). Glossary: new campaign document + process document entries; content id generalized to all three artifact classes; experiment marked superseded by the campaign document (#188 re-cut of the builder-API thread). - fix (code): the --unwired guide advertised an identity_id process ref that validate_campaign refuses — the process.ref open-slot hint now says content-id-only (strategy refs keep both); lib + seam pins updated. - filed forward: #190 (metric-vocabulary single-sourcing, the 0105 roster drift class), #191 (identity-ref store scan is O(store), performance only). - carry-on: regression gates green by hand — cargo test --workspace 916/0, clippy -D warnings clean, cargo doc --no-deps 0 warnings; no baseline to ratify (project has no metric baseline scripts). Cycle 0106 spec and plan retired per convention (git rm); durable record is the ledger notes above plus #188/#189. refs #189 |
||
|
|
691562494b |
docs: fieldtest F3/F6 doc-gap fixes — manifest provenance in glossary, Aura.toml scaffold reality
Two doc-tightenings from the green milestone fieldtest (F3, F6 in
fieldtests/milestone-project-environment/FINDINGS.md): the glossary
manifest entry now names the topology hash and the project provenance
block {namespace, dylib_sha256, commit} a project-hosted run carries;
project-layout.md's Aura.toml annotation now matches what the scaffold
actually emits today ([paths] runs only — the data archive root joins
once real data enters).
refs #180
|
||
|
|
7b429f931a |
audit: cycle 0104 tidy (drift-clean after three doc-mirror alignments)
Architect drift review (range d5c4361..45fb06d): drift_found, three items, all doc-mirror — resolved inline as close-fixes: - docs/design/INDEX.md — the two #171 deferral passages (C18 #158 realization + C24 status) now record the shipped identity id (additive sibling; content id keeps the store/reproduce roles; introspection-only until a dedup consumer exists). Whole-harness / structural-axis content-addressing stays deferred. - README.md — introspect table gains the --identity-id row incl. the combinable id-flag behaviour. - docs/glossary.md — three record-reality entries: content id, identity id (Avoid: identity hash, topology-identity hash), topology hash; the README row aligned to the canonical term. What holds (architect): additive-sibling discipline intact (no store code touched, every content-id/topology_hash pin green); C23 honoured precisely (each strip arm has a protecting property test; factoring byte-preserving via the canonical golden); the two extra engine tests are genuinely distinct coverage (recursion arm, role/output arms), no redundancy. Regression gates (all green): cargo build clean; cargo test --workspace 884 passed / 0 failed (873 baseline + 11 new); clippy --all-targets -D warnings clean; cargo doc --no-deps 0 warnings. Ephemeral cycle artifacts removed per project convention (git rm): docs/specs/0104-topology-identity-hash.md, docs/plans/0104-topology-identity-hash.md. refs #180 |
||
|
|
4928e289f7 |
feat(project): the project-as-crate load boundary (cycle 0102)
A research project is now a loadable external cdylib crate. Inside a directory whose ancestry holds an Aura.toml, aura discovers the project root cargo-style, locates the compiled dylib via cargo metadata (debug default, --release opt-in), loads it load-and-hold, and refuses mismatches before trusting anything: the AURA_PROJECT descriptor (aura-core::project, #[repr(C)]) carries a C-ABI stamp prefix (rustc + aura-core version, baked per consuming build by the new aura-core build.rs) validated before any Rust-ABI field is read. The vocabulary charter gates the merged resolution: project type ids are ::-namespaced (std stays bare), duplicates refuse, and the enumerable type-id list must agree with the resolver, so introspection can never silently omit a project type. All blueprint verbs resolve through the merged project + std vocabulary via a per-invocation Env threaded through the dispatch chains; registry, trace-store, and data paths anchor at the project runs root (Aura.toml [paths], paths-only by design — instrument geometry stays the recorded sidecar, C15). RunManifest gains the Tier-1 project provenance field (namespace + dylib sha256 + best-effort commit), stamped beside topology_hash on the blueprint-run paths; pre-0102 registry lines load unchanged. Default node names strip the namespace, so :: never reaches the param-path address space. Proven by the demo-project fixture (built by the e2e via cargo, path-dep on this workspace): run twice bit-identical, provenance recorded, introspection lists demo::* beside std, registry anchors at the discovered root from a subdirectory; the badcharter fixture proves the charter refusal through the real libloading path; a never-built project refuses with a cargo-build hint. Outside a project every path collapses to the previous literals — goldens and manifest pins byte-identical. Verification: cargo build --workspace clean; cargo test --workspace 862 passed / 0 failed (incl. 7 project_load e2e); clippy -D warnings clean (one precedent-matching allow(too_many_arguments) on run_oos_blueprint, whose arity the Env threading raised to 8); doc build unchanged. Docs/ledger aligned: Aura.toml field lists are paths-only in project-layout.md, glossary, C16/C17; new C13 realization note records the per-invocation-reload reading and the load-and-hold one-shot scope boundary. New deps, per-case review (aura-cli leaf binary only, never the frozen artifact): libloading, toml. refs #180 |
||
|
|
4de6d5cbad |
rename: retire the stage1-* family for the r-family (r-sma / r-breakout / r-meanrev)
The stage1 ordinal has been dead vocabulary since the C10 reframe dropped the two-stage research model: a 1 structurally implies a 2 that no longer exists. The family is renamed by its live discriminator - the R yardstick - with members named by their signal, uniform with their signal-named siblings (sma, macd, momentum): - selectors: stage1-r -> r-sma, stage1-breakout -> r-breakout, stage1-meanrev -> r-meanrev (old tokens are usage errors, exit 2 - no silent alias) - identifiers: Strategy::RSma/RBreakout/RMeanRev, HarnessKind::RSma, r_sma_*/r_breakout_*/r_meanrev_*, wrap_r, run_signal_r, RGrid, R_SMA_* - persisted identity: the sma_signal composite (param prefix sma_signal.fast.length / .slow.length; fixtures regenerated; content-ids shift - no test pins a literal hash, the registry parses no record names) - e2e test files git-mv'd to r_sma_e2e / r_breakout_e2e / r_meanrev_e2e - dead Stage-1/Stage-2 prose reworded to post-C10 vocabulary across rustdoc, Cargo.tomls, ledger live lines, and the glossary (historical entries stay; fieldtests corpus untouched) - CLAUDE.md invariant 7 rewritten to record the ratified C10 reframe faithfully (the token-swap alone would have laundered the retired gated-currency/realistic-broker design into unmarked live prose); the unbacked account-mode clause dropped Verification: cargo build/test --workspace green (51 targets), clippy -D warnings clean, doc build clean, acceptance grep gate leaves exactly the one resampling-stage false positive (harness.rs), smoke: --harness r-sma runs, --harness stage1-r exits 2 with the new usage line. Decision log: forks and rationale recorded on the issue (reconciliation + implementation-phase comments). closes #174 |
||
|
|
88e9c9a539 |
fix(cli): symmetric sweep/mc family-verb polish (closed error, mc seed label, mandatory-knob docs)
Three polish items surfaced by the World/C21 milestone fieldtest:
- A sweep of a fully-bound (closed) blueprint is refused up front with a clear
"this blueprint is fully bound; nothing to sweep" message — the symmetric
inverse of blueprint_mc_family's closed-blueprint guard — instead of leaking a
misleading UnknownKnob for a knob that is not unknown but bound out.
blueprint_sweep_family's error contract widens to String; the sweep terminal's
BindError (a genuine unknown/kind-mismatch axis) still surfaces verbatim.
- mc reproduce lines now carry each member's seed=<N> label. Monte-Carlo members
hold no tuning params, so the member label was blank; the seed is each draw's
realization identity. Sweep / walk-forward labels (which echo params) unchanged.
- docs (design ledger + glossary): state that every open knob --list-axes prints
is mandatory on sweep / walkforward — a subset is refused with the missing knob
named (BindError::MissingKnob), there is no default; pin a knob you do not want
to vary with a single-value axis.
RED-first for the two behaviour items. One existing unknown-axis E2E is re-pointed
from the closed fixture (which now hits the new "nothing to sweep" pre-check) to
the open fixture; it still exercises UnknownKnob("nope") specifically — resolve
raises UnknownKnob in phase 1 before MissingKnob in phase 2 — so the property is
preserved, not weakened.
closes #178
|
||
|
|
8d04a845ee |
docs(glossary): align terminology with industry standard
Reconcile 68 terms against algotrading frameworks (LEAN, NautilusTrader, backtrader, VectorBT, Zipline), quant-validation literature (Van Tharp, Bailey & Lopez de Prado, White), and stream/dataflow vocabulary. Conservative pass: extend Avoid lists with industry synonyms/homonyms and fold short disambiguation notes into definitions; no canonical headings renamed. Touched 18 entries. Avoid additions: overfit probability (PBO/CSCV), signal (entry/exit signal, trade signal), position table (transactions, trade blotter), conviction-based risk allocation (risk budgeting/parity/ contribution), run registry (model registry), session node (session window), sign-agreement (market breadth). Disambiguation notes: broker vs fill/account simulator, edge (wiring/trading/deploy senses), cycle (clock step vs DAG loop), manifest vs Cargo.toml config, experiment vs MLflow container, run-count (version counter), bias vs statistical bias, bootstrap vs statistical bootstrap, deflated score anchored on the Deflated Sharpe Ratio, Monte-Carlo (input not trade sequence), World vs Unreal UWorld. Deferred (out of scope this pass): heading renames, a new `record` entry + composite sense-split, the playground egui->web wording, the SoA Avoid line. |
||
|
|
39f9387c57 |
docs(glossary): add 'tap' — named recorded sink stream
Record-reality add: 'tap' is in consistent use across the code (ColumnarTrace.tap, the --tap flag, the equity/exposure/net_r_equity/ r_equity taps) and the design ledger, but had no glossary entry. The entry also draws the line the 'tap/sink' shorthand blurs: a sink is the recording-role node, a tap is the named stream it records. |
||
|
|
a517899297 |
docs: sync ledger cross-ref + glossary to the C10 rework (refs #116)
Follows the C10 rework (
|
||
|
|
3e8fd73f68 |
tidy: clear the milestone fieldtest findings (refusal reasons, --help, ledger + glossary)
Resolves the four non-bug findings from the inferential-validation milestone
fieldtest (the bug — the broken-pipe panic — is fixed in
|
||
|
|
458b2ae74b |
audit(0067): cycle close — lift SQN100 / stage1-r-trace rationale to ledger, drop ephemera
Architect audit clean (no drift, no debt): raw sqn verified bit-identical, C18 serde back-compat + C4 SoA seam + C1 determinism + Part-B symmetry all hold. - Ledger C10: add a "Realization (cycle 0067, #130 + #135)" note — SQN100 as the turnover-robust opt-in rank key (raw sqn / default ranker byte-unchanged, serde(default) for back-compat), and per-member --trace now symmetric across all three sweep strategies via the shared persist_traces_r. - Glossary: R-metrics list gains sqn_normalized; the SQN entry documents the SQN100 variant (was "deferred #130"). - Remove the ephemeral spec + plan (cycle closed; rationale lives in the ledger and git history). refs #130, refs #135 |
||
|
|
986a9fd5c7 |
audit(0066): cycle close — lift R-sweep/SQN rationale to ledger, drop ephemera
Cycle 0066 (#133) closed. The close audit (architect) found the family ratified against C12 axis-2 (rank-by-metric over the C18 family store) and the C10 R framing, with one [high] gap (swept-member manifest omitted the fixed R-defining params) fixed forward in
|
||
|
|
f040b66f30 |
design(c10): reframe to a bias stream + R-unit signal quality
Adopt the R-reframe ratified in #117: the strategy's native unit is risk (R), not pips/dollars, and its primary output is a directional bias. - exposure -> bias: the primary output is an UNSIZED direction + conviction `f64 in [-1,+1]`; sizing and the protective stop leave the strategy. - Signal quality is measured in R (Stage 1): an R-evaluator integrates the per-trade R-outcomes of a flat-1R RiskExecutor into R-expectancy. R is defined by the stop, account-/instrument-agnostic; pips retired as the unit. Flat-1R needs no equity, so Stage 1 is feed-forward (no cycle). - Risk-based execution is a decoupled layer: a RiskExecutor composite (stop-rule -> Sizer -> Veto -> position-management) per symbol, nested in a Broker/Account composite; account mode (netting/hedging) = composition constraint. "Sizer" is not "risk-manager" (that names the Veto layer). - Currency P&L is Stage 2 (fixed-fractional, compounding). The only feedback (equity -> Sizer) is cut by a z^-1 register on the fill edge (mark-to-market stays a same-cycle price read), encapsulated in the executor; flat-1R vs compounding is a structural axis (the explicit register is mandatory because C23 reorders the flat graph). - Position-event table stays the decoupled Stage-2 audit layer = first difference of the book (deal = target - book - in_flight); the flawed 0064 exposure-integral derive is abandoned. Touches: ledger C10 + CLAUDE.md domain invariant #7 + glossary (adds bias, R, R-evaluator, RiskExecutor, Sizer, veto, Stage 1/2; revises broker, exposure stream, position table, sim-optimal broker, strategy, ...). Also fixes cross-file drift surfaced by adversarial review (C20 guarantee + front-matter provenance still claimed "exposure stream"; cross-refs corrected to C9/C19/C20/C23). Industry-grounded against LEAN / nautilus_trader / backtrader / QSTrader / vectorbt / zipline. refs #117 |
||
|
|
86746e3d5d |
refactor(aura-core): Scalar as a native tagged enum, disjoint from Cell; typed RunManifest.params
Scalar was `struct { kind: ScalarKind, cell: Cell }` — "a Cell wearing a kind hat." The recorded reason for that shape was migration ease, which is not a design rationale (CLAUDE.md: rationale != effort), so the struct had no substantive defense. Redefine it as the native tagged union it conceptually is:
enum Scalar { I64(i64), F64(f64), Bool(bool), Timestamp(Timestamp) }
This is substantively better on four axes: kind/bits skew becomes unrepresentable (illegal states gone); accessors panic loudly on the wrong variant instead of a release-mode silent bit reinterpret; PartialEq derives the documented IEEE-754 / cross-kind value semantics (the hand-roll, needed only because the struct inherited Cell's bitwise compare, is gone); and serde is a plain derive emitting the externally-tagged wire form ({"I64":10}/{"F64":2.5}) — the private ScalarRepr shadow enum that motivated this was never needed. It is also C7-honest: erased-on-the-hot-path (Cell) and self-describing-at-the-edge (Scalar) are two disjoint types bridged by explicit conversion.
The whole public API is preserved (Scalar's fields were private), so call sites do not churn: the enum change is contained to scalar.rs, where cell() now encodes and from_cell() decodes per kind. Cell and ScalarKind are untouched.
With Scalar serializable, lift RunManifest.params from Vec<(String, f64)> to Vec<(String, Scalar)>: the param's kind (an i64 length vs an f64 scale) now survives into the C18 record (runs.jsonl) and the CLI JSON instead of collapsing to f64. scalar_as_param_f64 is deleted; sim_optimal_manifest passes typed params through. This is a deliberate wire-shape change — params now render as tagged scalars; the JSON-asserting tests are updated to the new shape on purpose.
Hand-authored manifest params across the CLI's single-run/mc/macd sites use honest kinds (lengths -> i64, scales -> f64) so they match the sweep path (which already derives correct kinds via zip_params); their in-binary JSON assertions are re-tagged accordingly.
Walk-forward fork resolves with no code change: WindowRun.chosen_params stays Vec<Scalar> (the serializable record carrier), reduced to f64 only at the param_stability statistic boundary (scalar_as_f64 retained). Glossary 'cell' entry updated to describe Scalar as the disjoint tagged union, not 'a cell plus its kind tag'.
Gates: build --all-targets, test --workspace (incl. new scalar_serde_round_trips), clippy -D warnings, doc --no-deps — all clean.
|
||
|
|
3598cb9dde |
audit: cycle 0047 — drift-clean (cell hot-path carrier)
cycle 0047 tidy. Architect drift review (b188773..82635fa, against the design ledger C7/C8/C1) found the carrier swap drift-clean: - Node::eval -> Option<&[Cell]>, all 8 aura-std out-buffers [Cell; N], the inter-node forward via the branch-free push_cell (harness.rs:426); Scalar survives only on the three keep-set boundaries (param plane, AnyColumn::get, source ingestion at harness.rs:402). The convert/keep partition and the three-role test rule are honoured site-for-site. - The dual API is coherent: fallible push (ingestion + kind-guard tests) vs infallible push_cell (bootstrap-verified inter-node forward) are each load-bearing and tested. No dead code, no C7 violation (no tag on the hot path; scratch: Vec<Cell> reused via clear(), no per-cycle alloc). - Both C7 realization notes + the C8 prose accurately describe the landed state. 285 tests green; build/clippy/test/doc clean. Tidy fix (pre-existing, surfaced by the review): - docs/glossary.md `node` entry said a node implements `schema()`, but Node::schema() was removed in cycle 0024 (the signature is declared pre-build on PrimitiveBuilder). Corrected to `lookbacks()` + `eval(ctx)`, the methods the Node trait actually carries. Record-reality. |
||
|
|
8eff6398ca | docs(glossary): add the cell entry | ||
|
|
0d7deb3a91 |
design(C10): reframe strategy output to intent/exposure stream; position table becomes a derived layer
The DAG expresses exactly one state at time t and a node emits at most one record per eval (C8), so a *sequence* of position events — where one decision instant (a stop-and-reverse) needs a close AND an open at the same event_ts — cannot be the DAG's per-cycle output without violating C8. The state the DAG can express faithfully is the desired exposure (one value per cycle); the buy/sell/close events are its first difference, a derived consequence. C10 is reframed accordingly: the strategy's primary, backtestable output is an intent/exposure stream (one signed, bounded f64 in [-1,+1] per cycle). Signal quality is measured by the sim-optimal broker integrating exposure*return into a synthetic pip-equity curve. The broker-independent position-event table survives as a decoupled, derivable, downstream position-management layer (computed table, not a per-eval output) feeding realistic broker nodes for viability/deploy — no longer the DAG output nor the signal-quality measure. Touches the ledger contract (INDEX.md C10 + provenance/milestone/C20 ancillary), the always-loaded summary (CLAUDE.md invariant #7), the glossary (broker, equity stream, position table, realistic broker, signal, sim-optimal broker, strategy reframed + new exposure-stream entry), and the north-star layout doc. Sealed specs/plans (0001-0006) left as historical record. refs #4 #5 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
3a02fbf383 |
audit: cycle 0006 tidy (clean) — glossary record-reality (sink is a role)
Architect drift review over 57310b8..HEAD: clean — no drift, no debt. The C1/C7 boundary is correctly drawn (recorded values escape only via a node-held mpsc::Sender with no out-edge; nothing recorded re-enters the graph; the engine surface shrank). C2 holds (Ctx::now() is the present cycle's ts). The C8/C22 cycle-0006 realization notes accurately describe what shipped — no overclaim. Test fixtures stayed in #[cfg(test)] (C9). Regression set is empty (profile) — architect is the sole gate; green. Record-reality: the glossary 'sink' entry defined a sink as 'a pure consumer node with no output', which the shipped TapForward node (records AND forwards an output) now contradicts. Updated to reality: a sink is a recording *role*, not a type — a node may be a pure consumer or record and produce in the same eval (C8 'both'). No invention; the entry now matches the substrate this cycle landed. |
||
|
|
57310b83c7 |
audit: cycle 0005 tidy — glossary record-reality (node-output-record)
Architect drift review over 9ff90b5..5228542 (node-output-record): drift_found,
all low-severity, NO contract violation. The load-bearing invariants hold:
- C7 forbids intact — the reused `scratch` buffer (cleared+extended, warm after
cycle 1) and node-owned `[Scalar; K]` output buffers give zero per-cycle heap
alloc on the inter-node forward path; no fifth scalar type, no dyn-Any, no
heterogeneous buffer (the TwoField mixed-kind producer is rejected at bootstrap,
never streamed). Purity grep clean. The sharpened C7 guarantee text matches the
shipped per-field kind check + the Edge::from_field scatter.
- C8 revised text faithful — one output port (out_len), record of 1..K columns
(Vec<FieldSpec>), field-wise binding only (N edges, no whole-record bind), scalar
= degenerate K=1. No internal contradiction with C7/C9/C10.
- C6 untouched, verified against the run loop — one eval per node per cycle, every
out-edge stamps SlotState { fresh_at: cycle_id, last_ts: ts } with the same ts,
so the K fields of one record are co-fresh by construction. fires() unchanged.
- C3/C4/C5/C9 unperturbed (diff touches only node/edge plumbing); C2 lookback
enforcement unperturbed (column.rs/ctx.rs/any.rs not in the diff).
- C10 coherence confirmed — a position event is a 5-field record
(event_ts/action/position_id/instrument_id/volume), exactly the K-field
base-column record C8/C7 now sanction; the decision/sizing node is an ordinary
K=5 producer, the broker an N-edge field-wise consumer. No contract gap blocks
the next consumer; C10 correctly out of scope this cycle.
Resolved [low] (the one confirmed drift) — glossary record-reality. The ledger
C7/C8 moved this cycle but the glossary lagged. Fixed three entries to the
post-0005 reality (this is audit's autonomous glossary write authority,
record-reality only): `node` ("at most one output" -> "at most one output port; a
producer's output is a record of 1..K base-scalar columns, scalar = degenerate
K=1"), `composite` (now connects the multi-column stream to the node-output model
— the record a producer's eval returns, bound field-wise), `edge` (forwards "one
field (from_field) of a producer's eval output record", per-field kind check).
The architect named `node` + `composite`; `edge` is an orchestrator-observed
addition in the same record-reality pass (post-from_field it read "forwards one
node's eval output", now imprecise for K>1).
Regression gate: profile regression list empty — architect is the sole gate, now
clean (36 tests: aura-core 19 + aura-std 3 + aura-engine 14; clippy -D warnings
clean; purity grep clean). Cycle 0005 is drift-clean.
Carry-on forward note (next-cycle owner, not a fix now):
- [low] cycle 0004's depth>1 join-lookback guard test remains merely OWED, not a
fresh hole — the substrate enforces it via Window bounds (column.rs/ctx.rs
untouched this cycle) and 0005 added no depth>1 join. Co-fresh borrowed-row
routing does not interact with per-input lookback. A confirmation test is still
owed when a depth>1 join lands.
NOT a milestone close: the walking-skeleton milestone still needs its end-to-end
fieldtest (ingest -> signal -> backtest -> position table -> broker -> pip-equity).
This cycle delivers the record-output substrate that the trading half (C10) now
builds on.
refs walking-skeleton
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
9ff90b5d80 |
audit: cycle 0004 tidy — diamond-barrier test + ledger/glossary record-reality
Architect drift review over 02fe891..f37b2a3 (firing-policies-and-merge):
drift_found, all medium/low, no contract violation. Invariants hold: C1 (the
merge is a deterministic linear scan, strict < on (timestamp, source-index) gives
C4 tie-break by declaration order; only per-call allocs), C3 (one merge at
ingestion), C5/C6 (both rails proven with worked vectors; sample-and-hold falls
out of the push model), C7 (type-erased edges, no dyn-Any/Rc/RefCell — purity grep
clean). Resolved the 0003 forward-note: cycle_id is now a real read field (the
freshness epoch, fresh_at == cycle_id), not write-only.
Resolved [med] (test gap): the barrier's timestamp token was proven only for the
multi-source same-timestamp case; C6's within-source diamond rejoin (one source,
two unequal-latency paths rejoining at a barrier) was claimed by the spec but
untested. Added `within_source_diamond_rejoin_barrier_fires`
(source -> {SMA(2), SMA(4)} -> BarrierSum): once SMA(4) warms at cycle 4, both
paths emit each cycle at the same timestamp and the barrier fires
(15+13, 17+15, 19+17). The code was already correct — every push in a cycle
stamps last_ts = that cycle's timestamp (source pushes and produced-edge forwards
alike) — so this closes the coverage gap, not a bug.
Resolved [med] (glossary record-reality): the run-count entry claimed it "drives
freshness-gated recompute", now false — the engine's firing gate reads the
per-wiring-slot cycle epoch (fresh_at), not Column::run_count. Sharpened the entry
to record reality: run-count is the node-visible per-column push counter;
fresh_at is the engine's per-slot freshness epoch. Not redundant (different
levels); both are maintained consistently on every push.
Resolved [low] (ledger silent on the barrier token): added a C6 "Realization
(cycle 0004)" note recording the load-bearing decision — barrier token is the
timestamp not cycle_id (forced by C4's same-timestamp-tie rule), firing tagged
per input with Firing::{Any, Barrier(u8)}, a mode-A input being its own trivial
group (so "per input group" and the per-input tag coincide).
Carry-on forward notes (next-cycle owners, not fixes now):
- [low] cycle_id is materialized internally (the freshness epoch) but not yet
surfaced in run output (run returns Vec<Option<Scalar>>). Its first observable
consumer is a sink / clock node (C18) or a timestamped trace — materialize the
surfacing then.
- [low] all join fixtures declare lookback 1; a test guarding C8's "a node never
reads beyond its declared lookback" for a depth>1 join is still owed (the
substrate already enforces it via Window bounds, so this is confirmation, not a
hole).
Regression gate: profile regression list empty — architect is the sole gate, now
clean (31 tests: aura-core 19 + aura-std 3 + aura-engine 9; clippy -D warnings
clean; purity grep clean). Cycle 0004 is drift-clean. NOT a milestone close: the
walking-skeleton milestone still needs its end-to-end fieldtest (ingest -> signal
-> backtest -> position table -> broker -> pip-equity), of which this cycle
delivers the firing/merge layer.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
02fe89176f |
audit: cycle 0003 tidy — rename Sim -> Harness (glossary alignment)
Architect drift review over 71c8f6e..dd5c3fa (deterministic-sim-loop). Invariants hold: C1 (single-threaded, bit-identical re-run, alloc-free per-cycle ring path), C7 (AnyColumn type-erased edges, Box<dyn Node> is the node object not a dyn-Any payload, kinds checked once at bootstrap), C8/C9 (DAG wired, Kahn rejects cycles, None forwards nothing = sample-and-hold seed). Column::run_count already exists, so the C5 freshness primitive lives at the substrate — the deferral is honest, not a hole. Resolved [high]: the runtime type was named `Sim`, colliding with the glossary's load-bearing distinction — `sim` is the disjoint *executable unit / parallelism* framing, whereas the thing built here (a closed root graph of source + nodes + observe under a clock) is by C20 / the glossary a **harness**. Renamed `Sim` -> `Harness`, `sim.rs` -> `harness.rs`, and the module/exports/doc to match, before any other code takes a dependency on the wrong term. Gates re-run green (26 tests, clippy -D warnings, purity grep). Resolved [med] (glossary gap): added an `edge` entry anchoring the new wiring vocabulary (Edge / source target) to the glossary — record-reality per the boss glossary-write authority. Carry-on with forward notes (next-cycle owners, not fixes now): - [med] C4 monotonic cycle_id has no realization in the runtime type yet (the cycle clock is the record iteration; the explicit counter's first reader is freshness). Cycle 0004 owns materializing it together with C5. - [low] Sub declares lookback 1; once depth>1 join nodes exist, add a test guarding C8's "a node never reads beyond its declared lookback". Regression gate: profile regression list empty — architect is the sole gate, now clean. Next direction: freshness-gated recompute + a second source (C5/C3). |
||
|
|
d566fed92b |
docs: bootstrap the project glossary; wire paths.glossary
Build a 44-entry glossary from the prose surface (design ledger, project layout, CLAUDE.md, crate doc-comments) in the convention's three-field format, and set paths.glossary so it becomes standing reading for every skill/agent role. Contested clusters resolved with the user: - bot vs frozen artifact kept as distinct entries (genus/species). - backtest / sim / run pinned as three distinct framings, none banned. - signal kept as its own concept (a score-producing node). - sim-optimal broker distinguished from Aura.toml's "default broker". Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |