← back to Dw Pairs Well
deploy/block2-clip-flip.sh
57 lines
#!/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 — update-or-append so an existing =0 line cannot silently win
cd /root/Projects/dw-pairs-well
for K in PAIRS_CLIP_DEFAULT SIMILAR_CLIP_DEFAULT; do
if grep -q "^${K}=" .env 2>/dev/null; then sed -i "s/^${K}=.*/${K}=1/" .env
else echo "${K}=1" >> .env; fi
done
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 ──"