ADR-0002: Null means unmeasured; zeros are always measured zeros
- Status: accepted
- Date: 2026-06-10 (contract introduced with row schema v2)
Context
Early agent-lane rows hard-coded 0 for signals the runner could not observe
(hydration bytes, tool wait time, parallel metrics, context truncation).
Dashboards cannot distinguish "measured zero" from "not measured", so
fabricated zeros silently corrupt the release-blocking question β "did this
changeset make Oak worse?" β with false confidence.
Decision
A metric value a runner cannot observe MUST be null, never a fabricated
zero. Every metric group carries a measurement_source describing how its
values were obtained. Consumers (summaries, dashboards, reports) must render
null as an explicit "unmeasured" state β never as zero, never as a pass.
Schema v1 rows (schema_version: 1) may contain placeholder zeros; consumers
treat those fields as unmeasured for v1 rows.
Consequences
- Numeric fields in row schemas are nullable wherever the signal is adapter- or probe-dependent.
- Adding a measurement means flipping null to a value, which is visible in trend charts as coverage growth, not a fake regression from zero.
- Reviewers can reject any diff that introduces a default
0for an unobserved signal by citing this ADR.