← 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
M data/rollback.ndjsonA tweak_two.py
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 →