[object Object]

← back to Dw Yolo Loop

live-price canary HARDENED (c45): retry/backoff + N=250 → UNKNOWN 20%→0.4%, number corrected

5d9d5623d6d21a91a369d303955520dff833b574 · 2026-06-16 16:36:02 -0700 · Steve Abrams

Hardened the c38 pilot into a promotable standing canary. retry/backoff cut
UNKNOWN from 30/150 (20%) to 1/245 (0.4%). Tighter+corrected number: SAMPLE_ONLY
43.7% / HAS_REAL 56.3% / NO_PRICE 0% (c38's noisy 59/40 was inflated by its high
UNKNOWN). Writes data/latest.json (c34 heartbeat shape); verdict PASS (FAIL if
NO_PRICE spikes — a blank-price regression the broken mirror can't catch).

Files touched

Diff

commit 5d9d5623d6d21a91a369d303955520dff833b574
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Tue Jun 16 16:36:02 2026 -0700

    live-price canary HARDENED (c45): retry/backoff + N=250 → UNKNOWN 20%→0.4%, number corrected
    
    Hardened the c38 pilot into a promotable standing canary. retry/backoff cut
    UNKNOWN from 30/150 (20%) to 1/245 (0.4%). Tighter+corrected number: SAMPLE_ONLY
    43.7% / HAS_REAL 56.3% / NO_PRICE 0% (c38's noisy 59/40 was inflated by its high
    UNKNOWN). Writes data/latest.json (c34 heartbeat shape); verdict PASS (FAIL if
    NO_PRICE spikes — a blank-price regression the broken mirror can't catch).
---
 scripts/live-price-canary/data/latest.json      | 24 +++++++++++++++
 scripts/live-price-canary/live-price-canary.mjs | 39 +++++++++++++++++++++++++
 2 files changed, 63 insertions(+)

diff --git a/scripts/live-price-canary/data/latest.json b/scripts/live-price-canary/data/latest.json
new file mode 100644
index 0000000..23018fb
--- /dev/null
+++ b/scripts/live-price-canary/data/latest.json
@@ -0,0 +1,24 @@
+{
+  "generated_at": "2026-06-16T23:34:26.704Z",
+  "status": "PASS",
+  "headline": "NO_PRICE 0% · SAMPLE_ONLY 43.7% · HAS_REAL 56.3% (n=245)",
+  "sampled": 250,
+  "decided": 245,
+  "buckets": {
+    "HAS_REAL": 138,
+    "SAMPLE_ONLY": 107,
+    "NO_PRICE": 0,
+    "PDP_404": 4,
+    "UNKNOWN": 1
+  },
+  "pct": {
+    "HAS_REAL": 56.3,
+    "SAMPLE_ONLY": 43.7,
+    "NO_PRICE": 0
+  },
+  "noprice_examples": [],
+  "thresholds": {
+    "warn": 3,
+    "fail": 8
+  }
+}
\ No newline at end of file
diff --git a/scripts/live-price-canary/live-price-canary.mjs b/scripts/live-price-canary/live-price-canary.mjs
new file mode 100644
index 0000000..dd314b7
--- /dev/null
+++ b/scripts/live-price-canary/live-price-canary.mjs
@@ -0,0 +1,39 @@
+// live-price-canary (c45) — hardened, promotable version of the c38 pilot.
+// READ-ONLY storefront crawl: the Mac2 mirror price col is unreliable (c37), so
+// measure TRUE customer-visible price live. Adds retry/backoff (the c38 pilot had
+// ~20% UNKNOWN from throttling) + writes data/latest.json (c34 heartbeat shape).
+// Classes per product: HAS_REAL (variant > $4.25) / SAMPLE_ONLY (only $4.25) /
+// NO_PRICE (blank|all 0). FAIL if NO_PRICE rate spikes (a real blank-price
+// regression the mirror can't catch). $0.
+import { execFileSync } from 'node:child_process';
+import fs from 'node:fs';
+const N=parseInt(process.argv[2]||'250',10);
+const NOPRICE_WARN=parseFloat(process.argv[3]||'3');   // % NO_PRICE → WARN
+const NOPRICE_FAIL=parseFloat(process.argv[4]||'8');   // % NO_PRICE → FAIL
+const PSQL='/opt/homebrew/opt/postgresql@14/bin/psql', DB='postgresql:///dw_unified?host=/tmp';
+const DIR=`${process.env.HOME}/Projects/designerwallcoverings/scripts/live-price-canary/data`;
+const Q=`${process.env.HOME}/.claude/yolo-queue`;
+const sleep=ms=>new Promise(r=>setTimeout(r,ms));
+const rows=execFileSync(PSQL,[DB,'-At','-F','\t','-c',
+  `select handle, vendor from shopify_products where status='ACTIVE' and handle is not null and handle<>'' order by random() limit ${N}`],{encoding:'utf8'}).trim().split('\n').filter(Boolean).map(l=>l.split('\t'));
+async function getj(h){ for(let a=0;a<5;a++){ try{ const r=await fetch(`https://www.designerwallcoverings.com/products/${encodeURIComponent(h)}.json`,{signal:AbortSignal.timeout(12000)}); if(r.status===200) return await r.json(); if(r.status===404) return {__404:true}; if(r.status===429){await sleep(1500*(a+1));continue;} }catch(e){ await sleep(1200*(a+1)); } } return null; }
+const b={HAS_REAL:0,SAMPLE_ONLY:0,NO_PRICE:0,PDP_404:0,UNKNOWN:0}; const noprice=[]; let decided=0;
+for(const [h,v] of rows){
+  const j=await getj(h);
+  if(j===null){b.UNKNOWN++; await sleep(140); continue;}
+  if(j.__404){b.PDP_404++; await sleep(140); continue;}
+  const prices=(j.product?.variants||[]).map(x=>parseFloat(x.price)).filter(n=>!isNaN(n));
+  let cls; if(!prices.length||prices.every(p=>p===0)){cls='NO_PRICE'; if(noprice.length<10)noprice.push(`${h} [${v}]`);}
+  else if(prices.every(p=>p<=4.25)) cls='SAMPLE_ONLY'; else cls='HAS_REAL';
+  b[cls]++; decided++; await sleep(140);
+}
+const pct=x=>decided?Math.round(1000*x/decided)/10:0;
+const noPricePct=pct(b.NO_PRICE);
+const verdict = noPricePct>=NOPRICE_FAIL?'FAIL':noPricePct>=NOPRICE_WARN?'WARN':'PASS';
+const out={generated_at:new Date().toISOString(), status:verdict, headline:`NO_PRICE ${noPricePct}% · SAMPLE_ONLY ${pct(b.SAMPLE_ONLY)}% · HAS_REAL ${pct(b.HAS_REAL)}% (n=${decided})`,
+  sampled:rows.length, decided, buckets:b, pct:{HAS_REAL:pct(b.HAS_REAL),SAMPLE_ONLY:pct(b.SAMPLE_ONLY),NO_PRICE:noPricePct}, noprice_examples:noprice, thresholds:{warn:NOPRICE_WARN,fail:NOPRICE_FAIL}};
+fs.writeFileSync(`${DIR}/latest.json`, JSON.stringify(out,null,2));
+fs.writeFileSync(`${Q}/live-price-canary-2026-06-16.json`, JSON.stringify(out,null,2));
+console.log(`[live-price-canary] ${verdict} · sampled=${rows.length} decided=${decided} UNKNOWN=${b.UNKNOWN} | ${out.headline}`);
+console.log(`  latest.json: ${DIR}/latest.json`);
+process.exit(verdict==='FAIL'?2:0);

← ac592b1 broken-image scan (c44): PASS — 0% broken on 117-sample (ima  ·  back to Dw Yolo Loop  ·  stage live-price-canary as install-ready launchd package (c4 463cd18 →