[object Object]

← back to Dw Yolo Loop

cycle-44: broken-image delivery pilot (312 active sampled, 99.7% OK, 0 broken; axis closed, read-only)

31803d5f4e1b74de56cb3499dcb36c8232e7c74c · 2026-06-16 16:01:01 -0700 · Steve Abrams

Files touched

Diff

commit 31803d5f4e1b74de56cb3499dcb36c8232e7c74c
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Tue Jun 16 16:01:01 2026 -0700

    cycle-44: broken-image delivery pilot (312 active sampled, 99.7% OK, 0 broken; axis closed, read-only)
---
 scripts/broken-image-pilot/broken-image-pilot.mjs | 53 +++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/scripts/broken-image-pilot/broken-image-pilot.mjs b/scripts/broken-image-pilot/broken-image-pilot.mjs
new file mode 100644
index 0000000..3859798
--- /dev/null
+++ b/scripts/broken-image-pilot/broken-image-pilot.mjs
@@ -0,0 +1,53 @@
+// Cycle-44 broken-image pilot (read-only, $0). Samples live ACTIVE products across
+// the catalog via /products.json and HEADs each product's featured image to measure
+// real delivery health (200 + image/* content-type). Complements c26 (presence) and
+// c29 (alt-text). No writes. Customer-facing + Google-feed quality signal.
+const HOST = 'https://www.designerwallcoverings.com';
+const PAGES = [1,8,16,24,32,40,48,56,64,72,80,88,96];
+const PER_PAGE_SAMPLE = 24;
+const UA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124 Safari/537.36';
+
+const sleep = ms => new Promise(r => setTimeout(r, ms));
+function pick(arr, n){ // deterministic-ish stride sample, no RNG
+  if (arr.length <= n) return arr;
+  const out=[], stride=arr.length/n;
+  for(let i=0;i<n;i++) out.push(arr[Math.floor(i*stride)]);
+  return out;
+}
+
+const results = [];
+let scanned=0, noImage=0, broken=0, ok=0, unknown=0;
+
+for (const pg of PAGES) {
+  let prods=[];
+  try {
+    const r = await fetch(`${HOST}/products.json?limit=250&page=${pg}`, {headers:{'User-Agent':UA}});
+    if (!r.ok){ console.error(`page ${pg}: HTTP ${r.status}`); continue; }
+    prods = (await r.json()).products || [];
+  } catch(e){ console.error(`page ${pg}: ${e.message}`); continue; }
+  if (!prods.length) continue;
+  for (const p of pick(prods, PER_PAGE_SAMPLE)) {
+    scanned++;
+    const img = (p.images && p.images[0] && p.images[0].src) || null;
+    if (!img){ noImage++; results.push({handle:p.handle, vendor:p.vendor, status:'NO_IMAGE', img:null}); continue; }
+    try {
+      const hr = await fetch(img, {method:'HEAD', headers:{'User-Agent':UA}});
+      const ct = hr.headers.get('content-type')||'';
+      if (hr.ok && ct.startsWith('image/')){ ok++; }
+      else { broken++; results.push({handle:p.handle, vendor:p.vendor, status:`BROKEN_${hr.status}_${ct||'noct'}`, img}); }
+    } catch(e){ unknown++; results.push({handle:p.handle, vendor:p.vendor, status:`ERR_${e.message.slice(0,30)}`, img}); }
+    await sleep(40);
+  }
+  await sleep(150);
+}
+
+const pct = n => scanned? (100*n/scanned).toFixed(1)+'%' : 'n/a';
+console.log(`\n=== Broken-image pilot — ${scanned} active products sampled across pages ${PAGES.join(',')} ===`);
+console.log(`OK (200 + image/*):   ${ok}  (${pct(ok)})`);
+console.log(`NO_IMAGE (0 images):  ${noImage}  (${pct(noImage)})`);
+console.log(`BROKEN (non-200/non-image): ${broken}  (${pct(broken)})`);
+console.log(`UNKNOWN (fetch error): ${unknown}  (${pct(unknown)})`);
+if (results.length){
+  console.log(`\n--- flagged (${results.length}) ---`);
+  for (const r of results.slice(0,40)) console.log(`[${r.status}] ${r.vendor} :: ${r.handle}`);
+}

← 72fbe08 add_roll_variants: enforce ROLL-unit in-script (standing rul  ·  back to Dw Yolo Loop  ·  broken-image scan (c44): PASS — 0% broken on 117-sample (ima ac592b1 →