← back to Newmor Onboard
scripts/final-verify.mjs
36 lines
import assert from 'node:assert/strict';
import {gql,fields,complete,read,save} from './shopify.mjs';
const phase=process.argv.includes('--canary')?'canary':'final';
const before=read('data/live-2026-09-09/shopify-before.json').products;
const latent=read('data/live-2026-09-09/configured-publications-baseline.json').products;
const plan=read('data/newmor-showroom-plan-2026-09-08.json');
const range=read('data/live-2026-09-09/vendor-range.json');
const imageFills=read('data/live-2026-09-09/image-fill-journal.json');
const eligible=new Set(phase==='canary'?['gid://shopify/Product/4351291785267','gid://shopify/Product/4351291818035']:range.candidates.filter(c=>c.found).map(c=>c.id));
const markers=new Set(plan.candidates.filter(c=>c.proposed.add_tags.length||c.proposed.set_showroom_line).map(c=>c.id));
const visible=p=>p.resourcePublications.nodes.filter(n=>n.isPublished).map(n=>n.publication.id).sort();
const configured=p=>p.configuredPublications.nodes.map(n=>n.publication.id).sort();
const sortMeta=p=>p.mf.nodes.filter(m=>m.namespace!=='custom'||m.key!=='showroom_line').sort((a,b)=>a.id.localeCompare(b.id));
const products=[];let after=null;
do{const d=await gql(`query($after:String){products(first:15,after:$after,query:"vendor:'Newmor Wallcoverings'"){nodes{${fields}}pageInfo{hasNextPage endCursor}}}`,{after});products.push(...d.products.nodes.map(complete));after=d.products.pageInfo.hasNextPage?d.products.pageInfo.endCursor:null;console.log(`Verify ${products.length}/542`);}while(after);
save(`data/live-2026-09-09/shopify-${phase}-after.json`,{fetched_at:new Date().toISOString(),products});
assert.equal(products.length,542);assert.equal(new Set(products.map(p=>p.id)).size,542);
let markerRepairs=0;
for(const p of products){
const b=before.find(b=>b.id===p.id),l=latent.find(b=>b.id===p.id);assert(b&&l);assert.equal(p.vendor,'Newmor Wallcoverings');
for(const key of ['vendor','handle','title','descriptionHtml','templateSuffix','createdAt'])assert.equal(p[key],b[key],`${key} drift ${p.id}`);
assert.deepEqual(p.variants,b.variants,`Variant/price drift ${p.id}`);assert.deepEqual(sortMeta(p),sortMeta(b),`Unapproved metafield change ${p.id}`);
const fill=imageFills.find(x=>x.id===p.id);assert.deepEqual(p.images,fill?fill.after.images:b.images,`Image drift ${p.id}`);
if(eligible.has(p.id)){
assert.equal(p.status,'ACTIVE');assert.deepEqual(visible(p),['gid://shopify/Publication/22208643184']);assert.deepEqual(configured(p),['gid://shopify/Publication/22208643184']);
assert.equal(p.showroom?.value,'true');assert(p.images.nodes.length>0);assert.deepEqual([...p.tags].sort(),[...new Set([...b.tags,'quotes','Showroom Line'])].sort());
if(markers.has(p.id))markerRepairs++;
}else{
assert.equal(p.status,b.status);assert.deepEqual(visible(p),[]);assert.deepEqual(configured(p),configured(l));assert.deepEqual(p.tags,b.tags);assert.deepEqual(p.showroom,b.showroom);
}
}
const counts=products.reduce((a,p)=>(a[p.status]=(a[p.status]||0)+1,a),{});
assert.equal(counts.ACTIVE,eligible.size);assert.equal(counts.DRAFT,305-eligible.size);assert.equal(counts.ARCHIVED,237);
save(`verification/${phase}-state-proof.json`,{timestamp:new Date().toISOString(),verdict:'PASS',counts,all_products:542,eligible:eligible.size,marker_repairs:markerRepairs,exact_image_fills:imageFills.length,assertions:['All variant IDs/titles/SKUs/prices/availability and product identity/content preserved','All non-showroom metafields unchanged','Exactly eligible products ACTIVE with Online Store-only visible and configured publication','All draft holds/archives status/tags/metafields/latent memberships unchanged','Only six exact-source Arbour images added','Final active records are Online Store-only; held latent memberships match baseline'],incident:'Initial KOT-23 activation temporarily exposed13previously latent channels; immediately restoredDRAFT, then corrected zero-channel activation barrier. Third-party ingestion during transient exposure not audited.',range_holds:range.candidates.filter(c=>!c.found)});
console.log(JSON.stringify({phase,verdict:'PASS',counts,markerRepairs}));