From 0522652ae2726907ce5ffc46631fdafd5f20ba46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Sat, 16 May 2026 12:23:30 +0200 Subject: [PATCH] feat(measurements): wire walking-steadiness + audio-exposure-event through every registry v1.4.30 commit 7 follow-up. The new MeasurementType values land in every derived registry the canonical enum drives: - measurement-list-meta.ts label keys + icons + colors so the measurements list view renders both types (Gauge for steadiness, Volume2 for the loud-listening event) - 6 locale files (de/en/es/fr/it/pl) carry typeWalkingSteadiness + typeAudioExposureEvent keys; English-fallback copy for the four non-EN/DE locales matches the existing v1.4.25 W8d pattern - chart-tokens.ts ALLOWED_CHART_TOKENS list so the LLM can reference `metric:WALKING_STEADINESS` + `metric:AUDIO_EXPOSURE_EVENT` in prose; dedicated chart components ship alongside the iOS sync - the enum-coverage drift-guard test's EXPECTED_TYPES + PDF exclusion set so the canonical enum-extension lint stays green Full unit suite passes (4035 specs). --- messages/de.json | 2 ++ messages/en.json | 2 ++ messages/es.json | 2 ++ messages/fr.json | 2 ++ messages/it.json | 2 ++ messages/pl.json | 2 ++ src/components/measurements/measurement-list-meta.ts | 12 ++++++++++++ .../__tests__/measurement-type-enum-coverage.test.ts | 11 ++++++++++- src/lib/insights/chart-tokens.ts | 5 +++++ 9 files changed, 39 insertions(+), 1 deletion(-) diff --git a/messages/de.json b/messages/de.json index e04f4ddcb..9f48090bd 100644 --- a/messages/de.json +++ b/messages/de.json @@ -299,6 +299,8 @@ "typeAudioExposureEnv": "Lärmbelastung (Umgebung)", "typeAudioExposureHeadphone": "Lärmbelastung (Kopfhörer)", "typeTimeInDaylight": "Zeit im Tageslicht", + "typeWalkingSteadiness": "Gehstabilität", + "typeAudioExposureEvent": "Lautes-Hören-Ereignis", "glucoseContext": "Kontext", "glucoseContextFasting": "Nüchtern (≥8 h ohne Nahrung)", "glucoseContextPostprandial": "Postprandial (2 h nach dem Essen)", diff --git a/messages/en.json b/messages/en.json index 55728b3a0..65cbf4fb5 100644 --- a/messages/en.json +++ b/messages/en.json @@ -299,6 +299,8 @@ "typeAudioExposureEnv": "Audio Exposure (Environment)", "typeAudioExposureHeadphone": "Audio Exposure (Headphones)", "typeTimeInDaylight": "Time in Daylight", + "typeWalkingSteadiness": "Walking Steadiness", + "typeAudioExposureEvent": "Loud-Listening Event", "glucoseContext": "Context", "glucoseContextFasting": "Fasting (≥8h without food)", "glucoseContextPostprandial": "Post-meal (2h after eating)", diff --git a/messages/es.json b/messages/es.json index c563c0ea7..1b9e493a0 100644 --- a/messages/es.json +++ b/messages/es.json @@ -299,6 +299,8 @@ "typeAudioExposureEnv": "Audio Exposure (Environment)", "typeAudioExposureHeadphone": "Audio Exposure (Headphones)", "typeTimeInDaylight": "Time in Daylight", + "typeWalkingSteadiness": "Walking Steadiness", + "typeAudioExposureEvent": "Loud-Listening Event", "glucoseContext": "Context", "glucoseContextFasting": "Fasting (≥8h without food)", "glucoseContextPostprandial": "Post-meal (2h after eating)", diff --git a/messages/fr.json b/messages/fr.json index c85667832..5a0f4f34e 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -299,6 +299,8 @@ "typeAudioExposureEnv": "Audio Exposure (Environment)", "typeAudioExposureHeadphone": "Audio Exposure (Headphones)", "typeTimeInDaylight": "Time in Daylight", + "typeWalkingSteadiness": "Walking Steadiness", + "typeAudioExposureEvent": "Loud-Listening Event", "glucoseContext": "Context", "glucoseContextFasting": "Fasting (≥8h without food)", "glucoseContextPostprandial": "Post-meal (2h after eating)", diff --git a/messages/it.json b/messages/it.json index 0879fb0cc..2aa68aed8 100644 --- a/messages/it.json +++ b/messages/it.json @@ -299,6 +299,8 @@ "typeAudioExposureEnv": "Audio Exposure (Environment)", "typeAudioExposureHeadphone": "Audio Exposure (Headphones)", "typeTimeInDaylight": "Time in Daylight", + "typeWalkingSteadiness": "Walking Steadiness", + "typeAudioExposureEvent": "Loud-Listening Event", "glucoseContext": "Context", "glucoseContextFasting": "Fasting (≥8h without food)", "glucoseContextPostprandial": "Post-meal (2h after eating)", diff --git a/messages/pl.json b/messages/pl.json index dd2be6386..2538e0400 100644 --- a/messages/pl.json +++ b/messages/pl.json @@ -299,6 +299,8 @@ "typeAudioExposureEnv": "Audio Exposure (Environment)", "typeAudioExposureHeadphone": "Audio Exposure (Headphones)", "typeTimeInDaylight": "Time in Daylight", + "typeWalkingSteadiness": "Walking Steadiness", + "typeAudioExposureEvent": "Loud-Listening Event", "glucoseContext": "Context", "glucoseContextFasting": "Fasting (≥8h without food)", "glucoseContextPostprandial": "Post-meal (2h after eating)", diff --git a/src/components/measurements/measurement-list-meta.ts b/src/components/measurements/measurement-list-meta.ts index c87cba09b..c26b364c0 100644 --- a/src/components/measurements/measurement-list-meta.ts +++ b/src/components/measurements/measurement-list-meta.ts @@ -68,6 +68,9 @@ export const MEASUREMENT_TYPE_LABEL_KEYS: Record = { AUDIO_EXPOSURE_ENV: "measurements.typeAudioExposureEnv", AUDIO_EXPOSURE_HEADPHONE: "measurements.typeAudioExposureHeadphone", TIME_IN_DAYLIGHT: "measurements.typeTimeInDaylight", + // ── v1.4.30 R-F T1.4 + T1.5 ── + WALKING_STEADINESS: "measurements.typeWalkingSteadiness", + AUDIO_EXPOSURE_EVENT: "measurements.typeAudioExposureEvent", }; export const MEASUREMENT_TYPE_ICONS: Record = { @@ -110,6 +113,12 @@ export const MEASUREMENT_TYPE_ICONS: Record = { AUDIO_EXPOSURE_ENV: Volume2, AUDIO_EXPOSURE_HEADPHONE: Headphones, TIME_IN_DAYLIGHT: Sun, + // ── v1.4.30 R-F T1.4 + T1.5 ── + // Activity/Gauge carries the mobility-steadiness signal (same + // family as VO2_MAX). Volume2 is reused for the loud-listening + // event flag — the event is a louder-cousin of the env quantity. + WALKING_STEADINESS: Gauge, + AUDIO_EXPOSURE_EVENT: Volume2, }; export const MEASUREMENT_TYPE_COLORS: Record = { @@ -149,4 +158,7 @@ export const MEASUREMENT_TYPE_COLORS: Record = { AUDIO_EXPOSURE_ENV: "bg-chart-5/20 text-chart-5", AUDIO_EXPOSURE_HEADPHONE: "bg-chart-5/20 text-chart-5", TIME_IN_DAYLIGHT: "bg-chart-2/20 text-chart-2", + // ── v1.4.30 R-F T1.4 + T1.5 ── + WALKING_STEADINESS: "bg-chart-2/20 text-chart-2", + AUDIO_EXPOSURE_EVENT: "bg-chart-5/20 text-chart-5", }; diff --git a/src/lib/__tests__/measurement-type-enum-coverage.test.ts b/src/lib/__tests__/measurement-type-enum-coverage.test.ts index 5dffea956..14cfee0a6 100644 --- a/src/lib/__tests__/measurement-type-enum-coverage.test.ts +++ b/src/lib/__tests__/measurement-type-enum-coverage.test.ts @@ -46,10 +46,13 @@ const EXPECTED_TYPES = [ "AUDIO_EXPOSURE_ENV", "AUDIO_EXPOSURE_HEADPHONE", "TIME_IN_DAYLIGHT", + // ── v1.4.30 R-F T1.4 + T1.5 ── + "WALKING_STEADINESS", + "AUDIO_EXPOSURE_EVENT", ] as const; describe("measurementTypeEnum coverage", () => { - it("exposes the 28 canonical measurement types", () => { + it("exposes the 30 canonical measurement types", () => { expect([...measurementTypeEnum.options].sort()).toEqual( [...EXPECTED_TYPES].sort(), ); @@ -96,6 +99,12 @@ describe("measurementTypeEnum coverage", () => { "AUDIO_EXPOSURE_ENV", "AUDIO_EXPOSURE_HEADPHONE", "TIME_IN_DAYLIGHT", + // v1.4.30 R-F T1.4 + T1.5 additions held under the same v1.5 gate. + // Walking-steadiness pairs with a mobility chip; audio-exposure + // events surface on the Insights audio sub-page. Neither belongs + // in the clinical PDF until the iOS-app sync lands. + "WALKING_STEADINESS", + "AUDIO_EXPOSURE_EVENT", ]); it("doctor-report PDF vital types cover the canonical enum minus documented exclusions", () => { diff --git a/src/lib/insights/chart-tokens.ts b/src/lib/insights/chart-tokens.ts index f231f064d..21ed87897 100644 --- a/src/lib/insights/chart-tokens.ts +++ b/src/lib/insights/chart-tokens.ts @@ -60,6 +60,11 @@ export const ALLOWED_CHART_TOKENS = [ "metric:AUDIO_EXPOSURE_ENV", "metric:AUDIO_EXPOSURE_HEADPHONE", "metric:TIME_IN_DAYLIGHT", + // v1.4.30 — R-F T1.4 + T1.5 Tier-1 additions. Same posture: the + // LLM can reference the tokens in prose; the chart components land + // alongside the iOS-app sync. + "metric:WALKING_STEADINESS", + "metric:AUDIO_EXPOSURE_EVENT", ] as const; export type ChartToken = (typeof ALLOWED_CHART_TOKENS)[number];