"Ended" on the period-end reminder records a new period instead of ending one #68
Labels
No Label
P0
P1
P2
release-blocker
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: null/Privacy-Period-Tracker#68
Loading…
Reference in New Issue
No description provided.
Delete Branch "%!s(<nil>)"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found by tracing the reminder pipeline at
93ec5b7.What is true now.
NotificationCopy.actionLabels(core/notifications/.../NotificationCopy.kt:123-133) givesPERIOD_END_CHECK_INthe labels ['Ended','Still going'] in Direct mode and ['Done','Not yet'] otherwise.ReminderWorker.kt:131-139then maps button index 0 toACTION_STARTEDand index 1 toACTION_NOT_YET— for EVERY kind, with no reference to which kind it is building.NotificationActionHandler.kt:37-49mapsACTION_STARTEDtorepository.confirmPeriodStart(today)andACTION_NOT_YETtorepository.recordNotYet(today).So when the app asks 'Is your period over?' (fired when
status is DuringPeriod && dayOfPeriod >= 5,ReminderRules.kt:84-92) and the user taps Ended, the app inserts a NEW period record starting today. Tapping 'Still going' writes a censoringNotYetObservationfor today.CycleRepository.setPeriodEnd(core/data/.../CycleRepository.kt:174) is unreachable from any notification.What it costs. It corrupts the health record — a phantom period start in the middle of a real period — and every forecast built on it afterwards. The user did nothing wrong and has no way to know. This is the most damaging defect currently in the tree.
What to do. Make labels and actions ONE table: a
ReminderAction { STARTED, NOT_YET, ENDED, STILL_GOING }and aReminderButton(action, label)returned together byNotificationCopy.buttons(kind, privacy), so a label can never be paired with the wrong write again. The handler maps ENDED tosetPeriodEndon the open period (the same callTodayViewModel.setEndmakes), and STILL_GOING to no write at all. Carry the action name in the PendingIntent extra rather than deriving it from an index.Traps.
PeriodRecordSource.NOTIFICATION_CONFIRMATIONexists (domain/cycle/.../Cycle.kt:6) but the handler writesMANUAL— use it. A notification already sitting in a user's shade at upgrade time carries the old action strings; parse them as unknown and write nothing rather than guessing.Verify:
a period-end check-in offers Ended and Still going and no start actioninNotificationCopyTest, andENDED closes the open period on the reminder dayplusSTILL_GOING writes nothingin a newapp/src/test/kotlin/dev/privacyllc/period/notifications/NotificationActionHandlerTest.kt.