From 65e5575c4f6ff364b5bc52f7698de7d75986e871 Mon Sep 17 00:00:00 2001 From: "coderabbitai[bot]" <136622811+coderabbitai[bot]@users.noreply.github.com> Date: Sun, 12 Jul 2026 16:29:41 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=9D=20Add=20docstrings=20to=20`claude/?= =?UTF-8?q?rag-review-improvements-f1bf84`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Docstrings generation was requested by @BigSimmo. * https://github.com/BigSimmo/Database/pull/514#issuecomment-4951731143 The following files were modified: * `src/components/ClinicalDashboard.tsx` * `src/components/clinical-dashboard/answer-content.tsx` * `src/components/clinical-dashboard/answer-result-surface.tsx` * `src/components/clinical-dashboard/display-text.ts` * `src/components/clinical-dashboard/evidence-panels.tsx` * `src/components/clinical-dashboard/output-panel.tsx` * `src/lib/answer-render-policy.ts` * `src/lib/rag-answer-text.ts` * `src/lib/rag.ts` * `src/lib/source-text-sanitizer.ts` --- src/components/ClinicalDashboard.tsx | 18 ++++++++-- .../clinical-dashboard/answer-content.tsx | 34 +++++++++++++++++++ .../answer-result-surface.tsx | 7 +++- .../clinical-dashboard/display-text.ts | 18 ++++++++++ .../clinical-dashboard/evidence-panels.tsx | 7 ++++ .../clinical-dashboard/output-panel.tsx | 10 ++++++ src/lib/answer-render-policy.ts | 7 ++++ src/lib/rag-answer-text.ts | 15 +++++++- src/lib/rag.ts | 30 +++++++++++++--- src/lib/source-text-sanitizer.ts | 25 +++++++++++++- 10 files changed, 161 insertions(+), 10 deletions(-) diff --git a/src/components/ClinicalDashboard.tsx b/src/components/ClinicalDashboard.tsx index fa47b66bc..6d884ce42 100644 --- a/src/components/ClinicalDashboard.tsx +++ b/src/components/ClinicalDashboard.tsx @@ -498,9 +498,13 @@ function answerTimedOutError() { } /** - * Read-only surface for a previous turn in the answer thread. Renders the - * question bubble and the natural-language answer with its source capsule; - * evidence drawers, clinical notes, and feedback stay on the latest turn only. + * Renders a collapsible, read-only view of a previous answer-thread turn with its question, answer, sources, and source-review notice. + * + * @param turn - The previous question and answer turn to display + * @param copied - Whether the turn's answer has been copied + * @param collapsed - Whether the answer content is collapsed + * @param onToggleCollapsed - Called when the answer visibility is toggled + * @param onCopy - Called with the answer text when copying is requested */ function PriorAnswerTurnSurface({ turn, @@ -678,6 +682,14 @@ function mergeDocumentRefresh(current: ClinicalDocument[], updates: ClinicalDocu }); } +/** + * Renders the clinical search dashboard, including document search, answer generation, conversation history, source management, and ingestion controls. + * + * @param initialSearchMode - The mode selected when the dashboard loads. + * @param initialQuery - The initial search or composer query. + * @param focusSearch - Whether to focus the search input on load. + * @param autoRunSearch - Whether to automatically submit the initial query. + */ export function ClinicalDashboard({ initialSearchMode = "answer", initialQuery = "", diff --git a/src/components/clinical-dashboard/answer-content.tsx b/src/components/clinical-dashboard/answer-content.tsx index 8b7edc725..d49793ac8 100644 --- a/src/components/clinical-dashboard/answer-content.tsx +++ b/src/components/clinical-dashboard/answer-content.tsx @@ -172,6 +172,12 @@ export const SourceImage = memo(function SourceImage({ ); }); +/** + * Displays the active search scope and source governance warnings. + * + * @param scope - The current search scope summary, or `null` when unavailable + * @param warnings - Source governance warnings to display + */ export function ScopeAndGovernanceNotice({ scope, warnings, @@ -234,6 +240,13 @@ export type AnswerDisplayTextOptions = { const primaryAnswerSafetySignalPattern = /\b(?:withhold|withheld|stop|cease|hold|threshold|escalat|urgent|red\s*zone|amber|immediately|do not|contraindicat|toxic)\b/i; +/** + * Produces sanitized, display-ready text for an answer. + * + * @param value - The answer text to sanitize + * @param options - Controls preformatted handling and bold-text preservation + * @returns The sanitized answer text + */ export function plainAnswerText(value: string, options: AnswerDisplayTextOptions = {}) { // clinicalProseUsefulness runs the source-noise stripper, so preformatted // answers bypass it and go straight to the lossless display path. @@ -248,6 +261,13 @@ export function plainAnswerText(value: string, options: AnswerDisplayTextOptions .trim(); } +/** + * Selects and compacts the primary answer text while preserving safety-critical guidance. + * + * @param value - The answer text to prepare for display + * @param options - Formatting options, including preformatted mode + * @returns The display-ready answer text + */ function primaryAnswerDisplayText(value: string, options: AnswerDisplayTextOptions = {}) { const cleaned = plainAnswerText(value, options); // Deterministic preformatted answers are already concise and display-ready; @@ -567,6 +587,20 @@ function SourcePreviewContent({ ); } +/** + * Displays a sanitized clinical answer with source status, source previews, and copy actions. + * + * @param text - The raw answer text to display. + * @param preformatted - Whether to preserve the supplied formatting during display processing. + * @param sourceCount - The number of direct sources associated with the answer. + * @param sourceOnly - Whether to show a notice that the answer was assembled solely from source passages. + * @param bestSource - The highest-priority source recommendation, when available. + * @param sources - Search results used to build the source preview. + * @param sourceLinks - Source links and snippets associated with the answer. + * @param copied - Whether the answer has been copied. + * @param onCopy - Callback invoked to copy the answer with source status. + * @returns The rendered answer section, or `null` when the answer has no displayable text. + */ export function NaturalLanguageAnswer({ text, preformatted = false, diff --git a/src/components/clinical-dashboard/answer-result-surface.tsx b/src/components/clinical-dashboard/answer-result-surface.tsx index 790e56cba..1619c3c19 100644 --- a/src/components/clinical-dashboard/answer-result-surface.tsx +++ b/src/components/clinical-dashboard/answer-result-surface.tsx @@ -1,4 +1,4 @@ -"use client"; +"use client"; import Link from "next/link"; import { memo, type RefObject, useCallback, useEffect, useRef, useState } from "react"; @@ -38,6 +38,11 @@ import type { } from "@/lib/types"; import { type AnswerEvidenceMapRow, type AnswerViewMode } from "@/lib/ward-output"; +/** + * Renders a staged answer with inline content and optional clinical notes, evidence, safety findings, and follow-up interfaces. + * + * @returns The staged answer surface. + */ function StagedAnswerResultSurfaceImpl({ answer, query, diff --git a/src/components/clinical-dashboard/display-text.ts b/src/components/clinical-dashboard/display-text.ts index d21e4fb5b..e752721d5 100644 --- a/src/components/clinical-dashboard/display-text.ts +++ b/src/components/clinical-dashboard/display-text.ts @@ -25,6 +25,12 @@ export type DisplayTextSanitizeOptions = { preserveBold?: boolean; }; +/** + * Normalizes display text by trimming surrounding whitespace and collapsing internal whitespace. + * + * @param value - The display text to normalize + * @returns The normalized display text + */ export function normalizeDisplayText(value: string) { return value.trim().replace(/\s+/g, " "); } @@ -189,6 +195,12 @@ export function compactSourceSnippet(value: string, options: CompactSourceSnippe return text; } +/** + * Compacts table fact fields into a deduplicated display representation. + * + * @param fact - The table fact whose fields should be compacted + * @returns The fact identifier and cleaned fields, or `null` when no displayable fields remain + */ export function compactTableFact(fact: NonNullable[number]) { const fields = [ { label: "Table", value: fact.table_title }, @@ -208,6 +220,12 @@ export function compactTableFact(fact: NonNullable[ return cleanedFields.length ? { id: fact.id, fields: cleanedFields } : null; } +/** + * Sanitizes answer text for display while removing embedded artifacts and low-information content. + * + * @param options - Controls minimum content thresholds, preformatted text handling, and bold formatting preservation. + * @returns The cleaned answer text, or an empty string when the input is empty, invalid, or artifact-like. + */ export function sanitizeAnswerDisplayText(value: string, options: DisplayTextSanitizeOptions = {}) { const normalized = ( options.preformatted diff --git a/src/components/clinical-dashboard/evidence-panels.tsx b/src/components/clinical-dashboard/evidence-panels.tsx index 1568806a8..3b1e98d96 100644 --- a/src/components/clinical-dashboard/evidence-panels.tsx +++ b/src/components/clinical-dashboard/evidence-panels.tsx @@ -569,6 +569,13 @@ function clinicalNotesAvailableTabs(sections: ClinicalDetailSection[]) { .filter((tab) => tab.count > 0); } +/** + * Builds the non-empty clinical detail sections used by the clinical notes view. + * + * @param answer - The answer from which to derive clinical detail sections. + * @param viewMode - Selects the standard or high-yield section set. + * @returns The sorted clinical detail sections with display-ready items. + */ function clinicalNotesDetailSectionsForAnswer(answer: RagAnswer, viewMode: AnswerViewMode) { const sections = viewMode === "high_yield" ? buildHighYieldClinicalOutputSections(answer) : buildClinicalOutputSections(answer); diff --git a/src/components/clinical-dashboard/output-panel.tsx b/src/components/clinical-dashboard/output-panel.tsx index 4b876fb65..12a1d1f07 100644 --- a/src/components/clinical-dashboard/output-panel.tsx +++ b/src/components/clinical-dashboard/output-panel.tsx @@ -26,6 +26,16 @@ import { buildHighYieldClinicalOutputSections, } from "@/lib/ward-output"; +/** + * Renders a source-backed clinical answer with structured details, lead content, or an evidence map. + * + * @param answer - The clinical answer to display + * @param collapsed - Whether to wrap the content in a collapsed utility drawer + * @param showLead - Whether to display the concise lead section + * @param viewMode - The presentation mode for the clinical output + * @param onViewModeChange - Callback invoked when the presentation mode changes + * @param evidenceMapRows - Evidence map rows to display instead of computing them from the answer + */ export function ClinicalOutputPanel({ answer, collapsed = false, diff --git a/src/lib/answer-render-policy.ts b/src/lib/answer-render-policy.ts index 29f6493dc..9f198c588 100644 --- a/src/lib/answer-render-policy.ts +++ b/src/lib/answer-render-policy.ts @@ -544,6 +544,13 @@ export function formatAnswerRenderCopyText(args: { .trim(); } +/** + * Builds a trust-gated render model for a clinical answer, including sources, evidence, warnings, and copy-ready text. + * + * @param answer - The clinical answer and associated evidence to render + * @param options - Optional source overrides and diagnostic decision details + * @returns The structured answer render model + */ export function buildAnswerRenderModel( answer: RagAnswer, options: BuildAnswerRenderModelOptions = {}, diff --git a/src/lib/rag-answer-text.ts b/src/lib/rag-answer-text.ts index 80790a050..418954660 100644 --- a/src/lib/rag-answer-text.ts +++ b/src/lib/rag-answer-text.ts @@ -197,13 +197,26 @@ function removeBadAnswerFragments(value: string) { // immediately followed by a community schedule with no sentence break (e.g. "...monitored daily // for inpatients for community patients weekly..."). The synthesis prompt handles most of these, // but this is a narrow deterministic safety-net for the clearest recurring pattern. It also -// consumes the original comma so it cannot produce a double comma. +/** + * Separates flattened inpatient and community patient schedule phrases into distinct sentences. + * + * @param value - Clinical prose containing a setting-related run-on phrase + * @returns The prose with the targeted setting run-on replaced by separate sentences + */ function separateSettingRunOns(value: string): string { return value .replace(/\bfor inpatients,?\s+for community patients,?/gi, "for inpatients. For community patients,") .replace(/\bfor community patients,?\s+for inpatients,?/gi, "for community patients. For inpatients,"); } +/** + * Cleans clinical answer text by removing artifacts, normalizing formatting, and improving readability. + * + * @param value - The clinical answer text to polish + * @param options - Formatting options + * @param options.preserveBold - Whether to preserve inline bold markers + * @returns The polished clinical answer text + */ export function polishClinicalAnswerProse(value: string, options: { preserveBold?: boolean } = {}) { // Bold markers normally come off before bullet normalization so an emphasized // item ("o **Reduce dose**") still reads as a sub-bullet to the "o" matcher. diff --git a/src/lib/rag.ts b/src/lib/rag.ts index b7e358b24..333e4087c 100644 --- a/src/lib/rag.ts +++ b/src/lib/rag.ts @@ -1336,7 +1336,14 @@ function mergeSearchResults(primary: SearchResult[], secondary: SearchResult[]) return Array.from(merged.values()); } -/** Search text chunk candidates. */ +/** + * Retrieves lexical document chunk candidates for the supplied query variants. + * + * @param queryVariants - Query variants used for strict matching and recall-oriented fallback searches. + * @param matchCount - Maximum number of candidates requested for the primary query. + * @param telemetry - Optional retrieval telemetry updated with RPC failures and text-relaxation usage. + * @returns Matching document chunks, using corrected or relaxed queries when strict matching produces no candidates. + */ async function searchTextChunkCandidates(args: { supabase: ReturnType; queryVariants: string[]; @@ -1621,7 +1628,12 @@ async function fetchDocumentTitleAliasRows(args: { })); } -/** Search document lookup fast path. */ +/** + * Retrieves and ranks document chunks for document-focused queries. + * + * @param args - Search configuration, including the required owner scope and optional document restrictions. + * @returns Ranked document lookup results, limited to `matchCount`. + */ async function searchDocumentLookupFastPath(args: { supabase: ReturnType; query: string; @@ -1919,7 +1931,12 @@ async function loadChunksForSignalMatches(args: { .filter(Boolean) as SearchResult[]; } -/** Search table fact candidates. */ +/** + * Retrieves document chunks containing table facts relevant to a query. + * + * @param args - Retrieval options, including query variants, scope filters, result limit, and optional telemetry. + * @returns Search results containing the highest-ranked table facts grouped by source chunk. + */ async function searchTableFactCandidates(args: { supabase: ReturnType; query: string; @@ -2884,7 +2901,12 @@ function shouldUseMemoryBeforeFastPath(queryClass: RagQueryClass) { return queryClass === "table_threshold" || queryClass === "medication_dose_risk" || queryClass === "comparison"; } -/** Search chunks with telemetry. */ +/** + * Retrieves and ranks document chunks using lexical, structured, memory, and embedding-based evidence, while recording retrieval telemetry. + * + * @param args - Retrieval options, including the query, scope, search mode, and embedding preferences. + * @returns The ranked search results and telemetry describing the retrieval process. + */ export async function searchChunksWithTelemetry(args: SearchChunksArgs) { assertGlobalSearchAllowed(args); throwIfAborted(args.signal); diff --git a/src/lib/source-text-sanitizer.ts b/src/lib/source-text-sanitizer.ts index d6a71c66d..848152681 100644 --- a/src/lib/source-text-sanitizer.ts +++ b/src/lib/source-text-sanitizer.ts @@ -288,6 +288,11 @@ export function sourceTextForClinicalProse(text: string) { return compactWhitespace(stripLowYieldSourceNoise(stripInternalImageDataBlocks(text))); } +/** + * Produces clinical prose with meaningful line breaks preserved. + * + * @returns The cleaned text with normalized whitespace and low-yield source noise removed. + */ export function sourceTextForClinicalProsePreservingBreaks(text: string) { return readableWhitespace(stripLowYieldSourceNoise(sourceTextForDisplayPreservingBreaks(text))); } @@ -300,12 +305,23 @@ export function sourceTextForClinicalProsePreservingBreaks(text: string) { // leave garble). Apply only glyph repair + whitespace collapse, matching the // server's own `finalizeRagAnswerQuality` exemption for `preformatted && grounded`. // When preserveBold is false, strip **bold** markers so literal Markdown markers -// never leak through to the display. +/** + * Normalizes preformatted text for display while preserving its readable structure. + * + * @param options - Controls whether Markdown bold markers are preserved. + * @returns The normalized text, with bold markers removed unless `preserveBold` is `true`. + */ export function normalizePreformattedDisplayText(text: string, options: { preserveBold?: boolean } = {}) { const normalized = readableWhitespace(text); return options.preserveBold ? normalized : normalized.replace(/\*\*([^*]+)\*\*/g, "$1"); } +/** + * Determines whether source text contains little clinically useful content. + * + * @param text - Source text to assess. + * @returns `true` if the text is predominantly source noise or contains only a short remainder, `false` otherwise. + */ export function isLowYieldClinicalText(text: string) { const cleaned = sourceTextForClinicalProse(text); if (!cleaned) return true; @@ -595,6 +611,13 @@ const standaloneBloodValueLinePattern = const bloodValueWithNounTailLinePattern = /^o\s+(?:\*\*)?(?:rh(?:d)?\s+)?(?:pos(?:itive)?|neg(?:ative)?)(?:\*\*)?\s+(?:blood(?!\s+(?:cultures?|tests?|screens?|samples?|results?)\b)|red\s+cells?)\b/i; +/** + * Replaces OCR-style lowercase `o` sub-bullets while preserving blood-group value text. + * + * @param text - Text containing potential OCR sub-bullet markers + * @param joiner - Text used to replace recognized sub-bullet markers + * @returns Text with eligible sub-bullet markers replaced + */ function replaceSubBulletOGlyphs(text: string, joiner: string) { return text.replace(subBulletOGlyphPattern, (match, offset: number) => { const before = text.slice(0, offset);