A user whose cycles run 28 +/- 1 was predicted to within a day and told,
five times in six, that the app was only moderately sure. Measured: High
appeared in 15.7% of her forecasts once she had eight cycles logged.
The cause was an asymmetry in confidence(). With no scored forecasts the
accuracy term was a flat 0.92 and she scored 0.64 -- High. The moment
real errors arrived, averaging 0.9 days against a cycle that varies by a
day, the term fell to 0.735 and she scored 0.51 -- Medium, and Medium
from then on. Being demonstrably as accurate as her cycle allows rated
worse than never having been checked, which is §16's "your predictions
are getting better" contradicted by the label printed next to it.
So the yardstick is now what the forecast already admits it does not
know. For a Laplace distribution E|X| = b: the mean error of a perfectly
calibrated forecast IS its scale, so errors inside the scale are the
model working and only the excess counts. The constant is 1.0 by that
identity, not by tuning.
Real inaccuracy is still punished and still visible: it arrives through
agreement, because scored error already feeds the scale. A run of bad
forecasts widens the window and drops the confidence beside it, together,
for the same reason.
MEDIUM_THRESHOLD moves 0.30 -> 0.40 as part of the same change, not as a
second opinion. The old thresholds sat where they had to sit while every
score was deflated; with scores no longer deflated, 0.30 stopped
separating anything and the §51 variable user began reading Medium beside
an eleven-day window. Tightening AGREEMENT_SENSITIVITY was tried first
across three values and rejected -- agreement multiplies into every
score, so every value that quietened the variable user also took High
from the stable one, and 1.0 broke §51 outright.
Measured at 400 seeds, stable users k>=8: High 15.7% -> 88.5%. Variable
user stays Low 93% of the time and reads High in 0.1%. Accuracy and
window widths are untouched by this commit -- it changes what the app
says about its forecasts, not the forecasts.
modelVersion -> personal-2, so §16's history spans the change rather than
comparing two engines' errors as though one engine made them.
closes#51
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>