← back to Dw Gemini Skip TK11321

lib/mfr-gate.js

88 lines

'use strict';

/*
 * mfr-gate.js — manufacturer-SKU PROVENANCE gate for the DRAFT→ACTIVE flip.
 *
 * Steve's HARD go-live rule (memory new-sku-vendor-mfr-gate, 2026-07-06): any SKU
 * that goes live must carry a REAL manufacturer SKU number — never blank, never a
 * reused internal counter, never an AI/importer-fabricated sequence. The
 * dw-golive-gate-canary MONITORS this after the fact; this gate ENFORCES it BEFORE
 * activation so the activator stops flipping non-compliant products live (TK-11063).
 *
 * Mirrors the canary's predicate (~/.claude/skills/dw-golive-gate-canary/auditor.mjs)
 * and extends it with the single-vendor FABRICATED-sequence class the canary's
 * cross-vendor-reuse test can't see (the Carnegie "Grain 6300 → 63001..630026" bug,
 * where the per-color join invented a 1..N counter and never captured a real color).
 *
 * DESIGN — pure + testable like five-field-extra.js. `mfrGate(ctx)` takes the
 * already-resolved facts (no I/O) so it unit-tests cleanly; the activator does the
 * cheap DB/metafield resolution and hands the result in. Fail-safe: this can only
 * BLOCK an activation, never cause one. Fail-OPEN on unknowns (blank/reuse are the
 * high-confidence classes and are covered explicitly; the fabricated-sequence class
 * only blocks on POSITIVE evidence from staging, never on absence of it).
 */

// A staging color_name that is just a placeholder ("Color 1", "Color 12", "colour 3")
// = DW never captured a real color for this SKU. Per the title rule (color from a real
// scrape only, never AI) this is itself a provenance failure, and it is the signature
// of the fabricated <base>+<seq> family (each fabricated member got a "Color N" stub).
const PLACEHOLDER_COLOR_RE = /^colou?r\s*\d+$/i;

// By-COLOUR private lines that legitimately have NO vendor mfr# (Steve, 2026-08-12) —
// they should stay LIVE, not be blocked. Kept in sync with the canary's
// NOMFR_EXEMPT_VENDORS. Extend for future by-colour lines.
const NOMFR_EXEMPT_VENDORS = ['novasuede'];

function isExemptVendor(vendor) {
  const v = String(vendor || '').toLowerCase();
  return NOMFR_EXEMPT_VENDORS.some((e) => v.includes(e));
}

/*
 * mfrGate(ctx) → { ok, reasons }
 *
 * ctx:
 *   vendor            {string}  the product's vendor (for the by-colour exemption)
 *   mfr               {string}  the RESOLVED mfr code (metafield dwc/custom/global
 *                               .manufacturer_sku, else the mfr_sku column). '' / null
 *                               / 'unknown' all count as blank.
 *   reusedAcrossVendors {bool}  true iff this exact code appears under >1 vendor in
 *                               shopify_products (the internal-counter bug class).
 *   stagingColorName  {string|null|undefined}  the color_name of the staging row whose
 *                               mfr_sku === this code, or null/undefined if there is no
 *                               such row / staging was not consulted. A PLACEHOLDER value
 *                               ("Color N") = fabricated provenance → BLOCK. A real color
 *                               name, or no staging row at all, does NOT block here.
 */
function mfrGate(ctx) {
  const ctxObj = ctx && typeof ctx === 'object' ? ctx : {};
  const vendor = ctxObj.vendor;
  const reasons = [];

  // By-colour private lines are a legitimate exception — never a mfr FAIL.
  if (isExemptVendor(vendor)) return { ok: true, reasons };

  const mfr = String(ctxObj.mfr == null ? '' : ctxObj.mfr).trim();

  // (a) blank / null / literal "unknown" (never allowed in a title either).
  if (!mfr || /^unknown$/i.test(mfr)) {
    reasons.push('mfr-sku-blank');
    return { ok: false, reasons }; // nothing else to test on a blank code
  }

  // (b) reused internal counter — the same code under >1 vendor.
  if (ctxObj.reusedAcrossVendors === true) reasons.push('mfr-sku-reused-across-vendors');

  // (c) fabricated single-vendor sequence — POSITIVE evidence only: the staging row
  // for this exact code carries a placeholder "Color N" name (the invented-counter
  // signature). Absence of a staging row, or a real color name, does NOT block.
  const staging = ctxObj.stagingColorName;
  if (typeof staging === 'string' && PLACEHOLDER_COLOR_RE.test(staging.trim())) {
    reasons.push('mfr-sku-fabricated-placeholder-color');
  }

  return { ok: reasons.length === 0, reasons };
}

module.exports = { mfrGate, isExemptVendor, NOMFR_EXEMPT_VENDORS, PLACEHOLDER_COLOR_RE };