[object Object]

← back to Gmc Titlefix

TK-11559: gated Google-channel exclude executor for the 3 tiny-image tail products (dry-run verified, not applied)

5854e2e0eb266a00bf8906616d3cc32f47f9b5b5 · 2026-09-12 23:54:49 -0700 · Steve

Revises DTD-B (archive all 3): read-only per-SKU due-diligence shows FLS-2768 is
a live sellable Hollywood roll ($31.92/yd) that must NOT be archived, and the 2
Coordonne are Showroom Line stubs. Reversible fix = publishableUnpublish from
Google & YouTube (Koroseal/Majilite precedent), rollback-map first.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KfevHRTapvcS2vMNNuC31z

Files touched

Diff

commit 5854e2e0eb266a00bf8906616d3cc32f47f9b5b5
Author: Steve <steve@designerwallcoverings.com>
Date:   Sat Sep 12 23:54:49 2026 -0700

    TK-11559: gated Google-channel exclude executor for the 3 tiny-image tail products (dry-run verified, not applied)
    
    Revises DTD-B (archive all 3): read-only per-SKU due-diligence shows FLS-2768 is
    a live sellable Hollywood roll ($31.92/yd) that must NOT be archived, and the 2
    Coordonne are Showroom Line stubs. Reversible fix = publishableUnpublish from
    Google & YouTube (Koroseal/Majilite precedent), rollback-map first.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01KfevHRTapvcS2vMNNuC31z
---
 data/tk11559-rollback-map.json | 26 ++++++++++++++++++
 tk11559-gmc-exclude.mjs        | 61 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 87 insertions(+)

