@the-cascade-protocol/cli 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. package/.dockerignore +7 -0
  2. package/.eslintrc.json +23 -0
  3. package/.prettierrc +7 -0
  4. package/DOCKER.md +36 -0
  5. package/Dockerfile +18 -0
  6. package/README.md +69 -0
  7. package/dist/commands/capabilities.d.ts +9 -0
  8. package/dist/commands/capabilities.d.ts.map +1 -0
  9. package/dist/commands/capabilities.js +194 -0
  10. package/dist/commands/capabilities.js.map +1 -0
  11. package/dist/commands/conformance.d.ts +15 -0
  12. package/dist/commands/conformance.d.ts.map +1 -0
  13. package/dist/commands/conformance.js +348 -0
  14. package/dist/commands/conformance.js.map +1 -0
  15. package/dist/commands/convert.d.ts +21 -0
  16. package/dist/commands/convert.d.ts.map +1 -0
  17. package/dist/commands/convert.js +134 -0
  18. package/dist/commands/convert.js.map +1 -0
  19. package/dist/commands/pod/export.d.ts +8 -0
  20. package/dist/commands/pod/export.d.ts.map +1 -0
  21. package/dist/commands/pod/export.js +72 -0
  22. package/dist/commands/pod/export.js.map +1 -0
  23. package/dist/commands/pod/helpers.d.ts +79 -0
  24. package/dist/commands/pod/helpers.d.ts.map +1 -0
  25. package/dist/commands/pod/helpers.js +369 -0
  26. package/dist/commands/pod/helpers.js.map +1 -0
  27. package/dist/commands/pod/index.d.ts +20 -0
  28. package/dist/commands/pod/index.d.ts.map +1 -0
  29. package/dist/commands/pod/index.js +29 -0
  30. package/dist/commands/pod/index.js.map +1 -0
  31. package/dist/commands/pod/info.d.ts +9 -0
  32. package/dist/commands/pod/info.d.ts.map +1 -0
  33. package/dist/commands/pod/info.js +196 -0
  34. package/dist/commands/pod/info.js.map +1 -0
  35. package/dist/commands/pod/init.d.ts +9 -0
  36. package/dist/commands/pod/init.d.ts.map +1 -0
  37. package/dist/commands/pod/init.js +251 -0
  38. package/dist/commands/pod/init.js.map +1 -0
  39. package/dist/commands/pod/query.d.ts +9 -0
  40. package/dist/commands/pod/query.d.ts.map +1 -0
  41. package/dist/commands/pod/query.js +169 -0
  42. package/dist/commands/pod/query.js.map +1 -0
  43. package/dist/commands/pod 2.js +1017 -0
  44. package/dist/commands/pod.d.ts +28 -0
  45. package/dist/commands/pod.d.ts 2.map +1 -0
  46. package/dist/commands/pod.d.ts.map +1 -0
  47. package/dist/commands/pod.js +1031 -0
  48. package/dist/commands/pod.js 2.map +1 -0
  49. package/dist/commands/pod.js.map +1 -0
  50. package/dist/commands/serve.d.ts +33 -0
  51. package/dist/commands/serve.d.ts.map +1 -0
  52. package/dist/commands/serve.js +74 -0
  53. package/dist/commands/serve.js.map +1 -0
  54. package/dist/commands/validate.d.ts +18 -0
  55. package/dist/commands/validate.d.ts.map +1 -0
  56. package/dist/commands/validate.js +275 -0
  57. package/dist/commands/validate.js.map +1 -0
  58. package/dist/index.d.ts +19 -0
  59. package/dist/index.d.ts.map +1 -0
  60. package/dist/index.js +49 -0
  61. package/dist/index.js.map +1 -0
  62. package/dist/lib/fhir-converter/cascade-to-fhir.d.ts +17 -0
  63. package/dist/lib/fhir-converter/cascade-to-fhir.d.ts.map +1 -0
  64. package/dist/lib/fhir-converter/cascade-to-fhir.js +358 -0
  65. package/dist/lib/fhir-converter/cascade-to-fhir.js.map +1 -0
  66. package/dist/lib/fhir-converter/converters-clinical.d.ts +29 -0
  67. package/dist/lib/fhir-converter/converters-clinical.d.ts.map +1 -0
  68. package/dist/lib/fhir-converter/converters-clinical.js +391 -0
  69. package/dist/lib/fhir-converter/converters-clinical.js.map +1 -0
  70. package/dist/lib/fhir-converter/converters-demographics.d.ts +20 -0
  71. package/dist/lib/fhir-converter/converters-demographics.d.ts.map +1 -0
  72. package/dist/lib/fhir-converter/converters-demographics.js +242 -0
  73. package/dist/lib/fhir-converter/converters-demographics.js.map +1 -0
  74. package/dist/lib/fhir-converter/fhir-to-cascade.d.ts +17 -0
  75. package/dist/lib/fhir-converter/fhir-to-cascade.d.ts.map +1 -0
  76. package/dist/lib/fhir-converter/fhir-to-cascade.js +63 -0
  77. package/dist/lib/fhir-converter/fhir-to-cascade.js.map +1 -0
  78. package/dist/lib/fhir-converter/index.d.ts +36 -0
  79. package/dist/lib/fhir-converter/index.d.ts.map +1 -0
  80. package/dist/lib/fhir-converter/index.js +187 -0
  81. package/dist/lib/fhir-converter/index.js.map +1 -0
  82. package/dist/lib/fhir-converter/types.d.ts +77 -0
  83. package/dist/lib/fhir-converter/types.d.ts.map +1 -0
  84. package/dist/lib/fhir-converter/types.js +236 -0
  85. package/dist/lib/fhir-converter/types.js.map +1 -0
  86. package/dist/lib/fhir-converter.d.ts +62 -0
  87. package/dist/lib/fhir-converter.d.ts.map +1 -0
  88. package/dist/lib/fhir-converter.js +1474 -0
  89. package/dist/lib/fhir-converter.js.map +1 -0
  90. package/dist/lib/mcp/audit.d.ts +24 -0
  91. package/dist/lib/mcp/audit.d.ts.map +1 -0
  92. package/dist/lib/mcp/audit.js +85 -0
  93. package/dist/lib/mcp/audit.js.map +1 -0
  94. package/dist/lib/mcp/server.d.ts +38 -0
  95. package/dist/lib/mcp/server.d.ts.map +1 -0
  96. package/dist/lib/mcp/server.js +172 -0
  97. package/dist/lib/mcp/server.js.map +1 -0
  98. package/dist/lib/mcp/tools.d.ts +47 -0
  99. package/dist/lib/mcp/tools.d.ts.map +1 -0
  100. package/dist/lib/mcp/tools.js +547 -0
  101. package/dist/lib/mcp/tools.js.map +1 -0
  102. package/dist/lib/output.d.ts +26 -0
  103. package/dist/lib/output.d.ts.map +1 -0
  104. package/dist/lib/output.js +64 -0
  105. package/dist/lib/output.js.map +1 -0
  106. package/dist/lib/shacl-validator.d.ts +53 -0
  107. package/dist/lib/shacl-validator.d.ts.map +1 -0
  108. package/dist/lib/shacl-validator.js +245 -0
  109. package/dist/lib/shacl-validator.js.map +1 -0
  110. package/dist/lib/turtle-parser.d.ts +64 -0
  111. package/dist/lib/turtle-parser.d.ts.map +1 -0
  112. package/dist/lib/turtle-parser.js +236 -0
  113. package/dist/lib/turtle-parser.js.map +1 -0
  114. package/dist/shapes/checkup.shapes.ttl +1459 -0
  115. package/dist/shapes/clinical.shapes.ttl +1350 -0
  116. package/dist/shapes/clinical.ttl +1369 -0
  117. package/dist/shapes/core.shapes.ttl +450 -0
  118. package/dist/shapes/core.ttl +603 -0
  119. package/dist/shapes/coverage.shapes.ttl +214 -0
  120. package/dist/shapes/coverage.ttl +182 -0
  121. package/dist/shapes/health.shapes.ttl +697 -0
  122. package/dist/shapes/health.ttl +859 -0
  123. package/dist/shapes/pots.shapes.ttl +481 -0
  124. package/package.json +54 -0
  125. package/src/commands/capabilities.ts +235 -0
  126. package/src/commands/conformance.ts +447 -0
  127. package/src/commands/convert.ts +164 -0
  128. package/src/commands/pod/export.ts +85 -0
  129. package/src/commands/pod/helpers.ts +449 -0
  130. package/src/commands/pod/index.ts +32 -0
  131. package/src/commands/pod/info.ts +239 -0
  132. package/src/commands/pod/init.ts +273 -0
  133. package/src/commands/pod/query.ts +224 -0
  134. package/src/commands/serve.ts +92 -0
  135. package/src/commands/validate.ts +303 -0
  136. package/src/index.ts +58 -0
  137. package/src/lib/fhir-converter/cascade-to-fhir.ts +369 -0
  138. package/src/lib/fhir-converter/converters-clinical.ts +446 -0
  139. package/src/lib/fhir-converter/converters-demographics.ts +270 -0
  140. package/src/lib/fhir-converter/fhir-to-cascade.ts +82 -0
  141. package/src/lib/fhir-converter/index.ts +215 -0
  142. package/src/lib/fhir-converter/types.ts +318 -0
  143. package/src/lib/mcp/audit.ts +107 -0
  144. package/src/lib/mcp/server.ts +192 -0
  145. package/src/lib/mcp/tools.ts +668 -0
  146. package/src/lib/output.ts +76 -0
  147. package/src/lib/shacl-validator.ts +314 -0
  148. package/src/lib/turtle-parser.ts +277 -0
  149. package/src/shapes/checkup.shapes.ttl +1459 -0
  150. package/src/shapes/clinical.shapes.ttl +1350 -0
  151. package/src/shapes/clinical.ttl +1369 -0
  152. package/src/shapes/core.shapes.ttl +450 -0
  153. package/src/shapes/core.ttl +603 -0
  154. package/src/shapes/coverage.shapes.ttl +214 -0
  155. package/src/shapes/coverage.ttl +182 -0
  156. package/src/shapes/health.shapes.ttl +697 -0
  157. package/src/shapes/health.ttl +859 -0
  158. package/src/shapes/pots.shapes.ttl +481 -0
  159. package/test-fixtures/fhir-bundle-example.json +216 -0
  160. package/test-fixtures/fhir-medication-example.json +18 -0
  161. package/tests/cli.test.ts +126 -0
  162. package/tests/fhir-converter.test.ts +874 -0
  163. package/tests/mcp-server.test.ts +396 -0
  164. package/tests/pod.test.ts +400 -0
  165. package/tsconfig.json +24 -0
