# Cascade Protocol Schema Reference

A comprehensive reference for all Cascade Protocol RDF/OWL vocabularies and SHACL validation shapes.

**Version:** June 2026
**Website:** https://cascadeprotocol.org
**Organization:** Cascade Agentic Labs LLC

---

## Table of Contents

1. [Overview](#overview)
2. [Three-Layer Architecture](#three-layer-architecture)
3. [Core Vocabulary](#core-vocabulary-v33)
4. [Clinical Vocabulary](#clinical-vocabulary-v19)
5. [Clinical SHACL Shapes](#clinical-shacl-shapes)
6. [Health Vocabulary](#health-vocabulary-v24)
7. [POTS Vocabulary](#pots-vocabulary-v14)
8. [Coverage Vocabulary](#coverage-vocabulary-v13)
9. [Checkup Vocabulary](#checkup-vocabulary-v32)
10. [Checkup SHACL Shapes](#checkup-shacl-shapes-adult)
11. [SHACL Validation](#shacl-validation)
12. [Diabetes Vocabulary](#diabetes-vocabulary-v10-draft)
13. [Genomics Vocabulary (Draft)](#genomics-vocabulary-v10-draft)
14. [Advisory Vocabulary (Draft)](#advisory-vocabulary-v10-draft)
15. [Evidence Vocabulary (Draft)](#evidence-vocabulary-v10-draft)
16. [Workbench Vocabulary (Draft)](#workbench-vocabulary-v10-draft)
17. [Settings Storage Convention](#settings-storage-convention-phase-b-target)
18. [Pod Storage Conventions](#pod-storage-conventions)
19. [Namespace Reference](#namespace-reference)

---

## Overview

The Cascade Protocol provides a modular ontology framework for representing personal health and wellness data using Linked Data standards (RDF, OWL, SHACL). The protocol is designed for:

- **Privacy-first architecture**: Local-first storage with encryption
- **Interoperability**: Alignment with FHIR, SNOMED CT, LOINC, and W3C PROV-O
- **Consumer wellness focus**: Data classified as consumer-generated (non-diagnostic)
- **Solid Pod compatibility**: WebID-based access control

### Design Principles

1. **Modularity**: Core concepts are stable; domain vocabularies evolve independently
2. **Standards-based**: Built on W3C RDF, OWL, and PROV-O recommendations
3. **Future-proof**: New health apps can extend without breaking existing data
4. **Provenance tracking**: All data includes comprehensive lineage metadata

### Guiding Principles

1. **Established vocabularies first.** Reference FHIR, LOINC, SNOMED CT, PROV-O, and other established standards before creating Cascade-specific terms. We only invent vocabulary when no standard exists.
2. **Three-layer ontology architecture.** Every data type follows the Layer 1 (standards) → Layer 2 (domain) → Layer 3 (patient) pattern described above.
3. **SNOMED CT and LOINC mappings required.** All clinical and wellness metrics must map to standard codes unless no code exists — in which case the gap is documented explicitly.
4. **Clear vocabulary separation.** `clinical:` for EHR-derived facts, `health:` for consumer device data, `pots:` for POTS screening protocol data (Layer 2), `coverage:` for insurance/benefits data (Layer 2), `checkup:` for patient-facing summaries, `core:` for cross-cutting primitives, and domain prefixes for specialized protocols.
5. **Privacy-first, local-first.** Data stored in Solid Pods with AES-256-GCM encryption at rest. No external API calls for core functionality.
6. **Provenance tracking.** W3C PROV-O metadata on all data — distinguishing consumer-generated (device/user) from clinical-generated (EHR/provider) sources.

### Ontology Objectives

1. **Interoperability:** Any domain property should be traceable to established standard codes (SNOMED CT, LOINC, FHIR) so that Cascade data can round-trip with clinical systems.
2. **Completeness:** Every data type serialized to Turtle has a corresponding vocabulary definition. No undefined terms.
3. **Consistency:** All vocabularies follow the same structural patterns — OWL ontology headers, version info, changelogs, and SHACL shapes where appropriate.
4. **Discoverability:** Every vocabulary has both a machine-readable `.ttl` file and a human-readable documentation page, linked from this index.
5. **Accuracy:** Version numbers in documentation match the actual `.ttl` file versions. Changelogs reflect all changes.

---

## Three-Layer Architecture

The Cascade Protocol uses a three-layer ontology architecture to balance interoperability with established healthcare standards and the need for patient-friendly data presentation.

| Layer                              | Namespaces                                                                 | Role                                                                                                                             | Example                                                                    |
| ---------------------------------- | -------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| **Layer 1: Established Standards** | `fhir:`, `sct:` (SNOMED CT), `loinc:`                                      | Canonical clinical and observation codes from healthcare standards bodies                                                        | `sct:364075005` (Heart rate), `loinc:40443-4` (Heart rate resting)         |
| **Layer 2: Domain Vocabulary**     | `health:` (wellness/device), `clinical:` (EHR), `pots:` (POTS screening protocol), `coverage:` (insurance/benefits), `cascade:` (cross-cutting) | Domain-specific properties linking to Layer 1 codes. Adds longitudinal tracking, trend inference, and device-specific semantics. | `health:restingHeartRate` annotated with `health:snomedCode sct:364075005` |
| **Layer 3: Patient-Facing**        | `checkup:` (summaries, intake forms, visit preparation)                    | Aggregated summaries, intake forms, insights, and visit preparation                                                              | `checkup:WellnessSummary` referencing Layer 2 observations                 |


### When is Layer 2 Needed?

Not all data domains require Layer 2 classes. Layer 2 is needed when the domain requires:

- **Longitudinal tracking** — medications use `clinical:MedicationUseEpisode` to track use over time
- **Computed aggregation** — lab results use `clinical:LabTestSeries` for trend inference
- **Device-specific data modeling** — wellness metrics use `health:` properties with SNOMED/LOINC annotations
- **Normalization from FHIR's multiple expression paths.** FHIR allows the same clinical fact to be expressed several ways — a procedure date as `performedDateTime` or `performedPeriod.start`, a medication as `MedicationStatement` or `MedicationRequest`. FHIR RDF preserves these variants faithfully, but that makes deduplication impossible without embedding FHIR-specific logic. Layer 2 normalizes to one canonical representation per clinical concept, which is what enables cross-system reconciliation.

Conditions, allergies, and family history are simple categorical data that map directly from Layer 1 standard codes (SNOMED, ICD-10) to Layer 3 patient summaries (`checkup:ConditionSummary`, `checkup:AllergySummary`). No Layer 2 intermediary is needed.


**1. Layer 1 — tighter definition**

Code systems and terminologies maintained by recognized healthcare standards bodies that provide canonical identifiers for clinical concepts, observations, and measurements._ That would include things like CVX (vaccine codes), RxNorm (drug codes), or CPT (procedure codes) if you needed them, but would exclude general-purpose web vocabularies.

**2. Layer 2 — additional examples**


- **Semantic bridging.** `health:restingHeartRate` is a human-readable property that carries SNOMED and LOINC annotations. Without it, your serialized data would just say `sct:364075005` with `loinc:40443-4`, which is machine-interoperable but unreadable. Layer 2 gives you a named property that's meaningful to developers while preserving the standard code linkage.
    
- **Adding context that standards don't capture.** SNOMED gives you "heart rate" as a concept. Layer 2 lets you distinguish resting vs. walking heart rate, attach device provenance, define measurement periods, and carry trend metadata — none of which exist in the code system itself.
    
- **Unifying multiple standard codes under one concept.** A `health:BPStatistics` class pulls together systolic (LOINC 8480-6) and diastolic (LOINC 8462-4) and adds AHA categorization — something neither LOINC code captures alone.
    
- **Defining the shape of serialized data.** Layer 1 codes are just identifiers. Layer 2 defines the actual RDF structure — what properties exist, their types, their ranges — that the SDK serializes and deserializes.
    

simple categorical data like conditions, allergies, and family history that map directly from Layer 1 codes to Layer 3 summaries. That's a useful negative test.

**3. Layer 3 — scope, restrictions, and graduation**

Layer 3 is where all the _patient-facing, app-specific_ classes live. But it's broader than just "downstream of Layer 2." Several patterns emerge:

- **Aggregation across Layer 2 sources** — `WellnessSummary` pulls from multiple `health:` properties into a single patient-readable snapshot.
- **App-layer enrichment via the mixed namespace pattern** — `LabResultSummary` and `ImmunizationSummary` add a single `checkup:` categorization property while referencing `clinical:` properties directly. They don't duplicate data, just add a presentation lens.
- **Purely app-specific concepts with no Layer 1/2 equivalent** — `DiscussionTopic`, `CheckInSettings`, `MedicationChangeRecord`. These are Cascade-proprietary and explicitly document the gap.
- **Direct Layer 1 → Layer 3 (skipping Layer 2)** — `DailyCheckIn`, questionnaire responses. The doc explicitly notes "Layer 2: Skipped" with rationale for each.

Potential guidelines for Layer 3 classes: They should be tied to a specific user-facing feature or view, and be the _only_ layer that app UI code touches directly.

**Graduation from Layer 3 to Layer 2**
- when a Layer 3 concept starts being needed across multiple apps. For example, if a Layer 3 summary class turned out to be useful not just in Cascade Checkup but also in POTS Check or a future diabetes app, that's a signal it should move to a Layer 2 domain vocabulary.

### Why Not Use FHIR RDF Directly?

FHIR has an official RDF serialization ([FHIR RDF](http://hl7.org/fhir/rdf.html)) that maps every FHIR resource to the `fhir:` namespace. Cascade uses `fhir:` as a Layer 1 vocabulary and aligns all Layer 2 classes to it via `rdfs:subClassOf fhir:Procedure`, `rdfs:subClassOf fhir:Encounter`, etc. But FHIR RDF is not used as the primary serialization format for three reasons:

1. **Ergonomics.** FHIR RDF requires heavy blank-node nesting and `fhir:index` ordering predicates to faithfully represent JSON arrays and complex types. A SPARQL query for a lab panel's LOINC code requires a five-step path (`fhir:DiagnosticReport.code/fhir:CodeableConcept.coding/fhir:Coding.code/fhir:value`). The Layer 2 equivalent is `clinical:loincCode`.

2. **Normalization.** FHIR's data model evolved over many years with multiple ways to express the same clinical fact. FHIR RDF preserves all these variants faithfully. Layer 2 picks one canonical form per concept — a prerequisite for cross-system deduplication and reconciliation.

3. **Perspective.** FHIR is designed for clinical system interoperability. Its resources contain metadata meaningful to EHR systems (security labels, version IDs, transaction references) but irrelevant to a patient's health profile. Layer 2 extracts what matters to the patient and discards the rest, which is why Cascade is privacy-first.

FHIR RDF is Layer 1 infrastructure — a reference anchor for semantic alignment, not a storage format.

---

## Core Vocabulary v3.3

**Namespace:** `https://ns.cascadeprotocol.org/core/v1#`
**Prefix:** `cascade:`
**Status:** Stable

The Core Vocabulary defines cross-cutting concepts used by all Cascade Protocol health data applications.

### Ontology Metadata

```turtle
@prefix cascade: <https://ns.cascadeprotocol.org/core/v1#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix dct: <http://purl.org/dc/terms/> .
@prefix prov: <http://www.w3.org/ns/prov#> .

<https://ns.cascadeprotocol.org/core/v1#> a owl:Ontology ;
    dct:title "Cascade Protocol Core Vocabulary"@en ;
    dct:description "Core vocabulary for schema versioning, data provenance, identity management, and patient demographics across all Cascade Protocol applications"@en ;
    dct:creator "Cascade Agentic Labs" ;
    owl:versionInfo "3.3" .
```

### Data Provenance Classes

The DataProvenance taxonomy uses a class hierarchy with two broad parent categories and six leaf subclasses used by the SDK:

| Class | Parent | Description |
|-------|--------|-------------|
| `cascade:DataProvenance` | `prov:Entity` | Root classification of how health data was generated or collected. |
| `cascade:ConsumerGenerated` | `cascade:DataProvenance` | Data generated directly by the user through personal devices (non-clinical setting). |
| `cascade:ClinicalGenerated` | `cascade:DataProvenance` | Data generated in a clinical setting under healthcare provider supervision. |

#### Consumer-Generated Subclasses (v1.2)

| Class | Parent | Description |
|-------|--------|-------------|
| `cascade:DeviceGenerated` | `cascade:ConsumerGenerated` | Data generated by a consumer health device (Apple Watch, blood pressure cuff, etc.) without clinical supervision. |
| `cascade:SelfReported` | `cascade:ConsumerGenerated` | Data manually entered by the patient (symptom logs, medication adherence, intake form fields). |
| `cascade:ConsumerWellness` | `cascade:ConsumerGenerated` | Aggregated wellness data from consumer platforms (Apple Health, Google Fit). |
| `cascade:AIAsserted` | `cascade:ConsumerGenerated` | Content surfaced by a general-purpose AI assistant in a patient-directed conversation (e.g. ChatGPT, Claude), **not** grounded in clinical sources. MUST be applied to assertions imported from AI conversations so they can never be mistaken for clinically-extracted data (`cascade:AIExtracted`) or verified records (`cascade:EHRVerified`). Marks content that must be evidence-checked before any reliance. (v3.3) |

#### Clinical-Generated Subclasses (v1.2)

| Class | Parent | Description |
|-------|--------|-------------|
| `cascade:EHRVerified` | `cascade:ClinicalGenerated` | Data imported from a verified Electronic Health Record system (Epic MyChart, Cerner, etc.). |
| `cascade:ScannedDocument` | `cascade:ClinicalGenerated` | Data extracted from a scanned or photographed clinical document. |
| `cascade:AIExtracted` | `cascade:ClinicalGenerated` | Data extracted from clinical documents using AI/NLP processing. |

> **SDK Alignment:** The SDK `DataProvenance.swift` enum maps to the six leaf subclasses (`EHRVerified`, `DeviceGenerated`, `ScannedDocument`, `SelfReported`, `AIExtracted`, `ConsumerWellness`). The parent categories (`ConsumerGenerated`, `ClinicalGenerated`) serve as taxonomy anchors — they are not referenced by serializer code but enable SPARQL queries like `?x rdfs:subClassOf+ cascade:ClinicalGenerated`.

> **AIExtracted vs AIAsserted (v3.3):** Keep these two AI provenance leaves distinct. `cascade:AIExtracted` (a `ClinicalGenerated` subclass) marks structured records pulled out of clinical documents by an extraction pipeline — clinically grounded source. `cascade:AIAsserted` (a `ConsumerGenerated` subclass, new in core v3.3) marks ungrounded content surfaced by a general-purpose AI assistant in a patient-directed conversation. AIAsserted content must be evidence-checked before reliance and must never be promoted to a clinical provenance class.

### Data Properties

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `cascade:schemaVersion` | owl:DatatypeProperty | xsd:string | Semantic version of the ontology schema (format: major.minor.patch). |
| `cascade:dataProvenance` | owl:ObjectProperty | cascade:DataProvenance | Classification of how data was generated (consumer vs clinical). |
| `cascade:creatorWebID` | owl:ObjectProperty | rdfs:Resource | Solid WebID URI of the user who created this data. Subproperty of `prov:wasAttributedTo`. |
| `cascade:sourceOrganization` | owl:DatatypeProperty | xsd:string | Organization that provided this record (e.g., "Kaiser Permanente", "Mayo Clinic"). Populated from FHIR `meta.source` or contained Organization reference during clinical record import. (v2.3) |
| `cascade:sourceDeviceName` | owl:DatatypeProperty | xsd:string | Device or app that recorded this measurement (e.g., "Apple Watch Series 9", "Omron BP Monitor"). Populated from HealthKit `HKSource` contributing app/device name. (v2.3) |

### Reconciliation Properties (v2.7)

> **Implementation note:** Phase 1 of the vocabulary refactor (2026-03-11) changed status and resolution values from string literals to named individuals, updated `cascade:conflictField` to store full predicate URIs, dropped the redundant `cascade:mergedSources` property, and renamed `cascade:conflictValues` to `cascade:conflictDescription`. v2.7 (2026-03-12) removed `cascade:conflictDescription` — `cascade:conflictDetail` blank nodes now carry an `rdfs:comment` for human-readable summaries. See [cascade-reconcile-experiment/docs/2026-03-11-PLAN-vocabulary-refactor.md] for the full phased plan.

Added to support multi-system data normalization via `cascade reconcile`. When a record has been processed by the reconciliation pipeline, these properties describe its origin and any conflicts that were detected and resolved.

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `cascade:sourceSystem` | owl:DatatypeProperty | xsd:string | The originating healthcare system name (e.g., "primary-care", "specialist", "hospital"). Added by `cascade convert --source-system` or the reconciliation pipeline. Enables provenance tracking across multi-system imports. |
| `cascade:reconciliationStatus` | owl:ObjectProperty | Named individual | Status of this record after multi-system reconciliation. Values are named individuals: `cascade:Canonical` (`https://ns.cascadeprotocol.org/core/v1#Canonical`) — unique record, no match across systems; `cascade:Merged` (`https://ns.cascadeprotocol.org/core/v1#Merged`) — deduplicated from multiple sources; `cascade:ConflictResolved` (`https://ns.cascadeprotocol.org/core/v1#ConflictResolved`) — conflicting values resolved via trust priority; `cascade:UnresolvedConflict` (`https://ns.cascadeprotocol.org/core/v1#UnresolvedConflict`) — flagged for manual clinical review; `cascade:WithinSourceDuplicate` (`https://ns.cascadeprotocol.org/core/v1#WithinSourceDuplicate`) — encounter-instance duplicate within same source system, suppressed during Pass 1 within-source deduplication. (v2.6) |
| `cascade:mergedFrom` | owl:ObjectProperty | rdfs:Resource | Links the canonical record to the original source record URIs that were merged into it. Multiple values permitted. Subproperty of `prov:wasDerivedFrom`. |
| `cascade:conflictResolution` | owl:ObjectProperty | Named individual | Strategy used to resolve a conflict between records from different systems. Values are named individuals: `cascade:TrustPriority` (`https://ns.cascadeprotocol.org/core/v1#TrustPriority`) — higher-trust source wins; `cascade:MergeValues` (`https://ns.cascadeprotocol.org/core/v1#MergeValues`) — fill missing fields from all sources; `cascade:FlagUnresolved` (`https://ns.cascadeprotocol.org/core/v1#FlagUnresolved`) — cannot auto-resolve, requires clinical review. |
| `cascade:conflictField` | owl:ObjectProperty | rdfs:Resource | The full URI of the RDF predicate where conflicting values were found across systems (e.g., `<https://ns.cascadeprotocol.org/health/v1#status>`, `<https://ns.cascadeprotocol.org/health/v1#resultValue>`). Stored as a URI reference, not a prefixed name string. |
| ~~`cascade:conflictDescription`~~ | owl:DatatypeProperty | xsd:string | **Removed v2.7.** Was informational prose describing conflicting values across systems. Replaced by `cascade:conflictDetail` structured blank node (v2.5); blank nodes carry an `rdfs:comment` for human-readable summaries. |
| `cascade:conflictDetail` | owl:ObjectProperty | cascade:ConflictDetail | Links a reconciled record to a structured `cascade:ConflictDetail` blank node describing per-system conflict values. Blank node includes `rdfs:comment` with human-readable conflict summary. (v2.5) |
| `cascade:ConflictDetail` | owl:Class | — | Structured representation of conflicting values across source systems for a single property. Used as a blank node linked from `cascade:conflictDetail`. (v2.5) |
| `cascade:conflictFor` | owl:ObjectProperty | rdfs:Resource | The predicate URI on which the conflict was detected. Links a `cascade:ConflictDetail` to the conflicting property. (v2.5) |
| `cascade:systemValue` | owl:ObjectProperty | — | Links a `cascade:ConflictDetail` to a blank node representing one source system's value for the conflicting property. (v2.5) |
| `cascade:forSystem` | owl:DatatypeProperty | xsd:string | The name of the source EHR system (e.g., `"primary-care"`, `"specialist"`) within a `cascade:systemValue` blank node. (v2.5) |

#### Example: Reconciled Condition Record

```turtle
<urn:uuid:canonical-condition-001> a health:ConditionRecord ;
    cascade:dataProvenance cascade:EHRVerified ;
    cascade:schemaVersion "1.3" ;
    cascade:sourceSystem "primary-care" ;
    health:conditionName "Ischemic heart disease (disorder)" ;
    health:status "active" ;
    health:snomedCode sct:414545008 ;
    # Reconciliation provenance
    cascade:reconciliationStatus cascade:ConflictResolved ;
    cascade:mergedFrom <urn:uuid:primary-care-condition-01>, <urn:uuid:specialist-condition-07> ;
    cascade:conflictResolution cascade:TrustPriority ;
    cascade:conflictField <https://ns.cascadeprotocol.org/health/v1#status> ;
    cascade:conflictDetail [
        a cascade:ConflictDetail ;
        cascade:conflictFor <https://ns.cascadeprotocol.org/health/v1#status> ;
        cascade:systemValue [ cascade:forSystem "primary-care" ; rdf:value "active" ] ;
        cascade:systemValue [ cascade:forSystem "specialist" ; rdf:value "resolved" ]
    ] ;
    prov:wasDerivedFrom <urn:uuid:primary-care-condition-01>, <urn:uuid:specialist-condition-07> .
```

### Vocabulary Organization (v1.3)

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `cascade:subConcern` | owl:AnnotationProperty | xsd:string | Classifies a vocabulary class by its functional role within a vocabulary. Values are vocabulary-specific documented conventions (e.g., 'summary', 'intake', 'analytics', 'identity', 'app-config', 'structural', 'deprecated'). |

### Shared Preference Properties (v1.3)

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `cascade:notificationsEnabled` | owl:DatatypeProperty | xsd:boolean | Whether the user has enabled push notifications across Cascade apps. |
| `cascade:preferredUnits` | owl:DatatypeProperty | xsd:string | User's preferred unit system: 'metric' or 'imperial'. |

### Usage Example

```turtle
@prefix cascade: <https://ns.cascadeprotocol.org/core/v1#> .
@prefix pots: <https://ns.cascadeprotocol.org/pots/v1#> .
@prefix prov: <http://www.w3.org/ns/prov#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

<#pots-check-123> a pots:POTSCheckResult ;
    cascade:schemaVersion "1.2" ;
    cascade:dataProvenance cascade:ConsumerGenerated ;
    prov:wasAttributedTo <https://id.cascadeprotocol.org/users/abc123> ;
    prov:wasGeneratedBy [
        a prov:Activity ;
        prov:wasAssociatedWith <https://id.cascadeprotocol.org/users/abc123> ;
        prov:startedAtTime "2025-10-31T10:00:00Z"^^xsd:dateTime
    ] .
```

### Vocabulary Organization (v1.3)

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `cascade:subConcern` | owl:AnnotationProperty | xsd:string | Classifies a vocabulary class by its functional role (e.g., 'summary', 'intake', 'analytics', 'identity', 'app-config', 'structural', 'deprecated'). |

### Shared Preference Properties (v1.3)

Cross-app user preferences for the `/settings/shared/preferences.ttl` path.

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `cascade:notificationsEnabled` | owl:DatatypeProperty | xsd:boolean | Whether push notifications are enabled across Cascade apps. |
| `cascade:preferredUnits` | owl:DatatypeProperty | xsd:string | Preferred unit system: 'metric' or 'imperial'. |

### Patient Profile Classes (v2.0)

Health-specific patient demographics promoted from `checkup:` namespace as part of the Schema Refactoring Plan (WS6). Designed as a Solid WebID Profile extension for health applications.

| Class | Parent | Description |
|-------|--------|-------------|
| `cascade:PatientProfile` | `rdfs:Resource` | Health-specific patient demographics (Solid WebID Profile extension). Consolidates identity properties previously in `checkup:PatientProfile`. |
| `cascade:Address` | `rdfs:Resource` | Structured postal address with FHIR Address semantics. |
| `cascade:PharmacyInfo` | `rdfs:Resource` | Preferred pharmacy for prescriptions. Replaces `checkup:preferredPharmacy` (string) with structured data. |
| `cascade:AdvanceDirectives` | `rdfs:Resource` | Patient advance directive declarations (living will, power of attorney, DNR). |
| `cascade:EmergencyContact` | `rdfs:Resource` | A patient's emergency contact person. Used as a blank node within PatientProfile. (v2.2) |

### Patient Profile Properties (v2.0)

#### PatientProfile Properties

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `cascade:dateOfBirth` | owl:DatatypeProperty | xsd:date | Patient date of birth. |
| `cascade:genderIdentity` | owl:DatatypeProperty | xsd:string | Gender identity: woman, man, non_binary, other, prefer_not_to_say. |
| `cascade:biologicalSex` | owl:DatatypeProperty | xsd:string | Biological sex: male, female, intersex. |
| `cascade:ageGroup` | owl:DatatypeProperty | xsd:string | Computed age group: pediatric, young_adult, adult, senior. |
| `cascade:emergencyContactName` | owl:DatatypeProperty | xsd:string | Full name of emergency contact. |
| `cascade:emergencyContactRelationship` | owl:DatatypeProperty | xsd:string | Relationship of emergency contact to patient. |
| `cascade:emergencyContactPhone` | owl:DatatypeProperty | xsd:string | Phone number of emergency contact. |
| `cascade:hasAddress` | owl:ObjectProperty | cascade:Address | **Deprecated v2.2 on PatientProfile** — use `cascade:address` (blank-node linking). Still used on PharmacyInfo. |
| `cascade:maritalStatus` | owl:DatatypeProperty | xsd:string | Marital status. Migrated from `checkup:maritalStatus`. |
| `cascade:raceEthnicity` | owl:DatatypeProperty | xsd:string | Race/ethnicity (multi-value). Migrated from `checkup:raceEthnicity`. |
| `cascade:hasPreferredPharmacy` | owl:ObjectProperty | cascade:PharmacyInfo | **Deprecated v2.2** — use `cascade:preferredPharmacy` (blank-node linking). |
| `cascade:hasAdvanceDirectives` | owl:ObjectProperty | cascade:AdvanceDirectives | **Deprecated v2.2** — use `cascade:advanceDirectives` (blank-node linking). |
| `cascade:computedAge` | owl:DatatypeProperty | xsd:integer | Patient age in years, computed from dateOfBirth at serialization time. (v2.2) |
| `cascade:profileId` | owl:DatatypeProperty | xsd:string | Unique identifier (UUID) for the patient profile instance. (v2.2) |
| `cascade:preferredLanguage` | owl:DatatypeProperty | xsd:string | Patient's preferred language. Backward compatibility; should use `dct:language` in identity profile. (v2.2) |
| `cascade:address` | owl:ObjectProperty | cascade:Address | Links to an Address blank node. Used by PatientProfileSerializer. (v2.2) |
| `cascade:emergencyContact` | owl:ObjectProperty | cascade:EmergencyContact | Links to an EmergencyContact blank node. (v2.2) |
| `cascade:advanceDirectives` | owl:ObjectProperty | cascade:AdvanceDirectives | Links to an AdvanceDirectives blank node. (v2.2) |
| `cascade:preferredPharmacy` | owl:ObjectProperty | cascade:PharmacyInfo | Links to a PharmacyInfo blank node. Replaces `cascade:hasPreferredPharmacy`. (v2.2) |

#### Address Properties (Simplified Aliases)

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `cascade:streetAddress` | owl:DatatypeProperty | xsd:string | Street address line. Simplified alias of `cascade:addressLine`. |
| `cascade:city` | owl:DatatypeProperty | xsd:string | City name. Simplified alias of `cascade:addressCity`. |
| `cascade:state` | owl:DatatypeProperty | xsd:string | State or province. Simplified alias of `cascade:addressState`. |
| `cascade:postalCode` | owl:DatatypeProperty | xsd:string | Postal/ZIP code. Simplified alias of `cascade:addressPostalCode`. |
| `cascade:country` | owl:DatatypeProperty | xsd:string | Country name or ISO code. Simplified alias of `cascade:addressCountry`. |

#### FHIR-Aligned Address Properties (v2.2)

These mirror the FHIR Address datatype fields used by the SDK Address struct.

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `cascade:addressUse` | owl:DatatypeProperty | xsd:string | Purpose of the address: home, work, temp, old. Aligns with FHIR Address.use. |
| `cascade:addressType` | owl:DatatypeProperty | xsd:string | Type of address: postal, physical, both. Aligns with FHIR Address.type. |
| `cascade:addressText` | owl:DatatypeProperty | xsd:string | Full address as a single text string. Aligns with FHIR Address.text. |
| `cascade:addressLine` | owl:DatatypeProperty | xsd:string | Street address line. Repeatable for multi-line addresses. Aligns with FHIR Address.line. |
| `cascade:addressCity` | owl:DatatypeProperty | xsd:string | City name. Aligns with FHIR Address.city. |
| `cascade:addressDistrict` | owl:DatatypeProperty | xsd:string | District or county. Aligns with FHIR Address.district. |
| `cascade:addressState` | owl:DatatypeProperty | xsd:string | State or province. Aligns with FHIR Address.state. |
| `cascade:addressPostalCode` | owl:DatatypeProperty | xsd:string | Postal or ZIP code. Aligns with FHIR Address.postalCode. |
| `cascade:addressCountry` | owl:DatatypeProperty | xsd:string | Country name or ISO code. Aligns with FHIR Address.country. |

#### PharmacyInfo Properties

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `cascade:pharmacyName` | owl:DatatypeProperty | xsd:string | Name of the pharmacy. |
| `cascade:pharmacyPhone` | owl:DatatypeProperty | xsd:string | Phone number of the pharmacy. |
| `cascade:pharmacyAddress` | owl:DatatypeProperty | xsd:string | Pharmacy address as a single text string. Simplified alternative to nested Address blank node. (v2.2) |
| `cascade:hasAddress` | owl:ObjectProperty | cascade:Address | Pharmacy postal address (reuses `cascade:hasAddress`). |

#### EmergencyContact Properties (v2.2)

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `cascade:contactName` | owl:DatatypeProperty | xsd:string | Full name of a contact person. |
| `cascade:contactRelationship` | owl:DatatypeProperty | xsd:string | Relationship of the contact to the patient: spouse, parent, child, sibling, partner, friend, caregiver, other. |
| `cascade:contactPhone` | owl:DatatypeProperty | xsd:string | Phone number for a contact person. Also used for general contact use on PatientProfile. |

#### AdvanceDirectives Properties

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `cascade:hasLivingWill` | owl:DatatypeProperty | xsd:boolean | Whether the patient has a living will. Migrated from `checkup:hasLivingWill`. |
| `cascade:hasPowerOfAttorney` | owl:DatatypeProperty | xsd:boolean | Whether the patient has a healthcare power of attorney. Migrated from `checkup:hasPowerOfAttorney`. |
| `cascade:hasDNR` | owl:DatatypeProperty | xsd:boolean | Whether the patient has a do-not-resuscitate order. Migrated from `checkup:hasDNR`. |
| `cascade:advanceDirectiveNotes` | owl:DatatypeProperty | xsd:string | Free-text notes about advance directives. Migrated from `checkup:advanceDirectiveNotes`. |

### FHIR Conversion Support (v2.8)

Added to support lossless FHIR ↔ Cascade conversion. These properties annotate converted records with FHIR provenance and layer promotion status.

#### LayerPromotionStatus Class and Individuals

| Class/Individual | Type | Description |
|-----------------|------|-------------|
| `cascade:LayerPromotionStatusValue` | owl:Class | Enumeration class for FHIR-to-Cascade layer promotion status values. |
| `cascade:FullyMapped` | Named Individual | Record has been fully mapped to a Layer 2 Cascade class. All domain properties are populated from the FHIR source. |
| `cascade:PendingLayerTwoPromotion` | Named Individual | Record is stored as a Layer 1 passthrough (FHIR JSON preserved in `cascade:fhirJson`) because no Layer 2 class exists yet for this FHIR resource type. |

#### FHIR Conversion Properties

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `cascade:layerPromotionStatus` | owl:ObjectProperty | cascade:LayerPromotionStatusValue | Indicates whether a converted FHIR record has been fully promoted to a Layer 2 Cascade class (`cascade:FullyMapped`) or is stored as a Layer 1 passthrough (`cascade:PendingLayerTwoPromotion`). (v2.8) |
| `cascade:fhirJson` | owl:DatatypeProperty | xsd:string | Inline FHIR JSON for passthrough records where no Layer 2 class exists. Always plain xsd:string (no base64 encoding). Enables lossless round-trip for obscure resource types. (v2.8) |
| `cascade:fhirResourceType` | owl:DatatypeProperty | xsd:string | The originating FHIR resource type (e.g., "Claim", "Appointment", "CarePlan"). Used for passthrough records and as a disambiguation hint on promoted records. (v2.8) |
| `cascade:sourceRecordDate` | owl:DatatypeProperty | xsd:dateTime | The primary date extracted from the source FHIR resource (resource-type-specific: Encounter.period.start, Claim.billablePeriod.start, etc.). Enables chronological sorting across mixed record types. (v2.8) |

### Conflict Resolution Classes (v2.9)

| Class | Description |
|-------|-------------|
| `cascade:UserResolution` | A patient's recorded decision for resolving a data conflict between two source records. Persisted so that the same resolution can be automatically applied on re-import. (v2.9) |
| `cascade:PendingConflict` | An unresolved conflict between two or more records from different sources, awaiting user resolution. Stored until the user reviews and resolves. (v2.9) |

### Conflict Resolution Properties (v2.9)

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `cascade:conflictId` | DatatypeProperty | xsd:string | A deterministic identifier for a conflict, derived from record type and identity fields. Stable across re-imports. Domain: `cascade:UserResolution` or `cascade:PendingConflict`. (v2.9) |
| `cascade:resolution` | DatatypeProperty | xsd:string | The user's resolution decision. Values: `kept-source-a`, `kept-source-b`, `kept-both`, `manual-edit`. Domain: `cascade:UserResolution`. (v2.9) |
| `cascade:keptRecord` | ObjectProperty | — | The record kept as the canonical version after conflict resolution. Domain: `cascade:UserResolution`. (v2.9) |
| `cascade:discardedRecords` | ObjectProperty | — | Records discarded during conflict resolution. Domain: `cascade:UserResolution`. (v2.9) |
| `cascade:userNote` | DatatypeProperty | xsd:string | Optional free-text note from the patient about their resolution decision. Domain: `cascade:UserResolution`. (v2.9) |
| `cascade:candidateRecords` | ObjectProperty | — | The conflicting records in a `PendingConflict`, awaiting user resolution. Domain: `cascade:PendingConflict`. (v2.9) |
| `cascade:detectedAt` | DatatypeProperty | xsd:dateTime | When the conflict was first detected during import. Domain: `cascade:PendingConflict`. (v2.9) |
| `cascade:autoResolved` | DatatypeProperty | xsd:boolean | True when a conflict was automatically resolved by applying a stored user resolution preference. (v2.9) |

### Document Provenance Properties (v2.9)

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `cascade:documentType` | DatatypeProperty | xsd:string | The type of clinical document. Values: `summarization`, `progress-note`, `discharge-summary`, `consultation-note`, `operative-note`, `history-physical`. (v2.9) |
| `cascade:sectionCode` | DatatypeProperty | xsd:string | LOINC code of the originating C-CDA section for this record (e.g., `11450-4` for Problem List). (v2.9) |
| `cascade:sourceRecordId` | DatatypeProperty | xsd:string | The original source system record identifier (e.g., C-CDA `<id>` element value) preserved for provenance. (v2.9) |

### AI Extraction Classes (v3.0)

| Class | Description |
|-------|-------------|
| `cascade:HealthRecord` | Abstract superclass for all Cascade health data records. Provides a common type for cross-record queries and provenance linkage. (v3.0) |
| `cascade:AIExtractionActivity` | A PROV-O Activity representing an AI/NLP extraction pass over a clinical document. Linked to extracted records via `prov:wasGeneratedBy`. (v3.0) |
| `cascade:AIDiscardedExtraction` | An extraction candidate that the AI model identified but discarded (low confidence, duplicate, or out-of-scope). Stored for audit and re-review purposes. (v3.0) |
| `cascade:SocialHistoryConsent` | Consent record governing the storage and processing of sensitive social history data under 42 CFR Part 2 and equivalent regulations. (v3.0) |

### AI Extraction Properties (v3.0)

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `cascade:extractionConfidence` | DatatypeProperty | xsd:decimal | Model confidence score for an extracted value, in the range [0.0, 1.0]. Domain: `cascade:AIExtractionActivity`. (v3.0) |
| `cascade:extractionModel` | DatatypeProperty | xsd:string | Identifier of the AI/NLP model used for extraction (e.g., `"qwen3.5-4b-q4_k_m"`). Domain: `cascade:AIExtractionActivity`. (v3.0) |
| `cascade:sourceNarrativeSection` | DatatypeProperty | xsd:string | The C-CDA or document section the AI extracted data from (e.g., `"medications"`, `"social-history"`). Domain: `cascade:AIExtractionActivity`. (v3.0) |
| `cascade:requiresUserReview` | DatatypeProperty | xsd:boolean | True when the extraction confidence is below the auto-accept threshold and the record must be reviewed by the patient before persisting. Domain: `cascade:AIExtractionActivity`. (v3.0) |
| `cascade:discardReason` | DatatypeProperty | xsd:string | Human-readable reason the extraction candidate was discarded. Domain: `cascade:AIDiscardedExtraction`. (v3.0) |
| `cascade:consentScope` | DatatypeProperty | xsd:string | Scope of the consent grant. Values: `social-history`, `substance-use`, `mental-health`. Domain: `cascade:SocialHistoryConsent`. (v3.0) |
| `cascade:consentGrantedAt` | DatatypeProperty | xsd:dateTime | Timestamp when the patient granted consent. Domain: `cascade:SocialHistoryConsent`. (v3.0) |
| `cascade:consentRevokedAt` | DatatypeProperty | xsd:dateTime | Timestamp when the patient revoked consent, if applicable. Domain: `cascade:SocialHistoryConsent`. (v3.0) |

### Advisory & AI Generation Provenance (v3.1–v3.2)

PROV-O activities recording how advisory patches are applied and how LLM-generated narrative content is produced.

| Class/Individual | Type | Description |
|------------------|------|-------------|
| `cascade:AdvisoryApplicationActivity` | owl:Class (`prov:Activity`) | An activity that applied a Cascade Advisory Patch (CAP) to a Pod. Joins to advisory provenance via `prov:used <advisory-iri>` and `prov:used <matched-record-iri>`, recording both the patch source and the record it was matched against. Use `prov:wasGeneratedBy` on records produced or modified by the patch. (v3.1) |
| `cascade:AIGenerationActivity` | owl:Class (`prov:Activity`) | An LLM-powered generation activity that produced narrative or summary content (e.g., `checkup:VariantNarrative` chunks). Sibling of `cascade:AIExtractionActivity`: extraction pulls structured records out of unstructured text, generation produces new prose. Records the model identifier, prompt version, temperature, and a `cascade:trigger` value indicating why the generation ran. Link generated content via `prov:wasGeneratedBy`. (v3.1) |
| `cascade:GenerationTrigger` | owl:Class | Closed enumeration of reasons an `AIGenerationActivity` may run. (v3.1) |
| `cascade:InitialGeneration` | Named Individual (`cascade:GenerationTrigger`) | First-time generation of a narrative or summary chunk; no prior version existed. (v3.1) |
| `cascade:RegenerationAfterReclassification` | Named Individual (`cascade:GenerationTrigger`) | Regeneration triggered because an upstream classification (e.g., variant pathogenicity, condition status) changed and the prior narrative is now stale. (v3.1) |
| `cascade:AudienceRetargeting` | Named Individual (`cascade:GenerationTrigger`) | Regeneration triggered to retarget existing content for a different audience (e.g., patient-facing vs. clinician-facing) without any underlying classification change. (v3.1) |

`AIGenerationActivity` reuses `cascade:extractionModel`, `cascade:extractionConfidence`, `cascade:sourceNarrativeSection`, and `cascade:requiresUserReview` (declared on `AIExtractionActivity`) and adds the properties below.

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `cascade:promptVersion` | DatatypeProperty | xsd:string | Identifier of the prompt template version used for this generation, e.g. `"variant-narrative-v2.1"`. Pair with `cascade:extractionModel` for full reproducibility. Domain: `cascade:AIGenerationActivity`. (v3.1) |
| `cascade:generationTemperature` | DatatypeProperty | xsd:decimal | Sampling temperature used during generation (typically 0.0–1.0). Recorded for reproducibility and to distinguish deterministic from creative outputs. Domain: `cascade:AIGenerationActivity`. (v3.1) |
| `cascade:trigger` | ObjectProperty | cascade:GenerationTrigger | The reason this generation activity ran. One of the `cascade:GenerationTrigger` named individuals. Domain: `cascade:AIGenerationActivity`. (v3.1) |
| `cascade:appliedTriplesCount` | DatatypeProperty | xsd:nonNegativeInteger | Total number of triples the advisory's CAP body inserted into the Pod for a single match. Lets an auditor verify CAP profile constraint C5 (≤ 64 inserted triples per match) at activity-record-read time without re-parsing the patch body. Domain: `cascade:AdvisoryApplicationActivity`. (v3.2) |

### Workbench Support: Ungrounded-AI Provenance & Caregiver Proxy (v3.3)

Added for the Cascade Workbench. `cascade:AIAsserted` (a `ConsumerGenerated` provenance leaf — see [Data Provenance Classes](#data-provenance-classes)) marks ungrounded general-AI content. `cascade:ProxyAgent` and its properties close the caregiver-proxy gap, recording a person operating a patient's Pod on the patient's behalf.

| Class | Type | Description |
|-------|------|-------------|
| `cascade:ProxyAgent` | owl:Class (`prov:Agent`) | A person operating a patient's Pod on the patient's behalf (e.g. a parent for a minor child, a caregiver for a dependent adult). Distinct from the patient (`cascade:PatientProfile`). Records who is acting and under what authority and scope. (v3.3) |

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `cascade:actsForPatient` | ObjectProperty (`prov:actedOnBehalfOf`) | rdfs:Resource | The patient (WebID) on whose behalf the proxy acts. Domain: `cascade:ProxyAgent`. (v3.3) |
| `cascade:proxyWebID` | ObjectProperty | rdfs:Resource | WebID of the proxy agent. Domain: `cascade:ProxyAgent`. (v3.3) |
| `cascade:proxyRelationship` | DatatypeProperty | xsd:string | Relationship of the proxy to the patient. Reuses the `cascade:contactRelationship` value space: `parent`, `guardian`, `caregiver`, `spouse`, `child`, `other`. Domain: `cascade:ProxyAgent`. (v3.3) |
| `cascade:proxyScope` | DatatypeProperty | xsd:string | Authority scope, e.g. `full`, `read-only`, `investigation-only`. Composable with `cascade:consentScope` (data-sensitivity), which it does not replace. Domain: `cascade:ProxyAgent`. (v3.3) |
| `cascade:proxyGrantedAt` | DatatypeProperty | xsd:dateTime | When proxy authority was granted. Domain: `cascade:ProxyAgent`. (v3.3) |
| `cascade:proxyRevokedAt` | DatatypeProperty | xsd:dateTime | When proxy authority was revoked, if applicable. Domain: `cascade:ProxyAgent`. (v3.3) |

### SHACL Shapes

**File:** `core.shapes.ttl` v1.1
Validation shapes for `cascade:PatientProfile` (required demographics, address structure), `cascade:DataProvenance` taxonomy, `cascade:UserResolution` (required conflictId + resolution), and `cascade:PendingConflict` (required conflictId). See [SHACL Validation](#shacl-validation) for cross-vocabulary overview.

---

## Clinical Vocabulary v1.9

**Namespace:** `https://ns.cascadeprotocol.org/clinical/v1#`
**Prefix:** `clinical:`
**Status:** Stable
**Imports:** Core Vocabulary v1

Vocabulary for clinical documents and structured health records imported from EHR systems via Apple HealthKit.

> **v1.9 (provenance):** `cascade:AIExtracted` is now a permitted `cascade:dataProvenance` value on every clinical record shape. Records produced by an AI document-extraction pipeline (e.g. the Workbench) carry `cascade:dataProvenance cascade:AIExtracted` and validate without error. See [Clinical SHACL Shapes](#clinical-shacl-shapes).

### Core Classes

| Class | Description | FHIR Alignment |
|-------|-------------|----------------|
| `clinical:ClinicalDocument` | Clinical documentation imported from EHR systems | fhir:DocumentReference |
| `clinical:ClinicalSection` | Section within a clinical document | - |
| `clinical:ClinicalNarrative` | Free-text clinical narrative | - |

### Document Type Classes (LOINC-aligned)

| Class | Description |
|-------|-------------|
| `clinical:ProgressNote` | Provider progress note documenting a patient encounter |
| `clinical:DischargeSummary` | Hospital discharge summary document |
| `clinical:ConsultationNote` | Specialist consultation note |
| `clinical:LaboratoryReport` | Laboratory test results with narrative interpretation |
| `clinical:ImagingReport` | Radiology/imaging report with findings |
| `clinical:VisitSummary` | After-visit summary provided to patient |

### Structured Clinical Record Classes

| Class | Description | FHIR Alignment |
|-------|-------------|----------------|
| `clinical:Medication` | Medication record from EHR | fhir:MedicationStatement |
| `clinical:Allergy` | Allergy or intolerance record | fhir:AllergyIntolerance |
| `clinical:LabResult` | Laboratory test result | fhir:Observation |
| `clinical:Condition` | Medical condition or diagnosis | fhir:Condition |
| `clinical:Immunization` | Vaccination record | fhir:Immunization |
| `clinical:Procedure` | Medical procedure record | fhir:Procedure |
| `clinical:CoverageRecord` | **Deprecated** — Insurance coverage/plan record. Use `coverage:InsurancePlan` for new data. Retained for EHR import pipeline backward compatibility. | fhir:Coverage |
| `clinical:VitalSign` | Vital sign observation | fhir:Observation |

### Longitudinal Record Classes (v1.2+)

| Class | Version | Description |
|-------|---------|-------------|
| `clinical:MedicationUseEpisode` | v1.2 | Canonical longitudinal record of patient's relationship with a medication over time. Derived from one or more source records via reconciliation. Episodes represent continuous periods of use - a gap beyond threshold (90 days) creates a new episode. |
| `clinical:Supplement` | v1.2 | Dietary supplement, OTC product, or herbal remedy with explicit regulatory status. Separate from Medication class due to different regulatory status and evidence requirements. |
| `clinical:LabTestSeries` | v1.4 | Longitudinal record of repeated measurements of the same laboratory test (identified by LOINC code) over time. One series per LOINC code per patient. Includes trend inference with confidence and explainable reason. |

### FHIR Converter Classes (v1.7)

Classes added to support lossless FHIR → Cascade conversion for resource types previously dropped by the converter.

| Class | Description | FHIR Alignment |
|-------|-------------|----------------|
| `clinical:Encounter` | Healthcare encounter (office visit, ER visit, inpatient stay). Normalizes FHIR Encounter's multiple period expression paths to canonical start/end. | fhir:Encounter |
| `clinical:MedicationAdministration` | Single medication administration event (administered by provider, not patient-reported). Distinct from `clinical:Medication` (patient-reported) and `clinical:MedicationUseEpisode` (longitudinal). | fhir:MedicationAdministration |
| `clinical:ImplantedDevice` | Medical device implanted in the patient (pacemaker, joint replacement, insulin pump). Carries UDI carrier for regulatory traceability. | fhir:Device |
| `clinical:ImagingStudy` | Diagnostic imaging study (X-ray, MRI, CT, ultrasound). Carries DICOM study UID and modality for linkage to external imaging systems. | fhir:ImagingStudy |

### Social History Classes (v1.8)

`clinical:SocialHistoryRecord` captures EHR-extracted social history observations subject to 42 CFR Part 2 sensitivity handling. It is **distinct** from `health:SocialHistoryRecord` (consumer-reported lifestyle data imported from Apple Health / C-CDA Social History sections). The two-class design preserves regulatory provenance:

| Class | Namespace | Source | Regulatory |
|-------|-----------|--------|------------|
| `health:SocialHistoryRecord` | `health:` | Consumer-reported (device, user entry, Apple Health import) | No special sensitivity |
| `clinical:SocialHistoryRecord` | `clinical:` | EHR-extracted (C-CDA Social History section, clinical provider) | 42 CFR Part 2 — requires `cascade:SocialHistoryConsent` |

| Class | Description | FHIR Alignment |
|-------|-------------|----------------|
| `clinical:SocialHistoryRecord` | EHR-extracted social history observation from a C-CDA Social History section (LOINC 29762-2). Carries provenance linking to source clinical document and consent record. Distinct from `health:SocialHistoryRecord` (consumer-reported). (v1.8) | fhir:Observation (social history category) |

### Key Properties - SocialHistoryRecord (v1.8)

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `clinical:socialHistoryCategory` | owl:DatatypeProperty | xsd:string | Category of the social history observation. Values: `smokingStatus`, `alcoholUse`, `substanceUse`, `occupation`, `educationLevel`, `sexualOrientation`, `genderIdentity`, `householdIncome`, `housingStatus`, `socialIsolation`. Maps to FHIR Observation.category `social-history`. (v1.8) |
| `clinical:packsPerYear` | owl:DatatypeProperty | xsd:decimal | Cumulative smoking exposure in pack-years (packs/day × years smoked). Applicable when `socialHistoryCategory` is `smokingStatus`. (v1.8) |
| `clinical:substanceType` | owl:DatatypeProperty | xsd:string | Type of substance for substance-use records (e.g., `"alcohol"`, `"cannabis"`, `"opioid"`). Applicable when `socialHistoryCategory` is `substanceUse`. (v1.8) |
| `clinical:frequencyDescription` | owl:DatatypeProperty | xsd:string | Free-text or coded frequency description (e.g., `"2-3 drinks/week"`, `"daily"`). (v1.8) |
| `clinical:socialHistoryConsent` | owl:ObjectProperty | cascade:SocialHistoryConsent | Links this record to the patient's 42 CFR Part 2 consent record governing storage and processing. Required for `substanceUse` category records. (v1.8) |

### Key Properties - Encounter (v1.7)

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `clinical:encounterClass` | owl:DatatypeProperty | xsd:string | Encounter classification: AMB (ambulatory), EMER (emergency), IMP (inpatient), SS (short stay), VR (virtual). Maps to FHIR Encounter.class. |
| `clinical:encounterStatus` | owl:DatatypeProperty | xsd:string | Encounter workflow status: planned, arrived, triaged, in-progress, onleave, finished, cancelled. Maps to FHIR Encounter.status. |
| `clinical:encounterType` | owl:DatatypeProperty | xsd:string | Clinical type of encounter (e.g., "Annual physical", "Follow-up visit"). Maps to FHIR Encounter.type display text. |
| `clinical:encounterStart` | owl:DatatypeProperty | xsd:dateTime | Start of the encounter period. Maps to FHIR Encounter.period.start. |
| `clinical:encounterEnd` | owl:DatatypeProperty | xsd:dateTime | End of the encounter period. Maps to FHIR Encounter.period.end. |
| `clinical:facilityName` | owl:DatatypeProperty | xsd:string | Name of the healthcare facility where the encounter occurred. Extracted from FHIR Encounter.serviceProvider or contained Organization. |
| `clinical:sourceRecordId` | owl:DatatypeProperty | xsd:string | Original FHIR resource ID from the source EHR system. Enables deduplication and cross-reference resolution. (No domain restriction — reusable across all clinical record classes.) |

### Key Properties - MedicationAdministration (v1.7)

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `clinical:administeredDate` | owl:DatatypeProperty | xsd:dateTime | Date and time of medication administration. Maps to FHIR MedicationAdministration.effectiveDateTime. |
| `clinical:administeredDose` | owl:DatatypeProperty | xsd:string | Dose administered as a human-readable string (value + unit, e.g., "500 mg"). Maps to FHIR MedicationAdministration.dosage.dose. |
| `clinical:administeredRoute` | owl:DatatypeProperty | xsd:string | Route of administration (e.g., "oral", "IV", "subcutaneous"). Maps to FHIR MedicationAdministration.dosage.route.text. |
| `clinical:administrationStatus` | owl:DatatypeProperty | xsd:string | Administration status: in-progress, not-done, on-hold, completed, entered-in-error, stopped, unknown. Maps to FHIR MedicationAdministration.status. |

### Key Properties - ImplantedDevice (v1.7)

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `clinical:deviceType` | owl:DatatypeProperty | xsd:string | Type of implanted device (e.g., "Pacemaker", "Hip prosthesis"). Maps to FHIR Device.type display text. |
| `clinical:implantDate` | owl:DatatypeProperty | xsd:dateTime | Date the device was implanted. Maps to FHIR Device.manufactureDate or associated Procedure.performedDateTime. |
| `clinical:deviceManufacturer` | owl:DatatypeProperty | xsd:string | Manufacturer of the device. Maps to FHIR Device.manufacturer. |
| `clinical:udiCarrier` | owl:DatatypeProperty | xsd:string | FDA Unique Device Identifier (UDI) carrier string. Maps to FHIR Device.udiCarrier.carrierHRF. Enables regulatory traceability. |
| `clinical:deviceStatus` | owl:DatatypeProperty | xsd:string | Device status: active, inactive, entered-in-error, unknown. Maps to FHIR Device.status. |

### Key Properties - ImagingStudy (v1.7)

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `clinical:imagingModality` | owl:DatatypeProperty | xsd:string | Imaging modality code (e.g., "MR", "CT", "US", "DX"). Maps to FHIR ImagingStudy.modality.code. |
| `clinical:studyDescription` | owl:DatatypeProperty | xsd:string | Human-readable description of the imaging study. Maps to FHIR ImagingStudy.description. |
| `clinical:numberOfSeries` | owl:DatatypeProperty | xsd:integer | Number of series in the study. Maps to FHIR ImagingStudy.numberOfSeries. |
| `clinical:studyDate` | owl:DatatypeProperty | xsd:dateTime | Date and time the study was started. Maps to FHIR ImagingStudy.started. |
| `clinical:dicomStudyUid` | owl:DatatypeProperty | xsd:string | DICOM Study Instance UID. Maps to FHIR ImagingStudy.identifier (DICOM system). Enables linkage to PACS/external imaging systems. |

### Key Properties - LaboratoryReport Additions (v1.7)

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `clinical:hasLabResult` | owl:ObjectProperty | clinical:LabResult | Links a LaboratoryReport to one or more LabResult instances within the panel. Enables DiagnosticReport → LaboratoryReport grouping of contained Observation resources. (v1.7) |
| `clinical:panelName` | owl:DatatypeProperty | xsd:string | Human-readable name of the laboratory panel (e.g., "Comprehensive Metabolic Panel", "CBC with Differential"). Maps to FHIR DiagnosticReport.code.text. (v1.7) |
| `clinical:reportCategory` | owl:DatatypeProperty | xsd:string | Category of the laboratory report (e.g., "LAB", "CH" for chemistry, "HM" for hematology). Maps to FHIR DiagnosticReport.category.coding.code. (v1.7) |

### Key Properties - MedicationUseEpisode

| Property | Range | Description |
|----------|-------|-------------|
| `clinical:canonicalName` | xsd:string | Normalized drug name for the medication episode |
| `clinical:episodeFirstSeenDate` | xsd:dateTime | Earliest CLINICAL date from source records |
| `clinical:episodeLastSeenDate` | xsd:dateTime | Most recent CLINICAL date from source records |
| `clinical:inferredStatus` | xsd:string | Inferred active/inactive status |
| `clinical:statusConfidence` | xsd:string | Confidence level: high, medium, low |
| `clinical:statusReason` | xsd:string | Reason for status inference |
| `clinical:usePattern` | xsd:string | Pattern: chronic, shortCourse, oneTime, asNeeded, unknown |
| `clinical:derivedFromRecord` | clinical:Medication | Links to source Medication record(s) |

### Key Properties - Supplement

| Property | Range | Description |
|----------|-------|-------------|
| `clinical:supplementName` | xsd:string | Name of the supplement or OTC product |
| `clinical:regulatoryStatus` | xsd:string | dietarySupplement, otcDrug, homeopathic, herbalRemedy, unknown |
| `clinical:evidenceStrength` | xsd:string | strongEvidence, moderateEvidence, limitedEvidence, traditionalUse, noEvidence, unknown |
| `clinical:form` | xsd:string | capsule, tablet, softgel, liquid, powder, gummy, spray, patch, tea, tincture, other |
| `clinical:dsldId` | xsd:string | NIH Dietary Supplement Label Database identifier |

### Key Properties - CoverageRecord (Deprecated)

> **Deprecation Notice:** `clinical:CoverageRecord` is deprecated. Use `coverage:InsurancePlan` from `coverage.ttl` for new insurance data. This class and its properties are retained for backward compatibility with existing EHR import pipeline data. See [Coverage Vocabulary](#coverage-vocabulary-v13) for the replacement.

| Property | Range | Description |
|----------|-------|-------------|
| `clinical:providerName` | xsd:string | Insurance provider/company name |
| `clinical:memberId` | xsd:string | Member ID on insurance card |
| `clinical:groupNumber` | xsd:string | Group number for employer-sponsored plans |
| `clinical:planName` | xsd:string | Name of the insurance plan |
| `clinical:planType` | xsd:string | Plan type: hmo, ppo, epo, pos, hdhp, medicare, medicaid, tricare, other |
| `clinical:coverageType` | xsd:string | Coverage classification (e.g., medical, dental, vision) |
| `clinical:relationship` | xsd:string | Relationship to subscriber: self, spouse, child, parent, other |
| `clinical:effectivePeriodStart` | xsd:dateTime | Coverage start date |
| `clinical:effectivePeriodEnd` | xsd:dateTime | Coverage end date |
| `clinical:payorName` | xsd:string | Name of the paying organization |
| `clinical:subscriberId` | xsd:string | Subscriber ID (may differ from member ID) |

### Key Properties - Procedure

| Property | Range | Description |
|----------|-------|-------------|
| `clinical:procedureName` | xsd:string | Name of the medical procedure |
| `clinical:procedureStatus` | xsd:string | Procedure status: completed, in_progress, not_done, entered_in_error, unknown |
| `clinical:procedureCategory` | xsd:string | Procedure category (e.g., Surgical, Diagnostic) |
| `clinical:performedDate` | xsd:dateTime | Date the procedure was performed |
| `clinical:bodySite` | xsd:string | Body site where the procedure was performed |
| `clinical:performer` | xsd:string | Name of the performing provider |
| `clinical:location` | xsd:string | Facility or location where the procedure was performed |
| `clinical:outcome` | xsd:string | Outcome of the procedure |
| `clinical:procedureSnomedCode` | xsd:string | SNOMED CT procedure code |
| `clinical:cptCode` | xsd:string | CPT procedure code |

### Healthcare Standards Alignment

**LOINC Document Type Mappings:**
- Progress note: loinc:11506-3
- Discharge summary: loinc:18842-5
- Consultation note: loinc:11488-4

**LOINC Section Codes:**
- Chief complaint: loinc:10154-3
- History of present illness: loinc:10164-2
- Medications: loinc:10160-0
- Allergies: loinc:48765-2
- Assessment: loinc:51848-0

---

## Clinical SHACL Shapes

SHACL validation shapes for clinical documents and structured records.

### Document Validation

```turtle
clinical:ClinicalDocumentShape a sh:NodeShape ;
    sh:targetClass clinical:ClinicalDocument ;

    # Required: importedAt timestamp
    sh:property [
        sh:path clinical:importedAt ;
        sh:datatype xsd:dateTime ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
        sh:message "Clinical document must have exactly one importedAt timestamp"
    ] ;

    # Required: sourceEHR name
    sh:property [
        sh:path clinical:sourceEHR ;
        sh:datatype xsd:string ;
        sh:minCount 1 ;
        sh:message "Clinical document must specify the source EHR system"
    ] ;

    # Required: provenance
    sh:property [
        sh:path cascade:dataProvenance ;
        sh:in (cascade:ClinicalGenerated cascade:EHRVerified cascade:ScannedDocument cascade:AIExtracted cascade:ConsumerGenerated cascade:DeviceGenerated cascade:SelfReported cascade:ConsumerWellness) ;
        sh:minCount 1 ;
        sh:message "Clinical documents must have valid provenance"
    ] .
```

### MedicationUseEpisode Validation

Required fields per Cascade Protocol:
- `canonicalName` - Normalized drug name
- `episodeFirstSeenDate` - Earliest clinical date
- `episodeLastSeenDate` - Most recent clinical date
- `derivedFromRecord` - Must link to at least one source record
- `inferredStatus` - active or inactive
- `statusReason` - Explains WHY system thinks this status
- `statusConfidence` - high, medium, or low

### Supplement Validation

Required fields:
- `supplementName` - Name of the supplement
- `regulatoryStatus` - REQUIRED to distinguish from FDA-approved medications

---

## Health Vocabulary v2.4

**Namespace:** `https://ns.cascadeprotocol.org/health/v1#`
**Prefix:** `health:`
**Status:** Stable
**Imports:** Core Vocabulary v1

Vocabulary for consumer-generated wellness observations from wearable devices and Apple HealthKit. Maps Cascade wellness properties to established SNOMED CT and LOINC codes following the three-layer ontology architecture. This is a **Layer 2** vocabulary.

### Composite Classes

| Class | Description |
|-------|-------------|
| `health:ActivitySnapshot` | Aggregated activity metrics over a measurement period (typically 7 days). Subclass of `prov:Entity`. |
| `health:SleepSnapshot` | Aggregated sleep metrics over a measurement period (typically 7 days). Subclass of `prov:Entity`. |
| `health:MetricTrend` | Time-bounded trend for a single wellness metric. Captures direction, magnitude, confidence, and comparison period. Subclass of `prov:Entity`. (v1.5) |
| `health:VO2MaxStatistics` | Statistical summary of VO2 Max readings over a measurement period (typically 180 days). Provides trend analysis, fitness classification, and min/max/mean calculations. (v1.7) |
| `health:HRVStatistics` | Statistical summary of Heart Rate Variability (SDNN) readings over a measurement period. (v1.7) |
| `health:BPStatistics` | Statistical summary of blood pressure readings over a measurement period with AHA category classification. Subclass of `prov:Entity`. (v1.8) |
| `health:HealthProfile` | Top-level wellness profile aggregating vital signs, body measurements, activity, and sleep data from consumer devices. Stored at `/wellness/` in the Cascade Pod. Subclass of `prov:Entity`. (v2.0) |
| `health:DailyVitalReading` | A single day's aggregated vital sign reading with value, unit, date, and sample count. Used in 90-day and 30-day history containers. Subclass of `fhir:Observation`. (v2.0) |
| `health:HRVReading` | A single heart rate variability (SDNN) observation with timestamp and optional source. Subclass of `fhir:Observation`. (v2.0) |
| `health:BloodPressureReading` | A single blood pressure observation with systolic and diastolic components, timestamp, and optional source. Subclass of `fhir:Observation`. (v2.0) |
| `health:VitalSignReading` | A single vital sign observation with value, unit, measurement period, timestamp, and source. Used for baseline readings and VO2 Max history entries. Subclass of `fhir:Observation`. (v2.0) |
| `health:DailyActivitySnapshot` | A single day's activity data: steps, active energy, exercise minutes, and stand hours. Subclass of `prov:Entity`. (v2.0) |
| `health:DailySleepSnapshot` | A single night's sleep data: duration in hours and quality classification. Subclass of `prov:Entity`. (v2.0) |

### MetricTrend Properties (v1.5)

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `health:trendMetric` | ObjectProperty | — | The wellness property this trend describes |
| `health:trendDirection` | DatatypeProperty | xsd:string | `increasing`, `decreasing`, `stable`, `insufficient_data` |
| `health:trendMagnitude` | DatatypeProperty | xsd:decimal | Percentage change between comparison periods |
| `health:trendPeriodStart` | DatatypeProperty | xsd:dateTime | Start of trend period |
| `health:trendPeriodEnd` | DatatypeProperty | xsd:dateTime | End of trend period |
| `health:trendBaselineValue` | DatatypeProperty | xsd:decimal | Reference value (e.g., 90-day average) |
| `health:trendCurrentValue` | DatatypeProperty | xsd:decimal | Current period average (e.g., 7-day) |
| `health:trendConfidence` | DatatypeProperty | xsd:string | `high` (>30 days), `medium` (14-30 days), `low` (<14 days) |
| `health:trendSource` | ObjectProperty | cascade:DataSource | Data source that produced the observations |

### VO2MaxStatistics Properties (v1.7)

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `health:vo2Mean` | DatatypeProperty | xsd:double | Average VO2 Max over measurement period (mL/kg/min) |
| `health:vo2Min` | DatatypeProperty | xsd:double | Lowest VO2 Max reading in period |
| `health:vo2MaxValue` | DatatypeProperty | xsd:double | Highest VO2 Max reading in period |
| `health:vo2SampleCount` | DatatypeProperty | xsd:integer | Number of measurements |
| `health:vo2DaysCovered` | DatatypeProperty | xsd:integer | Unique days with measurements |
| `health:vo2TrendDirection` | DatatypeProperty | xsd:string | `improving`, `declining`, `stable`, `unknown` |
| `health:vo2PercentageChange` | DatatypeProperty | xsd:double | Percentage change from oldest to newest |
| `health:fitnessClassification` | DatatypeProperty | xsd:string | Fitness level (see table below) |
| `health:isSparseData` | DatatypeProperty | xsd:boolean | True if < 3 samples or < 30 days |

### Fitness Classification Values

| Classification | VO2 Max Range (mL/kg/min) | Description |
|---------------|---------------------------|-------------|
| `veryPoor` | < 20 | Very poor cardiorespiratory fitness |
| `poor` | 20-29 | Poor cardiorespiratory fitness |
| `fair` | 30-34 | Fair cardiorespiratory fitness |
| `good` | 35-44 | Good cardiorespiratory fitness |
| `excellent` | 45-54 | Excellent cardiorespiratory fitness |
| `superior` | ≥ 55 | Superior cardiorespiratory fitness |

**Note:** Current classification is age/sex-agnostic. Future versions may incorporate user demographics (biological sex, date of birth) from Apple Health for personalized classification using standard VO2 Max percentile tables.

### VO2MaxStatistics TTL Example

```turtle
@prefix health: <https://ns.cascadeprotocol.org/health/v1#> .
@prefix cascade: <https://ns.cascadeprotocol.org/core/v1#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix prov: <http://www.w3.org/ns/prov#> .

<#vo2-stats-001> a health:VO2MaxStatistics ;
    health:vo2Mean "42.5"^^xsd:double ;
    health:vo2Min "40.1"^^xsd:double ;
    health:vo2MaxValue "44.8"^^xsd:double ;
    health:vo2SampleCount "8"^^xsd:integer ;
    health:vo2DaysCovered "45"^^xsd:integer ;
    health:vo2TrendDirection "improving" ;
    health:vo2PercentageChange "5.2"^^xsd:double ;
    health:fitnessClassification "good" ;
    health:isSparseData "false"^^xsd:boolean ;
    cascade:dataProvenance cascade:ConsumerGenerated ;
    prov:generatedAtTime "2026-02-03T10:30:00Z"^^xsd:dateTime .
```

### Shared Statistical Properties (v1.8)

These temporal properties are shared across all statistics classes (VO2MaxStatistics, HRVStatistics, BPStatistics):

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `health:periodStart` | DatatypeProperty | xsd:dateTime | Start date of the statistical measurement period |
| `health:periodEnd` | DatatypeProperty | xsd:dateTime | End date of the statistical measurement period |

### HRVStatistics Properties (v1.7, properties v1.8)

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `health:hrvSampleCount` | DatatypeProperty | xsd:integer | Number of HRV readings in the period |
| `health:hrvDaysCovered` | DatatypeProperty | xsd:integer | Number of unique days with HRV measurements |
| `health:hrvMean` | DatatypeProperty | xsd:double | Average HRV (SDNN) over the measurement period (ms) |
| `health:hrvMedian` | DatatypeProperty | xsd:double | Median HRV (SDNN) over the measurement period (ms) |
| `health:hrvStdDev` | DatatypeProperty | xsd:double | Standard deviation of HRV readings (ms) |
| `health:hrvMin` | DatatypeProperty | xsd:double | Lowest HRV reading in the period (ms) |
| `health:hrvMax` | DatatypeProperty | xsd:double | Highest HRV reading in the period (ms) |
| `health:hrvPercentile25` | DatatypeProperty | xsd:double | 25th percentile of HRV readings (ms) |
| `health:hrvPercentile75` | DatatypeProperty | xsd:double | 75th percentile of HRV readings (ms) |
| `health:hrvTrendDirection` | DatatypeProperty | xsd:string | Trend direction: `improving`, `declining`, `stable`, `unknown` |

### BPStatistics Properties (v1.8)

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `health:bpSampleCount` | DatatypeProperty | xsd:integer | Number of blood pressure readings in the period |
| `health:bpMeanSystolic` | DatatypeProperty | xsd:double | Average systolic blood pressure (mmHg) |
| `health:bpMeanDiastolic` | DatatypeProperty | xsd:double | Average diastolic blood pressure (mmHg) |
| `health:bpMinSystolic` | DatatypeProperty | xsd:double | Lowest systolic reading in the period (mmHg) |
| `health:bpMaxSystolic` | DatatypeProperty | xsd:double | Highest systolic reading in the period (mmHg) |
| `health:bpMinDiastolic` | DatatypeProperty | xsd:double | Lowest diastolic reading in the period (mmHg) |
| `health:bpMaxDiastolic` | DatatypeProperty | xsd:double | Highest diastolic reading in the period (mmHg) |
| `health:bpCategory` | DatatypeProperty | xsd:string | AHA category: `normal`, `elevated`, `hypertension_stage1`, `hypertension_stage2`, `hypertensive_crisis` |

### History Container Properties (v2.0)

Time-series containers emitted by HealthProfileSerializer for trend analysis. Each property links a `health:HealthProfile` to an ordered list of readings.

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `health:restingHeartRateHistory` | ObjectProperty | health:DailyVitalReading | Time series of daily resting heart rate readings (90-day lookback) |
| `health:walkingHeartRateHistory` | ObjectProperty | health:DailyVitalReading | Time series of daily walking heart rate readings (90-day lookback) |
| `health:hrvHistory` | ObjectProperty | health:HRVReading | Time series of HRV (SDNN) readings (7-day lookback) |
| `health:bloodPressureHistory` | ObjectProperty | health:BloodPressureReading | Time series of blood pressure readings (30-day lookback) with systolic and diastolic values |
| `health:vo2MaxHistory` | ObjectProperty | health:VitalSignReading | Time series of VO2 Max readings (180-day lookback) |
| `health:bodyMassHistory` | ObjectProperty | health:DailyVitalReading | Time series of daily body mass readings (30-day lookback) |
| `health:dailyActivityHistory` | ObjectProperty | health:DailyActivitySnapshot | Time series of daily activity snapshots (90-day lookback): steps, exercise, calories, stand hours per day |
| `health:dailySleepHistory` | ObjectProperty | health:DailySleepSnapshot | Time series of daily sleep snapshots (90-day lookback): duration and quality per night |

### SelfReport Base Class (v2.1)

Base class for patient-reported daily check-ins and self-assessments. Apps extend this with domain-specific response data via the SelfReportable protocol pattern.

| Class | Description |
|-------|-------------|
| `health:SelfReport` | Base class for patient-reported daily check-ins and self-assessments. Provides common structure for timestamped self-reports across health domains. Examples: medication adherence, symptom tracking, mood logging, sleep records. Subclass of `prov:Entity`. |

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `health:reportDate` | DatatypeProperty | xsd:dateTime | When the self-report was recorded |
| `health:reportType` | DatatypeProperty | xsd:string | Category of self-report (e.g., medication_adherence, symptom_tracking, mood, sleep) |
| `health:completionStatus` | DatatypeProperty | xsd:string | Whether the report is complete, partial, or skipped |
| `health:reportContext` | DatatypeProperty | xsd:string | What tracking plan or list this report relates to (free-form reference) |
| `health:reportNotes` | DatatypeProperty | xsd:string | Optional free-text notes from the patient |

### Statistics Container Linking Properties (v2.2)

ObjectProperties used by CheckupSerializer to link an intake form or wellness profile to its statistical summary nodes.

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `health:hasHRVStatistics` | ObjectProperty | health:HRVStatistics | Links a wellness profile to its HRV statistical summary |
| `health:hasBPStatistics` | ObjectProperty | health:BPStatistics | Links a wellness profile to its blood pressure statistical summary |

### Wellness Properties with Standard Code Mappings

| Metric | Property | SNOMED CT | LOINC | Unit |
|--------|----------|-----------|-------|------|
| Resting Heart Rate | `health:restingHeartRate` | 364075005 | 40443-4 | beats/min |
| Walking Heart Rate | `health:walkingHeartRate` | 364075005 | 89270-3 | beats/min |
| HRV (SDNN) | `health:heartRateVariability` | 80404004 | 80404-7 | ms |
| Blood Pressure | `health:bloodPressure` | 75367002 | 85354-9 | — |
| Systolic BP | `health:systolicBP` | 271649006 | 8480-6 | mmHg |
| Diastolic BP | `health:diastolicBP` | 271650006 | 8462-4 | mmHg |
| Respiratory Rate | `health:respiratoryRate` | 86290005 | 9279-1 | breaths/min |
| VO2 Max | `health:vo2Max` | 251880009 | 60842-2 | mL/kg/min |
| Walking Steadiness | `health:walkingSteadiness` | 364832000 | — | string |
| Average Daily Steps | `health:averageDailySteps` | 68130003 | 41950-7 | steps |
| Active Energy Burned | `health:activeEnergyBurnedKcal` | 251833007 | 41981-2 | kcal |
| Exercise Minutes | `health:exerciseMinutesWeekly` | 68130003 | 73985-4 | min |
| Stand Hours | `health:standHoursDaily` | — | — | hours |
| Sleep Duration | `health:averageDurationHours` | 248263006 | 93832-4 | hours |
| Body Weight | `health:bodyMass` | 27113001 | 29463-7 | kg |
| Body Height | `health:bodyHeight` | 50373000 | 8302-2 | cm |
| BMI | `health:bodyMassIndex` | 60621009 | 39156-5 | kg/m2 |
| Body Temperature | `health:bodyTemperature` | 386725007 | 8310-5 | °C |
| Oxygen Saturation | `health:oxygenSaturation` | 431314004 | 2708-6 | % |
| Blood Glucose | `health:bloodGlucose` | 33747003 | 2339-0 | mg/dL |
| Blood Type | `health:bloodType` | 365637002 | 882-1 | string |

### Annotation Properties

| Property | Description |
|----------|-------------|
| `health:snomedCode` | Links a wellness property to its SNOMED CT concept |
| `health:loincCode` | Links a wellness property to its LOINC observation code |
| `health:unit` | Human-readable unit of measurement |
| `health:ucumCode` | Unified Code for Units of Measure code |

### Social History (v2.4)

`health:SocialHistoryRecord` represents social history observations about a patient. Social history records are imported from C-CDA Social History sections (LOINC 29762-2).

| Term | Type | Range | Description |
|------|------|-------|-------------|
| `health:SocialHistoryRecord` | owl:Class | — | A social history observation about a patient, including smoking status, alcohol use, exercise, occupation, and other lifestyle factors. (v2.4) |
| `health:smokingStatus` | DatatypeProperty | xsd:string | Patient's smoking status. Common values: `current-smoker`, `former-smoker`, `never-smoker`. (v2.4) |
| `health:alcoholUse` | DatatypeProperty | xsd:string | Patient's alcohol consumption description. (v2.4) |
| `health:exerciseFrequency` | DatatypeProperty | xsd:string | Patient's reported exercise frequency. (v2.4) |
| `health:occupationalExposure` | DatatypeProperty | xsd:string | Occupational exposures relevant to patient health. (v2.4) |

### Notes

- **Walking Steadiness** maps to `sct:364832000` (Balance finding) — the closest available SNOMED concept. Apple's OK/Low/Very Low classification is proprietary.
- **Stand Hours** is Cascade-proprietary — no SNOMED CT or LOINC equivalent exists.
- Vital sign properties use `fhir:Observation` as their domain. Activity and sleep properties use their respective snapshot classes.
- **SHACL Shapes:** `health.shapes.ttl` v1.1 provides validation shapes for `health:HealthProfile` (required vital signs, measurement periods), `health:MetricTrend` (trendDirection/trendConfidence enum validation, required properties), `health:SocialHistoryRecord` (optional sourceSystem + smokingStatus), and statistical summary classes. See [SHACL Validation](#shacl-validation) for cross-vocabulary overview.

---

## POTS Vocabulary v1.4

**Namespace:** `https://ns.cascadeprotocol.org/pots/v1#`
**Prefix:** `pots:`
**Status:** Stable
**Imports:** Core Vocabulary v1

Domain-specific vocabulary for POTS (Postural Orthostatic Tachycardia Syndrome) home screening checks using the NASA Lean Test protocol.

### Core Classes

| Class | Description |
|-------|-------------|
| `pots:POTSCheckResult` | Complete result bundle from a guided home orthostatic screening check |
| `pots:HeartRateMeasurement` | Timed heart rate observation during standing phase |
| `pots:BloodPressureMeasurement` | Timed blood pressure observation during check |
| `pots:SymptomEvent` | User-reported symptom during standing phase |
| `pots:PostureStability` | Posture quality measurement from Core Motion sensors |

### Test Protocol

| Class | Description |
|-------|-------------|
| `pots:NASALean` | 10 minutes supine followed by 10 minutes standing against wall |

### Key Properties

| Property | Range | Description |
|----------|-------|-------------|
| `pots:date` | xsd:dateTime | ISO 8601 timestamp when check was performed |
| `pots:protocol` | xsd:string | Protocol used (currently only 'nasaLean') |
| `pots:supineHeartRate` | pots:HeartRateMeasurement | Baseline heart rate from supine phase |
| `pots:standingHeartRates` | rdf:List | Ordered list of standing phase measurements |
| `pots:maxHeartRateDelta` | xsd:double | Maximum HR increase using 30-second rolling window average |
| `pots:potsThresholdMet` | xsd:boolean | True if HR increase meets criteria (>=30 bpm adults, >=40 bpm pediatric) |
| `pots:orthostaticHypotensionSuspected` | xsd:boolean | True if BP drop suggests OH |
| `pots:orthostaticHypertensionSuspected` | xsd:boolean | True if BP increase suggests OH |
| `pots:userAgeAtTest` | xsd:integer | User's age for threshold calculation |
| `pots:postureQualityScore` | xsd:string | Letter grade (A-D) for posture stability |
| `pots:postureStability` | rdf:List | List of posture stability measurements from Core Motion during standing phase |

### Timing Properties (v1.3)

| Property | Range | Description |
|----------|-------|-------------|
| `pots:secondsSinceStand` | xsd:double | Time offset in seconds from the moment the user stood up. Used in standingHeartRates and standingBloodPressures items. |
| `pots:timestampSeconds` | xsd:double | Absolute timestamp in seconds. Used in SymptomEvent items for precise event timing. |

### Apple Health Import Properties (v1.3)

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `pots:importedBloodPressureHistory` | ObjectProperty | rdf:List | Collection of blood pressure readings imported from Apple Health for longitudinal context |
| `pots:importedHRVHistory` | ObjectProperty | rdf:List | Collection of HRV readings imported from Apple Health for longitudinal context |
| `pots:averageImportedBloodPressure` | DatatypeProperty | xsd:string | Computed average of imported BP readings, formatted as 'systolic/diastolic' |
| `pots:averageImportedHRV` | DatatypeProperty | xsd:double | Computed average of imported HRV readings from Apple Health (ms) |

### V2 Test Configuration & Patient Context (v1.4+)

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `pots:baselineDurationMinutes` | DatatypeProperty | xsd:integer | User-selected baseline duration in whole minutes (5, 10, or 15) (v1.4+) |
| `pots:testNotes` | DatatypeProperty | xsd:string | Optional free-text patient notes for the session (max 500 chars) (v1.4+) |
| `pots:bpProvided` | DatatypeProperty | xsd:boolean | Whether a blood pressure cuff was used during this check (v1.4+) |
| `pots:pppMinute1` | DatatypeProperty | xsd:decimal | PPP ratio (SBP-DBP)/SBP at 1 minute of standing (0.0-1.0) (v1.4+) |
| `pots:pppMinute3` | DatatypeProperty | xsd:decimal | PPP ratio at 3 minutes of standing (0.0-1.0) (v1.4+) |
| `pots:pppMinute5` | DatatypeProperty | xsd:decimal | PPP ratio at 5 minutes of standing (0.0-1.0) (v1.4+) |
| `pots:pppMinute7` | DatatypeProperty | xsd:decimal | PPP ratio at 7 minutes of standing (0.0-1.0) (v1.4+) |
| `pots:pppMinute10` | DatatypeProperty | xsd:decimal | PPP ratio at 10 minutes of standing (0.0-1.0) (v1.4+) |

### SNOMED CT Mappings

- Heart rate: sct:364075005
- Supine position: sct:40199007
- Standing position: sct:10904000
- POTS: sct:703273007
- Orthostatic hypotension: sct:28651003

### Data Classification

- **Type:** Consumer wellness data (non-diagnostic)
- **Target Age Range:** 13+ (COPPA compliant)
- **Devices:** Apple Watch (heart rate), iPhone (posture tracking)
- **Protocol:** NASA Lean Test (10 min supine + 10 min standing)

### SHACL Shapes

**File:** `pots.shapes.ttl` v1.0
Validation shapes for `pots:POTSCheckResult` (required protocol fields, heart rate measurements, threshold calculations) and `pots:HeartRateMeasurement` timing constraints. See [SHACL Validation](#shacl-validation) for cross-vocabulary overview.

---

## Coverage Vocabulary v1.3

**Namespace:** `https://ns.cascadeprotocol.org/coverage/v1#`
**Prefix:** `coverage:`
**Status:** Stable
**Imports:** Core Vocabulary v1
**Layer:** 2 (Domain Vocabulary)
**FHIR Alignment:** `fhir:Coverage`, `fhir:Claim`, `fhir:ExplanationOfBenefit`

Domain vocabulary for patient-owned insurance, benefits, and financial health data. Resolves the overlap between `checkup:InsuranceInfo` (Layer 3, patient-reported) and `clinical:CoverageRecord` (Layer 2, EHR-imported) with a unified, standardized representation. v1.3 adds clinical evidence linkage, appeal outcome detail, and standard-mapped denial reason codes (HL7/CARIN IG) for the Cascade Appeal system.

### Classes (8)

| Class | Description | FHIR Mapping | Status |
|-------|-------------|-------------|--------|
| `coverage:InsurancePlan` | Insurance plan enrollment | `fhir:Coverage` | Active (14 properties) |
| `coverage:Deductible` | Annual deductible tracking | `fhir:ExplanationOfBenefit` (partial) | Active (3 properties, v1.1) |
| `coverage:CopaySchedule` | Copay amounts by service | -- | Active (3 properties, v1.1) |
| `coverage:ClaimRecord` | Single insurance claim submitted to payer | `fhir:Claim` | Active (6 properties, v1.1) |
| `coverage:BenefitStatement` | Payer's adjudication decision on a claim (EOB) | `fhir:ExplanationOfBenefit` | Active (9 properties, v1.1) |
| `coverage:DenialNotice` | Formal denial of coverage initiating an appeal process. Recommended Pod storage: `/coverage/denials/{id}.ttl` | `fhir:ExplanationOfBenefit` | Active (7 properties, v1.2-1.3) |
| `coverage:AppealRecord` | Formal appeal filing contesting a DenialNotice. One record per appeal level. Recommended Pod storage: `/coverage/appeals/{id}.ttl` | `fhir:Task` | Active (7 properties, v1.2-1.3) |
| `coverage:DenialReasonCode` | Enumeration class for structured denial reason codes. Named individuals align with HL7 ClaimResponse adjudication and CARIN IG Blue Button STU2. | `http://terminology.hl7.org/CodeSystem/adjudication` | Active (v1.3) |

### InsurancePlan Properties (14)

**Core Insurance Properties (9):**

| Property | Type | Description | From |
|----------|------|-------------|------|
| `coverage:providerName` | xsd:string | Insurance company name | checkup + clinical |
| `coverage:memberId` | xsd:string | Member/subscriber ID number | both |
| `coverage:groupNumber` | xsd:string | Employer group number | both |
| `coverage:planName` | xsd:string | Insurance plan name | clinical |
| `coverage:planType` | xsd:string | HMO, PPO, EPO, POS, HDHP, etc. | clinical |
| `coverage:coverageType` | xsd:string | primary, secondary, dental, vision | both |
| `coverage:effectiveStart` | xsd:date | Coverage period start date | both |
| `coverage:effectiveEnd` | xsd:date | Coverage period end date | both |
| `coverage:subscriberId` | xsd:string | Policy holder ID from insurer | clinical |

**Subscriber Properties (2):**

| Property | Type | Description | From |
|----------|------|-------------|------|
| `coverage:subscriberName` | xsd:string | Name of insurance subscriber | checkup (Intake Plan) |
| `coverage:subscriberRelationship` | xsd:string | self, spouse, child, parent, other | checkup + clinical |

**Pharmacy Benefit Properties (3):**

| Property | Type | Description | From |
|----------|------|-------------|------|
| `coverage:rxBin` | xsd:string | Pharmacy benefit BIN | checkup |
| `coverage:rxPcn` | xsd:string | Pharmacy benefit PCN | checkup |
| `coverage:rxGroup` | xsd:string | Pharmacy benefit group number | checkup |

### Mixed Namespace Usage

`checkup:InsuranceInfo` (Layer 3) uses `coverage:` properties for standardized insurance data. Properties that remain in `checkup:`:

| Property | Reason |
|----------|--------|
| `checkup:primaryCareProvider` | App-layer enrichment (PCP is not insurance data) |
| `checkup:pcpPhone` | App-layer enrichment |

### Recommended Pod Storage

```
/coverage/
    plans/
        {plan-id}.ttl          # InsurancePlan instances
    deductibles/
        {year}.ttl             # Annual deductible tracking (future)
```

### Deductible Properties (v1.1)

| Property | Type | Description |
|----------|------|-------------|
| `coverage:deductibleAmount` | xsd:decimal | Annual deductible amount in USD |
| `coverage:deductibleMet` | xsd:decimal | Amount of deductible applied to date |
| `coverage:outOfPocketMax` | xsd:decimal | Annual out-of-pocket maximum in USD |

### CopaySchedule Properties (v1.1)

| Property | Type | Description |
|----------|------|-------------|
| `coverage:copayPrimary` | xsd:decimal | Primary care visit copay in USD |
| `coverage:copaySpecialist` | xsd:decimal | Specialist visit copay in USD |
| `coverage:copayEmergency` | xsd:decimal | Emergency room visit copay in USD |

### ClaimRecord Properties (v1.1)

Maps to FHIR `Claim` resource. Represents a single insurance claim submitted by a provider to the payer.

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `coverage:claimDate` | owl:DatatypeProperty | xsd:dateTime | Date the claim was submitted. Maps to FHIR Claim.billablePeriod.start. |
| `coverage:claimTotal` | owl:DatatypeProperty | xsd:decimal | Total billed amount for the claim in USD. Maps to FHIR Claim.total.value. |
| `coverage:claimStatus` | owl:DatatypeProperty | xsd:string | Claim lifecycle status: active, cancelled, draft, entered-in-error. Maps to FHIR Claim.status. |
| `coverage:claimType` | owl:DatatypeProperty | xsd:string | Category of claim: institutional, oral, pharmacy, professional, vision. Maps to FHIR Claim.type.coding.code. |
| `coverage:billingProvider` | owl:DatatypeProperty | xsd:string | Name of the billing provider or organization. Maps to FHIR Claim.provider display text. |
| `coverage:sourceRecordId` | owl:DatatypeProperty | xsd:string | Original FHIR resource ID from the source EHR system. Enables deduplication and cross-reference from BenefitStatement. (No domain restriction — shared with clinical: classes.) |

### BenefitStatement Properties (v1.1)

Maps to FHIR `ExplanationOfBenefit` resource. Represents the payer's adjudication decision on a claim.

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `coverage:adjudicationDate` | owl:DatatypeProperty | xsd:dateTime | Date the claim was adjudicated by the payer. Maps to FHIR ExplanationOfBenefit.created. |
| `coverage:adjudicationStatus` | owl:DatatypeProperty | xsd:string | EOB processing status: active, cancelled, draft, entered-in-error. Maps to FHIR ExplanationOfBenefit.status. |
| `coverage:outcomeCode` | owl:DatatypeProperty | xsd:string | Adjudication outcome: queued, complete, error, partial. Maps to FHIR ExplanationOfBenefit.outcome. |
| `coverage:denialReason` | owl:DatatypeProperty | xsd:string | Human-readable reason for claim denial or partial payment (if applicable). |
| `coverage:totalBilled` | owl:DatatypeProperty | xsd:decimal | Total amount billed by the provider. Maps to FHIR ExplanationOfBenefit.total (category=submitted). |
| `coverage:totalPaid` | owl:DatatypeProperty | xsd:decimal | Total amount paid by the payer. Maps to FHIR ExplanationOfBenefit.total (category=benefit). |
| `coverage:patientResponsibility` | owl:DatatypeProperty | xsd:decimal | Amount the patient is responsible for (deductible + copay + coinsurance). Maps to FHIR ExplanationOfBenefit.total (category=patientpay). |
| `coverage:relatedClaim` | owl:ObjectProperty | coverage:ClaimRecord | Links this BenefitStatement to the originating ClaimRecord. Maps to FHIR ExplanationOfBenefit.claim. Resolved via deterministic subject URI minting (OQ-2). |
| `coverage:sourceRecordId` | owl:DatatypeProperty | xsd:string | Original FHIR resource ID from the source EHR system. |

### FHIR Coverage Alignment

| coverage: property | FHIR Coverage field |
|--------------------|---------------------|
| `coverage:providerName` | `Coverage.payor.display` |
| `coverage:memberId` | `Coverage.identifier` |
| `coverage:groupNumber` | `Coverage.class` (group) |
| `coverage:planName` | `Coverage.class` (plan) |
| `coverage:planType` | `Coverage.type` |
| `coverage:coverageType` | `Coverage.type` |
| `coverage:effectiveStart` | `Coverage.period.start` |
| `coverage:effectiveEnd` | `Coverage.period.end` |
| `coverage:subscriberId` | `Coverage.subscriberId` |
| `coverage:subscriberName` | `Coverage.subscriber` |
| `coverage:subscriberRelationship` | `Coverage.relationship` |

### DenialNotice Properties (v1.2-1.3)

Represents a formal denial of coverage issued by an insurer. Distinct from `BenefitStatement` — a `DenialNotice` initiates an appeal process, not a payment record.

| Property | Type | Description | Version |
|----------|------|-------------|---------|
| `coverage:deniedProcedureCode` | xsd:string | CPT or HCPCS code of the denied service (e.g., E0787 for CGM) | v1.2 |
| `coverage:denialReasonCode` | xsd:string | Structured coded denial reason. Use `coverage:DenialReasonCode` named individuals (see below). Aligns with HL7 ClaimResponse adjudication and CARIN IG Blue Button STU2. Distinct from free-text `coverage:denialReason` | v1.2 |
| `coverage:denialLetterDate` | xsd:date | Date the denial notice was issued. The appeal deadline clock starts from this date | v1.2 |
| `coverage:appealDeadline` | xsd:date | Computed deadline for filing an appeal, based on denial date, plan type, and jurisdiction rules | v1.2 |
| `coverage:coveragePolicyReference` | xsd:string | The LCD, NCD, or coverage policy cited as the basis for denial (e.g., LCD L33822) | v1.2 |
| `coverage:sourceRecordId` | xsd:string | Insurer-assigned claim or denial number (shared property, no domain restriction) | v1.2 |
| `coverage:deniedClinicalContext` | owl:ObjectProperty (rdfs:Resource) | References clinical/health/pots records in the Pod relevant to this denial. Enables appeals to cite specific clinical evidence against policy criteria. Range is open to allow cross-namespace linking. | v1.3 |

Note: `coverage:providerName`, `coverage:memberId`, `coverage:planType`, and `coverage:denialReason` (free-text) are also used by `DenialNotice` via shared or existing properties.

### DenialReasonCode Named Individuals (v1.3)

Standard-mapped enumeration values for `coverage:denialReasonCode`. Aligned with HL7 ClaimResponse adjudication codes and [CARIN IG for Blue Button STU2](http://hl7.org/fhir/us/carin-bb/STU2/).

| Named Individual | Label | Standard Alignment |
|------------------|-------|--------------------|
| `coverage:NotMedicallyNecessary` | Not Medically Necessary | HL7 adjudication `noauth`; CMS denial code 50 |
| `coverage:LCDCriteriaNotMet` | LCD Criteria Not Met | CMS Local Coverage Determination criteria |
| `coverage:NCDCriteriaNotMet` | NCD Criteria Not Met | CMS National Coverage Determination criteria |
| `coverage:ServiceNotCovered` | Service Not Covered | HL7 adjudication `benefit` |
| `coverage:PriorAuthorizationRequired` | Prior Authorization Required | HL7 adjudication `noauth`; CARIN IG X12 835 reason code 4 |
| `coverage:DuplicateClaim` | Duplicate Claim | X12 835 reason code 18 |
| `coverage:InformationRequested` | Additional Information Requested | X12 835 reason code 16 |

### AppealRecord Properties (v1.2-1.3)

Represents a formal appeal filing contesting a `DenialNotice`. One `AppealRecord` per appeal level.

| Property | Type | Description | Version |
|----------|------|-------------|---------|
| `coverage:appealLevel` | xsd:string | Administrative level: `redetermination`, `qio_reconsideration`, `alj_hearing`, `mac_review`, `federal_court`, `internal_level1`, `internal_level2`, `external_review`, `state_insurance_dept`, `litigation` | v1.2 |
| `coverage:relatedDenialNotice` | coverage:DenialNotice | Links this AppealRecord to the DenialNotice it contests | v1.2 |
| `coverage:appealFiledDate` | xsd:date | Date the appeal was formally filed | v1.2 |
| `coverage:appealOutcome` | xsd:string | Outcome: `approved`, `denied`, `partial`, `withdrawn`, `pending` | v1.2 |
| `coverage:appealOutcomeDate` | xsd:date | Date the appeal outcome was received | v1.2 |
| `coverage:outcomeReason` | xsd:string | Free-text explanation of why the appeal was approved, denied, or partially approved. Captures the insurer's stated rationale. | v1.3 |
| `coverage:reversalAmount` | xsd:decimal | Reimbursement amount granted if the appeal was approved or partially approved. Expressed as a decimal in the currency of the related InsurancePlan. | v1.3 |

### Recommended Pod Storage

```
/coverage/
    plans/
        {plan-id}.ttl          # InsurancePlan instances
    deductibles/
        {year}.ttl             # Annual deductible tracking (future)
    denials/
        {denial-id}.ttl        # DenialNotice instances (v1.2)
    appeals/
        {appeal-id}.ttl        # AppealRecord instances (v1.2)
```

### Future Companion Vocabulary: billing:

A `billing:` vocabulary (Layer 2) will complement `coverage:` for patient-collected claims and bills: `billing:Claim`, `billing:Bill`, `billing:Payment`, `billing:ExplanationOfBenefits`.

### SHACL Shapes

**File:** `coverage.shapes.ttl` v1.3
Validation shapes for `coverage:InsurancePlan`, `coverage:ClaimRecord`, `coverage:BenefitStatement`, `coverage:DenialNotice`, and `coverage:AppealRecord`. See [SHACL Validation](#shacl-validation) for cross-vocabulary overview.

### Version History

| Version | Date | Changes |
|---------|------|---------|
| v1.0 | 2026-02-18 | Initial release: InsurancePlan (14 properties), Deductible, CopaySchedule |
| v1.1 | 2026-03-12 | Added ClaimRecord (6 properties) and BenefitStatement (9 properties) with FHIR Claim/EOB alignment |
| v1.2 | 2026-03-16 | Added DenialNotice class (6 properties) and AppealRecord class (5 properties) for denial/appeal workflow |
| v1.3 | 2026-03-17 | Added `coverage:deniedClinicalContext` (clinical evidence linkage), `coverage:outcomeReason`, `coverage:reversalAmount`, `coverage:DenialReasonCode` enumeration class with 7 named individuals mapped to HL7/CARIN IG adjudication codes |

---

## Checkup Vocabulary v3.2

**Namespace:** `https://ns.cascadeprotocol.org/checkup/v1#`
**Prefix:** `checkup:`
**Status:** Stable
**Imports:** Core Vocabulary v1, Clinical Vocabulary v1, Health Vocabulary v1

Vocabulary for patient intake forms and pre-visit health data aggregation.

### Core Classes (28 active)

| Class | Description |
|-------|-------------|
| `checkup:IntakeFormData` | Aggregated patient data for healthcare intake forms |
| `checkup:InsuranceInfo` | Insurance coverage details |
| `checkup:MedicationSummary` | Current medication with adherence data |
| `checkup:SupplementSummary` | Dietary supplement with regulatory classification |
| `checkup:AllergySummary` | Known allergen with reaction type and severity |
| `checkup:ConditionSummary` | Active or resolved health condition |
| `checkup:FamilyHistoryEntry` | Family member health condition for risk assessment |
| `checkup:ScreeningStatus` | Preventive screening status (USPSTF/ACS guidelines) |
| `checkup:VisitIssue` | Chief complaint for visit planning |
| `checkup:SuggestedQuestion` | AI-generated question for provider |
| `checkup:DiagnosticTestResult` | Reference to external diagnostic test (e.g., POTS Check) |
| `checkup:WellnessSummary` | Layer 3 patient-facing wellness summary aggregating `health:MetricTrend` data (v1.4) |
| `checkup:TrendInsight` | Patient-readable observation derived from trend data (v1.4) |
| `checkup:CorrelationInsight` | Temporal correlation between data domains — never implies causation (v1.4) |
| `checkup:KeyIndicator` | Distilled health metric for dashboard display with traffic-light status (v1.4) |
| `checkup:AttentionItem` | Flags baseline deviations, stale data, or threshold crossings (v1.4) |
| `checkup:VisitPrepSummary` | Curated one-page clinical summary for appointments (v1.4) |
| `checkup:DailyCheckIn` | Patient-reported daily medication adherence check-in with optional notes (v1.5) |
| `checkup:DiscussionTopic` | AI-generated or user-created topic for discussion during a healthcare visit (v1.5) |
| `checkup:CheckInSettings` | Application configuration for daily check-in notifications and scheduling (v1.5) |
| `checkup:IntakeQuestionnaireResponse` | FHIR-inspired intake questionnaire response using LOINC panel codes and SNOMED CT answers (v1.6) |
| `checkup:ResponseItem` | Question-answer pair within a questionnaire response with nested sub-item support (v1.6) |
| `checkup:ImmunizationSummary` | Patient-facing immunization record for intake forms using mixed namespace pattern (v1.7) |
| `checkup:LabResultSummary` | Patient-facing lab result summary using mixed namespace pattern with `clinical:` properties (v1.7) |
| `checkup:WellnessProfileReference` | Lightweight pointer to the SDK HealthProfile stored in a separate Pod location (v1.7) |
| `checkup:ProcedureSummary` | Patient-facing procedure record using mixed namespace pattern: `checkup:` for app-layer fields, `clinical:` for standardized data (v1.8) |
| `checkup:MedicationChangeRecord` | Recorded change to a medication or supplement since the last visit snapshot. Tracks change deltas for the "Changes Since Last Visit" report section (v1.9) |
| `checkup:VisitPrepTray` | Organized per-appointment visit preparation container grouping issues, topics, questions, and notes with intent categories and resolution tracking (v3.1) |

### Sub-Concern Classification (v1.10)

Every `checkup:` class is annotated with `cascade:subConcern` to document its functional role within the vocabulary. This taxonomy supports migration planning and vocabulary organization.

| Sub-Concern | Description | Classes |
|-------------|-------------|---------|
| **summary** | Genuine L3 — aggregates L2 data into patient-facing records | MedicationSummary, SupplementSummary, AllergySummary, ConditionSummary, FamilyHistoryEntry, ImmunizationSummary, LabResultSummary, ProcedureSummary |
| **analytics** | L3 insights — AI-generated or computed patient-facing analysis | WellnessSummary, TrendInsight, CorrelationInsight, KeyIndicator, AttentionItem, VisitPrepSummary, SuggestedQuestion, DiscussionTopic, MedicationChangeRecord |
| **intake** | Data collection — captures new patient-reported data | IntakeFormData, VisitIssue, IntakeQuestionnaireResponse, ResponseItem, DiagnosticTestResult, VisitPrepTray |
| **self-report** | Patient-reported outcomes — subclass of `health:SelfReport` (WS7 complete) | DailyCheckIn |
| **financial** | Insurance/billing — migrating to coverage: domain (WS4) | InsuranceInfo |
| **app-config** | Application settings — target: /settings/ hierarchy (WS5) | CheckInSettings |
| **structural** | Technical references, not domain concepts | WellnessProfileReference, ScreeningStatus |

### Dark Vocabulary Remediation (v1.10)

The following properties are emitted by CheckupSerializer but were not previously defined in the ontology. They are now formally defined in `checkup.ttl` with migration annotations indicating their future namespace.

#### Tier 3 Patient Profile Properties (**Removed v3.0** — migrated to `cascade:` namespace in core.ttl v2.0)

> **Removed in v3.0:** `checkup:PatientProfile` and these associated properties have been removed from the active vocabulary. Use the `cascade:` equivalents defined in Core Vocabulary v2.0 (`cascade:PatientProfile`, `cascade:Address`, `cascade:PharmacyInfo`, `cascade:AdvanceDirectives`). Existing serialized data using `checkup:` properties remains parseable but new serialization must use the `cascade:` namespace. See [Patient Profile Classes (v2.0)](#patient-profile-classes-v20) in Core Vocabulary.

| Property | Range | Migration Target | Status |
|----------|-------|-----------------|--------|
| `checkup:preferredLanguage` | xsd:string | `dct:language` in `/profile/card.ttl` | **Deprecated v2.0** |
| `checkup:maritalStatus` | xsd:string | `cascade:maritalStatus` | **Deprecated v2.0** |
| `checkup:raceEthnicity` | xsd:string | `cascade:raceEthnicity` | **Deprecated v2.0** |
| `checkup:preferredPharmacy` | xsd:string | `cascade:preferredPharmacy` (blank-node structured) | **Deprecated v2.0** |
| `checkup:hasLivingWill` | xsd:boolean | `cascade:hasLivingWill` on `cascade:AdvanceDirectives` | **Deprecated v2.0** |
| `checkup:hasPowerOfAttorney` | xsd:boolean | `cascade:hasPowerOfAttorney` on `cascade:AdvanceDirectives` | **Deprecated v2.0** |
| `checkup:hasDNR` | xsd:boolean | `cascade:hasDNR` on `cascade:AdvanceDirectives` | **Deprecated v2.0** |
| `checkup:advanceDirectiveNotes` | xsd:string | `cascade:advanceDirectiveNotes` on `cascade:AdvanceDirectives` | **Deprecated v2.0** |

#### Insurance Properties (migrating to `coverage:` in WS4)

| Property | Range | Migration Target |
|----------|-------|-----------------|
| `checkup:subscriberName` | xsd:string | `coverage:subscriberName` |
| `checkup:subscriberRelationship` | xsd:string | `coverage:subscriberRelationship` |
| `checkup:effectiveDate` | xsd:date | `coverage:effectiveStart` |
| `checkup:expirationDate` | xsd:date | `coverage:effectiveEnd` |
| `checkup:rxBin` | xsd:string | `coverage:rxBin` |
| `checkup:rxPcn` | xsd:string | `coverage:rxPcn` |
| `checkup:rxGroup` | xsd:string | `coverage:rxGroup` |

### Patient Profile Properties

> **Removed in v3.0:** `checkup:PatientProfile` class has been removed. Use `cascade:PatientProfile` from Core Vocabulary v2.0. The properties below are retained in the ontology for backward compatibility with existing serialized data but must not be used in new serialization.

| Property | Range | Description |
|----------|-------|-------------|
| `checkup:patientName` | xsd:string | Full legal name |
| `checkup:dateOfBirth` | xsd:date | Date of birth — use `cascade:dateOfBirth` for new data |
| `checkup:computedAge` | xsd:integer | Age in years at form generation |
| `checkup:ageGroup` | xsd:string | pediatric, young_adult, adult, senior — use `cascade:ageGroup` for new data |
| `checkup:biologicalSex` | xsd:string | male, female, intersex — use `cascade:biologicalSex` for new data |
| `checkup:genderIdentity` | xsd:string | woman, man, non_binary, other, prefer_not_to_say — use `cascade:genderIdentity` for new data |

### Medication Summary Properties (Phase 3)

| Property | Range | Description |
|----------|-------|-------------|
| `checkup:medicationName` | xsd:string | Name of medication |
| `checkup:dose` | xsd:string | Dose with units |
| `checkup:frequency` | xsd:string | once_daily, twice_daily, as_needed, etc. |
| `checkup:adherenceStatus` | xsd:string | taking_as_prescribed, usually_take, sometimes_miss, etc. |
| `checkup:adherenceBarrier` | xsd:string | cost, side_effects, forgetfulness, etc. |
| `checkup:episodeId` | xsd:string | Link to MedicationUseEpisode |
| `checkup:indication` | xsd:string | Why patient takes medication |
| `checkup:patientCost` | xsd:decimal | Out-of-pocket cost |
| `checkup:functionalImpact` | xsd:string | How medication helps functionally |
| `checkup:needsVerification` | xsd:boolean | Whether medication needs patient verification (v1.7) |
| `checkup:verificationReason` | xsd:string | Why verification is needed: `historical`, `duplicate`, `conflicting_sources` (v1.7) |
| `checkup:lastVerifiedDate` | xsd:dateTime | When patient last verified this medication (v1.7) |
| `checkup:importSessionId` | xsd:anyURI | Link to the import session that created this record (v1.7) |

### Supplement Summary Properties

| Property | Range | Description |
|----------|-------|-------------|
| `checkup:supplementName` | xsd:string | Name of supplement |
| `checkup:regulatoryStatus` | xsd:string | dietarySupplement, otcDrug, homeopathic, herbalRemedy, unknown |
| `checkup:evidenceStrength` | xsd:string | strongEvidence, moderateEvidence, limitedEvidence, etc. |
| `checkup:doctorAware` | xsd:boolean | Whether provider knows about supplement |

### Screening Status Properties

| Property | Range | Description |
|----------|-------|-------------|
| `checkup:screeningType` | xsd:string | mammogram, colonoscopy, pap_smear, etc. |
| `checkup:screeningStatus` | xsd:string | not_due, due, overdue, completed, declined |
| `checkup:lastCompletedDate` | xsd:date | When screening was last completed |
| `checkup:nextDueDate` | xsd:date | When screening is next due |
| `checkup:guidelineSource` | xsd:string | USPSTF, ACS, AAP, ACOG, ADA |
| `checkup:gradeLevel` | xsd:string | USPSTF grade: A, B, C, D, I |


### Allergy Summary Properties (v1.1+, typed codes v1.6)

| Property | Namespace | Range | Description |
|----------|-----------|-------|-------------|
| `checkup:allergen` | checkup | xsd:string | Name of the allergenic substance (drug, food, environmental) |
| `checkup:reaction` | checkup | xsd:string | Type of allergic reaction: hives, rash, swelling, difficulty_breathing, anaphylaxis, nausea, other |
| `checkup:allergySeverity` | checkup | xsd:string | Severity: mild, moderate, severe, life_threatening |
| `checkup:allergyCategory` | checkup | xsd:string | Category: medication, food, environmental, latex, contrast, other |
| `clinical:snomedCode` | clinical | xsd:string | SNOMED CT allergen concept code (v1.6 — typed code alignment) |
| `clinical:rxNormCode` | clinical | xsd:string | RxNorm code for medication allergens (v1.6 — typed code alignment) |

### Condition Summary Properties (v1.1+, typed codes v1.6)

| Property | Namespace | Range | Description |
|----------|-----------|-------|-------------|
| `checkup:conditionName` | checkup | xsd:string | Name of the health condition or diagnosis |
| `checkup:onsetDate` | checkup | xsd:date | Date when condition was first diagnosed or symptoms began |
| `checkup:onsetYear` | checkup | xsd:gYear | Year of condition onset if exact date unknown |
| `checkup:conditionStatus` | checkup | xsd:string | Current status: active, resolved, remission, recurrence, inactive |
| `clinical:icd10Code` | clinical | xsd:string | ICD-10-CM diagnosis code (v1.6 — typed code alignment, replaces checkup:icd10Code) |
| `clinical:snomedCode` | clinical | xsd:string | SNOMED CT concept ID (v1.6 — typed code alignment, replaces checkup:snomedCode) |
| `clinical:linkedConditionIds` | clinical | xsd:string | Space-separated UUIDs of related ConditionSummary records (v1.6) |

### Family History Entry Properties (v1.1+, typed codes v1.6)

| Property | Namespace | Range | Description |
|----------|-----------|-------|-------------|
| `checkup:relativeType` | checkup | xsd:string | Relationship to patient: mother, father, sibling, maternal_grandmother, etc. |
| `checkup:relativeSex` | checkup | xsd:string | Biological sex of relative: male, female |
| `checkup:familyCondition` | checkup | xsd:string | Name of health condition the relative has/had |
| `checkup:ageAtDiagnosis` | checkup | xsd:integer | Relative's age when condition was diagnosed |
| `checkup:ageAtDeath` | checkup | xsd:integer | Relative's age at death if deceased |
| `checkup:isDeceased` | checkup | xsd:boolean | Whether the relative is deceased |
| `clinical:icd10Code` | clinical | xsd:string | ICD-10-CM code for the family condition (v1.6 — typed code alignment, replaces checkup:familyConditionCode) |
| `clinical:snomedCode` | clinical | xsd:string | SNOMED CT concept code for the family condition (v1.6 — typed code alignment) |

> **Typed Code Alignment (v1.6 / Task A2):** These classes previously used `checkup:`-namespaced code properties (`checkup:icd10Code`, `checkup:snomedCode`, `checkup:familyConditionCode`). These are now serialized using `clinical:` namespace predicates (`clinical:icd10Code`, `clinical:snomedCode`, `clinical:rxNormCode`, `clinical:cvxCode`, `clinical:loincCode`) consistent with the mixed namespace pattern. The `checkup:` variants are retained in the TTL for backward compatibility but deprecated for new serialization.

### Daily Check-in Class (v1.5)

```turtle
checkup:DailyCheckIn a owl:Class ;
    rdfs:label "Daily Check-in" ;
    rdfs:comment "Patient-reported daily medication adherence check-in capturing response status, missed medications, and optional notes." ;
    cascade:subConcern "self-report" ;
    rdfs:subClassOf health:SelfReport .
```

**Three-Layer Analysis:**
- **Layer 1:** LOINC `79474-4` (Health status questionnaire), SNOMED `225390008` (Self-assessment). Primary purpose is medication adherence tracking — SNOMED `418633004` (Medication compliance) is also relevant.
- **Layer 2:** `health:SelfReport` base class provides common self-report structure (reportDate, reportType, completionStatus, reportContext, reportNotes). DailyCheckIn extends this with medication-specific properties. Apps implement the SelfReportable protocol pattern to bridge Swift models to the ontology.
- **Layer 3:** `checkup:DailyCheckIn` — patient-facing adherence tracking record.

> **Gap documented:** No LOINC code exists for structured medication adherence check-in with per-medication tracking. `79474-4` (Health status questionnaire) is the closest standard mapping for self-reported daily check-ins.

| Property | Range | Description | Standard Mapping |
|----------|-------|-------------|-----------------|
| `checkup:checkInDate` | xsd:dateTime | Date of the check-in (normalized to midnight) | — |
| `checkup:checkInResponse` | xsd:string | Adherence response: `allTaken`, `missedSome`, `skippedToday` | SNOMED `418633004` |
| `checkup:missedMedicationIds` | xsd:string | Comma-separated UUIDs of missed medications (when response is `missedSome`) | — |
| `checkup:checkInNotes` | xsd:string | Optional patient notes about the day | — |
| `checkup:submittedAt` | xsd:dateTime | Timestamp when the check-in was submitted | — |

### Discussion Topic Class (v1.5)

```turtle
checkup:DiscussionTopic a owl:Class ;
    rdfs:label "Discussion Topic" ;
    rdfs:comment "AI-generated or user-created topic for discussion during a healthcare visit. Topics are derived from medication data, adherence patterns, supplement interactions, or user input." ;
    rdfs:subClassOf prov:Entity .
```

**Three-Layer Analysis:**
- **Layer 1:** No standard equivalent — Cascade-proprietary concept for visit preparation.
- **Layer 2:** Skipped — patient-curated list, not device or EHR data.
- **Layer 3:** `checkup:DiscussionTopic` — patient-facing visit discussion item.

> **Gap documented:** No SNOMED CT or LOINC code exists for "patient-curated discussion topic." This is a Cascade-proprietary concept combining AI-generated medication-related questions with user-created discussion items for visit preparation.

| Property | Range | Description |
|----------|-------|-------------|
| `checkup:topicText` | xsd:string | The discussion topic question or statement |
| `checkup:topicCategory` | xsd:string | Category: `durationBased`, `recentChange`, `adherenceConcern`, `sideEffectReport`, `multipleForSame`, `supplementDoctor`, `interactionRisk`, `refillDue`, `effectivenessConcern`, `costConcern`, `custom` |
| `checkup:topicSource` | xsd:string | Source type: `medication`, `supplement`, `medicationPair`, `supplementMedicationPair`, `adherencePattern`, `custom` |
| `checkup:relevanceScore` | xsd:double | AI-computed relevance score (0.0-1.0) |
| `checkup:isSelected` | xsd:boolean | Whether the topic is active for the next visit |
| `checkup:relatedMedicationName` | xsd:string | Optional medication name providing context |
| `checkup:detailText` | xsd:string | Optional supplementary detail text |
| `checkup:generatedAt` | xsd:dateTime | When the topic was generated or created |

### Check-in Settings Class (v1.5)

```turtle
checkup:CheckInSettings a owl:Class ;
    rdfs:label "Check-in Settings" ;
    rdfs:comment "Application configuration for daily check-in notification scheduling and day-of-week preferences." .
```

| Property | Range | Description |
|----------|-------|-------------|
| `checkup:checkInEnabled` | xsd:boolean | Whether daily check-ins are active |
| `checkup:notificationHour` | xsd:integer | Notification hour in 24-hour format (0-23) |
| `checkup:notificationMinute` | xsd:integer | Notification minute (0-59) |
| `checkup:enabledDays` | xsd:string | Comma-separated enabled days: `sunday`, `monday`, `tuesday`, `wednesday`, `thursday`, `friday`, `saturday` |

> **Note:** This is application configuration, not health data. No SNOMED/LOINC mapping needed. Included in export for complete backup/restore capability.

### Intake Questionnaire Response Class (v1.6)

```turtle
checkup:IntakeQuestionnaireResponse a owl:Class ;
    rdfs:label "Intake Questionnaire Response" ;
    rdfs:comment "Response to a standardized intake questionnaire section. Structure inspired by FHIR QuestionnaireResponse but uses native Cascade Protocol serialization. Uses LOINC panel codes as questionnaire identifiers and SNOMED CT codes for standardized answers." ;
    rdfs:subClassOf prov:Entity ;
    rdfs:seeAlso fhir:QuestionnaireResponse .
```

**Three-Layer Analysis:**
- **Layer 1:** FHIR QuestionnaireResponse (structural alignment, not full adoption). Uses LOINC panel codes as questionnaire identifiers (e.g., `71421-2` Social History, `10187-3` Review of Systems). Uses SNOMED CT for coded answers (e.g., `8517006` Former smoker).
- **Layer 2:** Skipped — patient-reported data, not device-generated or EHR-derived.
- **Layer 3:** `checkup:IntakeQuestionnaireResponse` — patient-facing intake form data container.

> **Design rationale:** Full FHIR QuestionnaireResponse was evaluated and rejected: ~5-6x more verbose in RDF/Turtle due to `fhir:v` blank-node wrapping for every primitive value, creates two incompatible RDF patterns in the same Pod, and no standard FHIR Questionnaires combine surgical + social + safety screening into a single intake form. The hybrid approach uses LOINC/SNOMED as the actual vocabulary with `checkup:` providing only the minimal container. A mechanical transformation to FHIR QuestionnaireResponse JSON is preserved for clinical system export.

| Property | Range | Description | Standard Mapping |
|----------|-------|-------------|-----------------|
| `checkup:questionnaireId` | xsd:string | LOINC panel code identifying the questionnaire section | LOINC panel codes (e.g., `71421-2`) |
| `checkup:questionnaireTitle` | xsd:string | Human-readable title of the questionnaire section | — |
| `checkup:responseItem` | checkup:ResponseItem | Link to a question-answer pair | FHIR QuestionnaireResponse.item |
| `checkup:completedAt` | xsd:dateTime | Timestamp when the questionnaire was completed | — |
| `cascade:dataProvenance` | cascade:DataProvenance | Source of the questionnaire data | W3C PROV-O |

### Response Item Class (v1.6)

```turtle
checkup:ResponseItem a owl:Class ;
    rdfs:label "Response Item" ;
    rdfs:comment "A question-answer pair within an intake questionnaire response. Uses LOINC item codes as link identifiers and SNOMED CT codes for coded answers where available. Supports nested sub-items via childItem for hierarchical questionnaire structures." ;
    rdfs:subClassOf prov:Entity .
```

**Three-Layer Analysis:**
- **Layer 1:** Maps to FHIR QuestionnaireResponse.item structure. Individual items use LOINC codes as linkId values (e.g., `72166-2` Tobacco smoking status, `63512-8` Alcohol use).
- **Layer 2:** Skipped — question-answer pairs are patient-facing data.
- **Layer 3:** `checkup:ResponseItem` — individual question-answer entry.

| Property | Range | Description | Standard Mapping |
|----------|-------|-------------|-----------------|
| `checkup:itemLinkId` | xsd:string | LOINC item code identifying the question | LOINC item codes |
| `checkup:itemText` | xsd:string | Human-readable question display text | — |
| `checkup:itemAnswer` | xsd:string | Free-text answer value | — |
| `checkup:itemAnswerCode` | xsd:string | Coded answer value (SNOMED CT or LOINC answer code) | SNOMED CT / LOINC |
| `checkup:itemAnswerCodeSystem` | xsd:anyURI | Code system URI for the coded answer | — |
| `checkup:childItem` | checkup:ResponseItem | Nested sub-item for hierarchical questions | FHIR QuestionnaireResponse.item.item |

### Intake Questionnaire RDF Example (v1.6)

```turtle
@prefix checkup: <https://ns.cascadeprotocol.org/checkup/v1#> .
@prefix cascade: <https://ns.cascadeprotocol.org/core/v1#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

# Social History questionnaire response
_:social-hx a checkup:IntakeQuestionnaireResponse ;
    checkup:questionnaireId "71421-2" ;          # LOINC social history panel
    checkup:questionnaireTitle "Social History" ;
    checkup:completedAt "2026-02-09T14:30:00Z"^^xsd:dateTime ;
    cascade:dataProvenance cascade:SelfReported ;
    checkup:responseItem _:sh1, _:sh2, _:sh3 .

_:sh1 a checkup:ResponseItem ;
    checkup:itemLinkId "72166-2" ;               # LOINC: Tobacco smoking status
    checkup:itemText "Smoking Status" ;
    checkup:itemAnswer "Former smoker" ;
    checkup:itemAnswerCode "8517006" ;            # SNOMED: Former smoker
    checkup:itemAnswerCodeSystem <http://snomed.info/sct/> .

_:sh2 a checkup:ResponseItem ;
    checkup:itemLinkId "63512-8" ;               # LOINC: Alcohol use
    checkup:itemText "Alcohol Use" ;
    checkup:itemAnswer "Social drinker, 2-3 drinks per week" .

_:sh3 a checkup:ResponseItem ;
    checkup:itemLinkId "74009-2" ;               # LOINC: Occupation
    checkup:itemText "Occupation" ;
    checkup:itemAnswer "Software Engineer" .

# Surgical History questionnaire response
_:surgical-hx a checkup:IntakeQuestionnaireResponse ;
    checkup:questionnaireId "10167-5" ;          # LOINC: Surgical history
    checkup:questionnaireTitle "Surgical History" ;
    checkup:completedAt "2026-02-09T14:30:00Z"^^xsd:dateTime ;
    cascade:dataProvenance cascade:SelfReported ;
    checkup:responseItem _:surg1 .

_:surg1 a checkup:ResponseItem ;
    checkup:itemLinkId "80944-3" ;               # LOINC: Surgical procedure
    checkup:itemText "Previous Surgery" ;
    checkup:itemAnswer "Appendectomy, 2018" ;
    checkup:itemAnswerCode "80146-5" ;           # LOINC: Appendectomy
    checkup:itemAnswerCodeSystem <http://loinc.org/> .
```

> **Template-driven scalability:** Questionnaire templates are defined as JSON data files, not Swift code. A generic questionnaire renderer takes a template and produces a fill-in UI. New intake sections are added by adding template files with zero code changes. Priority order: (P1) surgical history, social history basics; (P2) advanced care planning, pharmacy preference; (P3) safety screening, sexual health.

### Immunization Summary Class (v1.7)

```turtle
checkup:ImmunizationSummary a owl:Class ;
    rdfs:label "Immunization Summary" ;
    rdfs:comment "Patient-facing immunization record for intake forms. Uses mixed namespace pattern: checkup: properties for app-layer enrichment (vaccineCategory) alongside clinical data fields." ;
    rdfs:subClassOf prov:Entity .
```

**Three-Layer Analysis:**
- **Layer 1:** Vaccine codes from CVX standard; administration details align with FHIR Immunization resource structure.
- **Layer 2:** Source data uses `clinical:Immunization` for EHR-imported records.
- **Layer 3:** `checkup:ImmunizationSummary` — patient-facing summary using the **mixed namespace pattern**. Most properties use `clinical:` namespace directly; `checkup:vaccineCategory` adds app-layer categorization for intake form display.

> **Mixed Namespace Pattern:** This class is a canonical example of the mixed namespace pattern used by Layer 3 summary classes. The `checkup:` namespace defines the container class and adds only app-layer enrichment properties (e.g., `checkup:vaccineCategory`). All standardized clinical data properties are referenced directly from `clinical:` namespace, avoiding data replication across layers.

| Property | Namespace | Range | Description |
|----------|-----------|-------|-------------|
| `checkup:vaccineName` | checkup | xsd:string | Name of vaccine administered |
| `checkup:administrationDate` | checkup | xsd:dateTime | Date vaccine was administered |
| `checkup:immunizationStatus` | checkup | xsd:string | Status: `completed`, `entered-in-error`, `not-done` |
| `checkup:vaccineCode` | checkup | xsd:string | CVX vaccine code for standardized identification |
| `checkup:vaccineCategory` | checkup | xsd:string | Categorization for intake: `routine`, `travel`, `occupational`, `other` |
| `checkup:manufacturer` | checkup | xsd:string | Vaccine manufacturer name |
| `checkup:lotNumber` | checkup | xsd:string | Vaccine lot number |
| `checkup:expirationDate` | checkup | xsd:date | Vaccine expiration date |
| `checkup:doseNumber` | checkup | xsd:integer | Dose sequence number in multi-dose series |
| `checkup:doseQuantity` | checkup | xsd:string | Dose quantity administered |
| `checkup:administrationRoute` | checkup | xsd:string | Route: `intramuscular`, `subcutaneous`, `oral`, etc. |
| `checkup:administrationSite` | checkup | xsd:string | Body site: `left arm`, `right arm`, etc. |
| `checkup:administeringProvider` | checkup | xsd:string | Name of provider who administered vaccine |
| `checkup:administeringLocation` | checkup | xsd:string | Location where vaccine was administered |
| `checkup:immunizationNotes` | checkup | xsd:string | Additional notes about immunization |
| `checkup:immunizationSourceRecord` | checkup | xsd:anyURI | Link to source `clinical:Immunization` record |

### Lab Result Summary Class (v1.7)

```turtle
checkup:LabResultSummary a owl:Class ;
    rdfs:label "Lab Result Summary" ;
    rdfs:comment "Patient-facing lab result summary for intake forms. Uses mixed namespace pattern: checkup:labCategory for app-layer categorization, clinical: properties for standardized lab data." ;
    rdfs:subClassOf prov:Entity .
```

**Three-Layer Analysis:**
- **Layer 1:** Lab result data uses LOINC codes for test identification and SNOMED CT for specimen types.
- **Layer 2:** Source data uses `clinical:LabResult` for EHR-imported records.
- **Layer 3:** `checkup:LabResultSummary` — patient-facing summary. Adds only `checkup:labCategory` for intake form display grouping; all clinical properties reference `clinical:` namespace directly via the mixed namespace pattern.

| Property | Namespace | Range | Description |
|----------|-----------|-------|-------------|
| `checkup:labCategory` | checkup | xsd:string | Intake form display category: `metabolic`, `hematology`, `lipid`, `thyroid`, `vitamin`, `other` |
| `clinical:testName` | clinical | xsd:string | Name of the lab test |
| `clinical:value` | clinical | xsd:string | Test result value |
| `clinical:interpretation` | clinical | xsd:string | Clinical interpretation |
| `clinical:effectiveDate` | clinical | xsd:dateTime | Date of test |
| `clinical:loincCode` | clinical | xsd:string | LOINC code identifying the test |
| `clinical:unit` | clinical | xsd:string | Unit of measurement |
| `clinical:referenceRange` | clinical | xsd:string | Reference range text |
| `clinical:referenceRangeLow` | clinical | xsd:double | Low bound of reference range |
| `clinical:referenceRangeHigh` | clinical | xsd:double | High bound of reference range |
| `clinical:specimenType` | clinical | xsd:string | Specimen type |
| `clinical:orderingProvider` | clinical | xsd:string | Ordering provider |
| `clinical:performingLab` | clinical | xsd:string | Performing laboratory |

### Wellness Profile Reference Class (v1.7)

```turtle
checkup:WellnessProfileReference a owl:Class ;
    rdfs:label "Wellness Profile Reference" ;
    rdfs:comment "Lightweight pointer to the patient's full wellness profile stored in the SDK HealthProfile. Uses rdfs:seeAlso to link to the wellness data file." ;
    rdfs:subClassOf prov:Entity .
```

**Three-Layer Analysis:**
- **Layer 1:** No standard equivalent — Cascade-specific container reference.
- **Layer 2:** Points to the SDK `HealthProfile` data via `rdfs:seeAlso`.
- **Layer 3:** `checkup:WellnessProfileReference` — structural link, no checkup-specific properties. Uses only `rdfs:seeAlso` (URI) and `rdfs:comment` (string).

### Suggested Question Additional Properties (v1.7)

| Property | Range | Description |
|----------|-------|-------------|
| `checkup:basedOnTemplate` | xsd:string | Template name the question was generated from |
| `checkup:basedOnScreening` | xsd:anyURI | Link to the screening record the question relates to |

### Visit Prep Summary — noteContent Property (v1.7)

Added to the existing `checkup:VisitPrepSummary` class (v1.4). Merges the previously planned separate `VisitPrepNotes` class into a single property:

| Property | Range | Description |
|----------|-------|-------------|
| `checkup:noteContent` | xsd:string | Free-text notes for visit preparation (user-authored discussion points) |

### Intake Form Data Aggregate Links (v1.7)

New aggregate link properties on `checkup:IntakeFormData`:

| Property | Range | Description |
|----------|-------|-------------|
| `checkup:hasImmunization` | checkup:ImmunizationSummary | Link to an immunization summary entry |
| `checkup:hasLabResult` | checkup:LabResultSummary | Link to a lab result summary entry |

### MedicationChangeRecord Properties (v1.9)

Tracks changes to medications and supplements between visit snapshots. Consumed by report generators (`PlainTextReportGenerator`, `PatientBriefSections`, `ProviderViews`) for the "Changes Since Last Visit" section.

**Three-Layer Analysis:**
- **Layer 1:** No standard equivalent. FHIR tracks medication versions via `Provenance` resources but has no discrete "change record" resource.
- **Layer 2:** Not applicable — change tracking is app-layer behavior, not clinical vocabulary.
- **Layer 3:** `checkup:MedicationChangeRecord` — Cascade-proprietary. Captures the delta between visit snapshots for patient-facing reports.

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `checkup:changeType` | DatatypeProperty | xsd:string | Type of change: `added`, `stopped`, `doseChanged`, `frequencyChanged`, `adherenceChanged`, `statusChanged` |
| `checkup:changedField` | DatatypeProperty | xsd:string | Name of the field that was changed (e.g., `dose`, `frequency`) |
| `checkup:changeRecordPreviousValue` | DatatypeProperty | xsd:string | Value of the field before the change |
| `checkup:changeRecordNewValue` | DatatypeProperty | xsd:string | Value of the field after the change |
| `checkup:changeDate` | DatatypeProperty | xsd:dateTime | Date when the change occurred |

**Aggregate Link:**

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `checkup:hasChange` | ObjectProperty | `checkup:MedicationChangeRecord` | Link from `MedicationSummary` or `SupplementSummary` to a change record |

**TTL Example:**
```turtle
<#med-change-abc123-0> a checkup:MedicationChangeRecord ;
    checkup:changeType "doseChanged" ;
    checkup:changedField "dose" ;
    checkup:changeRecordPreviousValue "10mg" ;
    checkup:changeRecordNewValue "20mg" ;
    checkup:changeDate "2026-02-01T00:00:00Z"^^xsd:dateTime .

<#medication-abc123> a checkup:MedicationSummary ;
    checkup:medicationName "Lisinopril" ;
    checkup:hasChange <#med-change-abc123-0> .
```

### VisitPrepTray Class (v3.1)

```turtle
checkup:VisitPrepTray a owl:Class ;
    rdfs:label "Visit Prep Tray" ;
    rdfs:comment "Per-appointment visit preparation container grouping issues, discussion topics, questions, and notes. Uses a typed payload wrapper (VisitItemPayload) to preserve existing type richness from VisitIssue, DiscussionTopic, and SuggestedQuestion." ;
    cascade:subConcern "intake" ;
    rdfs:subClassOf prov:Entity .
```

**Three-Layer Analysis:**
- **Layer 1:** No standard equivalent. FHIR has no "visit preparation tray" concept. Closest is `Encounter.reasonReference` which links conditions/observations to appointments.
- **Layer 2:** Not applicable — visit preparation is patient-curated, not clinical or device data.
- **Layer 3:** `checkup:VisitPrepTray` — Cascade-proprietary. Organizes patient visit preparation items by appointment with intent categories (discuss, schedule, inform, ask).

> **Distinction from `checkup:VisitPrepSummary`:** `VisitPrepSummary` (v1.4) is a rendered one-page clinical summary for appointments. `VisitPrepTray` (v3.1) is an interactive item container that the patient builds up before a visit — items can be added, resolved, and reorganized. The summary is output; the tray is input.

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `checkup:prepTitle` | DatatypeProperty | xsd:string | Display title for the visit prep (e.g., "Rheumatologist — Feb 28") |
| `checkup:appointmentDate` | DatatypeProperty | xsd:dateTime | Scheduled appointment date |
| `checkup:providerName` | DatatypeProperty | xsd:string | Name of the healthcare provider |
| `checkup:specialty` | DatatypeProperty | xsd:string | Provider specialty (e.g., "Rheumatology") |
| `checkup:prepStatus` | DatatypeProperty | xsd:string | Tray status: `preparing`, `ready`, `completed` |
| `checkup:completedDate` | DatatypeProperty | xsd:dateTime | When the visit was marked completed |
| `checkup:hasTrayItem` | ObjectProperty | checkup:VisitTrayItem | Link to a tray item |

**Visit Tray Item Properties:**

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `checkup:payloadType` | DatatypeProperty | xsd:string | Payload discriminator: `issue`, `topic`, `question`, `note`, `custom` |
| `checkup:intentCategory` | DatatypeProperty | xsd:string | Intent: `discuss`, `schedule`, `inform`, `ask` |
| `checkup:isResolved` | DatatypeProperty | xsd:boolean | Whether the item has been addressed |
| `checkup:sourceSection` | DatatypeProperty | xsd:string | Health Map section this item originated from (for `custom` payload type) |
| `checkup:sourceRecordId` | DatatypeProperty | xsd:anyURI | Link to the source record that prompted this item |

**Aggregate Links on IntakeFormData:**

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `checkup:hasVisitPrep` | ObjectProperty | checkup:VisitPrepTray | Link to a visit preparation tray |
| `checkup:activeVisitPrepId` | DatatypeProperty | xsd:string | UUID of the currently active visit prep tray |

---

## Checkup SHACL Shapes (Adult)

Validation shapes for adult patients (ages 18-64).

### Severity Levels

| Level | Meaning |
|-------|---------|
| `sh:Violation` | Must fix (blocks export) |
| `sh:Warning` | Should address (shown prominently) |
| `sh:Info` | Nice to have (suggestions) |

### IntakeFormData Validation

```turtle
checkup:IntakeFormDataShape a sh:NodeShape ;
    sh:targetClass checkup:IntakeFormData ;

    # VIOLATION: Patient Profile required (now cascade:PatientProfile)
    sh:property [
        sh:path checkup:hasPatientProfile ;
        sh:minCount 1 ;
        sh:node cascade:PatientProfileShape ;
        sh:severity sh:Violation ;
        sh:message "Patient profile is required for intake forms"
    ] ;

    # WARNING: Medications
    sh:property [
        sh:path checkup:hasMedication ;
        sh:node checkup:MedicationSummaryShape ;
        sh:severity sh:Warning ;
        sh:message "Medication list helps providers avoid drug interactions."
    ] ;

    # WARNING: Allergies
    sh:property [
        sh:path checkup:hasAllergy ;
        sh:node checkup:AllergySummaryShape ;
        sh:severity sh:Warning ;
        sh:message "Allergy information helps prevent adverse reactions."
    ] .
```

### Patient Profile Validation

> **Note:** `checkup:PatientProfile` was removed in v3.0. Patient profile validation is now defined in `core.shapes.ttl` as `cascade:PatientProfileShape`.

Required fields (VIOLATION if missing):
- `patientName` - minimum 2 characters
- `dateOfBirth` - xsd:date
- `biologicalSex` - male, female, or intersex

### Supplement Summary Validation

Required fields:
- `supplementName` - minimum 2 characters
- `regulatoryStatus` - REQUIRED to distinguish from medications

Valid regulatory statuses: dietarySupplement, otcDrug, homeopathic, herbalRemedy, unknown

---

## SHACL Validation

The Cascade Protocol uses [SHACL (Shapes Constraint Language)](https://www.w3.org/TR/shacl/) to validate RDF data against vocabulary constraints. Each vocabulary has a companion `.shapes.ttl` file that defines required properties, value ranges, and data quality expectations.

### Shapes Files

| File | Version | Vocabulary | Description |
|------|---------|------------|-------------|
| `core.shapes.ttl` | v1.0 | Core (`cascade:`) | PatientProfile demographics, Address structure, DataProvenance taxonomy |
| `clinical.shapes.ttl` | v1.0 | Clinical (`clinical:`) | ClinicalDocument, MedicationUseEpisode, Supplement required fields |
| `health.shapes.ttl` | v1.0 | Health (`health:`) | HealthProfile vital signs, MetricTrend enums, statistical summaries |
| `pots.shapes.ttl` | v1.0 | POTS (`pots:`) | POTSCheckResult protocol fields, HeartRateMeasurement timing |
| `coverage.shapes.ttl` | v1.0 | Coverage (`coverage:`) | InsurancePlan required fields, date ranges, plan type enums |
| `checkup.shapes.ttl` | v2.0 | Checkup (`checkup:`) | IntakeFormData completeness, adult patient validation (ages 18-64) |

### Severity Levels

All shapes files use three severity levels consistently:

| Level | Meaning | Example |
|-------|---------|---------|
| `sh:Violation` | Must fix — blocks export or indicates invalid data | Missing `patientName` on PatientProfile |
| `sh:Warning` | Should address — shown prominently in validation UI | No medications listed on intake form |
| `sh:Info` | Nice to have — suggestions for data completeness | Missing optional screening status |

### Usage

Shapes files are designed for:
- **Build-time validation** in Swift serialization tests
- **Export-time validation** before generating patient reports
- **Import-time validation** when processing external data

For detailed shape definitions, see the SHACL subsection in each vocabulary's documentation above, or the individual `.shapes.ttl` files in the ontology repository.

---

## Diabetes Vocabulary v1.0-draft

**Namespace:** `https://ns.cascadeprotocol.org/diabetes/v1#`
**Prefix:** `diabetes:`
**Status:** Draft (subject to change)
**Imports:** Core Vocabulary v1

Unified vocabulary for diabetes and pre-diabetes management, aggregating data from CGMs, glucose meters, insulin delivery systems, and lifestyle tracking devices.

### Diabetes Classification

| Class | Description | SNOMED CT |
|-------|-------------|-----------|
| `diabetes:Type1` | Autoimmune destruction of beta cells | sct:46635009 |
| `diabetes:Type2` | Insulin resistance with relative deficiency | sct:44054006 |
| `diabetes:Prediabetes` | Impaired glucose tolerance | sct:714628002 |
| `diabetes:GestationalDiabetes` | Diabetes diagnosed during pregnancy | sct:11687002 |
| `diabetes:LADA` | Latent autoimmune diabetes in adults | - |

### Glucose Measurement Classes

| Class | Description |
|-------|-------------|
| `diabetes:GlucoseReading` | Single blood glucose measurement from any source |
| `diabetes:CGMReading` | Interstitial glucose from CGM sensor |
| `diabetes:FingerStick` | Capillary blood from test strip meter |
| `diabetes:VenousLab` | Laboratory plasma glucose |
| `diabetes:CGMSession` | CGM monitoring session (10-14 days per sensor) |

### Insulin Delivery Classes

| Class | Description |
|-------|-------------|
| `diabetes:InsulinDose` | Record of insulin delivery |
| `diabetes:RapidActing` | Onset 15 min, peak 1-2 hr (Humalog, NovoLog) |
| `diabetes:ShortActing` | Onset 30 min, peak 2-4 hr (Regular) |
| `diabetes:IntermediateActing` | Onset 1-2 hr, peak 4-12 hr (NPH) |
| `diabetes:LongActing` | Onset 1-2 hr, no peak, 20-24+ hr (Lantus, Tresiba) |
| `diabetes:Bolus` | Meal bolus for carbohydrate coverage |
| `diabetes:CorrectionBolus` | Bolus to correct elevated glucose |
| `diabetes:Basal` | Background insulin for fasting control |

### Time in Range Metrics (ADA/EASD Consensus)

| Property | Target | Description |
|----------|--------|-------------|
| `diabetes:timeInRange` | >70% | % time 70-180 mg/dL |
| `diabetes:timeBelowRange` | <4% | % time <70 mg/dL |
| `diabetes:timeAboveRange` | <25% | % time >180 mg/dL |
| `diabetes:timeSeverelyLow` | <1% | % time <54 mg/dL |
| `diabetes:timeSeverelyHigh` | <5% | % time >250 mg/dL |
| `diabetes:coefficientOfVariation` | <36% | CV = SD/Mean * 100 |
| `diabetes:gmi` | - | Glucose Management Indicator (estimated HbA1c) |

### Pattern Detection

| Pattern Type | Description |
|--------------|-------------|
| `diabetes:DawnPhenomenon` | Early morning glucose rise (4-7 AM) |
| `diabetes:PostprandialSpike` | Glucose rise 1-3 hours after meals |
| `diabetes:ExerciseResponse` | Glucose changes during/after activity |
| `diabetes:NocturnalHypoglycemia` | Low glucose during sleep (12-6 AM) |
| `diabetes:InsulinSensitivityPattern` | Time-of-day variations in insulin effectiveness |

### Diabetes Profile Properties

| Property | Range | Description |
|----------|-------|-------------|
| `diabetes:diabetesType` | diabetes:DiabetesType | Type 1, Type 2, etc. |
| `diabetes:diagnosisDate` | xsd:date | When diagnosed |
| `diabetes:targetRangeLow` | xsd:double | Lower bound (default 70 mg/dL) |
| `diabetes:targetRangeHigh` | xsd:double | Upper bound (default 180 mg/dL) |
| `diabetes:carbRatio` | xsd:double | Grams of carbs per unit insulin |
| `diabetes:correctionFactor` | xsd:double | Expected glucose drop per unit |
| `diabetes:activeCGM` | xsd:string | Current CGM system |
| `diabetes:activeInsulinPump` | xsd:string | Current insulin pump |

### Pod Storage Paths (Recommended)

```
/wellness/diabetes/
  profile.ttl                    - DiabetesProfile
  daily-summaries/YYYY-MM-DD.ttl - DailyGlucoseSummary
  glucose-readings/YYYY-MM-DD.ttl - GlucoseReading batch
  insulin-doses/YYYY-MM-DD.ttl   - InsulinDose records
  meals/YYYY-MM-DD.ttl           - MealEvent/CarbEntry
  patterns/detected.ttl          - GlucosePattern analysis
  events/hypo.ttl                - HypoglycemicEvent log
  events/hyper.ttl               - HyperglycemicEvent log
  labs/results.ttl               - HbA1c and other labs
```

---

## Genomics Vocabulary v1.0-draft

**Namespace:** `https://ns.cascadeprotocol.org/genomics/v1#`
**Prefix:** `genomics:`
**Status:** Draft (v1-draft.0.2, 2026-05-05)
**Imports:** Core Vocabulary v1, Clinical Vocabulary v1
**Schema files:** [genomics.ttl](/docs/genomics/v1-draft/genomics.ttl) · [genomics.shapes.ttl](/docs/genomics/v1-draft/genomics.shapes.ttl)

> **Draft notice (per D-PATH).** The namespace URI is the stable major (`genomics/v1#`); the version-info string is `1.0-draft`. Pre-stable drafts are NOT registered in `spec/VOCAB_VERSIONS` — they land there only at v1.0 graduation.

Layer 2 vocabulary that bridges Layer 1 genomics standards (HGVS, ClinVar, VRS, HGNC, Sequence Ontology, HPO, MONDO/OMIM/ORDO, ACMG/AMP via LOINC answer codes, ClinGen review-status taxonomy) to Layer 3 patient-facing genetic counseling summaries (`checkup:GeneticCounselingSummary`, `checkup:VariantNarrative`).

### Variant + Interpretation

| Class | Anchor | Purpose |
|-------|--------|---------|
| `genomics:Variant` | `fhir:Observation`, `prov:Entity` | Single sequence variant. HGVS c./p./g., ClinVar VCV/RCV, VRS/CAid, HGNC gene, SO consequence term, zygosity, phase. |
| `genomics:CopyNumberVariant` | subClassOf `Variant` | CNV with `cnvIntervalStart`, `cnvIntervalEnd`, `cnvIntervalRef`, `copyNumber`. |
| `genomics:VariantInterpretation` | `prov:Entity` | ACMG/AMP classification at a point in time. Reclassification creates a new instance linked to the prior via `prov:wasRevisionOf`; never edit in place. Cardinality 1..1 on `condition` and `variantInterpreted` (D-Q5). |
| `genomics:Haplotype` | `fhir:Observation` | Multi-variant unit on one chromosome (PharmVar star alleles, HLA typing). |
| `genomics:Diplotype` | `fhir:Observation` | Pair of haplotypes (e.g., CYP2D6 *1/*4). |

### Pedigree

| Class | Purpose |
|-------|---------|
| `genomics:Pedigree` | Family-structure graph rooted at a `proband`. |
| `genomics:PedigreeMember` | One member with `relativeRole` (HL7 v3 RoleCode), `relativeSex`, `isDeceased`, `ageAtDeath`, `carrierStatus`, `testedForVariant`, `hpoTerm`, `phenotypeOnsetAge`. |

The Layer 3 `FamilyHistoryEntry` (ICD-10 + SNOMED, patient-reported) is unchanged — apps that don't do genetics keep using it.

### Tests, orders, and submitter assertions

| Class | Anchor | Purpose |
|-------|--------|---------|
| `genomics:GeneticTest` | `prov:Entity` | Test report. `testType`, `genePanel`, `variantsObserved`, `orderingProvider`, `performingLab`. |
| `genomics:GeneticTestOrder` | `fhir:ServiceRequest` | Pre-result test order. `orderedAt`, `orderStatus`, `resultedIn`. |
| `genomics:SubmitterAssertion` | `prov:Entity` | Per-submitter classification feeding aggregated `VariantInterpretation`. ClinVar VCV/SCV pattern via `aggregatedFrom`. |

### Sequencing-run provenance (per D-DIRECTORY)

| Class | Anchor | Purpose |
|-------|--------|---------|
| `genomics:SequencingRun` | `prov:Activity` | Sequencing-event metadata: `coverageDepth`, `sequencingTechnology`, `variantCallerVersion`, `laboratoryCertification`, sample/sequencing/file-generation dates. |
| `genomics:RawFile` | `prov:Entity` | Pointer-and-hash for BAM/CRAM/FASTQ/VCF. **Cascade does NOT ingest the bytes.** Carries `fileFormat`, `fileSizeBytes` (xsd:long for 50–100 GB BAM/CRAM cases), `fileHashSHA256`, `fileLocation`, `referenceGenome`, `htsgetEndpoint`. |

### Data-quality tier model (per D-QUALITY-TIER)

| Individual | Criterion |
|------------|-----------|
| `genomics:ClinicalGrade` | CLIA / CAP / ISO15189 lab + clinical-grade method (≥30x WGS or validated panel) + raw files retained. |
| `genomics:ResearchGrade` | Research-quality sequencing without full clinical certification. |
| `genomics:ConsumerGrade` | DTC genotyping arrays (23andMe, AncestryDNA, etc.) — explicitly lands here. |
| `genomics:UnknownQuality` | Quality tier cannot be determined. |

`genomics:dataQualityTier` annotates each `Variant`. The SHACL safety constraint requires that any `Pathogenic` / `LikelyPathogenic` `VariantInterpretation` either reference a `ClinicalGrade` Variant OR carry `requiresConfirmation true`.

### Closed enumerations

- **ACMG class:** `Pathogenic`, `LikelyPathogenic`, `VUS`, `LikelyBenign`, `Benign` (LOINC-coded).
- **Inheritance:** `AutosomalDominant`, `AutosomalRecessive`, `XLinkedDominant`, `XLinkedRecessive`, `Mitochondrial`, `YLinked`, `MultifactorialPolygenic`, `UnknownInheritance`.
- **Allelic requirement:** `Monoallelic`, `Biallelic`.
- **Zygosity:** `Heterozygous`, `Homozygous`, `Hemizygous`, `CompoundHeterozygous`, `MosaicLow`, `MosaicHigh`.
- **Phase:** `Cis`, `Trans`, `PhaseUnknown`.
- **Carrier status:** `PositiveAffected`, `PositiveUnaffected`, `Negative`, `NotTested`, `Obligate`.
- **Test type:** `SingleGeneTest`, `GenePanelTest`, `ExomeSequencing`, `GenomeSequencing`, `ChromosomalMicroarray`, `KaryotypeAnalysis`, `MLPA`, `RepeatExpansionTest`, `MethylationStudy`, `RNASequencing`.
- **Sequencing technology:** `ShortReadIllumina`, `LongReadONT`, `LongReadPacBio`, `Mixed`, `GenotypingArray`.
- **Lab certification:** `CLIA`, `CAP`, `ISO15189`, `Uncertified`.
- **File format:** `BAM`, `CRAM`, `FASTQ`, `gVCF`, `VCF`, `BCF`, `OtherFileFormat`.
- **Submitter category:** `SubmitterLaboratory`, `SubmitterConsortium`, `SubmitterExpertPanel`, `SubmitterResearch`, `SubmitterClinician`.
- **Order status:** `OrderPending`, `OrderInProgress`, `OrderResulted`, `OrderCancelled`.
- **Causality status:** `Causative`, `Contributory`, `UncertainCausality`, `Rejected` — Phenopacket-aligned variant-explains-phenotype semantics, distinct from ACMG classification.
- **Review status (ClinVar):** `NoAssertionProvided`, `CriteriaNotProvided`, `SingleSubmitter`, `ConflictingSubmissions`, `MultipleSubmittersNoConflict`, `ExpertPanelReviewed`, `PracticeGuideline` with `starRating` annotation.
- **Data provenance (genomics-specific):** `ConsumerArray`, `ClinicalSequencing`, `ResearchSequencing`, `Imported`, `AIExtractedGenomics`. Distinct from `cascade:dataProvenance`; the consumer-array lane drives Phase 2C importer routing.
- **Data quality tier:** `ClinicalGrade`, `ResearchGrade`, `ConsumerGrade`, `UnknownQuality`.
- **Somatic status (v0.2):** `Germline`, `Somatic`, `UnknownSomaticStatus`.

### v1-draft.0.2 additions (2026-05-05)

Phase 1 importer gaps surfaced four high-confidence additions. All additive; existing data validates unchanged.

| Term | Type | Maps | Purpose |
|------|------|------|---------|
| `genomics:reportedRecord` | ObjectProperty (no `rdfs:range`) | — | Generic GeneticTest &rarr; record predicate covering Diplotype / Haplotype / PGx implication / future genomics records. Resolves the HLA tie-break: `variantsObserved` has `rdfs:range genomics:Variant` and cannot represent non-Variant report links. |
| `genomics:refAllele` | DatatypeProperty (`xsd:string`) | LOINC 69547-8 | VCF-style reference allele string. |
| `genomics:altAllele` | DatatypeProperty (`xsd:string`) | LOINC 69551-0 | VCF-style alternate allele string. |
| `genomics:genomicStartEnd` | DatatypeProperty (`xsd:string`) | LOINC 81254-5 | 1-based inclusive `chrN:start-end` coordinates. |
| `genomics:somaticStatus` | ObjectProperty &rarr; `genomics:SomaticStatus` | LOINC 48002-0 | Germline vs somatic. Three named individuals: `Germline`, `Somatic`, `UnknownSomaticStatus`. |
| `genomics:variantAlleleFrequency` | DatatypeProperty (`xsd:decimal`, SHACL 0.0&ndash;1.0) | LOINC 81258-6 | VAF as a sequencing-evidence fraction. Distinct from `mosaicismFraction` (clinical conclusion). |

**Deferred** (need Ellen review or more importer experience): `genomics:CompositeVariant`, LOINC 48013-7 / 48019-4 / 48001-2, multi-gene Diplotype, SNOMED reaction-coding system.

See [genomics/v1-draft/](/docs/genomics/v1-draft/) for the full vocabulary documentation and the spec changelog at `spec/ontologies/genomics/CHANGELOG.md`.

---

## Advisory Vocabulary v1.0-draft

**Namespace:** `https://ns.cascadeprotocol.org/advisory/v1#`
**Prefix:** `advisory:`
**Status:** Draft (v1.0-draft.0.1, 2026-05-05)
**Underlying spec:** [W3C Linked Data Patch Format](https://www.w3.org/TR/ldpatch/) (Recommendation, 2015)
**Imports:** Core Vocabulary v1
**Schema files:** [advisory.ttl](/docs/advisory/v1-draft/advisory.ttl) · [advisory.shapes.ttl](/docs/advisory/v1-draft/advisory.shapes.ttl)

> **Draft notice (per D-PATH).** Pre-stable drafts are NOT registered in `spec/VOCAB_VERSIONS`.

The Advisory Vocabulary defines the **Cascade Advisory Patch (CAP) profile** — a strict subset of W3C LDPatch designed for clinical knowledge updates that are author-readable, statically auditable, and bounded in execution. Forward-compatible with full LDPatch — every CAP file is a valid LDPatch file.

### CAP profile constraints

| Constraint | Rule |
|------------|------|
| **C1: Operations** | Only `Add` and `Bind`. No `Delete`, `Cut`, or `UpdateList`. Supersession via `prov:wasRevisionOf` (additive, never destructive). |
| **C2: Single-identifier match** | At most one `Bind` per advisory. Path expression must be `?var <predicate> <literal>` where the predicate is whitelisted (`genomics:caId`, `genomics:vrsId`, `genomics:clinvarVariationId`, `clinical:loincCode`, `clinical:rxNormCode`, `clinical:icd10Code`, `clinical:snomedCode`, `genomics:hgncId`). Applier cost is O(index lookup). |
| **C3: No prefix manipulation** | Whitelisted prefixes only. |
| **C4: No IRI computation** | Inserted IRIs are literal patch text or the bound `?var`. No CONCAT / template substitution / string-to-IRI. |
| **C5: Bounded insert size** | At most 64 triples per match. |
| **C6: Required envelope metadata** | `humanSummary`, `advisoryClass`, `issuer`, `issuedAt` declared before any operation. |

### Classes

| Class | Anchor | Purpose |
|-------|--------|---------|
| `advisory:CascadeAdvisoryPatch` | subClassOf `prov:Entity` | The constrained-LDPatch envelope itself. |
| `advisory:AdvisoryClass` | OWL Class | Closed taxonomy (six individuals). |
| `advisory:Cadence` | OWL Class | Six-tier check cadence enum. |
| `advisory:TrustedIssuer` | OWL Class | Per-pod issuer trust record (D-Q3). |
| `advisory:TrustSourceEnum` | OWL Class | How an issuer was added to pod trust. |
| `advisory:AutoApplyPolicy` | OWL Class | Per-pod opt-in auto-apply policy. |
| `advisory:AutoApplyScope` | OWL Class | `(issuer, advisoryClass)` tuple for auto-apply. |

The `cascade:AdvisoryApplicationActivity` class — which records advisory-application events as a `prov:Activity` — is declared in core v3.1 and is referenced here, not redeclared.

### AdvisoryClass taxonomy (six closed-list individuals)

| Class | Default cadence | Use |
|-------|------------------|-----|
| `advisory:SafetyCritical` | `EveryAppOpen` | Drug recall, allergy alert, urgent variant reclassification. |
| `advisory:VariantReclassification` | `Monthly` | ACMG/AMP class change for a known variant. |
| `advisory:DrugInteraction` | `Monthly` | Newly identified drug-drug or drug-gene interaction. |
| `advisory:LabReferenceRangeUpdate` | `Quarterly` | Lab reference-range revision (e.g., new sex- or age-stratified ranges). |
| `advisory:SurveillanceGuidelineUpdate` | `Quarterly` to `Annually` | NCCN / USPSTF / specialty-society guideline change. |
| `advisory:CarrierFrequencyUpdate` | `Annually` | Updated population carrier frequency for a pathogenic variant. |

### Cadence enum

`advisory:EveryAppOpen`, `advisory:Daily`, `advisory:Weekly`, `advisory:Monthly`, `advisory:Quarterly`, `advisory:Annually`.

### Signing envelope (per D-Q4)

Detached JWS Ed25519 (RFC 7515 compact serialization). Properties: `signature`, `signatureIssuer` (iss), `signatureIssuedAt` (iat), `signatureExpiresAt` (exp), `signatureContentType` (cty, fixed to `application/x-cascade-advisory-patch`). W3C VC 2.0 wrapping is deferred to a later profile version.

### Trust model (per D-Q3)

The trust model is **per-pod**. The vocabulary declares `advisory:TrustedIssuer` and `advisory:TrustSourceEnum` (`RecommendedStarterList`, `UserAdded`, `ImportedFromRegistry`, `VerifiedViaDID`) so each pod can carry its own trust graph at `<pod>/trust/issuers.ttl`. The protocol does NOT define a centralized issuer registry. Issuer-trust allowlist enforcement is OUT of SHACL scope — that's a runtime concern.

### Application pipeline (informative)

1. **Parse as LDPatch.** Any LDPatch syntax error → reject.
2. **Profile envelope check.** Required `advisory:` metadata present and well-formed → continue, else reject.
3. **Constraint check.** C1–C5 enforced statically → continue, else reject.
4. **Signature verification.** Detached-JWS signature valid against trusted-issuer keys → continue, else queue for explicit user trust review.
5. **Selector evaluation.** `Bind` query against pod — zero matches: log inapplicable; one match: proceed; N matches: each treated as separate application.
6. **Application.** Inserts performed; `cascade:AdvisoryApplicationActivity` recorded with `prov:used` linking to the patch + matched node.

### Worked examples

- `example-brca2-reclassification.ldpatch` — VUS → Likely Pathogenic.
- `example-cpic-cyp2c19-warfarin.ldpatch` — CPIC PGx dosing guidance update tied to a CYP2C19 star allele.

Both files live at `cascadeprotocol.org/drafts/advisory-v1/`.

See [advisory/v1-draft/](/docs/advisory/v1-draft/) for the full vocabulary documentation and the spec changelog at `spec/ontologies/advisory/CHANGELOG.md`.

---

## Evidence Vocabulary v1.0-draft

**Namespace:** `https://ns.cascadeprotocol.org/evidence/v1#`
**Prefix:** `evidence:`
**Status:** Draft (v1-draft.0.2, 2026-07-01)
**Layer:** Layer 2 (cross-cutting)
**Imports / reuse:** Core Vocabulary v1 provenance primitives, W3C PROV-O
**Schema files:** [evidence.ttl](/docs/evidence/v1-draft/evidence.ttl) · [evidence.shapes.ttl](/docs/evidence/v1-draft/evidence.shapes.ttl)

> **Draft notice (per D-PATH).** The namespace URI is the stable major (`evidence/v1#`); the version-info string is `1.0-draft`. Pre-stable drafts are NOT registered in `spec/VOCAB_VERSIONS`; they land there only at v1.0 graduation.

Layer 2 cross-cutting vocabulary for grounding assertions in cited evidence. Generalizes the assertion, evidence, verdict pattern needed by Cascade Workbench (checking claims pulled from AI conversations against a patient's records and literature), the Cascade Appeal system, and PGx/genomics decision support. Reuses core provenance (`cascade:extractionModel`, `cascade:extractionConfidence`, `cascade:requiresUserReview`, `prov:wasDerivedFrom`) rather than redefining it. Uses `Assertion` (not "Claim") to avoid collision with `coverage:ClaimRecord`.

### Classes

| Class | Anchor | Purpose |
|-------|--------|---------|
| `evidence:Assertion` | subClassOf `prov:Entity` | A discrete, checkable statement evaluated against evidence. Carries the grading facets and zero-or-more evidence links. |
| `evidence:EvidenceLink` | OWL Class | Reified link from an Assertion to one piece of evidence (Pod record or Citation) with a stance. Modeled as a node so one Assertion can carry multiple, differently-directed links. |
| `evidence:Citation` | subClassOf `prov:Entity` | External bibliographic source (DOI/PMID), a first-class Pod resource once retrieved (recommended path `literature/`). |
| `evidence:GroundingActivity` | subClassOf `prov:Activity` | The model pass that graded an Assertion. Reuses `cascade:extractionModel` to record the model. |

### The facet model (verdict taxonomy v2, v1-draft.0.2)

The grounding outcome moved from a single flat `evidence:verdict` to orthogonal facets on the Assertion, each an object property over a closed enumeration, plus a numeric confidence. The facets are the canonical serialized form.

| Facet property | Range (closed enum) | Individuals |
|----------------|---------------------|-------------|
| `evidence:direction` | `DirectionValue` | `Supports`, `Contradicts`, `Mixed`, `None` (what the evidence in aggregate says). |
| `evidence:basis` | `BasisValue` | `Record`, `Literature`, `RecordAndLiterature`, `None` (where the evidence is). |
| `evidence:strength` | `StrengthValue` | `Strong`, `Moderate`, `Weak`. On basis `Record`, a deterministic function of the match (G-2), never model-emitted. |
| `evidence:settled` | `SettledValue` | `Settled`, `NeedsEvidence`. |
| `evidence:reason` | `NeedsEvidenceReasonValue` | `NoRecord`, `NeedsLiterature`, `NotCheckableByNature`. |
| `evidence:confidence` | `xsd:decimal` [0.0, 1.0] | Confidence in the grounding result, distinct from `evidence:groundingConfidence` (the activity's raw model confidence). |

Per-link stance stays on `evidence:StanceValue` (`Supports`, `Contradicts`, `Contextual`). Shared individuals: `Supports` / `Contradicts` are both `StanceValue` and `DirectionValue`; `None` is both `DirectionValue` and `BasisValue`; `NeedsLiterature` is both a deprecated `VerdictValue` and a `NeedsEvidenceReasonValue`. The property an individual appears on disambiguates its role.

### Deprecated: the flat verdict (removal at v1.0)

`evidence:verdict` and the `VerdictValue` individuals (`Supported`, `Contradicted`, `Unverifiable`, `NeedsLiterature`) are DEPRECATED in v1-draft.0.2, not removed. Draft-period data and fixtures already carry `evidence:verdict`, and the SHACL shapes keep a legacy branch so that data still validates during the one-release transition. Clients derive the flat value from the facets in code and MUST NOT serialize it going forward. Both are scheduled for removal at v1.0 graduation.

### Validation (SHACL)

`evidence.shapes.ttl` is SHACL Core only (`sh:or` / `sh:not` / `sh:in`), never SHACL-SPARQL, so `rdf-validate-shacl` and `cascade validate` enforce every constraint. Three node shapes: `AssertionShape`, `EvidenceLinkShape`, `CitationShape`.

- **Generalized grounding invariant.** A grounded result (`settled` `Settled`, `direction` one of `Supports`/`Contradicts`/`Mixed`, `basis` not `None`) of EITHER basis requires at least one `evidence:hasEvidenceLink`. Generalizes the v0.1 invariant, which only fired for the flat `Supported`/`Contradicted` verdicts.
- **Facet consistency.** A `NeedsEvidence` assertion must not carry a grounded direction; a grounded direction must carry a real basis (not `None`).
- **Graded-ness.** Every assertion carries the facet form (`settled`) or, for draft-period data, the deprecated flat `verdict`. Legacy branch removed at v1.0.

See [evidence/v1-draft/](/docs/evidence/v1-draft/) for the full vocabulary documentation and the spec changelog at `spec/ontologies/evidence/CHANGELOG.md`.

---

## Workbench Vocabulary v1.0-draft

**Namespace:** `https://ns.cascadeprotocol.org/workbench/v1#`
**Prefix:** `workbench:`
**Status:** Draft (v1-draft.0.5, 2026-07-15)
**Layer:** Layer 3 (application-specific)
**Imports / reuse:** Core Vocabulary v1, Evidence Vocabulary v1-draft, W3C Web Annotation (`oa:`), PROV-O, W3C RDF Calendar (`ical:`), SKOS
**Schema files:** [workbench.ttl](/docs/workbench/v1-draft/workbench.ttl) · [workbench.shapes.ttl](/docs/workbench/v1-draft/workbench.shapes.ttl)

> **Draft notice (per D-PATH).** The namespace URI is the stable major (`workbench/v1#`); the version-info string is `1.0-draft`. Pre-stable drafts are NOT registered in `spec/VOCAB_VERSIONS`; they land there only at v1.0 graduation.

Layer 3 vocabulary for the Cascade Workbench desktop investigation app. Holds the app-specific workspace objects, the append-only record-amendment overlays, the verification and filing axes, and the notes / research-flags / follow-ups substrate. The grounding model is deliberately NOT here (it is cross-cutting Layer 2 `evidence:`); phenotype capture extends `genomics:`. Per the Layer 3 graduation rule, any class here that proves useful to other apps should graduate to Layer 2.

### Workspace objects

| Class | Anchor | Purpose |
|-------|--------|---------|
| `workbench:Investigation` | OWL Class | A named, longitudinal inquiry over one patient's Pod: the top-level workspace object. |
| `workbench:ImportedConversation` | subClassOf `prov:Entity` | An AI-assistant conversation imported as a source. Extracted assertions are `evidence:Assertion` instances carrying `cascade:AIAsserted`. |
| `workbench:Hypothesis` | OWL Class | A candidate explanation with a lifecycle status (supports widening the differential and explicitly retiring/excluding). |
| `workbench:Pin` | OWL Class | A curated bookmark pointing at any resource with an optional note. |

Closed enumerations: Investigation status (`Active`, `Paused`, `Resolved`, `Archived`), Hypothesis status (`Proposed`, `Supported`, `Retired`, `Excluded`).

### Notes, research flags, and follow-ups: W3C Web Annotations (v1-draft.0.5)

Caregiver notes, "needs research" flags, and follow-ups are ONE artifact: an `oa:Annotation` over one or more graph nodes, distinguished by `oa:motivatedBy`. Nothing from `oa:` / `ical:` / `prov:` is redeclared; the vocabulary documents the usage profile and mints exactly one term.

| Artifact | `oa:motivatedBy` | Notes |
|----------|------------------|-------|
| Caregiver note | `oa:commenting` | Body required (`CommentingBodyShape`). |
| Research flag | `oa:questioning` | Target is typically an assertion / claim node. |
| Follow-up / open loop | `workbench:followUp` | Dual-typed `cal:Vtodo`; `ical:status` required, `ical:due` optional. |

- **Layer-1 reuse.** `oa:` carries the body (`oa:TextualBody`), multi-target (`oa:hasTarget`), motivation, and span selectors (`oa:TextQuoteSelector` / `oa:TextPositionSelector` via `oa:SpecificResource`, the same byte-verified-span idea the Claims Ledger uses). PROV-O carries required attribution (`prov:wasAttributedTo`, `prov:generatedAtTime`).
- **Follow-ups reuse W3C RDF Calendar.** `ical:due` (optional) and `ical:status` (required, the RFC 5545 VTODO enum `NEEDS-ACTION` / `IN-PROCESS` / `COMPLETED` / `CANCELLED`). `schema:dueDate` was considered and rejected: it does not exist (schema.org defines only `paymentDueDate`).
- **Exactly one minted term:** `workbench:followUp`, an `oa:Motivation` with `skos:broader oa:questioning`, per the Web Annotation custom-motivation extension rule.
- **Removed in v1-draft.0.5:** `workbench:InvestigationNote`, `workbench:hasNote`, `workbench:noteText` (draft removal; never emitted by shipping code). An investigation-scoped note is now an `oa:Annotation` targeting the `workbench:Investigation`.
- **Pod placement:** a top-level `notes/` container (`pod-structure.md` §5.2), separate from `annotations/` (record-amendment overlays are edit machinery, not user content).

### Append-only record-amendment overlays

Original records are immutable; every edit or delete is a new overlay resource written to `annotations/` and discovered at query time. Overlays carry `cascade:SelfReported` provenance, an optional `prov:wasAttributedTo`, and a `dct:created` timestamp.

| Class | Purpose |
|-------|---------|
| `workbench:Amendment` | Overrides one property value on an existing record without mutating the original. |
| `workbench:Annotation` | Augments a record with a note or extra attribute without overriding any value. |
| `workbench:Retraction` | Soft-delete / supersede (entered-in-error); the record's bytes are retained. |
| `workbench:Tombstone` | Content-free hard-erase audit marker (records the erasure event only: id, actor, timestamp, action), never a content hash. |

### Verification and filing axes

- **Verification axis (v1-draft.0.3).** `workbench:verificationStatus` + `VerificationStatusValue` (`Unverified`, `Confirmed`, `Refuted`), orthogonal to the SOURCE axis (`cascade:dataProvenance`). Mirrors FHIR AllergyIntolerance/Condition.verificationStatus. Open domain; patient self-entered data defaults to `Unverified`. Candidate to graduate to Layer 2 `clinical:`.
- **Filing / organization axis (v1-draft.0.4).** `workbench:userSourceLabel` (`xsd:string`), the user-chosen label for the SOURCE a record is filed under in the Workbench "filing cabinet". A filing preference attributed to the user, carried on a `workbench:Annotation` overlay (`annotationProperty` = `"workbench:userSourceLabel"`, `annotationValue` = the label) bearing `cascade:SelfReported` provenance. It MUST NOT overwrite the objective imported origin `clinical:sourceEHR`, which is preserved and shown alongside; the effective grouping source prefers this label, else `clinical:sourceEHR`, else the import-batch tag. Open domain, so it can file any record. Reuses already-shaped predicates, so no new SHACL shape.

### Validation (SHACL)

`workbench.shapes.ttl` is SHACL Core only. Alongside `InvestigationShape`, `ImportedConversationShape`, the four overlay shapes, and `VerificationStatusShape`, the notes substrate adds three shapes targeting every `oa:Annotation` in the Pod: `WebAnnotationShape` (at least one target, at least one motivation, required attribution plus an `xsd:dateTime` timestamp), `CommentingBodyShape` (commenting requires a body), `FollowUpShape` (followUp requires `ical:status` in the VTODO enum). All three violation classes were verified against `cascade validate` with positive and negative fixtures.

See [workbench/v1-draft/](/docs/workbench/v1-draft/) for the full vocabulary documentation and the spec changelog at `spec/ontologies/workbench/CHANGELOG.md`.

---

## Settings Storage Convention (Phase B Target)

Application configuration is distinct from health data and should be stored separately. This section documents the target storage architecture for Solid integration.

### Current State

CheckInSettings and other app configuration data are serialized inline within the main checkup TTL file. This pattern works correctly and is preserved for now. The `cascade:subConcern "app-config"` annotation identifies these classes as configuration, not health data.

### Target Storage Hierarchy

When Solid integration is implemented, settings will be stored at `/settings/`:

```
/settings/
    shared/
        preferences.ttl        # Cross-app: language, timezone, notification prefs
    checkup/
        config.ttl             # CheckInSettings, app-specific prefs
    pots/
        config.ttl             # POTS Check app-specific prefs
```

### Namespace Pattern

No new `settings:` vocabulary is needed:
- **Shared preferences** use `cascade:` properties (e.g., `cascade:notificationsEnabled`, `cascade:preferredUnits`)
- **App-specific settings** use their existing vocabulary (`checkup:CheckInSettings`, `pots:` config)
- Separation is by **file path**, not by **namespace**

**Shared preferences example** (target: `/settings/shared/preferences.ttl`):
```turtle
@prefix cascade: <https://ns.cascadeprotocol.org/core/v1#> .
@prefix dct: <http://purl.org/dc/terms/> .

<#preferences>
    dct:language "en-US" ;
    cascade:notificationsEnabled "true"^^xsd:boolean ;
    cascade:preferredUnits "imperial" .
```

**App-specific config example** (target: `/settings/checkup/config.ttl`):
```turtle
@prefix checkup: <https://ns.cascadeprotocol.org/checkup/v1#> .

<#checkInSettings>
    a checkup:CheckInSettings ;
    checkup:checkInEnabled "true"^^xsd:boolean ;
    checkup:notificationHour "9"^^xsd:integer ;
    checkup:notificationMinute "0"^^xsd:integer ;
    checkup:enabledDays "monday,tuesday,wednesday,thursday,friday" .
```

---

## Pod Storage Conventions

Recommended storage paths for all Cascade data, aligned with Solid container conventions. These are default paths — Solid Type Indexes can override them for discovery.

### Cascade Pod Layout

```
/ (root storage)
|-- profile/
|   |-- card.ttl                    # General identity (foaf:Agent, vcard:)
|   |-- health.ttl                  # cascade:PatientProfile (health extensions)
|-- settings/
|   |-- shared/
|   |   |-- preferences.ttl         # Cross-app settings (cascade: properties)
|   |-- checkup/
|   |   |-- config.ttl              # Checkup app settings
|   |-- pots/
|       |-- config.ttl              # POTS Check app settings
|-- wellness/                        # health: vocabulary data
|   |-- vitals/
|   |   |-- hrv/                    # HRV statistics
|   |   |-- bp/                     # Blood pressure statistics
|   |   |-- vo2max/                 # VO2 Max statistics
|   |-- activity/                   # Activity snapshots
|   |-- sleep/                      # Sleep snapshots
|   |-- self-reports/               # health:SelfReport instances
|-- clinical/                        # clinical: vocabulary data
|   |-- medications/
|   |-- conditions/
|   |-- lab-results/
|   |-- immunizations/
|   |-- procedures/
|-- coverage/                        # coverage: vocabulary data
|   |-- plans/
|   |-- deductibles/
|-- checkup/                         # checkup: vocabulary data (L3 only)
|   |-- intake-forms/
|   |-- visit-prep/
|   |-- daily-checkins/
|   |-- summaries/
|-- pots/                            # pots: vocabulary data
|   |-- results/
|   |-- measurements/
```

### Per-Vocabulary Storage Paths

| Vocabulary | Container | Key Classes |
|-----------|-----------|-------------|
| `cascade:` (core) | `/profile/`, `/settings/shared/` | PatientProfile, preferences |
| `health:` | `/wellness/` | HRVStatistics, BPStatistics, VO2MaxStatistics, SelfReport |
| `clinical:` | `/clinical/` | Medication, Condition, LabResult, Immunization, Procedure |
| `coverage:` | `/coverage/` | InsurancePlan |
| `checkup:` | `/checkup/` | IntakeFormData, DailyCheckIn, VisitPrepSummary |
| `pots:` | `/pots/` | POTSCheckResult |

### Type Index Registrations (Documentation Only)

Solid uses Type Indexes for data discovery. The following registrations are recommended for Cascade data (implementation deferred to Phase B):

```turtle
# Private Type Index (documentation only — not implemented in SDK yet)
@prefix solid: <http://www.w3.org/ns/solid/terms#> .
@prefix cascade: <https://ns.cascadeprotocol.org/core/v1#> .
@prefix health: <https://ns.cascadeprotocol.org/health/v1#> .
@prefix clinical: <https://ns.cascadeprotocol.org/clinical/v1#> .
@prefix checkup: <https://ns.cascadeprotocol.org/checkup/v1#> .
@prefix pots: <https://ns.cascadeprotocol.org/pots/v1#> .
@prefix coverage: <https://ns.cascadeprotocol.org/coverage/v1#> .

<> a solid:TypeIndex ; a solid:UnlistedDocument .

<#patient-profile> a solid:TypeRegistration ;
    solid:forClass cascade:PatientProfile ;
    solid:instance </profile/health.ttl> .

<#self-reports> a solid:TypeRegistration ;
    solid:forClass health:SelfReport ;
    solid:instanceContainer </wellness/self-reports/> .

<#insurance> a solid:TypeRegistration ;
    solid:forClass coverage:InsurancePlan ;
    solid:instanceContainer </coverage/plans/> .

<#pots-results> a solid:TypeRegistration ;
    solid:forClass pots:POTSCheckResult ;
    solid:instanceContainer </pots/results/> .

<#daily-checkins> a solid:TypeRegistration ;
    solid:forClass checkup:DailyCheckIn ;
    solid:instanceContainer </checkup/daily-checkins/> .
```

---

## Namespace Reference

### Cascade Protocol Namespaces

| Prefix | Namespace URI | Description |
|--------|---------------|-------------|
| `cascade:` | `https://ns.cascadeprotocol.org/core/v1#` | Core vocabulary |
| `clinical:` | `https://ns.cascadeprotocol.org/clinical/v1#` | Clinical documents |
| `health:` | `https://ns.cascadeprotocol.org/health/v1#` | Wellness & device data |
| `pots:` | `https://ns.cascadeprotocol.org/pots/v1#` | POTS screening |
| `checkup:` | `https://ns.cascadeprotocol.org/checkup/v1#` | Patient intake |
| `coverage:` | `https://ns.cascadeprotocol.org/coverage/v1#` | Insurance/benefits |
| `diabetes:` | `https://ns.cascadeprotocol.org/diabetes/v1#` | Diabetes management (draft) |
| `genomics:` | `https://ns.cascadeprotocol.org/genomics/v1#` | Variants, interpretations, pedigrees, sequencing-run provenance (draft) |
| `advisory:` | `https://ns.cascadeprotocol.org/advisory/v1#` | Cascade Advisory Patch (CAP) profile (draft) |

### External Standard Namespaces

| Prefix | Namespace URI | Description |
|--------|---------------|-------------|
| `owl:` | `http://www.w3.org/2002/07/owl#` | OWL Web Ontology Language |
| `rdf:` | `http://www.w3.org/1999/02/22-rdf-syntax-ns#` | RDF syntax |
| `rdfs:` | `http://www.w3.org/2000/01/rdf-schema#` | RDF Schema |
| `xsd:` | `http://www.w3.org/2001/XMLSchema#` | XML Schema datatypes |
| `sh:` | `http://www.w3.org/ns/shacl#` | SHACL shapes |
| `prov:` | `http://www.w3.org/ns/prov#` | W3C Provenance |
| `dct:` | `http://purl.org/dc/terms/` | Dublin Core terms |
| `fhir:` | `http://hl7.org/fhir/` | HL7 FHIR |
| `sct:` | `http://snomed.info/sct/` | SNOMED CT |
| `loinc:` | `http://loinc.org/rdf#` | LOINC codes |
| `ucum:` | `http://unitsofmeasure.org/` | Units of measure |

---

## Design Patterns

This section documents recurring patterns used when modeling data with the Cascade Protocol vocabularies. Following these patterns ensures cross-app interoperability and consistent RDF output.

### 1. SelfReport Extension Pattern

`health:SelfReport` is a base class for all patient-reported daily check-ins and self-assessments. Apps extend it with domain-specific subclasses.

**Base class (in `health:` vocabulary):**

| Property | Type | Description |
|----------|------|-------------|
| `health:reportDate` | xsd:dateTime | When the self-report was recorded |
| `health:reportType` | xsd:string | Category: `medication_adherence`, `symptom_tracking`, `mood`, `sleep`, etc. |
| `health:completionStatus` | xsd:string | `complete`, `partial`, or `skipped` |
| `health:reportContext` | xsd:string | What tracking plan this report relates to |
| `health:reportNotes` | xsd:string | Optional free-text notes from the patient |

**Extending for a domain (in app vocabulary):**

```turtle
# Define a domain-specific subclass
checkup:DailyCheckIn a owl:Class ;
    rdfs:subClassOf health:SelfReport ;
    rdfs:label "Daily Check-In" ;
    rdfs:comment "Medication adherence check-in. Extends health:SelfReport." .

# Domain-specific properties (checkup: namespace)
checkup:checkInResponse a owl:DatatypeProperty ;
    rdfs:domain checkup:DailyCheckIn ;
    rdfs:range xsd:string .
```

**Serialized output (mixed namespace pattern):**

```turtle
<#checkin-2026-02-18> a checkup:DailyCheckIn ;
    # Base properties (health: namespace -- any app understands these)
    health:reportDate "2026-02-18T09:00:00Z"^^xsd:dateTime ;
    health:reportType "medication_adherence" ;
    health:completionStatus "complete" ;
    health:reportNotes "Felt good today" ;
    # Domain-specific properties (checkup: namespace)
    checkup:checkInResponse "took_all" .
```

**Cross-app interoperability:** Any app understanding `health:SelfReport` can read the base fields (date, type, status) without understanding the domain-specific data. A medication management app can query all self-reports of type `medication_adherence` across multiple data sources.

### 2. Serializer Delegation Pattern

Complex domain serializers delegate to shared SDK serializers for cross-cutting data types, ensuring consistent RDF output regardless of which app writes the data.

**Problem:** The same data type (e.g., `cascade:PatientProfile`) might be serialized by both the SDK's `PatientProfileSerializer` and the app's `CheckupSerializer`. Without delegation, the two may emit different property names or structures.

**Solution:** Extract shared serialization helpers in the SDK and call them from domain serializers.

**Example: PatientProfile delegation**

```swift
// SDK: PatientProfileSerializer.swift
public static func serializeProfileProperties(
    _ profile: PatientProfile,
    includeSchemaVersion: Bool = false,
    includeProfileId: Bool = false
) -> String {
    // Canonical patient profile serialization
    var ttl = ""
    if let dob = profile.dateOfBirth {
        ttl += "    cascade:dateOfBirth \"\(dob)\"^^xsd:date ;\n"
    }
    // ... all other profile properties
    return ttl
}
```

```swift
// Checkup: CheckupSerializer.swift -- delegates to SDK
private func patientProfile(_ profile: PatientProfile) -> String {
    var ttl = "<#patient-profile> a cascade:PatientProfile ;\n"
    ttl += PatientProfileSerializer.serializeProfileProperties(profile)
    ttl += "    .\n"
    return ttl
}
```

**Benefits:**
- Single canonical representation for shared data types
- Bug fixes to shared data types automatically apply everywhere
- Easier testing (test the helper once, trust call sites)

### 3. Mixed Namespace Pattern

A single class or resource can use properties from multiple vocabularies. This is standard RDF practice and is how Cascade enables cross-vocabulary reuse.

**When to use:**
- An app-level (L3) class naturally uses standardized properties from L2 vocabularies
- A summary class aggregates data from multiple domain vocabularies
- Established standard vocabularies (FHIR, SNOMED, foaf, vcard) have the right term

**Example: checkup:InsuranceInfo using coverage: properties**

```turtle
# checkup:InsuranceInfo (L3 -- app-specific container)
# Uses coverage: for standardized insurance fields, checkup: for app-layer enrichment

<#insurance-primary> a checkup:InsuranceInfo ;
    # Standardized insurance properties (coverage: namespace)
    coverage:providerName "BlueCross BlueShield" ;
    coverage:memberId "XYZ123" ;
    coverage:coverageType "primary" ;
    coverage:effectiveStart "2026-01-01"^^xsd:date ;
    # App-specific enrichment (checkup: namespace -- PCP is not insurance data)
    checkup:primaryCareProvider "Dr. Smith" ;
    checkup:pcpPhone "555-1234" .
```

**Rules:**
1. Use the most specific applicable vocabulary (`coverage:` over `checkup:` for insurance properties)
2. App vocabulary (`checkup:`, `pots:`) is for app-layer enrichment only, not re-definitions
3. Never redefine a standard property in an app namespace (use the standard one directly)
4. Document which properties come from which namespace in the class definition comment

### 4. Per-Type Export Pattern (Pod Storage)

For Solid Pod compatibility, each data type should be serializable independently as a standalone TTL document that can be stored at its recommended Pod path.

**Recommended Pod layout:**

```
/ (root)
|-- profile/
|   |-- card.ttl           # foaf:Agent identity (IdentityProfileSerializer)
|   |-- health.ttl         # cascade:PatientProfile (PatientProfileSerializer)
|-- wellness/
|   |-- vitals/...         # health: HRV, BP, VO2Max statistics
|   |-- activity/...       # health: ActivitySnapshot instances
|   |-- sleep/...          # health: SleepSnapshot instances
|   |-- self-reports/...   # health:SelfReport instances
|-- clinical/
|   |-- medications/...    # clinical: Medication instances
|   |-- conditions/...     # clinical: Condition instances
|-- coverage/
|   |-- plans/...          # coverage: InsurancePlan instances
|-- checkup/
|   |-- intake-forms/...   # checkup: visit preparation summaries
|   |-- daily-checkins/... # checkup: DailyCheckIn instances
```

**Design principle:** Each resource should be self-contained -- it should include all the prefixes it needs and not depend on being embedded in a larger document.

> **Note:** The SDK currently writes a single combined TTL file per storage namespace. Splitting into per-type files is a Phase B feature requiring Solid Pod infrastructure. This pattern documents the target architecture.

---

## Version History

### Genomics Vocabulary (Draft)
- **v1.0-draft.0.1 (2026-05-05)**: Initial production draft authored in `spec/` (TASK-0.1 / TASK-0.2 of the Genomics & Advisory v0.1 workstream). 220 declared `genomics:` terms across 14 classes and ~30 net-new properties. Variant identity in four parallel languages (HGVS / ClinVar / VRS-CAid / HGNC + SO). Variant ≠ Interpretation pattern with `prov:wasRevisionOf` reclassification chain. `Pedigree` + `PedigreeMember` with HPO + MONDO + per-variant carrier status and HL7 v3 RoleCode relationship roles. Multi-variant units: `Haplotype`, `Diplotype`, `CopyNumberVariant`. ClinVar-aligned `SubmitterAssertion` + 7-value `ReviewStatus` taxonomy. `GeneticTest` + `GeneticTestOrder`. Sequencing-run provenance: `SequencingRun` (PROV-O Activity), `RawFile` pointer-and-hash entity (Cascade does NOT ingest BAM/CRAM bytes), htsget endpoint, lab-cert enum. Data-quality tier model: `ClinicalGrade` / `ResearchGrade` / `ConsumerGrade` / `UnknownQuality`. Causality enum (`Causative` / `Contributory` / `UncertainCausality` / `Rejected`) distinct from ACMG classification. SHACL: 12 `sh:NodeShape` declarations; D-Q5 multi-condition cardinality (`condition` 1..1, `variantInterpreted` 1..1); D-QUALITY-TIER `sh:xone` safety constraint requiring Pathogenic/LikelyPathogenic interpretations to either reference a `ClinicalGrade` Variant OR carry `requiresConfirmation true`. Per D-PATH, NOT registered in `spec/VOCAB_VERSIONS` until v1.0 graduation.

### Advisory Vocabulary (Draft)
- **v1.0-draft.0.1 (2026-05-05)**: Initial draft authored in `spec/` (TASK-0.3 / TASK-0.4 of the Genomics & Advisory v0.1 workstream). 55 declared `advisory:` terms (8 classes, 16 named individuals across 3 enums, 31 properties). Defines the Cascade Advisory Patch (CAP) envelope as a strict subset of W3C LDPatch (Recommendation, 2015) — author-readable, statically auditable, bounded-execution. Six AdvisoryClass categories (`SafetyCritical`, `VariantReclassification`, `DrugInteraction`, `LabReferenceRangeUpdate`, `SurveillanceGuidelineUpdate`, `CarrierFrequencyUpdate`). Six-tier Cadence enum. Per-pod `TrustedIssuer` + `TrustSourceEnum` (per D-Q3 — no centralized registry). Detached JWS Ed25519 signing envelope per D-Q4 (RFC 7515 compact serialization, content-type fixed to `application/x-cascade-advisory-patch`). `AutoApplyPolicy` with per-(`issuer`, `advisoryClass`) `AutoApplyScope` tuples. SHACL: 4 `sh:NodeShape` declarations enforcing required envelope fields, closed enumerations, and `AutoApplyPolicy` structure. `cascade:AdvisoryApplicationActivity` (declared in core v3.1) is referenced, not redeclared. Per D-PATH, NOT registered in `spec/VOCAB_VERSIONS` until v1.0 graduation.

### Clinical Vocabulary
- **v1.9 (2026-06-17)**: Added `cascade:AIExtracted` to every `cascade:dataProvenance` `sh:in` enumeration in `clinical.shapes.ttl`. `cascade:AIExtracted` (a `ClinicalGenerated` subclass, declared in core v3.3) is now a permitted provenance value on all clinical record shapes, so records produced by an AI document-extraction pipeline (e.g. the Workbench) validate without error. Shapes-only change; no new clinical classes or properties.
- **v1.8 (2026-03-28)**: Added `clinical:SocialHistoryRecord` class for EHR-extracted social history observations (C-CDA Social History section, LOINC 29762-2). Added 5 properties: `socialHistoryCategory` (10 value set), `packsPerYear`, `substanceType`, `frequencyDescription`, `socialHistoryConsent` (links to `cascade:SocialHistoryConsent`). Two-class social history design: `health:SocialHistoryRecord` (consumer-reported) vs `clinical:SocialHistoryRecord` (EHR-extracted, 42 CFR Part 2). Part of Phase P5.2.
- **v1.7 (2026-03-12)**: Added FHIR converter classes: `clinical:Encounter` (6 properties: encounterClass, encounterStatus, encounterType, encounterStart, encounterEnd, facilityName), `clinical:MedicationAdministration` (4 properties: administeredDate, administeredDose, administeredRoute, administrationStatus), `clinical:ImplantedDevice` (5 properties: deviceType, implantDate, deviceManufacturer, udiCarrier, deviceStatus), `clinical:ImagingStudy` (5 properties: imagingModality, studyDescription, numberOfSeries, studyDate, dicomStudyUid). Added 3 `clinical:LaboratoryReport` properties: `hasLabResult` (ObjectProperty → clinical:LabResult), `panelName`, `reportCategory`. Added permissive SHACL shapes for all new classes in `clinical.shapes.ttl` (OQ-4 decision). Part of Lossless FHIR ↔ Cascade Conversion Plan Phase A.
- **v1.6 (2026-02-22)**: Added `clinical:linkedConditionIds` DatatypeProperty on `clinical:Condition` for linking related conditions via space-separated UUIDs. Aligned typed code properties on Checkup summary classes to use `clinical:` namespace predicates: `clinical:loincCode` on `LabResult` (replaces legacy `checkup:loincCode`), `clinical:cvxCode` on `ImmunizationRecord` (preferred over `clinical:vaccineCode`), `clinical:icd10Code` on `FamilyHistoryEntry` and `ConditionSummary` (replaces `checkup:familyConditionCode` and `checkup:icd10Code`), `clinical:snomedCode` on `AllergySummary`/`ScreeningStatus`/`FamilyHistoryEntry`/`ConditionSummary`, `clinical:rxNormCode` on `AllergySummary`. Annotated `clinical:vaccineCode` as legacy. Part of Health Map v3 Pre-Phase Track A (Task A2).
- **v1.5 (2026-02-10)**: Added `CoverageRecord` class (11 properties) for insurance coverage/plan records imported from EHR via Apple HealthKit (FHIR Coverage resource). Added 3 new properties to existing `Procedure` class (procedureStatus, procedureCategory, procedureSnomedCode — prefixed to avoid domain collisions). Added `clinical:administrationRoute` property (previously missing from v1.3 medication enrichment set). Existing Procedure properties preserved (procedureName, performedDate, bodySite, performer, location, outcome, cptCode).
- **v1.4 (2026-01-28)**: Added `LabTestSeries` class for longitudinal lab tracking with trend inference. Enhanced `LabResult` with metadata properties (`orderingProvider`, `performingLab`, `observationStatus`, `referenceRangeLow/High`).
- **v1.3 (2026-01-26)**: Added 14 medication enrichment properties from FHIR extraction pipeline (`prescriber`, `indication`, `courseOfTherapyType`, `medicationForm`, `activeIngredient`, `provenanceClass`, `clinicalIntent`, dispensing properties).
- **v1.2 (2026-01-15)**: Added MedicationUseEpisode and Supplement classes
- **v1.1 (2026-01-01)**: Added 7 structured clinical record classes
- **v1.0 (2025-12-26)**: Initial release with document-centric vocabulary

### Health Vocabulary
- **v2.3 (2026-02-28)**: BUG-006 Pattern A standardization. Added 6 flat `health:` DatatypeProperties for `VitalSignReading` blank nodes emitted by `HealthProfileSerializer`: `health:value`, `health:date`, `health:sdnn`, `health:systolic`, `health:diastolic`, `health:walkingSteadinessLevel` (ObjectProperty). Added named individuals `health:OK`, `health:Low`, `health:VeryLow`, `health:Unknown` for walking steadiness values. Added `health:WalkingSteadinessUnknown` to legacy individual set. These replace the `fhir:Observation` nesting pattern (Pattern B) for wellness vital sign serialization.
- **v2.2 (2026-02-17)**: Added 2 statistics container linking ObjectProperties: `health:hasHRVStatistics` (links wellness profile to HRV statistical summary), `health:hasBPStatistics` (links wellness profile to BP statistical summary). Previously dark vocabulary emitted by CheckupSerializer. Part of Schema Refactoring Plan Phase 3 (PF1-R).
- **v2.1 (2026-02-17)**: Added `health:SelfReport` base class and 5 base properties (`reportDate`, `reportType`, `completionStatus`, `reportContext`, `reportNotes`) for patient-reported daily check-ins. Supports the SelfReportable protocol pattern where apps extend this class with domain-specific response data. Part of Schema Refactoring Plan Phase 3 (WS7).
- **v2.0 (2026-02-18)**: Schema Refactoring WS3b — Migrated HealthProfileSerializer from `cascade:` to `health:` namespace. Added 8 history container ObjectProperties (`restingHeartRateHistory`, `walkingHeartRateHistory`, `hrvHistory`, `bloodPressureHistory`, `vo2MaxHistory`, `bodyMassHistory`, `dailyActivityHistory`, `dailySleepHistory`) and 7 supporting classes (`HealthProfile`, `DailyVitalReading`, `HRVReading`, `BloodPressureReading`, `VitalSignReading`, `DailyActivitySnapshot`, `DailySleepSnapshot`). These capture time-series data for 90-day, 30-day, and 7-day lookback windows.
- **v1.9 (2026-02-17)**: Added `health:bloodType` property for ABO blood group and Rh factor (sct:365637002, loinc:882-1). Values: aPositive, aNegative, bPositive, bNegative, abPositive, abNegative, oPositive, oNegative. Sourced from HealthKit or manual entry. Previously dark vocabulary emitted in QR payload. Part of Schema Refactoring Plan Phase 2.5 (PF4).
- **v1.8 (2026-02-10)**: Added 6 body measurement and metabolic properties: `health:bodyMass` (sct:27113001, loinc:29463-7), `health:bodyHeight` (sct:50373000, loinc:8302-2), `health:bodyMassIndex` (sct:60621009, loinc:39156-5), `health:bodyTemperature` (sct:386725007, loinc:8310-5), `health:oxygenSaturation` (sct:431314004, loinc:2708-6), `health:bloodGlucose` (sct:33747003, loinc:2339-0). Added `health:BPStatistics` class with 8 properties for blood pressure statistical summaries (bpSampleCount, bpMean/Min/Max Systolic/Diastolic, bpCategory). Added shared temporal properties (periodStart, periodEnd). Completed `health:HRVStatistics` property definitions (10 properties: hrvSampleCount, hrvDaysCovered, hrvMean, hrvMedian, hrvStdDev, hrvMin, hrvMax, hrvPercentile25, hrvPercentile75, hrvTrendDirection).
- **v1.7 (2026-02-03)**: Added `health:VO2MaxStatistics` and `health:HRVStatistics` classes for statistical trend analysis. Added 9 properties for VO2 Max statistics (vo2Mean, vo2Min, vo2MaxValue, vo2SampleCount, vo2DaysCovered, vo2TrendDirection, vo2PercentageChange, fitnessClassification, isSparseData). Supports dual-path UI pattern with rich statistics preferred over single values.
- **v1.6 (2026-02-02)**: Added `health:trendPolarity` annotation property to all measurable wellness metrics. Defines whether an increase is favorable/unfavorable/neutral.
- **v1.5 (2026-02-01)**: Added `health:MetricTrend` class for time-bounded wellness trends with direction, magnitude, confidence, and baseline/current values. Follows pattern from `clinical:LabTestSeries` but for continuous device observations.
- **v1.4 (2026-01-29)**: Initial release with SNOMED CT and LOINC mappings for all wellness metrics. 2 composite classes, 14+ properties, 4 annotation properties.

### Core Vocabulary
- **v3.3 (2026-06-16)**: Cascade Workbench support. Added `cascade:AIAsserted` provenance leaf (subclass of `cascade:ConsumerGenerated`) for ungrounded content surfaced by a general-purpose AI assistant — distinct from `cascade:AIExtracted` (clinically grounded) and `cascade:EHRVerified`; must be evidence-checked before reliance. Added `cascade:ProxyAgent` (subclass of `prov:Agent`) for a person operating a patient's Pod on the patient's behalf (parent/guardian/caregiver), closing the caregiver-proxy gap, with 6 properties: `actsForPatient` (subproperty of `prov:actedOnBehalfOf`), `proxyWebID`, `proxyRelationship`, `proxyScope`, `proxyGrantedAt`, `proxyRevokedAt`.
- **v3.2 (2026-05-06)**: Forward-reference closure for the advisory applier. Added `cascade:appliedTriplesCount` (DatatypeProperty, range `xsd:nonNegativeInteger`, domain `cascade:AdvisoryApplicationActivity`) recording the number of triples inserted into the Pod by a single advisory application — auditable post-hoc verification of CAP profile constraint C5 (≤ 64 inserted triples per match).
- **v3.1 (2026-05-05)**: Genomics & Advisory provenance. Added `cascade:AdvisoryApplicationActivity` (`prov:Activity` subclass) for recording application of a Cascade Advisory Patch to a Pod (advisory and matched record linked via `prov:used`). Added `cascade:AIGenerationActivity` (`prov:Activity` subclass), sibling of `cascade:AIExtractionActivity`, for LLM-generated narrative chunks (e.g. `checkup:VariantNarrative`); reuses `extractionModel`/`extractionConfidence`/`sourceNarrativeSection`/`requiresUserReview` and adds `cascade:promptVersion` and `cascade:generationTemperature`. Added `cascade:trigger` ObjectProperty (domain `AIGenerationActivity`, range `cascade:GenerationTrigger`) with three named individuals: `cascade:InitialGeneration`, `cascade:RegenerationAfterReclassification`, `cascade:AudienceRetargeting`.
- **v3.0 (2026-03-28)**: Added `cascade:HealthRecord` abstract superclass for all health data records. Added `cascade:AIExtractionActivity` (PROV-O Activity for AI/NLP extraction passes, 4 properties: `extractionConfidence`, `extractionModel`, `sourceNarrativeSection`, `requiresUserReview`). Added `cascade:AIDiscardedExtraction` (audit record for discarded extraction candidates, 1 property: `discardReason`). Added `cascade:SocialHistoryConsent` (consent record for 42 CFR Part 2 sensitive data, 3 properties: `consentScope`, `consentGrantedAt`, `consentRevokedAt`). Part of Phase P5.2.
- **v2.8 (2026-03-12)**: Added FHIR conversion support: `cascade:LayerPromotionStatusValue` class, `cascade:FullyMapped` and `cascade:PendingLayerTwoPromotion` named individuals, `cascade:layerPromotionStatus` ObjectProperty, `cascade:fhirJson` DatatypeProperty (inline FHIR JSON for passthrough records), `cascade:fhirResourceType` DatatypeProperty, `cascade:sourceRecordDate` DatatypeProperty. Part of Lossless FHIR ↔ Cascade Conversion Plan Phase A (OQ-8 rename from conversionStatus to layerPromotionStatus).
- **v2.7 (2026-03-12)**: Removed `cascade:conflictDescription` (deprecated since v2.5). `cascade:conflictDetail` blank nodes now carry an `rdfs:comment` with a human-readable conflict summary, replacing the separate prose property.
- **v2.6 (2026-03-11)**: Within-source deduplication vocabulary (Phase 6 of reconciliation pipeline). Added `cascade:WithinSourceDuplicate` named individual for `cascade:ReconciliationStatus`. Represents encounter-instance duplicate records suppressed during Pass 1 within-source deduplication before cross-system matching.
- **v2.5 (2026-03-11)**: Structured conflict representation (Phase 5 of reconciliation pipeline). Added `cascade:ConflictDetail` class and 4 supporting properties: `cascade:conflictDetail` (ObjectProperty, links reconciled record to ConflictDetail blank node), `cascade:conflictFor` (ObjectProperty, the conflicting predicate URI), `cascade:systemValue` (ObjectProperty, per-system value blank node), `cascade:forSystem` (DatatypeProperty, system name string). Deprecated `cascade:conflictDescription` (informational prose, replaced by structured blank node).
- **v2.4 (2026-03-11)**: Added 7 reconciliation properties for multi-system data normalization: `cascade:sourceSystem` (originating EHR/system name, added by `cascade convert --source-system`), `cascade:reconciliationStatus` (canonical | merged | conflict-resolved | unresolved-conflict), `cascade:mergedFrom` (ObjectProperty, links to source record URIs, subproperty of `prov:wasDerivedFrom`), `cascade:mergedSources` (string list of contributing systems), `cascade:conflictResolution` (trust_priority | merge_values | flag_unresolved), `cascade:conflictField` (predicate where conflict was detected), `cascade:conflictValues` (human-readable conflict description). These properties are emitted by `cascade reconcile` and support the `cascade-reconcile-experiment` pipeline.
- **v2.3 (2026-02-20)**: Added 2 provenance detail properties: `cascade:sourceOrganization` (organization that provided a record, populated from FHIR `meta.source`) and `cascade:sourceDeviceName` (device/app that recorded a measurement, populated from HealthKit `HKSource`). Used across all 11 CheckupShared record models for Health Map provenance display. Part of Health Map v3 Pre-Phase Track A (Task A4).
- **v2.2 (2026-02-18)**: FHIR-aligned Address expansion and PatientProfile completeness (Phase 3.5). ONT1: Added 9 FHIR Address-aligned properties (`addressUse`, `addressType`, `addressText`, `addressLine`, `addressCity`, `addressDistrict`, `addressState`, `addressPostalCode`, `addressCountry`). Existing simple properties retained as aliases. ONT2: Added `EmergencyContact` class with 3 properties (`contactName`, `contactRelationship`, `contactPhone`). Added PatientProfile properties: `computedAge`, `profileId`, `pharmacyAddress`, `preferredLanguage`. Added blank-node linking object properties: `emergencyContact`, `advanceDirectives`, `preferredPharmacy`, `address`.
- **v2.1 (2026-02-17)**: Added `cascade:addedInSchemaVersion` annotation property and `cascade:cascadeUri` URI property (range: `xsd:anyURI`). Previously dark vocabulary emitted by CheckupSerializer. Part of Schema Refactoring Plan Phase 3 (PF1-R).
- **v2.0 (2026-02-17)**: Added `cascade:PatientProfile` class with 12 properties for health-specific patient demographics (Solid WebID Profile extension). Added `cascade:Address` class (5 properties) for structured postal addresses with FHIR Address semantics. Added `cascade:PharmacyInfo` class (2 properties + reused `hasAddress`) for preferred pharmacy. Added `cascade:AdvanceDirectives` class (4 properties) for advance directive declarations. Promotes patient identity from `checkup:` (Layer 3) to `cascade:` (cross-cutting) as part of Schema Refactoring Plan WS6. Emergency contact properties (`emergencyContactName`, `emergencyContactRelationship`, `emergencyContactPhone`) are new additions not previously in `checkup:`.
- **v1.2 (2026-02-10)**: Promoted `ConsumerGenerated` and `ClinicalGenerated` from OWL individuals to subclasses of `DataProvenance`. Added 6 leaf subclasses matching SDK `DataProvenance.swift` enum: `DeviceGenerated`, `SelfReported`, `ConsumerWellness` (under ConsumerGenerated); `EHRVerified`, `ScannedDocument`, `AIExtracted` (under ClinicalGenerated). Backward-compatible with existing data.
- **v1.1 (2026-02-01)**: Added `cascade:DataSource` class for device/app/system identity with reliability tiers. Subclass of `prov:Agent`.
- **v1.0 (2025-12-26)**: Initial release with provenance classes.

### Checkup Vocabulary
- **v3.2 (2026-02-26)**: Added `checkup:supplyEndDate` DatatypeProperty on `MedicationSummary`. Computed as `startDate + supplyDurationDays`, this field allows consumers to distinguish administrative EHR order expiry (`checkup:medicationEndDate`) from actual supply exhaustion. Fixes BUG-002 where all medications appeared inactive because the signal extraction script used `medicationEndDate` as the sole activity signal. 28 active classes, 1 property added.
- **v3.1 (2026-02-20)**: Added `checkup:VisitPrepTray` class (12 properties) for per-appointment visit preparation containers with typed payload wrapper (`VisitItemPayload` enum preserving `VisitIssue`, `DiscussionTopic`, `SuggestedQuestion` type richness). Added `checkup:hasTrayItem` ObjectProperty. Added `checkup:hasVisitPrep` and `checkup:activeVisitPrepId` aggregate links on `IntakeFormData`. 28 active classes. Part of Health Map v3 Pre-Phase Track A (Task A7).
- **v3.0 (2026-02-18)**: Removed 8 deprecated classes (`PatientProfile`, `VitalSignsTrend`, `WellnessBaseline`, `ActivitySummary`, `ClinicalSummary`, `HealthRecord`, `ReviewOfSystems`, `DataProvenance`) and associated properties. Clean break per guiding constraint #1. 27 active classes remain. CLN1 version bump.
- **v2.3 (2026-02-18)**: Deprecated `checkup:cascadeUri` in favor of `cascade:cascadeUri` from core.ttl (Phase 3.5 ONT3).
- **v2.2 (2026-02-17)**: `checkup:InsuranceInfo` class comment updated to reference `coverage:` namespace properties. Version bump to match `checkup.ttl` `owl:versionInfo`. Part of Schema Refactoring Plan Phase 3 (WS4 integration).
- **v2.1 (2026-02-17)**: `DailyCheckIn` now `rdfs:subClassOf health:SelfReport` (was `prov:Entity`). Base self-report properties (`reportDate`, `reportType`, `completionStatus`, `reportContext`, `reportNotes`) promoted to `health:` namespace. Part of Schema Refactoring Plan Phase 3 (WS7).
- **v2.0 (2026-02-17)**: Deprecated `checkup:` patient profile properties (`maritalStatus`, `raceEthnicity`, `preferredPharmacy`, `hasLivingWill`, `hasPowerOfAttorney`, `hasDNR`, `advanceDirectiveNotes`, `preferredLanguage`) in favor of `cascade:` equivalents in Core Vocabulary v2.0. Core demographics (`dateOfBirth`, `biologicalSex`, `genderIdentity`, `ageGroup`) migrated to `cascade:PatientProfile`. Part of Schema Refactoring Plan Phase 3 (WS6).
- **v1.11 (2026-02-18)**: Updated `InsuranceInfo` class comment to reference `coverage:` namespace for mixed namespace pattern. Part of Schema Refactoring Plan Phase 2 (WS4).
- **v1.10 (2026-02-17)**: Added `cascade:subConcern` annotations to all 35 checkup classes (9 categories). Deprecated `WellnessBaseline`, `ActivitySummary`, `ReviewOfSystems`. Defined 14 dark vocabulary properties with migration annotations. Part of Schema Refactoring Plan Phase 1 (WS2).
- **v1.9 (2026-02-10)**: Added `MedicationChangeRecord` class for tracking medication/supplement changes between visit snapshots (5 properties + `hasChange` link). Enables persistence of "Changes Since Last Visit" report data. Property names prefixed (`changeRecordPreviousValue`, `changeRecordNewValue`) to avoid collision with `VitalSignsTrend` properties.
- **v1.8 (2026-02-10)**: Added `ProcedureSummary` class with mixed namespace pattern (4 `checkup:` properties + 7 `clinical:` cross-references). Added `hasProcedure` aggregate link on `IntakeFormData`. Procedure serialization and deserialization implemented in `CheckupSerializer`/`CheckupDeserializer`.
- **v1.7 (2026-02-10)**: Added 5 new classes: `WellnessBaseline` (8 properties — aggregated wellness metrics snapshot), `ActivitySummary` (8 properties — activity and sleep metrics), `ImmunizationSummary` (16 properties — mixed namespace pattern with clinical:), `LabResultSummary` (1 checkup: property + 12 clinical: properties via mixed namespace), `WellnessProfileReference` (pointer to SDK HealthProfile). Added 4 MedicationSummary verification properties (needsVerification, verificationReason, lastVerifiedDate, importSessionId). Added 2 SuggestedQuestion properties (basedOnTemplate, basedOnScreening). Added `noteContent` property to VisitPrepSummary (merges planned VisitPrepNotes class). Added 4 IntakeFormData aggregate links (hasImmunization, hasLabResult, hasWellnessBaseline, hasActivitySummary). Mixed namespace pattern documented as standard for Layer 3 summary classes.
- **v1.6 (2026-02-09)**: Added 2 new classes for intake questionnaire data: `IntakeQuestionnaireResponse` (FHIR-inspired questionnaire container using LOINC panel codes as identifiers and SNOMED CT for coded answers, with `rdfs:seeAlso fhir:QuestionnaireResponse`), `ResponseItem` (question-answer pair with LOINC item codes, SNOMED CT coded answers, and nested sub-items via `childItem`). Added 10 new properties and `hasQuestionnaireResponse` link from `IntakeFormData`. Design follows "established vocabularies first" — LOINC/SNOMED as actual vocabulary, `checkup:` as minimal container. Mechanical transformation path to FHIR QuestionnaireResponse JSON preserved. Supports template-driven intake form expansion (Kaiser eCheck-In gap analysis). Also backfilled v1.5 classes into `checkup.ttl` ontology file (previously documented but not in TTL).
- **v1.5 (2026-02-07)**: Added 3 new classes for export completeness: `DailyCheckIn` (patient-reported medication adherence with per-medication tracking, mapped to LOINC `79474-4` and SNOMED `225390008`/`418633004`), `DiscussionTopic` (AI-generated or user-created visit discussion items with 11 categories, relevance scoring, and medication context — Cascade-proprietary, no standard equivalent), `CheckInSettings` (application configuration for notification scheduling, not health data). All classes follow three-layer ontology: L1 mappings documented or gaps noted, L2 skipped with rationale, L3 classes defined. Supports Bug 6/11 export overhaul Phase 4B serialization.
- **v1.4 (2026-02-01)**: Added 6 new classes: `WellnessSummary`, `TrendInsight`, `CorrelationInsight`, `KeyIndicator`, `AttentionItem`, `VisitPrepSummary`. Deprecated `VitalSignsTrend`. Added `health:` import.
- **v1.3 (2026-01-17)**: Added EHR provenance properties (`ehrSystemName`, `ehrOrganization`, `fhirResourceType`, `lastSyncedFromSource`) and medication classification (`relevanceTier`, `therapeuticClass`, `tierClassificationReason`).
- **v1.2 (2026-01-15)**: Added Phase 3 medication properties, doctorAware
- **v1.1 (2026-01-15)**: Added SupplementSummary class
- **v1.0 (2026-01-03)**: Initial release with 12 core classes

### Coverage Vocabulary
- **v1.1 (2026-03-12)**: Added `coverage:ClaimRecord` class (6 properties: claimDate, claimTotal, claimStatus, claimType, billingProvider, sourceRecordId; fhir:Claim alignment). Added `coverage:BenefitStatement` class (9 properties: adjudicationDate, adjudicationStatus, outcomeCode, denialReason, totalBilled, totalPaid, patientResponsibility, relatedClaim, sourceRecordId; fhir:ExplanationOfBenefit alignment). Promoted previously-deferred Deductible fill properties (deductibleAmount, deductibleMet, outOfPocketMax) and CopaySchedule fill properties (copayPrimary, copaySpecialist, copayEmergency). `coverage:sourceRecordId` defined as domain-unrestricted property shared across ClaimRecord and BenefitStatement (OQ pre-flight correction). Added permissive SHACL shapes for new classes. Part of Lossless FHIR ↔ Cascade Conversion Plan Phase A.
- **v1.0 (2026-02-18)**: Initial release. `InsurancePlan` class with 14 properties (8 core, 3 subscriber, 3 pharmacy benefit). `Deductible` and `CopaySchedule` classes defined (properties deferred). Unifies `checkup:InsuranceInfo` (L3) and `clinical:CoverageRecord` (L2). FHIR Coverage alignment. Part of Schema Refactoring Plan Phase 2 (WS4).

### POTS Vocabulary
- **v1.4 (2026-02-26)**: Added 8 new optional predicates for POTS Check V2. Test configuration: `baselineDurationMinutes` (user-selected baseline in whole minutes), `testNotes` (free-text patient notes, max 500 chars), `bpProvided` (boolean BP cuff flag). Proportional Pulse Pressure per-minute ratios: `pppMinute1`, `pppMinute3`, `pppMinute5`, `pppMinute7`, `pppMinute10` (decimal 0.0-1.0, PPP = (SBP-DBP)/SBP). All predicates are optional; v1.3 files remain fully parseable.
- **v1.3 (2026-02-10)**: Added 2 timing properties (`secondsSinceStand`, `timestampSeconds`) for fine-grained temporal resolution in standing/symptom data. Added 4 Apple Health import properties (`importedBloodPressureHistory`, `importedHRVHistory`, `averageImportedBloodPressure`, `averageImportedHRV`) for longitudinal context. Renamed `postureStabilitySamples` to `postureStability` to match shipped app serializer.
- **v1.2**: Added maxHeartRateDelta, userAgeAtTest, posture quality
- **v1.1**: Added orthostaticHypertensionSuspected, postureQualityScore
- **v1.0 (2025-10-31)**: Initial release

### SHACL Shapes Files
- **clinical.shapes.ttl v1.9 (2026-06-17)**: Added `cascade:AIExtracted` to every `cascade:dataProvenance` `sh:in` enumeration so AI-extracted clinical records (e.g. from the Workbench's document-extraction pipeline) validate. Shapes-only change.
- **core.shapes.ttl v1.0 (2026-02-18)**: Initial release. Validation shapes for `cascade:PatientProfile` (required demographics, address structure) and `cascade:DataProvenance` taxonomy.
- **clinical.shapes.ttl v1.7 additions (2026-03-12)**: Added permissive shapes for `clinical:Encounter`, `clinical:MedicationAdministration`, `clinical:ImplantedDevice`, `clinical:ImagingStudy`, and `clinical:LaboratoryReport` (panel additions). All new shapes use `sh:minCount 0` on every property (OQ-4 decision).
- **clinical.shapes.ttl v1.0 (2026-02-10)**: Initial release. Validation shapes for `clinical:ClinicalDocument`, `clinical:MedicationUseEpisode`, and `clinical:Supplement` required fields.
- **coverage.shapes.ttl v1.1 additions (2026-03-12)**: Added permissive shapes for `coverage:ClaimRecord` and `coverage:BenefitStatement`. All new shapes use `sh:minCount 0` on every property (OQ-4 decision).
- **coverage.shapes.ttl v1.0 (2026-02-18)**: Initial release. Validation shapes for `coverage:InsurancePlan`.
- **health.shapes.ttl v1.0 (2026-02-18)**: Initial release. Validation shapes for `health:HealthProfile`, `health:MetricTrend` enum validation, and statistical summary classes.
- **pots.shapes.ttl v1.0 (2026-02-18)**: Initial release. Validation shapes for `pots:POTSCheckResult` protocol fields and `pots:HeartRateMeasurement` timing constraints.
- **coverage.shapes.ttl v1.0 (2026-02-18)**: Initial release. Validation shapes for `coverage:InsurancePlan` required fields, date ranges, and plan type enums.
- **checkup.shapes.ttl v2.0 (2026-02-18)**: Updated for v3.0 vocabulary changes. Removed shapes for deleted classes (`PatientProfile`, `WellnessBaseline`, `ActivitySummary`). IntakeFormData shape now references `cascade:PatientProfileShape` from core shapes. Updated from v1.0.

---

*This document is generated from the official Cascade Protocol TTL schema files.*
*For the latest version, visit: https://cascadeprotocol.org/docs/*
