From 89d6320fcec94153af3f280683190f02d2e7f172 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 18 Aug 2026 18:40:16 +0000 Subject: [PATCH 1/2] fix(dsm): stop the diagnosis page stating its criteria twice MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The four cards above "Core diagnostic criteria" rendered `criteria.slice(0, 4)` — the same array the panel below lists in full — so every diagnosis showed criterion A-D twice, the second time truncated to four lines. The row also rendered `min(criteria.length, 4)` cards, and only 86 of the 146 records carry four or more criteria, so it was a ragged one- to-four tiles rather than a stable strip; a "Criterion D" card existed for just 85 records. Replace it with an at-a-glance row reporting the shape of the record rather than its content: criteria count plus letter range, specifier count, differential count, and whether a severity specifier is supported. All four are populated on all 146 records, so the row is always exactly four tiles. The ICD code and category stay out of it — the page header already carries both as chips. The criteria list itself, the sidebar, and all five in-page nav anchors are untouched. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_015ZQ87bTZSjifuat4Pwf7rZ --- src/components/dsm/dsm-diagnosis-page.tsx | 98 +++++++++++++++++++---- 1 file changed, 84 insertions(+), 14 deletions(-) diff --git a/src/components/dsm/dsm-diagnosis-page.tsx b/src/components/dsm/dsm-diagnosis-page.tsx index d2f7ef8e75..4020e23da4 100644 --- a/src/components/dsm/dsm-diagnosis-page.tsx +++ b/src/components/dsm/dsm-diagnosis-page.tsx @@ -1,10 +1,12 @@ import Link from "next/link"; +import type { ComponentType } from "react"; import { BookOpenCheck, ChevronRight, Search, ClipboardList, GitCompareArrows, + Gauge, ListChecks, MessageSquareText, ShieldCheck, @@ -19,6 +21,43 @@ import { inPageActionRowClass, inPageAnchor } from "@/components/in-page-nav/in- import { cn, codeText, metadataPill, pageContainer } from "@/components/ui-primitives"; import { dsmCriteria, resolveDsmDifferential, type DsmDiagnosis, type DsmLabeledText } from "@/lib/dsm"; +/** + * Explicit singular and plural rather than appending "s", because the one that + * matters here is irregular: "1 criterion" / "4 criteria". + * + * The zero branch is unreachable in the shipped catalogue — criteria, specifiers + * and differentials are each populated on all 146 records — but the JSON is a + * vendored upstream snapshot, so a re-export could introduce one and "0 criteria" + * would read as a rendering fault rather than as a fact about the record. + */ +function countLabel(count: number, singular: string, plural: string) { + if (count === 0) return "None in this record"; + return `${count} ${count === 1 ? singular : plural}`; +} + +/** One label/value pair in the at-a-glance row. Non-interactive by design. */ +function SummaryTile({ + icon: Icon, + label, + value, +}: { + icon: ComponentType<{ className?: string }>; + label: string; + value: string; +}) { + return ( +
+
+ + {label} +
+
+ {value} +
+
+ ); +} + function CriteriaRow({ criterion, index }: { criterion: DsmLabeledText; index: number }) { return (
  • @@ -39,6 +78,19 @@ export function DsmDiagnosisPage({ diagnosis }: { diagnosis: DsmDiagnosis }) { const criteria = dsmCriteria(diagnosis); const compareHref = `/dsm/compare?ids=${encodeURIComponent(diagnosis.slug)}`; + // "4 criteria, A-D" / "1 criterion, A". Twelve records carry a single criterion, + // so the range is appended only when there are at least two to span — otherwise + // it would read "A-A". Labels fall back to the ordinal the list rows already use. + const criteriaCountLabel = countLabel(criteria.length, "criterion", "criteria"); + const firstCriterionLabel = criteria[0]?.label || "1"; + const lastCriterionLabel = criteria.at(-1)?.label || String(criteria.length); + const criteriaSummary = + criteria.length > 1 + ? `${criteriaCountLabel}, ${firstCriterionLabel}\u2013${lastCriterionLabel}` + : criteria.length === 1 + ? `${criteriaCountLabel}, ${firstCriterionLabel}` + : criteriaCountLabel; + return ( <>
    -
    - {criteria.slice(0, 4).map((criterion, index) => ( -
    -

    - Criterion {criterion.label || index + 1} -

    -

    - {criterion.text} -

    -
    - ))} + {/* + The shape of the record, not its content. This row previously rendered + `criteria.slice(0, 4)` verbatim, which the `#criteria` panel below already + lists in full — so every diagnosis stated its criteria twice, the second + time truncated. It also rendered `min(criteria.length, 4)` cards, and only + 86 of 146 records carry four or more criteria, so the row was a ragged one + to four tiles rather than a stable strip. + + Every field read here is populated on all 146 records, so this is always + exactly four tiles. `icd_code` and the category are deliberately absent: + the page header already carries both as chips, and repeating them would be + the same defect in a new place. + */} +
    +
    + + + + +
    From 6b28de1ff78051e138c3e08c59f285ae8a1cc42c Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 18 Aug 2026 18:52:43 +0000 Subject: [PATCH 2/2] docs(ledger): record the DSM criteria-duplication review Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_015ZQ87bTZSjifuat4Pwf7rZ --- ...a3f12c1f952f99050f4632920a5e95b42b678790e93fabb0050.record.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/branch-review-records/92610868c245fa3f12c1f952f99050f4632920a5e95b42b678790e93fabb0050.record.md diff --git a/docs/branch-review-records/92610868c245fa3f12c1f952f99050f4632920a5e95b42b678790e93fabb0050.record.md b/docs/branch-review-records/92610868c245fa3f12c1f952f99050f4632920a5e95b42b678790e93fabb0050.record.md new file mode 100644 index 0000000000..1e85e5679a --- /dev/null +++ b/docs/branch-review-records/92610868c245fa3f12c1f952f99050f4632920a5e95b42b678790e93fabb0050.record.md @@ -0,0 +1 @@ +| 2026-08-18 | claude/diagnostic-criteria-duplication-udg99e | 89d6320fcec94153af3f280683190f02d2e7f172 | dsm diagnosis page criteria duplication | fixed: replaced criteria-echo card row with a four-tile at-a-glance summary; criteria list, sidebar and nav anchors untouched | test:focused 38 passed; vitest dsm 13 passed; typecheck; lint; check:design-system-contract (legacy shadow aliases 89, unchanged); rendered proof on 4 records |