← back to Sample Followup Sweep
test/sent-stamp-retry.test.js
130 lines
'use strict';
// TK-12320: a sent follow-up whose stamp was skipped / zero must be retried; a stamped one must not;
// and the chase date written is the message's SEND date, never the pass date. No FM, no network.
const assert = require('node:assert/strict');
const path = require('node:path');
const { pathToFileURL } = require('node:url');
(async () => {
const core = await import(pathToFileURL(path.join(__dirname, '../scripts/sent-stamp-core.mjs')).href);
const NOW = new Date(2026, 8, 26, 9, 0, 0).getTime(); // 09/26/2026 local
const SENT_1838 = new Date(2026, 8, 16, 8, 15, 0).getTime(); // 09/16/2026 local
const SENT_VAH = new Date(2026, 8, 13, 0, 5, 0).getTime(); // 09/13/2026 local
const SENT_KRA = new Date(2026, 8, 24, 12, 0, 0).getTime();
const longAgo = new Date(NOW - 86400e3).toISOString(); // past any backoff
const emailVid = core.buildEmailVid(
[{ slug: '1838', vid: '1838 WALLCOVERINGS' }, { slug: 'vahallan', vid: 'VAH' }, { slug: 'kravet', vid: 'KRA' }],
{ '1838': { sample_email: 'scott.myer@gmail.com' }, vahallan: { main_email: 'info@vahallan.com' }, kravet: { sample_email: 'matt.schoffman@kravet.com' } });
const msgs = [
{ id: 'm1838', to: '"scott.myer" <scott.myer@gmail.com>', internalDate: String(SENT_1838) },
{ id: 'mvah', to: 'info <info@vahallan.com>', internalDate: String(SENT_VAH) },
{ id: 'mkra', to: 'Matt <matt.schoffman@kravet.com>', internalDate: String(SENT_KRA) },
{ id: 'mnew', to: 'nobody@unknown.example', internalDate: String(NOW) },
];
const ledger = {
m1838: { vids: ['1838 WALLCOVERINGS'], stamped: 0, patterns: [], at: longAgo }, // poisoned stamped:0
mvah: { skip: 'no vid for recipient', to: 'info@vahallan.com' }, // poisoned skip (legacy: no timestamps)
mkra: { vids: ['KRA'], stamped: 2, patterns: ['A', 'B'], at: longAgo }, // terminal success
};
const stampCalls = [];
const deps = {
emailVid,
getBody: async id => `letter ${id}`,
stamp: async (vids, body, win, sentOn) => { stampCalls.push({ vids, body, win, sentOn }); return { stamped: ['X-1'], failed: 0 }; },
};
const r = await core.runPass({ msgs, ledger, now: NOW, dry: false, retrySecs: 900, minAgeDays: 10, maxAgeDays: 60, deps });
// (a) stamped:0 and skip entries ARE re-processed
const byBody = Object.fromEntries(stampCalls.map(c => [c.body, c]));
assert.ok(byBody['letter m1838'], '(a) stamped:0 entry must be re-processed');
assert.ok(byBody['letter mvah'], '(a) skip entry must be re-processed once its recipient maps');
assert.equal(r.ledger.m1838.stamped, 1);
assert.equal(r.ledger.m1838.recovered_from, 'stamped:0');
assert.equal(r.ledger.mvah.recovered_from, 'skip: no vid for recipient');
assert.equal(r.ledger.m1838.attempts, 2, 'history kept: attempts counts the prior try');
console.log('(a) PASS — stamped:0 and skip entries re-processed; attempts/recovered_from recorded');
// (b) stamped>=1 is NOT re-processed, and its ledger entry is untouched
assert.ok(!byBody['letter mkra'], '(b) terminal stamped>=1 entry must NOT be re-processed');
assert.deepEqual(r.ledger.mkra, ledger.mkra);
console.log('(b) PASS — stamped>=1 entry skipped and left intact');
// (c) stamp date = message send date, not today; window anchored on the send date too
assert.equal(byBody['letter m1838'].sentOn, '09/16/2026', '(c) 1838 must stamp its send date');
assert.equal(byBody['letter mvah'].sentOn, '09/13/2026', '(c) Vahallan must stamp its send date');
assert.notEqual(byBody['letter m1838'].sentOn, core.fmt(new Date(NOW)));
assert.equal(byBody['letter m1838'].win, '07/18/2026...09/06/2026');
assert.equal(r.ledger.m1838.sent_on_source, 'internalDate');
console.log('(c) PASS — chase date = send date (09/16, 09/13), not today (09/26)');
// unmapped recipient: ledgered as skip, NOT terminal, reported once
assert.deepEqual(r.unmapped, ['nobody@unknown.example']);
assert.equal(core.isTerminal(r.ledger.mnew), false);
assert.equal(r.ledger.mnew.attempts, 1);
// backoff: an immediate second pass does not re-query FM for the still-unmapped skip
stampCalls.length = 0;
const r2 = await core.runPass({ msgs, ledger: r.ledger, now: NOW + 30e3, dry: false, retrySecs: 900, minAgeDays: 10, maxAgeDays: 60, deps });
assert.equal(stampCalls.length, 0, 'terminal entries skipped; unmapped one in backoff');
assert.equal(r2.changed, false, 'no ledger churn inside the backoff window');
// …but after the backoff it is retried and picks up a newly-added mapping
const emailVid2 = core.buildEmailVid([{ slug: 'u', vid: 'UNK' }], { u: { sample_email: 'nobody@unknown.example' } });
const r3 = await core.runPass({ msgs, ledger: r.ledger, now: NOW + 901e3, dry: false, retrySecs: 900, minAgeDays: 10, maxAgeDays: 60, deps: { ...deps, emailVid: emailVid2 } });
assert.equal(r3.ledger.mnew.stamped, 1);
assert.equal(r3.ledger.mnew.attempts, 2);
console.log('(d) PASS — backoff suppresses churn; retry after backoff picks up a new mapping');
// oldest send first: the earlier letter owns the chase date
const order = [];
await core.runPass({ msgs: [msgs[2], msgs[1], msgs[0]], ledger: {}, now: NOW, dry: true, retrySecs: 900, minAgeDays: 10, maxAgeDays: 60,
deps: { ...deps, stamp: async (v, body) => { order.push(body); return { stamped: [] }; } } });
assert.deepEqual(order, ['letter mvah', 'letter m1838', 'letter mkra'], 'must process oldest send first');
// covered-only is NOT finished (a sibling letter item may not be in FM yet)
assert.equal(core.isTerminal({ vids: ['X'], stamped: 0, covered: 1, failed: 0 }), false);
assert.equal(core.isTerminal({ vids: ['X'], stamped: 0, covered: 0, failed: 0 }), false);
// an older send in backoff is pulled forward when a newer send to the same recipient is due,
// so the older letter still owns the chase date
{
const older = { id: 'old', to: 'a@v.com', internalDate: String(SENT_VAH) };
const newer = { id: 'new', to: 'A <a@v.com>', internalDate: String(SENT_KRA) };
const ev = core.buildEmailVid([{ slug: 'v', vid: 'V' }], { v: { sample_email: 'a@v.com' } });
const seenOrder = [];
const led = { old: { vids: ['V'], stamped: 0, last_try: new Date(NOW - 60e3).toISOString() } }; // in backoff
await core.runPass({ msgs: [newer, older], ledger: led, now: NOW, dry: false, retrySecs: 900, minAgeDays: 10, maxAgeDays: 60,
deps: { emailVid: ev, getBody: async id => id, stamp: async (v, body, w, sentOn) => { seenOrder.push(`${body}@${sentOn}`); return { stamped: [] }; } } });
assert.deepEqual(seenOrder, ['old@09/13/2026', 'new@09/24/2026'], 'older backoff send must run before the newer one');
}
// failed FM commit is NOT terminal even with stamped>=1
assert.equal(core.isTerminal({ stamped: 2, failed: 1 }), false);
// send-date fallbacks
assert.equal(core.sendDateOf({ date: 'Wed, 16 Sep 2026 08:15:00 -0700' }, NOW).source, 'date-header');
assert.equal(core.sendDateOf({}, NOW).source, 'fallback-today');
// a fetch-failed metadata row is ignored, not ledgered as a skip
const r4 = await core.runPass({ msgs: [{ id: 'bad', error: 'fetch-failed' }], ledger: {}, now: NOW, dry: false, retrySecs: 900, minAgeDays: 10, maxAgeDays: 60, deps });
assert.equal(r4.ledger.bad, undefined);
// a failed body fetch is not an outcome: nothing ledgered, nothing stamped
const r6 = await core.runPass({ msgs: [msgs[0]], ledger: {}, now: NOW, dry: false, retrySecs: 900, minAgeDays: 10, maxAgeDays: 60, deps: { ...deps, getBody: async () => null } });
assert.equal(r6.ledger.m1838, undefined);
// dry run never writes the ledger
const r5 = await core.runPass({ msgs, ledger, now: NOW, dry: true, retrySecs: 900, minAgeDays: 10, maxAgeDays: 60, deps });
assert.equal(r5.changed, false);
assert.deepEqual(r5.ledger, ledger);
console.log('(e) PASS — failed commits retried, date fallbacks, fetch-failed ignored, dry never writes');
// contact whose vendor is absent from fleet.json still maps via the slug-derived vid (Phillip Jeffries)
const aliases = require('../lib/slug-aliases.cjs');
const pjMap = core.buildEmailVid([], { pj: { sample_email: 'jballard@phillipjeffries.com' } }, { slugAliases: aliases.SLUG_ALIASES, slugForVid: aliases.slugForVid });
assert.deepEqual([...pjMap['jballard@phillipjeffries.com']], ['PJ']);
assert.deepEqual(core.buildEmailVid([], { pj: { sample_email: 'jballard@phillipjeffries.com' } })['jballard@phillipjeffries.com'], undefined);
console.log('(f) PASS — contact-only vendor (PJ) maps via slug-derived vid');
// NEGATIVE: the pre-fix rule ("any ledger entry suppresses") would have left 1838/Vahallan unstamped
const oldRule = e => !!e;
assert.equal(oldRule(ledger.m1838) && oldRule(ledger.mvah), true, 'old rule suppresses both poisoned sends');
assert.equal(core.shouldProcess(ledger.m1838, { now: NOW, retrySecs: 900 }).go, true);
console.log('sent-stamp-retry: ALL PASS');
})().catch(e => { console.error('FAIL:', e.message); process.exit(1); });