[object Object]

← back to Dw Yolo Loop

feed-eligibility: leak-check on feed-emitted fields only (title/handle/vendor)

257f9f8abd79a884d7039f3d7bd3774fba89e27e · 2026-06-15 08:23:01 -0700 · Steve Abrams

Calibrated: of 988 private-label tag-matches, only 29 actually leak through the
feed (token in title/handle/vendor); 959 are tags-only -> feed-safe (the feed
never emits tags). Those now pass the gate (+932 eligible w/ priced rolls) and
get a tag_scrub_needed advisory flag instead of a hard exclude.

Files touched

Diff

commit 257f9f8abd79a884d7039f3d7bd3774fba89e27e
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Mon Jun 15 08:23:01 2026 -0700

    feed-eligibility: leak-check on feed-emitted fields only (title/handle/vendor)
    
    Calibrated: of 988 private-label tag-matches, only 29 actually leak through the
    feed (token in title/handle/vendor); 959 are tags-only -> feed-safe (the feed
    never emits tags). Those now pass the gate (+932 eligible w/ priced rolls) and
    get a tag_scrub_needed advisory flag instead of a hard exclude.
---
 scripts/google-feed/feed-eligibility.mjs | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/scripts/google-feed/feed-eligibility.mjs b/scripts/google-feed/feed-eligibility.mjs
index 443a225..c86a7a9 100644
--- a/scripts/google-feed/feed-eligibility.mjs
+++ b/scripts/google-feed/feed-eligibility.mjs
@@ -93,9 +93,15 @@ query($cursor:String){
 
 function evaluate(p) {
   const reasons = [];
+  const flags = [];
   const title = p.title || '';
   const tagsBlob = (p.tags || []).join(' ');
   const ctx = norm([p.vendor, title, tagsBlob, p.handle, p.productType].join(' '));
+  // Leak check runs ONLY over fields the feed actually emits (title/handle/vendor).
+  // A private-label name buried in tags/productType never reaches Google via this feed,
+  // so it's a catalog-hygiene issue (tag scrub), not a feed blocker. Calibrated 2026-06-15:
+  // of 988 tag-matches only 29 were real feed-field leaks.
+  const feedCtx = norm([p.vendor, title, p.handle].join(' '));
   const variants = p.variants?.nodes || [];
   const rolls = variants.filter(v => !isSample(v)).map(v => parseFloat(v.price)).filter(Number.isFinite);
   const rollPrice = rolls.length ? Math.max(...rolls) : null;
@@ -109,16 +115,21 @@ function evaluate(p) {
   else if (rollPrice < FLOOR) reasons.push(`roll_price_below_floor_${rollPrice}`);
   if (rollPrice === 4.25) reasons.push('roll_price_is_425_sampletrap');
 
-  // private-label leak -> never customer-facing
+  // private-label leak -> only exclude if it reaches a FEED-emitted field
   for (const tok of PRIVATE_LABEL_LEAK) {
-    if (ctx.includes(tok)) { reasons.push(`private_label_leak:${tok}`); break; }
+    if (feedCtx.includes(tok)) { reasons.push(`private_label_leak:${tok}`); break; }
+  }
+  // tags-only private-label name = feed-safe but a catalog-hygiene flag
+  if (!reasons.some(r => r.startsWith('private_label_leak'))) {
+    for (const tok of PRIVATE_LABEL_LEAK) {
+      if (ctx.includes(tok)) { flags.push(`tag_scrub_needed:${tok}`); break; }
+    }
   }
   // banned words
   if (/\bwallpapers?\b/i.test(title)) reasons.push('title_says_wallpaper');
   if (/\bunknown\b/i.test(title)) reasons.push('title_says_unknown');
 
   // Kravet MAP floor (exclude only if we can PROVE it's below MAP; else flag)
-  const flags = [];
   const isKravet = KRAVET_FAMILY.some(k => ctx.includes(k));
   if (isKravet && rollPrice != null) {
     const cost = COST.get(p.id) || 0;

← 5de6726 Google feed scoping: live-Shopify-driven eligibility gate +  ·  back to Dw Yolo Loop  ·  Google feed: prep-actions (punch-list + unpublish-list) + ga 90c7e9a →