From 521a16e56f36331b1b4e76acc85bdb40dad2cf8d Mon Sep 17 00:00:00 2001 From: Brummel Date: Thu, 4 Jun 2026 18:23:04 +0200 Subject: [PATCH] docs(aura-std): document Add/LinComb firing policy + multi-row-per-ts shape MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolves the two spec_gaps from the cycle-0008 fieldtest (docs/specs/fieldtest-0008-sum-combinators.md), the same class the 0007 fieldtest raised for SimBroker (and which e9f4352 patched there) — the combinators shipped without the equivalent note: - per-input firing policy: both Add and every LinComb leg are Firing::Any (mode-A as-of join) — the node fires on every cycle in which any leg is fresh, once all legs have a value, pairing the fresh leg with the held value of the others; None until all present (no cold-leg-as-0.0). A consumer combining different-rate sources (e.g. an M5 signal with a daily-bias leg) needs this to predict whether the bias is held-and-combined every cycle (mode A, what ships) or only on rare both-fresh cycles (mode B). - multi-row-per-timestamp: a fired node emits one row per *cycle*, and two sources sharing a timestamp are two distinct cycles (C4 tie-break by source order), so a recorded combined stream may carry >1 row per timestamp. Correct and forced by C4/C5; ratified here, now stated on the surface so "one row per timestamp" is not silently assumed. Doc-only change; no behaviour change. Verified: RUSTDOCFLAGS="-D warnings" cargo doc -p aura-std clean (intra-doc links to aura_core::Firing::Any resolve); clippy --all-targets -D warnings clean; cargo test -p aura-std 14 passed. refs #11 --- crates/aura-std/src/add.rs | 10 ++++++++++ crates/aura-std/src/lincomb.rs | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/crates/aura-std/src/add.rs b/crates/aura-std/src/add.rs index 2e58cca..cc1fac2 100644 --- a/crates/aura-std/src/add.rs +++ b/crates/aura-std/src/add.rs @@ -6,6 +6,16 @@ use aura_core::{Ctx, FieldSpec, Firing, InputSpec, Node, NodeSchema, Scalar, Sca /// Two-input f64 sum: input 0 plus input 1. Emits `None` until both inputs /// have a value. +/// +/// # Firing and warm-up +/// +/// Both inputs are [`Firing::Any`](aura_core::Firing::Any) — a *mode-A as-of +/// join*: the node fires on every cycle in which either leg is fresh (once both +/// have produced a value), pairing the fresh leg with the held value of the +/// other. Until both legs have a value it emits `None` (no cold-leg-as-`0.0`). +/// With heterogeneous sources sharing a timestamp (same `ts` from two sources = +/// two distinct cycles, C4), a fired node emits one row per *cycle*, so a +/// recorded combined stream may carry more than one row per timestamp. pub struct Add { out: [Scalar; 1], } diff --git a/crates/aura-std/src/lincomb.rs b/crates/aura-std/src/lincomb.rs index 8134016..ad2baad 100644 --- a/crates/aura-std/src/lincomb.rs +++ b/crates/aura-std/src/lincomb.rs @@ -13,6 +13,16 @@ use aura_core::{Ctx, FieldSpec, Firing, InputSpec, Node, NodeSchema, Scalar, Sca /// construction parameters that configure the node and fix its arity /// (`weights.len()` inputs, in slot order). Emits `None` until *all* inputs /// have a value. +/// +/// # Firing and warm-up +/// +/// Every input is [`Firing::Any`](aura_core::Firing::Any) — a *mode-A as-of +/// join*: the node fires on every cycle in which any leg is fresh (once all +/// legs have produced a value), pairing each fresh leg with the held value of +/// the others. Until every leg has a value it emits `None` (no cold-leg-as- +/// `0.0`). With heterogeneous sources sharing a timestamp (same `ts` from two +/// sources = two distinct cycles, C4), a fired node emits one row per *cycle*, +/// so a recorded combined stream may carry more than one row per timestamp. pub struct LinComb { weights: Vec, out: [Scalar; 1],