transaction-deduplicator
Detects and removes duplicate transactions across overlapping bank, credit-card, and brokerage statement imports using a stable composite key (account_id, date ±1d, amount_cents, description_normalized). Emits a list of new transactions to commit, a list of suppressed duplicates with their reasons, and a list of suspicious near-duplicates that need human review. Use when ingesting financial statements that may overlap prior drops, merging multiple export sources for the same account, or when user mentions duplicate transactions, deduping a transaction file, or reconciling overlapping statements.
What this skill does
# Transaction Deduplicator
## Table of Contents
- [Overview](#overview)
- [Input contract](#input-contract)
- [The dedupe key](#the-dedupe-key)
- [Workflow](#workflow)
- [Near-duplicate handling](#near-duplicate-handling)
- [Output contract](#output-contract)
- [Guardrails](#guardrails)
## Overview
Statement drops often overlap. A January statement covers December 15 → January 14; the December statement covers November 15 → December 14; the same December 15 transaction appears in both. This skill identifies those duplicates without losing legitimate same-day same-amount same-merchant repeat charges (e.g., two coffees in one day).
## Input contract
The caller provides:
- `incoming` — array of newly extracted transactions: `{date, post_date, account_id, amount_cents, description_raw, source}`.
- `existing` — array of transactions already in the store with the same fields plus `id`.
## The dedupe key
A duplicate is identified by the tuple:
```
(account_id, abs(amount_cents), description_normalized, |date_a - date_b| <= 1 day)
```
- `description_normalized` uses the same normalization as the categorizer (uppercase, strip vendor codes, strip geo, collapse spaces, drop dates).
- The 1-day window absorbs `date` vs `post_date` mismatches between two sources.
- `abs(amount_cents)` allows a refund matched against the original purchase to NOT be considered a duplicate (different sign). The composite key uses signed amount.
Use **signed** `amount_cents`. Refunds (opposite sign) are never duplicates of purchases.
## Workflow
```
Dedupe Progress:
- [ ] Step 1: Index existing transactions by (account_id, signed_amount, normalized_desc)
- [ ] Step 2: For each incoming, look up the index
- [ ] Step 3: Filter index hits by date proximity (≤ 1 day)
- [ ] Step 4: If no hit, mark as new
- [ ] Step 5: If exactly one hit, mark as duplicate of that id
- [ ] Step 6: If multiple hits, run the multi-instance same-day rule
- [ ] Step 7: Surface near-duplicates (different amount or desc) for review
```
### Step 1 — Index
Build `existing_by_key[(account_id, amount_cents, description_normalized)] = [tx, …]`.
### Step 2 — Lookup
For each incoming transaction, compute its key tuple and look up the bucket.
### Step 3 — Date proximity filter
For each candidate in the bucket, keep only those with `|incoming.date − candidate.date| ≤ 1 day`. Use `min(date, post_date)` on each side if `post_date` exists.
### Step 4 — No hit
Mark `decision: "new"`. The bookkeeper will append it to `transactions.json`.
### Step 5 — Exactly one hit
Mark `decision: "duplicate"` and link `duplicate_of: <existing_id>`. Do not import.
### Step 6 — Multiple hits (legitimate same-day repeats)
When the existing store already has N transactions with the identical key on the same day, and the incoming batch contains M transactions with the same key on that day:
- If `M ≤ N` → all incoming considered duplicates of existing ones (1:1 pairing in date order).
- If `M > N` → the first N incoming are duplicates; the remaining `M − N` are new transactions (legitimate same-day repeat charges, e.g., two coffees, gas-station pre-auth + final).
This rule preserves real repeat charges while still suppressing overlap-import duplicates.
### Step 7 — Near-duplicate review
A *near-duplicate* shares everything except amount or description and is within 1 day. These commonly arise when:
- A pending charge ($45.00) finalizes at a slightly different amount ($45.83) — keep the final, drop the pending.
- The merchant string changes mid-cycle ("AMAZON.COM*ABC123" → "AMZN Mktp US").
Emit these to `review[]` with both records side-by-side and a suggested action: `keep_incoming_drop_existing | keep_existing_drop_incoming | keep_both | merge`.
## Near-duplicate handling
Compute a similarity score on near-misses:
- Amount delta: 1.0 if equal, 0.9 if within $1 or 2%, 0.5 if within $5 or 10%, else 0.0.
- Description Jaccard on token sets: 0.0–1.0.
- Date proximity: 1.0 same day, 0.7 within 1 day, 0.4 within 3 days.
`near_dup_score = 0.4*amount + 0.4*description + 0.2*date`.
Surface for review when `0.7 ≤ near_dup_score < 0.95`. Above `0.95` is treated as duplicate; below `0.7` is treated as independent.
## Output contract
```json
{
"new": [
{ "id": "tx_20260115_017", "decision": "new" }
],
"duplicates": [
{
"incoming_index": 4,
"decision": "duplicate",
"duplicate_of": "tx_20251220_003",
"reason": "exact key match within 1 day window"
}
],
"review": [
{
"incoming_index": 12,
"matched_existing_id": "tx_20260108_005",
"near_dup_score": 0.86,
"diff": {
"amount_cents": [-4500, -4583],
"description_raw": ["AMAZON PENDING", "AMZN MKTP US*AB12CD"]
},
"suggested_action": "keep_incoming_drop_existing",
"rationale": "incoming is the finalized charge (post_date set, definite merchant code)"
}
],
"summary": {
"incoming_total": 142,
"new_count": 96,
"duplicate_count": 44,
"review_count": 2
}
}
```
## Guardrails
- **Sign matters.** Never collapse a refund and a purchase by absolute value. Use signed amount in the key.
- **One-day window only.** Wider windows produce false positives across pay cycles.
- **Same-account only.** Never dedupe across accounts. A $50 transfer out of checking and a $50 deposit into savings are two records, not one duplicate.
- **Preserve raw description in review.** Show both `description_raw` strings to the human; do not show the normalized form.
- **Idempotency.** Running the dedupe on the same input twice produces the same output. The skill never mutates `existing`.
- **Audit.** For every suppressed duplicate, log `duplicate_of` so the user can trace why a transaction did not appear in the new import.
Related in Code Review
gstack
IncludedFast headless browser for QA testing and site dogfooding. Navigate pages, interact with elements, verify state, diff before/after, take annotated screenshots, test responsive layouts, forms, uploads, dialogs, and capture bug evidence. Use when asked to open or test a site, verify a deployment, dogfood a user flow, or file a bug with screenshots. (gstack)
startup-due-diligence
IncludedLegal due diligence review for seed-stage and Series A startups (US, Delaware C-Corp focus). Supports both investor and founder perspectives. Capabilities include: (1) Interactive document review and issue spotting; (2) Document request list generation; (3) Cap table and SAFE/convertible note analysis; (4) Red flag identification with severity ratings; (5) Diligence report generation. TRIGGERS: due diligence, DD, startup investment, cap table review, Series A, seed round, investor diligence, legal review startup, SAFE analysis, convertible note, 409A, founder vesting.
interview-master
IncludedThis skill should be used when the user asks to "generate interview questions", "prepare for interview", "optimize resume", "conduct mock interview", "analyze git commits for resume", "generate resume from code", "review my resume", or mentions interview preparation, career assistance, or extracting project experience from git history. Provides comprehensive interview and career development guidance for both job seekers and interviewers.
fix-issue
IncludedFixes GitHub issues using parallel analysis agents for root cause investigation, code exploration, and regression detection. Reads issue context from gh CLI, searches codebase and memory for related patterns, generates a fix with tests, and links the resolution back to the issue via PR. Includes prevention analysis to avoid recurrence. Use when debugging errors, resolving regressions, fixing bugs, or triaging issues.
sf-apex
IncludedGenerates and reviews Salesforce Apex code with 150-point scoring. TRIGGER when: user writes, reviews, or fixes Apex classes, triggers, test classes, batch/queueable/schedulable jobs, or touches .cls/.trigger files. DO NOT TRIGGER when: LWC JavaScript (use sf-lwc), Flow XML (use sf-flow), SOQL-only queries (use sf-soql), or non-Salesforce code.
swift-development
IncludedComprehensive Swift development for building, testing, and deploying iOS/macOS applications. Use when Claude needs to: (1) Build Swift packages or Xcode projects from command line, (2) Run tests with XCTest or Swift Testing framework, (3) Manage iOS simulators with simctl, (4) Handle code signing, provisioning profiles, and app distribution, (5) Format or lint Swift code with SwiftFormat/SwiftLint, (6) Work with Swift Package Manager (SPM), (7) Implement Swift 6 concurrency patterns (async/await, actors, Sendable), (8) Create SwiftUI views with MVVM architecture, (9) Set up Core Data or SwiftData persistence, or any other Swift/iOS/macOS development tasks.