Skip to main content

What is Synheart Flux?

Synheart Flux is a Rust-based on-device compute engine that transforms raw wearable vendor payloads (e.g., WHOOP, Garmin) and smartphone behavioral data into HSI-compliant human state signals. Flux centralizes two parallel pipelines:
  • Wearable Pipeline: vendor adaptation → normalization → feature derivation → baseline computation → HSI encoding
  • Behavioral Pipeline: session parsing → normalization → metric computation → baseline tracking → HSI encoding
Additionally, Flux provides a Snapshot API that combines staleness-aware bio context from wearables with realtime behavioral signals for adaptive systems.

Key Features

Wearable Processing

  • Parse vendor JSON into canonical, vendor-agnostic structures
  • Normalize units and scales (and surface data quality flags)
  • Derive features (sleep efficiency/fragmentation, normalized load, etc.)
  • Maintain rolling baselines for relative interpretation (HRV, RHR, sleep)
  • Encode daily windows into HSI JSON with provenance + quality/confidence

Behavioral Metrics

  • Parse behavioral session JSON (taps, scrolls, notifications, app switches, typing)
  • Compute engagement metrics (distraction score, focus hint, burstiness, interaction intensity)
  • Detect patterns (idle segments, engagement blocks, scroll jitter, deep focus periods)
  • Maintain rolling baselines across sessions (20-session default window)
  • Encode behavioral windows into HSI JSON with deviation tracking

Context Snapshots

  • Capture bio context from wearable processing (sleep quality, recovery, HRV/RHR deviations)
  • Apply staleness decay with configurable half-life (default 12 hours)
  • Combine with realtime behavior for context-aware adaptive systems
  • Read-only snapshots that don’t mutate baselines

Typing Correction and Clipboard Metrics

  • Correction tracking: number_of_backspace, number_of_delete, correction_rate
  • Clipboard activity: number_of_cut, number_of_paste, number_of_copy, clipboard_activity_rate
  • Rates included in HSI payload meta section:
    • correction_rate = (backspace + delete) / (typing_tap_count + backspace + delete)
    • clipboard_activity_rate = (copy + paste + cut) / (typing_tap_count + copy + paste + cut)

Non-goals

  • Emotion inference or labeling
  • Medical/diagnostic claims
  • UI, visualization, or cloud-side compute
  • Replacing wearable ingestion/auth SDKs

Installation

Rust (crate)

Add to your Cargo.toml:
[dependencies]
synheart-flux = "0.3"

Platform Installs (Android / iOS / Flutter / Desktop)

Flux is typically bundled into a host SDK (e.g., Synheart Wear, Synheart Behavior) as native artifacts.
  • Recommended (prebuilt): Download artifacts from GitHub Releases and vendor them into your SDK repo
  • Fallback (from source): Build artifacts in CI using the scripts in scripts/

Android (JNI .so inside an AAR)

  • Get: release asset synheart-flux-android-jniLibs.tar.gz
  • Place in your Android library/module:
src/main/jniLibs/
  arm64-v8a/libsynheart_flux.so
  armeabi-v7a/libsynheart_flux.so
  x86_64/libsynheart_flux.so
  • Build from source:
ANDROID_NDK_HOME=/path/to/ndk bash scripts/build-android.sh dist/android/jniLibs

iOS (XCFramework)

  • Get: release asset synheart-flux-ios-xcframework.zip
  • Place:
ios/Frameworks/SynheartFlux.xcframework
  • Build from source (macOS):
bash scripts/build-ios-xcframework.sh dist/ios

Flutter

