[object Object]

← back to Novasuede Onboard

Refine 2 colorways from swatch verification: Terracotta Oatmeal->Camel, Olive Mocha->Loden (tag+body together)

28e9650fcc2f3bac78836546ea9e9d787730b699 · 2026-06-24 16:15:46 -0700 · Steve

Files touched

Diff

commit 28e9650fcc2f3bac78836546ea9e9d787730b699
Author: Steve <steve@designerwallcoverings.com>
Date:   Wed Jun 24 16:15:46 2026 -0700

    Refine 2 colorways from swatch verification: Terracotta Oatmeal->Camel, Olive Mocha->Loden (tag+body together)
---
 data/rollback.ndjson |  2 ++
 tweak_two.py         | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/data/rollback.ndjson b/data/rollback.ndjson
index bc7d894..50787c4 100644
--- a/data/rollback.ndjson
+++ b/data/rollback.ndjson
@@ -157,3 +157,5 @@
 {"id": 7821432586291, "tags": "Architectural, Cal 117, color:Navy, Commercial, Contemporary, display_variant, DWCC-112230, Fabric, Fire Rated, Microfiber Suede, Minimalist, NFPA 260, Novasuede, Royal Blue, Solid, Suede, T3CCW, Textured, UFAC Class I, Upholstery, Wallcovering", "body_html": "<p>Novasuede\u2122 Royal Blue is a premium engineered microfiber suede delivering the tactile luxury of genuine suede with superior commercial-grade performance. Ideal for hospitality, healthcare, office, and high-end residential upholstery and wallcovering applications.</p>"}
 {"id": 7867431649331, "tags": "Architectural, Cal 117, color:Onyx, Commercial, Contemporary, display_variant, DWCC-112160, Fabric, Fire Rated, Microfiber Suede, Minimalist, New Arrival, NFPA 260, Novasuede, Solid, Suede, T3A2W, Textured, UFAC Class I, Upholstery, Wallcovering", "body_html": "<p>Novasuede\u2122 Satin is a premium engineered microfiber suede delivering the tactile luxury of genuine suede with superior commercial-grade performance. Ideal for hospitality, healthcare, office, and high-end residential upholstery and wallcovering applications.</p>"}
 {"id": 7867477229619, "tags": "Architectural, Cal 117, color:Onyx, Commercial, Contemporary, display_variant, DWCC-112160, Fabric, Fire Rated, Microfiber Suede, Minimalist, New Arrival, NFPA 260, Novasuede, Solid, Suede, T3A2W, Textured, UFAC Class I, Upholstery, Wallcovering", "body_html": "<p>Novasuede\u2122 Abyss is a premium engineered microfiber suede delivering the tactile luxury of genuine suede with superior commercial-grade performance. Ideal for hospitality, healthcare, office, and high-end residential upholstery and wallcovering applications.</p>"}
