[object Object]

← back to Designer Wallcoverings

Add Tres Tintas completeness audit (desc+spec+room, roll-vs-mural aware)

2228022a5e64fb211de18a95e5293e2bf2d10adc · 2026-06-23 13:03:38 -0700 · Steve

Audits all ~592 Tres Tintas products for the three backfills: designer
description (no leftover embedded spec table), correct spec shape (rolls need
width+repeat+weight; murals need material+weight — murals legitimately lack
width/repeat), and a room-setting image. Prints summary + the IDs still missing
each so stragglers can be re-run.

Files touched

Diff

commit 2228022a5e64fb211de18a95e5293e2bf2d10adc
Author: Steve <steve@designerwallcoverings.com>
Date:   Tue Jun 23 13:03:38 2026 -0700

    Add Tres Tintas completeness audit (desc+spec+room, roll-vs-mural aware)
    
    Audits all ~592 Tres Tintas products for the three backfills: designer
    description (no leftover embedded spec table), correct spec shape (rolls need
    width+repeat+weight; murals need material+weight — murals legitimately lack
    width/repeat), and a room-setting image. Prints summary + the IDs still missing
    each so stragglers can be re-run.
---
 shopify/scripts/tres-tintas-audit.js | 68 ++++++++++++++++++++++++++++++++++++
 1 file changed, 68 insertions(+)

diff --git a/shopify/scripts/tres-tintas-audit.js b/shopify/scripts/tres-tintas-audit.js
new file mode 100644
index 00000000..e2d7c7b0
--- /dev/null
+++ b/shopify/scripts/tres-tintas-audit.js
@@ -0,0 +1,68 @@
+#!/usr/bin/env node
+/**
+ * tres-tintas-audit.js — completeness audit across ALL Tres Tintas products.
+ *
+ * For each product reports whether it has:
+ *   - DESC: a designer description (no leftover embedded <table>/Specifications)
+ *   - SPEC: correct shape — ROLL needs width+repeat+weight; MURAL needs
+ *           material+weight (murals legitimately have no roll width/repeat,
+ *           detected via the /mural/ vendor URL → here via missing width but
+ *           present weight, OR a `mural`/`Mural` tag)
+ *   - ROOM: a 2nd image whose alt/url marks it a room/interior/setting
+ *
+ * Prints a summary + the IDs still missing each, so stragglers can be re-run.
+ */
+const fs = require('fs');
+const path = require('path');
+const STORE = 'designer-laboratory-sandbox.myshopify.com';
+const API = '2024-01';
+function envval(k){const e=fs.readFileSync(path.join(process.env.HOME,'Projects/secrets-manager/.env'),'utf8');const m=e.match(new RegExp(`^${k}=["']?([^"'\\n]+)`,'m'));return m?m[1].trim():null;}
+const H = { 'X-Shopify-Access-Token': envval('SHOPIFY_DRAFT_TOKEN'), 'Content-Type': 'application/json' };
+const sleep = (ms)=>new Promise(r=>setTimeout(r,ms));
+async function fetchRetry(u,o,t=3){let e;for(let i=0;i<t;i++){try{return await fetch(u,{...o,signal:AbortSignal.timeout(45000)});}catch(x){e=x;await sleep(800*(i+1));}}throw e;}
+async function gql(q,v){const r=await fetchRetry(`https://${STORE}/admin/api/${API}/graphql.json`,{method:'POST',headers:H,body:JSON.stringify({query:q,variables:v})});const j=await r.json();if(j.errors)throw new Error(JSON.stringify(j.errors));return j.data;}
+
+(async()=>{
+  const q=`query($c:String){products(first:100,query:"vendor:'Tres Tintas'",after:$c){pageInfo{hasNextPage endCursor}
+    edges{node{id title tags descriptionHtml
+      images(first:10){edges{node{url altText}}}
+      metafields(first:50){edges{node{namespace key value}}}}}}}`;
+  let cursor=null,total=0;
+  const miss={desc:[],spec:[],room:[]}, complete=[];
+  let rolls=0,murals=0;
+  while(true){
+    const conn=(await gql(q,{c:cursor})).products;
+    for(const e of conn.edges){
+      const n=e.node; total++;
+      const id=n.id.split('/').pop();
+      const d=n.descriptionHtml||'';
+      const tags=(n.tags||[]).map(t=>t.toLowerCase());
+      const mfs={}; n.metafields.edges.forEach(x=>mfs[`${x.node.namespace}.${x.node.key}`]=x.node.value);
+      const imgs=n.images.edges.map(x=>({url:x.node.url,alt:x.node.altText||''}));
+
+      const hasDesc = d.length>40 && !/<h3>\s*Specifications/i.test(d);
+      const hasRoom = imgs.length>1 || imgs.some(im=>/interior|_int|room|ambiente|setting/i.test(im.url+im.alt));
+      const isMural = tags.includes('mural') || (!!mfs['custom.product_weight'] && !mfs['custom.width']);
+      // spec completeness: roll needs width+repeat+weight; mural needs material+weight
+      const hasSpec = isMural
+        ? (!!mfs['custom.material'] && !!mfs['custom.product_weight'])
+        : (!!mfs['custom.width'] && !!mfs['custom.pattern_repeat'] && !!mfs['custom.product_weight']);
+      if(isMural)murals++; else rolls++;
+
+      if(!hasDesc)miss.desc.push(id);
+      if(!hasSpec)miss.spec.push(`${id}${isMural?'(mural)':''}`);
+      if(!hasRoom)miss.room.push(id);
+      if(hasDesc&&hasSpec&&hasRoom)complete.push(id);
+    }
+    if(conn.pageInfo.hasNextPage)cursor=conn.pageInfo.endCursor; else break;
+  }
+  console.log(`\n=== TRES TINTAS COMPLETENESS AUDIT ===`);
+  console.log(`total products: ${total}  (rolls: ${rolls}, murals: ${murals})`);
+  console.log(`FULLY COMPLETE (desc+spec+room): ${complete.length}/${total}`);
+  console.log(`missing description: ${miss.desc.length}`);
+  console.log(`missing spec:        ${miss.spec.length}`);
+  console.log(`missing room image:  ${miss.room.length}`);
+  if(miss.desc.length)console.log(`  desc gaps: ${miss.desc.slice(0,30).join(' ')}${miss.desc.length>30?' …':''}`);
+  if(miss.spec.length)console.log(`  spec gaps: ${miss.spec.slice(0,30).join(' ')}${miss.spec.length>30?' …':''}`);
+  if(miss.room.length)console.log(`  room gaps: ${miss.room.slice(0,30).join(' ')}${miss.room.length>30?' …':''}`);
+})().catch(e=>{console.error(e);process.exit(1);});

← ec1ab72f auto-save: 2026-06-23T12:51:44 (8 files) — shopify/scripts/c  ·  back to Designer Wallcoverings  ·  collection hero pipeline: heuristic-shortlist + Gemini visio a2ad8809 →