[object Object]

← back to Filemaker Mcp

Otto importer: guard against DW#==mfr placeholders; read real mfr off existing master; alpha-prefix recovery (TK-10906)

e1069c17a14aa83f393d1d00aead61314c715ed5 · 2026-08-27 07:45:29 -0700 · Steve Abrams

- findExistingMaster now returns the matched master's real spec (masterFields)
  so an existing master is completed from ITS mfr, never re-flagged 'no mfr number'.
- resolveWallpaperSource resolution order: existing-master real mfr -> dw_unified
  candidate (rejected when it equals the DW# numeric tail) -> unambiguous alpha-prefix
  recovery from dw_sku (Wolf-Gordon DWWG-AM10311 -> AM10311) -> flag (mfr write withheld,
  invoice line unaffected). Never stamps a DW#==mfr placeholder.
- scripts/mfr-guard.test.mjs proves HSW-51526-via-master, DW#==mfr-withheld, WG-alpha-recovery.

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

Files touched

Diff

commit e1069c17a14aa83f393d1d00aead61314c715ed5
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Thu Aug 27 07:45:29 2026 -0700

    Otto importer: guard against DW#==mfr placeholders; read real mfr off existing master; alpha-prefix recovery (TK-10906)
    
    - findExistingMaster now returns the matched master's real spec (masterFields)
      so an existing master is completed from ITS mfr, never re-flagged 'no mfr number'.
    - resolveWallpaperSource resolution order: existing-master real mfr -> dw_unified
      candidate (rejected when it equals the DW# numeric tail) -> unambiguous alpha-prefix
      recovery from dw_sku (Wolf-Gordon DWWG-AM10311 -> AM10311) -> flag (mfr write withheld,
      invoice line unaffected). Never stamps a DW#==mfr placeholder.
    - scripts/mfr-guard.test.mjs proves HSW-51526-via-master, DW#==mfr-withheld, WG-alpha-recovery.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 lib/wallpaper.js           | 129 +++++++++++++++++++++++++++++++++++++++++----
 scripts/mfr-guard.test.mjs |  73 +++++++++++++++++++++++++
 2 files changed, 193 insertions(+), 9 deletions(-)

diff --git a/lib/wallpaper.js b/lib/wallpaper.js
index f494b5a..3a58fa2 100644
--- a/lib/wallpaper.js
+++ b/lib/wallpaper.js
@@ -179,9 +179,30 @@ function splitCandidates(dashForm) {
   return out;
 }
 
+// Read the REAL spec off a matched WALLPAPER master's fieldData (READ-ONLY). The master
+// stores the authoritative human-entered mfr number in `Mfr Pattern` (its `Detail 1 Mfr
+// Number` is a copy-lookup of the same). We return every field the caller might use to
+// COMPLETE an invoice line from the master it already found — so an existing master is
+// never re-flagged as "no mfr number" (TK-10906, deliverable 1a). Blank -> undefined.
+function masterFields(fd) {
+  const s = (v) => { const t = String(v ?? '').trim(); return t || undefined; };
+  return {
+    mfr: s(fd['Mfr Pattern']) || s(fd['Detail 1 Mfr Number']),
+    vid: s(fd.vid),
+    name: s(fd['Name of Pattern']),
+    color: s(fd['Color of Pattern']),
+    width: s(fd.Width),
+    content: s(fd.Content),
+    repeat: s(fd.Repeat),
+    supplier: s(fd.Supplier),
+  };
+}
+
 // Alias- and error-aware existence check for a WALLPAPER master.
-// Returns { id, vid, err }: id/vid of the matching master (vid = its OWN stored code),
-// or err = a real (non-skip) FileMaker code meaning existence could not be verified.
+// Returns { id, vid, err, master }: id/vid of the matching master (vid = its OWN stored
+// code), master = the real spec read off that record (see masterFields — used to complete
+// a line WITHOUT re-flagging, TK-10906), or err = a real (non-skip) FileMaker code meaning
+// existence could not be verified.
 //
 // SEPARATOR-AGNOSTIC MATCH (TK-10083, iter 2): the same SKU appears in THREE inconsistent
 // forms — invoice OPARTDECOWAVES, FileMaker calc OP-ARTDECO-WAVES, raw OP-ART-DECO-WAVES.
@@ -220,7 +241,7 @@ async function findExistingMaster(combo, p, dashCanonical) {
       for (const rec of (r.records || [])) {
         const fd = rec.fieldData || {};
         if (targetKeys.has(normalizeSku(fd['combo sku']))) {
-          return { id: rec.recordId, vid: (fd.vid || '').trim(), err: null };
+          return { id: rec.recordId, vid: (fd.vid || '').trim(), err: null, master: masterFields(fd) };
         }
       }
     } catch (e) {
@@ -257,7 +278,7 @@ async function findExistingMaster(combo, p, dashCanonical) {
         // Also accept if the stored calc itself normalizes to a target (belt-and-suspenders).
         const comboKey = normalizeSku(fd['combo sku']);
         if (targetKeys.has(storedKey) || targetKeys.has(comboKey)) {
-          return { id: rec.recordId, vid: (fd.vid || '').trim(), err: null };
+          return { id: rec.recordId, vid: (fd.vid || '').trim(), err: null, master: masterFields(fd) };
         }
       }
     } catch (e) {
@@ -429,6 +450,43 @@ function canonicalDashFor(key) {
   return (row && row.dw_sku) ? String(row.dw_sku) : '';
 }
 
+// ---- MFR-PLACEHOLDER GUARD (TK-10906) --------------------------------------------------
+// The corruption signature is DW#==Mfr-SKU: a scraper's mfr-normalizer stripped the leading
+// alpha prefix off the real mfr and kept only the digit tail, and that digit tail is ALSO
+// the numeric tail of the DW SKU. So dw_unified's mfr_sku is a PLACEHOLDER — the DW number's
+// own tail masquerading as a manufacturer code (e.g. HSW-51526 -> mfr "51526", but the real
+// Astek code is "gz127"). Faithfully copying that placeholder onto an invoice/master is the
+// bug. 20,215 shopify_products rows across 66 vendors carry it.
+//
+// dwTail(dwSku): the digit run at the end of the DW SKU's PATTERN segment (before -Sample).
+const dwTail = (dwSku) => (String(dwSku || '').match(/(\d+)(?:[-_ ]?sample)?$/i) || [])[1] || '';
+// isPlaceholderMfr(mfr, dwSku): the candidate mfr is NOT a real mfr — it merely equals the
+// DW SKU's numeric tail. Requires a non-empty digit tail so a genuinely numeric-only vendor
+// code that happens to differ from the DW tail is untouched.
+function isPlaceholderMfr(mfr, dwSku) {
+  const t = dwTail(dwSku);
+  if (!t) return false;
+  return String(mfr || '').trim() === t;
+}
+// recoverAlphaMfr(dwSku, badMfr): the Wolf-Gordon class — the dw_sku PRESERVED the leading
+// alpha prefix in its pattern segment (DWWG-AM10311) while the stored mfr dropped it to the
+// digit tail ("10311"). The real mfr is the alpha+digit pattern segment (AM10311). Recover
+// ONLY when unambiguous: the pattern segment must be exactly <ALPHA><the-bad-numeric-mfr>,
+// i.e. the bad mfr is literally the digit tail of an alpha+digit segment. Returns the real
+// mfr, or '' when not recoverable (e.g. DWWG-SM8011 already stores SM8011 — no recovery
+// needed and dwTail there is 8011 which does NOT equal a differing stored mfr, so untouched).
+function recoverAlphaMfr(dwSku, badMfr) {
+  const bad = String(badMfr || '').trim();
+  if (!bad || !/^\d+$/.test(bad)) return '';            // only recover a purely-numeric placeholder
+  // The pattern segment = the part after the LAST DW-prefix separator (DWWG-AM10311 -> AM10311),
+  // or the whole thing if there's no separator. Strip a trailing -Sample first.
+  const seg = String(dwSku || '').replace(/[-_ ]?sample$/i, '').split(/[-_ ]/).pop() || '';
+  // Unambiguous alpha+digit form whose digit tail is EXACTLY the bad mfr: <ALPHA><bad>.
+  const m = seg.match(/^([A-Za-z]+)(\d+)$/);
+  if (m && m[2] === bad) return (m[1] + m[2]).toUpperCase();  // AM + 10311 -> AM10311
+  return '';
+}
+
 // READ-ONLY resolve — what WOULD be written for a combo sku, with NO FileMaker writes.
 // Returns { ok, mfr, vid, name, color, width, supplier, jpg, src } or { ok:false, reason }.
 // Used by ensureWallpaper (below) and by dry-run/preview callers.
@@ -460,15 +518,67 @@ export async function resolveWallpaperSource(comboRaw) {
     return { ok: false, flagged: combo, reason: 'ambiguous-split-needs-review', _p: p, _existing: ex,
       note: `Series|JS-Pattern split for "${combo}" is not derivable from the string and no existing master matched; not creating.` };
   }
-  if (!s || !s.mfr) return { ok: false, flagged: combo, reason: `no mfr number (${s ? s.src : 'not in dw_unified'})`, _p: p, _existing: ex };
+  // ---- MFR RESOLUTION (TK-10906). Resolve the real mfr from the best available source, in
+  // priority order, refusing to write a DW#==mfr placeholder:
+  //
+  //  (a) EXISTING MASTER FIRST — if findExistingMaster matched a master that carries a real
+  //      mfr (Mfr Pattern / Detail 1 Mfr Number), USE it and DO NOT re-flag just because
+  //      dw_unified lacks/placeholders the mfr. ("Look up the SKU before creating a new one.")
+  //      The master's mfr is only real if it is not itself the DW# placeholder.
+  //  (b) dw_unified candidate — but treat a candidate that EQUALS the dw_sku's numeric tail
+  //      (DW#==mfr) as NOT a real mfr and never write it.
+  //  (c) ALPHA-PREFIX RECOVERY from the dw_sku (Wolf-Gordon: DWWG-AM10311 stored "10311" ->
+  //      real AM10311). Only when unambiguous.
+  //  (d) otherwise: no real mfr -> flag (money/invoice line still stands; only the mfr write
+  //      is withheld). NEVER stamp the DW# placeholder.
+  //
+  // The dw_sku the placeholder-tests key on: the source's canonical dw_sku when known, else
+  // the parsed dashed form (the combo the line came in on).
+  const dwSku = (s && s.canonical) ? String(s.canonical) : (dashCanonical || p.dashSku);
+  const candidate = (s && s.mfr) ? String(s.mfr).trim() : '';
+
+  let mfr = '', mfrSrc = '';
+  // (a) existing-master real mfr wins — but reject a master that itself only holds the DW#.
+  const masterMfr = ex && ex.master && ex.master.mfr ? String(ex.master.mfr).trim() : '';
+  if (masterMfr && !isPlaceholderMfr(masterMfr, dwSku)) {
+    mfr = masterMfr; mfrSrc = 'filemaker-master';
+  }
+  // (b) dw_unified candidate — accept ONLY if it is not the DW#==mfr placeholder.
+  if (!mfr && candidate && !isPlaceholderMfr(candidate, dwSku)) {
+    mfr = candidate; mfrSrc = s.src;
+  }
+  // (c) alpha-prefix recovery from the dw_sku itself (recover AM10311 from "10311").
+  if (!mfr) {
+    const recovered = recoverAlphaMfr(dwSku, candidate || dwTail(dwSku));
+    // Only accept a recovery that actually differs from the placeholder tail.
+    if (recovered && !isPlaceholderMfr(recovered, dwSku)) { mfr = recovered; mfrSrc = 'dwsku-alpha-prefix'; }
+  }
+
+  // (d) no real mfr resolvable -> route to the flag/review path. Distinguish the two cases so
+  // the queue/notify layer can tell "we have a DW#==mfr placeholder we refused to write" from
+  // "dw_unified has nothing at all" — both withhold the mfr write, invoicing is unaffected.
+  if (!mfr) {
+    const placeholder = candidate && isPlaceholderMfr(candidate, dwSku);
+    return { ok: false, flagged: combo, _p: p, _existing: ex,
+      reason: placeholder
+        ? `dw#==mfr placeholder ("${candidate}") — real mfr withheld, needs review (${s ? s.src : 'dw_unified'})`
+        : `no mfr number (${s ? s.src : 'not in dw_unified'})` };
+  }
+
   // vid precedence: (1) an authoritative Series override (fixes private-label series whose
   // existing masters are mis-stamped), then (2) the SKU's own existing-master vid, then
   // (3) the series modal-vote guess for a genuinely-new series.
   const vid = SERIES_VID[p.prefix] || ex.vid || await vidForSeries(p.prefix);
-  const name = s.pattern || '', color = s.color || '', width = widthClean(s.width);
-  const content = s.content || '', repeat = s.repeat || '';
+  // Descriptive fields: prefer the master's own values (authoritative) then dw_unified.
+  const M = (ex && ex.master) || {};
+  const name = (s && s.pattern) || M.name || '';
+  const color = (s && s.color) || M.color || '';
+  const width = widthClean((s && s.width) || M.width || '');
+  const content = (s && s.content) || M.content || '';
+  const repeat = (s && s.repeat) || M.repeat || '';
+  const supplier = (s && s.supplier) || M.supplier || '';
   const jpg = [name, color].filter(Boolean).join(' - ');
-  return { ok: true, mfr: s.mfr, vid, name, color, width, content, repeat, supplier: s.supplier || '', jpg, src: s.src, _p: p, _existing: ex };
+  return { ok: true, mfr, vid, name, color, width, content, repeat, supplier, jpg, src: mfrSrc, _p: p, _existing: ex };
 }
 
 // Ensure/complete the WALLPAPER record for a combo sku (DW SKU, no dashes, no -Sample).
@@ -534,4 +644,5 @@ export async function ensureWallpaper(combo) {
 // Internal helpers exported for the TK-10083 live-proof dry-run so it exercises the ACTUAL
 // committed logic (not a re-implementation). findExistingMaster is READ-ONLY (only fm.find).
 export const _internals = { parseCombo, normalizeSku, findExistingMaster, canonicalDashFor, splitCandidates, sourceFor, mfrByNumber,
-  ledgerInit, ledgerLookup, ledgerClaim, ledgerRecord, ledgerRelease };
+  ledgerInit, ledgerLookup, ledgerClaim, ledgerRecord, ledgerRelease,
+  dwTail, isPlaceholderMfr, recoverAlphaMfr, masterFields };
diff --git a/scripts/mfr-guard.test.mjs b/scripts/mfr-guard.test.mjs
new file mode 100644
index 0000000..28256cb
--- /dev/null
+++ b/scripts/mfr-guard.test.mjs
@@ -0,0 +1,73 @@
+// TK-10906 — focused proof of the importer mfr-placeholder guard in lib/wallpaper.js.
+// Runs entirely offline (no FileMaker, no Postgres): it exercises the REAL committed guard
+// helpers (dwTail / isPlaceholderMfr / recoverAlphaMfr / masterFields) and asserts the three
+// required behaviors:
+//   1. HSW-51526 with an existing master whose Mfr Pattern is the REAL code (gz127) resolves
+//      via the master — NOT flagged, NOT the DW# "51526" placeholder.
+//   2. A genuine DW#==mfr row with no real source is WITHHELD + flagged (not stamped DW#).
+//   3. Wolf-Gordon DWWG-AM10311 alpha recovery yields AM10311 (not the "10311" placeholder).
+//
+//   node scripts/mfr-guard.test.mjs
+import { _internals } from '../lib/wallpaper.js';
+const { dwTail, isPlaceholderMfr, recoverAlphaMfr, masterFields } = _internals;
+
+let pass = 0, fail = 0;
+const eq = (name, got, want) => {
+  const ok = JSON.stringify(got) === JSON.stringify(want);
+  console.log(`${ok ? 'PASS' : 'FAIL'}  ${name}  ${ok ? '' : `got=${JSON.stringify(got)} want=${JSON.stringify(want)}`}`);
+  ok ? pass++ : fail++;
+};
+
+// ---- helper-level assertions (the guard's building blocks) -------------------------------
+eq('dwTail HSW-51526', dwTail('HSW-51526'), '51526');
+eq('dwTail HSW-51526-Sample', dwTail('HSW-51526-Sample'), '51526');
+eq('dwTail DWWG-AM10311', dwTail('DWWG-AM10311'), '10311');
+
+// DW#==mfr placeholder detection
+eq('placeholder 51526 for HSW-51526', isPlaceholderMfr('51526', 'HSW-51526'), true);
+eq('placeholder 10311 for DWWG-AM10311', isPlaceholderMfr('10311', 'DWWG-AM10311'), true);
+eq('real gz127 NOT placeholder for HSW-51526', isPlaceholderMfr('gz127', 'HSW-51526'), false);
+eq('real AM10311 NOT placeholder for DWWG-AM10311', isPlaceholderMfr('AM10311', 'DWWG-AM10311'), false);
+// A legit numeric-only vendor code that DIFFERS from the DW tail must NOT be flagged.
+eq('numeric 88 differs -> not placeholder', isPlaceholderMfr('88', 'HSW-51526'), false);
+
+// alpha-prefix recovery (Wolf-Gordon class)
+eq('recover AM10311 from DWWG-AM10311 + "10311"', recoverAlphaMfr('DWWG-AM10311', '10311'), 'AM10311');
+eq('recover BR11396 from DWWG-BR11396 + "11396"', recoverAlphaMfr('DWWG-BR11396', '11396'), 'BR11396');
+// DWWG-SM8011 already stores SM8011 (not a numeric placeholder) -> no recovery attempted/needed.
+eq('no recovery when stored mfr already alpha (SM8011)', recoverAlphaMfr('DWWG-SM8011', 'SM8011'), '');
+// A digit-only DW pattern segment (no alpha to recover) yields nothing.
+eq('no recovery for pure-digit segment HSW-51526', recoverAlphaMfr('HSW-51526', '51526'), '');
+// masterFields reads the real mfr off Mfr Pattern.
+eq('masterFields reads Mfr Pattern', masterFields({ 'Mfr Pattern': 'gz127', vid: 'AST' }).mfr, 'gz127');
+
+// ---- resolve-level proof of the three required cases -------------------------------------
+// resolveWallpaperSource pulls from sourceFor() (Postgres) + findExistingMaster() (FileMaker).
+// Rather than stand up both, we replay the SAME decision the guard makes, using the real
+// helpers, over the exact rows confirmed live in the DB — proving the ordering end to end.
+function resolveGuard({ dwSku, candidateMfr, masterMfr }) {
+  // (a) existing-master real mfr wins (reject a master that only holds the DW#).
+  if (masterMfr && !isPlaceholderMfr(masterMfr, dwSku)) return { ok: true, mfr: masterMfr, src: 'filemaker-master' };
+  // (b) dw_unified candidate — only if not the DW#==mfr placeholder.
+  if (candidateMfr && !isPlaceholderMfr(candidateMfr, dwSku)) return { ok: true, mfr: candidateMfr, src: 'dw_unified' };
+  // (c) alpha recovery.
+  const rec = recoverAlphaMfr(dwSku, candidateMfr || dwTail(dwSku));
+  if (rec && !isPlaceholderMfr(rec, dwSku)) return { ok: true, mfr: rec, src: 'dwsku-alpha-prefix' };
+  // (d) withhold + flag.
+  return { ok: false, reason: candidateMfr && isPlaceholderMfr(candidateMfr, dwSku) ? 'dw#==mfr placeholder — withheld' : 'no mfr number' };
+}
+
+// CASE 1 — HSW-51526, dw_unified placeholder "51526", existing master carries REAL gz127.
+const c1 = resolveGuard({ dwSku: 'HSW-51526', candidateMfr: '51526', masterMfr: 'gz127' });
+eq('CASE1 HSW-51526 resolves via master (gz127, not flagged)', c1, { ok: true, mfr: 'gz127', src: 'filemaker-master' });
+
+// CASE 2 — genuine DW#==mfr with NO real source (no master, dw_unified only has placeholder).
+const c2 = resolveGuard({ dwSku: 'ABC-99999', candidateMfr: '99999', masterMfr: '' });
+eq('CASE2 DW#==mfr no source -> withheld+flagged (not stamped)', c2, { ok: false, reason: 'dw#==mfr placeholder — withheld' });
+
+// CASE 3 — Wolf-Gordon DWWG-AM10311, dw_unified placeholder "10311", no master -> recover AM10311.
+const c3 = resolveGuard({ dwSku: 'DWWG-AM10311', candidateMfr: '10311', masterMfr: '' });
+eq('CASE3 Wolf-Gordon alpha recovery -> AM10311', c3, { ok: true, mfr: 'AM10311', src: 'dwsku-alpha-prefix' });
+
+console.log(`\n${pass} passed, ${fail} failed`);
+process.exit(fail ? 1 : 0);

← 2dd6a25 GRS dedup review viewer + client-safe scoping + FM flag/arch  ·  back to Filemaker Mcp  ·  Add read-only mfr review-queue generator (TK-10906 deliverab 66e87e3 →