← back to Consulting Designerwallcoverings Com

data/work-orders/EXECUTION-RUNBOOK.md

61 lines

# TK-17 Execution Runbook — Steve-approved batches → canonical DW tooling

**Prepared:** 2026-07-27 (TK-17, dw-consulting-session) · **Reversible prep only — no live write has run.**
**Steve's rulings (in-session):** Batch A **GO** · A′ **fold into A** · Batch B **canary GO** · Batch C **HOLD**.

This runbook maps each approved batch to the **existing, proven, vp-dw-commerce-owned** execution script (no hand-rolled pipeline), the exact **canary-scoped** command, verification, and rails. The live `--apply` is the **gated trigger** — per the TK-17 hard rule ("never auto-execute a live Shopify write; do reversible prep and STOP"), it runs under supervision (Steve or vp-dw-commerce), not autonomously from this prep session.

---

## Batch A + A′ — quote-tag write (9,684 SKUs)

**Vehicle:** the `tagsAdd` pattern (ref: `Designer-Wallcoverings/shopify/scripts/thibaut-mfr-tag.js`).
**Why safe:** `tagsAdd` is **append-only + idempotent** — it does NOT clobber existing tags (this closes Cody's clobber concern) and re-running is a no-op. It never touches title/price/variant/status.
**Set:** the 9,684 backlog products across the approved QUOTE lines (PJ 2,461 · Koroseal 2,454 · China Seas 1,776 · Maya Romanoff 624 · Newmor 512 · Quadrille 443 · Alan Campbell 434 · Architectural Fabrics 328 · Wolf Gordon 269 · **Home Couture 229 · Donghia 154** [A′ folded in]).
**Tag applied:** `quotes` → the product exits the backlog definition and the dead-end buy-box UX is cured; it still browses + samples.

**Canary-first (mandatory — do NOT one-shot 9,684):**
1. Generate the worklist (read-only) of the 9,684 product GIDs for these vendors.
2. `node <tag-script> --dry-run` → confirm it would append `quotes` to N products, no other tag change.
3. `--apply --limit 20` → tag 20, then **verify on the live store**: tag present, no existing tag lost, product still renders + samples, buy-box gone.
4. Scale in rate-limited waves (Shopify GraphQL cost-aware; the ~9,684 is a tag write, not variant-capped, but stage in batches with pauses and a run-report).

## Batch B — Hollywood roll variant (canary: 20 SKUs → then 813)

**Vehicle:** `Designer-Wallcoverings/shopify/scripts/bucketA-add-roll-variants.js` (owner: vp-dw-commerce). DRY-RUN by default; `--apply` live; `--limit N` canary; PG-mirror-first (writes `dw_unified.shopify_products.retail_price` before Shopify); idempotent; **never flips status**; never touches title/vendor/display_variant tag.
**Worklist (generated, read-only):** `data/work-orders/execution/batchB-hollywood-canary.tsv` — 20 rows `(shopify_id, mfr_sku, vendor, hw_price)`, real GIDs, 0 null IDs.

**⚠️ REQUIRED ADAPTATION before `--apply` (correctness gate):**
- The canonical script's `priceFor(vendor, cost)` computes `cost/0.65/0.85`. **Hollywood must price at `hw_price` directly** (it is already the customer-facing sell figure, NOT a cost). Feeding `hw_price` into the `cost/0.65/0.85` formula would MISPRICE by ~1.8×. So the script needs a one-branch add:
  ```js
  if (/hollywood/i.test(vendor)) return { rule: 'hw_price', price: round2(hwPrice) };
  ```
  and the worklist's 4th column must be read as the **price basis (hw_price)**, not a cost to be marked up.
- **`shopify_id` in the worklist is the full GID** (`gid://shopify/Product/…`). Confirm the script's `productVariantsBulkCreate` uses the GID (it does); the older PG-write path referenced a numeric id — verify the id form before `--apply`.
- **Price-ceiling flag:** reject/flag any row with `hw_price` outside $10–$100 (this canary is $44–$48; the wider `momentum_colorways` table reaches $3,578 — none in the 813, but guard anyway).

**Canary run (supervised):**
1. `node bucketA-add-roll-variants.js --dry-run` on the Hollywood worklist → confirm computed price == hw_price for all 20 (e.g. `A119-038 → $47.78`), no status change, roll SKU derived from `{mfr_sku}` correctly.
2. `--apply --limit 20` → creates the 20 roll variants, PG-first.
3. **Verify on the live store + GMC:** buy-box renders, price == hw_price (not $4.25, not 1.8× inflated), sample variant still present, GMC feed advertises the roll price. **This is where hw_price's sell-price provenance is confirmed in the real world.**
4. Only after the canary passes → scale to the remaining 793 (≤1,000 variants/day cap, ≥90 s batch gap).

## Batch C — Kravet-family MAP — HOLD (Steve ruled hold)

No write. The 3 candidates stay HOLD (`BW45141.2.0` GP&J-Baker-under-Phillipe-Romano brand fix first; `P8024114.5.0` NULL brand; `97/1002.CS.0` Cole & Son promotable-after-confirm). Optional separate task: fix the `BW45141.2.0` attribution.

## Batch D — HOLD (12,397)

No write. Awaiting vendor cost lists / trade discounts / brand fixes.

---

## Rails carried into every `--apply` (vp-dw-commerce standing)
- PostgreSQL mirror first → Shopify Admin API 2024-10 (`designer-laboratory-sandbox.myshopify.com` = LIVE store).
- Idempotent; never flip status; never surface private-label upstream names (Momentum/Versa on Hollywood).
- Canary → verify → scale; ≤1,000 variants/day; ≥90 s batch gap; run-report JSON per run.
- Token from `~/Projects/secrets-manager/.env` (`SHOPIFY_ADMIN_TOKEN`), never echoed.

## The trigger (gated)
Everything above is one supervised command from live. **Recommended:** vp-dw-commerce (or Steve) runs the Batch B `--apply --limit 20` canary + the Batch A `--apply --limit 20` tag canary, verifies, then authorizes the scale-up. I will verify results and report, but I do not fire the live `--apply` autonomously from this prep session (TK-17 hard rule).