[object Object]

← back to Fentucci Naturals

auto-save: 2026-07-27T18:53:10 (3 files) — data/golive-done.jsonl scripts/cadence-golive.sh scripts/reconcile-width-backfill.js

f13fc3dc00cac88df0c38ff8c7be42a8ea0712a5 · 2026-07-27 18:53:15 -0700 · Steve Abrams

Files touched

Diff

commit f13fc3dc00cac88df0c38ff8c7be42a8ea0712a5
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Mon Jul 27 18:53:15 2026 -0700

    auto-save: 2026-07-27T18:53:10 (3 files) — data/golive-done.jsonl scripts/cadence-golive.sh scripts/reconcile-width-backfill.js
---
 data/golive-done.jsonl              |  2 ++
 scripts/cadence-golive.sh           | 19 +++++++++++++++++
 scripts/reconcile-width-backfill.js | 42 +++++++++++++++++++++++++++++++++++++
 3 files changed, 63 insertions(+)

diff --git a/data/golive-done.jsonl b/data/golive-done.jsonl
index e69de29..d0220a3 100644
--- a/data/golive-done.jsonl
+++ b/data/golive-done.jsonl
@@ -0,0 +1,2 @@
+{"sku": "DWFN-100001", "product_id": 7896732631091}
+{"sku": "DWFN-100002", "product_id": 7896733679667}
diff --git a/scripts/cadence-golive.sh b/scripts/cadence-golive.sh
new file mode 100755
index 0000000..baafbf6
--- /dev/null
+++ b/scripts/cadence-golive.sh
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+# Daily go-live cadence tranche for the Fentucci Naturals (Tokiwa) line.
+# Steve-approved 2026-07-27 ("arm the cadence"), gated by DTD verdict B (finish-
+# then-close): trickle-activate 40/day rather than a bulk dump. go-live.py is
+# idempotent — skips already-ACTIVE + golive-done.jsonl, drops the $0/yard variant,
+# keeps the $4.25 sample, publishes to 12 channels (Google excluded). Exits 0 as a
+# no-op once all 504 are live. Width already reconciled to 36"; Needs-Width dropped.
+set -u
+ROOT="$HOME/Projects/fentucci-naturals"
+LOG="$ROOT/logs/cadence-golive.log"
+mkdir -p "$ROOT/logs"
+# grep-export, never `source` — an unquoted value in the secrets .env aborts set -a sourcing
+SHOPIFY_ADMIN_TOKEN=$(grep '^SHOPIFY_ADMIN_TOKEN=' "$HOME/Projects/secrets-manager/.env" | cut -d= -f2- | tr -d '"')
+export SHOPIFY_ADMIN_TOKEN
+{
+  echo "=== fentucci go-live tranche $(date '+%Y-%m-%d %H:%M:%S') ==="
+  cd "$ROOT" && python3 scripts/go-live.py --apply --limit 40
+  echo "=== done $(date '+%Y-%m-%d %H:%M:%S') ==="
+} >> "$LOG" 2>&1
diff --git a/scripts/reconcile-width-backfill.js b/scripts/reconcile-width-backfill.js
new file mode 100644
index 0000000..6f5a397
--- /dev/null
+++ b/scripts/reconcile-width-backfill.js
@@ -0,0 +1,42 @@
+// TK-34 width reconcile: set global.width="36 inches" + drop the Needs-Width tag
+// on the 504 Fentucci/Tokiwa DRAFTs, so TK-00058's Needs-Width guard stops
+// reverting them and go-live.py can trickle-activate. DRAFT products only —
+// nothing customer-facing flips here. Idempotent. --commit to write (dry by default).
+const fs = require('fs'), { execSync } = require('child_process');
+const TOK = fs.readFileSync('/Users/macstudio3/Projects/secrets-manager/.env', 'utf8')
+  .split('\n').find(l => l.startsWith('SHOPIFY_ADMIN_TOKEN=')).split('=')[1];
+const STORE = 'designer-laboratory-sandbox.myshopify.com', API = '2024-10';
+const DRY = !process.argv.includes('--commit');
+const WIDTH = '36 inches';
+const sleep = ms => new Promise(r => setTimeout(r, ms));
+async function gql(q, v) { for (let a = 0; a < 4; a++) { try {
+  const r = await fetch(`https://${STORE}/admin/api/${API}/graphql.json`, { method: 'POST',
+    headers: { 'X-Shopify-Access-Token': TOK, 'Content-Type': 'application/json' },
+    body: JSON.stringify({ query: q, variables: v }) });
+  const j = await r.json(); if (j.errors && a < 3) { await sleep(1500); continue; } return j;
+} catch { await sleep(1500); } } return {}; }
+
+// product IDs of the exact batch (DRAFT · image · quote-tag · fentucci)
+const rows = execSync(`psql "host=/tmp dbname=dw_unified" -tAc "SELECT shopify_product_id FROM tokiwa_catalog WHERE shopify_product_id IS NOT NULL"`)
+  .toString().trim().split('\n').map(s => s.trim()).filter(Boolean);
+
+(async () => {
+  console.log(`mode=${DRY ? 'DRY' : 'COMMIT'}  candidates=${rows.length}  width="${WIDTH}"`);
+  let set = 0, untagged = 0, skip = 0, err = 0;
+  for (const pid of rows) {
+    const gid = `gid://shopify/Product/${pid}`;
+    if (DRY) { set++; continue; }
+    // set width metafield
+    const mr = await gql(`mutation($mfs:[MetafieldsSetInput!]!){metafieldsSet(metafields:$mfs){userErrors{message}}}`,
+      { mfs: [{ ownerId: gid, namespace: 'global', key: 'width', type: 'single_line_text_field', value: WIDTH }] });
+    const me = mr.data?.metafieldsSet?.userErrors || [];
+    if (me.length) { err++; console.log(`  ERR width ${pid}: ${JSON.stringify(me)}`); } else set++;
+    // drop Needs-Width tag
+    const tr = await gql(`mutation($id:ID!,$t:[String!]!){tagsRemove(id:$id,tags:$t){userErrors{message}}}`,
+      { id: gid, t: ['Needs-Width'] });
+    if (!(tr.data?.tagsRemove?.userErrors || []).length) untagged++;
+    if (set % 50 === 0) console.log(`  ...${set}/${rows.length}`);
+    await sleep(250);
+  }
+  console.log(`DONE ${DRY ? '(DRY)' : ''}: width_set=${set} untagged=${untagged} skip=${skip} err=${err}`);
+})();

← 0805607 TK-00034 reconcile: revert the 40 quote-only activations → D  ·  back to Fentucci Naturals  ·  chore: v1.0.5 (session close — TK-34 go-live cadence) 842b7c2 →