From 972cc992009eafa6ea8222b96a44adb4331e3e8e Mon Sep 17 00:00:00 2001 From: Tyler Date: Sat, 20 Jun 2026 12:37:31 -0600 Subject: [PATCH] docs: mark SP4 partial shipped (claim drawer); tick all plan checkboxes --- README.md | 32 ++- .../plans/2026-06-20-cyclone-claim-drawer.md | 201 +++++++++--------- 2 files changed, 131 insertions(+), 102 deletions(-) diff --git a/README.md b/README.md index da1550f..89a11af 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,7 @@ backup API). ## Roadmap -Sub-projects 2 and 3 are **shipped**. Next up: +Sub-projects 2, 3, and the first half of 4 are **shipped**. Next up: - **Sub-project 3 (shipped) — More 837P/835 features.** - **837P validation rules:** R034 enforces `REF*G1` on frequency-code @@ -142,10 +142,21 @@ Sub-projects 2 and 3 are **shipped**. Next up: builds a 270 from a JSON payload (subscriber, provider, payer, service type); `POST /api/eligibility/parse-271` ingests the response and returns structured `coverage_benefits`. -- **Sub-project 4 — Frontend features.** Per-claim detail drawer, batch - diff view, real-time streaming of NDJSON GET responses, advanced - filters (date range, multi-status, saved filter sets), keyboard-driven - navigation. +- **Sub-project 4 (partially shipped) — Frontend features.** + - **Per-claim detail drawer (shipped):** click any row on the Claims + page to open a side-panel drawer with the full claim context — + state + amount header, validation panel, service lines, diagnoses, + parties (billing provider, subscriber, payer), raw X12 segments, + matched remittance summary, and a vertical state-history timeline. + URL is synced (`?claim=...`) so links and back-button restore the + drawer. Keyboard nav: `j`/`k` move between claims, `esc` closes, + `?` opens the cheatsheet overlay. Skeleton + error + not-found + (404) states are all distinct. Powered by a new backend endpoint + `GET /api/claims/{claim_id}` that returns the full drawer payload + in a single round-trip. + - **Remaining SP4:** batch diff view, real-time streaming of NDJSON + GET responses, advanced filters (date range, multi-status, saved + filter sets). ### SP3 endpoints @@ -162,6 +173,17 @@ Sub-projects 2 and 3 are **shipped**. Next up: The UI gains a new **Acks** page (sidebar entry) that lists persisted ACKs and lets you download the regenerated 999 text. +### SP4 endpoints (claim drawer) + +- `GET /api/claims/{claim_id}` — full claim context for the drawer + payload: header fields, diagnoses, service lines, parties + (billing provider / subscriber / payer), validation result, raw + X12 segments, matched remittance summary (or `null`), and the + claim's state history (ordered newest-first). 404 with a structured + `{ "error": "Not found", "detail": "Claim {id} not found" }` body + when the claim doesn't exist — distinct from a transient fetch + failure so the UI can render a dedicated not-found state. + ## License No license file yet; this is internal-use software. Add a `LICENSE` file diff --git a/docs/superpowers/plans/2026-06-20-cyclone-claim-drawer.md b/docs/superpowers/plans/2026-06-20-cyclone-claim-drawer.md index 8ee4dfd..19f1120 100644 --- a/docs/superpowers/plans/2026-06-20-cyclone-claim-drawer.md +++ b/docs/superpowers/plans/2026-06-20-cyclone-claim-drawer.md @@ -66,11 +66,11 @@ src/index.css # +CSS variables for Modern palette TDD discipline: write tests first, confirm red, implement, confirm green. -- [ ] **Step 1: Add failing tests** in `backend/tests/test_store_claim_detail.py` -- [ ] **Step 2: Run tests to verify they fail** -- [ ] **Step 3: Implement `to_ui_claim_detail` mapper + `get_claim_detail` method** -- [ ] **Step 4: Run tests to verify they pass** -- [ ] **Step 5: Commit** +- [x] **Step 1: Add failing tests** in `backend/tests/test_store_claim_detail.py` +- [x] **Step 2: Run tests to verify they fail** +- [x] **Step 3: Implement `to_ui_claim_detail` mapper + `get_claim_detail` method** +- [x] **Step 4: Run tests to verify they pass** +- [x] **Step 5: Commit** ```bash git add backend/src/cyclone/store.py backend/tests/test_store_claim_detail.py @@ -93,11 +93,11 @@ git commit -m "feat(store): get_claim_detail returns full claim context with his - `test_get_claim_detail_state_history_includes_manual_match` — manual_match event appears in history - `test_get_claim_detail_matched_remit_inlines_summary` — when matched, summary fields are populated -- [ ] **Step 1: Add failing tests** in `backend/tests/test_api_claim_detail.py` -- [ ] **Step 2: Run tests to verify they fail** -- [ ] **Step 3: Add the endpoint** (mirror `parse_999` endpoint pattern; use existing `_claim_to_ui` helpers) -- [ ] **Step 4: Run tests to verify they pass** -- [ ] **Step 5: Commit** +- [x] **Step 1: Add failing tests** in `backend/tests/test_api_claim_detail.py` +- [x] **Step 2: Run tests to verify they fail** +- [x] **Step 3: Add the endpoint** (mirror `parse_999` endpoint pattern; use existing `_claim_to_ui` helpers) +- [x] **Step 4: Run tests to verify they pass** +- [x] **Step 5: Commit** ```bash git add backend/src/cyclone/api.py backend/tests/test_api_claim_detail.py @@ -112,8 +112,8 @@ git commit -m "feat(api): GET /api/claims/{claim_id} returns full claim context" Expected: 409 + ~8 new = ~417 pass + 1 skip. All green. -- [ ] **Step 1: Run the full backend suite, confirm green** -- [ ] **Step 2: Tag phase complete** (no commit unless changes; otherwise commit "test(sp4): phase 1 backend complete") +- [x] **Step 1: Run the full backend suite, confirm green** +- [x] **Step 2: Tag phase complete** (no commit unless changes; otherwise commit "test(sp4): phase 1 backend complete") ## Phase 2 — Frontend foundation @@ -126,11 +126,11 @@ Expected: 409 + ~8 new = ~417 pass + 1 skip. All green. The `ClaimDetail` type matches the JSON response shape from Task 2. Nested types: `Diagnosis`, `ServiceLine`, `Parties`, `Validation`, `MatchedRemittance`, `StateHistoryEvent`. -- [ ] **Step 1: Add `ClaimDetail` interface** to `src/types/index.ts` (in the "backend-aligned" block, snake_case to match API) -- [ ] **Step 2: Add `api.getClaimDetail(id)` method** to `src/lib/api.ts` (uses `apiFetch` helper if present) -- [ ] **Step 3: Add test** to `src/lib/api.test.ts` — happy path + 404 -- [ ] **Step 4: Run frontend tests + typecheck, confirm green** -- [ ] **Step 5: Commit** +- [x] **Step 1: Add `ClaimDetail` interface** to `src/types/index.ts` (in the "backend-aligned" block, snake_case to match API) +- [x] **Step 2: Add `api.getClaimDetail(id)` method** to `src/lib/api.ts` (uses `apiFetch` helper if present) +- [x] **Step 3: Add test** to `src/lib/api.test.ts` — happy path + 404 +- [x] **Step 4: Run frontend tests + typecheck, confirm green** +- [x] **Step 5: Commit** ```bash git add src/types/index.ts src/lib/api.ts src/lib/api.test.ts @@ -160,11 +160,11 @@ Behavior: - Caches for the drawer session so j/k navigation reuses prior fetches within ~30s - Returns 404 state as `{ isError: true, error: }` -- [ ] **Step 1: Add failing tests** — null id (no fetch), happy path, 404 -- [ ] **Step 2: Run tests, confirm red** -- [ ] **Step 3: Implement the hook** -- [ ] **Step 4: Run tests, confirm green** -- [ ] **Step 5: Commit** +- [x] **Step 1: Add failing tests** — null id (no fetch), happy path, 404 +- [x] **Step 2: Run tests, confirm red** +- [x] **Step 3: Implement the hook** +- [x] **Step 4: Run tests, confirm green** +- [x] **Step 5: Commit** ```bash git add src/hooks/useClaimDetail.ts src/hooks/useClaimDetail.test.ts @@ -194,11 +194,11 @@ Behavior: - Ignores keys when an input/textarea/contentEditable has focus - Cleans up listener on unmount or `enabled === false` -- [ ] **Step 1: Add failing tests** — fires onNext for "j", ignores when input focused, cleanup on unmount -- [ ] **Step 2: Run tests, confirm red** -- [ ] **Step 3: Implement the hook** -- [ ] **Step 4: Run tests, confirm green** -- [ ] **Step 5: Commit** +- [x] **Step 1: Add failing tests** — fires onNext for "j", ignores when input focused, cleanup on unmount +- [x] **Step 2: Run tests, confirm red** +- [x] **Step 3: Implement the hook** +- [x] **Step 4: Run tests, confirm green** +- [x] **Step 5: Commit** ```bash git add src/hooks/useDrawerKeyboard.ts src/hooks/useDrawerKeyboard.test.ts @@ -228,11 +228,11 @@ Behavior: - `close()` strips the param via `history.pushState` - Returns null `claimId` when no param is set -- [ ] **Step 1: Add failing tests** — reads URL on mount, open adds param, setClaimId replaces, close removes -- [ ] **Step 2: Run tests, confirm red** -- [ ] **Step 3: Implement the hook** (mock `window.history` in tests via vitest's `vi.stubGlobal`) -- [ ] **Step 4: Run tests, confirm green** -- [ ] **Step 5: Commit** +- [x] **Step 1: Add failing tests** — reads URL on mount, open adds param, setClaimId replaces, close removes +- [x] **Step 2: Run tests, confirm red** +- [x] **Step 3: Implement the hook** (mock `window.history` in tests via vitest's `vi.stubGlobal`) +- [x] **Step 4: Run tests, confirm green** +- [x] **Step 5: Commit** ```bash git add src/hooks/useDrawerUrlState.ts src/hooks/useDrawerUrlState.test.ts @@ -248,8 +248,8 @@ npm test -- --run Expected: 10 + 5 new = 15 frontend pass. -- [ ] **Step 1: Run typecheck + frontend tests, confirm green** -- [ ] **Step 2: Commit if any changes** +- [x] **Step 1: Run typecheck + frontend tests, confirm green** +- [x] **Step 2: Commit if any changes** ## Phase 3 — Frontend leaf components @@ -292,8 +292,8 @@ Add the CSS variables from spec §3.3 to `:root`: Also add the Inter Tight + JetBrains Mono font imports (Google Fonts CDN). -- [ ] **Step 1: Append the CSS variables + font import** -- [ ] **Step 2: Commit** +- [x] **Step 1: Append the CSS variables + font import** +- [x] **Step 2: Commit** ```bash git add src/index.css @@ -312,10 +312,10 @@ git commit -m "feat(frontend): Modern palette CSS variables + Inter Tight/JetBra **Error:** Takes `{ kind: "not_found" | "network"; onRetry?: () => void; onClose: () => void }`. Renders the appropriate message + buttons. -- [ ] **Step 1: Add failing tests** for both components -- [ ] **Step 2: Implement** (keep simple — these are placeholder UIs) -- [ ] **Step 3: Run tests, confirm green** -- [ ] **Step 4: Commit** +- [x] **Step 1: Add failing tests** for both components +- [x] **Step 2: Implement** (keep simple — these are placeholder UIs) +- [x] **Step 3: Run tests, confirm green** +- [x] **Step 4: Commit** ```bash git add src/components/ClaimDrawer/ClaimDrawerSkeleton.tsx src/components/ClaimDrawer/ClaimDrawerSkeleton.test.tsx src/components/ClaimDrawer/ClaimDrawerError.tsx src/components/ClaimDrawer/ClaimDrawerError.test.tsx @@ -336,10 +336,10 @@ Renders: - Total amount (right of badge): big number, mono - Close button (top-right): `Button` with X icon -- [ ] **Step 1: Add failing tests** — renders ID, state badge with right color, total, close callback -- [ ] **Step 2: Implement** -- [ ] **Step 3: Run tests, confirm green** -- [ ] **Step 4: Commit** +- [x] **Step 1: Add failing tests** — renders ID, state badge with right color, total, close callback +- [x] **Step 2: Implement** +- [x] **Step 3: Run tests, confirm green** +- [x] **Step 4: Commit** ```bash git add src/components/ClaimDrawer/ClaimDrawerHeader.tsx src/components/ClaimDrawer/ClaimDrawerHeader.test.tsx @@ -361,10 +361,10 @@ Renders: - Group errors by `rule` field with count (e.g., `R050_diagnosis_present (2)`) - List messages under each rule group -- [ ] **Step 1: Add failing tests** — empty state, errors only, warnings only, both, grouping -- [ ] **Step 2: Implement** -- [ ] **Step 3: Run tests, confirm green** -- [ ] **Step 4: Commit** +- [x] **Step 1: Add failing tests** — empty state, errors only, warnings only, both, grouping +- [x] **Step 2: Implement** +- [x] **Step 3: Run tests, confirm green** +- [x] **Step 4: Commit** ```bash git add src/components/ClaimDrawer/ValidationPanel.tsx src/components/ClaimDrawer/ValidationPanel.test.tsx @@ -384,10 +384,10 @@ Renders: - Table: line #, procedure (qualifier + code + modifiers), charge (mono, big), units, date - Empty state: "No service lines" muted text -- [ ] **Step 1: Add failing tests** — empty, single line, multiple lines; procedure formatting -- [ ] **Step 2: Implement** -- [ ] **Step 3: Run tests, confirm green** -- [ ] **Step 4: Commit** +- [x] **Step 1: Add failing tests** — empty, single line, multiple lines; procedure formatting +- [x] **Step 2: Implement** +- [x] **Step 3: Run tests, confirm green** +- [x] **Step 4: Commit** ```bash git add src/components/ClaimDrawer/ServiceLinesTable.tsx src/components/ClaimDrawer/ServiceLinesTable.test.tsx @@ -407,10 +407,10 @@ Renders: - Inline list of code (mono) + qualifier (when present) + description (when available via inline dict) - Empty state: "No diagnoses" muted text -- [ ] **Step 1: Add failing tests** — empty, single, multiple; qualifier shown when present -- [ ] **Step 2: Implement** -- [ ] **Step 3: Run tests, confirm green** -- [ ] **Step 4: Commit** +- [x] **Step 1: Add failing tests** — empty, single, multiple; qualifier shown when present +- [x] **Step 2: Implement** +- [x] **Step 3: Run tests, confirm green** +- [x] **Step 4: Commit** ```bash git add src/components/ClaimDrawer/DiagnosesList.tsx src/components/ClaimDrawer/DiagnosesList.test.tsx @@ -430,10 +430,10 @@ Renders: - 3 stacked cards (vertical on mobile, 3-col grid on desktop ≥768px) - Each card: label (10px uppercase), name (16px), NPI/member ID (mono), address when present -- [ ] **Step 1: Add failing tests** — all 3 cards; missing fields gracefully omitted -- [ ] **Step 2: Implement** -- [ ] **Step 3: Run tests, confirm green** -- [ ] **Step 4: Commit** +- [x] **Step 1: Add failing tests** — all 3 cards; missing fields gracefully omitted +- [x] **Step 2: Implement** +- [x] **Step 3: Run tests, confirm green** +- [x] **Step 4: Commit** ```bash git add src/components/ClaimDrawer/PartiesGrid.tsx src/components/ClaimDrawer/PartiesGrid.test.tsx @@ -453,10 +453,10 @@ Renders: - Native `
` element (collapsed by default) - When expanded: monospace pre-formatted list with segments on separate lines, elements joined by `*` -- [ ] **Step 1: Add failing tests** — collapsed by default, toggle expands, segment rendering -- [ ] **Step 2: Implement** -- [ ] **Step 3: Run tests, confirm green** -- [ ] **Step 4: Commit** +- [x] **Step 1: Add failing tests** — collapsed by default, toggle expands, segment rendering +- [x] **Step 2: Implement** +- [x] **Step 3: Run tests, confirm green** +- [x] **Step 4: Commit** ```bash git add src/components/ClaimDrawer/RawSegmentsPanel.tsx src/components/ClaimDrawer/RawSegmentsPanel.test.tsx @@ -477,10 +477,10 @@ Renders: - Card with: remit ID, total paid (big mono), status badge, received date - "View remittance →" link button that opens the remittance detail (use `window.location` or a navigate handler — keep simple for v1: `window.location.href = \`/remittances?id=${matchedRemittance.id}\`` or trigger an event) -- [ ] **Step 1: Add failing tests** — null returns nothing, populated renders all fields -- [ ] **Step 2: Implement** -- [ ] **Step 3: Run tests, confirm green** -- [ ] **Step 4: Commit** +- [x] **Step 1: Add failing tests** — null returns nothing, populated renders all fields +- [x] **Step 2: Implement** +- [x] **Step 3: Run tests, confirm green** +- [x] **Step 4: Commit** ```bash git add src/components/ClaimDrawer/MatchedRemitCard.tsx src/components/ClaimDrawer/MatchedRemitCard.test.tsx @@ -507,10 +507,10 @@ Renders: - Each row: kind (10px uppercase), ts (mono), optional remittance ID when present - Empty state: "No history events" muted -- [ ] **Step 1: Add failing tests** — empty, single, multiple; kind-color mapping -- [ ] **Step 2: Implement** -- [ ] **Step 3: Run tests, confirm green** -- [ ] **Step 4: Commit** +- [x] **Step 1: Add failing tests** — empty, single, multiple; kind-color mapping +- [x] **Step 2: Implement** +- [x] **Step 3: Run tests, confirm green** +- [x] **Step 4: Commit** ```bash git add src/components/ClaimDrawer/StateHistoryTimeline.tsx src/components/ClaimDrawer/StateHistoryTimeline.test.tsx @@ -536,9 +536,9 @@ export { ClaimDrawerSkeleton } from "./ClaimDrawerSkeleton"; export { ClaimDrawerError } from "./ClaimDrawerError"; ``` -- [ ] **Step 1: Create the barrel** -- [ ] **Step 2: Run typecheck + tests, confirm green** -- [ ] **Step 3: Commit** +- [x] **Step 1: Create the barrel** +- [x] **Step 2: Run typecheck + tests, confirm green** +- [x] **Step 3: Commit** ```bash git add src/components/ClaimDrawer/index.ts @@ -572,10 +572,10 @@ Uses shadcn `Sheet` (or `Dialog`) primitive. Behavior: - `onNext` / `onPrev`: derives next/prev claim IDs from the `claims` prop (find current index, +1 or -1, wrap), then calls `onNavigate(newId)` - `onToggleHelp`: passed through to the keyboard hook -- [ ] **Step 1: Add failing tests** — renders null when no claimId, skeleton on loading, error state on error, sections on success, j/k calls onNavigate with the correct next/prev id (including wrap), `?` calls onToggleHelp, ESC calls onClose -- [ ] **Step 2: Implement** — keep this component focused on orchestration; defer visual polish to leaf components -- [ ] **Step 3: Run tests, confirm green** -- [ ] **Step 4: Commit** +- [x] **Step 1: Add failing tests** — renders null when no claimId, skeleton on loading, error state on error, sections on success, j/k calls onNavigate with the correct next/prev id (including wrap), `?` calls onToggleHelp, ESC calls onClose +- [x] **Step 2: Implement** — keep this component focused on orchestration; defer visual polish to leaf components +- [x] **Step 3: Run tests, confirm green** +- [x] **Step 4: Commit** ```bash git add src/components/ClaimDrawer/ClaimDrawer.tsx src/components/ClaimDrawer/ClaimDrawer.test.tsx @@ -596,10 +596,10 @@ Wire-up: - Clicking the dimmed overlay or ESC closes (via `close()`) - Background list dims to 60% opacity when drawer is open (use a `useState` for `drawerOpen` or derive from `claimId`) -- [ ] **Step 1: Add failing tests** — click row opens drawer; deep link opens on mount; ESC closes; URL clears -- [ ] **Step 2: Wire up the page** -- [ ] **Step 3: Run tests, confirm green** -- [ ] **Step 4: Commit** +- [x] **Step 1: Add failing tests** — click row opens drawer; deep link opens on mount; ESC closes; URL clears +- [x] **Step 2: Wire up the page** +- [x] **Step 3: Run tests, confirm green** +- [x] **Step 4: Commit** ```bash git add src/pages/Claims.tsx src/pages/Claims.test.tsx @@ -620,10 +620,10 @@ Renders: - Lists shortcuts: `j` next, `k` prev, `↑`/`↓` same, `esc` close, `?` toggle help - Dismisses on any other key or click outside -- [ ] **Step 1: Add failing tests** — renders when open, hidden otherwise, dismiss on close -- [ ] **Step 2: Implement** -- [ ] **Step 3: Run tests, confirm green** -- [ ] **Step 4: Commit** +- [x] **Step 1: Add failing tests** — renders when open, hidden otherwise, dismiss on close +- [x] **Step 2: Implement** +- [x] **Step 3: Run tests, confirm green** +- [x] **Step 4: Commit** ```bash git add src/components/KeyboardCheatsheet/ @@ -640,8 +640,8 @@ npm run typecheck Expected: ~15 frontend, ~417 backend + 1 skip. All green. -- [ ] **Step 1: Run all checks** -- [ ] **Step 2: Commit if any changes** +- [x] **Step 1: Run all checks** +- [x] **Step 2: Commit if any changes** ## Phase 5 — Smoke + merge @@ -662,8 +662,8 @@ Per spec §3.8: 7. Kill servers 8. Commit empty: `git commit --allow-empty -m "smoke: end-to-end SP4 (claim drawer) flow passes"` -- [ ] **Step 1: Run the smoke** -- [ ] **Step 2: Commit** +- [x] **Step 1: Run the smoke** +- [x] **Step 2: Commit** ### Task 25: README + plan doc updates @@ -671,8 +671,8 @@ Per spec §3.8: - Modify: `README.md` — mark "Sub-project 4" partially shipped (only per-claim drawer); describe the new feature - Modify: `docs/superpowers/plans/2026-06-20-cyclone-claim-drawer.md` — tick all `[ ]` to `[x]` -- [ ] **Step 1: Update README + plan doc** -- [ ] **Step 2: Commit** +- [x] **Step 1: Update README + plan doc** +- [x] **Step 2: Commit** ```bash git add README.md docs/superpowers/plans/2026-06-20-cyclone-claim-drawer.md @@ -688,10 +688,10 @@ git commit -m "docs: mark SP4 partial shipped (claim drawer); tick all plan chec 5. `git worktree remove /Users/openclaw/dev/cyclone/.worktrees/claim-drawer` 6. `git branch -d claim-drawer` -- [ ] **Step 1: Verify worktree clean** -- [ ] **Step 2: Discard main's stale changes (if any)** -- [ ] **Step 3: Fast-forward merge to main** -- [ ] **Step 4: Remove worktree + delete branch** +- [x] **Step 1: Verify worktree clean** +- [x] **Step 2: Discard main's stale changes (if any)** +- [x] **Step 3: Fast-forward merge to main** +- [x] **Step 4: Remove worktree + delete branch** ## Test count targets @@ -702,6 +702,13 @@ git commit -m "docs: mark SP4 partial shipped (claim drawer); tick all plan chec | P2 end | 0 | +5 | 417 / 15 | | P3 end | 0 | +10 (one per leaf) | 417 / 25 | | P4 end | 0 | +5 (drawer + page + cheatsheet) | 417 / 30 | +| **Actual final** | **417 + 1 skip** | **124** | **417 / 124** | + +(Note: the frontend test count grew well past the conservative target — +every leaf component ended up with its own dedicated test file, and the +drawer root + Claims page wiring + keyboard cheatsheet each gained +their own integration suite. Net new from SP4: 114 frontend tests +across 14 files. Backend matched the +8 estimate exactly.) ## Risk reminders