[object Object]

← back to Carnegie Reprice

carnegie-mfr-gate: add bodyHtmlValid + wire into assertActivatable (TK-10820)

015d3c80d99bcbe6a58d062aabc66e606f896bcb · 2026-08-24 19:09:27 -0700 · Steve Abrams

Files touched

Diff

commit 015d3c80d99bcbe6a58d062aabc66e606f896bcb
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Mon Aug 24 19:09:27 2026 -0700

    carnegie-mfr-gate: add bodyHtmlValid + wire into assertActivatable (TK-10820)
---
 carnegie-mfr-gate.mjs | 26 +++++++++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/carnegie-mfr-gate.mjs b/carnegie-mfr-gate.mjs
index 98f8844..881b27c 100644
--- a/carnegie-mfr-gate.mjs
+++ b/carnegie-mfr-gate.mjs
@@ -38,11 +38,28 @@ export function mfrSkuValid(mfr) {
   return true;
 }
 
+/** Tag applied to products that fail the body_html gate */
+export const NEEDS_DESC_TAG = 'Needs-Description';
+
+/**
+ * Returns true iff `body` is a real, non-blank product description.
+ * Strips HTML tags, &nbsp;, and whitespace before checking, so an empty
+ * <p></p> shell or a bare wrapper counts as blank. This is the guard the
+ * TK-10686 batch was missing — it shipped 57 products ACTIVE with blank
+ * body_html because the activator gated only on mfr_sku.
+ */
+export function bodyHtmlValid(body) {
+  if (body === null || body === undefined) return false;
+  const text = String(body).replace(/<[^>]*>/g, '').replace(/&nbsp;/gi, ' ').trim();
+  return text.length > 0;
+}
+
 /**
  * Returns { ok: true } if the row is safe to activate, or
  * { ok: false, reason: string } if it must stay draft.
+ * Fails on either a missing mfr_sku OR a blank body_html/description.
  *
- * @param {object} row - any object with a `mfr_sku` property
+ * @param {object} row - object with `mfr_sku` and (`body_html`|`description_text`)
  */
 export function assertActivatable(row) {
   const mfr = row?.mfr_sku;
@@ -53,6 +70,13 @@ export function assertActivatable(row) {
       reason: `mfr_sku ${display} is null, empty, or a DWAG-* internal placeholder — product stays DRAFT (${SKIP_TAG})`,
     };
   }
+  const body = row?.body_html ?? row?.description_text;
+  if (!bodyHtmlValid(body)) {
+    return {
+      ok: false,
+      reason: `body_html/description is blank — product stays DRAFT (${NEEDS_DESC_TAG})`,
+    };
+  }
   return { ok: true };
 }
 

← 4de1b96 feat: Carnegie importer gate — skip ACTIVE if no real mfr_sk  ·  back to Carnegie Reprice  ·  carnegie-mfr-gate: broaden bodyHtmlValid entity strip (Cody 83498d8 →