mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-14 14:40:52 +00:00
fix(health-score): drop the mood pillar when the mood module is disabled
The Personal Health Score weighted the 0.20 mood-stability pillar unconditionally — the fast-path read mood entries regardless of the account's module state, so a user who turned the mood module off was still scored (and silently penalised or rewarded) by a pillar hidden everywhere else in the product. The dashboard already blanks the mood tile and the coach snapshot unions mood out; the score ring and the insights card pillar list did not. Thread a default-on `moodEnabled` flag through the fast-path. When the caller resolves the mood module as disabled the helper skips the mood read entirely and leaves the series empty, so `moodStability` returns null and the existing proportional null-redistribution re-scales the surviving pillars to sum to 100. The analytics route resolves the module server-side and threads the flag; the insights card hides the Mood row via a new SSR-safe `useModuleEnabled` accessor so it never advertises a pillar the account turned off. Golden fixtures pin mood-on vs mood-off to different, correctly re-weighted scores and assert the disabled read is never issued. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
7c8d82f565
commit
3de53f549c
6 files changed
+224
-13
No files matched your search
@@ -17,6 +17,7 @@ import {
|
||||
type BpInTargetEnvelope,
|
||||
} from "@/lib/analytics/bp-in-target-fast-path";
|
||||
import { computeUserHealthScoreFastPath } from "@/lib/analytics/health-score-fast-path";
|
||||
import { isModuleEnabled } from "@/lib/modules/gate";
|
||||
import { buildHealthScoreBpInputs } from "@/lib/analytics/health-score-inputs";
|
||||
import { deriveBpWindow90 } from "@/lib/analytics/window-confidence";
|
||||
import { computeCorrelationHypothesesFastPath } from "@/lib/analytics/correlations-fast-path";
|
||||
@@ -420,12 +421,19 @@ async function buildAnalyticsResponse(user: AuthedUser) {
|
||||
// same prior-week delta values). The hand-rolled per-surface assembly that
|
||||
// let the two diverge is gone.
|
||||
const bpInputs = buildHealthScoreBpInputs(bpEnvelope, bpEnvelopePriorWeek);
|
||||
// v1.18.0 R4 — resolve the `mood` module server-side so a disabled-mood
|
||||
// account drops the mood-stability pillar from the ring instead of
|
||||
// being silently scored on data hidden everywhere else. The dashboard
|
||||
// already blanks the mood tile + the coach snapshot unions mood out;
|
||||
// this closes the matching gap on the Health Score.
|
||||
const moodEnabled = await isModuleEnabled(user.id, "mood");
|
||||
const healthScore = await computeUserHealthScoreFastPath({
|
||||
userId: user.id,
|
||||
...bpInputs,
|
||||
heightCm: user.heightCm ?? null,
|
||||
now: new Date(),
|
||||
coverage,
|
||||
moodEnabled,
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
Reference in new issue
Block a user