@@ -0,0 +1,859 @@
1
+ @prefix health: <https://ns.cascadeprotocol.org/health/v1#> .
2
+ @prefix cascade: <https://ns.cascadeprotocol.org/core/v1#> .
3
+ @prefix owl: <http://www.w3.org/2002/07/owl#> .
4
+ @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
5
+ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
6
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
7
+ @prefix dct: <http://purl.org/dc/terms/> .
8
+ @prefix fhir: <http://hl7.org/fhir/> .
9
+ @prefix sct: <http://snomed.info/sct/> .
10
+ @prefix loinc: <http://loinc.org/rdf#> .
11
+ @prefix prov: <http://www.w3.org/ns/prov#> .
12
+ @prefix ucum: <http://unitsofmeasure.org/> .
13
+
14
+ # ============================================================================
15
+ # Ontology Metadata
16
+ # ============================================================================
17
+
18
+ <https://ns.cascadeprotocol.org/health/v1#> a owl:Ontology ;
19
+ owl:imports <https://ns.cascadeprotocol.org/core/v1#> ;
20
+ dct:title "Cascade Protocol Health & Wellness Ontology"@en ;
21
+ dct:description "Vocabulary for consumer-generated wellness observations from wearable devices and HealthKit. Maps Cascade wellness properties to established SNOMED CT and LOINC codes following the three-layer ontology architecture."@en ;
22
+ dct:creator "Cascade Agentic Labs" ;
23
+ dct:created "2026-01-29"^^xsd:date ;
24
+ dct:modified "2026-02-17"^^xsd:date ;
25
+ owl:versionInfo "2.2" ;
26
+ rdfs:comment """Three-layer ontology for wellness data:
27
+ Layer 1 (Established standards): SNOMED CT concept IDs + LOINC observation codes
28
+ Layer 2 (Cascade health vocabulary): health: namespace properties linking to Layer 1
29
+ Layer 3 (Checkup summary): checkup: namespace patient-facing aggregations"""@en ;
30
+ rdfs:seeAlso <https://cascadeprotocol.org/docs/health/v1/> .
31
+
32
+ # Changelog:
33
+ # v2.2 (2026-02-17): Added 2 container linking ObjectProperties:
34
+ # health:hasHRVStatistics, health:hasBPStatistics. These link a wellness
35
+ # profile or intake form to its statistical summary nodes. Previously dark
36
+ # vocabulary emitted by CheckupSerializer. Part of Schema Refactoring
37
+ # Plan Phase 3 (PF1-R).
38
+ #
39
+ # v2.1 (2026-02-17): Added health:SelfReport base class and 5 base properties
40
+ # (reportDate, reportType, completionStatus, reportContext, reportNotes)
41
+ # for patient-reported daily check-ins. (Phase 3, WS7)
42
+ #
43
+ # v2.0 (2026-02-18): Schema Refactoring WS3b — Migrated HealthProfileSerializer
44
+ # from cascade: to health: namespace. Added 8 history container properties
45
+ # (restingHeartRateHistory, walkingHeartRateHistory, hrvHistory,
46
+ # bloodPressureHistory, vo2MaxHistory, bodyMassHistory, dailyActivityHistory,
47
+ # dailySleepHistory) and 7 supporting classes (HealthProfile, DailyVitalReading,
48
+ # HRVReading, BloodPressureReading, VitalSignReading, DailyActivitySnapshot,
49
+ # DailySleepSnapshot). These properties capture time-series data emitted by
50
+ # HealthProfileSerializer for 90-day, 30-day, and 7-day lookback windows.
51
+ #
52
+ # v1.9 (2026-02-17): Added health:bloodType property for ABO blood group and
53
+ # Rh factor. Values: aPositive, aNegative, bPositive, bNegative, abPositive,
54
+ # abNegative, oPositive, oNegative. Sourced from HealthKit
55
+ # (HKCharacteristicType.bloodType) or manual entry. Previously dark vocabulary
56
+ # emitted in QR payload. Part of Schema Refactoring Plan Phase 2.5 (PF4).
57
+ #
58
+ # v1.8 (2026-02-10): Added 6 body measurement properties with SNOMED/LOINC
59
+ # annotations (bodyMass, bodyHeight, bodyMassIndex, bodyTemperature,
60
+ # oxygenSaturation, bloodGlucose). Added health:BPStatistics class with
61
+ # 10 properties for blood pressure statistical summaries. Added shared
62
+ # temporal properties (periodStart, periodEnd). Completed HRVStatistics
63
+ # property definitions (hrvSampleCount, hrvDaysCovered, hrvMean, hrvMedian,
64
+ # hrvStdDev, hrvMin, hrvMax, hrvPercentile25, hrvPercentile75,
65
+ # hrvTrendDirection).
66
+ #
67
+ # v1.7 (2026-02-03): Added health:VO2MaxStatistics and health:HRVStatistics
68
+ # composite classes for statistical trend analysis. Added 9 new properties
69
+ # for VO2 Max statistics: vo2Mean, vo2Min, vo2MaxValue, vo2SampleCount,
70
+ # vo2DaysCovered, vo2TrendDirection, vo2PercentageChange, fitnessClassification,
71
+ # and isSparseData. These support the dual-path UI pattern where rich statistics
72
+ # are preferred when available, with fallback to single values. Part of the
73
+ # VO2 Max Statistics Implementation Plan Phase 5 (Documentation).
74
+ #
75
+ # v1.6 (2026-02-02): Added health:trendPolarity annotation property to all
76
+ # measurable wellness metrics. Defines whether an increase is generally
77
+ # favorable (higher_is_better), unfavorable (lower_is_better), or
78
+ # context-dependent (neutral). Used by presentation layers for trend arrow
79
+ # color semantics. Part of Visit Prep Feature Plan Phase 1.5.
80
+ #
81
+ # v1.5 (2026-02-01): Added health:MetricTrend class for time-bounded wellness
82
+ # trends with direction, magnitude, confidence, and baseline/current values.
83
+ # Follows the pattern established by clinical:LabTestSeries but designed for
84
+ # continuous daily observations from consumer devices (vs discrete clinical samples).
85
+ # Shares trendDirection/trendConfidence vocabulary with clinical: for cross-domain
86
+ # consistency. Added as part of Ontology Improvement Plan (Work Stream 2, Task 2.1).
87
+ #
88
+ # v1.4 (2026-01-29): Initial release. Wellness vital signs, activity, and sleep
89
+ # properties with SNOMED CT and LOINC standard code mappings for all metrics.
90
+ # Created as part of the Wellness Data Pipeline implementation (Tasks 1-7).
91
+
92
+ # ============================================================================
93
+ # Layer 2: Wellness Observation Properties
94
+ # ============================================================================
95
+ # Each property maps a cascade: wellness term to its SNOMED CT and LOINC equivalents.
96
+ # These properties are used by HealthProfileSerializer to produce interoperable TTL.
97
+
98
+ # ----------------------------------------------------------------------------
99
+ # Vital Signs — Cardiac
100
+ # ----------------------------------------------------------------------------
101
+
102
+ health:restingHeartRate a owl:DatatypeProperty ;
103
+ rdfs:label "Resting Heart Rate"@en ;
104
+ rdfs:comment "Average resting heart rate from wearable device"@en ;
105
+ rdfs:domain fhir:Observation ;
106
+ rdfs:range xsd:double ;
107
+ health:snomedCode sct:364075005 ; # Heart rate
108
+ health:loincCode loinc:40443-4 ; # Heart rate --resting
109
+ health:unit "beats/min" ;
110
+ health:ucumCode "/min" ;
111
+ health:trendPolarity "lower_is_better" .
112
+
113
+ health:walkingHeartRate a owl:DatatypeProperty ;
114
+ rdfs:label "Walking Heart Rate"@en ;
115
+ rdfs:comment "Average heart rate during walking from wearable device"@en ;
116
+ rdfs:domain fhir:Observation ;
117
+ rdfs:range xsd:double ;
118
+ health:snomedCode sct:364075005 ; # Heart rate
119
+ health:loincCode loinc:89270-3 ; # Heart rate --W exercise
120
+ health:unit "beats/min" ;
121
+ health:ucumCode "/min" ;
122
+ health:trendPolarity "lower_is_better" .
123
+
124
+ health:heartRateVariability a owl:DatatypeProperty ;
125
+ rdfs:label "Heart Rate Variability (SDNN)"@en ;
126
+ rdfs:comment "Standard deviation of normal-to-normal R-R intervals (SDNN) from wearable device"@en ;
127
+ rdfs:domain fhir:Observation ;
128
+ rdfs:range xsd:double ;
129
+ health:snomedCode sct:80404004 ; # Heart rate variability
130
+ health:loincCode loinc:80404-7 ; # R-R interval.standard deviation
131
+ health:unit "ms" ;
132
+ health:ucumCode "ms" ;
133
+ health:trendPolarity "higher_is_better" .
134
+
135
+ # ----------------------------------------------------------------------------
136
+ # Vital Signs — Cardiovascular
137
+ # ----------------------------------------------------------------------------
138
+
139
+ health:bloodPressure a owl:ObjectProperty ;
140
+ rdfs:label "Blood Pressure"@en ;
141
+ rdfs:comment "Blood pressure panel observation with systolic and diastolic components"@en ;
142
+ rdfs:domain fhir:Observation ;
143
+ health:snomedCode sct:75367002 ; # Blood pressure
144
+ health:loincCode loinc:85354-9 . # Blood pressure panel
145
+
146
+ health:systolicBP a owl:DatatypeProperty ;
147
+ rdfs:label "Systolic Blood Pressure"@en ;
148
+ rdfs:domain fhir:Observation ;
149
+ rdfs:range xsd:double ;
150
+ health:snomedCode sct:271649006 ; # Systolic blood pressure
151
+ health:loincCode loinc:8480-6 ; # Systolic blood pressure
152
+ health:unit "mmHg" ;
153
+ health:ucumCode "mm[Hg]" ;
154
+ health:trendPolarity "lower_is_better" .
155
+
156
+ health:diastolicBP a owl:DatatypeProperty ;
157
+ rdfs:label "Diastolic Blood Pressure"@en ;
158
+ rdfs:domain fhir:Observation ;
159
+ rdfs:range xsd:double ;
160
+ health:snomedCode sct:271650006 ; # Diastolic blood pressure
161
+ health:loincCode loinc:8462-4 ; # Diastolic blood pressure
162
+ health:unit "mmHg" ;
163
+ health:ucumCode "mm[Hg]" ;
164
+ health:trendPolarity "lower_is_better" .
165
+
166
+ # ----------------------------------------------------------------------------
167
+ # Vital Signs — Respiratory & Fitness
168
+ # ----------------------------------------------------------------------------
169
+
170
+ health:respiratoryRate a owl:DatatypeProperty ;
171
+ rdfs:label "Respiratory Rate"@en ;
172
+ rdfs:comment "Average respiratory rate from wearable device"@en ;
173
+ rdfs:domain fhir:Observation ;
174
+ rdfs:range xsd:double ;
175
+ health:snomedCode sct:86290005 ; # Respiratory rate
176
+ health:loincCode loinc:9279-1 ; # Respiratory rate
177
+ health:unit "breaths/min" ;
178
+ health:ucumCode "/min" ;
179
+ health:trendPolarity "neutral" .
180
+
181
+ health:vo2Max a owl:DatatypeProperty ;
182
+ rdfs:label "VO2 Max"@en ;
183
+ rdfs:comment "Estimated maximal oxygen consumption (cardiorespiratory fitness)"@en ;
184
+ rdfs:domain fhir:Observation ;
185
+ rdfs:range xsd:double ;
186
+ health:snomedCode sct:251880009 ; # Aerobic capacity
187
+ health:loincCode loinc:60842-2 ; # VO2 max
188
+ health:unit "mL/kg/min" ;
189
+ health:ucumCode "mL/kg/min" ;
190
+ health:trendPolarity "higher_is_better" .
191
+
192
+ # ----------------------------------------------------------------------------
193
+ # Walking Steadiness
194
+ # ----------------------------------------------------------------------------
195
+
196
+ health:walkingSteadiness a owl:DatatypeProperty ;
197
+ rdfs:label "Walking Steadiness"@en ;
198
+ rdfs:comment "Apple Health walking steadiness classification (OK / Low / Very Low). Maps to nearest SNOMED balance concept. No LOINC equivalent exists for this consumer-device metric."@en ;
199
+ rdfs:domain fhir:Observation ;
200
+ rdfs:range xsd:string ;
201
+ health:snomedCode sct:364832000 ; # Balance finding
202
+ rdfs:comment "SNOMED mapping note: 364832000 (Balance finding) is the closest available concept. Alternatives considered: 250043000 (Gait finding), 282097004 (Ability to walk). Apple's OK/Low/Very Low classification is proprietary."@en .
203
+
204
+ # Valid values for walkingSteadiness
205
+ health:WalkingSteadinessOK a health:WalkingSteadinessLevel ;
206
+ rdfs:label "OK" .
207
+ health:WalkingSteadinessLow a health:WalkingSteadinessLevel ;
208
+ rdfs:label "Low" .
209
+ health:WalkingSteadinessVeryLow a health:WalkingSteadinessLevel ;
210
+ rdfs:label "Very Low" .
211
+
212
+ # ----------------------------------------------------------------------------
213
+ # Body Measurements (v1.8)
214
+ # ----------------------------------------------------------------------------
215
+
216
+ health:bodyMass a owl:DatatypeProperty ;
217
+ rdfs:label "Body Mass"@en ;
218
+ rdfs:comment "Body weight measurement."@en ;
219
+ rdfs:domain fhir:Observation ;
220
+ rdfs:range xsd:double ;
221
+ health:snomedCode sct:27113001 ;
222
+ health:loincCode loinc:29463-7 ;
223
+ health:unit "kg" ;
224
+ health:ucumCode "kg" ;
225
+ health:trendPolarity "neutral" .
226
+
227
+ health:bodyHeight a owl:DatatypeProperty ;
228
+ rdfs:label "Body Height"@en ;
229
+ rdfs:comment "Body height measurement."@en ;
230
+ rdfs:domain fhir:Observation ;
231
+ rdfs:range xsd:double ;
232
+ health:snomedCode sct:50373000 ;
233
+ health:loincCode loinc:8302-2 ;
234
+ health:unit "cm" ;
235
+ health:ucumCode "cm" ;
236
+ health:trendPolarity "neutral" .
237
+
238
+ health:bodyMassIndex a owl:DatatypeProperty ;
239
+ rdfs:label "Body Mass Index"@en ;
240
+ rdfs:comment "Computed body mass index (weight/height squared)."@en ;
241
+ rdfs:domain fhir:Observation ;
242
+ rdfs:range xsd:double ;
243
+ health:snomedCode sct:60621009 ;
244
+ health:loincCode loinc:39156-5 ;
245
+ health:unit "kg/m2" ;
246
+ health:ucumCode "kg/m2" ;
247
+ health:trendPolarity "neutral" .
248
+
249
+ health:bodyTemperature a owl:DatatypeProperty ;
250
+ rdfs:label "Body Temperature"@en ;
251
+ rdfs:comment "Body temperature measurement."@en ;
252
+ rdfs:domain fhir:Observation ;
253
+ rdfs:range xsd:double ;
254
+ health:snomedCode sct:386725007 ;
255
+ health:loincCode loinc:8310-5 ;
256
+ health:unit "degC" ;
257
+ health:ucumCode "Cel" ;
258
+ health:trendPolarity "neutral" .
259
+
260
+ health:oxygenSaturation a owl:DatatypeProperty ;
261
+ rdfs:label "Oxygen Saturation"@en ;
262
+ rdfs:comment "Blood oxygen saturation (SpO2) from pulse oximeter."@en ;
263
+ rdfs:domain fhir:Observation ;
264
+ rdfs:range xsd:double ;
265
+ health:snomedCode sct:431314004 ;
266
+ health:loincCode loinc:2708-6 ;
267
+ health:unit "%" ;
268
+ health:ucumCode "%" ;
269
+ health:trendPolarity "higher_is_better" .
270
+
271
+ health:bloodGlucose a owl:DatatypeProperty ;
272
+ rdfs:label "Blood Glucose"@en ;
273
+ rdfs:comment "Blood glucose measurement."@en ;
274
+ rdfs:domain fhir:Observation ;
275
+ rdfs:range xsd:double ;
276
+ health:snomedCode sct:33747003 ;
277
+ health:loincCode loinc:2339-0 ;
278
+ health:unit "mg/dL" ;
279
+ health:ucumCode "mg/dL" ;
280
+ health:trendPolarity "neutral" .
281
+
282
+ # ----------------------------------------------------------------------------
283
+ # Blood Type (v1.9)
284
+ # ----------------------------------------------------------------------------
285
+
286
+ health:bloodType a owl:DatatypeProperty ;
287
+ rdfs:label "Blood Type"@en ;
288
+ rdfs:comment "ABO blood group and Rh factor. Values: aPositive, aNegative, bPositive, bNegative, abPositive, abNegative, oPositive, oNegative. Sourced from HealthKit (HKCharacteristicType.bloodType) or manual entry."@en ;
289
+ rdfs:domain health:HealthProfile ;
290
+ rdfs:range xsd:string ;
291
+ health:snomedCode sct:365637002 ;
292
+ health:loincCode loinc:882-1 .
293
+
294
+ # Note: health:HealthProfile is not formally defined in this ontology file
295
+ # but refers to the SDK's HealthProfile model stored at /wellness/. The
296
+ # bloodType property is a characteristic (not a time-series observation)
297
+ # so it does not use fhir:Observation as its domain.
298
+
299
+ # ----------------------------------------------------------------------------
300
+ # Activity Metrics
301
+ # ----------------------------------------------------------------------------
302
+
303
+ health:averageDailySteps a owl:DatatypeProperty ;
304
+ rdfs:label "Average Daily Steps"@en ;
305
+ rdfs:comment "Average number of steps per day over measurement period"@en ;
306
+ rdfs:domain health:ActivitySnapshot ;
307
+ rdfs:range xsd:integer ;
308
+ health:snomedCode sct:68130003 ; # Physical activity
309
+ health:loincCode loinc:41950-7 ; # Number of steps in 24 hour Measured
310
+ health:unit "steps" ;
311
+ health:trendPolarity "higher_is_better" .
312
+
313
+ health:activeEnergyBurnedKcal a owl:DatatypeProperty ;
314
+ rdfs:label "Active Energy Burned"@en ;
315
+ rdfs:comment "Active energy expenditure in kilocalories (excludes basal metabolic rate)"@en ;
316
+ rdfs:domain health:ActivitySnapshot ;
317
+ rdfs:range xsd:decimal ;
318
+ health:snomedCode sct:251833007 ; # Energy expenditure
319
+ health:loincCode loinc:41981-2 ; # Calories burned
320
+ health:unit "kcal" ;
321
+ health:ucumCode "kcal" .
322
+
323
+ health:exerciseMinutesWeekly a owl:DatatypeProperty ;
324
+ rdfs:label "Exercise Minutes (Weekly)"@en ;
325
+ rdfs:comment "Total minutes of exercise activity per week"@en ;
326
+ rdfs:domain health:ActivitySnapshot ;
327
+ rdfs:range xsd:integer ;
328
+ health:snomedCode sct:68130003 ; # Physical activity
329
+ health:loincCode loinc:73985-4 ; # Exercise activity
330
+ health:unit "min" ;
331
+ health:ucumCode "min" ;
332
+ health:trendPolarity "higher_is_better" .
333
+
334
+ health:standHoursDaily a owl:DatatypeProperty ;
335
+ rdfs:label "Stand Hours (Daily)"@en ;
336
+ rdfs:comment "Number of hours per day with at least one minute of standing. Cascade-proprietary metric — no SNOMED CT or LOINC equivalent exists. Apple Health-specific activity ring metric."@en ;
337
+ rdfs:domain health:ActivitySnapshot ;
338
+ rdfs:range xsd:integer ;
339
+ health:unit "hours" .
340
+
341
+ # ----------------------------------------------------------------------------
342
+ # Sleep Metrics
343
+ # ----------------------------------------------------------------------------
344
+
345
+ health:averageDurationHours a owl:DatatypeProperty ;
346
+ rdfs:label "Average Sleep Duration"@en ;
347
+ rdfs:comment "Average sleep duration in hours over measurement period"@en ;
348
+ rdfs:domain health:SleepSnapshot ;
349
+ rdfs:range xsd:decimal ;
350
+ health:snomedCode sct:248263006 ; # Duration of sleep
351
+ health:loincCode loinc:93832-4 ; # Sleep duration
352
+ health:unit "hours" ;
353
+ health:ucumCode "h" ;
354
+ health:trendPolarity "neutral" .
355
+
356
+ health:sleepQuality a owl:DatatypeProperty ;
357
+ rdfs:label "Sleep Quality"@en ;
358
+ rdfs:comment "Qualitative sleep quality assessment derived from wearable sleep analysis"@en ;
359
+ rdfs:domain health:SleepSnapshot ;
360
+ rdfs:range xsd:string .
361
+
362
+ # ============================================================================
363
+ # Composite Classes
364
+ # ============================================================================
365
+
366
+ health:ActivitySnapshot a owl:Class ;
367
+ rdfs:label "Activity Snapshot"@en ;
368
+ rdfs:comment "Aggregated activity metrics over a measurement period (typically 7 days)"@en ;
369
+ rdfs:subClassOf prov:Entity .
370
+
371
+ health:SleepSnapshot a owl:Class ;
372
+ rdfs:label "Sleep Snapshot"@en ;
373
+ rdfs:comment "Aggregated sleep metrics over a measurement period (typically 7 days)"@en ;
374
+ rdfs:subClassOf prov:Entity .
375
+
376
+ health:VO2MaxStatistics a owl:Class ;
377
+ rdfs:label "VO2 Max Statistics"@en ;
378
+ rdfs:comment "Statistical summary of VO2 Max readings over a measurement period (typically 180 days). Provides trend analysis, fitness classification, and min/max/mean calculations. Designed for dual-path UI display: rich statistics view when available, fallback to single VO2 Max value otherwise."@en ;
379
+ rdfs:subClassOf prov:Entity .
380
+
381
+ health:HRVStatistics a owl:Class ;
382
+ rdfs:label "HRV Statistics"@en ;
383
+ rdfs:comment "Statistical summary of Heart Rate Variability (SDNN) readings over a measurement period. Provides trend analysis and min/max/mean calculations."@en ;
384
+ rdfs:subClassOf prov:Entity .
385
+
386
+ health:BPStatistics a owl:Class ;
387
+ rdfs:label "Blood Pressure Statistics"@en ;
388
+ rdfs:comment "Statistical summary of blood pressure readings over a measurement period. Provides mean, min, max for systolic and diastolic values, plus AHA category classification."@en ;
389
+ rdfs:subClassOf prov:Entity .
390
+
391
+ health:HealthProfile a owl:Class ;
392
+ rdfs:label "Health Profile"@en ;
393
+ rdfs:comment "Top-level wellness profile aggregating vital signs, body measurements, activity, and sleep data from consumer devices. Stored at /wellness/ in the Cascade Pod."@en ;
394
+ rdfs:subClassOf prov:Entity .
395
+
396
+ health:DailyVitalReading a owl:Class ;
397
+ rdfs:label "Daily Vital Reading"@en ;
398
+ rdfs:comment "A single day's aggregated vital sign reading with value, unit, date, and sample count. Used in 90-day and 30-day history containers."@en ;
399
+ rdfs:subClassOf fhir:Observation .
400
+
401
+ health:HRVReading a owl:Class ;
402
+ rdfs:label "HRV Reading"@en ;
403
+ rdfs:comment "A single heart rate variability (SDNN) observation with timestamp and optional source."@en ;
404
+ rdfs:subClassOf fhir:Observation .
405
+
406
+ health:BloodPressureReading a owl:Class ;
407
+ rdfs:label "Blood Pressure Reading"@en ;
408
+ rdfs:comment "A single blood pressure observation with systolic and diastolic components, timestamp, and optional source."@en ;
409
+ rdfs:subClassOf fhir:Observation .
410
+
411
+ health:VitalSignReading a owl:Class ;
412
+ rdfs:label "Vital Sign Reading"@en ;
413
+ rdfs:comment "A single vital sign observation with value, unit, measurement period, timestamp, and source. Used for baseline readings and VO2 Max history entries."@en ;
414
+ rdfs:subClassOf fhir:Observation .
415
+
416
+ health:DailyActivitySnapshot a owl:Class ;
417
+ rdfs:label "Daily Activity Snapshot"@en ;
418
+ rdfs:comment "A single day's activity data: steps, active energy, exercise minutes, and stand hours."@en ;
419
+ rdfs:subClassOf prov:Entity .
420
+
421
+ health:DailySleepSnapshot a owl:Class ;
422
+ rdfs:label "Daily Sleep Snapshot"@en ;
423
+ rdfs:comment "A single night's sleep data: duration in hours and quality classification."@en ;
424
+ rdfs:subClassOf prov:Entity .
425
+
426
+ # ============================================================================
427
+ # History Container Properties (v2.0)
428
+ # ============================================================================
429
+ # Time-series containers emitted by HealthProfileSerializer for trend analysis.
430
+ # Each property links a HealthProfile to an ordered list of readings.
431
+
432
+ health:restingHeartRateHistory a owl:ObjectProperty ;
433
+ rdfs:label "Resting Heart Rate History"@en ;
434
+ rdfs:comment "Time series of daily resting heart rate readings (90-day lookback). Each entry is a DailyVitalReading with date and value."@en ;
435
+ rdfs:domain health:HealthProfile ;
436
+ rdfs:range health:DailyVitalReading .
437
+
438
+ health:walkingHeartRateHistory a owl:ObjectProperty ;
439
+ rdfs:label "Walking Heart Rate History"@en ;
440
+ rdfs:comment "Time series of daily walking heart rate readings (90-day lookback)."@en ;
441
+ rdfs:domain health:HealthProfile ;
442
+ rdfs:range health:DailyVitalReading .
443
+
444
+ health:hrvHistory a owl:ObjectProperty ;
445
+ rdfs:label "HRV History"@en ;
446
+ rdfs:comment "Time series of heart rate variability (SDNN) readings (7-day lookback)."@en ;
447
+ rdfs:domain health:HealthProfile ;
448
+ rdfs:range health:HRVReading .
449
+
450
+ health:bloodPressureHistory a owl:ObjectProperty ;
451
+ rdfs:label "Blood Pressure History"@en ;
452
+ rdfs:comment "Time series of blood pressure readings (30-day lookback). Each entry has systolic and diastolic values."@en ;
453
+ rdfs:domain health:HealthProfile ;
454
+ rdfs:range health:BloodPressureReading .
455
+
456
+ health:vo2MaxHistory a owl:ObjectProperty ;
457
+ rdfs:label "VO2 Max History"@en ;
458
+ rdfs:comment "Time series of VO2 Max readings (180-day lookback)."@en ;
459
+ rdfs:domain health:HealthProfile ;
460
+ rdfs:range health:VitalSignReading .
461
+
462
+ health:bodyMassHistory a owl:ObjectProperty ;
463
+ rdfs:label "Body Mass History"@en ;
464
+ rdfs:comment "Time series of daily body mass readings (30-day lookback)."@en ;
465
+ rdfs:domain health:HealthProfile ;
466
+ rdfs:range health:DailyVitalReading .
467
+
468
+ health:dailyActivityHistory a owl:ObjectProperty ;
469
+ rdfs:label "Daily Activity History"@en ;
470
+ rdfs:comment "Time series of daily activity snapshots (90-day lookback). Steps, exercise, calories, stand hours per day."@en ;
471
+ rdfs:domain health:HealthProfile ;
472
+ rdfs:range health:DailyActivitySnapshot .
473
+
474
+ health:dailySleepHistory a owl:ObjectProperty ;
475
+ rdfs:label "Daily Sleep History"@en ;
476
+ rdfs:comment "Time series of daily sleep snapshots (90-day lookback). Duration and quality per night."@en ;
477
+ rdfs:domain health:HealthProfile ;
478
+ rdfs:range health:DailySleepSnapshot .
479
+
480
+ # ============================================================================
481
+ # Self-Report Base Class (v2.1)
482
+ # ============================================================================
483
+ #
484
+ # Base class for patient-reported daily check-ins and self-assessments.
485
+ # Apps extend this with domain-specific response data.
486
+
487
+ health:SelfReport a owl:Class ;
488
+ rdfs:label "Self Report"@en ;
489
+ rdfs:comment "Base class for patient-reported daily check-ins and self-assessments. Provides common structure for timestamped self-reports across health domains. Apps extend this with domain-specific response data. Examples: medication adherence, symptom tracking, mood logging, sleep records."@en ;
490
+ rdfs:subClassOf prov:Entity .
491
+
492
+ health:reportDate a owl:DatatypeProperty ;
493
+ rdfs:label "Report Date"@en ;
494
+ rdfs:comment "When the self-report was recorded."@en ;
495
+ rdfs:domain health:SelfReport ;
496
+ rdfs:range xsd:dateTime .
497
+
498
+ health:reportType a owl:DatatypeProperty ;
499
+ rdfs:label "Report Type"@en ;
500
+ rdfs:comment "Category of self-report (e.g., medication_adherence, symptom_tracking, mood, sleep)."@en ;
501
+ rdfs:domain health:SelfReport ;
502
+ rdfs:range xsd:string .
503
+
504
+ health:completionStatus a owl:DatatypeProperty ;
505
+ rdfs:label "Completion Status"@en ;
506
+ rdfs:comment "Whether the report is complete, partial, or skipped."@en ;
507
+ rdfs:domain health:SelfReport ;
508
+ rdfs:range xsd:string .
509
+
510
+ health:reportContext a owl:DatatypeProperty ;
511
+ rdfs:label "Report Context"@en ;
512
+ rdfs:comment "What tracking plan or list this report relates to (free-form reference)."@en ;
513
+ rdfs:domain health:SelfReport ;
514
+ rdfs:range xsd:string .
515
+
516
+ health:reportNotes a owl:DatatypeProperty ;
517
+ rdfs:label "Report Notes"@en ;
518
+ rdfs:comment "Optional free-text notes from the patient."@en ;
519
+ rdfs:domain health:SelfReport ;
520
+ rdfs:range xsd:string .
521
+
522
+ # ============================================================================
523
+ # Annotation Properties
524
+ # ============================================================================
525
+
526
+ health:snomedCode a owl:AnnotationProperty ;
527
+ rdfs:label "SNOMED CT Code"@en ;
528
+ rdfs:comment "Links a wellness property to its SNOMED CT concept"@en .
529
+
530
+ health:loincCode a owl:AnnotationProperty ;
531
+ rdfs:label "LOINC Code"@en ;
532
+ rdfs:comment "Links a wellness property to its LOINC observation code"@en .
533
+
534
+ health:unit a owl:AnnotationProperty ;
535
+ rdfs:label "Display Unit"@en ;
536
+ rdfs:comment "Human-readable unit of measurement"@en .
537
+
538
+ health:ucumCode a owl:AnnotationProperty ;
539
+ rdfs:label "UCUM Code"@en ;
540
+ rdfs:comment "Unified Code for Units of Measure code"@en .
541
+
542
+ health:trendPolarity a owl:AnnotationProperty ;
543
+ rdfs:label "Trend Polarity"@en ;
544
+ rdfs:comment "Whether an increase in this metric is generally favorable ('higher_is_better'), unfavorable ('lower_is_better'), or context-dependent ('neutral'). Used by presentation layers to determine trend arrow color semantics. This is a general heuristic — individual clinical context may differ."@en .
545
+
546
+ # ============================================================================
547
+ # VO2 Max Statistics Properties (v1.7)
548
+ # ============================================================================
549
+ # Statistical analysis of VO2 Max readings with trend detection and fitness
550
+ # classification. Part of the dual-path wellness data pattern where rich
551
+ # statistics are preferred when available, with fallback to single values.
552
+
553
+ health:vo2Mean a owl:DatatypeProperty ;
554
+ rdfs:label "Mean VO2 Max"@en ;
555
+ rdfs:comment "Average VO2 Max over measurement period (mL/kg/min)"@en ;
556
+ rdfs:domain health:VO2MaxStatistics ;
557
+ rdfs:range xsd:double ;
558
+ health:unit "mL/kg/min" ;
559
+ health:ucumCode "mL/kg/min" .
560
+
561
+ health:vo2Min a owl:DatatypeProperty ;
562
+ rdfs:label "Minimum VO2 Max"@en ;
563
+ rdfs:comment "Lowest VO2 Max reading in measurement period"@en ;
564
+ rdfs:domain health:VO2MaxStatistics ;
565
+ rdfs:range xsd:double ;
566
+ health:unit "mL/kg/min" .
567
+
568
+ health:vo2MaxValue a owl:DatatypeProperty ;
569
+ rdfs:label "Maximum VO2 Max"@en ;
570
+ rdfs:comment "Highest VO2 Max reading in measurement period"@en ;
571
+ rdfs:domain health:VO2MaxStatistics ;
572
+ rdfs:range xsd:double ;
573
+ health:unit "mL/kg/min" .
574
+
575
+ health:vo2SampleCount a owl:DatatypeProperty ;
576
+ rdfs:label "Sample Count"@en ;
577
+ rdfs:comment "Number of VO2 Max measurements in the period"@en ;
578
+ rdfs:domain health:VO2MaxStatistics ;
579
+ rdfs:range xsd:integer .
580
+
581
+ health:vo2DaysCovered a owl:DatatypeProperty ;
582
+ rdfs:label "Days Covered"@en ;
583
+ rdfs:comment "Number of unique days with VO2 Max measurements"@en ;
584
+ rdfs:domain health:VO2MaxStatistics ;
585
+ rdfs:range xsd:integer .
586
+
587
+ health:vo2TrendDirection a owl:DatatypeProperty ;
588
+ rdfs:label "VO2 Trend Direction"@en ;
589
+ rdfs:comment "Trend direction based on comparison of first half vs second half of readings: 'improving', 'declining', 'stable', or 'unknown'. Uses 3% threshold (1 MET ≈ 3.5 mL/kg/min is clinically meaningful)."@en ;
590
+ rdfs:domain health:VO2MaxStatistics ;
591
+ rdfs:range xsd:string .
592
+
593
+ health:vo2PercentageChange a owl:DatatypeProperty ;
594
+ rdfs:label "Percentage Change"@en ;
595
+ rdfs:comment "Percentage change from oldest to newest reading period"@en ;
596
+ rdfs:domain health:VO2MaxStatistics ;
597
+ rdfs:range xsd:double .
598
+
599
+ health:fitnessClassification a owl:DatatypeProperty ;
600
+ rdfs:label "Fitness Classification"@en ;
601
+ rdfs:comment "Cardiorespiratory fitness level based on mean VO2 Max: 'veryPoor' (<20), 'poor' (20-29), 'fair' (30-34), 'good' (35-44), 'excellent' (45-54), 'superior' (≥55). Currently age/sex agnostic; future versions may use demographics for personalized classification."@en ;
602
+ rdfs:domain health:VO2MaxStatistics ;
603
+ rdfs:range xsd:string .
604
+
605
+ health:isSparseData a owl:DatatypeProperty ;
606
+ rdfs:label "Sparse Data Indicator"@en ;
607
+ rdfs:comment "True when measurements are limited (< 3 samples or < 30 days covered). Used to trigger messaging about VO2 Max measurement requirements."@en ;
608
+ rdfs:domain health:VO2MaxStatistics ;
609
+ rdfs:range xsd:boolean .
610
+
611
+ # ============================================================================
612
+ # Shared Statistics Temporal Properties (v1.8)
613
+ # ============================================================================
614
+
615
+ health:periodStart a owl:DatatypeProperty ;
616
+ rdfs:label "Period Start"@en ;
617
+ rdfs:comment "Start date of the statistical measurement period."@en ;
618
+ rdfs:range xsd:dateTime .
619
+
620
+ health:periodEnd a owl:DatatypeProperty ;
621
+ rdfs:label "Period End"@en ;
622
+ rdfs:comment "End date of the statistical measurement period."@en ;
623
+ rdfs:range xsd:dateTime .
624
+
625
+ # ============================================================================
626
+ # HRV Statistics Properties (v1.8)
627
+ # ============================================================================
628
+
629
+ health:hrvSampleCount a owl:DatatypeProperty ;
630
+ rdfs:label "HRV Sample Count"@en ;
631
+ rdfs:comment "Number of HRV readings in the period."@en ;
632
+ rdfs:domain health:HRVStatistics ;
633
+ rdfs:range xsd:integer .
634
+
635
+ health:hrvDaysCovered a owl:DatatypeProperty ;
636
+ rdfs:label "HRV Days Covered"@en ;
637
+ rdfs:comment "Number of unique days with HRV measurements."@en ;
638
+ rdfs:domain health:HRVStatistics ;
639
+ rdfs:range xsd:integer .
640
+
641
+ health:hrvMean a owl:DatatypeProperty ;
642
+ rdfs:label "Mean HRV"@en ;
643
+ rdfs:comment "Average HRV (SDNN) over the measurement period (ms)."@en ;
644
+ rdfs:domain health:HRVStatistics ;
645
+ rdfs:range xsd:double ;
646
+ health:unit "ms" .
647
+
648
+ health:hrvMedian a owl:DatatypeProperty ;
649
+ rdfs:label "Median HRV"@en ;
650
+ rdfs:comment "Median HRV (SDNN) over the measurement period (ms)."@en ;
651
+ rdfs:domain health:HRVStatistics ;
652
+ rdfs:range xsd:double ;
653
+ health:unit "ms" .
654
+
655
+ health:hrvStdDev a owl:DatatypeProperty ;
656
+ rdfs:label "HRV Standard Deviation"@en ;
657
+ rdfs:comment "Standard deviation of HRV readings over the measurement period (ms)."@en ;
658
+ rdfs:domain health:HRVStatistics ;
659
+ rdfs:range xsd:double ;
660
+ health:unit "ms" .
661
+
662
+ health:hrvMin a owl:DatatypeProperty ;
663
+ rdfs:label "Minimum HRV"@en ;
664
+ rdfs:comment "Lowest HRV reading in the period (ms)."@en ;
665
+ rdfs:domain health:HRVStatistics ;
666
+ rdfs:range xsd:double ;
667
+ health:unit "ms" .
668
+
669
+ health:hrvMax a owl:DatatypeProperty ;
670
+ rdfs:label "Maximum HRV"@en ;
671
+ rdfs:comment "Highest HRV reading in the period (ms)."@en ;
672
+ rdfs:domain health:HRVStatistics ;
673
+ rdfs:range xsd:double ;
674
+ health:unit "ms" .
675
+
676
+ health:hrvPercentile25 a owl:DatatypeProperty ;
677
+ rdfs:label "HRV 25th Percentile"@en ;
678
+ rdfs:comment "25th percentile of HRV readings over the measurement period (ms)."@en ;
679
+ rdfs:domain health:HRVStatistics ;
680
+ rdfs:range xsd:double ;
681
+ health:unit "ms" .
682
+
683
+ health:hrvPercentile75 a owl:DatatypeProperty ;
684
+ rdfs:label "HRV 75th Percentile"@en ;
685
+ rdfs:comment "75th percentile of HRV readings over the measurement period (ms)."@en ;
686
+ rdfs:domain health:HRVStatistics ;
687
+ rdfs:range xsd:double ;
688
+ health:unit "ms" .
689
+
690
+ health:hrvTrendDirection a owl:DatatypeProperty ;
691
+ rdfs:label "HRV Trend Direction"@en ;
692
+ rdfs:comment "Trend direction for HRV: improving, declining, stable, or unknown."@en ;
693
+ rdfs:domain health:HRVStatistics ;
694
+ rdfs:range xsd:string .
695
+
696
+ # ============================================================================
697
+ # Blood Pressure Statistics Properties (v1.8)
698
+ # ============================================================================
699
+
700
+ health:bpSampleCount a owl:DatatypeProperty ;
701
+ rdfs:label "BP Sample Count"@en ;
702
+ rdfs:comment "Number of blood pressure readings in the period."@en ;
703
+ rdfs:domain health:BPStatistics ;
704
+ rdfs:range xsd:integer .
705
+
706
+ health:bpMeanSystolic a owl:DatatypeProperty ;
707
+ rdfs:label "Mean Systolic BP"@en ;
708
+ rdfs:comment "Average systolic blood pressure over the measurement period (mmHg)."@en ;
709
+ rdfs:domain health:BPStatistics ;
710
+ rdfs:range xsd:double ;
711
+ health:unit "mmHg" .
712
+
713
+ health:bpMeanDiastolic a owl:DatatypeProperty ;
714
+ rdfs:label "Mean Diastolic BP"@en ;
715
+ rdfs:comment "Average diastolic blood pressure over the measurement period (mmHg)."@en ;
716
+ rdfs:domain health:BPStatistics ;
717
+ rdfs:range xsd:double ;
718
+ health:unit "mmHg" .
719
+
720
+ health:bpMinSystolic a owl:DatatypeProperty ;
721
+ rdfs:label "Minimum Systolic BP"@en ;
722
+ rdfs:comment "Lowest systolic blood pressure reading in the period (mmHg)."@en ;
723
+ rdfs:domain health:BPStatistics ;
724
+ rdfs:range xsd:double ;
725
+ health:unit "mmHg" .
726
+
727
+ health:bpMaxSystolic a owl:DatatypeProperty ;
728
+ rdfs:label "Maximum Systolic BP"@en ;
729
+ rdfs:comment "Highest systolic blood pressure reading in the period (mmHg)."@en ;
730
+ rdfs:domain health:BPStatistics ;
731
+ rdfs:range xsd:double ;
732
+ health:unit "mmHg" .
733
+
734
+ health:bpMinDiastolic a owl:DatatypeProperty ;
735
+ rdfs:label "Minimum Diastolic BP"@en ;
736
+ rdfs:comment "Lowest diastolic blood pressure reading in the period (mmHg)."@en ;
737
+ rdfs:domain health:BPStatistics ;
738
+ rdfs:range xsd:double ;
739
+ health:unit "mmHg" .
740
+
741
+ health:bpMaxDiastolic a owl:DatatypeProperty ;
742
+ rdfs:label "Maximum Diastolic BP"@en ;
743
+ rdfs:comment "Highest diastolic blood pressure reading in the period (mmHg)."@en ;
744
+ rdfs:domain health:BPStatistics ;
745
+ rdfs:range xsd:double ;
746
+ health:unit "mmHg" .
747
+
748
+ health:bpCategory a owl:DatatypeProperty ;
749
+ rdfs:label "BP Category"@en ;
750
+ rdfs:comment "AHA blood pressure category based on mean values: normal, elevated, hypertension_stage1, hypertension_stage2, hypertensive_crisis."@en ;
751
+ rdfs:domain health:BPStatistics ;
752
+ rdfs:range xsd:string .
753
+
754
+ # ============================================================================
755
+ # Temporal Trend Classes (v1.5)
756
+ # ============================================================================
757
+ # Design rationale: clinical:LabTestSeries captures discrete lab samples over
758
+ # clinical visits as a long-lived container. health:MetricTrend is a computed
759
+ # observation over a bounded time window from continuous daily device data —
760
+ # more like a derived fact than a container. They share trendDirection and
761
+ # trendConfidence vocabulary intentionally for cross-domain consistency.
762
+ # Values use objective direction (increasing/decreasing) rather than
763
+ # value-laden terms (improving/declining) — the ontology describes *what*
764
+ # happened; the presentation layer interprets whether it's good or bad.
765
+
766
+ health:MetricTrend a owl:Class ;
767
+ rdfs:label "Metric Trend" ;
768
+ rdfs:comment "A time-bounded trend for a single wellness metric, computed from a series of observations. Captures direction, magnitude, and comparison period." ;
769
+ rdfs:subClassOf prov:Entity .
770
+
771
+ # --- MetricTrend Properties ---
772
+
773
+ health:trendMetric a owl:ObjectProperty ;
774
+ rdfs:label "Trend Metric" ;
775
+ rdfs:comment "The wellness property this trend describes (e.g., health:restingHeartRate)" ;
776
+ rdfs:domain health:MetricTrend .
777
+
778
+ health:trendDirection a owl:DatatypeProperty ;
779
+ rdfs:label "Trend Direction" ;
780
+ rdfs:comment "Direction of change: increasing, decreasing, stable, or insufficient_data. Matches clinical:trendDirection values for cross-domain consistency. Semantic interpretation (whether 'increasing' is good or bad) is metric-specific and handled at the presentation layer, not the ontology layer." ;
781
+ rdfs:domain health:MetricTrend ;
782
+ rdfs:range xsd:string .
783
+
784
+ health:trendMagnitude a owl:DatatypeProperty ;
785
+ rdfs:label "Trend Magnitude" ;
786
+ rdfs:comment "Percentage change between comparison periods (e.g., -5.6 means a 5.6% decrease)" ;
787
+ rdfs:domain health:MetricTrend ;
788
+ rdfs:range xsd:decimal .
789
+
790
+ health:trendPeriodStart a owl:DatatypeProperty ;
791
+ rdfs:label "Trend Period Start" ;
792
+ rdfs:domain health:MetricTrend ;
793
+ rdfs:range xsd:dateTime .
794
+
795
+ health:trendPeriodEnd a owl:DatatypeProperty ;
796
+ rdfs:label "Trend Period End" ;
797
+ rdfs:domain health:MetricTrend ;
798
+ rdfs:range xsd:dateTime .
799
+
800
+ health:trendBaselineValue a owl:DatatypeProperty ;
801
+ rdfs:label "Baseline Value" ;
802
+ rdfs:comment "The reference value (e.g., 90-day average) this trend is compared against" ;
803
+ rdfs:domain health:MetricTrend ;
804
+ rdfs:range xsd:decimal .
805
+
806
+ health:trendCurrentValue a owl:DatatypeProperty ;
807
+ rdfs:label "Current Value" ;
808
+ rdfs:comment "The current period average (e.g., 7-day average)" ;
809
+ rdfs:domain health:MetricTrend ;
810
+ rdfs:range xsd:decimal .
811
+
812
+ health:trendConfidence a owl:DatatypeProperty ;
813
+ rdfs:label "Trend Confidence" ;
814
+ rdfs:comment "Confidence in the trend: high (>30 days data), medium (14-30 days), low (<14 days)" ;
815
+ rdfs:domain health:MetricTrend ;
816
+ rdfs:range xsd:string .
817
+
818
+ health:trendSource a owl:ObjectProperty ;
819
+ rdfs:label "Trend Data Source" ;
820
+ rdfs:comment "The data source (device, app, or system) that produced the underlying observations. Links to cascade:DataSource when available; for inline use, a blank node with cascade:sourceName is acceptable." ;
821
+ rdfs:domain health:MetricTrend ;
822
+ rdfs:range cascade:DataSource .
823
+
824
+ # ============================================================================
825
+ # Statistics Container Linking Properties (v2.2)
826
+ # ============================================================================
827
+ # ObjectProperties used by CheckupSerializer to link an intake form or
828
+ # wellness profile to its statistical summary nodes.
829
+
830
+ health:hasHRVStatistics a owl:ObjectProperty ;
831
+ rdfs:label "has HRV statistics"@en ;
832
+ rdfs:comment "Links a wellness profile to its HRV statistical summary."@en ;
833
+ rdfs:range health:HRVStatistics .
834
+
835
+ health:hasBPStatistics a owl:ObjectProperty ;
836
+ rdfs:label "has BP statistics"@en ;
837
+ rdfs:comment "Links a wellness profile to its blood pressure statistical summary."@en ;
838
+ rdfs:range health:BPStatistics .
839
+
840
+ # ============================================================================
841
+ # Standard Code Reference Table (for documentation)
842
+ # ============================================================================
843
+ #
844
+ # | Metric | Health Property | SNOMED CT | LOINC |
845
+ # |-----------------------|------------------------------|-------------|----------|
846
+ # | Resting Heart Rate | health:restingHeartRate | 364075005 | 40443-4 |
847
+ # | Walking Heart Rate | health:walkingHeartRate | 364075005 | 89270-3 |
848
+ # | HRV (SDNN) | health:heartRateVariability | 80404004 | 80404-7 |
849
+ # | Blood Pressure | health:bloodPressure | 75367002 | 85354-9 |
850
+ # | Systolic BP | (component) | 271649006 | 8480-6 |
851
+ # | Diastolic BP | (component) | 271650006 | 8462-4 |
852
+ # | Respiratory Rate | health:respiratoryRate | 86290005 | 9279-1 |
853
+ # | VO2 Max | health:vo2Max | 251880009 | 60842-2 |
854
+ # | Walking Steadiness | health:walkingSteadiness | 364832000 | --- |
855
+ # | Average Daily Steps | health:averageDailySteps | 68130003 | 41950-7 |
856
+ # | Active Energy Burned | health:activeEnergyBurnedKcal| 251833007 | 41981-2 |
857
+ # | Exercise Minutes | health:exerciseMinutesWeekly | 68130003 | 73985-4 |
858
+ # | Stand Hours | health:standHoursDaily | --- | --- |
859
+ # | Sleep Duration | health:averageDurationHours | 248263006 | 93832-4 |