fix: re-check verdict comes from the decision, and renders as labelled rows

'Within baseline' was re-derived by the console from two rates — a 0% rate on
a mostly-pending window read as recovery. The badge now follows the activity
Ava chose (Confirm Recovery closes the case; Flag Still Elevated does not),
and the four-line re-check summary (since approval / actions / rate / verdict)
renders as rows like the review coverage.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Yashas 2026-09-17 13:46:44 +05:30
parent f86a87af38
commit 35d4d97504
2 changed files with 23 additions and 8 deletions

View File

@ -95,12 +95,15 @@ export function Verdict({
/** What was covered, as rows of short facts — not a paragraph. Ava writes it
* as labelled lines; older cases wrote prose, which falls back to sentence
* bullets so nothing renders as a wall of text. */
function WorkStatement({ text }: { text: string }) {
function WorkStatement({ text, heading = 'Review coverage', bare = false }: { text: string; heading?: string; bare?: boolean }) {
const rows = workStatement(text);
const TONE: Record<string, string> = { FOUND: 'text-warn', WATCHED: 'text-muted', CLEAR: 'text-good', REVIEWED: 'text-ink' };
const TONE: Record<string, string> = {
FOUND: 'text-warn', WATCHED: 'text-muted', CLEAR: 'text-good', REVIEWED: 'text-ink',
'SINCE APPROVAL': 'text-ink', ACTIONS: 'text-ink', RATE: 'text-ink', VERDICT: 'text-warn',
};
return (
<div className="mt-3 border-t border-ai-edge/60 pt-3">
<p className="text-[11px] font-semibold tracking-wide text-faint uppercase">Review coverage</p>
<div className={bare ? '' : 'mt-3 border-t border-ai-edge/60 pt-3'}>
{heading && <p className="text-[11px] font-semibold tracking-wide text-faint uppercase">{heading}</p>}
{rows ? (
<dl className="mt-2 grid gap-y-2 text-[13px] sm:grid-cols-[9.5rem_1fr] sm:gap-x-4">
{rows.map((r) => (
@ -269,24 +272,31 @@ export function Recheck({ row }: { row: Row }) {
const current = num(row.current_rate);
const baseline = num(row.baseline_rate);
const recovered = num(row.recovered_amount);
const better = current != null && baseline != null && current - baseline <= 2;
// The verdict is the decision she made, not a rate comparison the console
// re-derives: Confirm Recovery closes the case, Flag Still Elevated sends it
// back for a person. A low rate on a mostly-pending window is not recovery.
const confirmed = str(row.current_state_name) === 'Closed';
return (
<Card
title="Re-check result"
subtitle="Scheduled re-check after approval"
actions={<Badge tone={better ? 'emerald' : 'amber'}>{better ? 'Within baseline' : 'Still elevated'}</Badge>}
actions={<Badge tone={confirmed ? 'emerald' : 'amber'}>{confirmed ? 'Recovery confirmed' : 'Not confirmed'}</Badge>}
>
<div className="space-y-3 px-5 py-4">
<Facts
cols={3}
rows={[
{ label: 'Current denial rate', value: pct(current), tone: better ? 'emerald' : 'rose' },
{ label: 'Denial rate now', value: pct(current), tone: confirmed ? 'emerald' : 'rose' },
{ label: 'Baseline', value: pct(baseline) },
{ label: 'Recovered to date', value: recovered == null ? '—' : money(recovered), tone: 'emerald' },
]}
/>
<p className="text-sm leading-relaxed whitespace-pre-wrap text-muted">{summary}</p>
{workStatement(summary) ? (
<WorkStatement text={summary} heading="" bare />
) : (
<p className="text-sm leading-relaxed whitespace-pre-wrap text-muted">{summary}</p>
)}
</div>
</Card>
);

View File

@ -194,6 +194,11 @@ export const WORK_LABELS: Record<string, string> = {
FOUND: 'Found',
WATCHED: 'Watched, below the bar',
CLEAR: 'Checked, nothing',
// the re-check
'SINCE APPROVAL': 'Since approval',
ACTIONS: 'Actions taken',
RATE: 'Denial rate',
VERDICT: 'Verdict',
};
export function workStatement(v: unknown): Array<{ key: string; label: string; items: string[] }> | null {
const lines = str(v).split(/\n+/).map((l) => l.trim()).filter(Boolean);