# C5 — Freshness-gated recompute and sample-and-hold **Guarantee.** The `cycle_id` advances everywhere (a cheap counter), but a node re-evaluates only when ≥1 of its own inputs is fresh this cycle (detected by run-count); otherwise it holds its last output. Stale inputs contribute their last (held) value. **Forbids.** Recomputing every node every cycle ("push all" is true for the *clock*, not for *recompute*); treating a held value as missing. **Why.** Total recompute does not scale to many sparse high-frequency sources; freshness-gating is the performance discipline that keeps the synchronous model fast. ## Current state Freshness is a run-count epoch. Each input slot carries `SlotState { fresh_at, last_ts }` (`crates/aura-engine/src/harness.rs`); a slot is fresh this cycle iff `fresh_at == cycle_id`. The firing predicate `fires` re-evaluates a node when any `Firing::Any` input is fresh this cycle, or when a barrier group completes (≥1 member fresh this cycle and every member carrying `last_ts == ts`) — the barrier / co-freshness machinery itself is C6. A node that does not fire pushes nothing, so downstream consumers keep reading the last value via `window[0]`: sample-and-hold falls out of the push model rather than being a separate mechanism. A held value is a real past value, never treated as missing. ## See also - [C6](c06-firing-policy.md) — the firing predicate and the barrier / co-freshness rule this gating builds on. - [C1](c01-determinism.md) — freshness is a deterministic function of `cycle_id`, so gating never perturbs the bit-identical run. - [C2](c02-causality.md) — a held value is past data, not look-ahead.