[object Object]

← back to York Reprice 2026 08

cadence: dual image-drawer onboard lookup + naturals-aware drift (no false MAP re-break) + collision-aware 2-factor onboard

9ee51a3a58bc4d58a4e029aab490c5355de6605a · 2026-07-12 11:43:47 -0700 · Steve

Files touched

Diff

commit 9ee51a3a58bc4d58a4e029aab490c5355de6605a
Author: Steve <steve@designerwallcoverings.com>
Date:   Sun Jul 12 11:43:47 2026 -0700

    cadence: dual image-drawer onboard lookup + naturals-aware drift (no false MAP re-break) + collision-aware 2-factor onboard
---
 cadence/york-cadence.mjs | 45 ++++++++++++++++++++++++++++++++++++---------
 1 file changed, 36 insertions(+), 9 deletions(-)

diff --git a/cadence/york-cadence.mjs b/cadence/york-cadence.mjs
index cd1704e..26bdc3d 100644
--- a/cadence/york-cadence.mjs
+++ b/cadence/york-cadence.mjs
@@ -21,37 +21,64 @@ const gql=async(query,v)=>{for(let a=0;a<8;a++){let j;try{const r=await fetch(UR
 const norm=s=>String(s||'').toUpperCase().trim();
 const words=s=>new Set(String(s||'').toLowerCase().replace(/[^a-z0-9 ]/g,' ').split(/\s+/).filter(w=>w.length>2));
 const share=(a,b)=>{const A=words(a),B=words(b);for(const w of A)if(B.has(w))return true;return false;};
+const cents=x=>Math.round(Number(x)*100);
+const priceOff=(a,b)=>Math.abs(cents(a)-cents(b))>1; // "off" = more than a 1-cent rounding gap
 
 // 1. master: mfr_sku -> {price,status,pattern,color}
 const M=new Map();
 for(const line of q(`select concat_ws(chr(31), upper(trim(export_sku)), coalesce(us_map,round(us_msrp*0.75,2)), sku_status, pattern_name, colorway) from york_master_aug2026 where export_sku is not null`).split('\n').filter(Boolean)){
   const [s,p,st,pat,col]=line.split(String.fromCharCode(31)); if(!M.has(s)) M.set(s,{price:parseFloat(p),status:st,pattern:pat,color:col});
 }
-// onboard-ready set from DB (master New, has york_catalog image, keyword-clear) — count only
-let onboardReady=0; try{ onboardReady=parseInt(q(`
- select count(*) from (select distinct on (upper(trim(export_sku))) upper(trim(export_sku)) s, pattern_name,product_name,book_name from york_master_aug2026 where sku_status='New' and export_sku is not null) n
- join york_catalog c on upper(trim(c.mfr_sku))=n.s
- where c.image_url is not null and c.image_url<>'' and lower(concat_ws(' ',n.pattern_name,n.product_name,n.book_name)) !~ 'banana|grape|bird|butterfly|palm|frond|leaf|foliage|botanical|floral|flower|tropical|jungle|vine|fern|bloom|garden|blossom'`)); }catch(e){}
+// naturals sell at a SINGLE-ROLL price (brewster_york_master.roll_price_single), NOT MAP — a second
+// valid price target. Without this the MAP-only drift check false-flags every correctly-priced
+// natural (grasscloth/sisal/paperweave/cork) as "drift" and would propose re-breaking it daily.
+const RPS=new Map();
+try{ for(const line of q(`select concat_ws(chr(31), upper(trim(mfr_sku)), roll_price_single) from brewster_york_master where roll_price_single is not null and roll_price_single>0`).split('\n').filter(Boolean)){
+  const [s,p]=line.split(String.fromCharCode(31)); if(!RPS.has(s)) RPS.set(s,parseFloat(p)); } }catch(e){}
+// onboard-ready CANDIDATES from DB (master 'New', settlement-keyword-clear, has a local image in
+// york_catalog OR brewster_catalog). york_catalog holds art for the archived York-branded line;
+// brewster_catalog holds it for the live Brewster/A-Street->Malibu line — every 'New' SKU is the
+// latter, so BOTH image drawers must be checked (checking only york_catalog is why this read 0).
+// 'Already live' is subtracted AFTER the live pagination below (liveMfr) so we never re-propose live SKUs.
+let onboardCand=[]; try{ onboardCand=q(`
+ select concat_ws(chr(31), n.s, n.pattern_name) from (select distinct on (upper(trim(export_sku))) upper(trim(export_sku)) s, pattern_name,product_name,book_name from york_master_aug2026 where sku_status='New' and export_sku is not null) n
+ left join york_catalog c on upper(trim(c.mfr_sku))=n.s
+ left join brewster_catalog b on upper(trim(b.mfr_sku))=n.s
+ where coalesce(nullif(c.image_url,''), nullif(b.image_url,'')) is not null
+   and lower(concat_ws(' ',n.pattern_name,n.product_name,n.book_name)) !~ 'banana|grape|bird|butterfly|palm|frond|leaf|foliage|botanical|floral|flower|tropical|jungle|vine|fern|bloom|garden|blossom'`)
+   .split('\n').map(x=>x.trim()).filter(Boolean)
+   .map(l=>{const [s,pat]=l.split(String.fromCharCode(31)); return {s,pat:pat||''};}); }catch(e){}
 
 // 2. live Jeffrey Stevens
-let cur=null, reprice=[], disco=[], liveMfr=new Set();
+let cur=null, reprice=[], disco=[], liveMfr=new Set(), liveTitles=new Map();
 for(let pg=0;pg<90;pg++){
   const d=(await gql(`query($c:String){products(first:60,after:$c,query:"vendor:'Jeffrey Stevens'"){pageInfo{hasNextPage endCursor} nodes{status title dwc:metafield(namespace:"dwc",key:"manufacturer_sku"){value} cust:metafield(namespace:"custom",key:"manufacturer_sku"){value} variants(first:20){nodes{id sku price title}}}}}`,{c:cur}))?.products; if(!d)break;
   for(const p of d.nodes){const mfr=norm(p.dwc?.value||p.cust?.value); if(!mfr)continue; liveMfr.add(mfr);
+    { const a=liveTitles.get(mfr)||[]; a.push(p.title||''); liveTitles.set(mfr,a); } // for collision-aware onboard 2-factor
     const m=M.get(mfr); if(!m)continue;
     const rolls=p.variants.nodes.filter(v=>!/sample|memo|-sample$/i.test((v.sku||'')+(v.title||''))); if(!rolls.length)continue;
     const roll=rolls.reduce((a,b)=>parseFloat(b.price)>parseFloat(a.price)?b:a); const price=parseFloat(roll.price);
     if(p.status==='ACTIVE'){
       if(['Dead','Phasing'].includes(m.status)) disco.push({mfr,title:p.title,status:m.status});
-      else if(['Active','New'].includes(m.status) && m.price>0 && Math.abs(price-m.price)>=0.01 && share(p.title,m.pattern))
-        reprice.push({mfr,title:p.title,cur:price,map:m.price});
+      else if(['Active','New'].includes(m.status) && m.price>0 && share(p.title,m.pattern)){
+        const rps=RPS.get(mfr);                                  // single-roll target (naturals)
+        const offMap=priceOff(price,m.price);                    // off from MAP
+        const offRps=rps?priceOff(price,rps):true;               // off from single-roll (or none)
+        if(offMap && offRps) reprice.push({mfr,title:p.title,cur:price,map:m.price,rps:rps||null});
+      }
     }
   }
   if(!d.pageInfo.hasNextPage)break; cur=d.pageInfo.endCursor;
 }
+// collision-aware onboard-ready: a candidate is truly un-onboarded only if NO live product carrying its
+// code shares a title word with its master pattern. Bare code-match masks cross-brand collisions
+// (a New York code coinciding with an unrelated live Anna French/Thibaut SKU) as false 'already live'.
+const onboardObjs=onboardCand.filter(c=>{ const titles=liveTitles.get(c.s)||[]; return !titles.some(t=>share(t,c.pat)); });
+const onboardMfrs=onboardObjs.map(c=>c.s);
+const onboardReady=onboardMfrs.length;
 const out={ts:new Date().toISOString(),live_js:liveMfr.size,
   reprice_drift:reprice.length, onboard_ready:onboardReady, disco:disco.length,
-  reprice_sample:reprice.slice(0,10), disco_sample:disco.slice(0,10)};
+  reprice_sample:reprice.slice(0,10), onboard_sample:onboardMfrs.slice(0,12), disco_sample:disco.slice(0,10)};
 fs.mkdirSync(ROOT+'/cadence/data',{recursive:true});
 fs.writeFileSync(ROOT+'/cadence/data/latest.json',JSON.stringify(out,null,2));
 const actionable=reprice.length+onboardReady+disco.length;

← 40d2167 DTD-A grasscloth model: naturals-fix (revert 16 + relabel/re  ·  back to York Reprice 2026 08  ·  cadence: fix swallowed-SQL-error false-zero — onboard-ready 27f6dd0 →