RetentionWindow() trimmed offline-rule samples to 1, but Check's offline
branch reads points[len-Duration:] and needs Duration samples. The window
never filled, boundCheck always returned "passed", and offline alerts never
fired a notification — while other alert types worked. Offline rules now
retain Duration samples (cycle rules still keep 1, matching their last-sample
lookback).
Fixes the prior over-correction in RetentionWindow; corrects the test that
had pinned the buggy offline=1 value, and adds offline + combined-rule
regression tests driving the real trim loop.