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>
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).
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>