[object Object]

← back to Designer Wallcoverings

TK-135: BARE-VALUE color tags (no color: prefix) + self-heal removes old color:Bucket; Shopify-authoritative

1ad1dff432fcc01e0a111464dc29498471d3d169 · 2026-07-27 19:34:58 -0700 · Steve

Files touched

Diff

commit 1ad1dff432fcc01e0a111464dc29498471d3d169
Author: Steve <steve@designerwallcoverings.com>
Date:   Mon Jul 27 19:34:58 2026 -0700

    TK-135: BARE-VALUE color tags (no color: prefix) + self-heal removes old color:Bucket; Shopify-authoritative
---
 shopify/scripts/tk135-apply-palette.js | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/shopify/scripts/tk135-apply-palette.js b/shopify/scripts/tk135-apply-palette.js
index 7b62bc97..69db0117 100644
--- a/shopify/scripts/tk135-apply-palette.js
+++ b/shopify/scripts/tk135-apply-palette.js
@@ -50,6 +50,7 @@ async function gqlR(q, v, tries = 4) {
 }
 const M_MF = `mutation($mf:[MetafieldsSetInput!]!){metafieldsSet(metafields:$mf){userErrors{field message}}}`;
 const M_TAG = `mutation($id:ID!,$tags:[String!]!){tagsAdd(id:$id,tags:$tags){userErrors{field message}}}`;
+const M_TAGDEL = `mutation($id:ID!,$tags:[String!]!){tagsRemove(id:$id,tags:$tags){userErrors{field message}}}`;
 
 // PG-first: append color tag idempotently in the mirror
 function pgAppendTags(rows) {
@@ -78,7 +79,10 @@ function load() {
   for (const l of lines) {
     const [gid, tag, pj] = l.split('\t');
     if (!gid || !tag || !pj || pj.startsWith('ERR:')) continue;
-    out.push({ gid, tag, palette: pj });
+    // Steve: BARE-VALUE tag (no color: label). `bare` is the tag we write; `prefixed`
+    // is the old color:Bucket form we may have written earlier and now remove (self-heal).
+    const bare = tag.replace(/^\s*[Cc]olor:\s*/, '').trim();
+    out.push({ gid, tag: bare, prefixed: tag, palette: pj });
   }
   return out;
 }
@@ -97,13 +101,12 @@ function load() {
   const report = { ticket: 'TK-135', started: new Date().toISOString(), apply: APPLY, updated: [], failed: [] };
 
   if (APPLY) {
-    // PG mirror is best-effort: Shopify is the authoritative customer-facing write and the mirror re-syncs from it,
-    // so a mirror hiccup (e.g. integrity trigger) must NEVER block the Shopify write.
-    try { const c = pgAppendTags(rows); console.log(`PG mirror tags appended — matched ${c}\n`); report.pg = c; }
-    catch (e) { console.error('⚠ PG mirror write skipped (non-fatal — Shopify authoritative, mirror re-syncs):', (e.message || e).toString().split('\n')[0]); report.pgSkipped = true; }
+    // Tags: Shopify-authoritative (mirror re-syncs). We skip the PG-mirror tag write here because
+    // (a) bare values like "Red" false-match via substring ILIKE, and (b) the mfr_sku trigger blocks some rows.
+    console.log(`(tags/metafields written Shopify-first; dw_unified mirror re-syncs from Shopify)\n`);
   } else {
-    console.log(`(dry-run) would PG-append ${rows.length} color tags, then Shopify metafield+tag each\n`);
-    rows.slice(0, 8).forEach(r => console.log(`  · ${r.gid.split('/').pop()}  ${r.tag}  palette=${r.palette}`));
+    console.log(`(dry-run) per product: metafield color_palette + remove old "${rows[0]?rows[0].prefixed:'color:X'}"-style tag + add BARE value tag\n`);
+    rows.slice(0, 8).forEach(r => console.log(`  · ${r.gid.split('/').pop()}  tag="${r.tag}" (was "${r.prefixed}")  palette=${r.palette}`));
     console.log(`\n  (dry-run) no writes made.`);
     if (REPORT) { fs.mkdirSync(path.dirname(REPORT), { recursive: true }); fs.writeFileSync(REPORT, JSON.stringify({ ...report, totals: { would_update: rows.length } }, null, 2)); }
     return;
@@ -112,6 +115,8 @@ function load() {
   for (const r of rows) {
     const mf = await gqlR(M_MF, { mf: [{ ownerId: r.gid, namespace: 'custom', key: 'color_palette', type: 'json', value: r.palette }] });
     const me = mf.data?.metafieldsSet?.userErrors || [];
+    // self-heal: remove the old prefixed color:Bucket if we wrote it earlier, then add the BARE value
+    if (r.prefixed && r.prefixed !== r.tag) await gqlR(M_TAGDEL, { id: r.gid, tags: [r.prefixed] });
     const tg = await gqlR(M_TAG, { id: r.gid, tags: [r.tag] });
     const te = tg.data?.tagsAdd?.userErrors || [];
     if (me.length || te.length) { report.failed.push({ gid: r.gid, me, te }); console.log(`  ❌ ${r.gid.split('/').pop()} ${JSON.stringify(me.concat(te))}`); }

← 525345fa auto-save: 2026-07-27T19:23:22 (3 files) — package-lock.json  ·  back to Designer Wallcoverings  ·  TK-135: unified color-tag normalizer — strip all color:/Colo 51ad1beb →