[object Object]

← back to Designerwallcoverings

TK-10895: bring main's copies to the final verified state (27999a6 + b0416ab)

a6afe99c25febd9af69e5fb52506d73429fa14ab · 2026-09-10 14:28:34 -0700 · Steve

The last two cherry-picks conflicted because they replay intermediate states of
files main had already diverged on. Replaying that history is not the goal - the
goal is that main holds the SAME scripts that produced today's verified writes.
So these are the exact file contents from tk11357-zero-price-source-fix; a diff
of all three files against that branch is empty.

Carries:
  27999a6  G1/G2/G3 release a row only on a recorded, named adjudication
           (LENGTH-NOT-STATED / LOADED-TOKEN-SUPPORTED / WP-ROW-COST-SUPPORTED),
           and G1 forces the length-free label on a length-adjudicated row.
  b0416ab  --table for the sheet-wide fabric-row sweep, plus the CDN grace
           period on the reprice script's post-write storefront check.

Why this mattered: all six TK-10895 commits had gone onto another ticket's
branch. main's executor still verified against the Admin API - the exact bug
that produced three false readings today - and tk10895-reprice-fabricrow5.mjs,
the tool that corrected 59 products' prices, did not exist on main at all.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Files touched

Diff

commit a6afe99c25febd9af69e5fb52506d73429fa14ab
Author: Steve <steve@designerwallcoverings.com>
Date:   Thu Sep 10 14:28:34 2026 -0700

    TK-10895: bring main's copies to the final verified state (27999a6 + b0416ab)
    
    The last two cherry-picks conflicted because they replay intermediate states of
    files main had already diverged on. Replaying that history is not the goal - the
    goal is that main holds the SAME scripts that produced today's verified writes.
    So these are the exact file contents from tk11357-zero-price-source-fix; a diff
    of all three files against that branch is empty.
    
    Carries:
      27999a6  G1/G2/G3 release a row only on a recorded, named adjudication
               (LENGTH-NOT-STATED / LOADED-TOKEN-SUPPORTED / WP-ROW-COST-SUPPORTED),
               and G1 forces the length-free label on a length-adjudicated row.
      b0416ab  --table for the sheet-wide fabric-row sweep, plus the CDN grace
               period on the reprice script's post-write storefront check.
    
    Why this mattered: all six TK-10895 commits had gone onto another ticket's
    branch. main's executor still verified against the Admin API - the exact bug
    that produced three false readings today - and tk10895-reprice-fabricrow5.mjs,
    the tool that corrected 59 products' prices, did not exist on main at all.
    
    Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
---
 scripts/tk10895-reprice-fabricrow5.mjs  | 26 ++++++++++++++++++++++++--
 scripts/tk10895-trancheB-golive-269.mjs | 30 +++++++++++++++++++++++++-----
 2 files changed, 49 insertions(+), 7 deletions(-)

diff --git a/scripts/tk10895-reprice-fabricrow5.mjs b/scripts/tk10895-reprice-fabricrow5.mjs
index 7c4eef0..3d12284 100644
--- a/scripts/tk10895-reprice-fabricrow5.mjs
+++ b/scripts/tk10895-reprice-fabricrow5.mjs
@@ -30,7 +30,23 @@ const T={
  '709221':{p:'Bijou Stripe',   wp:148, row:'5060-05WP', fab:183},
  '709321':{p:'Birds II',       wp:142, row:'5050-04WP', fab:182},
  '709421':{p:'Birds II',       wp:142, row:'5050-04WP', fab:182},
+ // El Cid, added 2026-09-10: our 7 live products carry mfr 726421-727021, which sit on the mill
+ // sheet's $172.00 row ALONGSIDE 303700F-10 (the 48" linen/cotton FABRIC). The wallpaper series
+ // 303700W-01..-10 is a clean single $143.00. Confirmed by width: ours are 24.5" paper, matching
+ // the W spec, not the 48" F spec.
+ '726421':{p:'El Cid', wp:143, row:'303700W-01', fab:172},
+ '726521':{p:'El Cid', wp:143, row:'303700W-02', fab:172},
+ '726621':{p:'El Cid', wp:143, row:'303700W-03', fab:172},
+ '726721':{p:'El Cid', wp:143, row:'303700W-04', fab:172},
+ '726821':{p:'El Cid', wp:143, row:'303700W-05', fab:172},
+ '726921':{p:'El Cid', wp:143, row:'303700W-06', fab:172},
+ '727021':{p:'El Cid', wp:143, row:'303700W-07', fab:172},
 };
