Add HealthMeasurement shape (Schema.org Health-Lifesci subset)#63
Add HealthMeasurement shape (Schema.org Health-Lifesci subset)#63jeswr wants to merge 3 commits intosolid:mainfrom
Conversation
Adds a SHACL shape for schema:Observation focused on the common health and fitness measurements emitted by Apple Health, Google Fit, and Strava exports — heart rate, steps, sleep duration, body weight, distance, exercise duration, and energy burned. Constrains schema:value, schema:unitCode, schema:unitText, schema:observationDate, schema:observationAbout, schema:measuredProperty, and schema:measurementMethod. Cites HL7 FHIR Observation as a heavier clinical alternative without depending on it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- schema:value: accept xsd:decimal, xsd:integer, xsd:double, or xsd:float so that integer step counts and double-precision sensor readings are not rejected by the exact sh:datatype match. - schema:observationDate: accept either xsd:dateTime or xsd:date so daily aggregates (weight, daily step total) validate alongside instantaneous readings. - schema:measurementMethod: add sh:maxCount 1 and an IRI-or-literal node-kind constraint so it matches the rest of the shape. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- schema:unitCode and schema:measurementMethod: replace the longhand sh:or node-kind disjunctions with the built-in sh:IRIOrLiteral so language-tagged strings are accepted and intent is clearer. - Top-level sh:description now flags that schema:Observation and the schema:observation* properties currently sit in the Schema.org pending area and that consumer-health exporters do not emit them natively (an importer is expected to map proprietary formats to this shape). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds a new SHACL NodeShape intended to validate a single health/fitness measurement represented as a Schema.org Observation, to support importing common consumer health exports into Solid Pods.
Changes:
- Introduces
HealthMeasurementShapetargetingschema:Observation. - Adds property constraints for numeric
schema:value, unit fields, observation timestamp/date, subject (observationAbout), measured property, and method/device.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @prefix schema: <https://schema.org/> . | ||
| @prefix sh: <http://www.w3.org/ns/shacl#> . | ||
| @prefix vs: <http://www.w3.org/2003/06/sw-vocab-status/ns#> . | ||
| @prefix xsd: <http://www.w3.org/2001/XMLSchema#> . | ||
|
|
||
| @prefix health_measurement_shape: <https://solidproject.org/shapes/health_measurement#> . | ||
|
|
||
| health_measurement_shape:HealthMeasurementShape | ||
| a sh:NodeShape ; | ||
| sh:targetClass schema:Observation ; | ||
| sh:name "Health Measurement Shape" ; | ||
| sh:description "SHACL shape for a single health or fitness measurement modelled as a Schema.org Observation. The intended representation for the common cases consumer health and fitness exports (Apple Health, Google Fit, Strava) describe — heart rate, steps, sleep duration, body weight, distance, exercise duration, and energy burned. Note: schema:Observation and the schema:observation* properties currently sit in the pending area of Schema.org (https://pending.schema.org/); native exporters typically emit proprietary formats and an importer is expected to map them to this shape." ; |
There was a problem hiding this comment.
This shape uses only the https://schema.org/ namespace. A lot of RDF data (and some shapes in this repo) still use the legacy http://schema.org/ IRIs, so instances/properties like http://schema.org/Observation or http://schema.org/value would not be targeted/validated by this shape. Consider adding a schema_http: prefix and accepting both forms (e.g., dual sh:targetClass entries, and sh:path via sh:alternativePath or the “legacy predicate” pattern used in shapes/chat.ttl).
| sh:path schema:observationAbout ; | ||
| sh:nodeKind sh:IRI ; | ||
| sh:maxCount 1 ; | ||
| sh:name "Observation About" ; | ||
| sh:description "The entity the observation is about. For personal health and fitness data this is typically the user's WebID (Schema.org schema:observationAbout)." ; | ||
| sh:codeIdentifier "observationAbout"; |
There was a problem hiding this comment.
The PR description lists schema:about as the link to the WebID/agent, but this shape uses schema:observationAbout. If schema:about is what consumers/exporters will emit, the shape should accept it (or the PR description should be updated to match schema:observationAbout).
| sh:property [ | ||
| sh:path schema:value ; | ||
| sh:or ( | ||
| [ sh:datatype xsd:decimal ] | ||
| [ sh:datatype xsd:integer ] | ||
| [ sh:datatype xsd:double ] | ||
| [ sh:datatype xsd:float ] | ||
| ) ; | ||
| sh:maxCount 1 ; | ||
| sh:name "Value" ; | ||
| sh:description "Numeric value of the measurement (e.g., 72 for a heart-rate reading, 8500 for a step count, 5.2 for a kilometre distance). May be xsd:decimal, xsd:integer, xsd:double, or xsd:float." ; | ||
| sh:codeIdentifier "value"; | ||
| ] ; |
There was a problem hiding this comment.
Several properties described as core constraints in the PR (e.g., schema:value, schema:unitCode, schema:observationDate, schema:observationAbout) only have sh:maxCount here, so an Observation with none of these fields would still conform. If these are intended to be required for a “per-measurement” node, add appropriate sh:minCount 1 constraints (at least for value/date/about, and likely measuredProperty/unitCode depending on the metric).
Adds a SHACL shape for a single health / fitness measurement on a Solid Pod, covering the common cases an Apple Health / Google Fit / Strava export emits.
Ontology basis
Schema.org Health-Lifesci extension —
MedicalEntity+Observation+QuantitativeValueprovide the foundation. For activity / fitness specifically, the shape composes with Schema.orgExerciseAction,Distance,Duration, andEnergy. FHIR Observation maps cleanly to this for clinical use cases but is intentionally not depended on — that's a separate, heavier-duty modelling effort.Scope
A focused per-measurement shape — heart rate, steps, sleep, weight, distance, duration, calories. Constraints:
schema:value(xsd:decimal)schema:unitCode(UN/CEFACT or QUDT — kept open viash:IRIOrLiteralso existing exporters' choices still pass)schema:observationDate(xsd:dateTime)schema:about(the WebID / agent the measurement belongs to)schema:measurementMethoddocumentedThe pending Schema.org Observation modelling refresh is referenced in the shape's comment block — when it lands, this shape can tighten without breaking consumers.
Consumer use cases
Self-review
Reviewed locally with
roborev review --localbefore opening. Two follow-up commits address its findings (sh:IRIOrLiteralforunitCodeflexibility; loosenedvalueandobservationDatedatatype constraints to match real-world exporters; tightenedmeasurementMethod).Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com