-
Notifications
You must be signed in to change notification settings - Fork 7
W3DS Health: observation-model health ontologies (34 schemas) #1099
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
14fae82
eafaadf
ac5f05a
a9114b0
c826c81
3316e96
93ea25a
b9c9c68
d9e87d8
32005bb
fa8c2bc
debbe4a
0faeab5
a61f754
114b01b
e33e761
2845acd
e65184c
84f168e
475d1e6
654d798
90752d3
b6ff019
3643e1b
0818ab7
b76100f
33cf121
e976bf8
9ca2538
785965f
d4fcdd8
3dcd244
66b363f
58a922e
d6613a1
0d79837
7c62485
0ad4626
06e6ec8
b459830
c1380cf
f79effa
a6112c5
31d9fa2
bf1ef17
f9060b0
690b082
298e913
ca84c14
af98b4f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,120 @@ | ||
| { | ||
| "$schema": "http://json-schema.org/draft-07/schema#", | ||
| "schemaId": "915892f9-693b-4f4f-95e6-17f9ceeb55ff", | ||
| "title": "ActiveEnergySeries", | ||
| "description": "Raw active energy burned samples over one local day from ONE device. One envelope per (person × day × device) — multiple devices coexist as separate envelopes; merging is a reader-side presentation concern. Sample = [startEpochSeconds, endEpochSeconds, value], epoch = UTC seconds, utcOffset gives the person's local offset. `stats` is DERIVED from samples (cheap-read preview) — samples are the source of truth. Canonical unit: kcal.", | ||
| "type": "object", | ||
| "properties": { | ||
| "subject": { | ||
| "type": "string", | ||
| "description": "@-prefixed eName of the person this data is about" | ||
| }, | ||
| "device": { | ||
| "type": [ | ||
| "string", | ||
| "null" | ||
| ], | ||
| "description": "w3id (@eName) of the measuring device's OWN eVault, where its Device passport lives; null if unknown" | ||
| }, | ||
| "provenance": { | ||
| "type": "object", | ||
| "description": "Import provenance. Vendor identity lives HERE only (source), never in metric keys.", | ||
| "properties": { | ||
| "source": { | ||
| "type": "string" | ||
| }, | ||
| "platform": { | ||
| "type": "string", | ||
| "description": "w3id (@eName) of the platform that wrote this envelope — machine-readable authorship; resolve it to read that platform's self-description" | ||
| }, | ||
| "externalId": { | ||
| "type": "string" | ||
| }, | ||
| "sourceName": { | ||
| "type": "string" | ||
| }, | ||
| "deviceSignature": { | ||
| "type": "string" | ||
| } | ||
| }, | ||
| "required": [ | ||
| "source" | ||
| ] | ||
| }, | ||
| "dedupKey": { | ||
| "type": "string", | ||
| "description": "Writer's idempotency key, unique within this ontology on the vault" | ||
| }, | ||
| "contentHash": { | ||
| "type": "string", | ||
| "description": "Writer-maintained md5 of the payload; recomputed on every rewrite" | ||
| }, | ||
| "updatedAt": { | ||
| "type": "string" | ||
| }, | ||
| "date": { | ||
| "type": "string", | ||
| "pattern": "^\\d{4}-\\d{2}-\\d{2}$", | ||
| "description": "local day — chunk key" | ||
| }, | ||
| "utcOffset": { | ||
| "type": "string", | ||
| "pattern": "^[+-]\\d{2}:\\d{2}$" | ||
| }, | ||
| "unit": { | ||
| "type": "string", | ||
| "const": "kcal" | ||
| }, | ||
| "sampleType": { | ||
| "type": "string", | ||
| "const": "interval" | ||
| }, | ||
| "samples": { | ||
| "type": "array", | ||
| "items": { | ||
| "type": "array", | ||
| "items": { | ||
| "type": "number" | ||
| }, | ||
| "minItems": 2, | ||
| "maxItems": 3 | ||
| } | ||
|
Comment on lines
+72
to
+81
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "== schema snippets =="
for f in services/ontology/schemas/activeEnergySeries.json services/ontology/schemas/basalEnergySeries.json services/ontology/schemas/cyclingDistanceSeries.json services/ontology/schemas/environmentalAudioSeries.json services/ontology/schemas/exerciseMinutesSeries.json services/ontology/schemas/flightsClimbedSeries.json services/ontology/schemas/headphoneAudioSeries.json services/ontology/schemas/heartRateSeries.json services/ontology/schemas/heartRateVariabilitySeries.json services/ontology/schemas/oxygenSaturationSeries.json services/ontology/schemas/respiratoryRateSeries.json; do
echo "--- $f"
sed -n '55,85p' "$f"
done
echo
echo "== schema header/descriptors around samples =="
for f in services/ontology/schemas/activeEnergySeries.json services/ontology/schemas/basalEnergySeries.json services/ontology/schemas/cyclingDistanceSeries.json services/ontology/schemas/environmentalAudioSeries.json services/ontology/schemas/exerciseMinutesSeries.json services/ontology/schemas/flightsClimbedSeries.json services/ontology/schemas/headphoneAudioSeries.json services/ontology/schemas/heartRateSeries.json services/ontology/schemas/heartRateVariabilitySeries.json services/ontology/schemas/oxygenSaturationSeries.json services/ontology/schemas/respiratoryRateSeries.json; do
echo "--- $f"
sed -n '1,90p' "$f" | grep -n -A2 -B2 -i 'samples\|interval\|point\|series\|timestamp\|epoch\|value' || true
done
echo
echo "== references to samples or series schemas =="
rg -n 'samples|activeEnergySeries|basalEnergySeries|cyclingDistanceSeries|environmentalAudioSeries|exerciseMinutesSeries|flightsClimbedSeries|headphoneAudioSeries|heartRateSeries|heartRateVariabilitySeries|oxygenSaturationSeries|respiratoryRateSeries' services/ontology -g '!*.lock' | head -200Repository: MetaState-Prototype-Project/prototype Length of output: 30154 🌐 Web query:
💡 Result: In JSON Schema draft-07, the "additionalItems" keyword is used to control whether an array can contain items beyond those defined in a tuple [1][2]. Tuple validation occurs when the "items" keyword is provided as an array of schemas, where each schema corresponds to an element at a specific index [2][3]. When using "items" as an array (a tuple): - The "items" keyword defines the schemas for the initial elements of the array [2][3]. - The "additionalItems" keyword defines the schema that any subsequent elements (those at indices greater than the number of schemas in the "items" array) must validate against [1][2]. - Setting "additionalItems" to false explicitly forbids any elements beyond the number of schemas defined in the "items" array [2]. For example, a schema defined as: { "$schema": "http://json-schema.org/draft-07/schema#", "items": [ { "type": "boolean" }, { "type": "number" } ], "additionalItems": false } will validate arrays like [true, 10] but will fail for arrays like [true, 10, "extra"] [2]. Note that "additionalItems" only has an effect when "items" is an array [2]. If "items" is a single schema (object form) or is omitted, "additionalItems" is ignored by the validator [2]. As of later versions of JSON Schema (starting with the 2020-12 specification), tuple validation is handled by the "prefixItems" keyword, and "additionalItems" has been replaced or restructured to clarify its behavior [4][5]. Citations:
Enforce the documented sample tuple arity. The 📍 Affects 11 files
🤖 Prompt for AI Agents |
||
| }, | ||
| "stats": { | ||
| "type": "object", | ||
| "description": "DERIVED from samples — preview only", | ||
| "properties": { | ||
| "min": { | ||
| "type": "number" | ||
| }, | ||
| "max": { | ||
| "type": "number" | ||
| }, | ||
| "avg": { | ||
| "type": "number" | ||
| }, | ||
| "sum": { | ||
| "type": "number" | ||
| }, | ||
| "count": { | ||
| "type": "integer" | ||
| } | ||
| }, | ||
| "required": [ | ||
| "count" | ||
| ] | ||
| } | ||
| }, | ||
| "required": [ | ||
| "subject", | ||
| "provenance", | ||
| "dedupKey", | ||
| "contentHash", | ||
| "date", | ||
| "utcOffset", | ||
| "unit", | ||
| "sampleType", | ||
| "samples", | ||
| "stats" | ||
| ] | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,120 @@ | ||
| { | ||
| "$schema": "http://json-schema.org/draft-07/schema#", | ||
| "schemaId": "28b50f16-0db1-445b-9f45-0412e9ac3f56", | ||
| "title": "BasalEnergySeries", | ||
| "description": "Raw basal (resting) energy burned samples over one local day from ONE device. One envelope per (person × day × device) — multiple devices coexist as separate envelopes; merging is a reader-side presentation concern. Sample = [startEpochSeconds, endEpochSeconds, value], epoch = UTC seconds, utcOffset gives the person's local offset. `stats` is DERIVED from samples (cheap-read preview) — samples are the source of truth. Canonical unit: kcal.", | ||
| "type": "object", | ||
| "properties": { | ||
| "subject": { | ||
| "type": "string", | ||
| "description": "@-prefixed eName of the person this data is about" | ||
| }, | ||
| "device": { | ||
| "type": [ | ||
| "string", | ||
| "null" | ||
| ], | ||
| "description": "w3id (@eName) of the measuring device's OWN eVault, where its Device passport lives; null if unknown" | ||
| }, | ||
| "provenance": { | ||
| "type": "object", | ||
| "description": "Import provenance. Vendor identity lives HERE only (source), never in metric keys.", | ||
| "properties": { | ||
| "source": { | ||
| "type": "string" | ||
| }, | ||
| "platform": { | ||
| "type": "string", | ||
| "description": "w3id (@eName) of the platform that wrote this envelope — machine-readable authorship; resolve it to read that platform's self-description" | ||
| }, | ||
| "externalId": { | ||
| "type": "string" | ||
| }, | ||
| "sourceName": { | ||
| "type": "string" | ||
| }, | ||
| "deviceSignature": { | ||
| "type": "string" | ||
| } | ||
| }, | ||
| "required": [ | ||
| "source" | ||
| ] | ||
| }, | ||
| "dedupKey": { | ||
| "type": "string", | ||
| "description": "Writer's idempotency key, unique within this ontology on the vault" | ||
| }, | ||
| "contentHash": { | ||
| "type": "string", | ||
| "description": "Writer-maintained md5 of the payload; recomputed on every rewrite" | ||
| }, | ||
| "updatedAt": { | ||
| "type": "string" | ||
| }, | ||
| "date": { | ||
| "type": "string", | ||
| "pattern": "^\\d{4}-\\d{2}-\\d{2}$", | ||
| "description": "local day — chunk key" | ||
| }, | ||
| "utcOffset": { | ||
| "type": "string", | ||
| "pattern": "^[+-]\\d{2}:\\d{2}$" | ||
| }, | ||
| "unit": { | ||
| "type": "string", | ||
| "const": "kcal" | ||
| }, | ||
| "sampleType": { | ||
| "type": "string", | ||
| "const": "interval" | ||
| }, | ||
| "samples": { | ||
| "type": "array", | ||
| "items": { | ||
| "type": "array", | ||
| "items": { | ||
| "type": "number" | ||
| }, | ||
| "minItems": 2, | ||
| "maxItems": 3 | ||
| } | ||
| }, | ||
| "stats": { | ||
| "type": "object", | ||
| "description": "DERIVED from samples — preview only", | ||
| "properties": { | ||
| "min": { | ||
| "type": "number" | ||
| }, | ||
| "max": { | ||
| "type": "number" | ||
| }, | ||
| "avg": { | ||
| "type": "number" | ||
| }, | ||
| "sum": { | ||
| "type": "number" | ||
| }, | ||
| "count": { | ||
| "type": "integer" | ||
| } | ||
| }, | ||
| "required": [ | ||
| "count" | ||
| ] | ||
| } | ||
| }, | ||
| "required": [ | ||
| "subject", | ||
| "provenance", | ||
| "dedupKey", | ||
| "contentHash", | ||
| "date", | ||
| "utcOffset", | ||
| "unit", | ||
| "sampleType", | ||
| "samples", | ||
| "stats" | ||
| ] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| { | ||
| "$schema": "http://json-schema.org/draft-07/schema#", | ||
| "schemaId": "ae1f8c24-41e6-4ec3-a128-07e423811332", | ||
| "title": "BiologicalSexFact", | ||
| "description": "A BiometricFact: one self-sufficient biometric attribute of a person — biological sex, e.g. \"male\". One envelope per (person × source). Identity fields (name, birthDate) are NOT here — they live in the shared User ontology.", | ||
| "type": "object", | ||
| "properties": { | ||
| "subject": { | ||
| "type": "string", | ||
| "description": "@-prefixed eName of the person this data is about" | ||
| }, | ||
| "device": { | ||
| "type": [ | ||
| "string", | ||
| "null" | ||
| ], | ||
| "description": "w3id (@eName) of the measuring device's OWN eVault, where its Device passport lives; null if unknown" | ||
| }, | ||
| "provenance": { | ||
| "type": "object", | ||
| "description": "Import provenance. Vendor identity lives HERE only (source), never in metric keys.", | ||
| "properties": { | ||
| "source": { | ||
| "type": "string" | ||
| }, | ||
| "platform": { | ||
| "type": "string", | ||
| "description": "w3id (@eName) of the platform that wrote this envelope — machine-readable authorship; resolve it to read that platform's self-description" | ||
| }, | ||
| "externalId": { | ||
| "type": "string" | ||
| }, | ||
| "sourceName": { | ||
| "type": "string" | ||
| }, | ||
| "deviceSignature": { | ||
| "type": "string" | ||
| } | ||
| }, | ||
| "required": [ | ||
| "source" | ||
| ] | ||
| }, | ||
| "dedupKey": { | ||
| "type": "string", | ||
| "description": "Writer's idempotency key, unique within this ontology on the vault" | ||
| }, | ||
| "contentHash": { | ||
| "type": "string", | ||
| "description": "Writer-maintained md5 of the payload; recomputed on every rewrite" | ||
| }, | ||
| "updatedAt": { | ||
| "type": "string" | ||
| }, | ||
| "value": { | ||
| "type": [ | ||
| "string", | ||
| "boolean" | ||
| ] | ||
|
Comment on lines
+55
to
+59
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Reject boolean biological-sex values.
🤖 Prompt for AI Agents |
||
| }, | ||
| "recordedAt": { | ||
| "type": "string" | ||
| } | ||
| }, | ||
| "required": [ | ||
| "subject", | ||
| "provenance", | ||
| "dedupKey", | ||
| "contentHash", | ||
| "value" | ||
| ] | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| { | ||
| "$schema": "http://json-schema.org/draft-07/schema#", | ||
| "schemaId": "79568be5-45b3-40ed-a96a-e5e39bc8814b", | ||
| "title": "BloodGlucoseObservation", | ||
| "description": "One spot measurement of blood glucose = one envelope. Canonical unit: mmol/L.", | ||
| "type": "object", | ||
| "properties": { | ||
| "subject": { | ||
| "type": "string", | ||
| "description": "@-prefixed eName of the person this data is about" | ||
| }, | ||
| "device": { | ||
| "type": [ | ||
| "string", | ||
| "null" | ||
| ], | ||
| "description": "w3id (@eName) of the measuring device's OWN eVault, where its Device passport lives; null if unknown" | ||
| }, | ||
| "provenance": { | ||
| "type": "object", | ||
| "description": "Import provenance. Vendor identity lives HERE only (source), never in metric keys.", | ||
| "properties": { | ||
| "source": { | ||
| "type": "string" | ||
| }, | ||
| "platform": { | ||
| "type": "string", | ||
| "description": "w3id (@eName) of the platform that wrote this envelope — machine-readable authorship; resolve it to read that platform's self-description" | ||
| }, | ||
| "externalId": { | ||
| "type": "string" | ||
| }, | ||
| "sourceName": { | ||
| "type": "string" | ||
| }, | ||
| "deviceSignature": { | ||
| "type": "string" | ||
| } | ||
| }, | ||
| "required": [ | ||
| "source" | ||
| ] | ||
| }, | ||
| "dedupKey": { | ||
| "type": "string", | ||
| "description": "Writer's idempotency key, unique within this ontology on the vault" | ||
| }, | ||
| "contentHash": { | ||
| "type": "string", | ||
| "description": "Writer-maintained md5 of the payload; recomputed on every rewrite" | ||
| }, | ||
| "updatedAt": { | ||
| "type": "string" | ||
| }, | ||
| "value": { | ||
| "type": "number" | ||
|
Comment on lines
+55
to
+56
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win Reject impossible negative health quantities. These schemas accept negative glucose, blood pressure, durations, distances, calories, sleep totals, dimensions, and route point counts, allowing invalid records into the eVault.
📍 Affects 6 files
🤖 Prompt for AI Agents |
||
| }, | ||
| "unit": { | ||
| "type": "string", | ||
| "const": "mmol/L" | ||
| }, | ||
| "measuredAt": { | ||
| "type": "string", | ||
| "description": "ISO 8601 with offset" | ||
| } | ||
| }, | ||
| "required": [ | ||
| "subject", | ||
| "provenance", | ||
| "dedupKey", | ||
| "contentHash", | ||
| "value", | ||
| "unit", | ||
| "measuredAt" | ||
| ] | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Require
deviceto preserve the unknown-device contract.The descriptions specify
nullwhen unknown, but omission is also valid. This makes device identity ambiguous and breaks the documented person × day × device partition.services/ontology/schemas/activeEnergySeries.json#L12-L18: add"device"torequired.services/ontology/schemas/basalEnergySeries.json#L12-L18: add"device"torequired.services/ontology/schemas/cyclingDistanceSeries.json#L12-L18: add"device"torequired.services/ontology/schemas/environmentalAudioSeries.json#L12-L18: add"device"torequired.services/ontology/schemas/exerciseMinutesSeries.json#L12-L18: add"device"torequired.services/ontology/schemas/flightsClimbedSeries.json#L12-L18: add"device"torequired.services/ontology/schemas/headphoneAudioSeries.json#L12-L18: add"device"torequired.services/ontology/schemas/heartRateSeries.json#L12-L18: add"device"torequired.services/ontology/schemas/heartRateVariabilitySeries.json#L12-L18: add"device"torequired.services/ontology/schemas/oxygenSaturationSeries.json#L12-L18: add"device"torequired.services/ontology/schemas/respiratoryRateSeries.json#L12-L18: add"device"torequired.📍 Affects 11 files
services/ontology/schemas/activeEnergySeries.json#L12-L18(this comment)services/ontology/schemas/basalEnergySeries.json#L12-L18services/ontology/schemas/cyclingDistanceSeries.json#L12-L18services/ontology/schemas/environmentalAudioSeries.json#L12-L18services/ontology/schemas/exerciseMinutesSeries.json#L12-L18services/ontology/schemas/flightsClimbedSeries.json#L12-L18services/ontology/schemas/headphoneAudioSeries.json#L12-L18services/ontology/schemas/heartRateSeries.json#L12-L18services/ontology/schemas/heartRateVariabilitySeries.json#L12-L18services/ontology/schemas/oxygenSaturationSeries.json#L12-L18services/ontology/schemas/respiratoryRateSeries.json#L12-L18🤖 Prompt for AI Agents