← back to Designerwallcoverings
TK-11679: curated colorway-facet un-truncation list (GET-verified) + gated reversible apply path
8544b4b0b407275005b0c56040f8861fd5a9f487 · 2026-09-14 00:37:23 -0700 · Steve
15 live Versace/Ultrasuede products carry a truncated color: facet (leading colour word dropped
by the first-comma parser). Curated per-product title-read corrections + reversible apply/rollback.
1 Romo ambiguous (Steve to name), 2 Rebel Walls correct-and-excluded, 15 not-yet-written cataloged.
GET-only verification; no Shopify/dw_unified writes fired.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RePUgpi4TWMrHo68U8ckpT
Files touched
A scripts/colorway-title-anchor/out/tk11679-curated-corrections.jsonA scripts/colorway-title-anchor/out/tk11679-live-verify.jsonA scripts/colorway-title-anchor/tk11679-apply-corrections.mjsA scripts/colorway-title-anchor/tk11679-build-correction-list.mjsA scripts/colorway-title-anchor/tk11679-verify-live.mjs
Diff
commit 8544b4b0b407275005b0c56040f8861fd5a9f487
Author: Steve <steve@designerwallcoverings.com>
Date: Mon Sep 14 00:37:23 2026 -0700
TK-11679: curated colorway-facet un-truncation list (GET-verified) + gated reversible apply path
15 live Versace/Ultrasuede products carry a truncated color: facet (leading colour word dropped
by the first-comma parser). Curated per-product title-read corrections + reversible apply/rollback.
1 Romo ambiguous (Steve to name), 2 Rebel Walls correct-and-excluded, 15 not-yet-written cataloged.
GET-only verification; no Shopify/dw_unified writes fired.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RePUgpi4TWMrHo68U8ckpT
---
.../out/tk11679-curated-corrections.json | 373 +++++++++++++++++++++
.../out/tk11679-live-verify.json | 348 +++++++++++++++++++
.../tk11679-apply-corrections.mjs | 132 ++++++++
.../tk11679-build-correction-list.mjs | 98 ++++++
.../colorway-title-anchor/tk11679-verify-live.mjs | 116 +++++++
5 files changed, 1067 insertions(+)
diff --git a/scripts/colorway-title-anchor/out/tk11679-curated-corrections.json b/scripts/colorway-title-anchor/out/tk11679-curated-corrections.json
new file mode 100644
index 0000000..83db037
--- /dev/null
+++ b/scripts/colorway-title-anchor/out/tk11679-curated-corrections.json
@@ -0,0 +1,373 @@
+{
+ "ticket": "TK-11679",
+ "spun_from": "TK-11076",
+ "ts": "2026-09-14T07:35:57.497Z",
+ "source_of_truth": "live GET (Shopify Admin 2024-10) 2026-09-14; evidence out/tk11076-residual-comma-truncation.json",
+ "metafield_target": "custom.real_color_name (single_line_text_field, verbatim comma form)",
+ "facet_tag_form": "color:<A / B / C> (Shopify tags split on comma, so commas -> \" / \" for the TAG only)",
+ "summary": {
+ "curated_live_corrections": 15,
+ "ambiguous_live_needs_steve": 1,
+ "excluded_rebel_correct": 2,
+ "pending_not_yet_written": 15,
+ "pending_obvious": 11,
+ "pending_needs_adjudication": 4
+ },
+ "corrections": [
+ {
+ "handle": "baroque-round-ornament-black-gold-silver-wallcovering-versace",
+ "product_gid": "gid://shopify/Product/7799386636339",
+ "vendor": "Versace",
+ "title": "Baroque Round Ornament Black, Gold, Silver Wallcovering | Versace",
+ "status": "ACTIVE",
+ "old_facet_tag": "color:Gold / Silver",
+ "old_real_color_name_metafield": "Gold, Silver",
+ "new_facet_tag": "color:Black / Gold / Silver",
+ "new_real_color_name_metafield": "Black, Gold, Silver",
+ "dropped_leading_color": "Black"
+ },
+ {
+ "handle": "medusa-medallion-stripe-grey-silver-metallic-wallcovering-versace",
+ "product_gid": "gid://shopify/Product/7799387357235",
+ "vendor": "Versace",
+ "title": "Medusa Medallion Stripe Grey, Silver, Metallic Wallcovering | Versace",
+ "status": "ACTIVE",
+ "old_facet_tag": "color:Silver / Metallic",
+ "old_real_color_name_metafield": "Silver, Metallic",
+ "new_facet_tag": "color:Grey / Silver / Metallic",
+ "new_real_color_name_metafield": "Grey, Silver, Metallic",
+ "dropped_leading_color": "Grey"
+ },
+ {
+ "handle": "medusa-label-metallic-black-white-wallcovering-versace",
+ "product_gid": "gid://shopify/Product/7799387324467",
+ "vendor": "Versace",
+ "title": "Medusa Label Metallic, Black, White Wallcovering | Versace",
+ "status": "ACTIVE",
+ "old_facet_tag": "color:Black / White",
+ "old_real_color_name_metafield": "Black, White",
+ "new_facet_tag": "color:Metallic / Black / White",
+ "new_real_color_name_metafield": "Metallic, Black, White",
+ "dropped_leading_color": "Metallic"
+ },
+ {
+ "handle": "crowns-roses-black-gold-cream-wallcovering-versace",
+ "product_gid": "gid://shopify/Product/7799386734643",
+ "vendor": "Versace",
+ "title": "Crowns & Roses Black, Gold, Cream Wallcovering | Versace",
+ "status": "ACTIVE",
+ "old_facet_tag": "color:Gold / Cream",
+ "old_real_color_name_metafield": "Gold, Cream",
+ "new_facet_tag": "color:Black / Gold / Cream",
+ "new_real_color_name_metafield": "Black, Gold, Cream",
+ "dropped_leading_color": "Black"
+ },
+ {
+ "handle": "medusa-circle-ornament-beige-grey-gold-wallcovering-versace",
+ "product_gid": "gid://shopify/Product/7799387226163",
+ "vendor": "Versace",
+ "title": "Medusa Circle Ornament Beige, Grey, Gold Wallcovering | Versace",
+ "status": "ACTIVE",
+ "old_facet_tag": "color:Grey / Gold",
+ "old_real_color_name_metafield": "Grey, Gold",
+ "new_facet_tag": "color:Beige / Grey / Gold",
+ "new_real_color_name_metafield": "Beige, Grey, Gold",
+ "dropped_leading_color": "Beige"
+ },
+ {
+ "handle": "medusa-filigree-white-beige-metallic-wallcovering-versace",
+ "product_gid": "gid://shopify/Product/7799387258931",
+ "vendor": "Versace",
+ "title": "Medusa Filigree White, Beige, Metallic Wallcovering | Versace",
+ "status": "ACTIVE",
+ "old_facet_tag": "color:Beige / Metallic",
+ "old_real_color_name_metafield": "Beige, Metallic",
+ "new_facet_tag": "color:White / Beige / Metallic",
+ "new_real_color_name_metafield": "White, Beige, Metallic",
+ "dropped_leading_color": "White"
+ },
+ {
+ "handle": "paradise-birds-gold-black-yellow-wallcovering-versace",
+ "product_gid": "gid://shopify/Product/7799387422771",
+ "vendor": "Versace",
+ "title": "Paradise Birds Gold, Black, Yellow Wallcovering | Versace",
+ "status": "ACTIVE",
+ "old_facet_tag": "color:Black / Yellow",
+ "old_real_color_name_metafield": "Black, Yellow",
+ "new_facet_tag": "color:Gold / Black / Yellow",
+ "new_real_color_name_metafield": "Gold, Black, Yellow",
+ "dropped_leading_color": "Gold"
+ },
+ {
+ "handle": "versace-floral-ornament-white-grey-metallic-wallcovering-versace",
+ "product_gid": "gid://shopify/Product/7799387717683",
+ "vendor": "Versace",
+ "title": "Versace Floral Ornament White, Grey, Metallic Wallcovering | Versace",
+ "status": "ACTIVE",
+ "old_facet_tag": "color:Grey / Metallic",
+ "old_real_color_name_metafield": "Grey, Metallic",
+ "new_facet_tag": "color:White / Grey / Metallic",
+ "new_real_color_name_metafield": "White, Grey, Metallic",
+ "dropped_leading_color": "White"
+ },
+ {
+ "handle": "versace-window-balustrade-grey-white-blue-wallcovering-versace-1",
+ "product_gid": "gid://shopify/Product/7799389847603",
+ "vendor": "Versace",
+ "title": "Versace Window Balustrade Grey, White, Blue Wallcovering | Versace",
+ "status": "ACTIVE",
+ "old_facet_tag": "color:White / Blue",
+ "old_real_color_name_metafield": "White, Blue",
+ "new_facet_tag": "color:Grey / White / Blue",
+ "new_real_color_name_metafield": "Grey, White, Blue",
+ "dropped_leading_color": "Grey"
+ },
+ {
+ "handle": "marble-line-grey-black-metallic-wallcovering-versace",
+ "product_gid": "gid://shopify/Product/7799386931251",
+ "vendor": "Versace",
+ "title": "Marble Line Grey, Black, Metallic Wallcovering | Versace",
+ "status": "ACTIVE",
+ "old_facet_tag": "color:Black / Metallic",
+ "old_real_color_name_metafield": "Black, Metallic",
+ "new_facet_tag": "color:Grey / Black / Metallic",
+ "new_real_color_name_metafield": "Grey, Black, Metallic",
+ "dropped_leading_color": "Grey"
+ },
+ {
+ "handle": "medusa-circle-gold-silver-white-wallcovering-versace",
+ "product_gid": "gid://shopify/Product/7799387095091",
+ "vendor": "Versace",
+ "title": "Medusa Circle Gold, Silver, White Wallcovering | Versace",
+ "status": "ACTIVE",
+ "old_facet_tag": "color:Silver / White",
+ "old_real_color_name_metafield": "Silver, White",
+ "new_facet_tag": "color:Gold / Silver / White",
+ "new_real_color_name_metafield": "Gold, Silver, White",
+ "dropped_leading_color": "Gold"
+ },
+ {
+ "handle": "medusa-circle-silver-gold-pink-wallcovering-versace",
+ "product_gid": "gid://shopify/Product/7799387160627",
+ "vendor": "Versace",
+ "title": "Medusa Circle Silver, Gold, Pink Wallcovering | Versace",
+ "status": "ACTIVE",
+ "old_facet_tag": "color:Gold / Pink",
+ "old_real_color_name_metafield": "Gold, Pink",
+ "new_facet_tag": "color:Silver / Gold / Pink",
+ "new_real_color_name_metafield": "Silver, Gold, Pink",
+ "dropped_leading_color": "Silver"
+ },
+ {
+ "handle": "versace-plain-glitter-pink-grey-purple-wallcovering-versace-1",
+ "product_gid": "gid://shopify/Product/7799389126707",
+ "vendor": "Versace",
+ "title": "Versace Plain Glitter Pink, Grey, Purple Wallcovering | Versace",
+ "status": "ACTIVE",
+ "old_facet_tag": "color:Grey / Purple",
+ "old_real_color_name_metafield": "Grey, Purple",
+ "new_facet_tag": "color:Pink / Grey / Purple",
+ "new_real_color_name_metafield": "Pink, Grey, Purple",
+ "dropped_leading_color": "Pink"
+ },
+ {
+ "handle": "ultra_2840",
+ "product_gid": "gid://shopify/Product/6790306758707",
+ "vendor": "Ultrasuede",
+ "title": "Ultrasuede™ Real Teal Aqua, Green, Blue | Wallcovering & Fabric",
+ "status": "ACTIVE",
+ "old_facet_tag": "color:Green / Blue",
+ "old_real_color_name_metafield": "Green, Blue",
+ "new_facet_tag": "color:Aqua / Green / Blue",
+ "new_real_color_name_metafield": "Aqua, Green, Blue",
+ "dropped_leading_color": "Aqua"
+ },
+ {
+ "handle": "ultra_2900",
+ "product_gid": "gid://shopify/Product/6790306988083",
+ "vendor": "Ultrasuede",
+ "title": "Ultrasuede™ Nectarine Orange, Pink, Red | Wallcovering & Fabric",
+ "status": "ACTIVE",
+ "old_facet_tag": "color:Pink / Red",
+ "old_real_color_name_metafield": "Pink, Red",
+ "new_facet_tag": "color:Orange / Pink / Red",
+ "new_real_color_name_metafield": "Orange, Pink, Red",
+ "dropped_leading_color": "Orange"
+ }
+ ],
+ "ambiguous_live": [
+ {
+ "handle": "one-two-three-one-two-three-romo",
+ "product_gid": "gid://shopify/Product/7787382407219",
+ "vendor": "Romo",
+ "title": "One, Two, Three One Two Three | Romo",
+ "status": "ACTIVE",
+ "current_facet_tags": [],
+ "current_real_color_name_metafield": "Three",
+ "why": "colorway not obvious from title \"One, Two, Three One Two Three\" — number-word pattern name; no color: tag currently exists (meta=\"Three\"). Steve must name the real Romo colorway or confirm LEAVE ALONE."
+ }
+ ],
+ "excluded": [
+ {
+ "handle": "dwrw-74399",
+ "product_gid": "gid://shopify/Product/6679601446963",
+ "vendor": "Rebel Walls",
+ "title": "Tin Plates, Ontario, black | Rebel Walls",
+ "status": "ACTIVE",
+ "current_facet_tags": [
+ "color:Ontario / Black"
+ ],
+ "current_real_color_name_metafield": "Ontario, Black",
+ "why": "CORRECT comma-form colorway (Rebel Walls \"Tin Plates\" — the comma is part of the real colorway); LEAVE ALONE."
+ },
+ {
+ "handle": "dwrw-74394",
+ "product_gid": "gid://shopify/Product/6679600955443",
+ "vendor": "Rebel Walls",
+ "title": "Tin Plates, Nebraska, White | Rebel Walls",
+ "status": "ACTIVE",
+ "current_facet_tags": [
+ "color:Nebraska / White"
+ ],
+ "current_real_color_name_metafield": "Nebraska, White",
+ "why": "CORRECT comma-form colorway (Rebel Walls \"Tin Plates\" — the comma is part of the real colorway); LEAVE ALONE."
+ }
+ ],
+ "pending_not_written": [
+ {
+ "handle": "ultra_2490",
+ "vendor": "Ultrasuede",
+ "title": "Ultrasuede™ Opalene Green, Blue, Aqua | Wallcovering & Fabric",
+ "current_extracted_colorway": "Blue, Aqua",
+ "proposed_real_color_name_metafield": "Green, Blue, Aqua",
+ "obvious_from_title": true,
+ "note": null
+ },
+ {
+ "handle": "pinks-turq-taupe-on-tint-dwak-700120",
+ "vendor": "Alan Campbell",
+ "title": "Pinks, Turq, Taupe on Tint | Alan Campbell",
+ "current_extracted_colorway": "Turq, Taupe On Tint",
+ "proposed_real_color_name_metafield": null,
+ "obvious_from_title": false,
+ "note": "comma is part of the pattern NAME \"Pinks, Turq, Taupe on Tint\" (Alan Campbell) — like the Rebel Walls case; likely LEAVE ALONE, adjudicate"
+ },
+ {
+ "handle": "my-fair-lady-ceramic-mug-11oz-15oz",
+ "vendor": "Steve Abrams Studios",
+ "title": "My Fair Lady Ceramic Mug, (11oz, 15oz)",
+ "current_extracted_colorway": "(11oz, 15oz)",
+ "proposed_real_color_name_metafield": null,
+ "obvious_from_title": false,
+ "note": "POD mug — \"(11oz, 15oz)\" is a SIZE variant, not a colorway; exclude from colorway logic entirely"
+ },
+ {
+ "handle": "ultra_2160",
+ "vendor": "Ultrasuede",
+ "title": "Ultrasuede™ Sahara Brown, Yellow, Cream | Wallcovering & Fabric",
+ "current_extracted_colorway": "Yellow, Cream",
+ "proposed_real_color_name_metafield": "Brown, Yellow, Cream",
+ "obvious_from_title": true,
+ "note": null
+ },
+ {
+ "handle": "versace-ornamental-floral-green-metallic-yellow-wallcovering-versace",
+ "vendor": "Versace",
+ "title": "Versace Ornamental Floral Green, Metallic, Yellow Wallcovering | Versace",
+ "current_extracted_colorway": "Metallic, Yellow",
+ "proposed_real_color_name_metafield": "Green, Metallic, Yellow",
+ "obvious_from_title": true,
+ "note": null
+ },
+ {
+ "handle": "smart-surfaces-beige-brown-orange-wallcovering-as-creation",
+ "vendor": "AS Creation",
+ "title": "Smart Surfaces Beige, Brown, Orange Wallcovering | AS Creation",
+ "current_extracted_colorway": "Brown, Orange",
+ "proposed_real_color_name_metafield": "Beige, Brown, Orange",
+ "obvious_from_title": true,
+ "note": null
+ },
+ {
+ "handle": "designwalls-beige-black-brown-cream-green-white-wallcovering-as-creation",
+ "vendor": "AS Creation",
+ "title": "Designwalls Beige, Black, Brown, Cream, Green, White Wallcovering | AS Creation",
+ "current_extracted_colorway": "Black, Brown, Cream, Green, White",
+ "proposed_real_color_name_metafield": "Beige, Black, Brown, Cream, Green, White",
+ "obvious_from_title": true,
+ "note": null
+ },
+ {
+ "handle": "stories-of-life-blue-green-turquoise-wallcovering-as-creation",
+ "vendor": "AS Creation",
+ "title": "Stories of Life Blue, Green, Turquoise Wallcovering | AS Creation",
+ "current_extracted_colorway": "Green, Turquoise",
+ "proposed_real_color_name_metafield": "Blue, Green, Turquoise",
+ "obvious_from_title": true,
+ "note": null
+ },
+ {
+ "handle": "henriot-floral-peach-gold-on-ecru-dwqc-600063",
+ "vendor": "Quadrille",
+ "title": "Henriot Floral, Peach, Gold on Ecru | Quadrille",
+ "current_extracted_colorway": "Peach, Gold On Ecru",
+ "proposed_real_color_name_metafield": null,
+ "obvious_from_title": false,
+ "note": "title \"Henriot Floral, Peach, Gold on Ecru | Quadrille\" — comma after \"Floral\" ambiguous (pattern \"Henriot Floral\" + colorway \"Peach, Gold on Ecru\"?); adjudicate"
+ },
+ {
+ "handle": "pinks-turq-taupe-on-tint-dwux-800008",
+ "vendor": "Suncloth",
+ "title": "Pinks, Turq, Taupe on Tint | Suncloth",
+ "current_extracted_colorway": "Turq, Taupe On Tint",
+ "proposed_real_color_name_metafield": null,
+ "obvious_from_title": false,
+ "note": "same comma-in-pattern-name case as the Alan Campbell twin (Suncloth); adjudicate"
+ },
+ {
+ "handle": "ap-digital-blue-green-grey-turquoise-wallcovering-as-creation",
+ "vendor": "AS Creation",
+ "title": "Ap Digital Blue, Green, Grey, Turquoise Wallcovering | AS Creation",
+ "current_extracted_colorway": "Green, Grey, Turquoise",
+ "proposed_real_color_name_metafield": "Blue, Green, Grey, Turquoise",
+ "obvious_from_title": true,
+ "note": null
+ },
+ {
+ "handle": "famous-garden-black-cream-orange-pink-red-wallcovering-as-creation",
+ "vendor": "AS Creation",
+ "title": "Famous Garden Black, Cream, Orange, Pink, Red Wallcovering | AS Creation",
+ "current_extracted_colorway": "Cream, Orange, Pink, Red",
+ "proposed_real_color_name_metafield": "Black, Cream, Orange, Pink, Red",
+ "obvious_from_title": true,
+ "note": null
+ },
+ {
+ "handle": "aquarium-fish-tank-blue-gray-red-orange-aqu-9801",
+ "vendor": "Designer Wallcoverings",
+ "title": "Aquarium Fish Tank -blue, gray, red, orange",
+ "current_extracted_colorway": "Gray, Red, Orange",
+ "proposed_real_color_name_metafield": "Blue, Gray, Red, Orange",
+ "obvious_from_title": true,
+ "note": "title uses \"-blue\" leading dash"
+ },
+ {
+ "handle": "ultra_2390",
+ "vendor": "Ultrasuede",
+ "title": "Ultrasuede™ Wheat Brown, Cream, Orange | Wallcovering & Fabric",
+ "current_extracted_colorway": "Cream, Orange",
+ "proposed_real_color_name_metafield": "Brown, Cream, Orange",
+ "obvious_from_title": true,
+ "note": null
+ },
+ {
+ "handle": "dwve-430200",
+ "vendor": "Phillipe Romano",
+ "title": "Alicante Velvet Walls Aqua, Blue, Green",
+ "current_extracted_colorway": "Blue, Green",
+ "proposed_real_color_name_metafield": "Aqua, Blue, Green",
+ "obvious_from_title": true,
+ "note": null
+ }
+ ]
+}
\ No newline at end of file
diff --git a/scripts/colorway-title-anchor/out/tk11679-live-verify.json b/scripts/colorway-title-anchor/out/tk11679-live-verify.json
new file mode 100644
index 0000000..88f7ce1
--- /dev/null
+++ b/scripts/colorway-title-anchor/out/tk11679-live-verify.json
@@ -0,0 +1,348 @@
+{
+ "ts": "2026-09-14T07:35:11.045Z",
+ "mode": "GET-ONLY",
+ "landed_count": 18,
+ "curated_live": 15,
+ "ambiguous_live": 1,
+ "excluded_rebel": 2,
+ "rows": [
+ {
+ "h": "baroque-round-ornament-black-gold-silver-wallcovering-versace",
+ "kind": "CURATED-live",
+ "title": "Baroque Round Ornament Black, Gold, Silver Wallcovering | Versace",
+ "vendor": "Versace",
+ "live_found": true,
+ "live_status": "ACTIVE",
+ "current_facet_tags": [
+ "color:Gold / Silver"
+ ],
+ "current_real_color_name_metafield": "Gold, Silver",
+ "evidence_meta": "Gold, Silver",
+ "evidence_colorTags": [
+ "color:Gold / Silver"
+ ],
+ "proposed_real_color_name_metafield": "Black, Gold, Silver",
+ "proposed_facet_tag": "color:Black / Gold / Silver",
+ "product_gid": "gid://shopify/Product/7799386636339"
+ },
+ {
+ "h": "medusa-medallion-stripe-grey-silver-metallic-wallcovering-versace",
+ "kind": "CURATED-live",
+ "title": "Medusa Medallion Stripe Grey, Silver, Metallic Wallcovering | Versace",
+ "vendor": "Versace",
+ "live_found": true,
+ "live_status": "ACTIVE",
+ "current_facet_tags": [
+ "color:Silver / Metallic"
+ ],
+ "current_real_color_name_metafield": "Silver, Metallic",
+ "evidence_meta": "Silver, Metallic",
+ "evidence_colorTags": [
+ "color:Silver / Metallic"
+ ],
+ "proposed_real_color_name_metafield": "Grey, Silver, Metallic",
+ "proposed_facet_tag": "color:Grey / Silver / Metallic",
+ "product_gid": "gid://shopify/Product/7799387357235"
+ },
+ {
+ "h": "medusa-label-metallic-black-white-wallcovering-versace",
+ "kind": "CURATED-live",
+ "title": "Medusa Label Metallic, Black, White Wallcovering | Versace",
+ "vendor": "Versace",
+ "live_found": true,
+ "live_status": "ACTIVE",
+ "current_facet_tags": [
+ "color:Black / White"
+ ],
+ "current_real_color_name_metafield": "Black, White",
+ "evidence_meta": "Black, White",
+ "evidence_colorTags": [
+ "color:Black / White"
+ ],
+ "proposed_real_color_name_metafield": "Metallic, Black, White",
+ "proposed_facet_tag": "color:Metallic / Black / White",
+ "product_gid": "gid://shopify/Product/7799387324467"
+ },
+ {
+ "h": "crowns-roses-black-gold-cream-wallcovering-versace",
+ "kind": "CURATED-live",
+ "title": "Crowns & Roses Black, Gold, Cream Wallcovering | Versace",
+ "vendor": "Versace",
+ "live_found": true,
+ "live_status": "ACTIVE",
+ "current_facet_tags": [
+ "color:Gold / Cream"
+ ],
+ "current_real_color_name_metafield": "Gold, Cream",
+ "evidence_meta": "Gold, Cream",
+ "evidence_colorTags": [
+ "color:Gold / Cream"
+ ],
+ "proposed_real_color_name_metafield": "Black, Gold, Cream",
+ "proposed_facet_tag": "color:Black / Gold / Cream",
+ "product_gid": "gid://shopify/Product/7799386734643"
+ },
+ {
+ "h": "medusa-circle-ornament-beige-grey-gold-wallcovering-versace",
+ "kind": "CURATED-live",
+ "title": "Medusa Circle Ornament Beige, Grey, Gold Wallcovering | Versace",
+ "vendor": "Versace",
+ "live_found": true,
+ "live_status": "ACTIVE",
+ "current_facet_tags": [
+ "color:Grey / Gold"
+ ],
+ "current_real_color_name_metafield": "Grey, Gold",
+ "evidence_meta": "Grey, Gold",
+ "evidence_colorTags": [
+ "color:Grey / Gold"
+ ],
+ "proposed_real_color_name_metafield": "Beige, Grey, Gold",
+ "proposed_facet_tag": "color:Beige / Grey / Gold",
+ "product_gid": "gid://shopify/Product/7799387226163"
+ },
+ {
+ "h": "medusa-filigree-white-beige-metallic-wallcovering-versace",
+ "kind": "CURATED-live",
+ "title": "Medusa Filigree White, Beige, Metallic Wallcovering | Versace",
+ "vendor": "Versace",
+ "live_found": true,
+ "live_status": "ACTIVE",
+ "current_facet_tags": [
+ "color:Beige / Metallic"
+ ],
+ "current_real_color_name_metafield": "Beige, Metallic",
+ "evidence_meta": "Beige, Metallic",
+ "evidence_colorTags": [
+ "color:Beige / Metallic"
+ ],
+ "proposed_real_color_name_metafield": "White, Beige, Metallic",
+ "proposed_facet_tag": "color:White / Beige / Metallic",
+ "product_gid": "gid://shopify/Product/7799387258931"
+ },
+ {
+ "h": "paradise-birds-gold-black-yellow-wallcovering-versace",
+ "kind": "CURATED-live",
+ "title": "Paradise Birds Gold, Black, Yellow Wallcovering | Versace",
+ "vendor": "Versace",
+ "live_found": true,
+ "live_status": "ACTIVE",
+ "current_facet_tags": [
+ "color:Black / Yellow"
+ ],
+ "current_real_color_name_metafield": "Black, Yellow",
+ "evidence_meta": "Black, Yellow",
+ "evidence_colorTags": [
+ "color:Black / Yellow"
+ ],
+ "proposed_real_color_name_metafield": "Gold, Black, Yellow",
+ "proposed_facet_tag": "color:Gold / Black / Yellow",
+ "product_gid": "gid://shopify/Product/7799387422771"
+ },
+ {
+ "h": "versace-floral-ornament-white-grey-metallic-wallcovering-versace",
+ "kind": "CURATED-live",
+ "title": "Versace Floral Ornament White, Grey, Metallic Wallcovering | Versace",
+ "vendor": "Versace",
+ "live_found": true,
+ "live_status": "ACTIVE",
+ "current_facet_tags": [
+ "color:Grey / Metallic"
+ ],
+ "current_real_color_name_metafield": "Grey, Metallic",
+ "evidence_meta": "Grey, Metallic",
+ "evidence_colorTags": [
+ "color:Grey / Metallic"
+ ],
+ "proposed_real_color_name_metafield": "White, Grey, Metallic",
+ "proposed_facet_tag": "color:White / Grey / Metallic",
+ "product_gid": "gid://shopify/Product/7799387717683"
+ },
+ {
+ "h": "versace-window-balustrade-grey-white-blue-wallcovering-versace-1",
+ "kind": "CURATED-live",
+ "title": "Versace Window Balustrade Grey, White, Blue Wallcovering | Versace",
+ "vendor": "Versace",
+ "live_found": true,
+ "live_status": "ACTIVE",
+ "current_facet_tags": [
+ "color:White / Blue"
+ ],
+ "current_real_color_name_metafield": "White, Blue",
+ "evidence_meta": "White, Blue",
+ "evidence_colorTags": [
+ "color:White / Blue"
+ ],
+ "proposed_real_color_name_metafield": "Grey, White, Blue",
+ "proposed_facet_tag": "color:Grey / White / Blue",
+ "product_gid": "gid://shopify/Product/7799389847603"
+ },
+ {
+ "h": "marble-line-grey-black-metallic-wallcovering-versace",
+ "kind": "CURATED-live",
+ "title": "Marble Line Grey, Black, Metallic Wallcovering | Versace",
+ "vendor": "Versace",
+ "live_found": true,
+ "live_status": "ACTIVE",
+ "current_facet_tags": [
+ "color:Black / Metallic"
+ ],
+ "current_real_color_name_metafield": "Black, Metallic",
+ "evidence_meta": "Black, Metallic",
+ "evidence_colorTags": [
+ "color:Black / Metallic"
+ ],
+ "proposed_real_color_name_metafield": "Grey, Black, Metallic",
+ "proposed_facet_tag": "color:Grey / Black / Metallic",
+ "product_gid": "gid://shopify/Product/7799386931251"
+ },
+ {
+ "h": "medusa-circle-gold-silver-white-wallcovering-versace",
+ "kind": "CURATED-live",
+ "title": "Medusa Circle Gold, Silver, White Wallcovering | Versace",
+ "vendor": "Versace",
+ "live_found": true,
+ "live_status": "ACTIVE",
+ "current_facet_tags": [
+ "color:Silver / White"
+ ],
+ "current_real_color_name_metafield": "Silver, White",
+ "evidence_meta": "Silver, White",
+ "evidence_colorTags": [
+ "color:Silver / White"
+ ],
+ "proposed_real_color_name_metafield": "Gold, Silver, White",
+ "proposed_facet_tag": "color:Gold / Silver / White",
+ "product_gid": "gid://shopify/Product/7799387095091"
+ },
+ {
+ "h": "dwrw-74399",
+ "kind": "EXCLUDE-rebel-correct",
+ "title": "Tin Plates, Ontario, black | Rebel Walls",
+ "vendor": "Rebel Walls",
+ "live_found": true,
+ "live_status": "ACTIVE",
+ "current_facet_tags": [
+ "color:Ontario / Black"
+ ],
+ "current_real_color_name_metafield": "Ontario, Black",
+ "evidence_meta": "Ontario, Black",
+ "evidence_colorTags": [
+ "color:Ontario / Black"
+ ],
+ "proposed_real_color_name_metafield": null,
+ "proposed_facet_tag": null,
+ "product_gid": "gid://shopify/Product/6679601446963"
+ },
+ {
+ "h": "one-two-three-one-two-three-romo",
+ "kind": "AMBIGUOUS-live",
+ "title": "One, Two, Three One Two Three | Romo",
+ "vendor": "Romo",
+ "live_found": true,
+ "live_status": "ACTIVE",
+ "current_facet_tags": [],
+ "current_real_color_name_metafield": "Three",
+ "evidence_meta": "Three",
+ "evidence_colorTags": [],
+ "proposed_real_color_name_metafield": null,
+ "proposed_facet_tag": null,
+ "product_gid": "gid://shopify/Product/7787382407219"
+ },
+ {
+ "h": "medusa-circle-silver-gold-pink-wallcovering-versace",
+ "kind": "CURATED-live",
+ "title": "Medusa Circle Silver, Gold, Pink Wallcovering | Versace",
+ "vendor": "Versace",
+ "live_found": true,
+ "live_status": "ACTIVE",
+ "current_facet_tags": [
+ "color:Gold / Pink"
+ ],
+ "current_real_color_name_metafield": "Gold, Pink",
+ "evidence_meta": "Gold, Pink",
+ "evidence_colorTags": [
+ "color:Gold / Pink"
+ ],
+ "proposed_real_color_name_metafield": "Silver, Gold, Pink",
+ "proposed_facet_tag": "color:Silver / Gold / Pink",
+ "product_gid": "gid://shopify/Product/7799387160627"
+ },
+ {
+ "h": "versace-plain-glitter-pink-grey-purple-wallcovering-versace-1",
+ "kind": "CURATED-live",
+ "title": "Versace Plain Glitter Pink, Grey, Purple Wallcovering | Versace",
+ "vendor": "Versace",
+ "live_found": true,
+ "live_status": "ACTIVE",
+ "current_facet_tags": [
+ "color:Grey / Purple"
+ ],
+ "current_real_color_name_metafield": "Grey, Purple",
+ "evidence_meta": "Grey, Purple",
+ "evidence_colorTags": [
+ "color:Grey / Purple"
+ ],
+ "proposed_real_color_name_metafield": "Pink, Grey, Purple",
+ "proposed_facet_tag": "color:Pink / Grey / Purple",
+ "product_gid": "gid://shopify/Product/7799389126707"
+ },
+ {
+ "h": "dwrw-74394",
+ "kind": "EXCLUDE-rebel-correct",
+ "title": "Tin Plates, Nebraska, White | Rebel Walls",
+ "vendor": "Rebel Walls",
+ "live_found": true,
+ "live_status": "ACTIVE",
+ "current_facet_tags": [
+ "color:Nebraska / White"
+ ],
+ "current_real_color_name_metafield": "Nebraska, White",
+ "evidence_meta": "Nebraska, White",
+ "evidence_colorTags": [
+ "color:Nebraska / White"
+ ],
+ "proposed_real_color_name_metafield": null,
+ "proposed_facet_tag": null,
+ "product_gid": "gid://shopify/Product/6679600955443"
+ },
+ {
+ "h": "ultra_2840",
+ "kind": "CURATED-live",
+ "title": "Ultrasuede™ Real Teal Aqua, Green, Blue | Wallcovering & Fabric",
+ "vendor": "Ultrasuede",
+ "live_found": true,
+ "live_status": "ACTIVE",
+ "current_facet_tags": [
+ "color:Green / Blue"
+ ],
+ "current_real_color_name_metafield": "Green, Blue",
+ "evidence_meta": "Green, Blue",
+ "evidence_colorTags": [
+ "color:Green / Blue"
+ ],
+ "proposed_real_color_name_metafield": "Aqua, Green, Blue",
+ "proposed_facet_tag": "color:Aqua / Green / Blue",
+ "product_gid": "gid://shopify/Product/6790306758707"
+ },
+ {
+ "h": "ultra_2900",
+ "kind": "CURATED-live",
+ "title": "Ultrasuede™ Nectarine Orange, Pink, Red | Wallcovering & Fabric",
+ "vendor": "Ultrasuede",
+ "live_found": true,
+ "live_status": "ACTIVE",
+ "current_facet_tags": [
+ "color:Pink / Red"
+ ],
+ "current_real_color_name_metafield": "Pink, Red",
+ "evidence_meta": "Pink, Red",
+ "evidence_colorTags": [
+ "color:Pink / Red"
+ ],
+ "proposed_real_color_name_metafield": "Orange, Pink, Red",
+ "proposed_facet_tag": "color:Orange / Pink / Red",
+ "product_gid": "gid://shopify/Product/6790306988083"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/scripts/colorway-title-anchor/tk11679-apply-corrections.mjs b/scripts/colorway-title-anchor/tk11679-apply-corrections.mjs
new file mode 100644
index 0000000..1132594
--- /dev/null
+++ b/scripts/colorway-title-anchor/tk11679-apply-corrections.mjs
@@ -0,0 +1,132 @@
+#!/usr/bin/env node
+/**
+ * TK-11679 — GATED apply of the CURATED per-product colorway-facet corrections.
+ * DEFAULT = DRY-RUN. Live writes require --apply AND are customer-facing Shopify metafield+tag
+ * writes on the LIVE store — do NOT run without Steve's approval (memo:
+ * ~/.claude/yolo-queue/pending-approval/2026-09-14-TK-11679-colorway-facet-truncation.md).
+ *
+ * Per handle, in order:
+ * 1. GET current tags + custom.real_color_name (fresh snapshot at write time).
+ * 2. Record OLD (tags + metafield) to the rollback file BEFORE the write (first-write-wins).
+ * 3. productUpdate: swap old color: facet tag -> new color: facet tag (preserve every other tag);
+ * set custom.real_color_name -> full comma-form colorway. NOTHING else touched.
+ * 4. GET again, VERIFY the new facet tag present + metafield == full colorway; else mark VERIFY-FAIL.
+ * 5. ledger the reversible action (log-exec.mjs) with a per-item undo command.
+ *
+ * Undo (per item or all): node tk11679-apply-corrections.mjs --rollback [--only=<handle>] --apply
+ *
+ * node tk11679-apply-corrections.mjs # DRY-RUN preview
+ * node tk11679-apply-corrections.mjs --apply # LIVE (Steve-gated)
+ * node tk11679-apply-corrections.mjs --rollback --apply
+ */
+import fs from 'node:fs';
+import path from 'node:path';
+import { fileURLToPath } from 'node:url';
+import { execSync } from 'node:child_process';
+
+const HERE = path.dirname(fileURLToPath(import.meta.url));
+const OUT = path.join(HERE, 'out');
+const STORE = process.env.SHOPIFY_STORE || 'designer-laboratory-sandbox.myshopify.com';
+const API = process.env.SHOPIFY_API_VERSION || '2024-10';
+const APPLY = process.argv.includes('--apply');
+const ROLLBACK_MODE = process.argv.includes('--rollback');
+const ONLY = ((process.argv.find(a => a.startsWith('--only=')) || '').split('=')[1] || '').trim();
+const CW_NS = 'custom', CW_KEY = 'real_color_name';
+const ROLLBACK_FILE = path.join(process.env.HOME, '.claude/yolo-queue/executed-reversible/TK-11679-colorway-facet-rollback.json');
+const sleep = ms => new Promise(r => setTimeout(r, ms));
+const norm = s => String(s || '').toLowerCase().replace(/\s+/g, ' ').trim();
+
+let TOKEN = process.env.SHOPIFY_ADMIN_TOKEN;
+if (!TOKEN) {
+ const env = fs.readFileSync(path.join(process.env.HOME, 'Projects/secrets-manager/.env'), 'utf8');
+ const m = env.match(/^SHOPIFY_ADMIN_TOKEN=(.+)$/m); TOKEN = m ? m[1].trim() : null;
+}
+if (!TOKEN) { console.error('FATAL: no SHOPIFY_ADMIN_TOKEN'); process.exit(1); }
+
+async function gql(query, variables) {
+ for (let a = 0; a < 6; a++) {
+ const res = await fetch(`https://${STORE}/admin/api/${API}/graphql.json`, {
+ method: 'POST', headers: { 'X-Shopify-Access-Token': TOKEN, 'Content-Type': 'application/json' },
+ body: JSON.stringify({ query, variables }), signal: AbortSignal.timeout(45000) }).catch(e => ({ _err: e }));
+ if (res._err) { await sleep(1500 * (a + 1)); continue; }
+ const j = await res.json().catch(() => ({}));
+ if (j.errors) { if (a === 5) return { errors: j.errors }; await sleep(1500 * (a + 1)); continue; }
+ await sleep(350); return j.data;
+ }
+ return { errors: [{ message: 'gql retries exhausted' }] };
+}
+
+const FIELDS = `id handle status title tags cw: metafield(namespace:"${CW_NS}", key:"${CW_KEY}"){ value }`;
+async function getByHandle(h) {
+ const d = await gql(`query($q:String!){ products(first:1, query:$q){ nodes{ ${FIELDS} } } }`, { q: `handle:${h}` });
+ return (d && d.products && d.products.nodes && d.products.nodes[0]) || null;
+}
+
+const curated = JSON.parse(fs.readFileSync(path.join(OUT, 'tk11679-curated-corrections.json'), 'utf8'));
+let items = curated.corrections; // ONLY the 15 obvious live corrections (ambiguous/excluded/pending are NOT in scope)
+if (ONLY) items = items.filter(i => i.handle === ONLY);
+
+function loadRollback() { return fs.existsSync(ROLLBACK_FILE) ? JSON.parse(fs.readFileSync(ROLLBACK_FILE, 'utf8')) : {}; }
+function saveRollback(rb) { fs.mkdirSync(path.dirname(ROLLBACK_FILE), { recursive: true }); fs.writeFileSync(ROLLBACK_FILE, JSON.stringify(rb, null, 2)); }
+
+async function doRollback() {
+ const rb = loadRollback();
+ const keys = Object.keys(rb).filter(k => rb[k] && rb[k].product_gid && (!ONLY || k === ONLY));
+ if (!keys.length) { console.log('nothing to roll back'); return; }
+ if (!APPLY) { console.log(`DRY-RUN rollback of ${keys.length}: ${keys.join(', ')}`); return; }
+ for (const h of keys) {
+ const r = rb[h];
+ const d = await gql(`mutation($input:ProductInput!){ productUpdate(input:$input){ userErrors{ message } } }`,
+ { input: { id: r.product_gid, tags: r.old_tags,
+ metafields: [{ namespace: CW_NS, key: CW_KEY, type: 'single_line_text_field', value: r.old_metafield || '' }] } });
+ const ue = d && d.productUpdate && d.productUpdate.userErrors;
+ console.log(`${h}: ${ue && ue.length ? 'ERR ' + JSON.stringify(ue) : 'restored'}`);
+ await sleep(700);
+ }
+}
+
+async function doApply() {
+ console.log(`${APPLY ? 'APPLY' : 'DRY-RUN'} — ${items.length} curated live corrections`);
+ const rb = loadRollback();
+ let done = 0, pass = 0, fail = 0;
+ for (const it of items) {
+ const p = await getByHandle(it.handle);
+ if (!p) { console.error(`NOT FOUND ${it.handle}`); fail++; continue; }
+ const liveTags = Array.isArray(p.tags) ? p.tags : String(p.tags || '').split(',').map(s => s.trim()).filter(Boolean);
+ // swap the color: facet tag(s); preserve everything else
+ const newTags = liveTags.filter(t => !/^color:/i.test(t));
+ if (!newTags.some(t => norm(t) === norm(it.new_facet_tag))) newTags.push(it.new_facet_tag);
+ const plan = { handle: it.handle, gid: p.id, oldTags: liveTags, newTags,
+ oldMeta: p.cw ? p.cw.value : '', newMeta: it.new_real_color_name_metafield };
+ console.log(`\n${it.handle}\n tags: strip color:* -> add ${it.new_facet_tag}\n meta: "${plan.oldMeta}" -> "${plan.newMeta}"`);
+ if (!APPLY) { continue; }
+
+ // record OLD before write (first-write-wins)
+ if (!rb[it.handle]) {
+ rb[it.handle] = { product_gid: p.id, ts: new Date().toISOString(), old_tags: liveTags, old_metafield: plan.oldMeta,
+ new_tags: newTags, new_metafield: plan.newMeta };
+ saveRollback(rb);
+ }
+ const d = await gql(`mutation($input:ProductInput!){ productUpdate(input:$input){ userErrors{ field message } } }`,
+ { input: { id: p.id, tags: newTags,
+ metafields: [{ namespace: CW_NS, key: CW_KEY, type: 'single_line_text_field', value: plan.newMeta }] } });
+ const ue = d && d.productUpdate && d.productUpdate.userErrors;
+ if (ue && ue.length) { console.error(` userErrors: ${JSON.stringify(ue)}`); fail++; continue; }
+ // verify
+ const v = await getByHandle(it.handle);
+ const vt = v ? (Array.isArray(v.tags) ? v.tags : String(v.tags || '').split(',').map(s => s.trim())) : [];
+ const facetOk = vt.some(t => norm(t) === norm(it.new_facet_tag));
+ const metaOk = norm(v && v.cw ? v.cw.value : '') === norm(plan.newMeta);
+ (facetOk && metaOk) ? pass++ : (fail++, console.error(` VERIFY FAIL facetOk=${facetOk} metaOk=${metaOk}`));
+ done++;
+ try { execSync(`node "${path.join(process.env.HOME, '.claude/yolo-queue/executed-reversible/log-exec.mjs')}" ` +
+ `--agent vp-dw-commerce --ticket TK-11679 --action "colorway facet un-truncate ${it.handle}: ${plan.newMeta}" --blast 1 ` +
+ `--undo "cd ${HERE} && node tk11679-apply-corrections.mjs --rollback --only=${it.handle} --apply" ` +
+ `--verify "GET ${it.handle} — color: facet + custom.real_color_name == full title colorway; title/price/status/sku/image unchanged"`,
+ { stdio: 'ignore' }); } catch {}
+ await sleep(700);
+ }
+ console.log(`\nDONE: ${done} · pass ${pass} · fail ${fail} · rollback=${ROLLBACK_FILE}`);
+}
+
+(ROLLBACK_MODE ? doRollback() : doApply());
diff --git a/scripts/colorway-title-anchor/tk11679-build-correction-list.mjs b/scripts/colorway-title-anchor/tk11679-build-correction-list.mjs
new file mode 100644
index 0000000..740c868
--- /dev/null
+++ b/scripts/colorway-title-anchor/tk11679-build-correction-list.mjs
@@ -0,0 +1,98 @@
+#!/usr/bin/env node
+/**
+ * TK-11679 — build the CURATED per-product colorway-facet correction list (reversible map + rollback
+ * source) from the GET-verified live state. NO WRITES to Shopify/PG. Emits reviewable JSON only.
+ *
+ * Output: out/tk11679-curated-corrections.json
+ * - corrections[] : 15 live products with an OBVIOUS title-read fix (old -> new facet + metafield).
+ * - ambiguous_live[]: 1 live truncation whose correct colorway is NOT obvious (Romo) -> Steve decides.
+ * - excluded[] : 2 Rebel Walls correct comma-form -> LEAVE ALONE.
+ * - pending_not_written[]: 15 not-yet-written rows -> adjudicate before any future run.
+ *
+ * node tk11679-build-correction-list.mjs
+ */
+import fs from 'node:fs';
+import path from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+const HERE = path.dirname(fileURLToPath(import.meta.url));
+const OUT = path.join(HERE, 'out');
+const verify = JSON.parse(fs.readFileSync(path.join(OUT, 'tk11679-live-verify.json'), 'utf8'));
+const evidence = JSON.parse(fs.readFileSync(path.join(OUT, 'tk11076-residual-comma-truncation.json'), 'utf8'));
+
+// title-read full colorway for the 15 not-yet-written rows (obvious from title; POD/mug + comma-name flagged)
+const PENDING_FIX = {
+ ultra_2490: { proposed: 'Green, Blue, Aqua', obvious: true },
+ 'pinks-turq-taupe-on-tint-dwak-700120': { proposed: null, obvious: false, note: 'comma is part of the pattern NAME "Pinks, Turq, Taupe on Tint" (Alan Campbell) — like the Rebel Walls case; likely LEAVE ALONE, adjudicate' },
+ 'my-fair-lady-ceramic-mug-11oz-15oz': { proposed: null, obvious: false, note: 'POD mug — "(11oz, 15oz)" is a SIZE variant, not a colorway; exclude from colorway logic entirely' },
+ ultra_2160: { proposed: 'Brown, Yellow, Cream', obvious: true },
+ 'versace-ornamental-floral-green-metallic-yellow-wallcovering-versace': { proposed: 'Green, Metallic, Yellow', obvious: true },
+ 'smart-surfaces-beige-brown-orange-wallcovering-as-creation': { proposed: 'Beige, Brown, Orange', obvious: true },
+ 'designwalls-beige-black-brown-cream-green-white-wallcovering-as-creation': { proposed: 'Beige, Black, Brown, Cream, Green, White', obvious: true },
+ 'stories-of-life-blue-green-turquoise-wallcovering-as-creation': { proposed: 'Blue, Green, Turquoise', obvious: true },
+ 'henriot-floral-peach-gold-on-ecru-dwqc-600063': { proposed: null, obvious: false, note: 'title "Henriot Floral, Peach, Gold on Ecru | Quadrille" — comma after "Floral" ambiguous (pattern "Henriot Floral" + colorway "Peach, Gold on Ecru"?); adjudicate' },
+ 'pinks-turq-taupe-on-tint-dwux-800008': { proposed: null, obvious: false, note: 'same comma-in-pattern-name case as the Alan Campbell twin (Suncloth); adjudicate' },
+ 'ap-digital-blue-green-grey-turquoise-wallcovering-as-creation': { proposed: 'Blue, Green, Grey, Turquoise', obvious: true },
+ 'famous-garden-black-cream-orange-pink-red-wallcovering-as-creation': { proposed: 'Black, Cream, Orange, Pink, Red', obvious: true },
+ 'aquarium-fish-tank-blue-gray-red-orange-aqu-9801': { proposed: 'Blue, Gray, Red, Orange', obvious: true, note: 'title uses "-blue" leading dash' },
+ ultra_2390: { proposed: 'Brown, Cream, Orange', obvious: true },
+ 'dwve-430200': { proposed: 'Aqua, Blue, Green', obvious: true },
+};
+
+const corrections = [], ambiguous = [], excluded = [];
+for (const r of verify.rows) {
+ if (r.kind === 'CURATED-live') {
+ corrections.push({
+ handle: r.h, product_gid: r.product_gid, vendor: r.vendor, title: r.title, status: r.live_status,
+ // OLD (rollback source — the live values GET-confirmed just now)
+ old_facet_tag: (r.current_facet_tags || [])[0] || null,
+ old_real_color_name_metafield: r.current_real_color_name_metafield,
+ // NEW (curated correction, read from the title)
+ new_facet_tag: r.proposed_facet_tag,
+ new_real_color_name_metafield: r.proposed_real_color_name_metafield,
+ dropped_leading_color: (() => {
+ const full = (r.proposed_real_color_name_metafield || '').split(/\s*,\s*/);
+ const cur = (r.current_real_color_name_metafield || '').split(/\s*,\s*/);
+ return full.filter(c => !cur.includes(c)).join(', ');
+ })(),
+ });
+ } else if (r.kind === 'AMBIGUOUS-live') {
+ ambiguous.push({
+ handle: r.h, product_gid: r.product_gid, vendor: r.vendor, title: r.title, status: r.live_status,
+ current_facet_tags: r.current_facet_tags, current_real_color_name_metafield: r.current_real_color_name_metafield,
+ why: 'colorway not obvious from title "One, Two, Three One Two Three" — number-word pattern name; no color: tag currently exists (meta="Three"). Steve must name the real Romo colorway or confirm LEAVE ALONE.',
+ });
+ } else if (r.kind === 'EXCLUDE-rebel-correct') {
+ excluded.push({
+ handle: r.h, product_gid: r.product_gid, vendor: r.vendor, title: r.title, status: r.live_status,
+ current_facet_tags: r.current_facet_tags, current_real_color_name_metafield: r.current_real_color_name_metafield,
+ why: 'CORRECT comma-form colorway (Rebel Walls "Tin Plates" — the comma is part of the real colorway); LEAVE ALONE.',
+ });
+ }
+}
+
+const pending = evidence.filter(r => r.landed === false).map(r => {
+ const f = PENDING_FIX[r.h] || { proposed: null, obvious: false, note: 'unmapped — adjudicate' };
+ return { handle: r.h, vendor: r.v, title: r.t, current_extracted_colorway: r.cw,
+ proposed_real_color_name_metafield: f.proposed, obvious_from_title: f.obvious, note: f.note || null };
+});
+
+const out = {
+ ticket: 'TK-11679', spun_from: 'TK-11076', ts: new Date().toISOString(),
+ source_of_truth: 'live GET (Shopify Admin 2024-10) 2026-09-14; evidence out/tk11076-residual-comma-truncation.json',
+ metafield_target: 'custom.real_color_name (single_line_text_field, verbatim comma form)',
+ facet_tag_form: 'color:<A / B / C> (Shopify tags split on comma, so commas -> " / " for the TAG only)',
+ summary: {
+ curated_live_corrections: corrections.length,
+ ambiguous_live_needs_steve: ambiguous.length,
+ excluded_rebel_correct: excluded.length,
+ pending_not_yet_written: pending.length,
+ pending_obvious: pending.filter(p => p.obvious_from_title).length,
+ pending_needs_adjudication: pending.filter(p => !p.obvious_from_title).length,
+ },
+ corrections, ambiguous_live: ambiguous, excluded, pending_not_written: pending,
+};
+const outFile = path.join(OUT, 'tk11679-curated-corrections.json');
+fs.writeFileSync(outFile, JSON.stringify(out, null, 2));
+console.log(JSON.stringify(out.summary, null, 2));
+console.log('wrote ' + outFile);
diff --git a/scripts/colorway-title-anchor/tk11679-verify-live.mjs b/scripts/colorway-title-anchor/tk11679-verify-live.mjs
new file mode 100644
index 0000000..b2640d6
--- /dev/null
+++ b/scripts/colorway-title-anchor/tk11679-verify-live.mjs
@@ -0,0 +1,116 @@
+#!/usr/bin/env node
+/**
+ * TK-11679 — GET-ONLY live confirmation of the 16 residual comma-truncated colorway facets
+ * (+ the 2 Rebel Walls correct-comma-form exclusions) that landed LIVE on Shopify under TK-11076.
+ *
+ * Reads the current color: facet TAG and the custom.real_color_name METAFIELD off each live
+ * product and records it beside the curated title-read correction. NO WRITES. Rails: GET only.
+ *
+ * node tk11679-verify-live.mjs
+ */
+import fs from 'node:fs';
+import path from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+const HERE = path.dirname(fileURLToPath(import.meta.url));
+const OUT = path.join(HERE, 'out');
+const STORE = process.env.SHOPIFY_STORE || 'designer-laboratory-sandbox.myshopify.com';
+const API = process.env.SHOPIFY_API_VERSION || '2024-10';
+// load token from secrets .env (no shell interpolation)
+let TOKEN = process.env.SHOPIFY_ADMIN_TOKEN;
+if (!TOKEN) {
+ const env = fs.readFileSync(path.join(process.env.HOME, 'Projects/secrets-manager/.env'), 'utf8');
+ const m = env.match(/^SHOPIFY_ADMIN_TOKEN=(.+)$/m);
+ TOKEN = m ? m[1].trim() : null;
+}
+if (!TOKEN) { console.error('FATAL: no SHOPIFY_ADMIN_TOKEN'); process.exit(1); }
+
+const sleep = ms => new Promise(r => setTimeout(r, ms));
+const CW_NS = 'custom', CW_KEY = 'real_color_name';
+
+async function gql(query, variables) {
+ for (let a = 0; a < 6; a++) {
+ const res = await fetch(`https://${STORE}/admin/api/${API}/graphql.json`, {
+ method: 'POST', headers: { 'X-Shopify-Access-Token': TOKEN, 'Content-Type': 'application/json' },
+ body: JSON.stringify({ query, variables }), signal: AbortSignal.timeout(45000) }).catch(e => ({ _err: e }));
+ if (res._err) { await sleep(1500 * (a + 1)); continue; }
+ const j = await res.json().catch(() => ({}));
+ if (j.errors) { if (a === 5) return { errors: j.errors }; await sleep(1500 * (a + 1)); continue; }
+ await sleep(300); return j.data;
+ }
+ return { errors: [{ message: 'gql retries exhausted' }] };
+}
+
+const FIELDS = `id handle status title vendor tags
+ cw: metafield(namespace:"${CW_NS}", key:"${CW_KEY}"){ value }`;
+
+async function fetchHandle(h) {
+ const d = await gql(`query($q:String!){ products(first:1, query:$q){ nodes{ ${FIELDS} } } }`, { q: `handle:${h}` });
+ return (d && d.products && d.products.nodes && d.products.nodes[0]) || null;
+}
+
+const evidence = JSON.parse(fs.readFileSync(path.join(OUT, 'tk11076-residual-comma-truncation.json'), 'utf8'));
+
+// ── CURATED per-product corrections. correct colorway READ FROM THE TITLE only. ──
+// Full color = pattern-name-stripped color segment of the title, verbatim, comma form.
+const CORRECT = {
+ // 16 live truncated — Versace / Ultrasuede
+ 'baroque-round-ornament-black-gold-silver-wallcovering-versace': 'Black, Gold, Silver',
+ 'medusa-medallion-stripe-grey-silver-metallic-wallcovering-versace': 'Grey, Silver, Metallic',
+ 'medusa-label-metallic-black-white-wallcovering-versace': 'Metallic, Black, White',
+ 'crowns-roses-black-gold-cream-wallcovering-versace': 'Black, Gold, Cream',
+ 'medusa-circle-ornament-beige-grey-gold-wallcovering-versace': 'Beige, Grey, Gold',
+ 'medusa-filigree-white-beige-metallic-wallcovering-versace': 'White, Beige, Metallic',
+ 'paradise-birds-gold-black-yellow-wallcovering-versace': 'Gold, Black, Yellow',
+ 'versace-floral-ornament-white-grey-metallic-wallcovering-versace': 'White, Grey, Metallic',
+ 'versace-window-balustrade-grey-white-blue-wallcovering-versace-1': 'Grey, White, Blue',
+ 'marble-line-grey-black-metallic-wallcovering-versace': 'Grey, Black, Metallic',
+ 'medusa-circle-gold-silver-white-wallcovering-versace': 'Gold, Silver, White',
+ 'medusa-circle-silver-gold-pink-wallcovering-versace': 'Silver, Gold, Pink',
+ 'versace-plain-glitter-pink-grey-purple-wallcovering-versace-1': 'Pink, Grey, Purple',
+ 'ultra_2840': 'Aqua, Green, Blue',
+ 'ultra_2900': 'Orange, Pink, Red',
+ // 16th live-truncated but AMBIGUOUS — colorway not obvious from title; do NOT auto-propose
+ 'one-two-three-one-two-three-romo': null, // AMBIGUOUS — needs Steve
+};
+const AMBIGUOUS = new Set(['one-two-three-one-two-three-romo']);
+const REBEL_EXCLUDE = new Set(['dwrw-74399', 'dwrw-74394']); // correct comma-form, leave alone
+
+async function run() {
+ const landed = evidence.filter(r => r.landed === true);
+ const rows = [];
+ for (const r of landed) {
+ const p = await fetchHandle(r.h);
+ const liveTags = p ? (Array.isArray(p.tags) ? p.tags : String(p.tags || '').split(',').map(s => s.trim())) : null;
+ const liveFacetTags = liveTags ? liveTags.filter(t => /^color:/i.test(t)) : null;
+ const liveMeta = p && p.cw ? p.cw.value : null;
+ const kind = REBEL_EXCLUDE.has(r.h) ? 'EXCLUDE-rebel-correct'
+ : AMBIGUOUS.has(r.h) ? 'AMBIGUOUS-live'
+ : 'CURATED-live';
+ const proposedMeta = CORRECT[r.h] || null; // verbatim comma form for custom.real_color_name
+ const proposedFacetTag = proposedMeta ? 'color:' + proposedMeta.replace(/\s*,\s*/g, ' / ') : null;
+ rows.push({
+ h: r.h, kind, title: p ? p.title : r.t, vendor: p ? p.vendor : r.v,
+ live_found: !!p, live_status: p ? p.status : null,
+ current_facet_tags: liveFacetTags,
+ current_real_color_name_metafield: liveMeta,
+ evidence_meta: r.meta, evidence_colorTags: r.colorTags,
+ proposed_real_color_name_metafield: proposedMeta,
+ proposed_facet_tag: proposedFacetTag,
+ product_gid: p ? p.id : null,
+ });
+ console.log(`[${kind}] ${r.h}\n status=${p ? p.status : 'NOT FOUND'} | current facet tags=${JSON.stringify(liveFacetTags)} | current meta=${JSON.stringify(liveMeta)}\n -> proposed meta=${JSON.stringify(proposedMeta)} | proposed tag=${JSON.stringify(proposedFacetTag)}`);
+ }
+ const outFile = path.join(OUT, 'tk11679-live-verify.json');
+ fs.writeFileSync(outFile, JSON.stringify({
+ ts: new Date().toISOString(), mode: 'GET-ONLY',
+ landed_count: landed.length,
+ curated_live: rows.filter(r => r.kind === 'CURATED-live').length,
+ ambiguous_live: rows.filter(r => r.kind === 'AMBIGUOUS-live').length,
+ excluded_rebel: rows.filter(r => r.kind === 'EXCLUDE-rebel-correct').length,
+ rows,
+ }, null, 2));
+ console.log(`\nwrote ${outFile}`);
+ console.log(`curated=${rows.filter(r=>r.kind==='CURATED-live').length} ambiguous=${rows.filter(r=>r.kind==='AMBIGUOUS-live').length} rebel-excluded=${rows.filter(r=>r.kind==='EXCLUDE-rebel-correct').length}`);
+}
+run();
← 1cc388f auto-data-snapshot: 2026-09-14T00:22:42 (1 data files) — scr
·
back to Designerwallcoverings
·
TK-11673: June SEO title_tag de-dup/de-truncate map builder 4a15ac1 →