# CHANGES REQUIRED ## Important findings ### 1. Lag/phase panels ignore empty selection and global period **Anchors:** `scripts/health/assets/health-assets/dashboard-v5.js:629-632`, `601-617` The filter treats an empty metric selection as “show every correlation”: ```js row.status === "computed" && (!correlationIds.size || ...) ``` Therefore, **Auswahl leeren** empties the trend but expands Lag and Phase to all validated results. Global period changes also alter the trend without changing or qualifying the aggregate scope. **Exact synthetic reproducer:** 1. Generate the checked-in synthetic fixture and v5 dashboard. 2. Open Explorer → **Schlaf und Erholung**. 3. Click **Auswahl leeren**. 4. Inspect: ```js ({ selected: [...document.querySelectorAll("#metric-picker input:checked")].map(x => x.value), trendEmpty: !document.querySelector("#explorer-chart-empty").hidden, lagCells: document.querySelectorAll("#explorer-lag-heatmap .explorer-result-cell").length, phaseCells: document.querySelectorAll("#explorer-phase .explorer-result-cell").length }) ``` **Observed:** ```json { "selected": [], "trendEmpty": true, "lagCells": 30, "phaseCells": 30 } ``` Period probe, using **7 T** and then **Alle**: ```json { "seven": {"trendPoints": "6", "lagCount": 15, "phaseCount": 15}, "all": {"trendPoints": "19", "lagCount": 15, "phaseCount": 15}, "lagIdentical": true, "phaseIdentical": true } ``` **Consequence:** Lag/phase evidence appears associated with the current empty selection and visible period even though it represents a different server-side aggregate scope. Since browser recomputation is forbidden, these panels should fail closed for empty/unmatched selections and explicitly disclose—or server-contract—an aggregate period/cadence independent of the global controls. --- ### 2. Weekly trend and event lane do not use the same visible domain **Anchors:** `dashboard-v5.js:537-540`, `613-615`, `405-424` The weekly trend domain is constructed from Monday bucket keys, while the Explorer event lane always derives its domain from raw daily measurement dates. **Exact synthetic reproducer:** 1. Explorer → **Schlaf und Erholung** → **Wöchentlich**. 2. Inspect: ```js const canvas = document.querySelector("#explorer-chart"); const marker = document.querySelector( '#explorer-event-track .event-marker[data-event-date="2026-06-14"]' ); ({ chartFirst: canvas.dataset.firstDay, chartLast: canvas.dataset.lastDay, eventDate: marker.dataset.eventDate, eventPosition: marker.style.getPropertyValue("--event-position"), eventAxis: document .querySelector("#explorer-event-track .event-axis") .getAttribute("aria-label") }) ``` **Observed:** ```json { "chartFirst": "2026-05-18", "chartLast": "2026-06-08", "eventDate": "2026-06-14", "eventPosition": "100%", "eventAxis": "Ereignisse von 24.5.2026 bis 14.6.2026" } ``` The existing browser test at `tests/browser/dashboard_v5.spec.js:240-276` currently asserts the `100%` event position but does not compare the event-lane domain with `data-first-day`/`data-last-day`. **Consequence:** Event markers are visually positioned against a different temporal axis from the weekly chart. Use one explicitly shared domain—potentially week intervals if events retain exact daily dates—and test both endpoints. --- ## Other reviewed semantics No additional blocker reproduced for: - Missing daily observations remaining unknown - Partial weeks remaining `null` - Seven finite numeric days required for a weekly value - Numeric zero preservation - Registry-controlled raw `sum`/`avg` - Index mode averaging daily `ratio_100` values - Same-cadence complete-case scatter pairing - Canonical registry/preset drift rejection - Affirmative administered-event allowlist - Aggregate-only correlation payload validation - Non-causal/descriptive wording - No persistence of scatter pairs or dates ## Verification - `129 passed` — full Python suite - `16 passed` — full Playwright suite against synthetic fixture - Focused v5 tests: `22 passed` - JavaScript syntax, Python compilation, and `git diff --check`: passed - No production data accessed; no repository files modified - Temporary synthetic fixture/server artifacts removed; final working-tree status matches the initial Sprint-5B tree