Files
vyndr/specs/render-reachability-guard.md
builtbykev 981a05cbd6 Render-reachability guard: make built-but-unread a CI failure
Three consecutive orders shipped a backend-correct field that never
reached a screen, all on a green suite: gradeBands (required by no
serving code), served_grade (dropped at the adapter boundary),
GradeScaleLegend (imported by nothing). Each was caught by luck on a later
re-check, and in two of the three I had already reported the wiring done.

WHY GREEN TESTS COULD NOT SEE IT: backend tests stop at the API payload.
They prove a field is PRODUCED and say nothing about whether it is
CONSUMED. Invisible by construction, not an oversight in any one test.

THE TRAP, NAMED: the difficulty pools in the backend, so by the time a
field exists on the payload it feels finished. What remains is a
three-line adapter change nobody considers worth verifying, so it gets
claimed rather than traced. The last inch is the one with no friction,
which is exactly why it gets skipped. "I added the field" and "a user can
see it" are different claims and only the first is fun.

THE GUARD traces each promised field the whole way: payload -> adapter
consumes -> component renders -> component is MOUNTED. Mounted is
transitive to a Next entry point (page/layout/template), the only thing
that puts a pixel on screen, depth-limited so an import cycle cannot hang
the suite.

Container rows are exempted EXPLICITLY, not silently: served_grade carries
container:true plus a rendersVia list, and a separate assertion checks
every named part actually renders. The exemption is auditable and cannot
hide an unrendered field.

The guard tests itself -- an orphan component must report unmounted, and
the contract must be non-empty, since an empty contract passing vacuously
is how this would most plausibly rot.

RETRO-PROOF: run unchanged against 3591c76, before the wiring, it goes
11 failed / 8 passed and names the exact bugs -- "the ceiling stance /
grade scale legend - its component is MOUNTED, not merely written", "the
served grade object - the adapter consumes it", "whether the band
separates from the baseline - a component actually renders it". Green on
the current tree.

HONEST SCOPE LIMIT: gradeBands is NOT in the contract and would not be
caught. It is a backend module, not a promised user-facing field, and it
is correctly unwired -- every band collapses to base-rate at current
resolution. Out of scope by design, not oversight.

Now in the standing suite, so the three-gate floor is tests green
(including reachability) + build exit 0 + fingerprint. No serving or model
change. p_win never mutated. No Bonferroni slot.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W1sivYNqY2TS5ftykmHBU9
2026-08-07 14:44:17 -04:00

4.6 KiB

Built-but-unread — the defect class, and the guard that ends it

The class

Three consecutive orders shipped a backend-correct field that never reached a screen. All three passed a fully green suite.

order what was built why it never rendered
grade bands gradeBands.js, six orders of work required by no serving code
91927a4 served_grade on the payload dropped at the adapter boundary
3591c76 GradeScaleLegend.tsx imported by nothing

Each was caught by luck on a later re-check, and in two of the three I had already reported the wiring as done.

Why green tests could not see it

Backend tests stop at the API payload. They prove a field is produced and say nothing about whether it is consumed. The failure is invisible to them by construction — not an oversight in any individual test.

The cognitive trap, named

The difficulty pools in the backend. Deriving the grade, proving the factors, measuring resolution — that is where the thinking happens, and by the time a field exists on the payload it feels finished. The remaining step is a three-line adapter change that nobody considers worth verifying, so it gets claimed rather than traced. The last inch is the one with no friction, which is exactly why it is the one that gets skipped.

Nothing here is a frontend-competence problem. It is that "I added the field" and "a user can see it" are different claims, and only the first one is fun.


The contract

tests/unit/renderReachability.test.js holds the promised-field contract — the things the grade product commits to a user seeing:

promise payload adapter component
the served grade object served_grade served_grade (container) GradeResultCard
what this grade means served_grade.meaning gradeMeaning GradeResultCard
whether the band separates separates_from_base_rate separatesFromBaseRate GradeResultCard
what the band realized band_realized_rate bandRealizedRate GradeResultCard
which factors moved the read factor_adjustment factorsApplied GradeResultCard
the ceiling stance GradeScaleLegend

Adding a served field without adding it here is allowed. Adding it here without wiring it to a mounted component is not.


The guard

For each promised field it traces the whole path:

payload field  ->  adapter consumes it  ->  component renders it  ->  component is MOUNTED

"Mounted" is transitive to a Next entry point (page/layout/template) — the only thing that puts a pixel on a screen. A component that exists and renders its field perfectly but is imported by nothing fails. Depth-limited so an import cycle cannot hang the suite.

Container rows are exempted explicitly, not silently. served_grade is consumed by the adapter but not rendered directly, so it carries container: true plus a rendersVia list — and a separate assertion checks that every named part actually renders. The exemption is auditable; it cannot hide an unrendered field.

The guard also tests itself: it asserts that an orphan component reports unmounted, and that the contract is non-empty (an empty contract would pass vacuously — the way this guard would most plausibly rot).

Retro-proof

Run unchanged against the tree at 3591c76, before the wiring:

Tests: 11 failed, 8 passed
  ● the ceiling stance / grade scale legend — its component is MOUNTED, not merely written
  ● the served grade object — the adapter consumes it
  ● whether the band separates from the baseline — a component actually renders it
  ● what this grade means — the adapter consumes it
  ● which proven factors moved the read — a component actually renders it
  ...

It names the exact three bugs. Green on the current tree.

One honest scope limit

gradeBands is not in the contract and would not be caught. It is a backend module, not a promised user-facing field, and it is correctly unwired — every band it produces collapses to base-rate at current resolution. The guard covers promised fields; a backend module that should not yet render is out of scope by design, not by oversight.


In the deploy floor

The guard runs in the standing suite, so it is part of the three-gate floor: tests green (now including reachability) + web build exit 0 + post-deploy fingerprint. A future order that adds a served field without wiring it to a mounted component fails CI rather than a hand-check three orders later.

No serving or model change in this order. p_win never mutated. No Bonferroni slot.