+{"id": 7821431046195, "tags": "AI-Lexicon-v3, Architectural, Bohemian, Cal 117, Color: Oatmeal, Commercial, Desert Modern, display_variant, DWCC-112310, Fabric, Fire Rated, Microfiber Suede, NFPA 260, Novasuede, Oatmeal, Organic Modern, Solid, Suede, T3FCW, Terracotta, Textured, UFAC Class I, Upholstery, Wallcovering, Warm", "body_html": "<p>A warm, medium-toned Oatmeal microfiber suede exudes a rustic charm, perfect for creating an organic and serene ambiance in Desert Modern or Organic Modern interiors.</p>\n<p><strong>Color:</strong> Oatmeal (warm, medium) \u00b7 <strong>Style:</strong> Desert Modern, Organic Modern, Bohemian \u00b7 100% nylon microfiber suede, 54\" wide, Cal 117 / NFPA 260 / UFAC Class I, 100,000+ double rubs.</p>"}
+{"id": 7692852887603, "tags": "100% Nylon Fiber Matrix, AI-Lexicon-v3, Architectural, Bedroom, Cal 117, Class A Fire Rated, Color: Mocha, Commercial, display_variant, Fabric, Fire Rated, Living Room, Mediterranean, Microfiber Suede, Mid-Century Modern, Mocha, NFPA 260, Novasuede, Novasuede\u2122 Fabric & Wallcovering, Office, Olive, Organic Modern, Solid, Suede, T3PEW, Textured, UFAC Class I, Upholstery, Wallcovering, Warm", "body_html": "<p>A rich Mocha microfiber suede exudes warmth and depth, perfect for creating an organic modern ambiance in Mediterranean-inspired spaces.</p>\n<p><strong>Color:</strong> Mocha (warm, dark) \u00b7 <strong>Style:</strong> Mediterranean, Organic Modern, Mid-Century Modern \u00b7 100% nylon microfiber suede, 54\" wide, Cal 117 / NFPA 260 / UFAC Class I, 100,000+ double rubs.</p>"}
diff --git a/tweak_two.py b/tweak_two.py
new file mode 100644
index 0000000..2b08580
--- /dev/null
+++ b/tweak_two.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python3
+"""Micro-tweak two colorway names that the swatch verification refined:
+   Terracotta: Oatmeal -> Camel   (swatch reads warmer than oatmeal)
+   Olive:      Mocha   -> Loden   (dark drab green-brown; keep the olive cast)
+Changes the `Color:` tag, the bare colorway tag, AND the body text together so
+tag and prose never disagree (the 2026-06-24 QA lesson). Backs up to the same
+rollback.ndjson FIRST. Dry-run unless --commit.
+"""
+import sys, json, re, time, urllib.request, pathlib
+ROOT = pathlib.Path(__file__).resolve().parent; DATA = ROOT/"data"
+env = pathlib.Path.home()/"Projects/secrets-manager/.env"
+TOKEN = next(l.split("=",1)[1].strip().strip('"') for l in env.read_text().splitlines()
+             if l.startswith("SHOPIFY_ADMIN_TOKEN="))
+API = "https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-01"
+COMMIT = "--commit" in sys.argv
+
+TWEAKS = {7821431046195: ("Oatmeal","Camel"),     # Terracotta
+          7692852887603: ("Mocha","Loden")}       # Olive
+
+def req(method, path, body=None):
+    data = json.dumps(body).encode() if body is not None else None
+    r = urllib.request.Request(API+path, data=data, method=method,
+        headers={"X-Shopify-Access-Token":TOKEN,"Content-Type":"application/json"})
+    for _ in range(6):
+        try:
+            with urllib.request.urlopen(r, timeout=30) as resp: return json.load(resp)
+        except urllib.error.HTTPError as e:
+            if e.code==429: time.sleep(2.5); continue
+            raise
+    raise RuntimeError("retries exhausted")
+
+def retag(tags, old, new):
+    out=[]
+    for t in (x.strip() for x in tags.split(",")):
+        if t == old: out.append(new)                         # bare colorway tag
+        elif t == f"Color: {old}": out.append(f"Color: {new}")  # primary color tag
+        else: out.append(t)
+    return ", ".join(out)
+
+rb = (DATA/"rollback.ndjson").open("a") if COMMIT else None
+for pid,(old,new) in TWEAKS.items():
+    cur = req("GET", f"/products/{pid}.json?fields=id,title,tags,body_html")["product"]
+    new_tags = retag(cur["tags"], old, new)
+    # whole-word, case-sensitive body swap (handles description + the "Color: X" trailer)
+    new_body = re.sub(rf"\b{re.escape(old)}\b", new, cur["body_html"])
+    print(f"\n# {cur['title']}  ({old} -> {new})")
+    print("  tags Color: ->", [t for t in new_tags.split(", ") if t.startswith("Color:")])
+    print("  body[:140] ->", re.sub('<[^>]+>',' ',new_body).strip()[:140])
+    if COMMIT:
+        rb.write(json.dumps({"id":cur["id"],"tags":cur["tags"],"body_html":cur["body_html"]})+"\n"); rb.flush()
+        req("PUT", f"/products/{pid}.json",
+            {"product":{"id":pid,"tags":new_tags,"body_html":new_body}})
+        print("  ✓ written"); time.sleep(0.6)
+if rb: rb.close()
+print(f"\n{'COMMITTED' if COMMIT else 'DRY RUN — no writes'}")

← d827c08 Fix QA deep-name mapping (pink-deep->Plum not Garnet); note:  ·  back to Novasuede Onboard  ·  auto-save: 2026-06-26T06:12:56 (1 files) — __pycache__/plan_ d3ed3b2 →