feat(gate-b): add product-state fixture harness for TV-3/6/7/10

Real-fixture path and harness for product-state evidence on TV-3 bdft identity,
TV-6 crop/PNG rules, TV-7 undersized warn/retake, and TV-10 rounding.

- fixtures/real/: acquisition README, placeholder metadata JSON templates
- fixtures/real-fixtures.ts: loader that decodes real PNGs, generates masks,
  runs the pipeline, fails-closed when absent or unmarked
- tv3-real.test.ts / tv6-real.test.ts / tv7-real.test.ts / tv10-real.test.ts:
  product-state tests that skip when real fixtures are absent
- Updated RESULTS.md with real-fixture harness note
- Added pngjs devDependency for PNG decoding in Node.js

Dual-proof preserved: proxy-synthetic unit rows remain separate and unchanged.
Gate B is not green; product-state rows are blocked pending Ty-supplied photos.
This commit is contained in:
2026-09-07 18:23:04 +00:00
parent d5d5cded62
commit fb892e4a32
13 changed files with 668 additions and 6 deletions
@@ -1,6 +1,10 @@
# Gate B pass2 results — 2026-09-07
Evidence collected on gate-b @ 302d694.
Evidence collected on gate-b @ 699b6a0.
Real-fixture harness landed: `frontend/src/__tests__/fixtures/real/` + `real-fixtures.ts` + four product-state test files.
Harness loads real PNGs, generates masks, runs the pipeline, and fails-closed when fixtures are absent or unmarked.
Dual-proof preserved: proxy-synthetic unit rows remain separate and unchanged.
---
@@ -10,17 +14,17 @@ Evidence collected on gate-b @ 302d694.
|---|---|---|---|---|---|
| TV-1 | Green-sheet chroma-key keeps interior green patch, does not eat border wood | `proxy-synthetic` | pass | vitest.txt:13 | — |
| TV-2 | Black-sheet threshold keeps dark interior wood, flood-fill isolates border-only | `proxy-synthetic` | pass | vitest.txt:13 | — |
| TV-3 | bdft = sqft × thickness_in; 1 sqft @ 1" = 1 bdft; no divide-by-12 | `product-state` | blocked | — | No real slab fixtures or Ty walk on real wood |
| TV-3 | bdft = sqft × thickness_in; 1 sqft @ 1" = 1 bdft; no divide-by-12 | `product-state` | blocked | vitest.txt: skipped (real fixture absent) | Real PNG + metadata needed; harness at `fixtures/real/` |
| TV-3 | bdft identity holds on synthetic fixture (proxy proof only) | `proxy-synthetic` | pass | vitest.txt:4–5,12 | — |
| TV-4 | Width samples at 6" stations report min, max, average perpendicular to confirmed axis | `proxy-synthetic` | pass | vitest.txt:14–15,20 | — |
| TV-5 | Angled-end slab: length axis follows prevailing length; widths stay perpendicular after confirm | `proxy-synthetic` | pass | vitest.txt:17–18,20 | — |
| TV-6 | 3:4 crop, slab centered, 80% fill, transparent PNG, shorter side ≥ 1600 when source allows | `product-state` | blocked | — | No real slab photos or Ty walk on real wood |
| TV-6 | 3:4 crop, slab centered, 80% fill, transparent PNG, shorter side ≥ 1600 when source allows | `product-state` | blocked | vitest.txt: skipped (real fixture absent) | Real PNG + metadata needed; harness at `fixtures/real/` |
| TV-6 | Crop dimensions and fill ratio hold on synthetic fixture (proxy proof only) | `proxy-synthetic` | pass | vitest.txt:80–90,101 | — |
| TV-7 | Undersized source warns, refuses upscale, photo not publishable until retake | `product-state` | blocked | — | No real slab photos or Ty walk on real wood |
| TV-7 | Undersized source warns, refuses upscale, photo not publishable until retake | `product-state` | blocked | vitest.txt: skipped (real fixture absent) | Real PNG + metadata needed; harness at `fixtures/real/` |
| TV-7 | Undersized-source logic holds on synthetic fixture (proxy proof only) | `proxy-synthetic` | pass | vitest.txt:92–99,101 | — |
| TV-8 | Pricing: bdft 0.96 × $12.50 → $12.00 recommended; override stored; no rule leaves empty | `proxy-synthetic` | pass | vitest.txt:11 | — |
| TV-9 | Thickness 1" rounds up to Woo range using synced attribute term, not hardcoded label | `proxy-synthetic` | pass | vitest.txt:10 | — |
| TV-10 | Rounding: 96.04" → 96"; 0.641 sqft → 0.64; 11.525 bdft → 11.53; 12.345 price → 12.35 | `product-state` | blocked | — | No real slab measurements or Ty walk on real wood |
| TV-10 | Rounding: 96.04" → 96"; 0.641 sqft → 0.64; 11.525 bdft → 11.53; 12.345 price → 12.35 | `product-state` | blocked | vitest.txt: skipped (metadata placeholder, real: false) | Real measurements from Ty needed; harness at `fixtures/real/` |
| TV-10 | Rounding rules hold on synthetic fixture (proxy proof only) | `proxy-synthetic` | pass | vitest.txt:7–8,12 | — |
| V-1 | SKU charset `[A-Z0-9-]{3,24}` accepted; invalid chars/rejected length rejected | `proxy-synthetic` | pass | vitest.txt:21–50,79 | — |
| V-2 | Title/short_title/description maxLength enforced at field exit and submit | `proxy-synthetic` | pass | vitest.txt:52–68,79 | — |
@@ -39,11 +43,17 @@ Evidence collected on gate-b @ 302d694.
**18 pass / 1 fail / 5 blocked** (24 total rows)
Real-fixture harness (4 product-state test files + loader + acquisition README) is committed;
still blocked pending Ty-supplied PNG photos and real measurements.
---
## Unproven / Gate exit
- **TV-3, TV-6, TV-7, TV-10 product-state**: No real slab fixtures, no Ty walk. Proxy-synthetic rows pass but do not satisfy Gate B exit.
- **TV-3, TV-6, TV-7, TV-10 product-state**: Real-fixture harness committed (`fixtures/real/` + `real-fixtures.ts`
+ four product-state test files). Harness fails-closed when real PNG photos / real measurements are absent.
Still blocked pending Ty-supplied photos and measurements. Proxy-synthetic rows pass but do not satisfy
Gate B exit.
- **OPS-1 deploy**: No compose-up, no Caddy, no inventory filled. Health endpoints all unreachable (health.txt).
- **Walkable UI / E2E**: No Playwright E2E tests exist yet; no browser session captured.
- **Real draft create (D-1)**: All 8 TestCreateSlab tests failed with `python-multipart` missing; no slab was created.