diff --git a/data/tk11559-rollback-map.json b/data/tk11559-rollback-map.json
new file mode 100644
index 0000000..5660ab1
--- /dev/null
+++ b/data/tk11559-rollback-map.json
@@ -0,0 +1,26 @@
+{
+  "ts": "2026-09-13T06:53:58.253Z",
+  "ticket": "TK-11559",
+  "channel": "Google & YouTube",
+  "publicationId": "gid://shopify/Publication/29646651457",
+  "rollback": [
+    {
+      "handle": "love-stars-cor-23333",
+      "productId": "gid://shopify/Product/1502513135728",
+      "undo": "publishablePublish to Google & YouTube",
+      "note": "Coordonné showroom stub; Needs-Price/Width; sample-only $4.25; not in coordonne_catalog; not found live"
+    },
+    {
+      "handle": "lola-leaf-stripes-cor-23336",
+      "productId": "gid://shopify/Product/1502514118768",
+      "undo": "publishablePublish to Google & YouTube",
+      "note": "Coordonné showroom stub; Needs-Price/Width; sample-only $4.25; not in coordonne_catalog; not found live; LEAF (settlement)"
+    },
+    {
+      "handle": "faux-leaf-squares-fls-2768",
+      "productId": "gid://shopify/Product/1495077552240",
+      "undo": "publishablePublish to Google & YouTube",
+      "note": "Hollywood LIVE SELLABLE $31.92/yd roll; catalog image is same 94px sample; interim only — source a real Momentum image then republish; LEAF (settlement)"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/tk11559-gmc-exclude.mjs b/tk11559-gmc-exclude.mjs
new file mode 100644
index 0000000..c56b208
--- /dev/null
+++ b/tk11559-gmc-exclude.mjs
@@ -0,0 +1,61 @@
+#!/usr/bin/env node
+/** TK-11559 — GATED interim fix for the 3 tiny-image tail products that have NO
+ *  autonomous larger image (2 Coordonné showroom stubs + 1 live Hollywood SKU).
+ *
+ *  Instead of archiving (DTD verdict B, now revised — see the pending-approval memo)
+ *  or shipping a wrong-colorway image, this UNPUBLISHES the 3 from the "Google &
+ *  YouTube" channel ONLY (Publication 29646651457). They leave the GMC feed → the
+ *  `image_too_small` DISAPPROVED signal clears at $0, no wrong image is shipped, and
+ *  the live sellable Hollywood product (FLS-2768, $31.92/yd roll) stays ACTIVE and
+ *  purchasable on the Online Store + every other channel.
+ *
+ *  Proven, Steve-approved precedent: gmc-exclude-koroseal.js / gmc-exclude-majilite.js
+ *  / Fentucci Option-A — publishableUnpublish from Google & YouTube, rollback-map first.
+ *
+ *  REVERSIBLE. Undo = publishablePublish each id back to Google & YouTube
+ *  (data/tk11559-rollback-map.json is written BEFORE any write).
+ *
+ *  DRY-RUN BY DEFAULT. --apply requires --yes-i-am-steve AND ticket approval.
+ *  This is an external-publish/feed change → HARD-GATED. Do NOT run --apply autonomously.
+ *
+ *    node tk11559-gmc-exclude.mjs                       # DRY-RUN: verify + write rollback map
+ *    node tk11559-gmc-exclude.mjs --apply --yes-i-am-steve   # GATED live unpublish
+ *
+ *  Cost: $0 (Shopify Admin API only). */
+import fs from 'fs';
+const SHOP='designer-laboratory-sandbox.myshopify.com', API='2024-10';
+const tok=(fs.readFileSync(process.env.HOME+'/Projects/secrets-manager/.env','utf8').match(/^SHOPIFY_FULL_ACCESS_TOKEN=(.+)$/m)||[])[1];
+const URL=`https://${SHOP}/admin/api/${API}/graphql.json`;
+const GOOGLE_PUB='gid://shopify/Publication/29646651457'; // Google & YouTube
+const APPLY=process.argv.includes('--apply');
+const CONFIRMED=process.argv.includes('--yes-i-am-steve');
+const sleep=ms=>new Promise(r=>setTimeout(r,ms));
+async function gql(q,v){for(let a=0;a<6;a++){const r=await fetch(URL,{method:'POST',headers:{'X-Shopify-Access-Token':tok,'Content-Type':'application/json'},body:JSON.stringify({query:q,variables:v}),signal:AbortSignal.timeout(60000)});const j=await r.json();if(j.errors){if(JSON.stringify(j.errors).includes('THROTTLED')&&a<5){await sleep(2500*(a+1));continue;}throw new Error(JSON.stringify(j.errors).slice(0,300));}return j.data;}throw new Error('throttled');}
+
+const TARGETS=[
+  {handle:'love-stars-cor-23333',       note:'Coordonné showroom stub; Needs-Price/Width; sample-only $4.25; not in coordonne_catalog; not found live'},
+  {handle:'lola-leaf-stripes-cor-23336',note:'Coordonné showroom stub; Needs-Price/Width; sample-only $4.25; not in coordonne_catalog; not found live; LEAF (settlement)'},
+  {handle:'faux-leaf-squares-fls-2768', note:'Hollywood LIVE SELLABLE $31.92/yd roll; catalog image is same 94px sample; interim only — source a real Momentum image then republish; LEAF (settlement)'},
+];
+
+const rollback=[];
+console.log(`${APPLY?'APPLY':'DRY-RUN'} | TK-11559 | unpublish ${TARGETS.length} from Google & YouTube`);
+for(const t of TARGETS){
+  const d=await gql(`query($h:String!){productByHandle(handle:$h){id title status resourcePublicationsV2(first:25){edges{node{publication{id name}isPublished}}}}}`,{h:t.handle});
+  const p=d.productByHandle;
+  if(!p){console.log('  SKIP not-found',t.handle);continue;}
+  const onG=p.resourcePublicationsV2.edges.some(e=>e.node.isPublished&&e.node.publication.id===GOOGLE_PUB);
+  console.log(`  ${t.handle}  status=${p.status}  onGoogle=${onG}`);
+  if(!onG){console.log('    already off Google & YouTube — nothing to do');continue;}
+  rollback.push({handle:t.handle,productId:p.id,undo:'publishablePublish to Google & YouTube',note:t.note});
+  if(APPLY){
+    if(!CONFIRMED){console.error('    REFUSED: --apply needs --yes-i-am-steve');process.exit(2);}
+    const res=await gql(`mutation($id:ID!,$pid:ID!){publishableUnpublish(id:$id,input:{publicationId:$pid}){userErrors{field message}}}`,{id:p.id,pid:GOOGLE_PUB});
+    console.log('    UNPUBLISHED',JSON.stringify(res.publishableUnpublish.userErrors));
+    await sleep(400);
+  }
+}
+fs.mkdirSync('data',{recursive:true});
+fs.writeFileSync('data/tk11559-rollback-map.json',JSON.stringify({ts:new Date().toISOString(),ticket:'TK-11559',channel:'Google & YouTube',publicationId:GOOGLE_PUB,rollback},null,2));
+console.log(`rollback map -> data/tk11559-rollback-map.json (${rollback.length} entries)`);
+if(!APPLY) console.log('DRY-RUN ONLY. Nothing written to Shopify. Re-run with --apply --yes-i-am-steve after ticket approval.');

← 84ec516 TK-11449: execute residual-3 stripe dedup (Steve-approved 'u  ·  back to Gmc Titlefix  ·  TK-11559: EXECUTED (Steve-approved) — archive 2 Coordonné st 0ebf126 →