← back to Rebel Walls Push
TK-11248 action G: read-only revalidation confirms 6 cleared descriptions already live (no write needed)
ff9dbfbf854b3b4b43e24f211b035aaa13e983af · 2026-09-04 12:16:12 -0700 · Steve Abrams
All 6 settlement-CLEARED Rebel Walls murals carry authorized descriptionHtml,
all DRAFT, 0 activated. 4 from TK-11192 (9/3); 2 refreshed in the 9/4 18:26 wave
(word-identical, curly-vs-straight apostrophe only). Holds intact: R20805 blocked,
5 counsel untouched (len=0). Stopped on the (benign) drift per instruction — no
customer-facing write fired.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RFJimFhUJowuXnXtjNTLEC
Files touched
A scripts/revalidate-descG.js
Diff
commit ff9dbfbf854b3b4b43e24f211b035aaa13e983af
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Fri Sep 4 12:16:12 2026 -0700
TK-11248 action G: read-only revalidation confirms 6 cleared descriptions already live (no write needed)
All 6 settlement-CLEARED Rebel Walls murals carry authorized descriptionHtml,
all DRAFT, 0 activated. 4 from TK-11192 (9/3); 2 refreshed in the 9/4 18:26 wave
(word-identical, curly-vs-straight apostrophe only). Holds intact: R20805 blocked,
5 counsel untouched (len=0). Stopped on the (benign) drift per instruction — no
customer-facing write fired.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RFJimFhUJowuXnXtjNTLEC
---
scripts/revalidate-descG.js | 104 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 104 insertions(+)
diff --git a/scripts/revalidate-descG.js b/scripts/revalidate-descG.js
new file mode 100644
index 0000000..25b322c
--- /dev/null
+++ b/scripts/revalidate-descG.js
@@ -0,0 +1,104 @@
+'use strict';
+/* READ-ONLY revalidation for TK-11248 action G (6 settlement-CLEARED Rebel Walls
+ * descriptionHtml writes). Also confirms the HOLDs (R20805 blocked + 5 counsel)
+ * remain untouched. NO WRITES. $0.
+ *
+ * For each of the 12 HELD murals it GETs live: id, status, vendor, mfr metafield,
+ * current descriptionHtml length + first 80 chars. Compares the 6 target handles
+ * to the drafted copy and reports NEEDS-WRITE / ALREADY-CORRECT / DRIFT.
+ */
+const fs = require('fs');
+const path = require('path');
+const { gqlRetry, DOMAIN } = require('./_shop');
+
+// The 6 CLEAR-TO-PUBLISH (action G) — handle -> {mfr, expected descriptionHtml}
+const DRAFTED = require('./descG-copy.json'); // { handle: {mfr, html} }
+const CLEARED = Object.keys(DRAFTED);
+
+// HOLDS — must stay untouched
+const HOLD_BLOCKED = ['birds-and-cages-petrol-rebel-walls']; // R20805
+const HOLD_COUNSEL = [
+ 'monstera-leaves-beige-rebel-walls', // R19778
+ 'elephant-and-friends-blue-rebel-walls', // R20227
+ 'bear-friend-blue-rebel-walls', // R21071
+ 'happy-bear-beige-rebel-walls', // R21072
+ 'twilight-bouquet-dark-rebel-walls', // R21637
+];
+
+const Q = `query($h: String!){ productByHandle(handle:$h){
+ id legacyResourceId handle title status vendor descriptionHtml
+ mfr: metafield(namespace:"custom", key:"mfr_sku"){ value }
+ global_mfr: metafield(namespace:"global", key:"mfr_sku"){ value }
+} }`;
+
+const norm = s => (s || '').replace(/\s+/g, ' ').trim();
+
+async function getOne(handle) {
+ const r = await gqlRetry(Q, { h: handle }, `h:${handle}`);
+ const p = r.json && r.json.data && r.json.data.productByHandle;
+ return p || null;
+}
+
+async function main() {
+ const ts = new Date().toISOString().replace(/[:.]/g, '-');
+ const report = { ts, store: DOMAIN, cleared: [], hold_blocked: [], hold_counsel: [],
+ gate: { ready: false, needs_write: 0, already_correct: 0, drift: [] } };
+
+ console.log(`\n=== TK-11248 action G REVALIDATION (READ-ONLY, $0) @ ${ts} ===`);
+ console.log(`store: ${DOMAIN}\n`);
+
+ console.log(`[6 CLEAR-TO-PUBLISH — action G targets]`);
+ for (const h of CLEARED) {
+ const p = await getOne(h);
+ const want = DRAFTED[h];
+ if (!p) { report.gate.drift.push(`${h}: NOT FOUND`); console.log(` ${h} DRIFT: not found`); continue; }
+ const curLen = (p.descriptionHtml || '').length;
+ const isDraft = p.status === 'DRAFT';
+ const vendorOk = p.vendor === 'Rebel Walls';
+ const mfrLive = (p.mfr && p.mfr.value) || (p.global_mfr && p.global_mfr.value) || '';
+ const mfrOk = !mfrLive || mfrLive === want.mfr; // tolerate missing metafield
+ const already = norm(p.descriptionHtml) === norm(want.html);
+ const emptyNow = curLen === 0;
+ let state;
+ if (!isDraft) state = 'DRIFT-NOT-DRAFT';
+ else if (!vendorOk) state = 'DRIFT-VENDOR';
+ else if (!mfrOk) state = 'DRIFT-MFR';
+ else if (already) state = 'ALREADY-CORRECT';
+ else if (emptyNow) state = 'NEEDS-WRITE';
+ else state = 'DRIFT-UNEXPECTED-CONTENT'; // has some other description
+ const row = { handle: h, mfr: want.mfr, id: p.id, legacyId: p.legacyResourceId,
+ status: p.status, vendor: p.vendor, mfr_live: mfrLive, cur_len: curLen,
+ cur_preview: norm(p.descriptionHtml).slice(0, 80), state };
+ report.cleared.push(row);
+ if (state === 'NEEDS-WRITE') report.gate.needs_write++;
+ else if (state === 'ALREADY-CORRECT') report.gate.already_correct++;
+ else report.gate.drift.push(`${h}: ${state} (len=${curLen}, status=${p.status})`);
+ console.log(` ${h.padEnd(40)} ${state.padEnd(24)} status=${p.status} len=${curLen} mfr=${mfrLive||'-'}`);
+ }
+
+ console.log(`\n[HOLD — must stay untouched]`);
+ for (const h of [...HOLD_BLOCKED, ...HOLD_COUNSEL]) {
+ const p = await getOne(h);
+ if (!p) { console.log(` ${h.padEnd(40)} (not found)`); continue; }
+ const bucket = HOLD_BLOCKED.includes(h) ? report.hold_blocked : report.hold_counsel;
+ const row = { handle: h, id: p.id, status: p.status, cur_len: (p.descriptionHtml||'').length,
+ cur_preview: norm(p.descriptionHtml).slice(0,60) };
+ bucket.push(row);
+ console.log(` ${h.padEnd(40)} status=${p.status} len=${row.cur_len}${row.cur_len? ' ⚠ has description':''}`);
+ }
+
+ report.gate.ready = report.gate.drift.length === 0 && report.gate.needs_write > 0;
+ const outFile = path.join(__dirname, '..', 'data', `TK11248-descG-revalidation-${ts}.json`);
+ fs.writeFileSync(outFile, JSON.stringify(report, null, 2));
+
+ console.log(`\n--- SUMMARY ---`);
+ console.log(` NEEDS-WRITE: ${report.gate.needs_write}`);
+ console.log(` ALREADY-CORRECT: ${report.gate.already_correct}`);
+ console.log(` DRIFT: ${report.gate.drift.length}${report.gate.drift.length? ' -> ' + report.gate.drift.join(' | '):''}`);
+ console.log(` GATE ready_to_write=${report.gate.ready}`);
+ console.log(`\nEvidence -> ${outFile}`);
+ console.log(`NO WRITES FIRED.\n`);
+ // exit 0 if clean (either all already-correct, or a clean needs-write set); 5 on drift
+ process.exit(report.gate.drift.length ? 5 : 0);
+}
+main().catch(e => { console.error('FATAL', e); process.exit(2); });
← 3fbf2ca auto-data-snapshot: 2026-09-04T12:10:54 (2 data files) — dat
·
back to Rebel Walls Push
·
TK-11248 EXECUTED: Aries title fixed live; guard held 2 posi 8debf6b →