[object Object]

← back to Dw Sku Integrity

Add confirmation gate to phillip-jeffries ambiguous mfr-sku backfill

7f84bbd403c985f1203089af4917b7fe8494d288 · 2026-09-15 19:05:26 -0700 · Steve

The 3 Savile Suiting Pinstripe SKUs are PROVENANCE_REVIEW rows whose
real_mfr_sku values are unverified guesses (DWJP-15047 & DWJP-15049 share
an identical title with the same candidate set and no recorded
justification). --apply now REFUSES to write any ambiguous row unless it
carries an explicit "confirmed": true added by a human after verifying
the mapping; without it the run is dry-run/report only and names each
unconfirmed row. Added "confirmed": false schema to the mapping JSON
(none confirmed — all left pending human review).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit 7f84bbd403c985f1203089af4917b7fe8494d288
Author: Steve <steve@designerwallcoverings.com>
Date:   Tue Sep 15 19:05:26 2026 -0700

    Add confirmation gate to phillip-jeffries ambiguous mfr-sku backfill
    
    The 3 Savile Suiting Pinstripe SKUs are PROVENANCE_REVIEW rows whose
    real_mfr_sku values are unverified guesses (DWJP-15047 & DWJP-15049 share
    an identical title with the same candidate set and no recorded
    justification). --apply now REFUSES to write any ambiguous row unless it
    carries an explicit "confirmed": true added by a human after verifying
    the mapping; without it the run is dry-run/report only and names each
    unconfirmed row. Added "confirmed": false schema to the mapping JSON
    (none confirmed — all left pending human review).
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 .../phillip-jeffries-tk11131/apply-3-ambiguous.mjs | 36 +++++++++++++++++++---
 .../backfill-mapping-3-ambiguous.json              |  6 ++--
 2 files changed, 34 insertions(+), 8 deletions(-)

diff --git a/apply-plans/phillip-jeffries-tk11131/apply-3-ambiguous.mjs b/apply-plans/phillip-jeffries-tk11131/apply-3-ambiguous.mjs
index 3c55974..b40b969 100644
--- a/apply-plans/phillip-jeffries-tk11131/apply-3-ambiguous.mjs
+++ b/apply-plans/phillip-jeffries-tk11131/apply-3-ambiguous.mjs
@@ -58,16 +58,42 @@ for (const r of rows) {
   toWrite.push({ row: r, needCustom, needGlobal });
 }
 
