Skip to main content

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 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)

// 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

// 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:
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 for the full ingest surface and 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.