# Visual dashboard release pattern

Use this for a presentation-only redesign of an existing private dashboard where data and medical contracts are frozen.

## Scope barrier

- Freeze the change set to renderer/template, CSS, client-side presentation logic, the already-approved chart adapter, and focused browser specs.
- Reject database modules, migrations, canonical writers, data-provider semantics, and new network/data sources unless the user explicitly widens scope.
- Before commit, derive the changed-path set from Git and fail if anything lies outside the approved presentation paths.
- Scan only added diff lines for SQL DDL/DML, canonical medical table writes, external URLs, and disallowed chart-library loads. This is a concise guard, not a substitute for product tests.

## Runtime preflight and deployment

1. Verify the requested base commit is `HEAD` and compare deployed runtime files against blobs from that commit by SHA-256.
2. If they match, do not redeploy the base or rerun the previous sprint's acceptance suite.
3. After renderer or asset edits, regenerate the private HTML, atomically install only changed V5 runtime files, and restart only the authorized service.
4. Keep the protected fallback artifact out of the deployment set and verify its checksum in the final smoke.

## Contextual shell contract

Use one global header with a small per-view matrix:

- Today: day label and previous/current/next-day controls.
- Cockpit, explorer, and nutrition trends: range controls.
- Calendar: its own month navigation, never a second global range bar.
- Record/documents: record navigation only.
- Global search remains reachable in every view.

Every visible control must navigate, open a dialog, change a documented state, or be removed. At 390 px, labels may collapse to embedded/local icons, but accessible names and 44 px targets remain.

## Today and cockpit acceptance

- Today shows only documented status, latest values, symptom check-in, medication, actionable tasks, chronology, nutrition, and completeness. Unknown and undocumented states stay neutral; never invent a readiness score.
- Every card and task has a concrete destination.
- Cockpit contains at most six prioritized metrics, each with value, date, personal-baseline delta when available, coverage, and a readable miniature.
- Metric-card drill-down must preserve the exact metric ID in the explorer URL/state.
- The focus chart exposes title, unit, period, genuine gaps, tooltips, zoom, event markers, and point-to-day navigation.
- A personal baseline band may be derived only from actual baseline values in the visible data. Never synthesize a percentage band.
- Laboratory bands remain observation-specific and require verified `(min,max,source)` data; absence produces no band.

## ECharts-only and motion checks

- Assert an ECharts instance exists for miniature and focus charts.
- Assert `window.Chart` is absent and no resource URL contains Chart.js bundles.
- Use 200–400 ms transitions and ECharts updates only when reduced motion is not requested.
- Under `prefers-reduced-motion: reduce`, assert ECharts animation is false and CSS durations collapse. Browsers may serialize `.01ms` as `0.00001s` or `1e-05s`; accept equivalent computed values.

## Fixture discipline

Before the one focused browser run, align the generated dashboard's `today` with the synthetic fixture's anchor date. Otherwise valid historical fixture rows can all fall outside the default active period and produce misleading empty cards/charts. Treat that as fixture-profile invalidity, not a product regression.

Use no more than six scenarios by combining:

1. contextual header matrix;
2. Today content and destinations;
3. cockpit metric cards, exact drill-down, and ECharts options;
4. chart/table/event-lane layout plus Chart.js absence;
5. 390 px overflow/touch targets;
6. reduced motion.

## Private read-only smoke

Load the authenticated private page with browser-context credentials, not URL credentials. Verify Today and Cockpit load, zero console/page errors, ECharts present, Chart.js absent, mobile overflow absent, runtime hashes current, service active, fallback checksum unchanged, remote tracking ref current, and working tree clean.

If the service listens on a private interface while the application Host allowlist expects loopback, use an ephemeral local TCP relay for the smoke. Do not weaken the service bind or Host allowlist merely to make the test convenient.
