[object Object]

← back to Designer Wallcoverings

Carl Robinson increments: add global.Sold-Per/Minimum to full canonical set + committed value-asserting verifier (67/67 pass)

a109ccd51f4c5e08611693724df8ea784eb8c98f · 2026-07-06 14:25:53 -0700 · Steve

Files touched

Diff

commit a109ccd51f4c5e08611693724df8ea784eb8c98f
Author: Steve <steve@designerwallcoverings.com>
Date:   Mon Jul 6 14:25:53 2026 -0700

    Carl Robinson increments: add global.Sold-Per/Minimum to full canonical set + committed value-asserting verifier (67/67 pass)
---
 .../set-increment-carl-robinson.cjs                |  3 ++
 .../verify-increment-carl-robinson.cjs             | 62 ++++++++++++++++++++++
 2 files changed, 65 insertions(+)

diff --git a/scripts/wallquest-refresh/set-increment-carl-robinson.cjs b/scripts/wallquest-refresh/set-increment-carl-robinson.cjs
index 5fd81cf8..3aa2be59 100644
--- a/scripts/wallquest-refresh/set-increment-carl-robinson.cjs
+++ b/scripts/wallquest-refresh/set-increment-carl-robinson.cjs
@@ -14,6 +14,9 @@ const MF = [
   { namespace: 'global', key: 'v_prods_quantity_order_units', value: INC, type: 'single_line_text_field' },
   { namespace: 'dwc', key: 'order_unit', value: INC, type: 'single_line_text_field' },
   { namespace: 'global', key: 'unit_of_measure', value: 'Priced Per Yard', type: 'single_line_text_field' },
+  // full canonical set per wallquest-textile-yard-pricing memory + DW CLAUDE.md global-namespace taxonomy
+  { namespace: 'global', key: 'Sold-Per', value: 'Yard', type: 'single_line_text_field' },
+  { namespace: 'global', key: 'Minimum', value: INC, type: 'single_line_text_field' },
 ];
 function shopify(method, path, body) {
   return new Promise((res, rej) => { const data = body ? JSON.stringify(body) : null;
diff --git a/scripts/wallquest-refresh/verify-increment-carl-robinson.cjs b/scripts/wallquest-refresh/verify-increment-carl-robinson.cjs
new file mode 100644
index 00000000..ed2a8ff3
--- /dev/null
+++ b/scripts/wallquest-refresh/verify-increment-carl-robinson.cjs
@@ -0,0 +1,62 @@
+// Re-runnable, committed verifier for the Carl Robinson 8-yard-increment enforcement.
+// Does a FRESH GET of each live product's metafields + tags + variants and ASSERTS
+// VALUES (not just key existence) — the exact thing set-increment's swallow-all catch
+// can't prove. Exits NON-ZERO if any product fails, so it's usable as a gate/canary.
+// Env: SHOPIFY_ADMIN_TOKEN. Optional: LIMIT=N to sample.
+const https = require('https');
+const { execSync } = require('child_process');
+const TOK = process.env.SHOPIFY_ADMIN_TOKEN;
+const DOMAIN = 'designer-laboratory-sandbox.myshopify.com';
+const INC = process.env.INC || '8';
+const LIMIT = parseInt(process.env.LIMIT || '999', 10);
+if (!TOK) { console.error('no SHOPIFY_ADMIN_TOKEN'); process.exit(2); }
+
+// exact expected values (canonical set per wallquest-textile-yard-pricing memory + DW CLAUDE.md)
+const EXPECT_MF = {
+  'global.v_prods_quantity_order_min': INC,
+  'global.v_prods_quantity_order_units': INC,
+  'dwc.order_unit': INC,
+  'global.unit_of_measure': 'Priced Per Yard',
+  'global.Sold-Per': 'Yard',
+  'global.Minimum': INC,
+  'global.packaged': 'Packaged in 8 yard bolts only',
+};
+function shopify(path) {
+  return new Promise((res, rej) => {
+    const req = https.request({ hostname: DOMAIN, path: `/admin/api/2024-10/${path}`, method: 'GET',
+      headers: { 'X-Shopify-Access-Token': TOK } },
+      r => { let d = ''; r.on('data', c => d += c); r.on('end', () => { try { res(JSON.parse(d)); } catch (e) { rej(e); } }); });
+    req.on('error', rej); req.end();
+  });
+}
+const sleep = ms => new Promise(r => setTimeout(r, ms));
+
+(async () => {
+  const rows = execSync(`PGPASSWORD=DW2024SecurePass psql -h 127.0.0.1 -U dw_admin -d dw_unified -tAc "SELECT dw_sku||'|'||shopify_product_id FROM carl_robinson_catalog WHERE on_shopify AND shopify_product_id IS NOT NULL ORDER BY dw_sku"`).toString().trim().split('\n').filter(Boolean).slice(0, LIMIT);
+  console.log(`Verifying ${rows.length} Carl Robinson products (asserting metafield VALUES + tag + per-yard + sample)\n`);
+  let pass = 0; const fails = [];
+  for (const row of rows) {
+    const [sku, pid] = row.split('|');
+    try {
+      const mfRes = await shopify(`products/${pid}/metafields.json`);
+      const have = {}; (mfRes.metafields || []).forEach(m => { have[`${m.namespace}.${m.key}`] = String(m.value); });
+      const missing = Object.entries(EXPECT_MF).filter(([k, v]) => have[k] !== String(v)).map(([k, v]) => `${k}!=${v} (got ${have[k] ?? 'MISSING'})`);
+      const prod = (await shopify(`products/${pid}.json?fields=tags,variants`)).product;
+      const tag = (prod.tags || '').split(',').map(s => s.trim()).includes('display_variant');
+      const std = prod.variants.find(v => !/-Sample$/i.test(v.sku));
+      const smp = prod.variants.find(v => /-Sample$/i.test(v.sku));
+      const yard = std && /yard/i.test(std.option1 || '');
+      const samp = smp && parseFloat(smp.price) === 4.25;
+      const issues = [...missing];
+      if (!tag) issues.push('display_variant tag MISSING');
+      if (!yard) issues.push(`variant option not per-yard (${std && std.option1})`);
+      if (!samp) issues.push(`sample not $4.25 (${smp && smp.price})`);
+      if (issues.length) fails.push(`${sku} (${pid}): ${issues.join('; ')}`);
+      else pass++;
+    } catch (e) { fails.push(`${sku} (${pid}): ERROR ${e.message}`); }
+    await sleep(90);
+  }
+  console.log(`PASS ${pass}/${rows.length}`);
+  if (fails.length) { console.error(`\nFAILURES (${fails.length}):`); fails.forEach(f => console.error('  ❌ ' + f)); process.exit(1); }
+  console.log('✅ ALL VERIFIED — every product has the full canonical increment set, tag, per-yard price, and $4.25 sample.');
+})().catch(e => { console.error('FATAL', e.message); process.exit(2); });

← 21c4a09b DWTT double-roll PHASE 2 live: 3105 metafields, 0 errors (ca  ·  back to Designer Wallcoverings  ·  Kravet-under-PR re-vendor tool (dry-run default; --apply/--a 080ee652 →