> ## 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.

# Lab Mode overview

> Research surface for recording structured experiment data alongside the live HSI loop

**Lab Mode** is a Synheart Core surface for recording structured experiment data alongside the live HSI measurement loop. Use it when you're running a study where the protocol — baselines, intervention windows, recovery — needs to be captured as first-class structure on top of the normal sample stream.

Lab Mode is **research-tier**. Cloud upload of lab sessions requires the `research` consent type and a capability token whose `hsi` tier is at least `research`. Without those, lab sessions stay on-device.

## What it gives you

* A **session** scoped to one protocol (e.g. "morning baseline + 5-min stressor").
* A tree of **windows** inside the session (e.g. baseline → stressor → recovery), each with a type, label, and free-form values.
* **Window-level overrides** for state values (used when the experimenter wants to assert a known ground truth for a slice of time).
* **Metadata cache** for the device + user info that should accompany every session export.

The live engine continues running normally — sample push and HSI emission are not paused by lab calls.

## Public API surface (Synheart Core)

```dart theme={null}
// Start a session under a protocol.
final ok = await Synheart.labStart(
  protocolJson: jsonEncode(protocol),
  startedAtMs: DateTime.now().millisecondsSinceEpoch,
);

// Open a window. Returns the window_id; nest by passing parentId.
final baselineId = await Synheart.labOpenWindow(
  windowType: 'baseline',
  label: 'pre-task',
  startedAtMs: now(),
);

// Close a window.
await Synheart.labCloseWindow(windowId: baselineId, endedAtMs: now());

// Annotate the window with values (any JSON object).
await Synheart.labSetWindowValues(
  windowId: baselineId,
  valuesJson: jsonEncode({'mood': 5, 'caffeinated': true}),
);

// Finalize the session — returns the session JSON and (with research
// consent + cloud config) enqueues a lab session export upload.
final sessionJson = await Synheart.labFinalize(endedAtMs: now());
```

Kotlin and Swift expose the same surface with idiomatic naming.

## Metadata cache

```dart theme={null}
// Compute metadata once at app start, re-upload when it changes.
final metaId = await Synheart.labEnsureMetadata(
  deviceId: deviceId,
  platform: 'ios',
  osVersion: osVersion,
  userInfoJson: jsonEncode(userInfo),
  deviceExtraJson: null,
);

// Force a re-upload (e.g. after the user updates their profile).
await Synheart.labMarkMetadataDirty(reason: 'profile-edit');
```

The runtime stamps the active `meta_id` into every finalized session's `session_metadata.extra_data.metadata_id`, so server-side analysis can group sessions by the device/user state at the time they were recorded.

## Availability

Lab is gated by a capability flag in the runtime artifact. Hosts should call `Synheart.isLabAvailable()` before assuming the surface is present:

```dart theme={null}
if (await Synheart.isLabAvailable()) {
  // safe to call labStart, labOpenWindow, etc.
}
```

When the runtime is built without the `lab` feature, every `lab*` method returns a "not available" sentinel (false / null) and never throws.

## Cloud upload path

When `cloudConfig.lab = true` AND `research` consent is granted, `labFinalize` enqueues an upload to `/ingest/v1/lab/session`. The upload is **separate from** the standard HSI ingest path (`/ingest/v1/hsi`) so research data is routed and retained under research-tier policies.

See [Cloud Protocol](/synheart-core/cloud-protocol) for the full ingest surface and [Consent System](/synheart-core/consent-system) for the `research` consent flow.

## When to use Lab Mode

* You're running an academic study and need protocol structure alongside the live state stream.
* You're A/B testing interventions and need windowed ground truth.
* You want to attach experimenter-supplied values (mood scores, intervention IDs, custom labels) to slices of time.

If you only need to flag interesting moments in a normal recording, prefer regular HSI snapshots with custom metadata.
