Health Score
@loop/health-score calculates a composite 0–100 health score by combining data from three sources: wearables (40%), check-ins (30%), and lab results (30%).
Installation
pnpm add @loop/health-scoreQuick Start
import { calculateHealthScore } from '@loop/health-score';
const { score, breakdown } = calculateHealthScore({
wearables: {
ouraReadiness: 82,
whoopRecovery: 75,
hrv: 45,
},
checkIns: {
energy: 7,
mood: 8,
focus: 6,
sleepQuality: 8,
},
labs: {
biomarkerCount: 15,
biomarkerScore: 78,
},
});
console.log(score); // 77
console.log(breakdown); // { wearables: 79, checkIns: 73, labs: 78 }Scoring Weights
| Source | Weight | Data |
|---|---|---|
| Wearables | 40% | Oura readiness, Whoop recovery, HRV |
| Check-ins | 30% | Energy, mood, focus, sleep quality (0–10 scale) |
| Labs | 30% | Biomarker count and composite biomarker score |
API Reference
calculateHealthScore(input)
Calculate the health score from all available data sources.
Parameters:
interface HealthScoreInput {
wearables?: {
ouraReadiness?: number; // 0-100
whoopRecovery?: number; // 0-100
hrv?: number; // milliseconds
};
checkIns?: {
energy?: number; // 0-10
mood?: number; // 0-10
focus?: number; // 0-10
sleepQuality?: number; // 0-10
};
labs?: {
biomarkerCount?: number; // number of recent biomarkers
biomarkerScore?: number; // 0-100 composite lab score
};
}Returns:
interface HealthScoreResult {
score: number; // 0-100 composite score
breakdown: {
wearables: number; // 0-100 wearable sub-score
checkIns: number; // 0-100 check-in sub-score
labs: number; // 0-100 lab sub-score
};
}calculate(options)
Full calculation with trend analysis:
import { calculate } from '@loop/health-score';
const result = calculate({
input: { wearables: { ouraReadiness: 82 }, checkIns: { mood: 8 } },
previousScores: [72, 75, 77],
});
console.log(result.score); // 79
console.log(result.trend); // 'improving'
console.log(result.average); // 75.75calculateTrend(currentScore, previousScore?)
Determine the trend direction:
import { calculateTrend } from '@loop/health-score';
calculateTrend(80, 72); // 'improving' (>5 point increase)
calculateTrend(75, 74); // 'stable' (within 5 points)
calculateTrend(60, 75); // 'declining' (>5 point decrease)
calculateTrend(80); // undefined (no previous score)Thresholds:
- Improving: current is 5+ points above previous
- Declining: current is 5+ points below previous
- Stable: within 5 points
calculateAverageScore(scores)
import { calculateAverageScore } from '@loop/health-score';
calculateAverageScore([72, 75, 80, 78]); // 76.25
calculateAverageScore([]); // undefinedHow Scoring Works
Wearable Score (40%)
- Oura Readiness (0–100): Used directly
- Whoop Recovery (0–100): Used directly
- HRV: Normalized to 0–100 scale based on population norms
- Average of available metrics is taken
Check-in Score (30%)
- Each metric (energy, mood, focus, sleep quality) is on a 0–10 scale
- Normalized to 0–100 by multiplying by 10
- Average of available metrics is taken
Lab Score (30%)
- Based on the composite biomarker score from
@loop/health-engine - Bonus points for having more biomarker data
- Score of 0 if no recent labs
Missing Data
If a data source is entirely missing, its weight is redistributed proportionally to the available sources. For example, if no wearable data exists, check-ins get ~43% weight and labs get ~57%.