[object Object]

← back to Wallco Ai

Fix publish-gate.py prod fail-closed: use resolved image path for seam scan (not dead Mac2 local_path) + PIL resize instead of macOS-only sips for vision JPEG

89d7ad5f77dbd10bbf9dd2952c0b5ab3d98a1d44 · 2026-05-29 12:52:35 -0700 · Steve

Files touched

Diff

commit 89d7ad5f77dbd10bbf9dd2952c0b5ab3d98a1d44
Author: Steve <steve@designerwallcoverings.com>
Date:   Fri May 29 12:52:35 2026 -0700

    Fix publish-gate.py prod fail-closed: use resolved image path for seam scan (not dead Mac2 local_path) + PIL resize instead of macOS-only sips for vision JPEG
---
 scripts/publish-gate.py | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/scripts/publish-gate.py b/scripts/publish-gate.py
index bdd5224..cee0fca 100644
--- a/scripts/publish-gate.py
+++ b/scripts/publish-gate.py
@@ -73,10 +73,13 @@ def _resolve_image(lp, image_url):
             for q in _QUAR: cands.append(str(q / iub))
     for c in cands:
         if c and os.path.isfile(c):
-            try: return Image.open(c).convert('RGB')
+            try: return Image.open(c).convert('RGB'), c
             except Exception: pass
-    return None
-img = _resolve_image(lp, image_url)
+    return None, None
+# Return BOTH the PIL image AND the resolved on-disk path. The seam scan + vision
+# check below must use the resolved path, NOT the raw Mac2 `local_path` (which
+# doesn't exist on prod) — otherwise both fail-closed on every prod design.
+img, img_path = _resolve_image(lp, image_url)
 if img is None:
     print(json.dumps({'pass': False, 'id': ID, 'reasons': ['image file missing/unreadable']})); sys.exit(1)
 W, H = img.size
@@ -87,7 +90,7 @@ if is_mural:
     checks['seamless'] = True  # murals don't tile
 else:
     try:
-        r = es.scan_path(Path(lp))
+        r = es.scan_path(Path(img_path))
         ok = r.get('ok') and r['edges_max'] <= 5 and r['mids_max'] <= 5
         checks['seamless'] = bool(ok)
         if not ok: reasons.append(f"seam ΔE edge={r.get('edges_max','?')} center={r.get('mids_max','?')} (need ≤5)")
@@ -136,7 +139,9 @@ PROMPT = (f"This is a wallpaper tile meant to be a '{subject}' design. Answer st
           f"Answer with exactly 'PASS' or 'FAIL: <short reason>'.")
 try:
     jpg = f'/tmp/pg_{ID}.jpg'
-    subprocess.run(['sips', '-Z', '512', '-s', 'format', 'jpeg', lp, '--out', jpg], capture_output=True)
+    # PIL resize (cross-platform) — the old `sips` call is macOS-only and threw
+    # FileNotFoundError on Linux/prod, making on_concept fail-closed every time.
+    _v = img.copy(); _v.thumbnail((512, 512)); _v.save(jpg, 'JPEG', quality=85)
     b64 = base64.b64encode(open(jpg, 'rb').read()).decode()
     body = json.dumps({"model": VMODEL, "prompt": PROMPT, "images": [b64], "stream": False,
                        "options": {"temperature": 0, "num_predict": 30}}).encode()

← 96e8588 fix: /api/design/:id/fix reads all_designs first (spoon fall  ·  back to Wallco Ai  ·  cactus-curator: auto-select 'Publish anyway' on gate-held (p 2547596 →