Whether a bin's trailing dB history shows a genuine RUN-AWAY trend — the ramp gate
PersistenceTracker.push confirms on. A window qualifies only when ALL hold
(thresholds from t, defaulting to today's values so existing single-arg call sites +
the web-ui re-export stay green):
no hop dips below −t.growthMaxDipDb (monotone, with jitter allowance);
the end-to-end rise clears t.growthMinTotalRiseDb;
no single hop carries more than t.growthMaxSingleFrameShare of that rise
(a step is an attack, not a ramp — issue #106);
the least-squares slope still clears t.growthMinDbPerFrame (kept as the
original #91 bar; implied by 1+2 on clean data, cheap belt-and-braces on noisy).
Fewer than two samples is never "growing" — there's no trend to measure yet. A window
that catches a run-away EMERGING from the floor (flat noise, then the ramp) fails 3
until the ramp fills the window — a deliberate 2–3 frame confirmation latency
(~100–300 ms at RTA hop rates) in exchange for never alarming on played music.
Whether a bin's trailing dB history shows a genuine RUN-AWAY trend — the ramp gate PersistenceTracker.push confirms on. A window qualifies only when ALL hold (thresholds from
t, defaulting to today's values so existing single-arg call sites + the web-ui re-export stay green):t.growthMaxDipDb(monotone, with jitter allowance);t.growthMinTotalRiseDb;t.growthMaxSingleFrameShareof that rise (a step is an attack, not a ramp — issue #106);t.growthMinDbPerFrame(kept as the original #91 bar; implied by 1+2 on clean data, cheap belt-and-braces on noisy).Fewer than two samples is never "growing" — there's no trend to measure yet. A window that catches a run-away EMERGING from the floor (flat noise, then the ramp) fails 3 until the ramp fills the window — a deliberate 2–3 frame confirmation latency (~100–300 ms at RTA hop rates) in exchange for never alarming on played music.