"An accumulator guard that resets on a transient flicker never fires"
▸ SYMPTOM
You add a cumulative guard to stop some exploit — a "max total rise per consecutive step-up run" budget to stop a character elevatoring up a lattice-free voxel cliff by chain-stepping its short risers — and it is provably in the build, yet it never blocks. Telemetry shows dozens of chained step-ups and zero budget-blocks: 47 step-ups, 1.78 m of rise in half a second, guard silent the whole time.
▸ CAUSE
A per-run accumulator that resets on a transient state flicker never fills. The reset keeps zeroing the counter faster than the episode can accumulate into it. There are usually two holes, both the same shape:
1. An over-eager reset on a flickering signal. A rise budget cleared on any airborne tick. But sprinting up a voxel staircase flickers Ground → Air for one or two ticks at every tread lip — a single-tick ground-probe miss over the riser seam — so the budget zeroed at every riser and never grew.
2. A phantom-progress reset. A "walked a flat stretch, clear the budget" reset accrued the intended pre-collision velocity delta each tick. So sprinting straight into a wall — the move dead-stopped by collision, realized displacement ~0 — still banked a full stride of phantom "flat" distance and cleared the budget while the body was pinned to the face.
Both holes reset on a per-tick proxy (any-air, intended-velocity) that the episode itself trips constantly.
▸ FIX
Reset only on a signal that truly ends the episode:
-
Gate the reset on a sustained signal, not an instantaneous one. Require continuous air for ~0.2 s before clearing the rise budget, so a real jump or fall resets but a sub-tick
Ground → Airflicker does not:snippetif ( continuousAirTime >= 0.2f ) riseBudget = 0f; // real airborne episode — clear // a 1–2 tick flicker never reaches the thresholdBonus: a jump already hard-clears coyote grace (it sets the grounded timer to a large sentinel), so gating on that same timer makes jumps reset instantly while flickers do not.
-
Accrue realized progress, not intended progress. Base the flat-stride reset on realized net-forward displacement — the post-collision position delta projected on the move direction, clamped
>= 0. A dead-stop into a wall and a lateral wall-slide then both add ~nothing, so a pinned body can no longer launder a phantom stride into a reset.
▸ WHY IT WORKS
An accumulator meant to survive a contiguous episode must only reset on a signal that genuinely marks the episode's end. Sustained air and realized forward progress are those signals; any-air and intended-velocity are per-tick proxies the exploit trips on every riser or every frame against a wall. Swapping each reset condition from the proxy to the true end-of-episode signal lets the counter finally accumulate and the guard fire.
General lesson: before trusting any accumulator guard, audit every reset path. One reset that fires on a transient proxy is enough to silently defeat the whole guard.
- Published