← back to Dw Yolo Loop
enrichment-board: local synthesis of c26/c28/c29/GMC into one ranked vendor×axis board
c79083c06225f8f62b27932a1f094d2e52280b94 · 2026-06-16 11:28:08 -0700 · Steve Abrams
Cycle-30 (/bin/zsh, no new scan). Joins metafield-coverage (specs/images/color),
alt-text-coverage, and GMC $4.25 worklist per repped vendor; ranks by total
products-needing-work. Result: specs is the dominant gap (TOP fix for ~all
repped vendors); Clarke & Clarke 3,573 leads, then Gaston Y Daniela/China Seas/
Coordonné/Lee Jofa/Brunschwig; Wolf Gordon is the lone alt-led vendor. Phillip
Jeffries excluded from ranking (display-excluded by rule).
Files touched
A scripts/enrichment-board/build-enrichment-board.mjs
Diff
commit c79083c06225f8f62b27932a1f094d2e52280b94
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Tue Jun 16 11:28:08 2026 -0700
enrichment-board: local synthesis of c26/c28/c29/GMC into one ranked vendor×axis board
Cycle-30 (/bin/zsh, no new scan). Joins metafield-coverage (specs/images/color),
alt-text-coverage, and GMC $4.25 worklist per repped vendor; ranks by total
products-needing-work. Result: specs is the dominant gap (TOP fix for ~all
repped vendors); Clarke & Clarke 3,573 leads, then Gaston Y Daniela/China Seas/
Coordonné/Lee Jofa/Brunschwig; Wolf Gordon is the lone alt-led vendor. Phillip
Jeffries excluded from ranking (display-excluded by rule).
---
.../enrichment-board/build-enrichment-board.mjs | 73 ++++++++++++++++++++++
1 file changed, 73 insertions(+)
diff --git a/scripts/enrichment-board/build-enrichment-board.mjs b/scripts/enrichment-board/build-enrichment-board.mjs
new file mode 100644
index 0000000..934cdc7
--- /dev/null
+++ b/scripts/enrichment-board/build-enrichment-board.mjs
@@ -0,0 +1,73 @@
+// build-enrichment-board — LOCAL synthesis (no Shopify scan, $0). Joins the
+// already-collected per-vendor enrichment audits into ONE ranked vendor×axis
+// board the enrichment pipeline can act on directly:
+// price = # ACTIVE products feeding Google at $4.25 (GMC worklist) [c-GMC]
+// specs = % with material+width metafields (any namespace, hardened) [c28]
+// images = % with >=1 image [c26]
+// color = % with color_hex/color_details [c26]
+// alt = % with ALL images alt-texted [c29]
+// Ranks repped vendors by total "products needing work" across axes.
+//
+// node build-enrichment-board.mjs
+// READ-ONLY (reads local JSON written by prior cycles). $0.
+import fs from 'node:fs';
+const Q=`${process.env.HOME}/.claude/yolo-queue`;
+const mf=JSON.parse(fs.readFileSync(`${Q}/metafield-coverage-2026-06-16.json`,'utf8'));
+const alt=JSON.parse(fs.readFileSync(`${Q}/alt-text-coverage-2026-06-16.json`,'utf8'));
+const gmc=JSON.parse(fs.readFileSync(`${Q}/gmc-feed-exclude-worklist.json`,'utf8'));
+
+// price gap: count GMC $4.25-on-Google targets per vendor
+const priceGap=new Map();
+for(const t of (gmc.targets||[])) priceGap.set(t.vendor, (priceGap.get(t.vendor)||0)+1);
+
+// alt lookup by vendor
+const altByVendor=new Map(alt.vendors.map(v=>[v.vendor, v]));
+
+// build board for REPPED vendors (from the metafield audit's repped flag)
+const PJ=/jeffries/i; // display-excluded — alt/price gaps are by-design, flag but don't rank
+const rows=mf.vendors.filter(v=>v.repped===true && v.active_products>=50).map(v=>{
+ const a=altByVendor.get(v.vendor)||{};
+ const specs=v.specs_pct??0, img=v.img1_pct??0, color=v.color_pct??0;
+ const altp=a.all_alt_pct??null, withImg=a.with_image??v.active_products;
+ const price=priceGap.get(v.vendor)||0;
+ // products-needing-work per axis (absolute), images/color usually ~0
+ const specsNeed=Math.round(v.active_products*(100-specs)/100);
+ const imgNeed=Math.round(v.active_products*(100-img)/100);
+ const colorNeed=Math.round(v.active_products*(100-color)/100);
+ const altNeed= altp==null?null:Math.round(withImg*(100-altp)/100);
+ const excluded=PJ.test(v.vendor);
+ // total work excludes price (separate one-shot GMC fix) and excludes PJ (by-design)
+ const totalNeed= excluded?0:(specsNeed+imgNeed+colorNeed+(altNeed||0));
+ // biggest single fixable axis
+ const axes=[['specs',specsNeed],['images',imgNeed],['color',colorNeed],['alt',altNeed||0]].filter(x=>!excluded);
+ axes.sort((a,b)=>b[1]-a[1]);
+ return { vendor:v.vendor, active:v.active_products, excluded,
+ price_gap:price, specs_pct:specs, images_pct:img, color_pct:color, alt_pct:altp,
+ specs_need:specsNeed, alt_need:altNeed, total_need:totalNeed,
+ top_fix: excluded?'(display-excluded — by design)':(axes[0]&&axes[0][1]>0?`${axes[0][0]} (${axes[0][1]})`:'—clean—') };
+}).sort((a,b)=>b.total_need-a.total_need);
+
+const board={ generated_at:new Date().toISOString(), source:'local synthesis of c26/c28/c29/GMC (no new scan)',
+ repped_vendors:rows.length, rows };
+fs.writeFileSync(`${Q}/enrichment-board-2026-06-16.json`, JSON.stringify(board,null,2));
+
+const pc=p=>p==null?'—':p+'%';
+let md=`# Repped-vendor ENRICHMENT BOARD — ${new Date().toISOString().slice(0,16)}\n\n`;
+md+=`**LOCAL synthesis ($0, no new scan)** of four prior-cycle audits into one ranked vendor×axis to-do. `;
+md+=`Axes: price=# products feeding Google at $4.25 (GMC) · specs=material+width metafields (c28) · images=≥1 image (c26) · color=hex/details (c26) · alt=all-images-alt'd (c29). Ranked by total products needing work (specs+images+color+alt; price is a separate one-shot GMC fix; Phillip Jeffries excluded from ranking — display-excluded by rule).\n\n`;
+md+=`## Ranked board — ${rows.filter(r=>!r.excluded).length} repped vendors\n`;
+md+=`| # | Vendor | Active | price $4.25 | specs | images | color | alt | TOP FIX (products) |\n|--:|---|--:|--:|--:|--:|--:|--:|---|\n`;
+let i=0;
+for(const r of rows){ i++; md+=`| ${i} | ${r.vendor}${r.excluded?' ⚠️':''} | ${r.active} | ${r.price_gap||'—'} | ${pc(r.specs_pct)} | ${pc(r.images_pct)} | ${pc(r.color_pct)} | ${pc(r.alt_pct)} | ${r.top_fix} |\n`; }
+md+=`\n## How to read it\n`;
+md+=`- **TOP FIX** = the single axis with the most products needing work for that vendor — the highest-leverage backfill to task the enrichment pipeline with first.\n`;
+md+=`- **price $4.25** = products whose min variant feeds Google at the sample price (the GMC exclusion set); fixed in one shot by the GMC opt-out + the sample-split remodel, not per-vendor enrichment.\n`;
+md+=`- **images/color ~100%** across repped vendors (c26) — already solved; specs + alt are where the real per-vendor work is.\n`;
+md+=`- ⚠️ = display-excluded (Phillip Jeffries); its blank alt/price are by-design, excluded from ranking.\n`;
+md+=`- All backfills are GATED (prod writes); this board only prioritizes them.\n`;
+fs.writeFileSync(`${Q}/enrichment-board-2026-06-16.md`, md);
+
+console.log(`[enrichment-board] repped vendors ranked: ${rows.filter(r=>!r.excluded).length} (+1 excluded)`);
+console.log('Top 8 by products-needing-work:');
+for(const r of rows.filter(r=>!r.excluded).slice(0,8)) console.log(` ${(""+r.total_need).padStart(5)} need ${r.vendor.padEnd(22)} TOP=${r.top_fix}`);
+console.log(`Board: ${Q}/enrichment-board-2026-06-16.md`);
← 5c719ab schu roll-adds: complete all 81 (41 clean + 36 edge + 4 oddb
·
back to Dw Yolo Loop
·
specs-reparse sizing (c32): the data exists but won't join — 83eb6fa →