← 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
M lib/wallpaper.jsA scripts/mfr-guard.test.mjs
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 →