feat(cycle): exclude disturbed temperatures from the symptothermal engine

A fever, illness, alcohol or a late/short-sleep reading can fake or mask
a temperature rise. Add a per-day `temperatureExcluded` flag on
CycleDayLog (migration 0156): when set, the engine drops the reading from
the cover-line baseline AND the shift evaluation, so a spike neither
fabricates nor masks a rise (Sensiplan: the cover line is drawn over the
last six unbracketed values).

Wired end to end — schema + Prisma, the engine's `detectTempShift`
filter, the Zod input/patch schemas, the day-log upsert (partial merge +
change detection), the read DTO, the calendar/insights/coach selects, the
backup round-trip, and the OpenAPI contract (a new boolean on the day-log
and calendar-day DTOs for the iOS client). The log-day sheet gains a
"mark reading as disturbed" toggle that appears once a temperature is
entered, translated across all six locales.

Citation: de.wikipedia "Symptothermale Methode"; myNFP "Temperaturkurve
auswerten" — Störfaktor bracketing.
This commit is contained in:
Marc-André Bombeck committed 2026-06-14 15:04:25 +02:00
1 parent cd55c60fae
commit 4bfe9f11d7
27 files changed
+199 -7

No files matched your search

+2
View File
@@ -99,6 +99,7 @@ export const GET = apiHandler(async (request: NextRequest) => {
date: true,
flow: true,
basalBodyTempC: true,
temperatureExcluded: true,
ovulationTest: true,
cervicalMucus: true,
_count: { select: { symptomLinks: true } },
@@ -125,6 +126,7 @@ export const GET = apiHandler(async (request: NextRequest) => {
date: l.date,
flow: l.flow,
basalBodyTempC: l.basalBodyTempC,
temperatureExcluded: l.temperatureExcluded,
ovulationTest: l.ovulationTest,
cervicalMucus: l.cervicalMucus,
hasSymptoms: l._count.symptomLinks > 0,
+1
View File
@@ -90,6 +90,7 @@ export const GET = apiHandler(async () => {
date: true,
flow: true,
basalBodyTempC: true,
temperatureExcluded: true,
ovulationTest: true,
cervicalMucus: true,
symptomLinks: { select: { symptom: { select: { key: true } } } },