Compare commits
No commits in common. "400f9ec3a0a7fcbee5aaf680454946cbff11bb4a" and "f86a87af3854dea0d536c325f486f29d81860a54" have entirely different histories.
400f9ec3a0
...
f86a87af38
@ -95,15 +95,12 @@ export function Verdict({
|
|||||||
/** What was covered, as rows of short facts — not a paragraph. Ava writes it
|
/** 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
|
* as labelled lines; older cases wrote prose, which falls back to sentence
|
||||||
* bullets so nothing renders as a wall of text. */
|
* bullets so nothing renders as a wall of text. */
|
||||||
function WorkStatement({ text, heading = 'Review coverage', bare = false }: { text: string; heading?: string; bare?: boolean }) {
|
function WorkStatement({ text }: { text: string }) {
|
||||||
const rows = workStatement(text);
|
const rows = workStatement(text);
|
||||||
const TONE: Record<string, string> = {
|
const TONE: Record<string, string> = { FOUND: 'text-warn', WATCHED: 'text-muted', CLEAR: 'text-good', REVIEWED: 'text-ink' };
|
||||||
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 (
|
return (
|
||||||
<div className={bare ? '' : 'mt-3 border-t border-ai-edge/60 pt-3'}>
|
<div className="mt-3 border-t border-ai-edge/60 pt-3">
|
||||||
{heading && <p className="text-[11px] font-semibold tracking-wide text-faint uppercase">{heading}</p>}
|
<p className="text-[11px] font-semibold tracking-wide text-faint uppercase">Review coverage</p>
|
||||||
{rows ? (
|
{rows ? (
|
||||||
<dl className="mt-2 grid gap-y-2 text-[13px] sm:grid-cols-[9.5rem_1fr] sm:gap-x-4">
|
<dl className="mt-2 grid gap-y-2 text-[13px] sm:grid-cols-[9.5rem_1fr] sm:gap-x-4">
|
||||||
{rows.map((r) => (
|
{rows.map((r) => (
|
||||||
@ -272,27 +269,24 @@ export function Recheck({ row }: { row: Row }) {
|
|||||||
const current = num(row.current_rate);
|
const current = num(row.current_rate);
|
||||||
const baseline = num(row.baseline_rate);
|
const baseline = num(row.baseline_rate);
|
||||||
const recovered = num(row.recovered_amount);
|
const recovered = num(row.recovered_amount);
|
||||||
// The verdict is the decision she made, not a rate comparison the console
|
const better = current != null && baseline != null && current - baseline <= 2;
|
||||||
// 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 (
|
return (
|
||||||
<Card
|
<Card
|
||||||
title="Re-check result"
|
title="Re-check result"
|
||||||
subtitle="Scheduled re-check after approval"
|
subtitle="Scheduled re-check after approval"
|
||||||
actions={<Badge tone={confirmed ? 'emerald' : 'amber'}>{confirmed ? 'Recovery confirmed' : 'Not confirmed'}</Badge>}
|
actions={<Badge tone={better ? 'emerald' : 'amber'}>{better ? 'Within baseline' : 'Still elevated'}</Badge>}
|
||||||
>
|
>
|
||||||
<div className="space-y-3 px-5 py-4">
|
<div className="space-y-3 px-5 py-4">
|
||||||
<Facts
|
<Facts
|
||||||
cols={3}
|
cols={3}
|
||||||
rows={[
|
rows={[
|
||||||
{ label: 'Denial rate now', value: pct(current), tone: confirmed ? 'emerald' : 'rose' },
|
{ label: 'Current denial rate', value: pct(current), tone: better ? 'emerald' : 'rose' },
|
||||||
{ label: 'Baseline', value: pct(baseline) },
|
{ label: 'Baseline', value: pct(baseline) },
|
||||||
{ label: 'Recovered to date', value: recovered == null ? '—' : money(recovered), tone: 'emerald' },
|
{ label: 'Recovered to date', value: recovered == null ? '—' : money(recovered), tone: 'emerald' },
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
<WorkStatement text={summary} heading="" bare />
|
<p className="text-sm leading-relaxed whitespace-pre-wrap text-muted">{summary}</p>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -95,25 +95,7 @@ export const CARC: Record<string, string> = {
|
|||||||
export function recommendations(v: unknown): string[] {
|
export function recommendations(v: unknown): string[] {
|
||||||
const s = str(v).trim();
|
const s = str(v).trim();
|
||||||
if (!s) return [];
|
if (!s) return [];
|
||||||
// Ava is asked for one numbered line each, but sometimes runs them together
|
const parts = s.split(/\n(?=\s*\d+\.\s)/).map((x) => x.trim()).filter(Boolean);
|
||||||
// ("… recovered. 2. Billing: …"). Split at a line break OR at a sentence end
|
|
||||||
// followed by the next number in sequence — "2." after "1.", never "$1.5M".
|
|
||||||
let parts = s.split(/\n(?=\s*\d+\.\s)/).map((x) => x.trim()).filter(Boolean);
|
|
||||||
if (parts.length === 1) {
|
|
||||||
const out: string[] = [];
|
|
||||||
let rest = parts[0];
|
|
||||||
let n = 2;
|
|
||||||
for (;;) {
|
|
||||||
const re = new RegExp(`(?<=[.;:)])\\s+(?=${n}\\.\\s+[A-Z(])`);
|
|
||||||
const m = re.exec(rest);
|
|
||||||
if (!m) break;
|
|
||||||
out.push(rest.slice(0, m.index).trim());
|
|
||||||
rest = rest.slice(m.index).trim();
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
out.push(rest);
|
|
||||||
parts = out.filter(Boolean);
|
|
||||||
}
|
|
||||||
return parts.length ? parts : [s];
|
return parts.length ? parts : [s];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,11 +194,6 @@ export const WORK_LABELS: Record<string, string> = {
|
|||||||
FOUND: 'Found',
|
FOUND: 'Found',
|
||||||
WATCHED: 'Watched, below the bar',
|
WATCHED: 'Watched, below the bar',
|
||||||
CLEAR: 'Checked, nothing',
|
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 {
|
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);
|
const lines = str(v).split(/\n+/).map((l) => l.trim()).filter(Boolean);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user