fix(medications): key the dedup pin guard on persisted attribution, not a timestamp shape

Every standalone intake anchors its slot on the take time since
v1.15.19, so guarding the nightly dedup on that shape excluded ordinary
drift duplicates from collapsing — the original point of the sweep.
Releasing a pinned dose now persists the user's choice on the row, the
dedup and the repair script key their exclusion on that flag, the read
model reports a released row as deliberately off-schedule instead of
re-snapping it within the anchor epsilon, and the attributed badge only
shows on rows actually bound to a slot. A few fixture names and stray
comments also drop personal references.
This commit is contained in:
Marc-André Bombeck committed 2026-06-10 17:33:56 +02:00
1 parent 04765ea8ac
commit a5650d0617
11 files changed
+267 -93

No files matched your search

+11 -3
View File
@@ -113,7 +113,11 @@ interface IntakeRow {
skipped: boolean;
source: string;
createdAt: Date;
/** v1.16.0 — slot-binding provenance; USER_PIN = deliberate user pin. */
/**
* v1.16.0 — slot-binding provenance; USER_PIN = the user fixed the
* attribution by hand (pin onto a slot OR released as deliberately
* ad-hoc with `scheduledFor === takenAt`).
*/
attributionSource: string;
}
@@ -121,8 +125,12 @@ interface IntakeRow {
* Rank a row for the slot-winner pick: pinned take (3) > taken (2) >
* skipped (1) > pending (0). `takenAt` set and `skipped` together still
* counts as taken — the recorded dose dominates. The USER_PIN rung
* (v1.16.0) mirrors the dedup worker: a deliberate "diesem Slot
* zuordnen" decision is the dose of record for its slot.
* (v1.16.0) mirrors the dedup worker's rank
* (`src/lib/medications/intake-slot-dedup.ts`). The worker additionally
* excludes USER_PIN rows from its SNAP clusters (the snap could move a
* user-fixed anchor); this script needs no such exclusion — its groups
* are exact-instant, so a USER_PIN row in a group already sits ON its
* fixed anchor and the rank keeps it as the dose of record there.
*/
function rowRank(row: IntakeRow): number {
if (row.takenAt !== null) {