A scored snapshot outlives the period it was scored against #47

Closed
opened 2026-08-20 16:13:28 -05:00 by null · 0 comments
Owner

Found by tracing the learning loop at 93ec5b7.

What is true now. CycleRepository.editPeriod and deletePeriod never touch scored prediction_records. Editing a confirmed start to correct a mistake, or deleting it outright, leaves the old actualStartDate and absoluteErrorDays in place. PredictionRecordDao.recentAbsoluteErrors() keeps feeding that error into PredictionInput.recentAbsoluteErrors, so the engine widens its window from a measurement about a period the user has since corrected or withdrawn — and §16's accuracy card reports it to her.

What it costs. The engine learns from a fact the user has retracted; the accuracy figures describe a history that no longer exists.

What to do. Add scoredAgainst(actual) and deleteById(id) queries to PredictionRecordDao. In editPeriod, after the update and before snapshotForecast, re-score each snapshot recorded against the old start against the new one; in deletePeriod, retract them.

Traps. Match on actualStartDate, not basedOnLastConfirmedPeriodId — the latter is null on the not-yet and delete paths. Re-scoring must not be able to fabricate a better history: predictedStartDate stays immutable (so a correction worsens the figure as readily as it improves one) and the same backfill rule that gates first scoring must gate re-scoring, retracting rather than recomputing when the corrected start falls before the forecast's lineage began. Depends on the lineage fix landing first, since that gate reads generatedAt as a lineage origin.

Verify: editing a period re-scores the forecast that was scored against it, editing a period to before its forecast existed retracts the score and deleting a period retracts the score recorded against it in CycleRepositoryTest.kt.

Found by tracing the learning loop at 93ec5b7. **What is true now.** `CycleRepository.editPeriod` and `deletePeriod` never touch scored `prediction_records`. Editing a confirmed start to correct a mistake, or deleting it outright, leaves the old `actualStartDate` and `absoluteErrorDays` in place. `PredictionRecordDao.recentAbsoluteErrors()` keeps feeding that error into `PredictionInput.recentAbsoluteErrors`, so the engine widens its window from a measurement about a period the user has since corrected or withdrawn — and §16's accuracy card reports it to her. **What it costs.** The engine learns from a fact the user has retracted; the accuracy figures describe a history that no longer exists. **What to do.** Add `scoredAgainst(actual)` and `deleteById(id)` queries to `PredictionRecordDao`. In `editPeriod`, after the update and before `snapshotForecast`, re-score each snapshot recorded against the old start against the new one; in `deletePeriod`, retract them. **Traps.** Match on `actualStartDate`, not `basedOnLastConfirmedPeriodId` — the latter is null on the not-yet and delete paths. Re-scoring must not be able to fabricate a better history: `predictedStartDate` stays immutable (so a correction worsens the figure as readily as it improves one) and the same backfill rule that gates first scoring must gate re-scoring, retracting rather than recomputing when the corrected start falls before the forecast's lineage began. Depends on the lineage fix landing first, since that gate reads `generatedAt` as a lineage origin. Verify: `editing a period re-scores the forecast that was scored against it`, `editing a period to before its forecast existed retracts the score` and `deleting a period retracts the score recorded against it` in CycleRepositoryTest.kt.
null added this to the Batch 09 — Prediction Science & Hardening milestone 2026-08-20 16:13:28 -05:00
null added the
P1
label 2026-08-20 16:13:28 -05:00
null closed this issue 2026-08-20 16:13:57 -05:00
Sign in to join this conversation.
No Label
P0
P1
P2
release-blocker
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: null/Privacy-Period-Tracker#47
No description provided.