[object Object]

← back to Dw Rotation Activator

rotation-activator: block $4.25 sample-leak price from passing the activation gate (TK-10456)

d9e84e1c0d0ef978e9a7d281305653a5231ac9f3 · 2026-08-31 12:42:22 -0700 · Steve

The 5-field gate required a sellable variant with price>0, but the universal
$4.25 memo-sample price is >0, so any draft whose only sellable roll was stuck
at $4.25 passed the gate and the rotation flipped it DRAFT->ACTIVE — re-leaking
reverted discontinued/no-price products (5 Thibaut murals + 6 Chloe re-activated
at $4.25 hours after being reverted). Now a sellable variant priced at exactly
the sample-leak $4.25 no longer counts as a real price; a real price on any
sellable variant still passes. Fail-safe: can only block an activation.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit d9e84e1c0d0ef978e9a7d281305653a5231ac9f3
Author: Steve <steve@designerwallcoverings.com>
Date:   Mon Aug 31 12:42:22 2026 -0700

    rotation-activator: block $4.25 sample-leak price from passing the activation gate (TK-10456)
    
    The 5-field gate required a sellable variant with price>0, but the universal
    $4.25 memo-sample price is >0, so any draft whose only sellable roll was stuck
    at $4.25 passed the gate and the rotation flipped it DRAFT->ACTIVE — re-leaking
    reverted discontinued/no-price products (5 Thibaut murals + 6 Chloe re-activated
    at $4.25 hours after being reverted). Now a sellable variant priced at exactly
    the sample-leak $4.25 no longer counts as a real price; a real price on any
    sellable variant still passes. Fail-safe: can only block an activation.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 lib/five-field-extra.js       | 17 ++++++++++++++++-
 test/five-field-extra.test.js | 22 ++++++++++++++++++++++
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/lib/five-field-extra.js b/lib/five-field-extra.js
index 6fd9940..57b0c00 100644
--- a/lib/five-field-extra.js
+++ b/lib/five-field-extra.js
@@ -1,5 +1,13 @@
 'use strict';
 
+// The universal memo-sample price. A "sellable" (non-sample) variant stuck at
+// exactly this value is the $4.25 sample-price LEAK, NOT a real sellable price —
+// so it must NOT satisfy the price>0 gate (else the activator flips DRAFT→ACTIVE
+// on a product that is orderable at $4.25). Fail-safe: this can only BLOCK an
+// activation, never cause one. (TK-10456, 2026-08-31 — the rotation was
+// re-activating reverted $4.25 murals/Chloe because $4.25 > 0 passed the gate.)
+const SAMPLE_LEAK_PRICE = 4.25;
+
 function fiveFieldExtra(product) {
   const hasValidVariantsShape = Array.isArray(product?.variants?.nodes);
   const hasValidTagsShape = Array.isArray(product?.tags);
@@ -9,11 +17,17 @@ function fiveFieldExtra(product) {
     : [];
   const hasSample = variants.some((variant) => /-sample$/i.test(variant.sku || ''));
   const sellable = variants.filter((variant) => !/-sample$/i.test(variant.sku || ''));
-  const hasSellablePriced = sellable.some((variant) => {
+  const pricedSellable = sellable.filter((variant) => {
     if (typeof variant.price !== 'string' || !/^\d+(?:\.\d+)?$/.test(variant.price)) return false;
     const price = Number(variant.price);
     return Number.isFinite(price) && price > 0;
   });
+  const hasSellablePriced = pricedSellable.length > 0;
+  // If the ONLY priced sellable variant(s) sit at the sample-leak price, this is a
+  // $4.25 leak, not a real price → block. A real price on any sellable variant
+  // (e.g. a $384 roll alongside a $4.25 sample) still passes.
+  const onlySampleLeakPriced = hasSellablePriced &&
+    pricedSellable.every((variant) => Number(variant.price) === SAMPLE_LEAK_PRICE);
   const isQuoteOnly = tags.includes('quotes');
   const reasons = [];
   if (!hasValidVariantsShape) reasons.push('invalid-variants-shape');
@@ -21,6 +35,7 @@ function fiveFieldExtra(product) {
   if (!hasSample) reasons.push('no-sample-variant');
   if (!sellable.length && !isQuoteOnly) reasons.push('no-sellable-variant');
   if (!hasSellablePriced && !isQuoteOnly) reasons.push('sellable-price-not-gt-0');
+  else if (onlySampleLeakPriced && !isQuoteOnly) reasons.push('sellable-price-is-sample-leak-4.25');
   if (tags.length < 2) reasons.push('fewer-than-2-tags');
   return { ok: reasons.length === 0, reasons };
 }
diff --git a/test/five-field-extra.test.js b/test/five-field-extra.test.js
index 8e68d11..374e7e0 100644
--- a/test/five-field-extra.test.js
+++ b/test/five-field-extra.test.js
@@ -27,6 +27,28 @@ test('rejects missing, zero, malformed, and negative sellable prices', () => {
   }
 });
 
+test('blocks the $4.25 sample-leak price on the sellable variant (TK-10456)', () => {
+  // a "sellable" roll stuck at the memo-sample price 4.25 is the leak, not a real price
+  const leak = fiveFieldExtra(product([
+    { sku: 'DW-100-Sample', price: '4.25' }, { sku: 'DW-100-Roll', price: '4.25' },
+  ]));
+  assert.equal(leak.ok, false);
+  assert.ok(leak.reasons.includes('sellable-price-is-sample-leak-4.25'));
+
+  // a real price alongside a 4.25 sample still passes
+  const real = fiveFieldExtra(product([
+    { sku: 'DW-100-Sample', price: '4.25' }, { sku: 'DW-100-Roll', price: '384.00' },
+  ]));
+  assert.deepEqual(real, { ok: true, reasons: [] });
+
+  // mixed: a real sellable + a leaked sellable still passes (any real price is enough)
+  const mixed = fiveFieldExtra(product([
+    { sku: 'DW-100-Sample', price: '4.25' }, { sku: 'DW-100-Roll', price: '4.25' },
+    { sku: 'DW-100-DR', price: '768.00' },
+  ]));
+  assert.equal(mixed.ok, true);
+});
+
 test('fails closed on non-array variants and tags with explicit shape reasons', () => {
   const variants = [{ sku: 'DW-100-SAMPLE', price: '5.00' }, { sku: 'DW-100', price: '125.00' }];
   const tagsString = fiveFieldExtra({ variants: { nodes: variants }, tags: 'wallpaper' });

← c4f1747 Fail closed on malformed activation fields  ·  back to Dw Rotation Activator  ·  feat(golive-gate): mfr_sku provenance gate blocks blank/fabr 99013ea →