feat(insights): make sleep debt a configurable source ladder with a computed explainer

Generalise sleep debt onto the existing per-metric source-priority picker
(a new sleepDebt ladder, native-above-computed, default WHOOP > Oura > Polar >
computed) instead of assuming one provider. The rhythm read resolves the active
source off the ladder and carries it on the DTO; when the active source is our
own COMPUTED engine — every user today, since no provider ships a native
sleep-debt balance — the Sleep page explains what the figure means and that it
differs from a wearable's native number. The computed model itself is unchanged
and correct (a short rolling balance of need minus sleep, surplus-credited);
only stale comments that still referenced the old 14-night window are corrected.
This commit is contained in:
Marc-André Bombeck committed 2026-06-28 16:04:22 +02:00
1 parent c862b4880f
commit d570d558fa
15 files changed
+245 -23

No files matched your search

+4 -2
View File
@@ -2691,7 +2691,8 @@
"caption": "Kumuliertes Defizit der letzten {nights} Nächte",
"clearValue": "Ausgeglichen",
"clearCaption": "Kein aufgelaufenes Defizit über die letzten {nights} Nächte",
"learning": "Dein Schlaf wird noch erfasst — {counted} Nächte bisher, noch {remaining} für eine verlässliche Bilanz."
"learning": "Dein Schlaf wird noch erfasst — {counted} Nächte bisher, noch {remaining} für eine verlässliche Bilanz.",
"computedInfo": "Das ist HealthLogs eigene Schätzung: eine gleitende Bilanz aus Bedarf minus Schlaf über die letzten Nächte, die Aufholschlaf wieder abbaut. Sie kann vom nativen Schlafdefizit eines Wearables abweichen, das ein eigenes Bedarfsmodell nutzt."
},
"average": {
"title": "Durchschnitt pro Nacht",
@@ -4043,7 +4044,8 @@
"skinTemperature": "Hauttemperatur",
"respiratoryRate": "Atemfrequenz",
"recovery": "Erholung",
"stress": "Stress"
"stress": "Stress",
"sleepDebt": "Schlafdefizit"
},
"sourceLabels": {
"WITHINGS": "Withings",
+4 -2
View File
@@ -2691,7 +2691,8 @@
"caption": "Cumulative shortfall over the last {nights} nights",
"clearValue": "All caught up",
"clearCaption": "No accumulated shortfall over the last {nights} nights",
"learning": "Still learning your sleep — {counted} nights so far, {remaining} more to read a reliable balance."
"learning": "Still learning your sleep — {counted} nights so far, {remaining} more to read a reliable balance.",
"computedInfo": "This is HealthLog's own estimate: a rolling balance of need minus sleep over recent nights, with catch-up sleep paying it down. It can differ from a wearable's native sleep-debt figure, which uses its own need model."
},
"average": {
"title": "Average per night",
@@ -4043,7 +4044,8 @@
"skinTemperature": "Skin temperature",
"respiratoryRate": "Respiratory rate",
"recovery": "Recovery",
"stress": "Stress"
"stress": "Stress",
"sleepDebt": "Sleep debt"
},
"sourceLabels": {
"WITHINGS": "Withings",
+4 -2
View File
@@ -2691,7 +2691,8 @@
"caption": "Déficit acumulado de las últimas {nights} noches",
"clearValue": "Al día",
"clearCaption": "Sin déficit acumulado en las últimas {nights} noches",
"learning": "Aún estamos midiendo tu sueño — {counted} noches hasta ahora, faltan {remaining} para un balance fiable."
"learning": "Aún estamos midiendo tu sueño — {counted} noches hasta ahora, faltan {remaining} para un balance fiable.",
"computedInfo": "Esta es la estimación propia de HealthLog: un balance móvil de la necesidad menos el sueño de las últimas noches, que el sueño de recuperación va reduciendo. Puede diferir de la cifra de deuda de sueño nativa de un wearable, que usa su propio modelo de necesidad."
},
"average": {
"title": "Media por noche",
@@ -4043,7 +4044,8 @@
"skinTemperature": "Temperatura de la piel",
"respiratoryRate": "Frecuencia respiratoria",
"recovery": "Recuperación",
"stress": "Estrés"
"stress": "Estrés",
"sleepDebt": "Deuda de sueño"
},
"sourceLabels": {
"WITHINGS": "Withings",
+4 -2
View File
@@ -2691,7 +2691,8 @@
"caption": "Déficit cumulé sur les {nights} dernières nuits",
"clearValue": "À jour",
"clearCaption": "Aucun déficit cumulé sur les {nights} dernières nuits",
"learning": "Votre sommeil est encore en cours d'analyse — {counted} nuits jusqu'ici, encore {remaining} pour un bilan fiable."
"learning": "Votre sommeil est encore en cours d'analyse — {counted} nuits jusqu'ici, encore {remaining} pour un bilan fiable.",
"computedInfo": "Il s'agit de l'estimation propre à HealthLog : un solde glissant entre le besoin et le sommeil des dernières nuits, que le sommeil de récupération réduit. Elle peut différer de la dette de sommeil native d'un wearable, qui utilise son propre modèle de besoin."
},
"average": {
"title": "Moyenne par nuit",
@@ -4043,7 +4044,8 @@
"skinTemperature": "Température cutanée",
"respiratoryRate": "Fréquence respiratoire",
"recovery": "Récupération",
"stress": "Stress"
"stress": "Stress",
"sleepDebt": "Dette de sommeil"
},
"sourceLabels": {
"WITHINGS": "Withings",
+4 -2
View File
@@ -2691,7 +2691,8 @@
"caption": "Deficit cumulato nelle ultime {nights} notti",
"clearValue": "In pari",
"clearCaption": "Nessun deficit accumulato nelle ultime {nights} notti",
"learning": "Stiamo ancora misurando il tuo sonno — {counted} notti finora, ne mancano {remaining} per un bilancio affidabile."
"learning": "Stiamo ancora misurando il tuo sonno — {counted} notti finora, ne mancano {remaining} per un bilancio affidabile.",
"computedInfo": "Questa è la stima propria di HealthLog: un bilancio mobile tra fabbisogno e sonno delle ultime notti, che il sonno di recupero riduce. Può differire dal dato di debito di sonno nativo di un dispositivo indossabile, che usa un proprio modello di fabbisogno."
},
"average": {
"title": "Media per notte",
@@ -4043,7 +4044,8 @@
"skinTemperature": "Temperatura cutanea",
"respiratoryRate": "Frequenza respiratoria",
"recovery": "Recupero",
"stress": "Stress"
"stress": "Stress",
"sleepDebt": "Debito di sonno"
},
"sourceLabels": {
"WITHINGS": "Withings",
+4 -2
View File
@@ -2691,7 +2691,8 @@
"caption": "Skumulowany niedobór z ostatnich {nights} nocy",
"clearValue": "Na bieżąco",
"clearCaption": "Brak skumulowanego niedoboru w ostatnich {nights} nocach",
"learning": "Wciąż analizujemy Twój sen — {counted} nocy do tej pory, jeszcze {remaining}, aby uzyskać wiarygodny bilans."
"learning": "Wciąż analizujemy Twój sen — {counted} nocy do tej pory, jeszcze {remaining}, aby uzyskać wiarygodny bilans.",
"computedInfo": "To własne oszacowanie HealthLog: ruchomy bilans potrzeby snu minus sen z ostatnich nocy, który sen nadrabiający zmniejsza. Może różnić się od natywnego wskaźnika długu snu z urządzenia, które korzysta z własnego modelu zapotrzebowania."
},
"average": {
"title": "Średnia na noc",
@@ -4043,7 +4044,8 @@
"skinTemperature": "Temperatura skóry",
"respiratoryRate": "Częstość oddechów",
"recovery": "Regeneracja",
"stress": "Stres"
"stress": "Stres",
"sleepDebt": "Dług snu"
},
"sourceLabels": {
"WITHINGS": "Withings",