-console.log(`${toWrite.length} to write, out of ${rows.length}.`);
+// AMBIGUOUS-ROW CONFIRMATION GATE (TK-11131 follow-up).
+// Every row in backfill-mapping-3-ambiguous.json is a PROVENANCE_REVIEW SKU: it was
+// NOT auto-resolved in the 897-item run and its real_mfr_sku is an UNVERIFIED guess
+// (e.g. DWJP-15047 & DWJP-15049 share the identical title "Savile Suiting Pinstripe -
+// White" with the same candidate set and no recorded justification). Writing that to
+// the live customer-facing manufacturer_sku metafield without a human sign-off would
+// bake in a guess. So --apply REFUSES to write any ambiguous row unless it carries an
+// explicit "confirmed": true in the mapping JSON (added by a human after verifying the
+// mapping). No confirmation => dry-run/report only, never a write.
+const confirmedWrites = toWrite.filter(w => w.row.confirmed === true);
+const unconfirmed = toWrite.filter(w => w.row.confirmed !== true);
+
+if (unconfirmed.length) {
+  console.log(`\n⛔ ${unconfirmed.length} ambiguous row(s) NOT confirmed — will NOT be written:`);
+  for (const { row } of unconfirmed) {
+    console.log(`   NEEDS CONFIRMATION: ${row.sku} "${row.title}" -> ${row.real_mfr_sku} (unverified)`);
+  }
+  console.log(`   To write one, a human must verify the mapping and add "confirmed": true to that row`);
+  console.log(`   in backfill-mapping-3-ambiguous.json.\n`);
+}
+
+console.log(`${confirmedWrites.length} confirmed to write, ${unconfirmed.length} awaiting confirmation, out of ${rows.length}.`);
 if (DRY) {
-  for (const { row, needCustom, needGlobal } of toWrite) {
+  for (const { row, needCustom, needGlobal } of confirmedWrites) {
     const fields = [needCustom && 'custom', needGlobal && 'global'].filter(Boolean).join('+');
     console.log(`DRY: would set ${row.sku} (${row.shopify_gid}) -> ${row.real_mfr_sku} [${fields}]`);
   }
   process.exit(0);
 }
 
-const metafields = toWrite.flatMap(({ row, needCustom, needGlobal }) => {
+if (!confirmedWrites.length) {
+  console.log('Nothing confirmed to write — no live metafields changed. (Confirm rows to proceed.)');
+  process.exit(0);
+}
+
+const metafields = confirmedWrites.flatMap(({ row, needCustom, needGlobal }) => {
   const mf = [];
   if (needCustom) mf.push({ ownerId: row.shopify_gid, namespace: 'custom', key: 'manufacturer_sku', type: 'single_line_text_field', value: row.real_mfr_sku });
   if (needGlobal) mf.push({ ownerId: row.shopify_gid, namespace: 'global', key: 'manufacturer_sku', type: 'single_line_text_field', value: row.real_mfr_sku });
@@ -82,13 +108,13 @@ if (metafields.length) {
   } else {
     // undo-map derived from the SUCCESS result — only rows actually written, only
     // the fields written (before = null, since we only wrote empty fields).
-    const undoMap = toWrite.map(({ row, needCustom, needGlobal }) => ({
+    const undoMap = confirmedWrites.map(({ row, needCustom, needGlobal }) => ({
       gid: row.shopify_gid,
       sku: row.sku,
       wrote: { custom: needCustom, global: needGlobal },
       before: { custom: null, global: null },
     }));
     fs.writeFileSync(new URL('./undo-map-3-ambiguous.json', import.meta.url), JSON.stringify(undoMap, null, 1));
-    console.log('SET:', toWrite.map(({ row }) => `${row.sku}->${row.real_mfr_sku}`).join(', '));
+    console.log('SET:', confirmedWrites.map(({ row }) => `${row.sku}->${row.real_mfr_sku}`).join(', '));
   }
 }
diff --git a/apply-plans/phillip-jeffries-tk11131/backfill-mapping-3-ambiguous.json b/apply-plans/phillip-jeffries-tk11131/backfill-mapping-3-ambiguous.json
index c768949..efddf7b 100644
--- a/apply-plans/phillip-jeffries-tk11131/backfill-mapping-3-ambiguous.json
+++ b/apply-plans/phillip-jeffries-tk11131/backfill-mapping-3-ambiguous.json
@@ -1,5 +1,5 @@
 [
- {"sku":"DWJP-15047-Sample","shopify_gid":"gid://shopify/Product/7941491097651","title":"Savile Suiting Pinstripe - White","real_mfr_sku":"10823"},
- {"sku":"DWJP-15048-Sample","shopify_gid":"gid://shopify/Product/7941491130419","title":"Savile Suiting Pinstripe - Ecru","real_mfr_sku":"10826"},
- {"sku":"DWJP-15049-Sample","shopify_gid":"gid://shopify/Product/7941491228723","title":"Savile Suiting Pinstripe - White","real_mfr_sku":"10825"}
+ {"sku":"DWJP-15047-Sample","shopify_gid":"gid://shopify/Product/7941491097651","title":"Savile Suiting Pinstripe - White","real_mfr_sku":"10823","confirmed":false},
+ {"sku":"DWJP-15048-Sample","shopify_gid":"gid://shopify/Product/7941491130419","title":"Savile Suiting Pinstripe - Ecru","real_mfr_sku":"10826","confirmed":false},
+ {"sku":"DWJP-15049-Sample","shopify_gid":"gid://shopify/Product/7941491228723","title":"Savile Suiting Pinstripe - White","real_mfr_sku":"10825","confirmed":false}
 ]

← 0c2d8d5 auto-data-snapshot: 2026-09-15T18:34:22 (6 data files) — app  ·  back to Dw Sku Integrity  ·  (newest)