mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-10 13:22:14 +00:00
feat(cycle): cycle-phase correlation insight + Coach phase dimension
Add the menstrual-cycle phase as a channel in the existing FDR-guarded correlation machinery, the same way rated mood factors were folded in — no new statistics, the same Welch + Benjamini-Hochberg pipeline, the same day floors and q = 0.10 gate. Two complementary mechanisms, both confined to a gender-gated surface: - a categorical luteal-vs-follicular contrast per outcome metric (resting heart rate, HRV, sleep, steps, weight, basal/wrist/skin temperature), surfacing one headline finding (resting-heart-rate-by-phase, falling back to HRV); and - the continuous phase ordinal folded into the lagged-Pearson matrix. Phase never reaches the general correlations route — the temperature channels held out of the general matrix are un-blocked only here, behind the cycle gate, so a reproductive inference can never leak onto a non-gated surface. Every row shows n, effect size, p and q; nothing is fabricated on thin data and nothing is framed as causal. Surface it through a new gated GET /api/cycle/insights and a drop-in card that mirrors the mood-factor crosstab. Add a cycle dimension to the Coach snapshot: current phase + day-of-cycle, the next predicted event (period range + confidence + method, fertile window goal-gated), and the headline phase finding — present only for a cycle-enabled account, so a non-cycle snapshot is unchanged. A new ground rule keeps the Coach descriptive: never contraception-grade, never a "safe day" claim. OpenAPI regenerated; phase-correlation + snapshot-inclusion tests added; copy localised across all six locales. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
5f485ca780
commit
77a652a47c
18 files changed
+2057
-4
No files matched your search
@@ -578,6 +578,27 @@ paths:
|
||||
"403": *a2
|
||||
"422": *a3
|
||||
"429": *a4
|
||||
/api/cycle/insights:
|
||||
get:
|
||||
tags:
|
||||
- Cycle
|
||||
summary: Cycle-phase correlation insights (v1.15.0)
|
||||
description: "FDR-guarded luteal-vs-follicular phase contrast per outcome metric (RHR / HRV / sleep / steps / weight /
|
||||
temperatures), plus the single headline finding (resting-heart-rate-by-phase, falling back to HRV). The same
|
||||
Welch t-test + Benjamini-Hochberg machinery the mood-factor crosstab runs; only rows with p < 0.05 AND q ≤ 0.10
|
||||
surface. Strictly gender-gated — phase never appears on the general `/api/insights/correlations` route.
|
||||
Observational only, never causal. Gated: `cycle.disabled` 403 when the feature is off."
|
||||
responses:
|
||||
"200":
|
||||
description: Phase-correlation rows + headline.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/CycleInsightsEnvelope"
|
||||
"401": *a1
|
||||
"403": *a2
|
||||
"422": *a3
|
||||
"429": *a4
|
||||
/api/cycle/cycles/{id}:
|
||||
delete:
|
||||
tags:
|
||||
@@ -5289,6 +5310,180 @@ components:
|
||||
- data
|
||||
- error
|
||||
additionalProperties: false
|
||||
CycleInsightsEnvelope:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
rows:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/CyclePhaseCrosstabRow"
|
||||
headline:
|
||||
anyOf:
|
||||
- $ref: "#/components/schemas/CyclePhaseCrosstabRow"
|
||||
- type: "null"
|
||||
lagged:
|
||||
type: object
|
||||
properties:
|
||||
discovered:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/CyclePhaseLaggedPair"
|
||||
pairsTested:
|
||||
type: integer
|
||||
minimum: -9007199254740991
|
||||
maximum: 9007199254740991
|
||||
fdrQ:
|
||||
type: number
|
||||
minPairs:
|
||||
type: integer
|
||||
minimum: -9007199254740991
|
||||
maximum: 9007199254740991
|
||||
required:
|
||||
- discovered
|
||||
- pairsTested
|
||||
- fdrQ
|
||||
- minPairs
|
||||
additionalProperties: false
|
||||
contrast:
|
||||
type: object
|
||||
properties:
|
||||
high:
|
||||
type: string
|
||||
const: LUTEAL
|
||||
low:
|
||||
type: string
|
||||
const: FOLLICULAR
|
||||
required:
|
||||
- high
|
||||
- low
|
||||
additionalProperties: false
|
||||
windowDays:
|
||||
type: integer
|
||||
minimum: -9007199254740991
|
||||
maximum: 9007199254740991
|
||||
cyclesObserved:
|
||||
type: integer
|
||||
minimum: -9007199254740991
|
||||
maximum: 9007199254740991
|
||||
required:
|
||||
- rows
|
||||
- headline
|
||||
- lagged
|
||||
- contrast
|
||||
- windowDays
|
||||
- cyclesObserved
|
||||
additionalProperties: false
|
||||
error:
|
||||
type: "null"
|
||||
meta:
|
||||
type: object
|
||||
properties:
|
||||
requestId:
|
||||
type: string
|
||||
additionalProperties: false
|
||||
required:
|
||||
- data
|
||||
- error
|
||||
additionalProperties: false
|
||||
CyclePhaseCrosstabRow:
|
||||
type: object
|
||||
properties:
|
||||
metricKey:
|
||||
type: string
|
||||
enum:
|
||||
- restingHeartRate
|
||||
- heartRateVariability
|
||||
- sleepDuration
|
||||
- steps
|
||||
- weight
|
||||
- basalBodyTemp
|
||||
- wristTemperature
|
||||
- skinTemperature
|
||||
display:
|
||||
type: string
|
||||
enum:
|
||||
- hours
|
||||
- steps
|
||||
- bpm
|
||||
- ms
|
||||
- kg
|
||||
- celsius
|
||||
lutealDays:
|
||||
type: integer
|
||||
minimum: -9007199254740991
|
||||
maximum: 9007199254740991
|
||||
follicularDays:
|
||||
type: integer
|
||||
minimum: -9007199254740991
|
||||
maximum: 9007199254740991
|
||||
lutealAvg:
|
||||
type: number
|
||||
follicularAvg:
|
||||
type: number
|
||||
delta:
|
||||
type: number
|
||||
pValue:
|
||||
type: number
|
||||
qValue:
|
||||
type: number
|
||||
confidence:
|
||||
type: string
|
||||
enum:
|
||||
- low
|
||||
- medium
|
||||
- high
|
||||
required:
|
||||
- metricKey
|
||||
- display
|
||||
- lutealDays
|
||||
- follicularDays
|
||||
- lutealAvg
|
||||
- follicularAvg
|
||||
- delta
|
||||
- pValue
|
||||
- qValue
|
||||
- confidence
|
||||
additionalProperties: false
|
||||
description: One FDR-surviving luteal-vs-follicular contrast for an outcome metric. `delta = lutealAvg − follicularAvg`.
|
||||
Observational, never causal.
|
||||
CyclePhaseLaggedPair:
|
||||
type: object
|
||||
properties:
|
||||
behaviour:
|
||||
type: string
|
||||
outcome:
|
||||
type: string
|
||||
n:
|
||||
type: integer
|
||||
minimum: -9007199254740991
|
||||
maximum: 9007199254740991
|
||||
r:
|
||||
type: number
|
||||
pValue:
|
||||
type: number
|
||||
qValue:
|
||||
type: number
|
||||
interpretation:
|
||||
type: string
|
||||
lagDays:
|
||||
type: integer
|
||||
minimum: -9007199254740991
|
||||
maximum: 9007199254740991
|
||||
required:
|
||||
- behaviour
|
||||
- outcome
|
||||
- n
|
||||
- r
|
||||
- pValue
|
||||
- qValue
|
||||
- interpretation
|
||||
- lagDays
|
||||
additionalProperties: false
|
||||
description: One FDR-surviving lagged-Pearson pair from the continuous CYCLE_PHASE ordinal × outcome matrix (mechanism
|
||||
B). Descriptive, never causal.
|
||||
CycleProfileEnvelope:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
Reference in new issue
Block a user