← back to Designer Wallcoverings
Kravet roll-add: add unit-mismatch guard (skip mural/panel/high-price products from per-roll variants) + write-audit-before-mutation pattern (survives process death). Cody FIX-FIRST items.
74ddf8b9ffdc529998e31a511566d1089ce4326c · 2026-08-18 15:34:22 -0700 · Steve
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
M shopify/scripts/cadence/add-kravet-roll-variants.js
Diff
commit 74ddf8b9ffdc529998e31a511566d1089ce4326c
Author: Steve <steve@designerwallcoverings.com>
Date: Tue Aug 18 15:34:22 2026 -0700
Kravet roll-add: add unit-mismatch guard (skip mural/panel/high-price products from per-roll variants) + write-audit-before-mutation pattern (survives process death). Cody FIX-FIRST items.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
.../scripts/cadence/add-kravet-roll-variants.js | 30 +++++++++++++++++-----
1 file changed, 24 insertions(+), 6 deletions(-)
diff --git a/shopify/scripts/cadence/add-kravet-roll-variants.js b/shopify/scripts/cadence/add-kravet-roll-variants.js
index fe249772..94ecaae3 100644
--- a/shopify/scripts/cadence/add-kravet-roll-variants.js
+++ b/shopify/scripts/cadence/add-kravet-roll-variants.js
@@ -155,6 +155,15 @@ function rollLabel(tags) {
const label = rollLabel((p.tags || []).join(' '));
const rollSku = (c.variant_sku || '').replace(/-sample$/i, '');
const price = c.map.toFixed(2);
+ // UNIT-MISMATCH GUARD (2026-08-18, Cody FIX-FIRST): never create a "Sold Per Single Roll"
+ // variant on a mural/panel/meter product. Signal = mural/panel/scenic/tapestry/embroider in
+ // title/tags, OR a high MAP with no detected roll width (bare label). Skip + emit metric.
+ const ROLL_MAP_CEILING = 1500;
+ const muralish = /\b(mural|panel|scenic|tapestry|embroider)\b/i.test(`${c.title || ''} ${(p.tags || []).join(' ')}`);
+ if (muralish || (c.map > ROLL_MAP_CEILING && !/In Wide/i.test(label))) {
+ skip++; console.log(` ⚠ SKIP-REVIEW (unit-mismatch?) ${c.mfr_sku} @ $${price} label:"${label}" ${(c.title || '').slice(0, 40)}`);
+ continue;
+ }
const variantInput = [{
price,
inventoryPolicy: 'CONTINUE',
@@ -166,23 +175,32 @@ function rollLabel(tags) {
console.log(` + [${c.map_src}] ${c.mfr_sku} add "${label}" @ $${price} opt:${optName} sku:${rollSku} ${(c.title||'').slice(0,32)}`);
added++; continue;
}
+ // WRITE-AUDIT-BEFORE-MUTATION (2026-08-18, Cody FIX-FIRST): record intent (committed=false,
+ // no variant id) BEFORE creating, then UPDATE to committed after the API confirms. Survives a
+ // process death between create and log — the flaw that leaked 12 untracked variants.
+ const esc = s => String(s == null ? '' : s).replace(/'/g, "''");
+ let auditId = null;
+ try {
+ auditId = psql(`INSERT INTO kravet_roll_add_audit(shopify_id,mfr_sku,roll_sku,option_name,option_value,map_price,map_source,committed,note)
+ VALUES ('${c.shopify_id}','${esc(c.mfr_sku)}','${esc(rollSku)}','${esc(optName)}','${esc(label)}',${c.map},'${esc(c.map_src)}',false,'PENDING pre-mutation') RETURNING id;`);
+ } catch (e) { console.log(` ⚠ pre-audit INSERT failed ${c.mfr_sku}: ${String(e.message || e).slice(0, 100)}`); }
const res = await gqlRetry(MUT_CREATE, { pid: c.shopify_id, variants: variantInput });
const r = res.json && res.json.data && res.json.data.productVariantsBulkCreate;
const ue = r && r.userErrors;
const good = res.status === 200 && ue && ue.length === 0 && r.productVariants && r.productVariants.length;
const vid = good ? r.productVariants[0].id : null;
- // AUDIT-WRITE GUARD (2026-08-18): the variant is already created above; a failed
- // audit INSERT must NOT crash the run and leak an untracked variant. Wrap + emit vid.
+ const noteVal = good ? "'created'" : `'${esc(JSON.stringify(ue || res.raw || res.err)).slice(0, 150)}'`;
try {
- psql(`INSERT INTO kravet_roll_add_audit(shopify_id,mfr_sku,roll_sku,option_name,option_value,map_price,map_source,created_variant_id,committed,note)
- VALUES ('${c.shopify_id}','${(c.mfr_sku||'').replace(/'/g,"''")}','${rollSku.replace(/'/g,"''")}','${optName.replace(/'/g,"''")}','${label.replace(/'/g,"''")}',${c.map},'${c.map_src}',${vid?`'${vid}'`:'NULL'},${good},${good?'NULL':`'${JSON.stringify(ue||res.raw||res.err).slice(0,150).replace(/'/g,"''")}'`});`);
+ if (auditId) psql(`UPDATE kravet_roll_add_audit SET committed=${good}, created_variant_id=${vid ? `'${vid}'` : 'NULL'}, note=${noteVal} WHERE id=${auditId};`);
+ else psql(`INSERT INTO kravet_roll_add_audit(shopify_id,mfr_sku,roll_sku,option_name,option_value,map_price,map_source,created_variant_id,committed,note)
+ VALUES ('${c.shopify_id}','${esc(c.mfr_sku)}','${esc(rollSku)}','${esc(optName)}','${esc(label)}',${c.map},'${esc(c.map_src)}',${vid ? `'${vid}'` : 'NULL'},${good},${noteVal});`);
} catch (e) {
- console.log(` ⚠ AUDIT-WRITE FAILED (variant WAS created — record manually): shopify_id=${c.shopify_id} sku=${rollSku} vid=${vid||'?'} map=${c.map} src=${c.map_src} err=${String(e.message||e).slice(0,120)}`);
+ console.log(` ⚠ AUDIT-UPDATE FAILED (variant vid=${vid || '?'} created — record manually): ${String(e.message || e).slice(0, 100)}`);
}
if (good) { added++; console.log(` ✓ ${c.mfr_sku} +${label} @ $${price}`); }
else { fail++; console.log(` ✗ ${c.mfr_sku} ${JSON.stringify(ue || res.raw || res.err).slice(0,150)}`); }
}
- console.log(`\n${COMMIT ? 'DONE' : 'PREVIEW'}: ${added} ${COMMIT ? 'added' : 'would add'}, ${already} already-have-roll, ${fail} failed.`);
+ console.log(`\n${COMMIT ? 'DONE' : 'PREVIEW'}: ${added} ${COMMIT ? 'added' : 'would add'}, ${already} already-have-roll, ${skip} skipped-review (unit-mismatch), ${fail} failed.`);
if (COMMIT) console.log('Audit + rollback ids in dw_unified.kravet_roll_add_audit.');
else console.log(`\nDRY-RUN — no writes. Re-run with --commit (--limit ${LIMIT}) to add roll variants.`);
})();
← 252e2e9f Kravet roll-add: guard audit INSERT in try/catch so a loggin
·
back to Designer Wallcoverings
·
Kravet roll-add: harden unit-mismatch ceiling — drop the wid 67771259 →