[object Object]

← back to Sample Followup Sweep

sample-followup: draft gated vid-backfill for 3 verified leaked SKUs (TK-12118)

5b5b893a14fc504e4cca2bc395a0cd51b4febda9 · 2026-09-23 17:33:14 -0700 · Steve Abrams

Files touched

Diff

commit 5b5b893a14fc504e4cca2bc395a0cd51b4febda9
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Wed Sep 23 17:33:14 2026 -0700

    sample-followup: draft gated vid-backfill for 3 verified leaked SKUs (TK-12118)
---
 scripts/tk12118-vid-backfill.mjs | 74 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 74 insertions(+)

diff --git a/scripts/tk12118-vid-backfill.mjs b/scripts/tk12118-vid-backfill.mjs
new file mode 100644
index 0000000..1010631
--- /dev/null
+++ b/scripts/tk12118-vid-backfill.mjs
@@ -0,0 +1,74 @@
+// TK-12118 — backfill the missing `vid` on the 3 VERIFIED outstanding empty-vid records the
+// coverage-reconcile canary (TK-12117) flagged as LEAKED (outstanding in FileMaker but dropped
+// by the sweep before grouping because vid was blank → never chased, never reported).
+//
+// Vendors verified LIVE against FileMaker sibling records (not prefix guesses):
+//   DWTT70793  rec 538622  entered 07/30/2026  -> vid "Thib" (Supplier "Thibaut Wallpaper"; sibling 02/18/2025 carries vid=Thib)
+//   GLM9116    rec 541395  entered 09/08/2026  -> vid "FTR"  (Company "future Textile"; siblings carry vid=FTR = Future Textiles)
+//   DWPN100994 rec 541415  entered 09/08/2026  -> vid "POI"  (Supplier "Pointe at Justin David"; sibling carries vid=POI)
+//     NOTE: DWPN100994 ARRIVED 09/14/2026 on a twin record — after this backfill the never-false-chase
+//     guard (TK-12105) will correctly SUPPRESS it (arrived), not chase it. Expected/correct.
+//
+// NOT included: DWLC1059 (Supplier "LA Walls") — LA Walls has NO vid anywhere in FileMaker or the
+// fleet; assigning one is a vendor-registry decision for Steve. Left as WARN, not backfilled.
+//
+// USAGE:
+//   node ~/Projects/sample-followup-sweep/scripts/tk12118-vid-backfill.mjs            # backfill + write restore-map
+//   node ~/Projects/sample-followup-sweep/scripts/tk12118-vid-backfill.mjs --rollback # undo (set vid back to '')
+// Blast radius = 3 rows. Reversible via the restore-map (data/tk12118-vid-backfill-restore-map.json).
+import { readFileSync, writeFileSync } from 'node:fs';
+import { homedir } from 'node:os';
+import { join } from 'node:path';
+
+const cfg = JSON.parse(readFileSync(join(homedir(), '.claude.json'), 'utf8'));
+const env = cfg?.mcpServers?.filemaker?.env || {};
+for (const k of ['FM_CLOUD_HOST', 'FM_CLARIS_EMAIL', 'FM_CLARIS_PASSWORD']) process.env[k] = env[k];
+const fm = await import('/Users/macstudio3/Projects/filemaker-mcp/src/fm-client.js');
+
+const DB = 'WALLPAPER', LAYOUT = 'Report for old memo samples', FIELD = 'vid';
+const MAP = join(homedir(), 'Projects/sample-followup-sweep/data/tk12118-vid-backfill-restore-map.json');
+const TARGETS = [
+  { sku: 'DWTT70793',  recordId: '538622', vid: 'Thib', entered: '07/30/2026' },
+  { sku: 'GLM9116',    recordId: '541395', vid: 'FTR',  entered: '09/08/2026' },
+  { sku: 'DWPN100994', recordId: '541415', vid: 'POI',  entered: '09/08/2026' },
+];
+const ROLLBACK = process.argv.includes('--rollback');
+
+async function readRec(recordId) {
+  const { records } = await fm.findRecords(DB, LAYOUT, { 'recordId': `==${recordId}` }, { limit: 1 })
+    .catch(async () => {
+      // some layouts don't expose recordId as a findable field — fall back to getRecord if available
+      if (fm.getRecord) { const r = await fm.getRecord(DB, LAYOUT, recordId); return { records: r ? [r] : [] }; }
+      return { records: [] };
+    });
+  return records[0] || null;
+}
+
+if (ROLLBACK) {
+  const map = JSON.parse(readFileSync(MAP, 'utf8'));
+  for (const m of map) {
+    await fm.updateRecord(DB, LAYOUT, m.recordId, { [FIELD]: m.oldVid }, { dryRun: false });
+    console.log(`rolled back rec ${m.recordId} (${m.sku}) vid -> "${m.oldVid}"`);
+  }
+  console.log('rollback complete.');
+  process.exit(0);
+}
+
+const restore = [];
+for (const t of TARGETS) {
+  // SAFETY: only write if the record still has an EMPTY vid and matches the expected SKU (guard against drift)
+  const rec = await readRec(t.recordId);
+  const cur = rec ? (rec.fieldData[FIELD] || '').trim() : null;
+  const curSku = rec ? (rec.fieldData['combo sku'] || '').trim() : null;
+  if (!rec) { console.log(`SKIP ${t.sku} rec ${t.recordId}: record not found`); continue; }
+  if (curSku !== t.sku) { console.log(`SKIP ${t.sku} rec ${t.recordId}: SKU mismatch (found "${curSku}") — aborting this row`); continue; }
+  if (cur !== '') { console.log(`SKIP ${t.sku} rec ${t.recordId}: vid already "${cur}" (not empty) — not overwriting`); continue; }
+  restore.push({ sku: t.sku, recordId: t.recordId, oldVid: '' });
+  await fm.updateRecord(DB, LAYOUT, t.recordId, { [FIELD]: t.vid }, { dryRun: false });
+  // read-back verify
+  const after = await readRec(t.recordId);
+  const now = after ? (after.fieldData[FIELD] || '').trim() : '?';
+  console.log(`${now === t.vid ? 'OK  ' : 'WARN'} ${t.sku} rec ${t.recordId}: vid "" -> "${now}"${now === t.vid ? '' : ' (expected ' + t.vid + ')'}`);
+}
+writeFileSync(MAP, JSON.stringify(restore, null, 2));
+console.log(`\nrestore-map written: ${MAP} (${restore.length} rows). Rollback: node scripts/tk12118-vid-backfill.mjs --rollback`);

← b9f7fd7 auto-data-snapshot: 2026-09-23T16:24:32 (2 data files) — dat  ·  back to Sample Followup Sweep  ·  auto-data-snapshot: 2026-09-23T18:30:30 (1 data files) — dat 367e1e4 →