← back to Dw Pairs Well
yolo contrarian fixes: freshness+rowcount+live-spot gates in fix-osp-kamatera.sh; export-osp-flags.sh writes provenance .meta; block2-clip-flip.sh with hard PASS/ABORT prompt, link-check precondition, validated pm2 target (no guessing); 12/12 empirical flag-vs-live verification OK
bd214fc9b55ba793326899395d275161b12ecff3 · 2026-07-13 02:01:55 -0700 · Steve Abrams
Files touched
M .gitignoreA deploy/block2-clip-flip.shA deploy/export-osp-flags.shM deploy/fix-osp-kamatera.sh
Diff
commit bd214fc9b55ba793326899395d275161b12ecff3
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Mon Jul 13 02:01:55 2026 -0700
yolo contrarian fixes: freshness+rowcount+live-spot gates in fix-osp-kamatera.sh; export-osp-flags.sh writes provenance .meta; block2-clip-flip.sh with hard PASS/ABORT prompt, link-check precondition, validated pm2 target (no guessing); 12/12 empirical flag-vs-live verification OK
---
.gitignore | 1 +
deploy/block2-clip-flip.sh | 53 ++++++++++++++++++++++++++++++++++++++++++++++
deploy/export-osp-flags.sh | 12 +++++++++++
deploy/fix-osp-kamatera.sh | 17 +++++++++++++++
4 files changed, 83 insertions(+)
diff --git a/.gitignore b/.gitignore
index bf5ad72..001755a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,3 +20,4 @@ tools/ci-hashes.jsonl
tools/pattern-id-by-dwsku.json
tools/pattern-id-titlefirst-by-dwsku.json
deploy/osp-flags.tsv
+deploy/osp-flags.meta
diff --git a/deploy/block2-clip-flip.sh b/deploy/block2-clip-flip.sh
new file mode 100755
index 0000000..725b85c
--- /dev/null
+++ b/deploy/block2-clip-flip.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+# Block 2 — update Kamatera's visual-search service + flip CLIP defaults for pairs-well.
+# HARD-GATED version (contrarian findings 2026-07-13): link-check must PASS first,
+# Steve must type PASS at the prompt, and the pm2 process name is validated (no guessing).
+# RUN FROM MAC2: bash ~/Projects/dw-pairs-well/deploy/block2-clip-flip.sh
+set -euo pipefail
+cd "$(dirname "$0")/.."
+
+echo "── precondition: live link check must PASS (run after Item 1 / fix-osp-kamatera.sh) ──"
+RES=$(BASE=https://pairs.designerwallcoverings.com STORE=https://designerwallcoverings.com N=5 bash tools/live-link-check.sh | tail -1)
+echo "$RES"
+[[ "$RES" == *PASS* ]] || { echo "ABORT: link guarantee not PASS — run fix-osp-kamatera.sh first"; exit 1; }
+
+echo
+echo "── customer-facing default flip ahead: PAIRS_CLIP_DEFAULT=1 + SIMILAR_CLIP_DEFAULT=1 ──"
+echo "Eyeball first if you want: https://pairs.designerwallcoverings.com/api/similar?dw_sku=BGA-47951&engine=clip&limit=6"
+read -p "Type PASS to proceed with the CLIP flip, anything else aborts: " ans
+[ "$ans" = "PASS" ] || { echo "aborted by operator"; exit 1; }
+
+echo "── push updated visual-search service + gap embedder ──"
+rsync -az ~/Projects/dw-photo-capture/visual-search/search_service.py \
+ ~/Projects/dw-photo-capture/visual-search/embed_shopify_gap.py \
+ root@45.61.58.125:/root/public-projects/dwphoto/visual-search/
+
+ssh root@45.61.58.125 'set -e
+ # validate the pm2 process that owns :9914 — abort loudly rather than guess
+ PROC=$(pm2 jlist | python3 -c "
+import sys, json
+for p in json.load(sys.stdin):
+ port = str(p.get(\"pm2_env\", {}).get(\"env\", {}).get(\"VS_PORT\", \"\"))
+ name = p[\"name\"]
+ if port == \"9914\" or \"visual\" in name.lower():
+ print(name); break
+")
+ [ -n "$PROC" ] || { echo "ABORT: no pm2 process matches visual-search/:9914 — find it with pm2 ls"; exit 1; }
+ echo "restarting pm2 process: $PROC"
+ pm2 restart "$PROC"
+ sleep 25
+ curl -sf http://127.0.0.1:9914/health || { echo "ABORT: :9914 unhealthy after restart"; exit 1; }
+
+ # embed the shopify-only gap on Kamatera (resumable, background)
+ cd /root/public-projects/dwphoto/visual-search
+ export DW_UNIFIED_DB="$(grep ^DW_UNIFIED_DB= ../.env | cut -d= -f2-)"
+ nohup nice -n 15 python3 embed_shopify_gap.py --workers 16 > gap-embed.log 2>&1 &
+
+ # flip CLIP defaults
+ cd /root/Projects/dw-pairs-well
+ grep -q PAIRS_CLIP_DEFAULT .env 2>/dev/null || printf "PAIRS_CLIP_DEFAULT=1\nSIMILAR_CLIP_DEFAULT=1\n" >> .env
+ pm2 restart dw-pairs-well
+ sleep 6
+ curl -sf https://pairs.designerwallcoverings.com/healthz >/dev/null && echo "pairs-well healthy, CLIP defaults ON"
+'
+echo "── done. Re-verify: BASE=https://pairs.designerwallcoverings.com N=8 bash tools/live-link-check.sh ──"
diff --git a/deploy/export-osp-flags.sh b/deploy/export-osp-flags.sh
new file mode 100755
index 0000000..02a1400
--- /dev/null
+++ b/deploy/export-osp-flags.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+# Export online_store_published flags from the LOCAL dw_unified mirror, with the
+# provenance metadata fix-osp-kamatera.sh asserts on (export timestamp + row count).
+set -euo pipefail
+cd "$(dirname "$0")"
+psql -d dw_unified -h /tmp -tA -F$'\t' -c \
+ "SELECT shopify_id, online_store_published FROM shopify_products WHERE shopify_id IS NOT NULL AND online_store_published IS NOT NULL;" \
+ > osp-flags.tsv
+ROWS=$(wc -l < osp-flags.tsv | tr -d ' ')
+printf 'exported_at=%s\nrows=%s\nsource=local dw_unified mirror (Mac2, /tmp socket)\n' \
+ "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$ROWS" > osp-flags.meta
+echo "exported $ROWS rows → osp-flags.tsv (+ .meta)"
diff --git a/deploy/fix-osp-kamatera.sh b/deploy/fix-osp-kamatera.sh
index 08cd2e8..6a7a701 100755
--- a/deploy/fix-osp-kamatera.sh
+++ b/deploy/fix-osp-kamatera.sh
@@ -10,6 +10,23 @@ cd "$(dirname "$0")"
[ -s osp-flags.tsv ] || { echo "osp-flags.tsv missing — re-export from local mirror first"; exit 1; }
+# ── Freshness + provenance gates (contrarian findings, 2026-07-13) ──
+# 1. Export must be <24h old (companion .meta written by the exporter).
+[ -s osp-flags.meta ] || { echo "osp-flags.meta missing — re-export (export-osp-flags.sh)"; exit 1; }
+EXPORT_TS=$(grep '^exported_at=' osp-flags.meta | cut -d= -f2)
+AGE_H=$(( ( $(date +%s) - $(date -j -f '%Y-%m-%dT%H:%M:%SZ' "$EXPORT_TS" +%s 2>/dev/null || echo 0) ) / 3600 ))
+[ "$AGE_H" -lt 24 ] || { echo "osp-flags.tsv is ${AGE_H}h old (>24h) — re-export first"; exit 1; }
+# 2. Row-count sanity: the active catalog carries >70k flag rows.
+ROWS=$(wc -l < osp-flags.tsv | tr -d ' ')
+[ "$ROWS" -gt 70000 ] || { echo "osp-flags.tsv has only $ROWS rows (<70k) — refusing"; exit 1; }
+# 3. Spot provenance: a published + an unpublished sample must match the LIVE store.
+SPOT_T=$(grep -m1 $'\tt$' osp-flags.tsv >/dev/null && psql -d dw_unified -h /tmp -tA -c "SELECT handle FROM shopify_products WHERE status='ACTIVE' AND online_store_published IS TRUE AND handle IS NOT NULL LIMIT 1")
+SPOT_F=$(psql -d dw_unified -h /tmp -tA -c "SELECT handle FROM shopify_products WHERE status='ACTIVE' AND online_store_published IS FALSE AND handle IS NOT NULL LIMIT 1")
+CT=$(curl -s -o /dev/null -w '%{http_code}' --max-time 15 -L "https://designerwallcoverings.com/products/$SPOT_T")
+CF=$(curl -s -o /dev/null -w '%{http_code}' --max-time 15 -L "https://designerwallcoverings.com/products/$SPOT_F")
+[ "$CT" = 200 ] && [ "$CF" = 404 ] || { echo "provenance spot check FAILED (published→$CT expected 200, unpublished→$CF expected 404) — mirror flags don't match live store, DO NOT SYNC"; exit 1; }
+echo "gates passed: age ${AGE_H}h · $ROWS rows · live spot check 200/404 ✓"
+
scp -q osp-flags.tsv root@45.61.58.125:/tmp/osp-flags.tsv
ssh root@45.61.58.125 'set -e
← 73efede deps: bump qs to 6.15.3 via npm audit fix (GHSA-q8mj-m7cp-5q
·
back to Dw Pairs Well
·
auto-save: 2026-07-13T08:23:39 (1 files) — 5x/live-sweep-1.m 779cabe →