# Stacked Panel Null Handling Plan

## Current Design

- TiDB dashboard JSON is stored under `tidb-dashboards/` and `tidb-ng-dashboards/`.
- Clinic-only dashboard JSON is stored under `clinic-dashboards/` and `dedicated-dataplane/`.
- Build workflows copy these JSON files into publish directories through `make dashboards`; Grafana reads the generated JSON from the image.
- Legacy graph panels represent stacking with `stack: true` at the panel or series override level, and null handling with `nullPointMode`.
- Newer time series panels represent stacking under `fieldConfig.defaults.custom.stacking.mode`; the current checked-in dashboards only use `mode: "none"` there.

## Risks

- Stacked graph panels with `nullPointMode: "null"` can render misleading stacked areas when one series has gaps.
- Full JSON reformatting would create large noisy diffs across generated dashboard files.
- Changing only the latest source version does not repair already checked-in local historical dashboard JSON.

## Target Contract

- Every legacy graph panel with stack enabled must use `nullPointMode: "null as zero"`.
- Newer time series panels are not changed in this pass because no checked-in panel currently enables field-config stacking.
- Latest checked-in source dashboards are fixed directly.
- Existing local dashboard JSON is also normalized so current image builds are not blocked by historical local files.
- No non-stacked panel is changed just because it has `nullPointMode`.

## Implementation Steps

1. Detect stacked panels structurally from parsed JSON.
2. For legacy graph panels, update only those panels' `nullPointMode` to `null as zero`.
3. Apply the same normalization across checked-in dashboard JSON.

## Verification Checklist

- Parse all dashboard JSON successfully after modification.
- Assert no stacked legacy panel has a `nullPointMode` other than `null as zero`.
- Assert no newer time series panel has enabled field-config stacking without a follow-up null-handling decision.
- Review git diff to ensure only dashboard JSON and this plan changed.
