← back to Designer Wallcoverings
snapshot: sweep uncommitted working tree — TK-11503 explicit-mode guard sweep, $0/weight/re-intro activation guards, Kravet MAP-pricing fixes + accumulated drift
9ef06c30e24a6641a330f3ffc9081a7ae60f9ead · 2026-09-22 15:01:07 -0700 · Steve Abrams
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V4aFgngtRw1gy1rEQbfoPH
Files touched
A tk12015-deploy-guards.sh
Diff
commit 9ef06c30e24a6641a330f3ffc9081a7ae60f9ead
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Tue Sep 22 15:01:07 2026 -0700
snapshot: sweep uncommitted working tree — TK-11503 explicit-mode guard sweep, $0/weight/re-intro activation guards, Kravet MAP-pricing fixes + accumulated drift
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V4aFgngtRw1gy1rEQbfoPH
---
tk12015-deploy-guards.sh | 205 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 205 insertions(+)
diff --git a/tk12015-deploy-guards.sh b/tk12015-deploy-guards.sh
new file mode 100755
index 00000000..e6c16f0e
--- /dev/null
+++ b/tk12015-deploy-guards.sh
@@ -0,0 +1,205 @@
+#!/usr/bin/env bash
+# ============================================================================
+# TK-12015 — turnkey, drift-safe deploy for two reviewed prod patches
+# Phase 2a: shopify/scripts/cadence/cadence-import.js (leak denylists + scanPublicLeak)
+# Phase 2b: DW-Programming/ImportNewSkufromURL/{import/sku,create-product}/route.ts + lib/banned-words.ts
+#
+# DTD verdict C — VERIFY-DRIFT-FIRST per file:
+# box == EDITED -> already deployed (no-op, idempotent)
+# box == PRISTINE -> clean, no drift -> back up box then copy the reviewed EDITED file up
+# box == neither -> DRIFT -> DO NOT overwrite; print drift + surgical hunks; MANUAL
+#
+# Steve runs this (ssh/scp run under his shell). It NEVER overwrites a file it flags drifted,
+# backs up every box file before writing, verifies each write, and is safe to re-run.
+# $0 local except the ssh/scp round-trips + the gated build/restart it performs on the box.
+# ============================================================================
+set -uo pipefail
+
+BOX="root@45.61.58.125"
+LOCAL_ROOT="$HOME/Projects/Designer-Wallcoverings"
+SHOPIFY_REPO="$LOCAL_ROOT/shopify"
+DWP_REPO="$LOCAL_ROOT/DW-Programming"
+
+# Pinned commits (created by stack-refactor-deployprep). edited = commit, pristine = commit~1.
+SHOPIFY_EDITED="32ec10997dce8c35a365c750dcf0fc2a563edbd8"
+DWP_EDITED="66f1e6a5e783383d7704cc31e888916f732a12d8"
+
+TS="$(date +%Y%m%d-%H%M%S)"
+WORK="$(mktemp -d /tmp/tk12015-deploy.XXXXXX)"
+trap 'rm -rf "$WORK"' EXIT
+
+APPLIED_CADENCE=0
+APPLIED_9830=0
+declare -a RESULTS=()
+
+C_RED='\033[0;31m'; C_GRN='\033[0;32m'; C_YEL='\033[1;33m'; C_CYA='\033[0;36m'; C_RST='\033[0m'
+say() { printf '%b\n' "$*"; }
+hr() { printf '%s\n' "----------------------------------------------------------------------"; }
+
+# ---- per-file surgical hunks (printed only when a file is MANUAL) --------------
+surgical_hunks() {
+ case "$1" in
+ cadence-import.js)
+cat <<'HUNKS'
+ MEMO: ~/.claude/yolo-queue/pending-approval/TK-12015-phase2a-cadence-chokepoint-leakguard.md
+ EDIT 1 — extend scrubBanned() (change the Carlsten line's terminating ';' to '' and append):
+ .replace(/\bGreenland\b/gi, '')
+ .replace(/\bMomentum(?:\s+Textiles(?:\s*&(?:amp;)*\s*Walls)?)?\b/gi, '')
+ .replace(/\bVersa(?:\s+Designed\s+Surfaces)?\b/gi, '')
+ .replace(/\bRigo(?:\s+Wallcovering)?\b/gi, '')
+ .replace(/\bTokiwa(?:\s+USA)?\b/gi, '');
+ EDIT 2 — append to bannedBrandReason() RULES (after the Carlsten rule):
+ [/\bGreenland\b/i, '"Greenland" is a banned private-label upstream (→ Phillipe Romano)'],
+ [/\bMomentum\b/i, '"Momentum" is a banned private-label upstream (→ Hollywood Wallcoverings)'],
+ [/\bVersa\b/i, '"Versa"/"Versa Designed Surfaces" is a banned Momentum sub-brand'],
+ [/\bRigo\b/i, '"Rigo" is a banned private-label upstream (→ Phillipe Romano)'],
+ [/\bTokiwa\b/i, '"Tokiwa" is a banned private-label upstream (→ Fentucci Naturals)'],
+ EDIT 3 — add function scanPublicLeak(input) immediately AFTER bannedBrandReason() (see memo for full body).
+ EDIT 4 — in pushOne() hold block: compute `const leaks = scanPublicLeak(payload.input);`,
+ change `if (hold)` to `if (hold || leaks.length)`, and return err `HELD: ${why}` where
+ why = hold ? `banned front-facing Brand (${hold})` : `LEAK: ${leaks.join('; ')}`.
+HUNKS
+ ;;
+ sku-route.ts)
+cat <<'HUNKS'
+ MEMO: ~/.claude/yolo-queue/pending-approval/TK-12015-phase2b-createproduct-privatelabel-fallback.md
+ EDIT 1a (~L384) — change `const privateLabel = ...` to `let privateLabel = url.searchParams.get('privateLabel') === 'true';`
+ EDIT 1b — in the body-parse branch, after `sourceUrl = body.source;` add:
+ if (body.privateLabel === true || body.privateLabel === 'true') privateLabel = true;
+HUNKS
+ ;;
+ create-product-route.ts)
+cat <<'HUNKS'
+ MEMO: ~/.claude/yolo-queue/pending-approval/TK-12015-phase2b-createproduct-privatelabel-fallback.md
+ EDIT — add scanPublicLeak to the banned-words import, then inside the try{} after validateTitle():
+ import { cleanWallpaper, validateTitle, scanPublicLeak } from '@/lib/banned-words';
+ ...
+ validateTitle(productDTO.title);
+ scanPublicLeak({ title: productDTO.title, vendor: (productDTO as any).vendor,
+ bodyHtml: (productDTO as any).bodyHtml, tags: (productDTO as any).tags });
+HUNKS
+ ;;
+ banned-words.ts)
+cat <<'HUNKS'
+ MEMO: ~/.claude/yolo-queue/pending-approval/TK-12015-phase2b-createproduct-privatelabel-fallback.md
+ EDIT — append REAL_VENDOR_DENYLIST (Array<[RegExp,string]>) + export function scanPublicLeak(p)
+ that throws on any banned real-vendor term in title/vendor/bodyHtml/tags (see memo for full body).
+HUNKS
+ ;;
+ esac
+}
+
+# process_file <name> <box_path> <repo_dir> <edited_sha> <relpath> <kind:cadence|9830|9830-nobuild>
+process_file() {
+ local name="$1" boxpath="$2" repo="$3" sha="$4" rel="$5" kind="$6"
+ hr; say "${C_CYA}== $name ==${C_RST}"
+ say " box: $boxpath"
+
+ local pristine="$WORK/pristine-$name" edited="$WORK/edited-$name" boxcopy="$WORK/box-$name"
+
+ # 1. extract pinned pristine + edited from local git (deterministic, branch-independent)
+ if ! git -C "$repo" show "${sha}~1:${rel}" > "$pristine" 2>"$WORK/err"; then
+ say "${C_RED} ERROR: cannot read PRISTINE (${sha}~1:${rel}) — $(cat "$WORK/err")${C_RST}"
+ RESULTS+=("ERROR $name (pristine unreadable)"); return
+ fi
+ if ! git -C "$repo" show "${sha}:${rel}" > "$edited" 2>"$WORK/err"; then
+ say "${C_RED} ERROR: cannot read EDITED (${sha}:${rel}) — $(cat "$WORK/err")${C_RST}"
+ RESULTS+=("ERROR $name (edited unreadable)"); return
+ fi
+
+ # 2. pull the current box copy
+ if ! scp -q "$BOX:$boxpath" "$boxcopy" 2>"$WORK/err"; then
+ say "${C_RED} UNREACHABLE: scp down failed — $(cat "$WORK/err")${C_RST}"
+ RESULTS+=("MANUAL $name (box unreachable — deploy by hand)"); return
+ fi
+
+ # 3. three-way verdict (idempotent: check EDITED first so a re-run is a clean no-op)
+ if diff -q "$boxcopy" "$edited" >/dev/null 2>&1; then
+ say "${C_GRN} ALREADY DEPLOYED — box already == reviewed edited file (no-op).${C_RST}"
+ RESULTS+=("PASS $name (already deployed)")
+ return
+ fi
+
+ if ! diff -q "$boxcopy" "$pristine" >/dev/null 2>&1; then
+ # box differs from BOTH edited and pristine -> genuine drift. NEVER overwrite.
+ say "${C_YEL} DRIFT DETECTED — box differs from the reviewed pristine baseline. NOT overwriting.${C_RST}"
+ say "${C_YEL} --- drift (pristine -> box) ---${C_RST}"
+ diff -u "$pristine" "$boxcopy" | sed 's/^/ /' | head -120
+ say "${C_YEL} --- apply these surgical hunks on the box by hand ---${C_RST}"
+ surgical_hunks "$name" | sed 's/^/ /'
+ RESULTS+=("MANUAL $name (DRIFT — surgical hunks printed above)")
+ return
+ fi
+
+ # 4. CLEAN (box == pristine): back up box, then copy edited up, then verify the write.
+ say "${C_GRN} CLEAN (box == pristine). Backing up + deploying reviewed file...${C_RST}"
+ if ! ssh "$BOX" "cp -p '$boxpath' '$boxpath.bak-$TS'" 2>"$WORK/err"; then
+ say "${C_RED} ERROR: backup failed, NOT writing — $(cat "$WORK/err")${C_RST}"
+ RESULTS+=("ERROR $name (backup failed, not written)"); return
+ fi
+ say " backup: $boxpath.bak-$TS"
+ if ! scp -q "$edited" "$BOX:$boxpath" 2>"$WORK/err"; then
+ say "${C_RED} ERROR: scp up failed — $(cat "$WORK/err")${C_RST}"
+ RESULTS+=("ERROR $name (write failed — box unchanged, backup present)"); return
+ fi
+ # verify write landed byte-identical to edited
+ scp -q "$BOX:$boxpath" "$WORK/verify-$name" 2>/dev/null
+ if diff -q "$WORK/verify-$name" "$edited" >/dev/null 2>&1; then
+ say "${C_GRN} DEPLOYED + verified byte-identical.${C_RST}"
+ RESULTS+=("PASS $name (deployed)")
+ case "$kind" in cadence) APPLIED_CADENCE=1;; 9830) APPLIED_9830=1;; esac
+ else
+ say "${C_RED} ERROR: post-write verify MISMATCH. Restore: ssh $BOX \"cp '$boxpath.bak-$TS' '$boxpath'\"${C_RST}"
+ RESULTS+=("ERROR $name (verify mismatch — restore from .bak-$TS)")
+ fi
+}
+
+say "${C_CYA}TK-12015 drift-safe deploy — $(date)${C_RST}"
+say "box=$BOX ts=$TS"
+
+# ---- the 4 target files ------------------------------------------------------
+process_file "cadence-import.js" \
+ "/root/Projects/Designer-Wallcoverings/shopify/scripts/cadence/cadence-import.js" \
+ "$SHOPIFY_REPO" "$SHOPIFY_EDITED" "scripts/cadence/cadence-import.js" "cadence"
+
+process_file "sku-route.ts" \
+ "/root/Projects/Designer-Wallcoverings/DW-Programming/ImportNewSkufromURL/app/api/import/sku/route.ts" \
+ "$DWP_REPO" "$DWP_EDITED" "ImportNewSkufromURL/app/api/import/sku/route.ts" "9830"
+
+process_file "create-product-route.ts" \
+ "/root/Projects/Designer-Wallcoverings/DW-Programming/ImportNewSkufromURL/app/api/create-product/route.ts" \
+ "$DWP_REPO" "$DWP_EDITED" "ImportNewSkufromURL/app/api/create-product/route.ts" "9830"
+
+process_file "banned-words.ts" \
+ "/root/Projects/Designer-Wallcoverings/DW-Programming/ImportNewSkufromURL/lib/banned-words.ts" \
+ "$DWP_REPO" "$DWP_EDITED" "ImportNewSkufromURL/lib/banned-words.ts" "9830"
+
+# ---- post-deploy verification (only when something changed this run) ---------
+if [ "$APPLIED_CADENCE" = "1" ]; then
+ hr; say "${C_CYA}== cadence-import.js changed -> dry-run ==${C_RST}"
+ ssh "$BOX" "cd /root/Projects/Designer-Wallcoverings/shopify/scripts/cadence && node cadence-import.js --dry-run 2>&1 | tail -40"
+fi
+
+if [ "$APPLIED_9830" = "1" ]; then
+ hr; say "${C_CYA}== :9830 file(s) changed -> npm run build && pm2 restart ==${C_RST}"
+ ssh "$BOX" "cd /root/Projects/Designer-Wallcoverings/DW-Programming/ImportNewSkufromURL && npm run build && pm2 restart ImportNewSkufromURL-9830 && pm2 logs ImportNewSkufromURL-9830 --lines 20 --nostream"
+fi
+
+# ---- summary -----------------------------------------------------------------
+hr; say "${C_CYA}SUMMARY${C_RST}"; hr
+manual=0; err=0
+for r in "${RESULTS[@]}"; do
+ case "$r" in
+ PASS*) say "${C_GRN} $r${C_RST}";;
+ MANUAL*) say "${C_YEL} $r${C_RST}"; manual=1;;
+ ERROR*) say "${C_RED} $r${C_RST}"; err=1;;
+ esac
+done
+hr
+if [ "$err" = "1" ]; then
+ say "${C_RED}RESULT: ERRORS present — review above. Backups are at <path>.bak-$TS on the box.${C_RST}"; exit 1
+elif [ "$manual" = "1" ]; then
+ say "${C_YEL}RESULT: MANUAL action needed on the drifted/unreachable file(s) above (surgical hunks printed). Clean files deployed.${C_RST}"; exit 2
+else
+ say "${C_GRN}RESULT: ALL PASS — every target deployed (or already deployed) + verified.${C_RST}"; exit 0
+fi
← 8dca38a7 trade-retag: guard empty --query and log preimage only after
·
back to Designer Wallcoverings
·
snapshot before /code-review ultra — TK-11786 review fixes ( d9142ec0 →