Privacy-Period-Tracker/domain/prediction
null 1761bf33a0 fix: account for not knowing her centre, not just her spread
The window promises to hold the actual start four times in five. For a
user whose cycles genuinely disagree it was delivering closer to three in
four, and the missing piece was structural rather than a mistuned knob:
the spread estimate measured how far her cycles fall from a centre and
never asked how well that centre is known. With four intervals it is not
known well.

The correction is the textbook one -- a future draw around an ESTIMATED
centre is wider than around the true centre by sqrt(1 + 1/n) -- taken over
the effective sample size, because recency weighting means eight intervals
do not contribute eight intervals' worth of evidence.

Applied only to the branch that actually estimates from a sample. The
zero- and one-interval branches are hand-tuned constants standing in for
total uncertainty when there is nothing to estimate from, and multiplying
those would have counted the same doubt twice -- measured, that mistake
widened a first-cycle window by a day and a half and bought nothing.

Not a knob: 1.22x at two intervals, 1.06x at eight, 1.03x at fifteen,
fixed by the arithmetic rather than chosen to reach a number.

The issue this closes was filed on a wrong measurement, and that is worth
recording. A 40-seed run showed mid-learning coverage collapsing to 57.5%;
at 400 seeds the same cells sit at 73-85%, and the collapse was one
unlucky cell rather than a defect. What survived the larger sample is
smaller and real, and is what this fixes: variable-user coverage 75.6% ->
76.8% late, 72.2% -> 73.3% mid-learning.

The floor in the guard stays below the promise on purpose. For an
intrinsically unpredictable cycle the last few points would cost width she
cannot afford, and the width ceiling in the same file is the other jaw of
that vice.

Fixture window returns to 4.56 days, exactly where it was before this
batch -- so across the three calibration commits the engine now predicts
the §51 fleet at MAE 0.44 instead of 0.67, with 9/9 coverage, for the same
window it always had.

closes #52

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-20 16:30:00 -05:00
..
src fix: account for not knowing her centre, not just her spread 2026-08-20 16:30:00 -05:00
build.gradle.kts chore: adopt the project template and add the Kotlin/Compose skeleton 2026-08-18 02:16:47 -05:00