Appearance
Screen conformance ledger
Every approved merchant-mobile design screen, and whether it exists in the app. The machine source of truth is screen-conformance.json; this page is the narrative. The data lives in exactly one place — never restate a screen's status here, or the two will disagree the first time one moves (the QRS-249/284/287 duplicate-source-of-truth bug class).
Run it: npm run check:screens.
⚠ THIS LEDGER'S NUMBER IS PRESENCE, AND IT HAS ALREADY BEEN READ AS PARITY ONCE
check:screens answers does an implementation path exist — never does it match the design. It says so throughout this page, and on 2026-08-14 the "27 of 36 built" figure was still allowed to imply that the merchant journey matched its approved designs. It does not: six audited screens diverge, one of them structurally.
The parity question has its own page and its own count: Ganapati parity audit. Read the two numbers together or neither is meaningful.
Why this exists (QRS-626)
On 2026-08-13 the product owner asked why, after two days of Shift-Left design work explicitly done so that client-side implementation could proceed smoothly, the implementation still had "significant screen mismatches, incomplete features, and deviations from the approved designs" — and why the answer kept arriving as one corrective prompt at a time.
The cause was measurable, and nothing in the repo could measure it.
The Claude Design prototype project (633dc069-6df8-4408-b625-068907c60c33) carries its own screen registry at SCREENS.md. It is authoritative by construction: PrototypeHub.dc.html generates itself from that file, and the file's own instruction is "To add, rename or retire a screen on the hub, edit the table above; never the hub." It had never been opened.
Implementation instead tracked the 20-step Ganapati journey — which SCREENS.md itself introduces as "a reading order over the shared, parameterised screens". A view over the set, not the set.
Measured at introduction: 23 approved mobile-console screens + 2 onboarding rows = 25. Nine built, three behind a later design round, nine unimplemented and reachable, four deferred by the design itself. Two of the unimplemented screens, Messages and Thread, sit behind a main tab, placeheld by an EmptyState whose source comment read "Backend-gated (messaging backend absent in R1)" — a justification that had gone stale two days earlier when the chat schema shipped (CR-26.0.1-22/23/24).
The deeper failure, which is the one the gate targets
Every other standard in this repo is script-enforced: check:readmes, check:parity, check:naming, check:docs-impact, check:docs, check:release, check:sql, check:portal-nav. Design conformance was enforced by the product owner noticing. That is not enforcement; it is a review queue with one reviewer and no alarm — and it produced exactly the loop the owner objected to. CLAUDE.md states the lesson in its own words, from three prior incidents: a standard with no gate decays.
A second, subtler cause is worth recording because it will recur under other names: backend blockers were allowed to stop client work the owner had explicitly descoped. Payments was held on QRS-622 (daily_sales has a feature key, a plan entitlement and no table) and Analytics on QRS-576 (no cardActivity rollup) — both genuine, both backend. The stated goal was client-side first, backend after. The repo's own packages/data seam exists precisely for this, and it had already been used one screen earlier to build all of Collections and Order detail against orders/service.stub.ts. The pattern was proven and then abandoned. For Analytics the point is sharper still: the design's null path — "nothing is recorded yet", offering the counts that do exist — is exactly what renders when the rollup is absent. The blocker was the screen's designed content.
What the gate checks
Six rules, each bidirectional, because a ledger that can only be wrong in one direction is one people quietly stop updating.
| Rule | Catches |
|---|---|
| S1 | A status outside built / stale / missing. |
| S2 | A built/stale entry whose impl path is not on disk — the rename-and-forget direction. |
| S3 | A missing entry that is implemented, either by a recorded path or by one appearing at its conventional feature directory. This is the direction that makes the printed count a fact rather than an estimate. |
| S4 | A stale entry with no staleReason. "Needs updating" that does not say to what is how the Settings screen sat pending across two sessions. |
| S5 | reachable: false with no blocking reason, so a legitimate deferral cannot hide something merely forgotten. |
| S6 | Two entries sharing a design or impl path, which would let one screen launder another's status. |
The headline number — unimplemented and reachable — prints on every run, green or red. That is the design: the number is always visible, and it can only come down through real work.
What it deliberately does not check
- Fidelity. Whether a built screen matches its design. A script cannot see spacing, states or interaction feel; that stays a design pull plus a drift-ledger row (ADR-0015). Claiming more would repeat QRS-246 — a standard documented for months and implemented by nothing. This gate answers presence, the same presence-vs-freshness split
check:readmesandcheck:docs-impactalready accept, and presence is precisely what was unmeasured. - Whether the registry has gained a screen since transcription. That needs the network, and a gate that fails when the design project is unreachable gets switched off.
source.transcribedAtis the honest marker: re-transcribe when pulling a design round, and treat the ledger as stale-by-default after one.
Scope — read this before quoting the count
The ledger covers the merchant mobile app only: SCREENS.md's Merchant console — Mobile section plus its Onboarding & sign-up rows. The registry holds five further approved sections that are not counted here — Public Setu Card, Consumer app, Consumer marketplace (desktop), Merchant console Desktop, and the platform Admin Panel — plus two marked SUPERSEDED, DO NOT IMPLEMENT.
So a green run means "the merchant mobile app is accounted for", never "the product is designed and built". Scoping it this way is deliberate: the failure being fixed was mis-tracking one surface, and a ledger that silently spanned six would make the merchant number unreadable again.
Working rule
- Before implementing a screen, re-pull its design and re-read its
SCREENS.mdrow — the Purpose cell carries the round notes, which is where a later round's changes are actually recorded. - Update the ledger row in the same change as the code. A status that disagrees with the disk makes every count untrustworthy, which is worse than no ledger.
- A backend gap is not a reason to skip a screen. Build against the
packages/datastub seam and record the backend item as its ownQRS-###. If the design has a null/empty state, that state is the deliverable while the data is absent. - Four screens are deferred by the design, not by us —
More.dc.htmlrenders Reviews, Announcements, Invite & Earn and Partner program as NOT BACKED YET rather than linking them. Building one would put a screen behind an unreachable entry. Theirblockingfield records why.
Related
- Screen Coverage Mandate — the forward half: how a screen is designed before it exists.
- Foundational Screen Prompts — the per-feature spec table.
- Design drift ledger — records divergence on screens that are built (ADR-0015).
- Claude Designs screen reviews — audits existing designs against the standard.