← back to Sample Followup Sweep
sample-followup: coverage-reconciliation canary (silent-skip false-green safety net) — TK-12117
1d2b68097ad7d99518c6747a9595955a91f92718 · 2026-09-23 16:20:15 -0700 · Steve Abrams
READ-ONLY scripts/coverage-reconcile.mjs queries live FileMaker for the true
outstanding population (two-read vid+letterSent join) and reconciles it against
the sweep's own bucketing (lib/sweep.js reconcileCoverage). A row outstanding in
FM but in NO sweep bucket = LEAKED = FAIL; never PASS on 'it ran'. Emits
PASS/WARN/FAIL + latest.json. Ships test/coverage-reconcile.test.cjs (5 asserts,
incl injected-leak FAIL) + a --self-test seam. First live run FOUND 4 real
empty-vid silent skips (FAIL). launchd install drafted to pending-approval (gated).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
A data/coverage-reconcile/latest.jsonA launchd/com.steve.sample-followup-coverage-reconcile.plistM lib/sweep.jsA scripts/coverage-reconcile.mjsA test/coverage-reconcile.test.cjs
Diff
commit 1d2b68097ad7d99518c6747a9595955a91f92718
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Wed Sep 23 16:20:15 2026 -0700
sample-followup: coverage-reconciliation canary (silent-skip false-green safety net) — TK-12117
READ-ONLY scripts/coverage-reconcile.mjs queries live FileMaker for the true
outstanding population (two-read vid+letterSent join) and reconciles it against
the sweep's own bucketing (lib/sweep.js reconcileCoverage). A row outstanding in
FM but in NO sweep bucket = LEAKED = FAIL; never PASS on 'it ran'. Emits
PASS/WARN/FAIL + latest.json. Ships test/coverage-reconcile.test.cjs (5 asserts,
incl injected-leak FAIL) + a --self-test seam. First live run FOUND 4 real
empty-vid silent skips (FAIL). launchd install drafted to pending-approval (gated).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
data/coverage-reconcile/latest.json | 52 +++++++++
....steve.sample-followup-coverage-reconcile.plist | 49 +++++++++
lib/sweep.js | 62 ++++++++++-
scripts/coverage-reconcile.mjs | 118 +++++++++++++++++++++
test/coverage-reconcile.test.cjs | 69 ++++++++++++
5 files changed, 349 insertions(+), 1 deletion(-)
diff --git a/data/coverage-reconcile/latest.json b/data/coverage-reconcile/latest.json
new file mode 100644
index 0000000..9b68ae3
--- /dev/null
+++ b/data/coverage-reconcile/latest.json
@@ -0,0 +1,52 @@
+{
+ "verdict": "FAIL",
+ "status": "FAIL",
+ "window": "07/25/2026...09/13/2026",
+ "population": 98,
+ "accounted": 94,
+ "covered": 81,
+ "uncovered": 13,
+ "leakedCount": 4,
+ "reconciles": true,
+ "runStale": false,
+ "buckets": {
+ "chaseable": 0,
+ "suppressed14d": 59,
+ "needsConfirm": 13,
+ "guardSuppressed": 14,
+ "noVendorMap": 0,
+ "noChase": 8
+ },
+ "leaked": [
+ {
+ "vid": "",
+ "sku": "DWTT70793",
+ "entered": "07/30/2026",
+ "mfr": "T10973",
+ "why": "empty vid — sweep drops it before grouping (silent skip)"
+ },
+ {
+ "vid": "",
+ "sku": "DWLC1059",
+ "entered": "08/21/2026",
+ "mfr": "23003",
+ "why": "empty vid — sweep drops it before grouping (silent skip)"
+ },
+ {
+ "vid": "",
+ "sku": "GLM9116",
+ "entered": "09/08/2026",
+ "mfr": "SLO1-White Iris",
+ "why": "empty vid — sweep drops it before grouping (silent skip)"
+ },
+ {
+ "vid": "",
+ "sku": "DWPN100994",
+ "entered": "09/08/2026",
+ "mfr": "PI-KOTOR-SPRUCE",
+ "why": "empty vid — sweep drops it before grouping (silent skip)"
+ }
+ ],
+ "ts": "2026-09-23T23:18:45.212Z",
+ "skill": "sample-followup-coverage-reconcile"
+}
\ No newline at end of file
diff --git a/launchd/com.steve.sample-followup-coverage-reconcile.plist b/launchd/com.steve.sample-followup-coverage-reconcile.plist
new file mode 100644
index 0000000..0d0909c
--- /dev/null
+++ b/launchd/com.steve.sample-followup-coverage-reconcile.plist
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<!--
+ TK-12117 — Coverage-reconciliation canary (READ-ONLY). Runs `node scripts/coverage-reconcile.mjs`
+ daily at 07:45 (just AFTER the 7:00 Tue-Fri sweep) so the run-marker freshness check is meaningful.
+ Writes latest.json to a fleet-health skill dir so fleet-health-rollup globs it.
+ READ-ONLY: FileMaker reads only (FM_READONLY=1), no send, never passes --self-test.
+
+ Install (Steve — GATED, scheduled-job install):
+ mkdir -p ~/.claude/skills/sample-followup-coverage-reconcile/data
+ cp ~/Projects/sample-followup-sweep/launchd/com.steve.sample-followup-coverage-reconcile.plist ~/Library/LaunchAgents/
+ launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.steve.sample-followup-coverage-reconcile.plist
+ Uninstall:
+ launchctl bootout gui/$(id -u)/com.steve.sample-followup-coverage-reconcile
+-->
+<plist version="1.0">
+<dict>
+ <key>Label</key>
+ <string>com.steve.sample-followup-coverage-reconcile</string>
+ <key>ProgramArguments</key>
+ <array>
+ <string>/opt/homebrew/bin/node</string>
+ <string>/Users/macstudio3/Projects/sample-followup-sweep/scripts/coverage-reconcile.mjs</string>
+ </array>
+ <key>WorkingDirectory</key>
+ <string>/Users/macstudio3/Projects/sample-followup-sweep</string>
+ <key>EnvironmentVariables</key>
+ <dict>
+ <key>PATH</key>
+ <string>/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
+ <key>COVERAGE_DATA_DIR</key>
+ <string>/Users/macstudio3/.claude/skills/sample-followup-coverage-reconcile/data</string>
+ </dict>
+ <key>StartCalendarInterval</key>
+ <array>
+ <dict><key>Weekday</key><integer>2</integer><key>Hour</key><integer>7</integer><key>Minute</key><integer>45</integer></dict>
+ <dict><key>Weekday</key><integer>3</integer><key>Hour</key><integer>7</integer><key>Minute</key><integer>45</integer></dict>
+ <dict><key>Weekday</key><integer>4</integer><key>Hour</key><integer>7</integer><key>Minute</key><integer>45</integer></dict>
+ <dict><key>Weekday</key><integer>5</integer><key>Hour</key><integer>7</integer><key>Minute</key><integer>45</integer></dict>
+ <dict><key>Weekday</key><integer>6</integer><key>Hour</key><integer>9</integer><key>Minute</key><integer>0</integer></dict>
+ </array>
+ <key>RunAtLoad</key>
+ <false/>
+ <key>StandardOutPath</key>
+ <string>/Users/macstudio3/Projects/sample-followup-sweep/out/coverage-reconcile.log</string>
+ <key>StandardErrorPath</key>
+ <string>/Users/macstudio3/Projects/sample-followup-sweep/out/coverage-reconcile.log</string>
+</dict>
+</plist>
diff --git a/lib/sweep.js b/lib/sweep.js
index 21c2a8d..ce118ce 100644
--- a/lib/sweep.js
+++ b/lib/sweep.js
@@ -1,4 +1,5 @@
'use strict';
+const { slugForVid, normVid } = require('./slug-aliases.cjs'); // TK-12117 coverage reconciliation
// Phase 1 — Sweep.
// Given a vendor's requested-sample rows, split them into the follow-up set,
// an escalation set (already 2nd-requested), and skipped (with reasons).
@@ -81,4 +82,63 @@ function suppressChase(enteredDate, siblings = []) {
return { suppress: false, reason: null };
}
-module.exports = { sweep, ageDays, suppressChase };
+// TK-12117 (Steve false-green doctrine): COVERAGE RECONCILIATION. Pure function — given ALL
+// in-window 'Report for old memo samples' records + the contacts map + the recently-emailed set,
+// bucket EVERY outstanding row (Date WP Sample Sent empty, non-empty entered) into exactly one
+// disposition and ASSERT the sweep would account for all of them. A row that is outstanding in
+// FileMaker but would appear in NO sweep bucket (e.g. the sweep drops empty-vid rows before
+// grouping) = LEAKED = a silent skip = FAIL. This makes "ran successfully while chasing only a
+// fraction" impossible: PASS requires the FM population to be fully accounted AND every row in an
+// actioned bucket — never PASS merely because the script ran.
+// buckets: chaseable | suppressed14d | needsConfirm | guardSuppressed | noVendorMap | noChase
+// actioned (covered) = chaseable + suppressed14d + guardSuppressed + noChase
+// uncovered (accounted but NOT actually chased) = noVendorMap + needsConfirm -> WARN
+// leaked (outstanding but in no bucket) -> FAIL
+// records: array of { fieldData: {...} } (FileMaker shape) OR plain field objects (fixtures).
+function reconcileCoverage(records, { contacts = {}, recentSet = new Set(), runStale = false } = {}) {
+ const norm = (v) => String(v == null ? '' : v).replace(/[\r\n]/g, '').trim();
+ const fd = (r) => (r && r.fieldData) ? r.fieldData : (r || {});
+ // siblings by sku (all in-window records) for the never-false-chase guard
+ const siblings = {};
+ for (const r of records) {
+ const d = fd(r); const sku = norm(d['combo sku']); if (!sku) continue;
+ (siblings[sku] = siblings[sku] || []).push({ entered: norm(d['today for client']), wpSampleSent: norm(d['Date WP Sample Sent']), letterSent: norm(d['Date Sample Request Letter Sent']) });
+ }
+ const b = { chaseable: [], suppressed14d: [], needsConfirm: [], guardSuppressed: [], noVendorMap: [], noChase: [] };
+ const leaked = [];
+ let population = 0;
+ for (const r of records) {
+ const d = fd(r);
+ const wp = norm(d['Date WP Sample Sent']);
+ const entered = norm(d['today for client']);
+ if (wp !== '' || entered === '') continue; // only OUTSTANDING in-window rows are the denominator
+ population++;
+ const sku = norm(d['combo sku']);
+ const vid = normVid(d.vid);
+ const tag = { vid, sku, entered, mfr: norm(d['Mfr Pattern']) };
+ if (!vid) { leaked.push({ ...tag, why: 'empty vid — sweep drops it before grouping (silent skip)' }); continue; }
+ const g = suppressChase(entered, siblings[sku] || []);
+ if (g.suppress) { b.guardSuppressed.push({ ...tag, reason: g.reason }); continue; }
+ const c = contacts[slugForVid(vid)];
+ if (!c) { b.noVendorMap.push(tag); continue; }
+ if (c.disposition === 'no-chase') { b.noChase.push(tag); continue; }
+ const email = c.sample_email || c.main_email;
+ if (!email || !c.account_number) { b.noVendorMap.push({ ...tag, why: 'incomplete contact (no email/account)' }); continue; }
+ const recips = String(email).toLowerCase().split(/[,;]\s*/).map((s) => s.trim()).filter(Boolean);
+ if (recips.some((e) => recentSet.has(e))) { b.suppressed14d.push(tag); continue; }
+ if (c.needs_confirm) { b.needsConfirm.push(tag); continue; }
+ b.chaseable.push(tag);
+ }
+ const counts = Object.fromEntries(Object.entries(b).map(([k, v]) => [k, v.length]));
+ const accounted = Object.values(counts).reduce((s, n) => s + n, 0);
+ const covered = counts.chaseable + counts.suppressed14d + counts.guardSuppressed + counts.noChase;
+ const uncovered = counts.noVendorMap + counts.needsConfirm;
+ const reconciles = (accounted + leaked.length === population);
+ let verdict;
+ if (leaked.length > 0 || !reconciles) verdict = 'FAIL'; // silent-skip / reconciliation broke
+ else if (uncovered > 0 || runStale) verdict = 'WARN'; // real outstanding not actually chased, or run missed
+ else verdict = 'PASS'; // fully accounted + every row actioned
+ return { verdict, status: verdict, population, accounted, covered, uncovered, leaked, reconciles, counts, buckets: b };
+}
+
+module.exports = { sweep, ageDays, suppressChase, reconcileCoverage };
diff --git a/scripts/coverage-reconcile.mjs b/scripts/coverage-reconcile.mjs
new file mode 100644
index 0000000..bd8a9f0
--- /dev/null
+++ b/scripts/coverage-reconcile.mjs
@@ -0,0 +1,118 @@
+#!/usr/bin/env node
+// TK-12117 — COVERAGE-RECONCILIATION CANARY (READ-ONLY).
+// Steve's false-green doctrine: never PASS on "it ran" — assert coverage against an INDEPENDENT
+// source. This queries LIVE FileMaker for the true outstanding population in the active window and
+// reconciles it against the sweep's own bucketing (lib/sweep.js reconcileCoverage). A row that is
+// outstanding in FileMaker but would appear in NO sweep bucket = LEAKED (silent skip) = FAIL.
+// PASS = population fully accounted AND every outstanding row in an ACTIONED bucket + run fresh
+// WARN = uncovered-but-accounted rows (no-vendor-map / needs-confirm) > 0, OR the Tue-Fri run missed
+// FAIL = FM unreadable / reconciliation broke / leaked rows
+// Writes data/latest.json every run (fleet-health-rollup vocab: top-level verdict AND status).
+// Usage:
+// node scripts/coverage-reconcile.mjs # live run
+// node scripts/coverage-reconcile.mjs --self-test # injected-leak fixture must go FAIL (never in the plist)
+import { readFileSync, writeFileSync, mkdirSync, existsSync, statSync, readdirSync } from 'node:fs';
+import { homedir } from 'node:os'; import { join, dirname } from 'node:path'; import { fileURLToPath } from 'node:url';
+import { createRequire } from 'node:module'; import http from 'node:http';
+const require = createRequire(import.meta.url);
+const __dir = dirname(fileURLToPath(import.meta.url)); const ROOT = join(__dir, '..');
+const { reconcileCoverage } = require(join(ROOT, 'lib', 'sweep.js'));
+
+const SELF_TEST = process.argv.includes('--self-test');
+const MIN_AGE = 10, MAX_AGE = Number(process.env.MAX_AGE) || 60;
+const DATA_DIR = process.env.COVERAGE_DATA_DIR || join(ROOT, 'data', 'coverage-reconcile');
+const pad = (n) => String(n).padStart(2, '0');
+const fmt = (d) => `${pad(d.getMonth() + 1)}/${pad(d.getDate())}/${d.getFullYear()}`;
+const readJSON = (f, d) => { try { return JSON.parse(readFileSync(f, 'utf8')); } catch { return d; } };
+
+function writeLatest(obj) {
+ mkdirSync(DATA_DIR, { recursive: true });
+ writeFileSync(join(DATA_DIR, 'latest.json'), JSON.stringify({ ...obj, ts: new Date().toISOString(), skill: 'sample-followup-coverage-reconcile' }, null, 2));
+}
+
+// --- SELF-TEST seam (guarded; the launchd plist must NEVER pass --self-test) ---
+if (SELF_TEST) {
+ const contacts = { fabr: { sample_email: 'customers@fabricut.com', account_number: 'On File' } };
+ const row = (vid, sku) => ({ fieldData: { vid, 'combo sku': sku, 'today for client': '09/10/2026', 'Date WP Sample Sent': '', 'Date Sample Request Letter Sent': '', 'Mfr Pattern': 'P' } });
+ const r = reconcileCoverage([row('FABR', 'A'), row('', 'LEAK')], { contacts });
+ console.log(`[SELF-TEST] injected empty-vid leak -> verdict=${r.verdict} leaked=${r.leaked.length} (expect FAIL/>=1)`);
+ process.exit(r.verdict === 'FAIL' && r.leaked.length >= 1 ? 0 : 1);
+}
+
+// --- recently-emailed set: recently-contacted.json (<=14d) + best-effort live Gmail (read-only) ---
+function recentSet() {
+ const set = new Set();
+ const raw = readJSON(join(ROOT, 'data', 'recently-contacted.json'), {});
+ const cutoff = new Date(Date.now() - 14 * 864e5);
+ if (!Array.isArray(raw)) for (const [addr, when] of Object.entries(raw)) { const d = new Date(when); if (!isNaN(d) && d >= cutoff) set.add(String(addr).toLowerCase().trim()); }
+ return set;
+}
+async function mergeGmailRecent(set) {
+ try {
+ const g = (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 = g('GEORGE_BASIC_AUTH'); if (!auth.includes(':')) auth = 'admin:' + g('GEORGE_BASIC_AUTH_PASS');
+ auth = 'Basic ' + Buffer.from(auth).toString('base64');
+ const q = encodeURIComponent('in:sent subject:"Sample Follow-Up — Outstanding Memos" -subject:"Re:" newer_than:14d');
+ await new Promise((res) => { const req = http.request({ host: '127.0.0.1', port: 9850, path: `/api/messages?account=info&maxResults=100&q=${q}`, method: 'GET', headers: { Authorization: auth } }, (r) => { let b = ''; r.on('data', (d) => b += d); r.on('end', () => { try { const j = JSON.parse(b); for (const m of (j.messages || [])) for (const e of String(m.to || '').match(/[\w.+-]+@[\w.-]+\.\w+/g) || []) set.add(e.toLowerCase()); } catch {} res(); }); }); req.on('error', () => res()); req.end(); });
+ } catch {}
+ return set;
+}
+
+// --- run-marker freshness: on a Tue-Fri, a REAL scheduled run (mode DRAFT/SEND) must have a marker today ---
+function runStaleToday() {
+ const now = new Date(); const dow = now.getDay();
+ if (![2, 3, 4, 5].includes(dow)) return false; // not a scheduled run-day -> not stale
+ const marker = join(ROOT, 'data', 'runs', `scheduled-${fmt(now).replace(/\//g, '-')}.json`);
+ const rep = readJSON(marker, null);
+ if (rep && (rep.mode === 'DRAFT' || rep.mode === 'SEND')) return false; // real run fired today
+ // fallback: scheduled-send.log written today
+ try { const s = statSync(join(ROOT, 'out', 'scheduled-send.log')); const d = new Date(s.mtime); if (d.toDateString() === now.toDateString()) return false; } catch {}
+ return true;
+}
+
+async function main() {
+ // FileMaker read-only — ALL in-window 'Report for old memo samples' records (independent denominator).
+ let records;
+ try {
+ 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 hi = new Date(); hi.setDate(hi.getDate() - MIN_AGE);
+ const lo = new Date(); lo.setDate(lo.getDate() - MAX_AGE);
+ const win = `${fmt(lo)}...${fmt(hi)}`;
+ // Two-read join (recordId is stable across layouts, one WALLPAPER2 table): A = 'REPORT ON SAMPLES
+ // ORDERED' has vid + combo sku + entered + Date WP Sample Sent; B = 'Report for old memo samples'
+ // has Date Sample Request Letter Sent. Neither has BOTH, so join B's letterSent onto A by recordId.
+ const A = (await fm.findRecords('WALLPAPER', 'REPORT ON SAMPLES ORDERED', { 'today for client': win }, { limit: 3000 })).records || [];
+ const B = (await fm.findRecords('WALLPAPER', 'Report for old memo samples', { 'today for client': win }, { limit: 3000 })).records || [];
+ const letterByRid = {}; for (const r of B) letterByRid[String(r.recordId)] = (r.fieldData['Date Sample Request Letter Sent'] || '');
+ records = A.map((r) => ({ fieldData: { ...r.fieldData, 'Date Sample Request Letter Sent': letterByRid[String(r.recordId)] || '' } }));
+ var window = win;
+ } catch (e) {
+ writeLatest({ verdict: 'FAIL', status: 'FAIL', error: `FileMaker unreadable: ${e.message}`, population: null, note: 'NOT-MEASURED — cannot verify coverage' });
+ console.error(`FAIL — FileMaker unreadable: ${e.message}`);
+ process.exit(1);
+ }
+ const contacts = readJSON(join(ROOT, 'data', 'contacts.json'), {});
+ const set = await mergeGmailRecent(recentSet());
+ const runStale = runStaleToday();
+ const r = reconcileCoverage(records, { contacts, recentSet: set, runStale });
+
+ const out = { verdict: r.verdict, status: r.status, window, population: r.population, accounted: r.accounted,
+ covered: r.covered, uncovered: r.uncovered, leakedCount: r.leaked.length, reconciles: r.reconciles,
+ runStale, buckets: r.counts, leaked: r.leaked.slice(0, 20) };
+ writeLatest(out);
+
+ console.log(`Coverage reconciliation — window ${window}`);
+ console.log(` population (outstanding in FM): ${r.population}`);
+ console.log(` covered/actioned: ${r.covered} (chaseable ${r.counts.chaseable} + suppressed14d ${r.counts.suppressed14d} + guardSuppressed ${r.counts.guardSuppressed} + noChase ${r.counts.noChase})`);
+ console.log(` uncovered (accounted, NOT chased): ${r.uncovered} (noVendorMap ${r.counts.noVendorMap} + needsConfirm ${r.counts.needsConfirm})`);
+ console.log(` leaked (outstanding, NO bucket): ${r.leaked.length}`);
+ if (r.leaked.length) r.leaked.slice(0, 10).forEach((x) => console.log(` ⚠ LEAK vid=${JSON.stringify(x.vid)} sku=${x.sku} — ${x.why}`));
+ console.log(` reconciles (accounted+leaked==population): ${r.reconciles} run-stale: ${runStale}`);
+ console.log(` VERDICT: ${r.verdict}`);
+ process.exit(r.verdict === 'FAIL' ? 1 : 0);
+}
+main();
diff --git a/test/coverage-reconcile.test.cjs b/test/coverage-reconcile.test.cjs
new file mode 100644
index 0000000..065195e
--- /dev/null
+++ b/test/coverage-reconcile.test.cjs
@@ -0,0 +1,69 @@
+'use strict';
+// TK-12117 coverage-reconciliation negative test (ship-with-a-negative-test doctrine).
+// Proves the canary goes RED on an injected fault (an outstanding row in NO bucket = silent skip)
+// and GREEN only when the population is fully accounted + actioned.
+const assert = require('node:assert');
+const { reconcileCoverage } = require('../lib/sweep');
+
+// A resolvable vendor (chaseable) + a no-chase vendor as the "known good" contacts.
+const contacts = {
+ fabr: { name: 'Fabricut', sample_email: 'customers@fabricut.com', account_number: 'On File' },
+ spn: { name: 'Spoonflower', disposition: 'no-chase' },
+ wat: { name: 'Watts 1874', sample_email: 'sophie@watts1874.co.uk', account_number: 'On File', needs_confirm: true },
+};
+const row = (vid, sku, entered, wp = '', letter = '') => ({ fieldData: {
+ vid, 'combo sku': sku, 'today for client': entered, 'Date WP Sample Sent': wp, 'Date Sample Request Letter Sent': letter, 'Mfr Pattern': 'P-' + sku } });
+
+// 1. NEGATIVE — inject an outstanding row with EMPTY vid (the sweep drops it before grouping) → LEAKED → FAIL
+{
+ const recs = [ row('FABR', 'DWFC1', '09/10/2026'), row('', 'DWLEAK1', '09/11/2026') ];
+ const r = reconcileCoverage(recs, { contacts });
+ assert.equal(r.verdict, 'FAIL', `1 injected empty-vid leak must FAIL, got ${r.verdict}`);
+ assert.ok(r.leaked.length >= 1, '1 leaked row must be reported');
+ assert.equal(r.population, 2, '1 population must count both outstanding rows');
+ console.log(`(1) PASS — injected empty-vid leak -> FAIL (leaked=${r.leaked.length}, pop=${r.population})`);
+}
+
+// 2. CLEAN — a single resolvable, not-recently-emailed, not-needs-confirm row → PASS
+{
+ const recs = [ row('FABR', 'DWFC2', '09/10/2026') ];
+ const r = reconcileCoverage(recs, { contacts, recentSet: new Set() });
+ assert.equal(r.verdict, 'PASS', `2 clean must PASS, got ${r.verdict}`);
+ assert.equal(r.counts.chaseable, 1, '2 must be chaseable');
+ assert.equal(r.leaked.length, 0, '2 no leak');
+ console.log(`(2) PASS — clean chaseable row -> PASS (chaseable=${r.counts.chaseable})`);
+}
+
+// 3. UNCOVERED — an outstanding row whose vid has NO contact (no-vendor-map) → accounted but not chased → WARN
+{
+ const recs = [ row('NOSUCHVID', 'DWX3', '09/10/2026') ];
+ const r = reconcileCoverage(recs, { contacts });
+ assert.equal(r.verdict, 'WARN', `3 no-vendor-map must WARN, got ${r.verdict}`);
+ assert.equal(r.counts.noVendorMap, 1, '3 must be noVendorMap');
+ assert.equal(r.leaked.length, 0, '3 accounted, not leaked');
+ console.log(`(3) PASS — no-vendor-map row -> WARN (uncovered=${r.uncovered})`);
+}
+
+// 4. RUN-STALE — clean population but the scheduled run did not fire on a run-day → WARN
+{
+ const recs = [ row('FABR', 'DWFC4', '09/10/2026') ];
+ const r = reconcileCoverage(recs, { contacts, runStale: true });
+ assert.equal(r.verdict, 'WARN', `4 run-stale must WARN, got ${r.verdict}`);
+ console.log('(4) PASS — clean population but run missed on run-day -> WARN');
+}
+
+// 5. GUARD/RECENT reconcile — arrived-dup guard + recently-emailed both count as ACTIONED (covered) → PASS
+{
+ const recs = [
+ row('FABR', 'DWFC5', '09/08/2026'), // outstanding
+ row('FABR', 'DWFC5', '09/08/2026', '09/14/2026'), // arrived same-date twin -> guard suppress
+ row('WAT', 'DWW5', '09/10/2026'), // needs_confirm vendor BUT recently emailed -> suppressed14d (covered)
+ ];
+ const r = reconcileCoverage(recs, { contacts, recentSet: new Set(['sophie@watts1874.co.uk']) });
+ assert.equal(r.counts.guardSuppressed, 1, '5 arrived twin -> guardSuppressed');
+ assert.equal(r.counts.suppressed14d, 1, '5 recently-emailed -> suppressed14d (covered, not needsConfirm WARN)');
+ assert.equal(r.verdict, 'PASS', `5 all actioned must PASS, got ${r.verdict}`);
+ console.log('(5) PASS — guard-suppressed + recently-emailed both actioned -> PASS');
+}
+
+console.log('\nALL COVERAGE-RECONCILE ASSERTIONS PASSED');
← 473c034 sample-followup: resolve MAJ (Majilite) + BRAND (Brand McKen
·
back to Sample Followup Sweep
·
auto-data-snapshot: 2026-09-23T16:24:32 (2 data files) — dat b9f7fd7 →