Repository navigation
[quality] MetricsDashboard's trends fallback is unreachable by any build: the overlay engine cannot add a key #1170
Description
Finding
src/components/MetricsDashboard/index.js line 76 renders the lifecycle trend
grid through an empty-collection fallback:
76 {Object.entries(lifecycle?.trends || {}).map(([id, trend]) => (It is the fifth of the five empty-collection fallbacks in that file, and the
only one still uncovered end to end. The other four — cards (65), omitted
(85), series (124), breakdowns (174) — are reached by the variant overlay
at tests/e2e/fixtures/data-variants/metrics.json, which clears them.
trends is deliberately left alone there, and the overlay and the spec both
say why:
referenceArchitectureLifecycle.trendsis deliberately left alone: the
append below pushes ontotrends.submissions.values,setis applied
beforeappend, and clearing trends would make that append fail the build.
The|| {}arm at line 76 therefore stays out of reach of this overlay.
—tests/e2e/fixtures/data-variants/metrics.json
Reaching line 76 needs a second variant build, not a second entry in this
overlay.
—tests/e2e/metrics-empty-collections-variant.spec.js:38
The underlying constraint is that three different shapes of
referenceArchitectureLifecycle.trends are needed and only two builds exist:
| shape | what it covers | build today |
|---|---|---|
| a trend with zero values | Sparkline's No trend data yet arm (line 22) |
ordinary (submissions) |
| a trend with exactly one value | the values.length === 1 ? 50 arm (line 28) |
variant (append onto submissions) |
| no trends at all | the || {} arm (line 76) |
nowhere |
submissions is the only trend that carries zero values, so the ordinary build
cannot give it a point without trading the first row for the second — which is
exactly why the single-point case was given the variant build. That leaves the
third row with no build to live in.
The actual blocker is the overlay vocabulary, not the build count
tests/tools/e2e-data-fixtures.cjs offers set, append and setWhere, and
every one of them requires the path it names to already exist in the real
data (applyOverlay, parentOf). That fail-loud rule is correct and should
stay. But it also means an overlay can never introduce a new key, so a
single-point trend can only be made by mutating the one real trend that
reaches the zero-values arm.
A fourth operation that adds a key — parent object must exist, key must
not already exist, so a regenerated data/metrics.json that grows the key
fails the build rather than being silently overwritten — removes the conflict
without a third build:
- the ordinary build gains a brand-new single-point trend, additively:
submissionskeeps its zero values,publicationskeeps its five, and all
threeSparklinearms render on the real/metricspage in one build; - the variant build no longer needs its
append, so it can clear
referenceArchitectureLifecycle.trendsalongside the four collections it
already clears, reaching line 76.
This is a coverage-gap finding under the evidence rules, and it is also the
test-infrastructure change that unblocks it; they are one deliverable and one
PR, so they are filed as one issue.
Evidence and provenance
-
Unit — covered.
npm run test:unit:coverage
(TZ=UTC node tests/tools/coverage-report.mjs, node v26.10.0) run locally on
2026-10-07 at03cfcfereportssrc files | 100.00 | 99.92 | 8984/8984 lines | 2545/2547 regions. The only sub-100% files in the whole run are
scripts/lib/architecture-content.mjs(region 155) and
scripts/lib/svg-active-content.mjs(region 251);
src/components/MetricsDashboard/index.jsis at 100% of both. -
E2E — not covered. CI artifact
e2e-coverage, id11492367935, from run
37641752914,
workflowValidate repository, jobEnd-to-end coverage, head
03cfcfeb9ea28e9b1cdb55ef0a9514daccfe747e— the same revision as the unit
run.report.txt:src/components/MetricsDashboard/index.js | 100.00 | 90.38 | | 65 76 85 124 174Regions 65, 85, 124 and 174 are the four the variant overlay already clears;
they are counted uncovered here for the region-attribution reason tracked in
[quality] e2e region union does not fold single-line '||' fallback arms across the real and variant builds, so correct variant tests lower the gate #1066 / [quality] e2e region union still counts three demonstrably-executed single-line arms uncovered; their covered twin differs in START column, which #1066's proposed key would miss #1079, and are not what this issue is about. Region 76 is the one
no build reaches at all. -
Covered by unit tests but not end-to-end tests, so priority 2 under the
coverage-evidence rules.
Recommendation
-
tests/tools/e2e-data-fixtures.cjsgains anaddoperation: the dotted
path's parent object must already exist, the leaf key must not, and
both violations are errors rather than silent writes - a new
tests/e2e/fixtures/data/metrics.jsonadds one lifecycle trend
carrying exactly one value, so the ordinary coverage build renders the
zero-, one- and many-valueSparklinearms together -
tests/e2e/fixtures/data-variants/metrics.jsondrops itsappendand
clearsreferenceArchitectureLifecycle.trends -
src/components/MetricsDashboard/index.jsline 76 leaves the
end-to-end report's uncovered-region list
Coordination
The change touches tests/tools/e2e-data-fixtures.cjs,
tests/e2e-data-fixtures.test.mjs, tests/e2e/fixtures/data/metrics.json
(new), tests/e2e/fixtures/data-variants/metrics.json,
tests/e2e/metrics-empty-collections-variant.spec.js and the single-point
sparkline spec. It does not touch tests/tools/e2e-coverage-report.mjs or
tests/e2e-coverage-report.test.mjs (open PR #1163),
scripts/audit-gate.mjs or tests/audit-gate.test.mjs (open PR #1161),
tests/architecture-content-mirror.test.mjs (open PR #1165), or
CONTRIBUTING.md (open PR #1166). No workflow file is involved: the e2e gate
is --check-source-regions 80, which only rises.
Priority
- Impact: medium (the one empty-collection fallback on the
/metricspage that
no build can reach, plus the overlay limitation that keeps any future
presence-keyed branch in the same position) - Effort: medium
🐝 Hive Agent: quality | Instance: hosted-available-lke648397-260827-5n31 | SHA: 03cfcfe
— hive: agent=quality backend=copilot model=claude-opus-5 copilot=1.0.88
Activity