From 1db33ef2fa26b082273e03ed372b96aa9a2bf261 Mon Sep 17 00:00:00 2001 From: Tyler Date: Sat, 20 Jun 2026 18:46:24 -0600 Subject: [PATCH] =?UTF-8?q?docs(sp6):=20README=20=E2=80=94=20Inbox=20secti?= =?UTF-8?q?on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/README.md b/README.md index 0f04602..50baec6 100644 --- a/README.md +++ b/README.md @@ -128,6 +128,46 @@ backoff schedule on error is `1s → 2s → 4s → 8s → 16s → 30s` capped. | ---------------------------- | ------- | ------------------------------------------------------- | | `CYCLONE_TAIL_HEARTBEAT_S` | `15` | Idle heartbeat interval (seconds). Lower it for tests. | +## Inbox + +`/inbox` is the working surface. Four lanes, dark by default (Ticker Tape +aesthetic): + +- **Rejected** — claims whose 999 set-level response was R or E. Re-submit in bulk. +- **Candidates** — remits whose CLP-claim-id didn't match exactly; each one shows its top scored claim. One-click manual match or dismiss. +- **Unmatched** — claims still waiting for a remit, and remits with no candidates above the threshold. +- **Done today** — terminal state transitions in the last 24 hours. + +The page subscribes to the SP5 claim and remittance tail streams +(`/api/claims/stream` and `/api/remittances/stream`); a new `item` +event refetches the lane payload (debounced ~250ms). When a 999 +parses and rejects claims, the inbox reflects the new +**Rejected** rows within a fraction of a second. + +### Inbox endpoints + +| Method | Path | Notes | +| ------ | --------------------------------------------- | ---------------------------------------------------------------- | +| GET | `/api/inbox/lanes` | All four lanes in one call. | +| POST | `/api/inbox/candidates/{remit_id}/match` | Manual match. `409` if the claim state moved out from under us. | +| POST | `/api/inbox/candidates/dismiss` | `{pairs: [{claim_id, remit_id}]}`. Session-scoped. | +| POST | `/api/inbox/rejected/resubmit` | `{claim_ids: [...]}`. `200` with `conflicts` for non-rejected. | +| GET | `/api/inbox/export.csv?lane=` | Streams CSV of the lane's rows. | + +### Scoring + +4-field weighted (sum = 100): + +| Field | Weight | Rule | +| ----------------------- | ------ | ------------------------------------------------------------- | +| Patient control number | 40 | Exact match, normalized (case + leading zeros). | +| Service date | 25 | Linear decay over ±3 days. | +| Charge amount | 20 | Linear decay over ±10%. | +| Provider NPI | 15 | Exact match. Missing → 0. | + +Tiers: **strong** (≥75, full opacity, Match enabled), **weak** +(50–74, dimmed), **hidden** (<50, not surfaced). + ## Persistence Parsed batches, claims, remittances, matches, and activity events are