> ## Documentation Index
> Fetch the complete documentation index at: https://docs.synheart.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Self-Reference Model (SRM)

> Per-subject longitudinal baseline engine — dimensions, maturity states, reference view, and snapshot lifecycle.

## 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`](/synheart-core/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.

| Dimension          | Tier      | Window | Notes                                            |
| ------------------ | --------- | ------ | ------------------------------------------------ |
| `sleep_need`       | primary   | 14d    | 30d buffer retained                              |
| `sleep_regularity` | primary   | 14d    |                                                  |
| `hrv_rmssd`        | primary   | 30d    | 2-MAD outlier exclusion                          |
| `resting_hr`       | primary   | 14d    | 2-MAD outlier exclusion                          |
| `recovery_score`   | primary   | 30d    |                                                  |
| `hrv_sdnn`         | secondary | 30d    | Apple Health SDNN, tracked separately from RMSSD |
| `deep_sleep_min`   | secondary | 7d     | μ/σ                                              |
| `rem_sleep_min`    | secondary | 7d     | μ/σ                                              |
| `daily_strain`     | secondary | 14d    |                                                  |
| `motion_steps_est` | secondary | 14d    | 2-MAD outlier exclusion                          |
| `hrv_hr_std_bpm`   | secondary | 30d    | Overnight HR standard deviation                  |

## Maturity states

The overall `status` field on `WearableReferenceView` has four values, emitted by the runtime as uppercase strings:

| Status    | Meaning                                                                                                                                |
| --------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `EMPTY`   | No reference exists, or all dimensions absent.                                                                                         |
| `WARMING` | At least one primary dimension present, but not all five at sufficient confidence.                                                     |
| `READY`   | All five primary dimensions present, each at or above its per-dimension `min_confidence`. Downstream personalized scoring is unlocked. |
| `STALE`   | Was `READY`; at least one primary dimension has decayed past its `staleness_days` window or fallen to zero confidence.                 |

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`:

| Dimension          | `min_days` | `min_confidence` | `staleness_days` |
| ------------------ | ---------- | ---------------- | ---------------- |
| `sleep_need`       | 7          | 0.50             | 7                |
| `sleep_regularity` | 5          | 0.50             | 7                |
| `hrv_rmssd`        | 10         | 0.50             | 7                |
| `resting_hr`       | 5          | 0.45             | 10               |
| `recovery_score`   | 7          | 0.50             | 5                |

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:

```text theme={null}
status: String           // "EMPTY" | "WARMING" | "READY" | "STALE"
modelVersion: String?
recentSleepScoreMedian: Int?
dimensions: Map<String, Number>     // per-dimension central value
confidence: Map<String, Double>     // 0.0 – 1.0 per dimension
```

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](/synheart-core/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:

| FFI symbol                          | When the host calls it                                                                                                                                                                                     |
| ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `synheart_core_export_srm_snapshot` | On app background / session end. The host writes the returned JSON to its own secure store (Keychain, EncryptedSharedPreferences).                                                                         |
| `synheart_core_load_srm_snapshot`   | On app cold start, after the runtime handle is created. Schema or config mismatch is rejected; the caller must invoke `recompute()` afterward — load alone does not produce a new `WearableReferenceView`. |
| `synheart_core_wipe_local_data`     | On user consent revocation or account wipe. Clears the SRM snapshot along with other local stores.                                                                                                         |

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.

## Related

* [Baselines facade](/synheart-core/baselines) — host-facing read API over the latest reference + recent-scores ring.
* [Scoring models](/synheart-core/scoring) — recovery/readiness/sleep scorers that consume the reference view; personalized stage gates on `status == READY`.
* [Health backfill](/synheart-core/health-backfill) — cold-start path that seeds the SRM from platform health stores.
* [Runtime FFI](/synheart-core/runtime-ffi#srm-and-baselines) — snapshot export/load and direct SRM accessors.
