← back to Wallco Ai
output/room-mockup-coverage-2026-05-31.md
146 lines
# wallco.ai — Room-Mockup Coverage Gap Report
**Date:** 2026-05-31
**Mode:** READ-ONLY audit (no DB writes, no renders, no deletes)
**Host:** my-server (45.61.58.125) · `/root/public-projects/wallco-ai`
**DB:** queried through the app's own `lib/db.js` (`psqlQuery`) — same connection
the live server uses, so counts match what the app sees.
---
## TL;DR
**37 room-mockup references over-claim** — a `wallco_rooms` row
(`removed_at IS NULL`) records a room for a published design, but **no PNG exists
on disk at the canonical path *or* the legacy `/uploads/` fallback**. These 37
rows span **18 distinct published designs**.
- **Customer-visible broken cards = 0.** The live PDP "See in a room" path uses a
dual-path resolver (`server.js` ~L194–218) that checks file existence
(canonical `data/rooms/design_<id>_<type>.png`, then legacy `image_path`) and
**drops** room types whose file is absent. So these 37 are *silently dropped* —
the design renders with no room card for that type, not a broken/404 image.
- **0 tiny/corrupt files** (>0 but ≤50 KB) are present, so nothing garbage is
being served either.
- The gap is therefore an **internal coverage** shortfall: 18 published designs
are recorded as having room mockups they can't actually display.
---
## Method / source of truth
- The customer PDP reads room types **live from the `wallco_rooms` TABLE**
(`WHERE design_id=$1 AND removed_at IS NULL`), not the `designs.json` snapshot.
This audit treats the **table** as authoritative.
- For each active room row on a published design, the file was checked at the
**canonical** path `data/rooms/design_<id>_<room_type>.png`. Any row whose
canonical file was missing/≤0 bytes was then **re-checked against the legacy
`image_path` / `filename` fallback** (the same dual-path the resolver uses)
before being declared broken — so this is not an over-report.
- `wallco_rooms` size column is `file_size_bytes` (the DB has no `file_size`).
- "Published" basis = `all_designs.is_published=true AND NOT user_removed`
(this is the table `wallco_rooms.design_id` joins to). Snapshot/customer
`spoon_all_designs` figures are reported alongside for context.
---
## Counts (verified)
| Metric | Count |
|---|---|
| Published designs — `all_designs` (`is_published AND NOT user_removed`) | **2,902** |
| Published designs claiming ≥1 room (distinct, via `wallco_rooms` table) | **2,649** |
| Active `wallco_rooms` rows for published designs | **3,827** |
| └─ PNG present, ideal (≥1.5 MB) | 349 |
| └─ PNG present, acceptable (50 KB–1.5 MB) | 3,441 |
| └─ PNG present, tiny/corrupt (>0, ≤50 KB) | 0 |
| └─ **PNG missing — canonical AND legacy `/uploads/` (OVER-CLAIM)** | **37** |
| **Coverage gap (broken references)** | **37 rows · 18 distinct designs** |
| Rooms present on disk ÷ claimed (published) | **99.0 %** (3,790 / 3,827) |
| Room PNG files on disk (`data/rooms/*.png`) | 7,298 |
### Context / secondary figures
| Metric | Count |
|---|---|
| `spoon_all_designs` published (customer snapshot basis) | 1,321 |
| `spoon` published designs claiming ≥1 room (distinct) | 1,058 |
| `all_designs` published with non-empty `room_mockups` jsonb | 71 |
| `wallco_rooms` **active rows across ALL designs** (pub + unpub) | 8,674 |
> **Wider over-claim signal (not customer-facing):** there are 8,674 active
> `wallco_rooms` rows but only 7,298 room PNGs on disk. The ~1,376 difference is
> dominated by **unpublished** designs (outside the customer surface and outside
> this report's published-scope of 37). Worth a follow-up table-vs-disk
> reconciliation if the admin gallery surfaces unpublished rooms.
---
## The 37 broken rows — 18 distinct designs
All 37 have `image_path = /uploads/rooms/design_<id>_<room>.png` recorded, but the
file exists at **neither** the canonical `data/rooms/` path **nor** `/uploads/`.
**Distinct broken design IDs (18):**
`11, 12, 13, 15, 22, 23, 3498, 9964, 11542, 17493, 24896, 26798, 27076, 27104, 27357, 37709, 38890, 38933`
| # | design_id | room_type |
|---|---|---|
| 1 | 11 | bedroom |
| 2 | 11 | dining_room |
| 3 | 11 | office |
| 4 | 11 | bathroom |
| 5 | 12 | living_room |
| 6 | 12 | dining_room |
| 7 | 12 | office |
| 8 | 12 | bathroom |
| 9 | 13 | bedroom |
| 10 | 13 | dining_room |
| 11 | 13 | office |
| 12 | 13 | bathroom |
| 13 | 15 | bedroom |
| 14 | 15 | dining_room |
| 15 | 15 | office |
| 16 | 15 | bathroom |
| 17 | 22 | bedroom |
| 18 | 22 | dining_room |
| 19 | 22 | office |
| 20 | 22 | bathroom |
_(rows 21–37 — designs 23, 3498, 9964, 11542, 17493, 24896, 26798, 27076, 27104×2,
27357, 37709, 38890, 38933 — are in the full list: `output/room-mockup-broken-list-2026-05-31.tsv`.)_
### Pattern
- **Designs 11, 12, 13, 15, 22, 23** are low-ID legacy/seed designs, each claiming
~4 room types (bedroom/dining_room/office/bathroom or living_room) — 24 of the
37 rows. These look like early room-mockup rows written before the canonical
`data/rooms/` convention existed; the `/uploads/` files were never migrated.
- The remaining 13 rows are scattered mid/high-ID designs (3498, 9964, 11542,
17493, 24896, 26798, 27076, 27104, 27357, 37709, 38890, 38933), mostly a single
`bedroom`/`office`/`dining_room` row each.
---
## Recommended next steps (Steve-gated — NOT executed here)
Per the read-only scope + overnight gated-action rule, nothing below was run; a
ready-to-run companion note is at
`~/.claude/yolo-queue/pending-approval/room-mockup-coverage-remediation.md`.
- **Option A (recommended) — Re-render the 37 missing rooms FREE + LOCAL** via the
PIL composite (`scripts/pil-room-composite.py`), never the $750 cloud. Once each
PNG lands ≥50 KB at `data/rooms/design_<id>_<room>.png`, the card reappears
automatically (resolver reads table + checks file). No DB write needed.
- **Option B — Soft-remove the 37 stale rows** (`UPDATE wallco_rooms SET removed_at=now()…`)
so the table stops claiming rooms it can't back. Cosmetic only (resolver already
hides them). Lower value than A for published designs.
- **Follow-up — reconcile the wider 8,674-vs-7,298 gap** for unpublished designs
if the admin gallery shows them.
---
_Provenance: all figures trace to `/tmp/wallco_audit_result.txt` (node/lib-db
counts + canonical disk-check) and `/tmp/wallco_refine.txt` (dual-path
verification), 2026-05-31. An earlier draft of this report contained numbers
fabricated by a transient tool-output display glitch; it was discarded and every
figure here was re-derived from the on-disk audit files._