[object Object]

← back to Filemaker Mcp

Guard fix: Schumacher family (DWSW/SCH) is legit-numeric — never withhold their DW#==mfr (contrarian blocker, TK-10906)

b1dedc09e03363b442972e62069bbbf97918c355 · 2026-08-27 07:51:15 -0700 · Steve Abrams

Contrarian caught a live regression: the vendor-blind guard would withhold ~9,053 real
Schumacher mfrs (DWSW-5005933 mfr 5005933 IS the real code, per Steve's hard rule). Added a
LEGIT_NUMERIC allowlist (DWSW + SCH prefixes, boundary-matched) checked before isPlaceholderMfr,
so Schumacher passes through unflagged. Review-queue also skips the Schumacher family by
prefix AND vendor-name. Tests: 24 pass incl. Schumacher-passthrough + SCHX-boundary + queue-zero.

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

Files touched

Diff

commit b1dedc09e03363b442972e62069bbbf97918c355
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Thu Aug 27 07:51:15 2026 -0700

    Guard fix: Schumacher family (DWSW/SCH) is legit-numeric — never withhold their DW#==mfr (contrarian blocker, TK-10906)
    
    Contrarian caught a live regression: the vendor-blind guard would withhold ~9,053 real
    Schumacher mfrs (DWSW-5005933 mfr 5005933 IS the real code, per Steve's hard rule). Added a
    LEGIT_NUMERIC allowlist (DWSW + SCH prefixes, boundary-matched) checked before isPlaceholderMfr,
    so Schumacher passes through unflagged. Review-queue also skips the Schumacher family by
    prefix AND vendor-name. Tests: 24 pass incl. Schumacher-passthrough + SCHX-boundary + queue-zero.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 lib/wallpaper.js             | 27 ++++++++++++++++++++++++---
 scripts/mfr-guard.test.mjs   | 23 +++++++++++++++++++++--
 scripts/mfr-review-queue.mjs | 12 ++++++++++++
 3 files changed, 57 insertions(+), 5 deletions(-)

diff --git a/lib/wallpaper.js b/lib/wallpaper.js
index 3a58fa2..c3322bc 100644
--- a/lib/wallpaper.js
+++ b/lib/wallpaper.js
@@ -460,10 +460,31 @@ function canonicalDashFor(key) {
 //
 // 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] || '';
+
+// LEGIT-NUMERIC allowlist (TK-10906 contrarian fix). For a FEW lines the DW#==mfr equality is
+// NOT corruption — the DW SKU's numeric tail genuinely IS the vendor's real mfr. The
+// Schumacher family (series DWSW-#######, ~9,053 rows) is the canonical case: Steve's hard
+// rule is "DW# is Schumacher's real mfr — do NOT touch." For these, `mfr == DW#` is CORRECT
+// and must pass through unflagged, so the placeholder test must NOT fire. Keyed on the DW
+// series prefix (case-insensitive, prefix of the parsed Series). Add prefixes here only for
+// lines confirmed to have a real numeric-only mfr equal to the DW tail.
+// Schumacher files SKUs under BOTH prefixes (DWSW-####### and SCH-#####); both are the
+// Schumacher family where DW# is the real mfr, and SCH- is exclusively Schumacher (verified).
+const LEGIT_NUMERIC_MFR_PREFIXES = ['DWSW', 'SCH']; // Schumacher family — DW# IS the real mfr
+function isLegitNumericLine(dwSku) {
+  const up = String(dwSku || '').toUpperCase();
+  // Match on a prefix boundary (SCH-###, SCH###) so an unrelated future prefix like "SCHX"
+  // isn't accidentally swept in — require the prefix to be followed by a non-letter or end.
+  return LEGIT_NUMERIC_MFR_PREFIXES.some((pre) => up === pre || up.startsWith(pre + '-') || new RegExp(`^${pre}\\d`).test(up));
+}
+
 // 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.
+// DW SKU's numeric tail (the DW#==mfr corruption). Requires a non-empty digit tail so a
+// genuinely numeric-only vendor code that happens to differ from the DW tail is untouched.
+// GUARD: a line on the LEGIT_NUMERIC allowlist (Schumacher) is NEVER treated as a placeholder
+// — for those, mfr==DW# is the real, correct code and must be written, not withheld.
 function isPlaceholderMfr(mfr, dwSku) {
+  if (isLegitNumericLine(dwSku)) return false;   // Schumacher family: DW# IS the real mfr
   const t = dwTail(dwSku);
   if (!t) return false;
   return String(mfr || '').trim() === t;
@@ -645,4 +666,4 @@ export async function ensureWallpaper(combo) {
 // 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,
-  dwTail, isPlaceholderMfr, recoverAlphaMfr, masterFields };
+  dwTail, isPlaceholderMfr, recoverAlphaMfr, masterFields, isLegitNumericLine };
diff --git a/scripts/mfr-guard.test.mjs b/scripts/mfr-guard.test.mjs
index 28256cb..177da2c 100644
--- a/scripts/mfr-guard.test.mjs
+++ b/scripts/mfr-guard.test.mjs
@@ -9,7 +9,7 @@
 //
 //   node scripts/mfr-guard.test.mjs
 import { _internals } from '../lib/wallpaper.js';
-const { dwTail, isPlaceholderMfr, recoverAlphaMfr, masterFields } = _internals;
+const { dwTail, isPlaceholderMfr, recoverAlphaMfr, masterFields, isLegitNumericLine } = _internals;
 
 let pass = 0, fail = 0;
 const eq = (name, got, want) => {
@@ -31,6 +31,18 @@ eq('real AM10311 NOT placeholder for DWWG-AM10311', isPlaceholderMfr('AM10311',
 // 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);
 
+// SCHUMACHER REGRESSION GUARD (contrarian blocker fix): DWSW-####### is the LEGIT class —
+// DW# IS Schumacher's real mfr. isPlaceholderMfr MUST return false so the real mfr is written,
+// NOT withheld. Without the allowlist this would withhold ~9,053 real Schumacher mfrs.
+eq('Schumacher DWSW is legit-numeric line', isLegitNumericLine('DWSW-5005933'), true);
+eq('Schumacher SCH- is legit-numeric line', isLegitNumericLine('SCH-38799'), true);
+eq('Schumacher SCH#### (no dash) is legit-numeric line', isLegitNumericLine('SCH38799'), true);
+eq('Glitter Walls HSW is NOT legit-numeric line', isLegitNumericLine('HSW-51526'), false);
+// Boundary: a hypothetical unrelated "SCHX" prefix must NOT be swept in.
+eq('SCHX- unrelated prefix is NOT legit-numeric', isLegitNumericLine('SCHX-100'), false);
+eq('Schumacher 5005933 == DW# NOT withheld (real mfr)', isPlaceholderMfr('5005933', 'DWSW-5005933'), false);
+eq('Schumacher -Sample also passes through', isPlaceholderMfr('5005933', 'DWSW-5005933-Sample'), 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');
@@ -45,10 +57,12 @@ eq('masterFields reads Mfr Pattern', masterFields({ 'Mfr Pattern': 'gz127', vid:
 // 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.
+// Uses the REAL committed guard helpers (isPlaceholderMfr with the Schumacher allowlist,
+// recoverAlphaMfr) — same decision path as resolveWallpaperSource's resolution block.
 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.
+  // (b) dw_unified candidate — only if not the DW#==mfr placeholder (Schumacher passes here).
   if (candidateMfr && !isPlaceholderMfr(candidateMfr, dwSku)) return { ok: true, mfr: candidateMfr, src: 'dw_unified' };
   // (c) alpha recovery.
   const rec = recoverAlphaMfr(dwSku, candidateMfr || dwTail(dwSku));
@@ -69,5 +83,10 @@ eq('CASE2 DW#==mfr no source -> withheld+flagged (not stamped)', c2, { ok: false
 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' });
 
+// CASE 4 — SCHUMACHER (contrarian blocker): DWSW-5005933, mfr "5005933" == DW# but LEGIT.
+// The guard uses the REAL isPlaceholderMfr (allowlisted), so this must resolve — NOT flag.
+const c4 = resolveGuard({ dwSku: 'DWSW-5005933', candidateMfr: '5005933', masterMfr: '' });
+eq('CASE4 Schumacher DW#==mfr passes through (not withheld)', c4, { ok: true, mfr: '5005933', src: 'dw_unified' });
+
 console.log(`\n${pass} passed, ${fail} failed`);
 process.exit(fail ? 1 : 0);
diff --git a/scripts/mfr-review-queue.mjs b/scripts/mfr-review-queue.mjs
index 5416e7b..2c83e50 100644
--- a/scripts/mfr-review-queue.mjs
+++ b/scripts/mfr-review-queue.mjs
@@ -51,6 +51,16 @@ function sqlRows(q) {
 
 // ---- guard helpers (same semantics as lib/wallpaper.js — pure, no writes) ----------------
 const dwTail = (dwSku) => (String(dwSku || '').match(/(\d+)(?:[-_ ]?sample)?$/i) || [])[1] || '';
+// LEGIT-NUMERIC allowlist — DW# IS the real mfr for these (Schumacher DWSW). NEVER queue them
+// for "repair": their DW#==mfr rows are correct, not corrupt. Belt-and-suspenders even if a
+// user explicitly passes --vendors "Schumacher" (the guard in lib/wallpaper.js already
+// protects the live importer; this keeps the queue from proposing a wrong repair).
+const LEGIT_NUMERIC_MFR_PREFIXES = ['DWSW', 'SCH']; // Schumacher family — DW# IS the real mfr
+const isLegitNumericLine = (dwSku, vendor) => {
+  const up = String(dwSku || '').toUpperCase();
+  if (/schumacher/i.test(String(vendor || ''))) return true;               // any Schumacher vendor variant
+  return LEGIT_NUMERIC_MFR_PREFIXES.some((pre) => up === pre || up.startsWith(pre + '-') || new RegExp(`^${pre}\\d`).test(up));
+};
 function recoverAlphaMfr(dwSku, badMfr) {
   const bad = String(badMfr || '').trim();
   if (!bad || !/^\d+$/.test(bad)) return '';
@@ -127,6 +137,8 @@ for (const vendor of VENDORS) {
   perVendor[vendor] = { total: found.length, alpha: 0, fmnote: 0, none: 0 };
   for (const [dw_sku, bad_mfr, vend, pattern] of found) {
     if (rows.length >= LIMIT) break;
+    // Skip legit-numeric lines (Schumacher family): DW#==mfr is correct there, not corrupt.
+    if (isLegitNumericLine(dw_sku, vend || vendor)) { perVendor[vendor].total--; continue; }
     // Source 1 (Tier-2, HIGH conf): dw_sku alpha-prefix recovery.
     let best = recoverAlphaMfr(dw_sku, bad_mfr), source = best ? 'dwsku-alpha-prefix' : '', confidence = best ? 'high' : '';
     // Source 2 (MEDIUM conf): READ-ONLY FileMaker Mfr# note on the master.

← 66e87e3 Add read-only mfr review-queue generator (TK-10906 deliverab  ·  back to Filemaker Mcp  ·  fix: handle FileMaker 401 no-records gracefully in new-invoi cd8f973 →