docs(ledger, glossary): tap-subscribers cycle tidy — C8/C27/C28 lifts, tap subscription vocabulary
Cycle-close audit for the #283/#77 tap-subscribers cycle (09994b8..6e3f394). Architect review: code contract-clean; what holds — C1/C7/C8 (empty-output caller-built consumers, (Timestamp, Cell) zero-heap payload, lifecycle hooks inside the sequential loop, byte-identical twin-run and streamed-vs-legacy byte-equality pins), C28 (assembly-crate placement of the writer-holding consumer, c28_layering guard green), C25 (registry growth = new Rust entry, data-expressible Named form, roster-enumerating refusals). All drift items were doc lifts, resolved in this commit: - C8: the lifecycle is now a symmetric pair — initialize() as finalize's start-of-stream mirror (infallible by signature; acquire-in-initialize, degrade-to-inert, surface-once-at-finalize); history sidecar records the refinement and the #77 resolution the old Deferred paragraph still carried as open. - C27: Guarantee and Current state now describe the shipped model — tap plan (Named{label, params} | Live) over the layered fold registry, BOTH entry points (run_signal_r AND run_measurement) on the one shared wiring pair, record streaming at constant memory. - C28: aura-runner now defines one graph node of its own (the in-graph record consumer — exactly the graph-meets-persistence assembly position); the #297 refusal-site count grows ~20 → ~24 (the four tap-plan refusals, already typed before the exit). - glossary §tap: the subscription/fold-registry sense added; Avoid line steers probe/monitor/scope away from the observation slot. Bench (report-only, loadavg 5.8 > 2 on the box — read with care), all fingerprints OK, no regression: engine_throughput bars_per_s 14005262 wall_s 0.714s Δ bars_per_s +3.0% wall_s -3.0% ingest_throughput bars_per_s 12970670 wall_s 0.387s Δ bars_per_s +0.5% wall_s -0.5% campaign_sweep cpu_percent 2202.0 peak_rss_mb 92.2 wall_s 1.396s Δ cpu_percent +1.5% peak_rss_mb -6.1% wall_s -1.5% campaign_heavy cpu_percent 2155.0 peak_rss_mb 94.8 wall_s 5.585s Δ cpu_percent +1.8% peak_rss_mb -3.5% wall_s -0.4% cli_fixed_cost help_ms 1.5ms run_ms 3.6ms Δ help_ms -1.8% run_ms -2.6% No baseline update (report-only surface; no ratify due). Correction on 6e3f394's body: "no Probe symbol is introduced anywhere" — introduced is the operative word; the pre-existing aura-core test fixture `struct Probe` stays, as the cycle's design record specified. Follow-ups on the tracker: #308 (legacy Recorder surface migration), #307 (binary trace format). Cycle spec/plan working files discarded. refs #283 refs #77
This commit is contained in:
@@ -32,8 +32,10 @@ a zero-width `Some(&[])`, and it pushes its record to a destination it holds as
|
||||
field (a channel, a chart handle). A node may record **and** return a forwarded
|
||||
output in the same `eval` (the "both" case). `None` = filter / not-yet-warmed-up /
|
||||
pure sink. Sources are pure producers; sinks are pure consumers. Beside `eval`,
|
||||
the contract has a second lifecycle phase, `finalize()` — a default-no-op hook the
|
||||
engine calls once per node, in topological order, after the source loop drains —
|
||||
the contract has a symmetric lifecycle pair — default-no-op hooks the engine calls
|
||||
once per node, in topological order: `initialize()` before the first source value,
|
||||
letting a consumer acquire its run resources (e.g. the file a recording sink
|
||||
streams into) at stream start, and `finalize()` after the source loop drains,
|
||||
letting a sink fold online and flush one compact summary at stream end instead of
|
||||
streaming a row every fired cycle. A node also exposes `label()`, a single-line,
|
||||
non-load-bearing render symbol (C23).
|
||||
@@ -55,7 +57,12 @@ boundary is the determinism / graph-as-data boundary (C1/C7). `finalize` gives a
|
||||
folding sink O(trades)/O(1) owned accumulator state and one summary row, instead of
|
||||
an unbounded channel that buffers O(cycles) rows until the run ends; it runs once
|
||||
*after* the deterministic event loop, adding no within-sim concurrency (C1), and
|
||||
holds only owned state, no interior mutability (C7).
|
||||
holds only owned state, no interior mutability (C7). `initialize` mirrors it at
|
||||
stream start (#283): resource acquisition happens inside the same deterministic
|
||||
sequence, and the hook is infallible by signature — a consumer that fails to
|
||||
acquire stores the error, degrades to inert, and surfaces the failure once,
|
||||
terminally, at `finalize` (the run completes; refusal-worthy faults are caught
|
||||
pre-run, at construction/bind time).
|
||||
|
||||
## Current state
|
||||
|
||||
@@ -70,7 +77,8 @@ structural axis, C20, never a numeric sweep param).
|
||||
`trait Node` declares `lookbacks() -> Vec<usize>`, `eval(&mut self, ctx) ->
|
||||
Option<&[Cell]>`, `label() -> String` (default a placeholder every shipped node
|
||||
overrides; overrides carry identifying params so `SMA(2)` vs `SMA(4)` disambiguate
|
||||
in a graph render, #13), and `finalize(&mut self)` (default no-op). There is **no**
|
||||
in a graph render, #13), and the lifecycle pair `initialize(&mut self)` /
|
||||
`finalize(&mut self)` (both default no-op). There is **no**
|
||||
`Node::schema()` — the signature is pre-build data, not a built-node method. The
|
||||
signature is declared once on the value-empty recipe `PrimitiveBuilder`
|
||||
(`aura-core/src/node.rs`), whose `schema()` / `params()` are read pre-build by the
|
||||
@@ -83,9 +91,10 @@ against the producer's `output` at bootstrap. A sink's empty `output` therefore
|
||||
makes it structurally unwireable as an in-graph producer — no edge can bind a field
|
||||
of a zero-output node. The run loop (`aura-engine/src/harness.rs`) debug-asserts
|
||||
`row.len()` equals the declared output width, and that `lookbacks()` arity equals
|
||||
`signature().inputs.len()`. The end-of-stream `finalize` epilogue is realized in
|
||||
`Harness::run` (`aura-engine/src/harness.rs`), which calls `finalize()` once per
|
||||
node in topological order after the source loop drains; `GatedRecorder` and
|
||||
`signature().inputs.len()`. The lifecycle pair is realized in `Harness::run`
|
||||
(`aura-engine/src/harness.rs`): an `initialize()` prologue once per node in
|
||||
topological order before the source loop, and the `finalize()` epilogue after it
|
||||
drains — each pinned by its own once-per-run mirror test; `GatedRecorder` and
|
||||
`SeriesReducer` (`aura-std`) are the folding siblings of the per-cycle `Recorder`
|
||||
(`aura-std/src/recorder.rs`), which survives for the live / `--trace` / test-tap
|
||||
path.
|
||||
@@ -124,8 +133,7 @@ untouched), blanked in the identity projection by `strip_debug_symbols`, dissolv
|
||||
at inline like the name, and surfaced read-only in the graph model and viewer
|
||||
(C22).
|
||||
|
||||
Deferred: the recording sink's own per-cycle allocation — the `Recorder`→`Probe`
|
||||
rename and its accumulate-vs-stream choice — stays open (#77). Naming input ports
|
||||
Deferred: Naming input ports
|
||||
(`PortSpec.name`) makes swap-prone same-kind slots self-documenting but does not add
|
||||
a name-consuming wiring validation; a swapped same-kind wiring is still only
|
||||
kind-checked (#21). The construction op-script vocabulary has no doc-carrying
|
||||
|
||||
Reference in New Issue
Block a user