Repository navigation
feat(aggregator): charges auto-matcher core — dedupe Plaid+Gmail charges, match to hub services (#1057) - #2113
Conversation
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 2 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 62dde64762
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const existing = clusters.find( | ||
| (cl) => | ||
| cl.amountUsd === candidate.amountUsd && | ||
| cl.normalized === normalized && | ||
| daysBetween(cl.first.at, candidate.at) <= DEDUPE_WINDOW_DAYS, |
There was a problem hiding this comment.
Preserve separate purchases from the same source
When two distinct Plaid transactions have the same merchant and amount within three days, this lookup merges them even though both are from Plaid. For example, two $20 OpenAI purchases on consecutive days, paid with different cards, produce only one $20 row; adding their Gmail alerts still leaves one row. The unconditional continue discards every additional observation after a source slot is occupied, silently understating charge evidence. Restrict cross-source matching to clusters whose slot for the incoming source is empty, preserving separate purchases and pairing their alerts one-to-one.
Useful? React with 👍 / 👎.
Queue task 2990 / issue #1057 — step 2+4 core of the charges auto-matcher (pure module first, collector wiring next).
What this adds
pm-stack/aggregator/src/charges-match.ts— pure, deterministic matcher:ChargeCandidatenormalization for both sources (Plaid transactions and Gmail receipt/card alerts share the shape: date, merchant, amount, method).*descriptors, id-like tokens (e.g.UC5DPA22Y4), filler (US,INC,.COM), and pure-digit tokens.Plaid, Plaid date/method win); Gmail-only rows labelledGmail alert.pm-stack/aggregator/test/charges-match.test.ts— 10 fixture tests covering dedupe, window edges, aliases, unmatched surfacing, and rerun determinism.Verified
transactions-getshape verified live for a 14-day window. Gmail connector connected.bun test test/charges-match.test.ts test/usage.test.ts— 31 pass. Files biome-formatted (treefmt-clean).tsc --noEmitin a fresh worktree reports only the pre-existing missing@types/bunin that worktree (no node_modules); no errors in the new files.Remaining for #1057 (task 2990 stays open, parked with this resume point)
scripts/collect-fleet-feed.ts: Plaid read + Gmail alert read for the period, candidate normalization, persisted classification state so unmatched charges surface exactly once, feedchargessection + attention surfacing.Refs #1057
Need help on this PR? Tag
@codesmith-botwith what you need.