Skip to content

Live (part 4) — notify on match SUGGESTION + MISALIGNMENT

Goal

Part 4 of T-037. (a) New notifyMatchSuggestion producer for ambiguous / new-vendor / no-match cases (today only console.logged) so misses surface for QA. (b) Wire the misalignment/integrity alerts (notifyDataIntegrity / integrityEmail) to the matchers — honors [[feedback_no_silent_fixes]] (detect + notify, never silently correct).

Optional extras (dormant infra, same system — fold here or split later)

  • Resend webhook handler pages/api/webhooks/resend.ts (bounce/complaint) — stub, no logic.
  • Overdue-invoice cron /api/cron/check-overdue-invoices.ts — doesn't exist.
  • Verify RESEND_API_KEY set in PROD Vercel (gates all email).

Log

  • 2026-06-14 created (T-037 split, owner).

Decision log

2026-07-09 — routed to Accounting (Diagnostics) (owner-confirmed)

  • ✅ Read AGENTS.md. Owner confirmation (2026-07-09, verbatim): "T-041 for Accounting (Diagnostics) it is". Scope note from the 2026-07-09 backlog review: the core (match-SUGGESTION producer + misalignment alerts) is untouched and real; the "dormant extras" (Resend bounce webhook + delivery log) are carved out to T-162 P3 (User Management) — do not build them here. Queue behind the agent's active T-156/T-157/T-158 cluster; sibling re-scoped tasks T-038 + T-040 are the same producer family and also theirs.
  • Source: EOP Local Assistance (fork) · session edb0abc7-6373-449b-8e31-379fd38d391b

2026-07-10 — BUILT + SHIPPED (owner: "proceed") — status → done

  • ✅ Read AGENTS.md · checked the board by scope (no dup — T-162 owns consumption/preferences; the dormant extras are its P3 per the 2026-07-09 carve-out and were NOT built here) · tracking T-041.
  • Source: Accounting (Diagnostics) · https://claude.ai/code/session_01G58Y71noihrYCDEDMexmea
  • (a) Suggestions surface: new notifyMatchSuggestion producer + a NEW notification type match_suggestion (topic books), registered across the full taxonomy (type union, labels, topic map, TYPE_META, bell + inbox icon/color maps — the exhaustive Record<NotificationType,…> pattern makes tsc enforce completeness). Severity info (advisory queue: a human should look, nothing is wrong yet). Wired from the two EVENT-driven hooks (tx sync + invoice upload); the engine's per-suggestion detail strings are already self-contained.
  • Noise controls (why not everywhere): suggestions are DERIVED fresh per run and never persisted (owner design), so the Refresh-button rescanMatching — which re-derives the same suggestions every click — stays silent per its own documented no-noise contract; and per-batch suggestion notifications cap at 10 (the T-040 digest carries the full count).
  • (b) Misalignment alerts: engine FAILURES now fire notifyDataIntegrity (warning → also emails; watchdog-exempt in the preference engine): all three engine catch-blocks on the tx-sync path + the invoice-upload path — which previously could throw through the seam; it now swallows LOUDLY (notify + note), honoring both the no-silent-fixes rule and the seam contract ("hooks may never fail the create"). The missing-defaultGl throw in applyVendorLink is exactly the case this catches.
  • Carve-out honored: no Resend webhook, no delivery log, no preference/consumption work — T-162 P3 / User Management. Coordination note left on T-162: match_suggestion is a new row their matrix picks up automatically from TYPE_META.
  • Verification: 6 new tests (matchSuggestionNotify.test.ts): per-suggestion notify on both event paths; the 10-cap; rescan silence (behavioral, not just static); engine-throw → data-integrity alert on both paths with the hook surviving. Suite 663/663; unfiltered tsc clean.
  • Commit SHAs (append-only): this ship commit (T-041 in subject; merged via PR).
  • Deploy: pending (main 🟡🟡 manual).
  • Blast radius: notification volume + one new NotificationType (match_suggestion — UM's matrix/inbox pick it up from the taxonomy maps). Engine behavior change: an invoice-upload matcher crash no longer propagates to the create seam (was caught there anyway; now notified).