| name | fraud-detection |
| description | Screen a Medicare/Medicaid claims corpus for fraud, waste, and abuse and produce ranked, fully-cited investigation referrals for an SIU / program-integrity team. Use when asked to run a fraud sweep, screen claims for FWA, find billing anomalies, or generate investigation referrals over a claims dataset. |
Fraud Detection — claims screening → cited investigation
Screens a Medicare/Medicaid claims corpus against the public rulebook (NCCI MUE, OIG LEIE,
CMS enrollment, PFS) and produces ranked, fully-cited investigation referrals for an SIU.
The skill orchestrates a three-tier investigation: a deterministic floor does the detection,
the model judges and narrates on top, and every dollar/rule allegation traces back to the floor.
Output framing
- "Indicators consistent with [scheme]," not "fraud." A pattern match doesn't establish intent
— that's a downstream investigative/legal determination. This is standard SIU language and the
framing the renderers use.
- Render for review. The skill writes packets to
$CLAUDE_HEALTHCARE_DATA/fraud-detection/out/; the payer's SIU workflow
decides what to do with them. The model does not send/publish on its own.
Inputs
- The payer's claims in
corpus.duckdb (canonical 6-table schema: claims-schema.sql). Getting
this is step 1 below — without it nothing else matters.
- Quarter (the NCCI/PFS rule set to cite against, e.g.
2026q3).
- Line of business (
medicare / medicaid).
Data root
All fetched/generated state lives outside the plugin install path (which is wiped on upgrade)
at ~/.claude/data/healthcare/fraud-detection/ — override the parent dir with
$CLAUDE_HEALTHCARE_DATA (each skill appends its own name). Below, data-cache/ and out/ are
subdirectories of $CLAUDE_HEALTHCARE_DATA/fraud-detection. Resolve it once at the start of a run:
export CLAUDE_HEALTHCARE_DATA="${CLAUDE_HEALTHCARE_DATA:-$HOME/.claude/data/healthcare}"
Steps
-
Get the payer's claims into corpus.duckdb. Open with: "Where do your adjudicated claims
live?" and follow ${CLAUDE_PLUGIN_ROOT}/skills/fraud-detection/LOAD-CLAIMS.md — it walks you
and the user from "I don't know" to a populated $CLAUDE_HEALTHCARE_DATA/fraud-detection/data-cache/corpus.duckdb. If they
already have a .duckdb with the canonical tables (schema:
${CLAUDE_PLUGIN_ROOT}/skills/fraud-detection/claims-schema.sql), use it directly.
Draft the brief (corpusDb path, quarter, line of business) and confirm scope.
-
Seed the public reference layer (first run / new quarter only). Detectors cite against
$CLAUDE_HEALTHCARE_DATA/fraud-detection/data-cache/reference/<quarter>/reference.duckdb. If that file is missing for the
requested quarter, fetch it now — this prints per-source ✓ name (size) progress as ~34 sources land:
node "${CLAUDE_PLUGIN_ROOT}/skills/fraud-detection/scripts/fetch-reference.js" 2026q3
node "${CLAUDE_PLUGIN_ROOT}/skills/fraud-detection/scripts/fetch-enrichment.js"
Requires unzip and pdftotext (poppler) on PATH; both ship with most distros / brew install poppler. Needs real network egress — if you see "Could not resolve host" for cms.gov / oig.hhs.gov,
the command sandbox is blocking it; re-run with sandbox disabled. Policy PDFs (NCCI manual, MLN articles) land under reference/<q>/policy/*.txt
for grep; everything keyed lands in reference.duckdb. Skip if already present. If a fetch fails
or a table is missing, see REFERENCE-DATA.md for source URLs and recovery.
-
Create the run directory. Each invocation lands in its own minute-stamped directory so prior
runs are preserved side-by-side. Every script honors FRAUD_OUT_DIR:
export FRAUD_OUT_DIR="$CLAUDE_HEALTHCARE_DATA/fraud-detection/out/run-$(date +%Y%m%d-%H%M)"
mkdir -p "$FRAUD_OUT_DIR"
echo
The inviolable line
The model adjudicates, explores, and narrates freely, but any dollar or rule allegation must trace
to a detect-stage deterministic recompute (the gate in scripts/gate.js). Adjudicate may dismiss
or downgrade a finding (with an auditable reason) — it never adds one or changes its dollars.
Synthesize narratives are separate, clearly-marked model output and never introduce a number the
floor did not compute.
Enrichment — local cached data (canonical), MCPs for interactive only
The deterministic pipeline reads enrichment from local cached files (scripts/fetch-enrichment.js
→ $CLAUDE_HEALTHCARE_DATA/fraud-detection/data-cache/enrichment/, loaded via scripts/enrichment.js) — no runtime auth, no drift, fully
reproducible. The healthcare plugin's bundled MCP servers (CMS Coverage / ICD-10 / NPI Registry) are
for interactive adjudicate/synthesize exploration only; the pipeline does not depend on them.
- ICD-10-CM — code validity / description (NLM Clinical Tables)
- CMS Coverage (LCD/NCD) — medical-necessity policy index; cached, feeds D4 adjudication
- NPI Registry — provider taxonomy/status
How it works (plugin layout)
- Entry skill — this file; orchestrates the workflow, never does the math.
- Workflow —
workflows/investigate.js (Claude Code dynamic Workflow): Detect → Adjudicate → Synthesize.
- Deterministic sweep —
scripts/screen.js <corpus.duckdb> <quarter> <lob> runs all detectors and
writes $FRAUD_OUT_DIR/referrals.json. Zero model calls.
- Detectors —
scripts/dNN-*.js (one deterministic module each, sharing the Finding shape).
- Pipeline —
scripts/pipeline.js (run → gate → roll up → rank → referrals.json).
- Citation gate —
scripts/gate.js (independently recomputes every cited number; uncited or
non-reproducing findings are dropped — "citation-or-zero").
- Reference data —
scripts/reference-data.js loads $CLAUDE_HEALTHCARE_DATA/fraud-detection/data-cache/reference/ (NCCI/MUE, LEIE, PFS,
enrollment), fetched by scripts/fetch-reference.js, versioned by date-of-service quarter.
- Enrichment —
scripts/enrichment.js loads $CLAUDE_HEALTHCARE_DATA/fraud-detection/data-cache/enrichment/, fetched by fetch-enrichment.js.
- Stage merge —
scripts/apply-stages.js (workflow return → referrals.adjudicated.json / .final.json).
- Renderers —
scripts/render-dashboard.js (→ index.html), render-packet.js, render-xlsx.js → $FRAUD_OUT_DIR/.
Every allegation cites a public rule with a value the gate independently recomputes, or it is dropped.