← back to Sample Followup Sweep
auto-data-snapshot: 2026-09-23T13:45:21 (2 data files) — data/contacts.json.bak-20260923-131934-TK12085 scripts/send-reconciled.mjs.bak-20260923-131934-TK12085
20ca7a94d092536cb1fd506bd862e63cf781d2e4 · 2026-09-23 13:45:27 -0700 · auto-commit-fleet
Files touched
A data/contacts.json.bak-20260923-131934-TK12085A scripts/send-reconciled.mjs.bak-20260923-131934-TK12085
Diff
commit 20ca7a94d092536cb1fd506bd862e63cf781d2e4
Author: auto-commit-fleet <steve@designerwallcoverings.com>
Date: Wed Sep 23 13:45:27 2026 -0700
auto-data-snapshot: 2026-09-23T13:45:21 (2 data files) — data/contacts.json.bak-20260923-131934-TK12085 scripts/send-reconciled.mjs.bak-20260923-131934-TK12085
---
data/contacts.json.bak-20260923-131934-TK12085 | 377 +++++++++++++++++++++
...send-reconciled.mjs.bak-20260923-131934-TK12085 | 99 ++++++
2 files changed, 476 insertions(+)
diff --git a/data/contacts.json.bak-20260923-131934-TK12085 b/data/contacts.json.bak-20260923-131934-TK12085
new file mode 100644
index 0000000..6ef5aae
--- /dev/null
+++ b/data/contacts.json.bak-20260923-131934-TK12085
@@ -0,0 +1,377 @@
+{
+ "dgd": {
+ "name": "Designers Guild @ Osborne & Little",
+ "sample_email": "Polancol@oalusa.com",
+ "account_number": "1433803"
+ },
+ "osb": {
+ "name": "Osborne & Little",
+ "sample_email": "Polancol@oalusa.com",
+ "account_number": "1433803"
+ },
+ "wq": {
+ "name": "WallQuest / Malibu",
+ "sample_email": "orders@wallquest.com",
+ "account_number": "651317"
+ },
+ "thi": {
+ "name": "Thibaut",
+ "sample_email": "cathy.dy@thibautdesign.com",
+ "account_number": "0108751"
+ },
+ "thib": {
+ "name": "Thibaut",
+ "sample_email": "cathy.dy@thibautdesign.com",
+ "account_number": "0108751"
+ },
+ "pj": {
+ "name": "Phillip Jeffries",
+ "sample_email": "jballard@phillipjeffries.com",
+ "account_number": "On File"
+ },
+ "mor": {
+ "name": "Morris & Co",
+ "sample_email": "Sample@jaspershowroom.com",
+ "account_number": "On File"
+ },
+ "yor": {
+ "name": "York",
+ "sample_email": "RiveraH@yorkwall.com, orders@yorkwall.com",
+ "account_number": "34328"
+ },
+ "qua": {
+ "name": "Quadrille",
+ "sample_email": "Rhaiza@quadrilleinc.com",
+ "account_number": "37017"
+ },
+ "sca": {
+ "name": "Scalamandre",
+ "sample_email": "FLOVOS@scalamandre.com",
+ "account_number": "595234"
+ },
+ "kra": {
+ "name": "Kravet",
+ "sample_email": "matt.schoffman@kravet.com",
+ "account_number": "10087117"
+ },
+ "kor": {
+ "name": "Koroseal",
+ "sample_email": "samples@koroseal.com, sshortino@koroseal.com",
+ "account_number": "580270"
+ },
+ "bre": {
+ "name": "Brewster",
+ "sample_email": "brewsterorders@brewp.com",
+ "account_number": "6003784"
+ },
+ "brewster": {
+ "name": "Brewster",
+ "sample_email": "brewsterorders@brewp.com",
+ "account_number": "6003784"
+ },
+ "green": {
+ "name": "Greenland (bmwallpaper)",
+ "sample_email": "sales@bmwallpaper.com",
+ "account_number": "On File"
+ },
+ "astsand": {
+ "name": "Astek",
+ "sample_email": "amy.d@astek.com",
+ "account_number": "SAND001"
+ },
+ "arte-international": {
+ "name": "Arte (@ Egg & Dart)",
+ "sample_email": "Therese@egg-and-dart.com",
+ "account_number": "On File"
+ },
+ "pin": {
+ "name": "Pindler & Pindler",
+ "sample_email": "LosAngelesShowroom@pindlercorp.com",
+ "account_number": "696636"
+ },
+ "maya": {
+ "name": "Maya Romanoff",
+ "sample_email": "ari@quintushome.com",
+ "account_number": "On File"
+ },
+ "twi": {
+ "name": "twill (Karin Klein)",
+ "sample_email": "karinkleintextiles@gmail.com",
+ "account_number": "On File",
+ "needs_confirm": true,
+ "contact_source": "George: Karin Klein <karinkleintextiles@gmail.com> active sample-request replies 8/2026 (Steve screenshot: VID Twi, Karin Klein Textiles)"
+ },
+ "olp": {
+ "name": "Olivia & Poppy",
+ "sample_email": "info@oliviaandpoppy.com",
+ "account_number": "On File"
+ },
+ "san": {
+ "name": "Sancar (AS Cr\u00e9ation) \u2014 inferred",
+ "sample_email": "sales@sancarwallcovering.com",
+ "account_number": "1674444"
+ },
+ "chin": {
+ "name": "China Seas by Quadrille \u2014 inferred",
+ "sample_email": "Rhaiza@quadrilleinc.com",
+ "account_number": "37017"
+ },
+ "jofa": {
+ "name": "Lee Jofa (Kravet family) \u2014 inferred",
+ "sample_email": "matt.schoffman@kravet.com",
+ "account_number": "10087117"
+ },
+ "con": {
+ "name": "Concertex",
+ "sample_email": "info@concertex.com",
+ "account_number": "On File"
+ },
+ "sand": {
+ "name": "Sanderson Design Group \u2014 Zoffany/William Morris @ Jasper Showroom",
+ "sample_email": "Sample@jaspershowroom.com",
+ "account_number": "On File"
+ },
+ "sandb": {
+ "name": "Sandberg (via Gimmersta US)",
+ "sample_email": "support@gimmersta.com",
+ "account_number": "On File"
+ },
+ "rbl": {
+ "name": "Rebel Walls (via Gimmersta US)",
+ "sample_email": "support@gimmersta.com",
+ "account_number": "On File"
+ },
+ "spn": {
+ "name": "Spoonflower (online \u2014 no rep desk)",
+ "disposition": "no-chase",
+ "disposition_reason": "online print-on-demand \u2014 no sample-order desk to email (vendor type has no rep)",
+ "disposition_set": "2026-08-15"
+ },
+ "pf": {
+ "name": "Pierre Frey",
+ "sample_email": "hbarragan@kneedlerfauchere.com",
+ "account_number": "On File",
+ "contact_source": "DW Sent history \u2014 Kneedler Fauch\u00e8re (PF LA rep), order correspondence 2026-08-12; CONFIRM before send"
+ },
+ "rad": {
+ "disposition": "no-chase",
+ "disposition_reason": "item Dig-4350114V shares Spoonflower DIG- digital-print prefix \u2014 POD/no sample desk (INFERRED; reverse if RAD is a real chaseable vendor)",
+ "disposition_set": "2026-08-15",
+ "sample_email": "scott@radfordgraphics.com, jason@radfordgraphics.com"
+ },
+ "wol": {
+ "name": "Wolf Gordon",
+ "sample_email": "samples@wolfgordon.com",
+ "account_number": "149713",
+ "needs_confirm": true,
+ "contact_source": "George: dedicated sample desk samples@wolfgordon.com, sample-request confirmations Aug 2026"
+ },
+ "romo": {
+ "name": "Romo",
+ "sample_email": "fawn.bowen@romo.com",
+ "account_number": "223641",
+ "needs_confirm": true,
+ "contact_source": "George: Fawn Bowen, Sampling Coordinator, memo corr 8/17/2026"
+ },
+ "inn": {
+ "name": "Innovations",
+ "sample_email": "hmartinez@innovationsusa.com",
+ "account_number": "58315",
+ "needs_confirm": true,
+ "contact_source": "George: Hektor Martinez showroom, sample corr 8/17/2026 (acct Net Less 20%)"
+ },
+ "dtex": {
+ "name": "Designtex",
+ "sample_email": "samples@designtex.com",
+ "account_number": "On File",
+ "needs_confirm": true,
+ "contact_source": "George: Donna Dawson, Representative (LA), price-check corr 8/6/2026 \u2014 rep not sample desk, CONFIRM"
+ },
+ "mom": {
+ "name": "Momentum (\u2192Hollywood, INTERNAL chase only)",
+ "sample_email": "ddedic@momtex.com",
+ "account_number": "On File",
+ "needs_confirm": true,
+ "contact_source": "George: momtex sample-shipped notices Aug 2026; PRIVATE-LABEL, never customer-facing"
+ },
+ "ver": {
+ "name": "Versace (via Sancar)",
+ "sample_email": "sales@sancarwallcovering.com",
+ "account_number": "1674444",
+ "needs_confirm": true,
+ "contact_source": "George: 'sancar (VERSACE)' memo 8/17/2026 \u2014 Versace ordered through Sancar desk"
+ },
+ "sch": {
+ "name": "Schumacher (F. Schumacher)",
+ "disposition": "no-chase",
+ "disposition_reason": "self-service online sample ordering; only noreply@mailer.fschumacher.com exists \u2014 no rep desk to chase (George-verified 8/20)",
+ "disposition_set": "2026-08-20",
+ "sample_email": "la-samples@schumacher.com"
+ },
+ "sir": {
+ "name": "Sir Edward",
+ "sample_email": "sales@sir-edward.com",
+ "account_number": "On File",
+ "needs_confirm": true,
+ "contact_source": "George/Gmail mining 2026-08-20 (grounded on live outstanding-memo Mfr Patterns): D\u00e9sir\u00e9e Ouweneel <sales@sir-edward.com>, active sample/sales corr; DWFM40xxx file-requested art items"
+ },
+ "cow": {
+ "name": "Cowtan & Tout / Colefax & Fowler / Jane Churchill",
+ "sample_email": "la_sample@cowtan.com",
+ "account_number": "On File",
+ "needs_confirm": true,
+ "contact_source": "George/Gmail mining 2026-08-20 (grounded on live outstanding-memo Mfr Patterns): LA Sample <la_sample@cowtan.com> replies to New Sample Request; DWPD Cowtan/Colefax/JaneChurchill patterns"
+ },
+ "bm": {
+ "name": "B&M Wallpaper (Nora / Greenland factory)",
+ "sample_email": "sales@bmwallpaper.com",
+ "account_number": "On File",
+ "needs_confirm": true,
+ "contact_source": "George/Gmail mining 2026-08-20 (grounded on live outstanding-memo Mfr Patterns): 'NORA & GREENLAND' <sales@bmwallpaper.com> already replies to our sample follow-ups; GRS/HLW woven-texture SKUs"
+ },
+ "amer": {
+ "name": "American Silk Mills (SolidSensuede)",
+ "sample_email": "crystal.guard@americansilk.com",
+ "account_number": "On File",
+ "needs_confirm": true,
+ "contact_source": "George/Gmail mining 2026-08-20 (grounded on live outstanding-memo Mfr Patterns): Crystal Guard <crystal.guard@americansilk.com> replies to New Sample Request; SDP SolidSensuede SKUs"
+ },
+ "egg": {
+ "name": "Egg & Dart (Arte distributor)",
+ "sample_email": "therese@egg-and-dart.com",
+ "account_number": "On File",
+ "needs_confirm": true,
+ "contact_source": "George/Gmail mining 2026-08-20 (grounded on live outstanding-memo Mfr Patterns): Therese Stachowiak <therese@egg-and-dart.com>, same desk as arte; BEC SKU"
+ },
+ "coor": {
+ "name": "Coordonn\u00e9 (via NewWall)",
+ "sample_email": "tricia@newwall.com",
+ "account_number": "On File",
+ "needs_confirm": true,
+ "contact_source": "George/Gmail mining 2026-08-20 (grounded on live outstanding-memo Mfr Patterns): Tricia Robb <tricia@newwall.com> handles NWD/Coordonn\u00e9; DWDC 'Bike ride Fawn' A00907"
+ },
+ "christian-lacroix-europe": {
+ "name": "Christian Lacroix (via Osborne & Little / Designers Guild)",
+ "sample_email": "Polancol@oalusa.com",
+ "account_number": "1433803",
+ "needs_confirm": true,
+ "contact_source": "George/Gmail mining 2026-08-20 (grounded on live outstanding-memo Mfr Patterns): CL is a Designers Guild/O&L brand; Leandra Polanco <Polancol@oalusa.com> is our O&L sample desk; PCL codes EUR prefix"
+ },
+ "hyg": {
+ "name": "Hygge & West",
+ "sample_email": "info@hyggeandwest.com",
+ "account_number": "On File",
+ "needs_confirm": true,
+ "contact_source": "George/Gmail mining 2026-08-20 (grounded on live outstanding-memo Mfr Patterns): only Hygge & West address on file is support@hyggeandwest.com (marketing/support); DWHW2 'Be Good' SKU \u2014 CONFIRM it accepts trade sample requests"
+ },
+ "fol": {
+ "name": "Folia Fabrics (RETIRED)",
+ "disposition": "no-chase",
+ "disposition_reason": "Folia source decommissioned 2026-08-18 (folia-scraper retired); Ralph LWP items were Folia-distributed \u2014 no live desk to chase",
+ "disposition_set": "2026-08-20",
+ "contact_source": "George/Gmail mining 2026-08-20 (grounded on live outstanding-memo Mfr Patterns)",
+ "sample_email": "customerservice@folia-fabrics.com"
+ },
+ "phillipe-romano": {
+ "name": "Phillipe Romano (private label)",
+ "disposition": "no-chase",
+ "disposition_reason": "DW private label (Command54/RIGO/Justin David umbrella) \u2014 internal only, never chase a customer-facing vendor desk; PI-ACOUSTIC DWPN SKU",
+ "disposition_set": "2026-08-20",
+ "contact_source": "George/Gmail mining 2026-08-20 (grounded on live outstanding-memo Mfr Patterns)"
+ },
+ "carl": {
+ "name": "Carlsten / Desima (private label, archived)",
+ "disposition": "no-chase",
+ "disposition_reason": "Carlsten/Desima private-label line (Steve: Desima/Kravet); TTF Capitone items \u2014 archived line, no live sample desk",
+ "disposition_set": "2026-08-20",
+ "contact_source": "George/Gmail mining 2026-08-20 (grounded on live outstanding-memo Mfr Patterns)"
+ },
+ "ftr": {
+ "name": "(unresolved) metallic-leaf vendor \u2014 GLM/GLMG SL08/B20 gunmetal/bronze/copper codes",
+ "needs_confirm": true,
+ "unresolved_email": true,
+ "contact_source": "George/Gmail mining 2026-08-20 (grounded on live outstanding-memo Mfr Patterns): no vendor identity found in George; metallic/gilded-leaf line, distributor unknown",
+ "sample_email": "ftg1@futuretextiles.com"
+ },
+ "ulr": {
+ "name": "Ulrich Welter",
+ "needs_confirm": true,
+ "unresolved_email": false,
+ "sample_email": "info@welter-wandunikate.de",
+ "confidence": "HIGH",
+ "contact_source": "TK-11524 (worker-w03, 2026-09-12) George/Gmail resolution: Ulrich Welter = Welter Wandunikate (DW flock-velvet 'Austrian Prince' / glass-bead mfr). Address info@welter-wandunikate.de confirmed via Gmail msg 17e4fa0f0ecd5b7d \u2014 a two-way DW<->Ulrich order/cost/shipping thread (Ulrich emailed FROM this address to info@designerwallcoverings.com). Held needs_confirm:true pending Steve's confirm per the standing convention before it can draft."
+ },
+ "tbd": {
+ "name": "(placeholder — unidentified vendor)",
+ "disposition": "no-chase",
+ "disposition_reason": "TK-11524 (worker-w03, 2026-09-12): vid 'TBD' is a FileMaker data-entry placeholder, not a real vendor — there is no sample desk to chase. The durable fix is correcting the vid on the source memo in FileMaker (a canonical FM write, gated/out-of-scope for this data-hygiene pass). Dispositioned so the empty sample_email is EXPECTED, not a phantom gap.",
+ "disposition_set": "2026-09-12"
+ },
+ "1838-wallcoverings": {
+ "name": "1838 Wallcoverings",
+ "needs_confirm": true,
+ "unresolved_email": true,
+ "contact_source": "George/Gmail mining 2026-08-20 (grounded on live outstanding-memo Mfr Patterns): real line (1838-scraper-manager); likely distributed via Maxwell Fabrics (distribution@postmark.pdfsystems.com is order-only, not a sample desk) \u2014 no inbound sample-desk contact captured; CONFIRM the 1838/Maxwell sample email",
+ "sample_email": "scott.myer@gmail.com",
+ "account_number": "On File"
+ },
+ "bar": {
+ "name": "Barneby Gates",
+ "needs_confirm": true,
+ "contact_source": "George/Gmail 2026-09-15: active DW vendor (live PO thread 101832; invoices SI-32897/SI-32880 in GBP). studio@=order/PO desk, alice@Gates=dispatch. Steve chose BOTH recipients 2026-09-15 (TK sample-followup vendor re-attribution). account On File; CONFIRM DW acct# + true sample desk.",
+ "sample_email": "studio@barnebygates.com, alice@barnebygates.com",
+ "account_number": "On File"
+ },
+ "poi": {
+ "name": "Pointe (via Justin David private label)",
+ "needs_confirm": true,
+ "unresolved_email": true,
+ "contact_source": "George/Gmail mining 2026-08-20 (grounded on live outstanding-memo Mfr Patterns): PI- codes DWPR/DWPN, 'from pointe'; Justin David desk jackie@justindavid.com is the likely source but POI may be an internal PR/JD private-label \u2014 CONFIRM whether to chase externally at all",
+ "sample_email": "samples@justindavid.com",
+ "account_number": "On File"
+ },
+ "paul": {
+ "name": "Paul Montgomery",
+ "sample_email": "info@paulmontgomery.com",
+ "account_number": "1045144",
+ "contact_source": "George/Gmail mining 2026-08-25 (grounded on live outstanding-memo Mfr Patterns + account#); confirmed 'New Sample Request for Designer Wallcoverings' thread"
+ },
+ "mdc": {
+ "name": "MDC Wallcoverings",
+ "sample_email": "sample@mdcwall.com",
+ "account_number": "1062427",
+ "note": "private-label as Phillipe Romano; chase real vendor MDC (internal)",
+ "contact_source": "George/Gmail mining 2026-08-25 (grounded on live outstanding-memo Mfr Patterns + account#); MDC Customer Service <cs@mdcwall.com>"
+ },
+ "eli": {
+ "name": "Elitis (USA \u2014 Annalisa Dominguez)",
+ "main_email": "ANNALISA@elitis.us",
+ "account_number": "1062120",
+ "needs_confirm": true,
+ "contact_source": "Steve-corrected 2026-08-25: sent to Elitis USA rep Annalisa <ANNALISA@elitis.us> (not France HQ contact@elitis.fr)",
+ "sample_email": "annalisa@elitis.us"
+ },
+ "lin": {
+ "name": "Lincrusta",
+ "main_email": "rebecca.cragg@lincrusta.com",
+ "account_number": "1062465",
+ "needs_confirm": true,
+ "contact_source": "George/Gmail mining 2026-08-25 (grounded on live outstanding-memo Mfr Patterns + account#); active rep Rebecca Cragg (corr. through 8/18/2026) \u2014 main/rep fallback per Steve 8/25",
+ "sample_email": "federico.contigiani@lincrusta.com"
+ },
+ "lbi": {
+ "name": "LBI Boyd (Jill Carol)",
+ "sample_email": "jill@lbiboyd.com",
+ "account_number": "On File"
+ },
+ "vah": {
+ "name": "Vahallan",
+ "sample_email": "info@vahallan.com",
+ "account_number": "On File"
+ },
+ "bru": {
+ "name": "Brunschwig & Fils (@ Kravet)",
+ "sample_email": "matt.schoffman@kravet.com",
+ "account_number": "10087117"
+ }
+}
\ No newline at end of file
diff --git a/scripts/send-reconciled.mjs.bak-20260923-131934-TK12085 b/scripts/send-reconciled.mjs.bak-20260923-131934-TK12085
new file mode 100644
index 0000000..3f6c293
--- /dev/null
+++ b/scripts/send-reconciled.mjs.bak-20260923-131934-TK12085
@@ -0,0 +1,99 @@
+#!/usr/bin/env node
+// Reconciled sample-follow-up DRAFTER (Steve 8/20).
+// Pulls outstanding memos in the "fill-in-since-last-send / 10-day-floor" window and DRAFTS one
+// letter per vendor into info@ Drafts (NEVER auto-sends). Steve reviews + sends from Drafts.
+// Letter = intro + "Attn / processed by: <vendor processor>" + Ref#·Date Ordered·Manufacturer# table.
+// WIN env overrides the FileMaker date range (default = today's fill-in window).
+import { readFileSync, writeFileSync } from 'node:fs'; import { homedir } from 'node:os'; import { join } from 'node:path'; import { createRequire } from 'node:module';
+const require = createRequire(import.meta.url);
+const ROOT = join(homedir(), 'Projects/sample-followup-sweep');
+const { georgeRequest } = require(join(ROOT, 'lib/george-transport.js'));
+// Rolling window: memos that crossed the 10-day follow-up floor within the last CATCHUP days (default 7),
+// so a daily scheduled run always covers any gap. Env WIN overrides for a manual one-off. (Draft-dedup
+// below stops the same memo being drafted twice across runs.)
+const _pad = (n) => String(n).padStart(2, '0');
+const _fmt = (d) => `${_pad(d.getMonth() + 1)}/${_pad(d.getDate())}/${d.getFullYear()}`;
+// Steve 2026-09-22 (TK-12013/TK-12014): full active window [today-MAX_AGE .. today-MIN_AGE] inclusive,
+// NOT a narrow rolling catch-up band — so no older still-outstanding memo is ever dropped. Draft-dedup
+// (reconciled-draft-ledger keyed by vendor+combo-sku) makes re-covering already-drafted memos a no-op.
+const _MIN_AGE = 10, _MAX_AGE = Number(process.env.MAX_AGE) || 60;
+const _hi = new Date(); _hi.setDate(_hi.getDate() - _MIN_AGE); // includes exactly-10d cohort (inclusive range)
+const _lo = new Date(); _lo.setDate(_lo.getDate() - _MAX_AGE); // 60-day dead-lead floor
+const WIN = process.env.WIN || `${_fmt(_lo)}...${_fmt(_hi)}`;
+
+// --- FileMaker: pull outstanding (Date WP Sample Sent empty) in WIN, group by vid ---
+const cfg = JSON.parse(readFileSync(join(homedir(), '.claude.json'), 'utf8'));
+const fenv = cfg?.mcpServers?.filemaker?.env || {};
+for (const k of ['FM_CLOUD_HOST', 'FM_CLARIS_EMAIL', 'FM_CLARIS_PASSWORD']) process.env[k] = fenv[k];
+process.env.FM_READONLY = '1';
+const fm = await import('/Users/macstudio3/Projects/filemaker-mcp/src/fm-client.js');
+const A = (await fm.findRecords('WALLPAPER', 'REPORT ON SAMPLES ORDERED',
+ { 'Date WP Sample Sent': '=', 'today for client': WIN }, { limit: 1200 }).catch(() => ({ records: [] }))).records;
+const snap = {};
+for (const r of A) { const d = r.fieldData; const v = String(d.vid || '').toUpperCase(); if (!v) continue;
+ (snap[v] = snap[v] || []).push({ mfr: (d['Mfr Pattern'] || '').trim(), sku: d['combo sku'] || '', req: d['today for client'] || '' }); }
+writeFileSync(join(ROOT, 'data/outstanding-snapshot.json'), JSON.stringify(snap, null, 2));
+
+const esc = s => String(s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
+const SHIP = { name: 'Designer Wallcoverings', line1: '15442 Ventura Blvd. #102', csz: 'Sherman Oaks, CA 91403', phone: '1-888-373-4564' };
+// Sent-verified addresses + processor (person at vendor who handled the order), per vendor
+const V = {
+ YOR: { name: 'York', to: 'RiveraH@yorkwall.com, orders@yorkwall.com', acct: '34328', proc: 'York Sample Dept (order-thru-website desk)' },
+ BRE: { name: 'Brewster', to: 'brewsterorders@brewp.com', acct: '6003784', proc: 'Brewster Orders desk' },
+ BMGREEN:{ name: 'Greenland / bmwallpaper', to: 'sales@bmwallpaper.com', acct: 'On File', proc: 'Nora (NORA & GREENLAND)' },
+ OSB: { name: 'Osborne & Little', to: 'Polancol@oalusa.com', acct: '1433803', proc: 'Leandra Polanco' },
+ KRA: { name: 'Kravet', to: 'matt.schoffman@kravet.com', acct: '10087117', proc: 'Matt Schoffman' },
+ ROMO: { name: 'Romo', to: 'fawn.bowen@romo.com', acct: '223641', proc: 'Fawn Bowen (Sampling Coordinator)' },
+ SANDB: { name: 'Sandberg (via Gimmersta)', to: 'support@gimmersta.com', acct: 'On File', proc: 'Alva' },
+ WQ: { name: 'WallQuest / Malibu', to: 'orders@wallquest.com', acct: '651317', proc: 'WallQuest Orders desk' },
+ THIB: { name: 'Thibaut', to: 'cathy.dy@thibautdesign.com', acct: '0108751', proc: 'Cathy Dy' },
+ ARTE: { name: 'Arte (@ Egg & Dart)', to: 'Therese@egg-and-dart.com', acct: 'On File', proc: 'Therese Stachowiak' },
+};
+// merge BM + GREEN under one bmwallpaper letter
+const items = {};
+for (const [vid, arr] of Object.entries(snap)) { const key = (vid === 'BM' || vid === 'GREEN') ? 'BMGREEN' : vid; (items[key] = items[key] || []).push(...arr); }
+
+function letter(v, rows) {
+ // Steve 8/20: do NOT show our internal Ref # (DW SKU) to the vendor — Date Ordered + Mfr # only.
+ const tbl = rows.map(r => `<tr style="border-bottom:1px solid #eee"><td style="padding:5px 18px 5px 0;white-space:nowrap">${esc(r.req || '—')}</td><td style="padding:5px 0">${esc(r.mfr)}</td></tr>`).join('\n');
+ return `<div style="font-family:Arial,Helvetica,sans-serif;font-size:14px;color:#222;line-height:1.5">
+<p>We are following up on memo samples we have not yet received (ordered ~10 days ago).</p>
+<p><strong>Our account number is ${esc(v.acct)}</strong></p>
+<p><strong>Attn / processed by:</strong> ${esc(v.proc)} — please route these to whoever handled the original order.</p>
+<table style="border-collapse:collapse;font-size:14px;margin:8px 0">
+<tr style="text-align:left;border-bottom:2px solid #333"><th style="padding:5px 18px 5px 0">Date Ordered</th><th style="padding:5px 0">Manufacturer #</th></tr>
+${tbl}
+</table>
+<p>Ship to:<br>${esc(SHIP.name)}<br>${esc(SHIP.line1)}<br>${esc(SHIP.csz)}<br>${esc(SHIP.phone)}</p>
+<p><strong>Sidemark: Samples ASAP</strong></p>
+<p>Thank you!<br>Showroom Manager</p>
+<p style="font-size:11px;color:#666">Designer Wallcoverings · 15442 Ventura Blvd. #102 · Sherman Oaks, CA 91403<br>
+To stop receiving sample follow-up emails, <a href="mailto:info@designerwallcoverings.com?subject=Unsubscribe%20from%20sample%20follow-ups">unsubscribe here</a>.</p></div>`;
+}
+// George draft (account=info, /api/drafts — no send-approval token)
+const genv = k => { for (const f of ['/Users/macstudio3/Projects/Designer-Wallcoverings/DW-MCP/.env', '/Users/macstudio3/Projects/george-gmail/.env']) { try { const m = readFileSync(f, 'utf8').match(new RegExp('^' + k + '=(.+)$', 'm')); if (m) return m[1].trim(); } catch {} } return ''; };
+let auth = genv('GEORGE_BASIC_AUTH'); if (!auth.includes(':')) auth = 'admin:' + genv('GEORGE_BASIC_AUTH_PASS');
+auth = 'Basic ' + Buffer.from(auth).toString('base64');
+async function draft(to, subject, body) {
+ const result = await georgeRequest({ path: '/api/drafts', payload: { account: 'info', to, subject, body }, headers: { Authorization: auth } });
+ try { const parsed = JSON.parse(result.body); return parsed.success ? 'ok' : result.body.slice(0, 80); } catch { return result.body.slice(0, 80); }
+}
+
+const DO = process.argv.includes('--draft');
+// Draft-dedup: never re-draft a memo (keyed by vendor+combo-sku) that a prior run already drafted,
+// so a daily scheduled run over a rolling window can't pile up duplicate drafts.
+const LEDGER = join(ROOT, 'data/reconciled-draft-ledger.json');
+let ledger = {}; try { ledger = JSON.parse(readFileSync(LEDGER, 'utf8')); } catch {}
+const stamp = _fmt(new Date());
+console.log(`Reconciled follow-up — window ${WIN} — ${DO ? 'DRAFT into info@' : 'DRY-RUN (add --draft to create)'}\n`);
+for (const [key, rows] of Object.entries(items)) {
+ const v = V[key]; if (!v) { console.log(` ? no vendor map for ${key} (${rows.length})`); continue; }
+ const fresh = rows.filter(r => !ledger[`${key}:${r.sku}`]);
+ if (!fresh.length) { console.log(` ⊘ ${v.name.padEnd(26)} — all ${rows.length} already drafted (skip)`); continue; }
+ const subj = `Sample Follow-Up — Outstanding Memos (Acct ${v.acct}) — Designer Wallcoverings`;
+ if (!DO) { console.log(` · ${v.name.padEnd(26)} → ${v.to.padEnd(40)} (${fresh.length}) refs: ${fresh.map(r => r.sku).join(', ')}`); continue; }
+ const r = await draft(v.to, subj, letter(v, fresh));
+ console.log(` ${r === 'ok' ? '✎' : '✗'} ${v.name.padEnd(26)} → ${v.to.padEnd(40)} (${fresh.length}) ${r === 'ok' ? '' : r}`);
+ if (r === 'ok') for (const row of fresh) ledger[`${key}:${row.sku}`] = stamp;
+}
+if (DO) writeFileSync(LEDGER, JSON.stringify(ledger, null, 2));
← 7394a41 sample-followup: resolve 68 blocked overdue rows (TK-12085)
·
back to Sample Followup Sweep
·
auto-data-snapshot: 2026-09-23T14:17:00 (2 data files) — dat 04e0986 →