Skip to main content
Synced from the repo — do not edit here

Canonical source: docs/claude/labs.md. This page is generated by docs/scripts/sync-handbook.mjs. Edit the source file in the repo; changes appear here on the next build.

Labs System

The labs system spans lab ordering, document upload, AI analysis, registry management, and visualization.

End-to-End Lab Flow

  1. Ordering (Junction Health): Test catalog -> Lab packages -> Place order
  2. Upload: Upload PDF/Image -> Text extraction -> AI analysis
  3. Storage: labs collection, documentLinks, documentSummaries
  4. Display: Client summary, Labs tab, Copilot access

Lab Ordering (Junction Health)

Integration: functions_junction.py

FunctionPurpose
junction_get_test_catalogFetch available lab tests
junction_create_lab_packageCreate saved test bundle
junction_order_testOrder specific tests for patient
junction_order_from_packageOrder from saved package
junction_get_ordersList orders for patient
junction_get_resultsFetch results for order
junction_webhookHandle order/result updates

Collections:

  • clinicsv2/{clinic}/lab_orders/{id} - Order records
  • clinicsv2/{clinic}/lab_packages/{id} - Saved test bundles
  • clinicsv2/{clinic}/config/junction - API key configuration

Lab Marketplace Configuration

UI: Basis Flow Web Marketplace -> Labs Tab (basisflow-web/app/(main)/marketplace/page.tsx)

Features:

  • Test catalog browsing with search
  • Create/edit lab packages (saved test bundles)
  • Enable/disable Junction integration per clinic
  • API key configuration

Lab Upload & Analysis

Document Processing Flow:

  1. Staff uploads PDF/image via ImportLabModal
  2. File stored in Cloud Storage
  3. analyze_document_summary extracts text (OCR if needed)
  4. DocumentProcessor runs AI analysis:
    • Pattern matching for common lab values (regex)
    • AI analysis for complex/unclear values
    • Confidence scoring for extracted data
  5. Extracted values stored in labs collection
  6. Summary stored in documentSummaries for Copilot

Key Files:

  • functions_ai_documents.py - Document upload/analysis entry point
  • document_processor.py - Core extraction logic
  • functions_lab_analysis.py - Lab-specific analysis
  • functions_transcriber_replacement.py - Legacy lab analysis functions

Analysis Model:

class ExtractedDataPoint:
field_name: str # e.g., "ldl_cholesterol"
value: float # e.g., 145.0
unit: str # e.g., "mg/dL"
confidence: float # 0.0-1.0
source_text: str # Original text snippet
health_type: str # Canonical metric key
timestamp: datetime # Sample collection date

One-source registry + verdict engine (updated 2026-07-18 — #386/#392)

The current source of truth is a single generated registry that all surfaces read (no more per-surface drift):

  • generated/lab_registry.json (~800+ analytes) is generated by tools/build_lab_registry.py from the analyte sources, merging core-over-registry refRanges (age/gender-based), canonicalUnit, and unit conversions. It generates the frontend TS (tools/generate_lab_ts.pybasisflow-web/lib/lab-analytes-generated.ts) and the mobile Dart mirror, all CI-drift-gated (tools/validate_lab_maps.py, validate_lab_ranges.py) so generated output can't diverge from source.
  • lab_verdict.py is the ONE verdict engine. evaluate_verdict(analyte_key, value, unit, sex) → in-range/out-of-range, using the unified registry. canonical_analyte_key() resolves aliases (lab_analyte_aliases.json) so a doc stored under a variant key still finds its range; _norm_unit() collapses cosmetic unit spellings while keeping genuinely-different units distinct (mmol/L ≠ mg/dL — the "HDL 3.9" guard). LOINC via lab_loinc_map.json.
  • Aliases + canonicalization at ingest: every ingestion path — AI-analyze (functions_ai_documents.py), Junction (functions_junction.py), manual upload — canonicalizes the analyte key (one lab = one key, no duplicate graph series) and normalizes units (no mixed mmol/mg-dL on one graph).
  • Persist verdict at write (#392): the computed verdict is stored on the lab doc at write time so Atlas + the UI read the same verdict (Atlas parity). (NOTE 2026-07-18: committed to master but the ingestion functions may not be redeployed yet — verify live.)
  • Lab values feed protocol efficacy: lab-type biomarkers on a protocol read from users/{uid}/labs (analyteKey) — see programs-protocols.md → "Lab-type biomarker routing (#6)".
  • Benchmarks: wearable/body-comp metric benchmarks (zone minutes WEEKLY, FFMI, VO2max) live alongside in generated/metric_benchmarks.json (tools/generate_metric_benchmarks.py); lab reference ranges in generated/lab_reference_ranges_generated.json. Registry consumers: mobile findBenchmarkForType, web benchmark-defaults.ts. (Several of these generated artifacts + generators were deploy-held/uncommitted as of 2026-07-18 — the registry regeneration was half-landed; check git before trusting.)

Lab Registry (legacy endpoint)

The registry provides canonical definitions for lab analytes (names, units, reference ranges).

Endpoint: get_lab_registry (HTTP)

Response:

{
"analytes": {
"ldl_cholesterol": {
"display_name": "LDL Cholesterol",
"unit": "mg/dL",
"reference_low": 0,
"reference_high": 100
}
},
"panels": {
"lipid_panel": {
"display_name": "Lipid Panel",
"analytes": ["ldl_cholesterol", "hdl_cholesterol"]
}
}
}

Clinic Synonyms: Clinics can define their own mappings for non-standard lab names:

  • upsert_clinic_lab_synonyms - Update clinic-specific synonyms
  • Storage: clinicsv2/{clinic}/settings/labSynonyms

Lab Visualization

Client Summary (ClientDetailPage.tsx -> SummaryTab):

  • Groups labs by source document
  • Shows count and out-of-range indicators
  • Clicking navigates to Labs tab or document preview

Labs Tab (ClientDetailPage.tsx -> LabsTab):

  • Lists all lab results by category
  • Shows trend charts for individual analytes
  • Reference range indicators (low/normal/high)
  • Age/gender-aware reference ranges when available
  • Import new labs modal

Data Sources:

  • clinicsv2/{clinic}/clinic_users/{uid}/labs - Individual lab values
  • clinicsv2/{clinic}/clinic_users/{uid}/documentLinks - Source documents

Lab Data Model

interface LabResult {
id: string;
displayName: string; // "LDL Cholesterol"
value: number; // 145
unit: string; // "mg/dL"
referenceRange?: {
low?: number;
high?: number;
text?: string; // "Optimal: <100"
};
collectedAt: Timestamp; // Sample date
source?: {
documentId?: string; // Reference to source doc
type?: 'junction' | 'upload' | 'manual';
};
category?: string; // "Lipid Panel", "Metabolic", etc.
analyteKey?: string; // Canonical key from registry
}

Key Files

FilePurpose
functions_junction.pyJunction Health integration
functions_ai_documents.pyDocument upload/analysis
document_processor.pyLab value extraction
metric_registry.pyMetric definitions
basisflow-web/...ClientDetailPage.tsxLabs visualization
basisflow/...tab_labs.dartLegacy Flutter labs tab