+// Optional table file: the hardcoded T above is the original 12; a JSON file lets a wider,
+// evidence-driven sweep be repriced without editing code. Same shape: {mfr:{p,wp,row,fab}}.
+const TF=(()=>{const i=process.argv.indexOf('--table');return i>-1?process.argv[i+1]:null;})();
+if (TF) { const extra=JSON.parse(fs.readFileSync(TF,'utf8')); for (const [k,v] of Object.entries(extra)) T[k]=v;
+          console.log(`loaded ${Object.keys(extra).length} rows from ${TF}`); }
 const retail=c=>Math.round((c/0.65/0.85)*100)/100;
 
 async function api(path,opts={},tries=6){
@@ -72,8 +88,14 @@ for(const [mfr,t] of Object.entries(T)){
   else res=await api(`/variants/${v.id}.json`,{method:'PUT',body:JSON.stringify({variant:{id:v.id,price:want.toFixed(2)}})});
   if(res.status>=400||res.status===0){console.log(`${mfr} HARD FAIL ${res.status}`);hard++;continue;}
 
-  await sleep(800);
-  const sf=await storefront(p.handle);          // VERIFY on the oracle, not the Admin API
+  // The storefront is CDN-fronted: an 800ms read served stale documents and produced 7 FALSE
+  // hard-failures on writes that had actually landed. Wait, then re-read once before failing.
+  await sleep(2500);
+  let sf=await storefront(p.handle);            // VERIFY on the oracle, not the Admin API
+  const settled=x=>{const l=x?x.variants.filter(v=>parseFloat(v.price)>50):null;
+    return MODE==='revert' ? (l&&l.length===0)
+                           : (l&&l.length===1&&Math.abs(parseFloat(l[0].price)-want)<0.01);};
+  if(!settled(sf)){ await sleep(4000); sf=await storefront(p.handle); }
   const live=sf?sf.variants.filter(x=>parseFloat(x.price)>50):null;
   const okNow = MODE==='revert' ? (live && live.length===0)
                                 : (live && live.length===1 && Math.abs(parseFloat(live[0].price)-want)<0.01);
diff --git a/scripts/tk10895-trancheB-golive-269.mjs b/scripts/tk10895-trancheB-golive-269.mjs
index 609b717..76eb39c 100644
--- a/scripts/tk10895-trancheB-golive-269.mjs
+++ b/scripts/tk10895-trancheB-golive-269.mjs
@@ -57,13 +57,33 @@ for (const w of work) {
   const e = byMfr[w.mfr];
   if (!e) { fail.push([w.mfr, 'not in evidence CSV']); continue; }
   if (e.decision !== 'GO') fail.push([w.mfr, `evidence says decision=${e.decision}`]);
-  if (e.mill_unit !== 'PER_ROLL') fail.push([w.mfr, `G1 unit=${e.mill_unit}`]);
-  if (e.mill_yards_per_roll !== '5') fail.push([w.mfr, `G1 yards=${e.mill_yards_per_roll}`]);
-  if (e.cost_cell_clean !== 'YES') fail.push([w.mfr, `G2 ambiguous cost cell ${e.cost_cell}`]);
-  if (e.cost_row_type_clean !== 'YES') fail.push([w.mfr, 'G3 priced off the sheet FABRIC row']);
+  // G1: the mill's published spec is the default proof of unit+length. A row may substitute a
+  // recorded LENGTH-NOT-STATED adjudication — which asserts unit=per-roll on independent retail
+  // evidence and explicitly declines to claim a length — and such a row ships a length-free label.
+  const lenAdj = (e.roll_length_adjudicated || '').startsWith('LENGTH-NOT-STATED');
+  if (!lenAdj) {
+    if (e.mill_unit !== 'PER_ROLL') fail.push([w.mfr, `G1 unit=${e.mill_unit}`]);
+    if (e.mill_yards_per_roll !== '5') fail.push([w.mfr, `G1 yards=${e.mill_yards_per_roll}`]);
+  } else if (!/^Sold Per Single Roll - [\d.]+In Wide$/.test(w.label)) {
+    fail.push([w.mfr, 'G1 length-adjudicated row must carry the length-FREE label']);
+  }
+  // G2: a dirty cost cell may be released ONLY by a recorded adjudication that names its basis.
+  // Inference is allowed to unblock, but it must be written down and auditable, never implicit.
+  if (e.cost_cell_clean !== 'YES' && !(e.cost_cell_adjudicated || '').startsWith('LOADED-TOKEN-SUPPORTED'))
+    fail.push([w.mfr, `G2 ambiguous cost cell ${e.cost_cell} with no recorded adjudication`]);
+  // G3: same rule as G2 — a FABRIC-row cost may be released only by a recorded adjudication.
+  if (e.cost_row_type_clean !== 'YES' && !(e.cost_row_adjudicated || '').startsWith('WP-ROW-COST-SUPPORTED'))
+    fail.push([w.mfr, 'G3 priced off the sheet FABRIC row with no recorded adjudication']);
   if (!/^\d+$/.test(w.pid)) fail.push([w.mfr, `pid not bare numeric: ${w.pid}`]);
   if (!(parseFloat(w.price) > 50)) fail.push([w.mfr, `price sanity: ${w.price}`]);
-  if (!/^Sold Per Single Roll - 5 Yards - [\d.]+In Wide$/.test(w.label)) fail.push([w.mfr, `label: ${w.label}`]);
+  // Label: the yardage form is the default. The length-free form is permitted ONLY when the row
+  // carries a recorded LENGTH-NOT-STATED adjudication — i.e. we deliberately decline to state a
+  // length we cannot source, rather than inventing one. (DW house convention already has this
+  // shape: Brunschwig ships "Sold Per Single Roll - 36In Wide".)
+  const withYards = /^Sold Per Single Roll - 5 Yards - [\d.]+In Wide$/.test(w.label);
+  const noYards   = /^Sold Per Single Roll - [\d.]+In Wide$/.test(w.label);
+  if (!withYards && !(noYards && (e.roll_length_adjudicated || '').startsWith('LENGTH-NOT-STATED')))
+    fail.push([w.mfr, `label: ${w.label}`]);
 }
 console.log(`PRE-FLIGHT: ${work.length} rows · evidence rows ${ev.length} · failures ${fail.length}`);
 if (fail.length) {

← e14d23e TK-10895: storefront verify needs a CDN grace period  ·  back to Designerwallcoverings  ·  TK-11404: correct FINDINGS — DTD+live audit found a real JSO e52390b →