Bundle the same artifacts in your Flutter plugin:
android/src/main/jniLibs/*/libsynheart_flux.so
ios/Frameworks/SynheartFlux.xcframework

Desktop (macOS / Linux / Windows)

  • Get (examples):
    • synheart-flux-desktop-linux-x86_64.tar.gz
    • synheart-flux-desktop-macos-<arch>.tar.gz
    • synheart-flux-desktop-windows-x86_64.zip
  • Use them in your app/tooling distribution (or load dynamically via FFI).

WebAssembly (WASI)

Flux can be compiled to WASM for cross-language integration:
rustup target add wasm32-wasip1
cargo build --target wasm32-wasip1 --release
The WASM module exports alloc and dealloc for host-managed memory, alongside the standard Flux FFI API.

Usage

One-shot Conversion (Stateless)

use synheart_flux::{garmin_to_hsi_daily, whoop_to_hsi_daily};

fn main() -> Result<(), synheart_flux::ComputeError> {
    let whoop_json = r#"{"sleep": [], "recovery": [], "cycle": []}"#.to_string();
    let garmin_json = r#"{"dailies": [], "sleep": []}"#.to_string();

    let whoop_hsi = whoop_to_hsi_daily(
        whoop_json,
        "America/New_York".to_string(),
        "device-123".to_string(),
    )?;

    let garmin_hsi = garmin_to_hsi_daily(
        garmin_json,
        "America/Los_Angeles".to_string(),
        "garmin-device-456".to_string(),
    )?;

    println!("WHOOP payloads: {}", whoop_hsi.len());
    println!("Garmin payloads: {}", garmin_hsi.len());
    Ok(())
}

Persistent Baselines Across Calls

For baselines that accumulate across multiple payloads (e.g., across app launches), use FluxProcessor:
use synheart_flux::FluxProcessor;

fn main() -> Result<(), synheart_flux::ComputeError> {
    let mut p = FluxProcessor::with_baseline_window(7);

    // Load baseline state from disk/keychain/etc.
    // p.load_baselines(&saved_json)?;

    let whoop_json = r#"{"sleep": [], "recovery": [], "cycle": []}"#;
    let hsi = p.process_whoop(whoop_json, "America/New_York", "device-123")?;

    // Save baseline state for next run
    let saved_json = p.save_baselines()?;
    println!("HSI payloads: {}", hsi.len());
    Ok(())
}

Behavioral Metrics (One-shot)

use synheart_flux::behavior_to_hsi;

fn main() -> Result<(), synheart_flux::ComputeError> {
    let session_json = r#"{
        "session_id": "sess-123",
        "device_id": "device-456",
        "timezone": "America/New_York",
        "start_time": "2024-01-15T14:00:00Z",
        "end_time": "2024-01-15T14:30:00Z",
        "events": [
            {"timestamp": "2024-01-15T14:01:00Z", "event_type": "scroll", "scroll": {"velocity": 150.5, "direction": "down"}},
            {"timestamp": "2024-01-15T14:02:00Z", "event_type": "tap", "tap": {"tap_duration_ms": 120}},
            {"timestamp": "2024-01-15T14:03:00Z", "event_type": "notification", "interruption": {"action": "ignored"}},
            {"timestamp": "2024-01-15T14:05:00Z", "event_type": "app_switch", "app_switch": {"from_app_id": "app1", "to_app_id": "app2"}}
        ]
    }"#.to_string();

    let hsi_json = behavior_to_hsi(session_json)?;
    println!("Behavioral HSI: {}", hsi_json);
    Ok(())
}

Behavioral Metrics with Persistent Baselines

use synheart_flux::BehaviorProcessor;

fn main() -> Result<(), synheart_flux::ComputeError> {
    let mut processor = BehaviorProcessor::with_baseline_window(20); // 20 sessions

    let session_json = r#"{"session_id": "...", "device_id": "...", ...}"#;
    let hsi = processor.process(session_json)?;

    // Save baseline state for next run
    let saved_json = processor.save_baselines()?;
    println!("Behavioral HSI: {}", hsi);
    Ok(())
}

Context-Aware Snapshots

The snapshot_now() API provides staleness-aware bio context combined with optional realtime behavior. This is useful for adaptive systems that need honest background context from wearables while relying on behavior for realtime state.
use synheart_flux::FluxProcessor;

fn main() -> Result<(), synheart_flux::ComputeError> {
    let mut processor = FluxProcessor::new();

    // First, process wearable data to capture bio context
    let whoop_json = r#"{"sleep": [...], "recovery": [...], "cycle": [...]}"#;
    processor.process_whoop(whoop_json, "America/New_York", "device-123")?;

    // Later, take a snapshot with current time
    // Bio context confidence decays over time (50% at 12 hours, 25% at 24 hours)
    let snapshot = processor.snapshot_now(
        "2024-01-15T14:00:00Z",  // Current time (RFC3339)
        "America/New_York",
        "device-123",
        None,  // Optional: behavior session JSON for realtime state
    )?;

    println!("Snapshot HSI: {}", snapshot);
    Ok(())
}

With Realtime Behavior

use synheart_flux::FluxProcessor;

fn main() -> Result<(), synheart_flux::ComputeError> {
    let mut processor = FluxProcessor::new();

    // Process wearable data (e.g., from morning sync)
    processor.process_whoop(whoop_json, "America/New_York", "device-123")?;

    // During the day, take snapshots with current behavior
    let behavior_json = r#"{
        "session_id": "sess-456",
        "device_id": "device-123",
        "timezone": "America/New_York",
        "start_time": "2024-01-15T14:00:00Z",
        "end_time": "2024-01-15T14:30:00Z",
        "events": [...]
    }"#;

    let snapshot = processor.snapshot_now(
        "2024-01-15T14:35:00Z",
        "America/New_York",
        "device-123",
        Some(behavior_json),  // Include realtime behavior
    )?;

    // Snapshot contains both:
    // - axes.context: bio_freshness, recovery_context, sleep_context (decayed confidence)
    // - axes.behavior: distraction, focus, task_switch_rate, etc. (realtime)
    println!("Combined snapshot: {}", snapshot);
    Ok(())
}

Behavioral Axes

AxisDirectionDescription
distractionhigher_is_moreComposite distraction score (0-1)
focushigher_is_moreInverse of distraction (0-1)
task_switch_ratehigher_is_moreApp switch frequency (normalized)
notification_loadhigher_is_moreNotification frequency (normalized)
burstinessbidirectionalTemporal clustering (Barabasi index)
scroll_jitter_ratehigher_is_moreDirection reversals ratio
interaction_intensityhigher_is_moreEvents per second (normalized)
idle_ratiohigher_is_moreIdle time ratio

Context Axes (Snapshot API)

AxisDirectionDescription
bio_freshnesshigher_is_moreHow fresh the wearable data is (1.0 = just observed, decays over time)
recovery_contexthigher_is_moreRecovery score with staleness-decayed confidence
sleep_contexthigher_is_moreSleep quality with staleness-decayed confidence
hrv_delta_contextbidirectionalHRV deviation from baseline (0.5 = at baseline)
rhr_delta_contexthigher_is_moreRHR deviation from baseline (>0.5 = below baseline, better)

Staleness Decay

Bio context confidence decays exponentially with a 12-hour half-life:
  • 0 hours: 100% confidence
  • 12 hours: 50% confidence
  • 24 hours: 25% confidence
  • ~40 hours: ~10% confidence (considered stale)

Adapt-Engine Integration

The SnapshotAdapter converts snapshot_now() output to the HsiSnapshot format expected by synheart-adapt-engine:
use synheart_flux::{FluxProcessor, SnapshotAdapter};

fn main() -> Result<(), synheart_flux::ComputeError> {
    let mut processor = FluxProcessor::new();

    // Process wearable data
    processor.process_whoop(whoop_json, "America/New_York", "device-123")?;

    // Take a snapshot
    let snapshot_json = processor.snapshot_now(
        "2024-01-15T14:00:00Z",
        "America/New_York",
        "device-123",
        Some(behavior_json),
    )?;

    // Convert to adapt-engine format
    let adapter = SnapshotAdapter::new();
    let adapt_snapshot = adapter.convert(&snapshot_json)?;

    // adapt_snapshot is now compatible with synheart-adapt-engine::PolicyEngine
    println!("Readiness: {}", adapt_snapshot.scores.readiness_score);
    println!("Stress: {}", adapt_snapshot.scores.stress_load_proxy);
    println!("Attention: {}", adapt_snapshot.scores.attention_capacity_proxy);
    println!("Freshness: {} ms", adapt_snapshot.freshness_ms);

    Ok(())
}

Score Mapping

Adapt-Engine Fieldsnapshot_now() SourceMapping
readiness_scorerecovery_context, focus, sleep_contextWeighted average (40%, 40%, 20%)
stress_load_proxyrecovery_context1.0 - recovery
attention_capacity_proxydistraction1.0 - distraction
freshness_msbio_context_age_hoursage_hours * 3600000
sourcesPresence of axesWearable and/or Behavior

Custom Mapping Configuration

use synheart_flux::{SnapshotAdapter, MappingConfig};

let config = MappingConfig {
    recovery_weight: 0.5,    // More weight on recovery
    focus_weight: 0.3,
    sleep_weight: 0.2,
    default_score: 0.5,      // When axis is missing
    default_confidence: 0.3,
};

let adapter = SnapshotAdapter::with_config(config);

HSI Output Format

Flux emits HSI 1.0 JSON payloads that conform to the Human State Interface specification.

Required Fields

  • hsi_version — Schema version (e.g., "1.0")
  • observed_at_utc — When the data was observed
  • computed_at_utc — When HSI was computed
  • producer — Name, version, and instance_id of the producing software
  • window_ids / windows — Time windows with start/end timestamps
  • source_ids / sources — Data sources with type and quality
  • axes — Behavioral readings organized by domain
  • privacy — Data handling declarations

Feature Flags

  • ffi: Enables the C FFI bindings for mobile and cross-language integration. Provides:
    • Wearable functions: flux_whoop_to_hsi_daily, flux_garmin_to_hsi_daily, and stateful FluxProcessor API
    • Behavioral functions: flux_behavior_to_hsi, and stateful BehaviorProcessor API
    • Snapshot functions: flux_processor_snapshot_now (stateful), flux_snapshot_now (stateless)
  • cli: Enables the flux command-line binary for processing wearable data

Resources

License

Licensed under the Apache License, Version 2.0.