From 76e2eddd05f4ebfffea421f47a11a833e10ded1e Mon Sep 17 00:00:00 2001 From: Yashas Date: Wed, 16 Sep 2026 13:15:21 +0530 Subject: [PATCH] refactor: one front door MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Start Investigation is gone. The daily review is the only way a case is born — "she isn't asked" should not ship with a button for asking her. A person still steers Ava, but only about something she already found: Send Back to Ava carries the note. Removed the ask-a-question screen, route and ghost button; the case page's "request" card now says how the review came to exist (live, or a replay of a past morning) instead of echoing a question nobody typed. Backend counterpart: sm2/custom-apps/denials-investigator/09_one_front_door.sql. Co-Authored-By: Claude Fable 5.1 --- src/App.tsx | 2 - src/api/config.ts | 7 +-- src/layout/Shell.tsx | 9 ++-- src/screens/CaseScreen.tsx | 20 +++----- src/screens/NewInvestigationScreen.tsx | 71 -------------------------- src/screens/QueueScreen.tsx | 9 +--- 6 files changed, 15 insertions(+), 103 deletions(-) delete mode 100644 src/screens/NewInvestigationScreen.tsx diff --git a/src/App.tsx b/src/App.tsx index 47b30f9..f3f929b 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -4,7 +4,6 @@ import { Shell } from './layout/Shell'; import { Login } from './pages/Login'; import { QueueScreen } from './screens/QueueScreen'; import { CaseScreen } from './screens/CaseScreen'; -import { NewInvestigationScreen } from './screens/NewInvestigationScreen'; import { RunReviewScreen } from './screens/RunReviewScreen'; /** @@ -25,7 +24,6 @@ export function App() { }> } /> } /> - } /> } /> {/* Awaiting Review is the landing page, not "all cases": it is the queue with work in it, and the one the console exists to serve. */} diff --git a/src/api/config.ts b/src/api/config.ts index 6a8afe6..c3771be 100644 --- a/src/api/config.ts +++ b/src/api/config.ts @@ -30,8 +30,7 @@ export const DECISIONS_VIEW = 'dni-rv-ava-decisions'; // hardcoded: each activity's fields are read from view-service at open time. // --------------------------------------------------------------------------- export const ACT = { - REVIEW: 'dni-act-review', // INIT — the daily sweep. No question, no form. - START: 'dni-act-start', // INIT — a human asks a specific question + REVIEW: 'dni-act-review', // INIT — the daily sweep. The ONLY way a case is born. FINDINGS: 'dni-act-findings', // Ava NOTHING: 'dni-act-nothing', // Ava — a quiet morning; closes the case itself APPROVE: 'dni-act-approve', @@ -135,7 +134,9 @@ export const STAGE_ACTIONS: Record = { label: 'Send Back to Ava', roles: ['revenue_cycle_manager'], kind: 'secondary', - hint: 'She re-runs the investigation with your note', + // The only way a person asks Ava anything: in the context of something + // she already found. There is deliberately no "ask a question" door. + hint: 'She re-runs the review with your note', }, { activity: ACT.REJECT, label: 'Reject', roles: ['revenue_cycle_manager'], kind: 'danger' }, ], diff --git a/src/layout/Shell.tsx b/src/layout/Shell.tsx index 24f9dea..20fb3a9 100644 --- a/src/layout/Shell.tsx +++ b/src/layout/Shell.tsx @@ -1,5 +1,5 @@ import { NavLink, Outlet, useNavigate } from 'react-router-dom'; -import { LogOut, Radar, Search } from 'lucide-react'; +import { LogOut, Radar } from 'lucide-react'; import { useZino } from '../api/provider'; import { QUEUES, prettyRole } from '../api/config'; import { NorthlakeLockup } from '../components/NorthlakeLogo'; @@ -29,15 +29,12 @@ export function Shell() {
- {/* The sweep is the product; the question is the exception. */} + {/* The only way a case is born. Nobody asks Ava a question; she + decides what is worth a person's time. */} - {user && (
diff --git a/src/screens/CaseScreen.tsx b/src/screens/CaseScreen.tsx index a007dc4..2356aaa 100644 --- a/src/screens/CaseScreen.tsx +++ b/src/screens/CaseScreen.tsx @@ -54,7 +54,6 @@ export function CaseScreen() { const scanned = str(row?.scanned_summary); const flagged = num(row?.flagged_count); const kind = str(row?.finding_kind); - const isSweep = scanned !== '' || flagged != null || !str(row?.question); const quiet = flagged === 0 && !str(row?.summary); const trace = useQuery(() => client.avaTrace(String(id)), [id], true, aiOwned ? 4000 : 0); @@ -102,12 +101,9 @@ export function CaseScreen() { )}

- {str(row.question) || - (isSweep - ? `Daily review — every payer, department and front desk${ - str(row.review_as_of) ? `, as of ${str(row.review_as_of).slice(0, 10)}` : '' - }. Nobody asked; Ava decides what is worth your time.` - : `Scope: ${str(row.scope) || 'all payers and departments'}`)} + Daily review — every payer, department and front desk + {str(row.review_as_of) ? `, as of ${str(row.review_as_of).slice(0, 10)}` : ''}. + Nobody asked; Ava decides what is worth your time.

@@ -172,15 +168,13 @@ export function CaseScreen() { {/* ---------------- the ask, in full ---------------- */} - +
-
-

Ask Ava

-

- Hand her a question about denials. She investigates and comes back with a cause, a - dollar figure and a recommendation for you to approve. -

-
- - -
- - - -
-

What she will do

-
    -
  1. Reconcile the claims data against the finance report before trusting it
  2. -
  3. Baseline the denial rate, then slice by payer, reason code, department and desk
  4. -
  5. Find where the change concentrates and when it started
  6. -
  7. Look for the cause in the payer's own policy bulletins
  8. -
  9. Count what is still inside the appeal window and what it is worth
  10. -
-

- - Read-only against {LAKEHOUSE.platform} · {LAKEHOUSE.catalog}.{LAKEHOUSE.schema} -

-
-
-
- - { - setOpen(false); - navigate('/q/investigating'); - }} - activityUid={ACT.START} - title="Start an investigation" - subtitle="Ava picks this up as soon as you submit" - submitLabel="Send to Ava" - onDone={(r) => { - if (r.instance_id) navigate(`/c/${r.instance_id}`); - }} - /> -
- ); -} diff --git a/src/screens/QueueScreen.tsx b/src/screens/QueueScreen.tsx index 78f6cce..3f4dc9b 100644 --- a/src/screens/QueueScreen.tsx +++ b/src/screens/QueueScreen.tsx @@ -79,15 +79,12 @@ function CaseCard({ row, onOpen }: { row: Row; onOpen: () => void }) { const summary = str(row.summary); const atRisk = num(row.amount_at_risk); const recoverable = num(row.recoverable_amount); - const scope = str(row.scope); - const question = str(row.question); const aiOwned = state === 'Investigating' || state === 'Monitoring'; const scanned = str(row.scanned_summary); const flagged = num(row.flagged_count); const kind = str(row.finding_kind); // A sweep that found nothing: closed by Ava herself, never on a desk. const quiet = flagged === 0 && !summary; - const isSweep = scanned !== '' || flagged != null; return ( @@ -99,7 +96,6 @@ function CaseCard({ row, onOpen }: { row: Row; onOpen: () => void }) { {quiet ? 'Nothing to report' : state} - {isSweep && daily review} {kind && FINDING_KIND[kind] && {FINDING_KIND[kind]}} {aiOwned ? ( @@ -117,10 +113,7 @@ function CaseCard({ row, onOpen }: { row: Row; onOpen: () => void }) {

- {summary || - (quiet ? scanned : '') || - question || - (isSweep ? 'Ava is reviewing every payer, department and desk…' : `Scope: ${scope || 'all payers'}`)} + {summary || (quiet ? scanned : '') || 'Ava is reviewing every payer, department and desk…'}

{(atRisk || recoverable) && (