Skip to main content

Overview

The Self-Reference Model (SRM) is the per-subject longitudinal baseline engine inside the native runtime. It ingests vendor-agnostic daily wearable values, maintains rolling per-dimension statistics, and emits a typed WearableReferenceView that downstream scoring (recovery, readiness) consumes as “the user’s normal.” It is the data model behind the reference field on Baselines. Hosts never write SRM state directly — they push daily values, and the runtime maintains the model.

Dimensions

The SRM tracks 11 dimensions. Five are primary: they gate the overall maturity state. The remaining six are secondary — populated when available, used by specific scorers, but not required for the model to be considered ready.

Maturity states

The overall status field on WearableReferenceView has four values, emitted by the runtime as uppercase strings: Personalized scoring (e.g. recovery Stage 3) gates on status == READY.

Per-dimension thresholds

Each primary dimension carries its own min_days, min_confidence, and staleness_days: Confidence ramps up linearly over the first three days after a gap resumes, and decays exponentially when observations stop arriving.

WearableReferenceView

The host-typed shape exposed by every SDK:
Cross-language parity:
  • Flutter: WearableReferenceView in lib/src/models/sleep_score.dart
  • Kotlin: WearableReferenceView in synheart-core/.../models/SleepScore.kt
  • Swift: WearableReferenceView in SynheartCore/Models/SleepScore.swift
Kotlin types dimensions as Map<String, Number>; Swift and Dart use the platform numeric type (Double / num). Shape is otherwise byte-equivalent across platforms.

Source fidelity

The engine distinguishes two input fidelities:
  • Raw observation — direct samples (e.g. an HR trace the runtime aggregated itself).
  • Provider summary — pre-computed vendor metrics (e.g. a Whoop recovery score).
Both count equally toward min_days. Confidence is weighted by raw_ratio — a dimension fed only by provider summaries matures, but at discounted confidence relative to one fed by raw samples.

Backfill parity

Nights ingested via Health backfill and nights ingested live are treated identically by the SRM — backfilled days count toward min_days the same as live days. Backfill events carry a backfilled flag for telemetry; this does not change their weight in the model. Late backfill (events older than seven days) does not trigger an incremental recompute; the runtime performs a full recompute instead.

Snapshot lifecycle

The runtime exposes export and load over FFI so hosts can persist longitudinal state across cold starts: The Baselines.reset() facade method clears the host-side cache only — it does not wipe the runtime’s SRM snapshot. Use the FFI wipe call for runtime state.
  • Baselines facade — host-facing read API over the latest reference + recent-scores ring.
  • Scoring models — recovery/readiness/sleep scorers that consume the reference view; personalized stage gates on status == READY.
  • Health backfill — cold-start path that seeds the SRM from platform health stores.
  • Runtime FFI — snapshot export/load and direct SRM accessors.