= {}): ClinicalDocumentSummaryProfile {
+ return {
+ overview: "Safe lithium care requires baseline tests, timed monitoring, and urgent action for toxicity.",
+ applies_to: [],
+ key_clinical_actions: [item("Check renal, thyroid and calcium status before treatment.", [4])],
+ medication_dose_monitoring: [],
+ thresholds_timing: [item("Take trough levels 12 hours after the last dose.", [6])],
+ escalation_risk_warnings: [item("Withhold lithium and urgently assess suspected toxicity.", [9])],
+ required_forms_documentation: [],
+ not_covered: [],
+ important_tables_images: [],
+ best_questions: [],
+ source_quality_notes: [],
+ ...overrides,
+ };
+}
+
+function documentWithProfile(summaryProfile: ClinicalDocumentSummaryProfile): ClinicalDocument {
+ return {
+ id: "document-1",
+ title: "Lithium monitoring protocol",
+ file_name: "lithium-monitoring.pdf",
+ created_at: "2026-07-24T00:00:00.000Z",
+ summary: {
+ id: "summary-1",
+ document_id: "document-1",
+ summary: "Stored summary fallback.",
+ clinical_specifics: { profile: summaryProfile },
+ },
+ } as ClinicalDocument;
+}
+
+describe("buildDocumentClinicalSummaryModel", () => {
+ it("orders source-backed priorities by safety, monitoring, then clinical action", () => {
+ const model = buildDocumentClinicalSummaryModel(documentWithProfile(profile()));
+
+ expect(model.summary).toContain("baseline tests");
+ expect(model.priorities.map((priority) => priority.title)).toEqual([
+ "Escalation and safety",
+ "Timing and monitoring",
+ "Key clinical action",
+ ]);
+ expect(model.priorities.map((priority) => priority.page)).toEqual([9, 6, 4]);
+ });
+
+ it("skips unsupported and duplicate profile items", () => {
+ const repeated = "Take trough levels 12 hours after the last dose.";
+ const model = buildDocumentClinicalSummaryModel(
+ documentWithProfile(
+ profile({
+ escalation_risk_warnings: [item("Unsupported warning.", [3], "not_found")],
+ thresholds_timing: [item(repeated, [6])],
+ key_clinical_actions: [item(repeated, [6])],
+ }),
+ ),
+ );
+
+ expect(model.priorities).toHaveLength(1);
+ expect(model.priorities[0]).toMatchObject({ title: "Timing and monitoring", page: 6 });
+ });
+
+ it("does not surface generic source-review copy as the high-yield summary", () => {
+ const model = buildDocumentClinicalSummaryModel(
+ documentWithProfile(profile({ overview: "Source-backed review of the indexed document." })),
+ );
+
+ expect(model.summary).toBe("Stored summary fallback.");
+ });
+});
diff --git a/tests/ui-smoke.spec.ts b/tests/ui-smoke.spec.ts
index 20fdd89d6..0566ed5df 100644
--- a/tests/ui-smoke.spec.ts
+++ b/tests/ui-smoke.spec.ts
@@ -3353,6 +3353,15 @@ test.describe("Clinical KB UI smoke coverage", () => {
await expect(page.getByRole("heading", { level: 1, name: "Synthetic lithium monitoring protocol" })).toBeVisible({
timeout: 30_000,
});
+ const clinicalSummary = page.getByTestId("document-clinical-summary");
+ await expect(clinicalSummary).toBeVisible();
+ await expect(clinicalSummary.getByRole("heading", { name: "High-yield clinical summary" })).toBeVisible();
+ const clinicalPriorities = clinicalSummary.getByRole("button", { name: /Clinical priorities/ });
+ await expect(clinicalPriorities).toHaveAttribute("aria-expanded", "true");
+ await clinicalPriorities.click();
+ await expect(clinicalPriorities).toHaveAttribute("aria-expanded", "false");
+ await expect(page.getByRole("heading", { name: "Key sections", exact: true })).toHaveCount(0);
+ await expect(page.getByRole("heading", { name: "Useful pages", exact: true })).toHaveCount(0);
const summaryCard = page.getByTestId("high-yield-summary");
await expect(summaryCard).toBeVisible();
await expect(summaryCard).toHaveJSProperty("open", false);
@@ -3388,6 +3397,19 @@ test.describe("Clinical KB UI smoke coverage", () => {
await expect(page.getByRole("heading", { level: 1, name: "Synthetic lithium monitoring protocol" })).toBeVisible({
timeout: 30_000,
});
+ const clinicalSummary = page.getByTestId("document-clinical-summary");
+ const summaryToggle = clinicalSummary.getByTestId("toggle-document-summary");
+ await expect(clinicalSummary).toBeVisible();
+ await expect(summaryToggle).toBeVisible();
+ await expect(summaryToggle).toHaveAttribute("aria-expanded", "false");
+ await summaryToggle.click();
+ await expect(summaryToggle).toHaveAttribute("aria-expanded", "true");
+ await expect(summaryToggle).toContainText("Show less");
+ await clinicalSummary.getByTestId("open-clinical-priorities").click();
+ const prioritiesSheet = page.getByRole("dialog", { name: "Clinical priorities" });
+ await expect(prioritiesSheet).toBeVisible();
+ await page.keyboard.press("Escape");
+ await expect(prioritiesSheet).toHaveCount(0);
const indexedText = page.locator("#source-text");
const summary = page.getByTestId("high-yield-summary");
const images = page.locator("#source-images");
From 6bbce2b97477cb4497624abe2a37c74864e872c8 Mon Sep 17 00:00:00 2001
From: BigSimmo <87357024+BigSimmo@users.noreply.github.com>
Date: Sat, 25 Jul 2026 00:53:29 +0800
Subject: [PATCH 2/9] fix(documents): use named summary type token
---
src/components/document-viewer/document-clinical-summary.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/components/document-viewer/document-clinical-summary.tsx b/src/components/document-viewer/document-clinical-summary.tsx
index eba970a47..5e9844de0 100644
--- a/src/components/document-viewer/document-clinical-summary.tsx
+++ b/src/components/document-viewer/document-clinical-summary.tsx
@@ -356,7 +356,7 @@ export function DocumentClinicalSummary({
{model.summary ? (
From 88a986dd240acaa68fcc340e7629caadc4074275 Mon Sep 17 00:00:00 2001
From: BigSimmo <87357024+BigSimmo@users.noreply.github.com>
Date: Sat, 25 Jul 2026 01:01:29 +0800
Subject: [PATCH 3/9] docs: record PR 1169 thread verification
---
docs/branch-review-ledger.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/branch-review-ledger.md b/docs/branch-review-ledger.md
index 4808a2600..324a42286 100644
--- a/docs/branch-review-ledger.md
+++ b/docs/branch-review-ledger.md
@@ -747,3 +747,4 @@ This file is append-only. Never rewrite or delete an existing review record; app
| 2026-07-24 | remediate-audit-system-issues (PR #1160) | bdf530fc8c6faaa4491c510396b47872fc39bf25 | Run PR sweep: CI fix + threads + drift | second re-merge after main moved to 2e68888f3 during first push; clean ort merge (ledger + layout.tsx); taskkill /T retained; sitemap prettier retained | merge only; no provider-backed checks run |
| 2026-07-24 | codex/query-ribbon-search-headings (PR #1166) | c94e89f392f578c4b2c749195dd485b74959074c | Run PR re-sync sweep | Before: CONFLICTING. After: merged origin/main clean. CI re-running. | merge origin/main and/or conflict re-check only; no provider-backed checks run |
| 2026-07-24 | cursor/comprehensive-repo-review-ledger-d9a1 (PR #1150) | 345c02cdbaefb13aeb951a14674aedfe4648a50e | Run PR re-sync sweep | Before: CONFLICTING. After: merged origin/main clean. | merge origin/main and/or conflict re-check only; no provider-backed checks run |
+| 2026-07-25 | codex/document-clinical-summary-20260725 (PR #1169) | 6bbce2b97477cb4497624abe2a37c74864e872c8 | Open-PR maintenance: review-thread verification | Before: 2 unresolved Codex threads; branch current with main and required CI running. After: both persisted-profile/placeholder-summary fixes confirmed on the exact head and ready for reply-then-resolve; no further code change required. | `node scripts/run-vitest.mjs run tests/document-clinical-summary.test.ts tests/document-clinical-summary.dom.test.tsx --reporter=dot` pass (5/5); `git diff --check` pass; no provider-backed checks run. |
From ef4ffca5687a76fd05a28c5a84b1132e0e1193f2 Mon Sep 17 00:00:00 2001
From: Cursor Agent
Date: Fri, 24 Jul 2026 17:01:39 +0000
Subject: [PATCH 4/9] fix(documents): guard profile pages and filter
placeholder summaries
- Default missing pages arrays to [] before page lookup
- Skip enrichment placeholder text in clinical summary display
Co-authored-by: BigSimmo
---
.../document-clinical-summary.tsx | 27 ++++++++++++++-----
1 file changed, 20 insertions(+), 7 deletions(-)
diff --git a/src/components/document-viewer/document-clinical-summary.tsx b/src/components/document-viewer/document-clinical-summary.tsx
index 5e9844de0..257249767 100644
--- a/src/components/document-viewer/document-clinical-summary.tsx
+++ b/src/components/document-viewer/document-clinical-summary.tsx
@@ -70,6 +70,21 @@ const priorityTone: Record) {
return items.find((item) => {
if (item.support === "not_found") return false;
@@ -116,7 +131,7 @@ function prioritiesFromProfile(profile: ClinicalDocumentSummaryProfile): Documen
if (!item) return [];
const text = cleanClinicalSummaryText(item.text);
usedText.add(text.toLowerCase());
- const page = item.pages.find((value) => Number.isInteger(value) && value > 0) ?? null;
+ const page = profileItemPages(item).find((value) => Number.isInteger(value) && value > 0) ?? null;
return [
{
id: candidate.id,
@@ -157,13 +172,11 @@ export function buildDocumentClinicalSummaryModel(document: ClinicalDocument): D
const profile = document.summary?.clinical_specifics?.profile;
const formatted = formatDocumentSummary(document.summary?.summary);
const priorities = profile ? prioritiesFromProfile(profile) : prioritiesFromFormattedSummary(document);
- const profileOverview = cleanClinicalSummaryText(profile?.overview ?? "");
- const usefulProfileOverview =
- profileOverview && !/source-backed review/i.test(profileOverview) ? profileOverview : "";
+ const profileOverview = usefulSummaryText(profile?.overview ?? "");
const summary = cleanClinicalSummaryText(
- usefulProfileOverview ||
- formatted.lead ||
- formatted.sections[0]?.items.join(" ") ||
+ profileOverview ||
+ usefulSummaryText(formatted.lead ?? "") ||
+ usefulSummaryText(formatted.sections[0]?.items.join(" ") ?? "") ||
priorities
.slice(0, 2)
.map((priority) => priority.text)
From 42abd25379c924500f7c2ca2e28d1337d40cad0c Mon Sep 17 00:00:00 2001
From: BigSimmo <87357024+BigSimmo@users.noreply.github.com>
Date: Sat, 25 Jul 2026 01:06:43 +0800
Subject: [PATCH 5/9] fix(documents): harden clinical summary fallbacks
---
.../document-clinical-summary.tsx | 12 +++++++-----
tests/document-clinical-summary.test.ts | 16 ++++++++++++++++
2 files changed, 23 insertions(+), 5 deletions(-)
diff --git a/src/components/document-viewer/document-clinical-summary.tsx b/src/components/document-viewer/document-clinical-summary.tsx
index 257249767..defa7aaf4 100644
--- a/src/components/document-viewer/document-clinical-summary.tsx
+++ b/src/components/document-viewer/document-clinical-summary.tsx
@@ -70,7 +70,7 @@ const priorityTone: Record priority.text)
- .join(" "),
+ usefulSummaryText(
+ priorities
+ .slice(0, 2)
+ .map((priority) => priority.text)
+ .join(" "),
+ ),
);
return {
summary,
diff --git a/tests/document-clinical-summary.test.ts b/tests/document-clinical-summary.test.ts
index 8e993f313..542e0252f 100644
--- a/tests/document-clinical-summary.test.ts
+++ b/tests/document-clinical-summary.test.ts
@@ -78,6 +78,22 @@ describe("buildDocumentClinicalSummaryModel", () => {
expect(model.priorities[0]).toMatchObject({ title: "Timing and monitoring", page: 6 });
});
+ it("handles persisted profile items without a pages array", () => {
+ const legacyItem = {
+ ...item("Take a trough level after the last dose.", []),
+ pages: undefined,
+ } as unknown as DocumentSummaryProfileItem;
+ const model = buildDocumentClinicalSummaryModel(
+ documentWithProfile(
+ profile({
+ thresholds_timing: [legacyItem],
+ }),
+ ),
+ );
+
+ expect(model.priorities.find((priority) => priority.title === "Timing and monitoring")?.page).toBeNull();
+ });
+
it("does not surface generic source-review copy as the high-yield summary", () => {
const model = buildDocumentClinicalSummaryModel(
documentWithProfile(profile({ overview: "Source-backed review of the indexed document." })),
From 605a47b551a03774fab41416bf980dfbc9610221 Mon Sep 17 00:00:00 2001
From: BigSimmo <87357024+BigSimmo@users.noreply.github.com>
Date: Sat, 25 Jul 2026 01:36:10 +0800
Subject: [PATCH 6/9] fix(documents): tolerate malformed summary profiles
---
.../document-clinical-summary.tsx | 18 +++++++++++++-----
tests/document-clinical-summary.test.ts | 15 +++++++++++++++
2 files changed, 28 insertions(+), 5 deletions(-)
diff --git a/src/components/document-viewer/document-clinical-summary.tsx b/src/components/document-viewer/document-clinical-summary.tsx
index defa7aaf4..4e5b388f1 100644
--- a/src/components/document-viewer/document-clinical-summary.tsx
+++ b/src/components/document-viewer/document-clinical-summary.tsx
@@ -93,6 +93,14 @@ function firstRenderableItem(items: DocumentSummaryProfileItem[], usedText: Set<
});
}
+function profileItems(value: unknown): DocumentSummaryProfileItem[] {
+ if (!Array.isArray(value)) return [];
+ return value.filter(
+ (item): item is DocumentSummaryProfileItem =>
+ typeof item === "object" && item !== null && typeof (item as { text?: unknown }).text === "string",
+ );
+}
+
function profilePriorityCandidates(profile: ClinicalDocumentSummaryProfile): PriorityCandidate[] {
return [
{
@@ -100,14 +108,14 @@ function profilePriorityCandidates(profile: ClinicalDocumentSummaryProfile): Pri
title: "Escalation and safety",
label: "Critical safety",
tone: "safety",
- items: profile.escalation_risk_warnings ?? [],
+ items: profileItems(profile.escalation_risk_warnings),
},
{
id: "monitoring",
title: "Timing and monitoring",
label: "Monitoring",
tone: "monitoring",
- items: [...(profile.thresholds_timing ?? []), ...(profile.medication_dose_monitoring ?? [])],
+ items: [...profileItems(profile.thresholds_timing), ...profileItems(profile.medication_dose_monitoring)],
},
{
id: "action",
@@ -115,9 +123,9 @@ function profilePriorityCandidates(profile: ClinicalDocumentSummaryProfile): Pri
label: "Clinical action",
tone: "action",
items: [
- ...(profile.key_clinical_actions ?? []),
- ...(profile.required_forms_documentation ?? []),
- ...(profile.applies_to ?? []),
+ ...profileItems(profile.key_clinical_actions),
+ ...profileItems(profile.required_forms_documentation),
+ ...profileItems(profile.applies_to),
],
},
];
diff --git a/tests/document-clinical-summary.test.ts b/tests/document-clinical-summary.test.ts
index 542e0252f..62de72661 100644
--- a/tests/document-clinical-summary.test.ts
+++ b/tests/document-clinical-summary.test.ts
@@ -94,6 +94,21 @@ describe("buildDocumentClinicalSummaryModel", () => {
expect(model.priorities.find((priority) => priority.title === "Timing and monitoring")?.page).toBeNull();
});
+ it("ignores malformed persisted profile groups and items", () => {
+ const malformed = profile({
+ thresholds_timing: { text: "not an array" },
+ medication_dose_monitoring: [null, "invalid", { support: "direct" }],
+ escalation_risk_warnings: [null, item("Escalate valid safety concerns.", [7])],
+ } as unknown as Partial);
+
+ const model = buildDocumentClinicalSummaryModel(documentWithProfile(malformed));
+
+ expect(model.priorities.map((priority) => priority.text)).toEqual([
+ "Escalate valid safety concerns.",
+ "Check renal, thyroid and calcium status before treatment.",
+ ]);
+ });
+
it("does not surface generic source-review copy as the high-yield summary", () => {
const model = buildDocumentClinicalSummaryModel(
documentWithProfile(profile({ overview: "Source-backed review of the indexed document." })),
From 75c40c82f4cace438261e129e59a2579a59b4c5a Mon Sep 17 00:00:00 2001
From: BigSimmo <87357024+BigSimmo@users.noreply.github.com>
Date: Sat, 25 Jul 2026 01:36:28 +0800
Subject: [PATCH 7/9] docs: record PR 1169 profile guard
---
docs/branch-review-ledger.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/branch-review-ledger.md b/docs/branch-review-ledger.md
index 1f59fc5c3..3a2b5d3ef 100644
--- a/docs/branch-review-ledger.md
+++ b/docs/branch-review-ledger.md
@@ -760,3 +760,4 @@ This file is append-only. Never rewrite or delete an existing review record; app
| 2026-07-25 | codex/document-clinical-summary-20260725 (PR #1169) | 6bbce2b97477cb4497624abe2a37c74864e872c8 | Open-PR maintenance: review-thread verification | Before: 2 unresolved Codex threads; branch current with main and required CI running. After: both persisted-profile/placeholder-summary fixes confirmed on the exact head and ready for reply-then-resolve; no further code change required. | `node scripts/run-vitest.mjs run tests/document-clinical-summary.test.ts tests/document-clinical-summary.dom.test.tsx --reporter=dot` pass (5/5); `git diff --check` pass; no provider-backed checks run. |
| 2026-07-25 | cursor/pr-babysit-bugbot-agents-6c52 (PR #1167) | ee44812aae9dad1973d8302eba5bfca5000dffb6 | Open-PR maintenance: review-thread fixes | Before: 8 unresolved Codex/CodeRabbit threads; branch current with main. After: target-head pinning, fresh-main verification, exact `cursor[bot]` identity checks, explicit mutation/provider authorization, direct reply-then-resolve semantics, and no-op ledger bookkeeping are documented. | Prettier check on both agent files pass; `git diff --check` pass; GitHub author probe confirmed `cursor[bot]` account type `Bot`; no provider-backed checks run. |
| 2026-07-25 | codex/fix-merge-conflicts-and-ci-on-open-prs (PR #1170) | e979fc892f11a17b1a8f2ef1ab058ef40d629182 | Open-PR maintenance: CI fix + threads + drift | Before: Static PR checks failed because route-group moves made nine valid legacy `src/app/*` documentation references appear missing; 0 unresolved threads; branch already contained current main. After: docs-link resolution checks known App Router route groups and the focused failure is fixed. | `node scripts/check-docs-links.mjs` pass (1162 references); Prettier check pass; `git diff --check` pass; no provider-backed checks run. |
+| 2026-07-25 | codex/document-clinical-summary-20260725 (PR #1169) | 605a47b551a03774fab41416bf980dfbc9610221 | Open-PR maintenance: malformed persisted profile guard | Before: one actionable thread showed non-array or malformed persisted summary groups could throw during render. After: every priority group is normalized through an array/item guard and malformed values are ignored while valid items still render. | Focused Vitest 7/7 pass; Prettier and diff checks pass; no provider-backed checks run. |
From b6a13ebce00d7fed71cdd09f6c85824a4a538ee5 Mon Sep 17 00:00:00 2001
From: BigSimmo <87357024+BigSimmo@users.noreply.github.com>
Date: Sat, 25 Jul 2026 01:38:49 +0800
Subject: [PATCH 8/9] fix(documents): keep empty summaries unverified
---
.../document-viewer/document-clinical-summary.tsx | 11 +++++++----
tests/document-clinical-summary.dom.test.tsx | 11 +++++++++++
2 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/src/components/document-viewer/document-clinical-summary.tsx b/src/components/document-viewer/document-clinical-summary.tsx
index 4e5b388f1..dbf944343 100644
--- a/src/components/document-viewer/document-clinical-summary.tsx
+++ b/src/components/document-viewer/document-clinical-summary.tsx
@@ -348,6 +348,7 @@ export function DocumentClinicalSummary({
const mobilePrioritiesButtonRef = useRef(null);
const prioritiesId = useId();
const canExpandSummary = model.summary.length > 140;
+ const hasRenderableSummary = Boolean(model.summary || model.priorities.length);
function navigateFromSheet(page: number) {
setMobilePrioritiesOpen(false);
@@ -371,10 +372,12 @@ export function DocumentClinicalSummary({
High-yield clinical summary
-
-
- Source-backed
-
+ {hasRenderableSummary ? (
+
+
+ Source-backed
+
+ ) : null}
{model.summary ? (
{
expect(onPageChange).toHaveBeenCalledWith(9);
expect(screen.queryByTestId("clinical-priorities-sheet")).not.toBeInTheDocument();
});
+
+ it("does not label an unindexed empty state as source-backed", () => {
+ const emptyDocument = { ...document, summary: undefined } as ClinicalDocument;
+
+ render(
+ `?page=${page}`} onPageChange={vi.fn()} />,
+ );
+
+ expect(screen.getByText("A structured clinical summary has not been indexed for this document yet.")).toBeVisible();
+ expect(screen.queryByText("Source-backed")).not.toBeInTheDocument();
+ });
});
From 09043be976af266f9abd1eb745dec952802bde6f Mon Sep 17 00:00:00 2001
From: BigSimmo <87357024+BigSimmo@users.noreply.github.com>
Date: Sat, 25 Jul 2026 01:56:27 +0800
Subject: [PATCH 9/9] fix(documents): verify summary evidence metadata
---
.../document-clinical-summary.tsx | 15 ++++++++++---
tests/document-clinical-summary.test.ts | 21 +++++++++++++++++++
2 files changed, 33 insertions(+), 3 deletions(-)
diff --git a/src/components/document-viewer/document-clinical-summary.tsx b/src/components/document-viewer/document-clinical-summary.tsx
index dbf944343..125f8fcd6 100644
--- a/src/components/document-viewer/document-clinical-summary.tsx
+++ b/src/components/document-viewer/document-clinical-summary.tsx
@@ -42,6 +42,7 @@ export type DocumentClinicalPriority = {
export type DocumentClinicalSummaryModel = {
summary: string;
priorities: DocumentClinicalPriority[];
+ sourceBacked: boolean;
};
type PriorityCandidate = {
@@ -85,6 +86,14 @@ function profileItemPages(item: DocumentSummaryProfileItem): number[] {
return Array.isArray(item.pages) ? item.pages : [];
}
+function verifiedSupport(item: DocumentSummaryProfileItem): DocumentSummarySupportLevel | null {
+ if (item.support !== "direct" && item.support !== "partial") return null;
+ const hasLinkedSource = [item.source_chunk_ids, item.source_image_ids].some(
+ (ids) => Array.isArray(ids) && ids.some((id) => typeof id === "string" && id.trim()),
+ );
+ return hasLinkedSource ? item.support : null;
+}
+
function firstRenderableItem(items: DocumentSummaryProfileItem[], usedText: Set) {
return items.find((item) => {
if (item.support === "not_found") return false;
@@ -147,7 +156,7 @@ function prioritiesFromProfile(profile: ClinicalDocumentSummaryProfile): Documen
label: candidate.label,
text,
page,
- support: item.support,
+ support: verifiedSupport(item),
tone: candidate.tone,
},
];
@@ -195,6 +204,7 @@ export function buildDocumentClinicalSummaryModel(document: ClinicalDocument): D
return {
summary,
priorities,
+ sourceBacked: priorities.some((priority) => priority.support === "direct" || priority.support === "partial"),
};
}
@@ -348,7 +358,6 @@ export function DocumentClinicalSummary({
const mobilePrioritiesButtonRef = useRef(null);
const prioritiesId = useId();
const canExpandSummary = model.summary.length > 140;
- const hasRenderableSummary = Boolean(model.summary || model.priorities.length);
function navigateFromSheet(page: number) {
setMobilePrioritiesOpen(false);
@@ -372,7 +381,7 @@ export function DocumentClinicalSummary({
High-yield clinical summary
- {hasRenderableSummary ? (
+ {model.sourceBacked ? (
Source-backed
diff --git a/tests/document-clinical-summary.test.ts b/tests/document-clinical-summary.test.ts
index 62de72661..fe4693d28 100644
--- a/tests/document-clinical-summary.test.ts
+++ b/tests/document-clinical-summary.test.ts
@@ -60,6 +60,7 @@ describe("buildDocumentClinicalSummaryModel", () => {
"Key clinical action",
]);
expect(model.priorities.map((priority) => priority.page)).toEqual([9, 6, 4]);
+ expect(model.sourceBacked).toBe(true);
});
it("skips unsupported and duplicate profile items", () => {
@@ -109,6 +110,26 @@ describe("buildDocumentClinicalSummaryModel", () => {
]);
});
+ it("keeps text-only persisted profile items unverified", () => {
+ const textOnlyItem = {
+ text: "Review monitoring after dose changes.",
+ pages: [5],
+ } as DocumentSummaryProfileItem;
+ const model = buildDocumentClinicalSummaryModel(
+ documentWithProfile(
+ profile({
+ escalation_risk_warnings: [],
+ thresholds_timing: [textOnlyItem],
+ key_clinical_actions: [],
+ }),
+ ),
+ );
+
+ expect(model.priorities).toHaveLength(1);
+ expect(model.priorities[0]?.support).toBeNull();
+ expect(model.sourceBacked).toBe(false);
+ });
+
it("does not surface generic source-review copy as the high-yield summary", () => {
const model = buildDocumentClinicalSummaryModel(
documentWithProfile(profile({ overview: "Source-backed review of the indexed document." })),