diff --git a/src/components/Findings.tsx b/src/components/Findings.tsx
index a2b140d..6206e16 100644
--- a/src/components/Findings.tsx
+++ b/src/components/Findings.tsx
@@ -2,11 +2,12 @@ import { useState } from 'react';
import { Link } from 'react-router-dom';
import { AlertTriangle, CheckCircle2, ChevronDown, ExternalLink, FileSearch } from 'lucide-react';
import type { Slice } from '../api/charts';
+import type { ReviewedFacts } from '../format';
import { affectedClaimsHref, recoverableClaimsHref } from '../lib/claimsLink';
import type { LinkDates } 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, sentences, shortDate, splitRecommendation, sqlSteps, str, workStatement } from '../format';
+import { firstDeadline, headline, longDate, money, num, pct, prose, recommendations, reviewedFacts, sentences, shortDate, splitRecommendation, sqlSteps, str, workStatement } from '../format';
/**
* Ava's findings, laid out for a person who has ninety seconds.
@@ -95,8 +96,45 @@ 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. */
+/** The comparison, drawn: this period against that one, then what was set aside. */
+function Periods({ f }: { f: ReviewedFacts }) {
+ const span = (r: { from: string; to: string } | null) => (r ? `${longDate(r.from)} – ${longDate(r.to)}` : '—');
+ return (
+
+
+
+
This period
+
{span(f.window)}
+ {f.windowClaims &&
{f.windowClaims} claims
}
+
+
+
Compared with
+
{span(f.baseline)}
+ {f.baselineClaims &&
{f.baselineClaims} claims
}
+
+
+
+ {f.pendingExcluded && (
+ <>
+ Set aside {f.pendingExcluded} pending claims (the insurer has not answered yet)
+ >
+ )}
+ {(f.insurers || f.departments || f.desks) && (
+ <>
+ {f.pendingExcluded ? ' · ' : ''}Looked across{' '}
+ {[f.insurers && `${f.insurers} insurers`, f.departments && `${f.departments} departments`, f.desks && `${f.desks} desks`].filter(Boolean).join(' · ')}
+ >
+ )}
+ {f.ceiling && <> · Nothing after {longDate(f.ceiling)} was used>}
+ {f.requested && <> · Requested {span(f.requested)}; the last 6 weeks of it were compared with the 8 before them>}
+
+
+ );
+}
+
function WorkStatement({ text, heading = 'Review coverage', bare = false }: { text: string; heading?: string; bare?: boolean }) {
const rows = workStatement(text);
+ const reviewed = rows ? reviewedFacts(rows.find((r) => r.key === 'REVIEWED')?.items ?? []) : null;
const TONE: Record = {
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',
@@ -104,9 +142,10 @@ function WorkStatement({ text, heading = 'Review coverage', bare = false }: { te
return (
{heading &&
{heading}
}
+ {rows && reviewed &&
}
{rows ? (
- {rows.map((r) => (
+ {rows.filter((r) => !(reviewed && r.key === 'REVIEWED')).map((r) => (
- {r.label}
-
diff --git a/src/format.ts b/src/format.ts
index 3daa1a8..7987fe0 100644
--- a/src/format.ts
+++ b/src/format.ts
@@ -231,6 +231,46 @@ export function workStatement(v: unknown): Array<{ key: string; label: string; i
return rows.length >= 2 ? rows : null;
}
+/** The REVIEWED row as fixed fields. Ava writes `window=2026-08-03..2026-09-13;
+ * window_claims=14,860; baseline=…` — this turns that into the two periods
+ * and the counts the console draws. Null when the row is older free text. */
+export interface ReviewedFacts {
+ window: { from: string; to: string } | null;
+ windowClaims: string;
+ baseline: { from: string; to: string } | null;
+ baselineClaims: string;
+ pendingExcluded: string;
+ insurers: string;
+ departments: string;
+ desks: string;
+ ceiling: string | null;
+ requested: { from: string; to: string } | null;
+}
+export function reviewedFacts(items: string[]): ReviewedFacts | null {
+ const kv: Record = {};
+ for (const it of items) {
+ const m = it.match(/^([a-z_]+)\s*=\s*(.+)$/i);
+ if (m) kv[m[1].toLowerCase()] = m[2].trim();
+ }
+ if (!kv.window && !kv.baseline) return null;
+ const range = (v?: string) => {
+ const m = v?.match(/(\d{4}-\d{2}-\d{2})\s*(?:\.\.|to|–|-)\s*(\d{4}-\d{2}-\d{2})/);
+ return m ? { from: m[1], to: m[2] } : null;
+ };
+ return {
+ window: range(kv.window),
+ windowClaims: kv.window_claims ?? '',
+ baseline: range(kv.baseline),
+ baselineClaims: kv.baseline_claims ?? '',
+ pendingExcluded: kv.pending_excluded ?? '',
+ insurers: kv.insurers ?? '',
+ departments: kv.departments ?? '',
+ desks: kv.desks ?? '',
+ ceiling: kv.ceiling ?? null,
+ requested: range(kv.requested),
+ };
+}
+
/** 2026-07-26 → "Jul 26, 2026". For prose; shortDate is for axes and chips. */
export function longDate(iso: string | null): string {
if (!iso) return '';