← back to Dw Contact Us Pages
approval memo copy
4c198c42240071a77bbeaf259cb26a90c434f6f8 · 2026-09-19 10:26:18 -0700 · Steve Abrams
Files touched
Diff
commit 4c198c42240071a77bbeaf259cb26a90c434f6f8
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Sat Sep 19 10:26:18 2026 -0700
approval memo copy
---
docs-memo-copy.md | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 70 insertions(+)
diff --git a/docs-memo-copy.md b/docs-memo-copy.md
new file mode 100644
index 0000000..ef85671
--- /dev/null
+++ b/docs-memo-copy.md
@@ -0,0 +1,70 @@
+# TK-11925 — Designers Guild + Ralph Lauren + Christian Lacroix → "contact-us" product pages (785 ACTIVE)
+
+**Ticket:** TK-11925-designers-guild-contact-us-pages-568-act · **Owner:** vp-dw-commerce (executor: claude-run-11925) · **Drafted:** 2026-09-19
+**Store:** designer-laboratory-sandbox.myshopify.com = the LIVE DW store · **Live theme:** 145556635699 (role main)
+**Scope (Steve, in-session 2026-09-19):** ALL ACTIVE products of vendors "Designers Guild", "Ralph Lauren", "Christian Lacroix Europe". NOT Quadrille.
+**Steve's CLARIFY answers (2026-09-19):** (1) Hide + HARDEN · (2) Unpublish from Google & YouTube + Shop + Buy Button only · (3) Boost grid cards show "Contact us for pricing".
+
+## What the customer sees after approval
+- Product page: image gallery → **contact block directly below the image** (phone (888) 373-4564 · info@ mailto with SKU prefilled · inline "request pricing & availability" form posting to the existing /api/sku-inquiry pipeline) · title/vendor/SKU/description on the right. **No price, no add-to-cart, no $4.25 sample button.**
+- Collection / search cards (Boost): price replaced by "Contact us for pricing" for the 3 vendors.
+- Roll/yard variants: inventory policy DENY + on-hand 0, so a cart permalink or the public .json cannot complete a purchase (the price STRING remains visible in /products/<handle>.json — Shopify cannot hide it; see residuals).
+- Google & YouTube / Shop / Buy Button: products unpublished → no GMC price/availability mismatch. Online Store, FB/IG, Pinterest, TikTok, Houzz, POS unchanged.
+
+## Blast radius (measured live 2026-09-19)
+| Item | Count |
+|---|---|
+| Products (DG / RL / CL) | 785 (568 / 140 / 77) |
+| Non-sample variants to harden (DENY + 0) | 737 (598 currently UNTRACKED + CONTINUE → tracking enabled then on_hand 0; 139 tracked with stock → on_hand 0; 48 products are sample-only, nothing to harden) |
+| Sample variants (untouched) | 785 (783 × $4.25, 1 × $3.50, 1 × $5.00) |
+| Publications to remove (products × 3 channels, only where currently published) | 2,355 (785 × 3, all currently published) |
+| Theme assets written on 145556635699 | 7 (new: templates/product.contact-us.json, snippets/dw-contact-us-block.liquid, assets/dw-contact-us-cards.js · edited: snippets/product.liquid (+1 gated render line), snippets/hide-browse-hidden.liquid (+1 script tag + vendor list), snippets/product-list-item.liquid (+1 template_suffix branch), layout/theme.liquid (JSON-LD Offer carve-out extended from the existing Newmor condition to product.template_suffix == contact-us); live preimage of all 4 already captured in data/theme-preimage/145556635699/) |
+
+## Mechanism
+1. **Alternate template** `templates/product.contact-us.json` — the live product template minus the `price` and `form` blocks (the buy box iterates `section.blocks`, so no price / cart / sample markup is emitted at all — not hidden, absent). `description` block enabled.
+2. **Contact block** `snippets/dw-contact-us-block.liquid`, rendered by a one-line additive edit in `snippets/product.liquid` immediately after the gallery, gated on `template.suffix == 'contact-us'`. Zero effect on any other template. Belt-and-braces CSS under `body.template-suffix-contact-us` (theme.liquid already stamps that body class).
+3. **Cards** `assets/dw-contact-us-cards.js` (MutationObserver over `.boost-sd__product-item`, same pattern as the live dw-showroom-hide.js) + a `template_suffix` branch in `snippets/product-list-item.liquid` for the liquid-rendered path. Vendor list data-driven (shop metafield → theme setting → literal fallback), mirroring `showroom_vendors`.
+4. **Product writes** (scripts, preimage-first, ledgered): `assign-template` (templateSuffix → contact-us) · `harden-variants` (non-sample: DENY + 0 at every location) · `unpublish-channels` (3 publication ids).
+
+## Order of operations (each step dry-runs first; every step writes its preimage BEFORE the first write)
+```
+cd ~/Projects/dw-contact-us-pages
+node scripts/enumerate.mjs # refresh data/targets.json (read-only)
+node scripts/push-theme.mjs --theme 145556635699 --allow-main --apply # theme preimage → data/theme-preimage/145556635699/
+node scripts/assign-template.mjs --apply # ledger: data/ledger-template.jsonl
+# RECOMMENDED: run harden once with --limit 1 (one RL product) and eyeball Shopify admin before the full run
+# (inventorySetQuantities right after tracked:true is the one call that could not be dry-run-proven)
+node scripts/harden-variants.mjs --apply # ledger: data/ledger-variants.jsonl
+node scripts/unpublish-channels.mjs --apply # ledger: data/ledger-channels.jsonl
+node scripts/verify.mjs # PASS/FAIL table: PDP has no cart/price, block present, .json roll unavailable
+```
+Optional safer sequencing: run push-theme against an unpublished DUPLICATE of the live theme first (Admin → Themes → Duplicate), preview a DG product with `?preview_theme_id=<id>&view=contact-us`, then run against main.
+
+## Rollback (exact, per step, independent)
+```
+node scripts/unpublish-channels.mjs --rollback --apply # republish exactly what was published
+node scripts/harden-variants.mjs --rollback --apply # restore policy + per-location quantities from ledger
+node scripts/assign-template.mjs --rollback --apply # restore old templateSuffix per product
+node scripts/rollback-theme.mjs --theme 145556635699 --apply # restore edited assets from preimage, delete new ones
+```
+
+## Gate classification
+Customer-facing Shopify writes (theme publish on the live main theme + 785 product/variant/channel writes) → **HARD GATE, Steve's yes required.** Reversible (recorded undo for every write), no spend, no send-to-list, no DNS, no remote push. Blast radius > 500 items → flagged.
+
+## Residual risks / things Steve should know
+- `/products/<handle>.json` and `.js` still expose the roll variant's price STRING (available:false after hardening). Shopify has no switch for this. Only removing the variant would hide it — not proposed (destroys pricing data).
+- Boost cards depend on a JS hook; if Boost changes its card markup the price could reappear on grids (page stays clean because the template has no price block). verify.mjs checks a live grid.
+- Canary interactions: dw-five-field-canary counts "has sellable variant / complete pricing" — these products still have priced variants so it should not regress; the zero-price tripwires watch $0 variants with qty>0 — we set qty 0, the opposite direction. dw-active-weight-canary unaffected.
+- GMC: unpublishing from Google & YouTube removes the offers on the next channel sync (gmc-push-freshness-canary may show a one-time drop of ~785 offers).
+- Sample orders: customers can no longer order a $4.25 sample of these lines online; the contact block invites a request instead. (If Steve wants samples back for one vendor, the `form` block could be restored in a per-vendor template variant.)
+- Quick-shop modal: opening a DG/RL/CL card's quick view would have rendered the quickshop template (price + cart) — mitigated three ways (block/CSS gated on product.template_suffix, .dw-contact-us-product wrapper class, card JS removes quick-view triggers). NOT browser-verified before apply; verify.mjs cannot see Boost's client-side DOM — eyeball one collection after apply.
+- Ralph Lauren "Minimum order: N yards" notice renders outside the block loop; hidden by CSS only (verify reports WARN, not FAIL).
+- Reversing the vendor→contact-us decision later = the four rollback commands above; the template files can stay in the theme harmlessly.
+
+## Files
+Repo: ~/Projects/dw-contact-us-pages (git, local only) — commits: 0158453 … b8b6045 (14 commits; scripts dry-run verified, push-theme write to main REFUSED without --allow-main in a negative test)
+Preimage snapshot (read-only capture before any write): /private/tmp/claude-501/-Users-macstudio3/209bfc7d-5bb8-4376-a8c3-a55dd4e3b2b3/scratchpad/preimage/preimage.json (785 products, captured 2026-09-19T17:02Z, copied into the repo data/ dir)
+Contrarian review: Cody (contrarian agent) verdict FIX FIRST → all 3 HIGH findings fixed in 942c738 + 2b12c68 (ledger-before-write, ledger-only-on-truth, JSON-LD Offer carve-out); MED findings #4 min-order notice (CSS-hidden + verify WARN), #5 quick-shop (gated on product.template_suffix + wrapper-class CSS + card JS strips quick-view triggers), #6 stale preimage (2h freshness guard, enumerate is step 1) folded in; #7 eur-90463 (onlineStoreUrl null) = manual eyeball after apply · Second-model check: Codex spend-capped (429) → Kimi kimi-k3 review ($0.019): confirmed 2024-10 mutation shapes; flagged null-payload-as-success, 200-row qty batches (cap 100), template rollback '' vs null, HTTP-throw aborting the run — all fixed in 2b12c68
+
+## APPROVE / REVISE / BLOCK
+vp-dw-commerce recommendation: **APPROVE** — vendor-policy-driven, fully reversible, preimage-first, matches Steve's three CLARIFY answers.
← b8b6045 harden-variants --limit N canary flag; README review-driven
·
back to Dw Contact Us Pages
·
TK-11925: add Nina Campbell (433 active) to contact-us cohor 4a9eb58 →