← back to Designerwallcoverings
TK-11237: add no-description go-live gate to 6 ungated onboarders — HOLD as draft if body_html empty
844d921fab812e13f8e20892a1bc5f90d99ddbbe · 2026-09-04 09:53:29 -0700 · Steve Abrams
Mirrors the eadef9f TK-10303 manufacturer_sku gate. The 09-02 onboard flipped
~1005 Architectural Fabrics (Vahallan) products ACTIVE with empty body_html,
tripping dw-five-field-canary (no_desc +1006). These 6 go-live scripts activated
without a description check that the .mjs onboarders (sanderson/stout/stroheim/
muralsource) already carry via validateBeforeActivate. Query descriptionHtml right
before status:ACTIVE and HOLD the product as draft if empty. Reversible-local;
no live data touched.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C7vPkHaqxBs7n9C4SHodTQ
Files touched
M scripts/artmura-onboard/go-live-artmura.jsM scripts/fallingstar-onboard/go-live-fallingstar.jsM scripts/knoll-onboard/go-live.mjsM scripts/maharam-onboard/go-live.mjsM scripts/osborne-onboard/go-live.mjsM scripts/tres-tintas-onboard/go-live-tres-tintas.js
Diff
commit 844d921fab812e13f8e20892a1bc5f90d99ddbbe
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Fri Sep 4 09:53:29 2026 -0700
TK-11237: add no-description go-live gate to 6 ungated onboarders — HOLD as draft if body_html empty
Mirrors the eadef9f TK-10303 manufacturer_sku gate. The 09-02 onboard flipped
~1005 Architectural Fabrics (Vahallan) products ACTIVE with empty body_html,
tripping dw-five-field-canary (no_desc +1006). These 6 go-live scripts activated
without a description check that the .mjs onboarders (sanderson/stout/stroheim/
muralsource) already carry via validateBeforeActivate. Query descriptionHtml right
before status:ACTIVE and HOLD the product as draft if empty. Reversible-local;
no live data touched.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C7vPkHaqxBs7n9C4SHodTQ
---
scripts/artmura-onboard/go-live-artmura.js | 7 +++++++
scripts/fallingstar-onboard/go-live-fallingstar.js | 7 +++++++
scripts/knoll-onboard/go-live.mjs | 7 +++++++
scripts/maharam-onboard/go-live.mjs | 7 +++++++
scripts/osborne-onboard/go-live.mjs | 7 +++++++
scripts/tres-tintas-onboard/go-live-tres-tintas.js | 7 +++++++
6 files changed, 42 insertions(+)
diff --git a/scripts/artmura-onboard/go-live-artmura.js b/scripts/artmura-onboard/go-live-artmura.js
index eb9a17d..acbb6d0 100644
--- a/scripts/artmura-onboard/go-live-artmura.js
+++ b/scripts/artmura-onboard/go-live-artmura.js
@@ -94,6 +94,13 @@ async function goLive(pid) {
console.error(' ⛔ HELD (no manufacturer_sku metafield — TK-10303 go-live gate): ' + gidP);
return { heldNoMfr: true, errs: ['heldNoMfr: no manufacturer_sku metafield'] }; } }
// 4: activate product
+ // TK-11237 go-live gate: never flip a product ACTIVE with an empty description/body_html.
+ // Fail-safe for the no-description breach class (Architectural Fabrics 09-02, ~1005 SKUs):
+ // even if create-drafts shipped an empty descriptionHtml, this HOLDS the product as draft.
+ { const _dh = await gql('query($id:ID!){product(id:$id){descriptionHtml}}', { id: gidP });
+ if (!((_dh?.product?.descriptionHtml || '').replace(/<[^>]*>/g, '').trim())) {
+ console.error(' ⛔ HELD (empty description — TK-11237 go-live gate): ' + gidP);
+ return { heldNoDesc: true, errs: ['heldNoDesc: empty description'] }; } }
const r4 = await gql(M_ACTIVE, { id: gidP });
(r4.productUpdate?.userErrors || []).forEach(e => errs.push('active:' + e.message));
return { status: r4.productUpdate?.product?.status, errs };
diff --git a/scripts/fallingstar-onboard/go-live-fallingstar.js b/scripts/fallingstar-onboard/go-live-fallingstar.js
index 39b3899..3dd81ff 100644
--- a/scripts/fallingstar-onboard/go-live-fallingstar.js
+++ b/scripts/fallingstar-onboard/go-live-fallingstar.js
@@ -85,6 +85,13 @@ async function goLive(pid) {
if (!((_mf?.product?.c?.value || _mf?.product?.d?.value || '').trim())) {
console.error(' ⛔ HELD (no manufacturer_sku metafield — TK-10303 go-live gate): ' + gidP);
return ['heldNoMfr: no manufacturer_sku metafield']; } }
+ // TK-11237 go-live gate: never flip a product ACTIVE with an empty description/body_html.
+ // Fail-safe for the no-description breach class (Architectural Fabrics 09-02, ~1005 SKUs):
+ // even if create-drafts shipped an empty descriptionHtml, this HOLDS the product as draft.
+ { const _dh = await gql('query($id:ID!){product(id:$id){descriptionHtml}}', { id: gidP });
+ if (!((_dh?.product?.descriptionHtml || '').replace(/<[^>]*>/g, '').trim())) {
+ console.error(' ⛔ HELD (empty description — TK-11237 go-live gate): ' + gidP);
+ return { heldNoDesc: true, errs: ['heldNoDesc: empty description'] }; } }
const r4 = await gql(M_ACTIVE, { id: gidP });
(r4.productUpdate?.userErrors || []).forEach(e => errs.push('active:' + e.message));
return errs;
diff --git a/scripts/knoll-onboard/go-live.mjs b/scripts/knoll-onboard/go-live.mjs
index 9f11f6e..e1e6af9 100644
--- a/scripts/knoll-onboard/go-live.mjs
+++ b/scripts/knoll-onboard/go-live.mjs
@@ -82,6 +82,13 @@ async function goLive(pid, sku) {
if (!((_mf?.product?.c?.value || _mf?.product?.d?.value || '').trim())) {
console.error(' ⛔ HELD (no manufacturer_sku metafield — TK-10303 go-live gate): ' + gidP);
return { heldNoMfr: true }; } }
+ // TK-11237 go-live gate: never flip a product ACTIVE with an empty description/body_html.
+ // Fail-safe for the no-description breach class (Architectural Fabrics 09-02, ~1005 SKUs):
+ // even if create-drafts shipped an empty descriptionHtml, this HOLDS the product as draft.
+ { const _dh = await gql('query($id:ID!){product(id:$id){descriptionHtml}}', { id: gidP });
+ if (!((_dh?.product?.descriptionHtml || '').replace(/<[^>]*>/g, '').trim())) {
+ console.error(' ⛔ HELD (empty description — TK-11237 go-live gate): ' + gidP);
+ return { heldNoDesc: true, errs: ['heldNoDesc: empty description'] }; } }
const r4 = await gql(M_ACTIVE, { id: gidP });
(r4.productUpdate?.userErrors || []).forEach(e => errs.push('active:' + e.message));
const status = r4.productUpdate?.product?.status;
diff --git a/scripts/maharam-onboard/go-live.mjs b/scripts/maharam-onboard/go-live.mjs
index 32ba632..0a5b75b 100644
--- a/scripts/maharam-onboard/go-live.mjs
+++ b/scripts/maharam-onboard/go-live.mjs
@@ -87,6 +87,13 @@ async function goLive(pid, sku, mfrSku) {
if (!((_mf?.product?.c?.value || _mf?.product?.d?.value || '').trim())) {
console.error(' ⛔ HELD (no manufacturer_sku metafield — TK-10303 go-live gate): ' + gidP);
return { heldNoMfr: true }; } }
+ // TK-11237 go-live gate: never flip a product ACTIVE with an empty description/body_html.
+ // Fail-safe for the no-description breach class (Architectural Fabrics 09-02, ~1005 SKUs):
+ // even if create-drafts shipped an empty descriptionHtml, this HOLDS the product as draft.
+ { const _dh = await gql('query($id:ID!){product(id:$id){descriptionHtml}}', { id: gidP });
+ if (!((_dh?.product?.descriptionHtml || '').replace(/<[^>]*>/g, '').trim())) {
+ console.error(' ⛔ HELD (empty description — TK-11237 go-live gate): ' + gidP);
+ return { heldNoDesc: true, errs: ['heldNoDesc: empty description'] }; } }
const r4 = await gql(M_ACTIVE, { id: gidP });
(r4.productUpdate?.userErrors || []).forEach(e => errs.push('active:' + e.message));
const status = r4.productUpdate?.product?.status;
diff --git a/scripts/osborne-onboard/go-live.mjs b/scripts/osborne-onboard/go-live.mjs
index 8806de1..a3dd51c 100644
--- a/scripts/osborne-onboard/go-live.mjs
+++ b/scripts/osborne-onboard/go-live.mjs
@@ -80,6 +80,13 @@ async function goLive(pid) {
if (!((_mf?.product?.c?.value || _mf?.product?.d?.value || '').trim())) {
console.error(' ⛔ HELD (no manufacturer_sku metafield — TK-10303 go-live gate): ' + gidP);
return { heldNoMfr: true }; } }
+ // TK-11237 go-live gate: never flip a product ACTIVE with an empty description/body_html.
+ // Fail-safe for the no-description breach class (Architectural Fabrics 09-02, ~1005 SKUs):
+ // even if create-drafts shipped an empty descriptionHtml, this HOLDS the product as draft.
+ { const _dh = await gql('query($id:ID!){product(id:$id){descriptionHtml}}', { id: gidP });
+ if (!((_dh?.product?.descriptionHtml || '').replace(/<[^>]*>/g, '').trim())) {
+ console.error(' ⛔ HELD (empty description — TK-11237 go-live gate): ' + gidP);
+ return { heldNoDesc: true, errs: ['heldNoDesc: empty description'] }; } }
const r4 = await gql(M_ACTIVE, { id: gidP });
(r4.productUpdate?.userErrors || []).forEach(e => errs.push('active:' + e.message));
return { status: r4.productUpdate?.product?.status, errs };
diff --git a/scripts/tres-tintas-onboard/go-live-tres-tintas.js b/scripts/tres-tintas-onboard/go-live-tres-tintas.js
index dfd4f04..a90e0f9 100644
--- a/scripts/tres-tintas-onboard/go-live-tres-tintas.js
+++ b/scripts/tres-tintas-onboard/go-live-tres-tintas.js
@@ -87,6 +87,13 @@ async function goLive(pid) {
if (!((_mf?.product?.c?.value || _mf?.product?.d?.value || '').trim())) {
console.error(' ⛔ HELD (no manufacturer_sku metafield — TK-10303 go-live gate): ' + gid);
return { heldNoMfr: true, errs: ['heldNoMfr: no manufacturer_sku metafield'] }; } }
+ // TK-11237 go-live gate: never flip a product ACTIVE with an empty description/body_html.
+ // Fail-safe for the no-description breach class (Architectural Fabrics 09-02, ~1005 SKUs):
+ // even if create-drafts shipped an empty descriptionHtml, this HOLDS the product as draft.
+ { const _dh = await gql('query($id:ID!){product(id:$id){descriptionHtml}}', { id: gid });
+ if (!((_dh?.product?.descriptionHtml || '').replace(/<[^>]*>/g, '').trim())) {
+ console.error(' ⛔ HELD (empty description — TK-11237 go-live gate): ' + gid);
+ return { heldNoDesc: true, errs: ['heldNoDesc: empty description'] }; } }
const ra = await gql(M_ACTIVE, { id: gid });
(ra.productUpdate?.userErrors || []).forEach(e => errs.push('active:' + e.message));
return { errs };
← 5c650c9 TK-11226: filtered synth-only restore-map for the gated 143-
·
back to Designerwallcoverings
·
TK-11237: description backfill tooling — grounded generator b5eddda →