"""R0-4 — post-deploy FRONTEND gate. Three test rounds were invalidated by a stale frontend (Vercel promote skipped twice; an outdated URL once). This gate verifies the ARTIFACT the testers actually load: fetch the canonical production URL, locate the built bundle, and assert it carries the current engine's markers and points at the right backend. Run it after every Vercel promote — a failure means testers would be looking at old code. Pure stdlib (no pip installs in CI). Usage: python verify_live_frontend.py [base_url] # default: https://room-editor-9y3b.vercel.app Exit 0 = the served frontend is current; non-zero = block/alert. """ import re import sys import urllib.request CANONICAL_URL = "https://room-editor-9y3b.vercel.app" BACKEND_HOST = "modventures-room-visualizer.hf.space" # Marker inventory: object property names survive minification; function # names do not. Keep one marker per shipped feature generation so a stale # build is identifiable by WHICH markers are missing. ENGINE_MARKERS = [ ("defaultRotation", "P1-4 rotation consumption"), ("keepRug", "R3-3 rug toggle"), ("tileWidthM", "R1-3/R2-1 metric sizing"), ("groutFrac", "R2-3 procedural cells"), ("rugFlags", "R3-3 rug flags"), ("Classic Checkered", "catalog present"), ("Calacatta Marble", "R2-2 seamless pack (2026-06-12)"), ("viz2d/convert", "backend API wiring"), (BACKEND_HOST, "points at the canonical backend"), ] def fetch(url: str, timeout: int = 30) -> str: req = urllib.request.Request(url, headers={"User-Agent": "verify-live-frontend"}) with urllib.request.urlopen(req, timeout=timeout) as r: return r.read().decode("utf-8", errors="replace") def main() -> int: base = sys.argv[1] if len(sys.argv) > 1 else CANONICAL_URL print(f"frontend gate target: {base}", flush=True) html = fetch(base) ok = True title = re.search(r"