diff --git a/src/components/Findings.tsx b/src/components/Findings.tsx index ca73aea..ae5c5b0 100644 --- a/src/components/Findings.tsx +++ b/src/components/Findings.tsx @@ -5,7 +5,7 @@ import type { Slice } from '../api/charts'; import { affectedClaimsHref, recoverableClaimsHref } from '../lib/claimsLink'; import { Badge, Card, Facts } from './core'; import type { AvaDecision, AvaTraceStep, Row } from '../api/types'; -import { firstDeadline, headline, money, num, pct, prose, recommendations, shortDate, splitRecommendation, sqlSteps, str } from '../format'; +import { firstDeadline, headline, money, num, pct, prose, recommendations, sentences, shortDate, splitRecommendation, sqlSteps, str, workStatement } from '../format'; /** * Ava's findings, laid out for a person who has ninety seconds. @@ -63,12 +63,7 @@ export function Verdict({ )} AI analysis · Ava - {scanned && ( -

- What Ava reviewed. - {scanned} -

- )} + {scanned && }
@@ -96,6 +91,41 @@ 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 }) { + const rows = workStatement(text); + const TONE: Record = { FOUND: 'text-warn', WATCHED: 'text-muted', CLEAR: 'text-good', REVIEWED: 'text-ink' }; + return ( +
+

Review coverage

+ {rows ? ( +
+ {rows.map((r) => ( +
+
{r.label}
+
+ {r.items.map((it, i) => ( + + {it} + + ))} +
+
+ ))} +
+ ) : ( +
    + {sentences(text).map((s, i) => ( +
  • {s}
  • + ))} +
+ )} +
+ ); +} + /** The decision list. Rendered directly above the Approve / Send back / Reject buttons. */ export function Recommendations({ row }: { row: Row }) { const recs = recommendations(row.recommendations).map(prose); diff --git a/src/format.ts b/src/format.ts index 934e252..0779d21 100644 --- a/src/format.ts +++ b/src/format.ts @@ -184,6 +184,28 @@ export function firstDeadline(recs: unknown): string | null { } /** 2026-10-02 → "Oct 2" */ +/** Ava's work statement: labelled lines ("REVIEWED: a; b; c"). Returns the + * rows in her order, items split on ";" — or null when the text is an older + * free-form paragraph, in which case the caller falls back to sentences. */ +export const WORK_LABELS: Record = { + REVIEWED: 'Reviewed', + FOUND: 'Found', + WATCHED: 'Watched, below the bar', + CLEAR: 'Checked, nothing', +}; +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 rows: Array<{ key: string; label: string; items: string[] }> = []; + for (const line of lines) { + const m = line.match(/^([A-Z][A-Z ]{2,20}):\s*(.*)$/); + if (!m) continue; + const key = m[1].trim(); + const items = m[2].split(/;\s*/).map((x) => x.trim().replace(/[.]$/, '')).filter(Boolean); + rows.push({ key, label: WORK_LABELS[key] ?? key.charAt(0) + key.slice(1).toLowerCase(), items }); + } + return rows.length >= 2 ? rows : null; +} + /** 2026-07-26 → "Jul 26, 2026". For prose; shortDate is for axes and chips. */ export function longDate(iso: string | null): string { if (!iso) return ''; diff --git a/src/screens/QueueScreen.tsx b/src/screens/QueueScreen.tsx index e498fb5..8a1496b 100644 --- a/src/screens/QueueScreen.tsx +++ b/src/screens/QueueScreen.tsx @@ -4,7 +4,7 @@ import { useQuery, useZino } from '../api/provider'; import { FINDING_KIND, QUEUES, RECORD_VIEW, STAGE_TONE } from '../api/config'; import { Badge, Button, Empty, ErrorNote, Spinner } from '../components/core'; import type { Row } from '../api/types'; -import { dateTime, headline, money, num, prose, str } from '../format'; +import { dateTime, headline, money, num, prose, sentences, str, workStatement } from '../format'; /** * A queue, as a morning briefing. @@ -157,7 +157,11 @@ function CaseCard({ row, onOpen }: { row: Row; onOpen: () => void }) { )}
- {quiet && scanned &&

{scanned}

} + {quiet && scanned && ( +

+ {(workStatement(scanned)?.find((r) => r.key === 'REVIEWED')?.items ?? sentences(scanned).slice(0, 1)).join(' · ')} +

+ )} ); }