← back to Sample Followup Sweep
TK-11409: the static contact list expires instead of blocking forever
74e43c219b9d015298cc744571333de22755ed09 · 2026-09-10 12:29:26 -0700 · Steve Abrams
data/recently-contacted.json was a PERMANENT blocklist: hand-written, last edited
2026-08-20, 26 addresses, nothing ever expiring -- and it held the biggest accounts
(Kravet, Thibaut, Osborne & Little, York, WallQuest, Sancar, Innovations, MDC,
Maharam, Koroseal, Phillip Jeffries, Wolf Gordon...). So even after the Gmail query
was corrected to match the chase subject, those vendors stayed suppressed from SEND
forever by a snapshot nobody had looked at in three weeks.
This was a THIRD suppression source. The earlier fix narrowed one of them and I never
checked whether another existed -- same failure family as the rest of the ticket: a
record taken once and trusted indefinitely.
- File converted from a bare array to { address: 'YYYY-MM-DD' }, every entry seeded
with the file mtime (the only honest date available).
- Entries now EXPIRE after RECENT_DAYS.
- A bare-array file is still accepted but treated as expired-unknown, so an old copy
or a hand-edit cannot resurrect permanent-blocklist behaviour.
- Each run prints how many are live vs expired, so the list can never go quiet again.
Verified: 0 within 14d, 26 expired. Sancar is now correctly sendable (no chase in 14
days -- its recent mail was new sample ORDERS). WallQuest stays correctly suppressed
(real chase sent 09/01).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Files touched
M data/recently-contacted.jsonM scripts/scheduled-run.mjs
Diff
commit 74e43c219b9d015298cc744571333de22755ed09
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu Sep 10 12:29:26 2026 -0700
TK-11409: the static contact list expires instead of blocking forever
data/recently-contacted.json was a PERMANENT blocklist: hand-written, last edited
2026-08-20, 26 addresses, nothing ever expiring -- and it held the biggest accounts
(Kravet, Thibaut, Osborne & Little, York, WallQuest, Sancar, Innovations, MDC,
Maharam, Koroseal, Phillip Jeffries, Wolf Gordon...). So even after the Gmail query
was corrected to match the chase subject, those vendors stayed suppressed from SEND
forever by a snapshot nobody had looked at in three weeks.
This was a THIRD suppression source. The earlier fix narrowed one of them and I never
checked whether another existed -- same failure family as the rest of the ticket: a
record taken once and trusted indefinitely.
- File converted from a bare array to { address: 'YYYY-MM-DD' }, every entry seeded
with the file mtime (the only honest date available).
- Entries now EXPIRE after RECENT_DAYS.
- A bare-array file is still accepted but treated as expired-unknown, so an old copy
or a hand-edit cannot resurrect permanent-blocklist behaviour.
- Each run prints how many are live vs expired, so the list can never go quiet again.
Verified: 0 within 14d, 26 expired. Sancar is now correctly sendable (no chase in 14
days -- its recent mail was new sample ORDERS). WallQuest stays correctly suppressed
(real chase sent 09/01).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
---
data/recently-contacted.json | 29 ++++++++++++++++++++++++++++-
scripts/scheduled-run.mjs | 25 ++++++++++++++++++++++++-
2 files changed, 52 insertions(+), 2 deletions(-)
diff --git a/data/recently-contacted.json b/data/recently-contacted.json
index 0085f41..a2bf542 100644
--- a/data/recently-contacted.json
+++ b/data/recently-contacted.json
@@ -1 +1,28 @@
-["riverah@yorkwall.com","orders@yorkwall.com","orders@wallquest.com","matt.schoffman@kravet.com","samples@koroseal.com","sshortino@koroseal.com","jballard@phillipjeffries.com","ddedic@momtex.com","karinkleintextiles@gmail.com","customerservice@wolfgordon.com","ari@quintushome.com","jill@lbiboyd.com","jcarol@lbiboyd.com","hbarragan@kneedlerfauchere.com","polancol@oalusa.com","sales@sancarwallcovering.com","fawn.bowen@romo.com","sample@mdcwall.com","bfoss@maharam.com","aaramburu@maharam.com","annalisa@elitis.us","therese@egg-and-dart.com","cathy.dy@thibautdesign.com","federico.contigiani@lincrusta.com","hmartinez@innovationsusa.com","amy.d@astek.com"]
+{
+ "aaramburu@maharam.com": "2026-08-20",
+ "amy.d@astek.com": "2026-08-20",
+ "annalisa@elitis.us": "2026-08-20",
+ "ari@quintushome.com": "2026-08-20",
+ "bfoss@maharam.com": "2026-08-20",
+ "cathy.dy@thibautdesign.com": "2026-08-20",
+ "customerservice@wolfgordon.com": "2026-08-20",
+ "ddedic@momtex.com": "2026-08-20",
+ "fawn.bowen@romo.com": "2026-08-20",
+ "federico.contigiani@lincrusta.com": "2026-08-20",
+ "hbarragan@kneedlerfauchere.com": "2026-08-20",
+ "hmartinez@innovationsusa.com": "2026-08-20",
+ "jballard@phillipjeffries.com": "2026-08-20",
+ "jcarol@lbiboyd.com": "2026-08-20",
+ "jill@lbiboyd.com": "2026-08-20",
+ "karinkleintextiles@gmail.com": "2026-08-20",
+ "matt.schoffman@kravet.com": "2026-08-20",
+ "orders@wallquest.com": "2026-08-20",
+ "orders@yorkwall.com": "2026-08-20",
+ "polancol@oalusa.com": "2026-08-20",
+ "riverah@yorkwall.com": "2026-08-20",
+ "sales@sancarwallcovering.com": "2026-08-20",
+ "sample@mdcwall.com": "2026-08-20",
+ "samples@koroseal.com": "2026-08-20",
+ "sshortino@koroseal.com": "2026-08-20",
+ "therese@egg-and-dart.com": "2026-08-20"
+}
\ No newline at end of file
diff --git a/scripts/scheduled-run.mjs b/scripts/scheduled-run.mjs
index 5e7a8b9..93ecf70 100644
--- a/scripts/scheduled-run.mjs
+++ b/scripts/scheduled-run.mjs
@@ -302,7 +302,30 @@ const run = async () => {
// Recently-contacted suppression: vendors the human desk already emailed a "New Sample Request"
// for (harvested from info@ Sent into data/recently-contacted.json). Stops the sweep from
// duplicating what the team already sent manually — the whole point of the 2026-08-20 fix.
- const RECENT = new Set(readJSON('data/recently-contacted.json', []).map((e) => String(e).toLowerCase().trim()).filter(Boolean));
+ // TK-11409: this static file was a PERMANENT blocklist. Hand-written, last edited 2026-08-20,
+ // 26 addresses, nothing ever expiring — and it held the biggest accounts (Kravet, Thibaut,
+ // Osborne, York, WallQuest, Sancar, Innovations, MDC, Maharam...). So even after the Gmail query
+ // was corrected to match the chase subject, those vendors stayed suppressed forever by a snapshot
+ // nobody had looked at in three weeks. Same failure family as the rest of this ticket: a record
+ // taken once and trusted indefinitely.
+ // It is now a { address: 'YYYY-MM-DD' } map and entries EXPIRE after RECENT_DAYS. A bare-array
+ // file is still read (every entry treated as expired-unknown -> ignored) so an old copy or a
+ // hand-edit can't resurrect the permanent-blocklist behaviour.
+ const RECENT = new Set();
+ {
+ const raw = readJSON('data/recently-contacted.json', {});
+ const cutoff = new Date(Date.now() - RECENT_DAYS * 864e5);
+ let kept = 0, expired = 0;
+ if (Array.isArray(raw)) {
+ expired = raw.length; // undated legacy format: no evidence of recency, so it suppresses nothing
+ } else {
+ for (const [addr, when] of Object.entries(raw || {})) {
+ const d = new Date(when);
+ if (!isNaN(d) && d >= cutoff) { RECENT.add(String(addr).toLowerCase().trim()); kept++; } else expired++;
+ }
+ }
+ if (expired) console.log(`(static contact list: ${kept} still within ${RECENT_DAYS}d, ${expired} expired and no longer suppressing)`);
+ }
try { const live = await georgeRecentRecipients(RECENT_DAYS); for (const e of live) RECENT.add(e); if (live.size) console.log(`(anti-dup pool: ${live.size} recipient(s) emailed in last ${RECENT_DAYS}d — enforced on SEND, drafted-with-flag on DRAFT)`); } catch {}
const sent = [], skipped = [], needsConfirm = [], drafted = [], suppressed = [];
// TK-11409: make the two previously-SILENT draft-mode outcomes visible in the report.
← 17b5c5c auto-data-snapshot: 2026-09-10T12:25:41 (1 data files) — dat
·
back to Sample Followup Sweep
·
TK-11409: sent-poller stops pre-filling the 2nd-request slot d0bc2fd →