{"id":45034729,"url":"https://github.com/synheart-ai/synheart-behavior-swift","last_synced_at":"2026-05-16T06:42:16.697Z","repository":{"id":339313430,"uuid":"1095753997","full_name":"synheart-ai/synheart-behavior-swift","owner":"synheart-ai","description":"iOS SDK for behavioral signals — typing, gestures, scrolling, attention, app switching.","archived":false,"fork":false,"pushed_at":"2026-05-16T05:54:11.000Z","size":32853,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-16T06:36:38.843Z","etag":null,"topics":["attention","behavioral-analytics","ios","scrolling","sdk","swift","typing"],"latest_commit_sha":null,"homepage":"https://docs.synheart.ai/synheart-behavior/swift","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/synheart-ai.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-13T13:28:32.000Z","updated_at":"2026-05-16T05:54:15.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/synheart-ai/synheart-behavior-swift","commit_stats":null,"previous_names":["synheart-ai/synheart-behavior-swift"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/synheart-ai/synheart-behavior-swift","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/synheart-ai%2Fsynheart-behavior-swift","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/synheart-ai%2Fsynheart-behavior-swift/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/synheart-ai%2Fsynheart-behavior-swift/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/synheart-ai%2Fsynheart-behavior-swift/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/synheart-ai","download_url":"https://codeload.github.com/synheart-ai/synheart-behavior-swift/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/synheart-ai%2Fsynheart-behavior-swift/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33093153,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-16T04:41:52.686Z","status":"ssl_error","status_checked_at":"2026-05-16T04:41:52.009Z","response_time":115,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["attention","behavioral-analytics","ios","scrolling","sdk","swift","typing"],"created_at":"2026-02-19T06:12:59.828Z","updated_at":"2026-05-16T06:42:16.690Z","avatar_url":"https://github.com/synheart-ai.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Synheart Behavior\n\n\n\u003e **Source-available.** This repository is open for reading, auditing, and\n\u003e filing issues. We do **not** accept pull requests — see\n\u003e [CONTRIBUTING.md](CONTRIBUTING.md) for the rationale and how to contribute\n\u003e via issues. Security reports go through [SECURITY.md](SECURITY.md).\n\u003e On-device behavioral signal inference from digital interactions for iOS applications\n\n[![CI](https://github.com/synheart-ai/synheart-behavior-swift/actions/workflows/ci.yml/badge.svg)](https://github.com/synheart-ai/synheart-behavior-swift/actions/workflows/ci.yml)\n[![Swift](https://img.shields.io/badge/Swift-5.9%2B-orange?logo=swift)](https://swift.org)\n[![SPM](https://img.shields.io/badge/SPM-compatible-brightgreen?logo=swift)](https://www.swift.org/package-manager/)\n[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n[![Platform](https://img.shields.io/badge/platform-iOS%2012%2B-lightgrey.svg)](https://developer.apple.com/ios/)\n\nA privacy-preserving mobile SDK that collects digital behavioral signals from smartphones. The SDK transforms low-level digital interaction events into structured numerical representations of behavior across event and session. By modeling interaction timing, intensity, fragmentation, and interruption patterns without collecting content or personal data, the SDK provides stable, interpretable metrics to represent digital behavior.\n\nThese behavioral signals power downstream systems such as:\n\n- Focus and distraction inference\n- Digital wellness analytics\n- Cognitive load and fatigue estimation\n- Multimodal human state modeling (HSI)\n\n## 🚀 Features\n\n- **Privacy-First**: No text, content, or personally identifiable information (PII) collected—only timing-based signals\n- **Real-Time Streaming**: Event callbacks for scroll, tap, swipe, notification, and call interactions\n- **Session Tracking**: Built-in session management with comprehensive summaries\n- **On-Demand Metrics**: Calculate behavioral metrics for custom time ranges within sessions\n- **Swift Package Manager**: Easy integration via SPM, no extra native binaries required\n- **System State Tracking**: Internet connectivity, charging state, and device context\n- **Minimal Permissions**: No permissions required for basic functionality (scroll, tap, swipe). Optional permissions for notification and call tracking.\n- **Platform Support**: iOS 13.0+\n\n## 📦 Installation\n\n### Swift Package Manager\n\nAdd to your `Package.swift`:\n\n```swift\ndependencies: [\n    .package(url: \"https://github.com/synheart-ai/synheart-behavior-swift.git\", from: \"0.4.0\")\n]\n```\n\nThen add `SynheartBehavior` to your target:\n\n```swift\n.target(\n    name: \"MyApp\",\n    dependencies: [\n        .product(name: \"SynheartBehavior\", package: \"synheart-behavior-swift\"),\n    ]\n)\n```\n\n### Xcode\n\n1. File → Add Packages…\n2. Enter `https://github.com/synheart-ai/synheart-behavior-swift.git`\n3. Select the latest version\n\n### Platform Setup\n\nThis SDK is **self-contained** and does **not** require bundling any native binaries or `.xcframework` files.\n\nFor optional features (notifications and calls), see the [Permissions](#-permissions) section below.\n\n## 🎯 Quick Start\n\nHere's a complete example to get you started:\n\n```swift\nimport SwiftUI\nimport SynheartBehavior\n\n@main\nstruct MyApp: App {\n    @StateObject private var behaviorHost = BehaviorHost()\n\n    var body: some Scene {\n        WindowGroup {\n            ContentView()\n                .environmentObject(behaviorHost)\n        }\n    }\n}\n\n@MainActor\nfinal class BehaviorHost: ObservableObject {\n    let behavior: SynheartBehavior\n    @Published private(set) var sessionId: String?\n\n    init() {\n        let config = BehaviorConfig(\n            enableInputSignals: true,\n            enableAttentionSignals: true,\n            enableMotionLite: false\n        )\n        self.behavior = SynheartBehavior(config: config)\n\n        do {\n            try behavior.initialize()\n        } catch {\n            print(\"Init failed: \\(error)\")\n        }\n\n        // Listen to real-time events\n        behavior.setEventHandler { event in\n            print(\"Event: \\(event.eventType) at \\(event.timestamp)\")\n            print(\"Payload: \\(event.metrics)\")\n        }\n    }\n\n    func startSession() {\n        do {\n            sessionId = try behavior.startSession()\n            print(\"Session started: \\(sessionId ?? \"n/a\")\")\n        } catch {\n            print(\"Failed to start session: \\(error)\")\n        }\n    }\n\n    func endSession() {\n        guard let id = sessionId else { return }\n        do {\n            let summary = try behavior.endSession(sessionId: id)\n            print(\"Session ended: \\(summary.duration)ms\")\n            print(\"Total events: \\(summary.eventCount)\")\n            print(\"App switches: \\(summary.appSwitchCount)\")\n            sessionId = nil\n        } catch {\n            print(\"Failed to end session: \\(error)\")\n        }\n    }\n\n    deinit {\n        behavior.dispose()\n    }\n}\n```\n\n### Key Steps\n\n1. **Initialize the SDK** - Construct `SynheartBehavior(config:)` and call `try initialize()` once during app startup\n2. **Listen to Events** - Register a handler with `setEventHandler { … }` for real-time behavioral signals\n3. **Track Sessions** - Start and end sessions to get behavioral summaries\n4. **Clean Up** - Call `dispose()` when done to free resources\n\n## 📡 Real-Time Event Tracking\n\nThe SDK streams behavioral events in real-time as they occur. This is the primary way to track user behavior:\n\n```swift\nbehavior.setEventHandler { event in\n    print(\"Event: \\(event.eventType) at \\(event.timestamp)\")\n    print(\"Payload: \\(event.metrics)\")\n\n    switch event.eventType {\n    case .scroll:\n        let velocity = event.metrics[\"velocity\"] as? Double\n        print(\"Scroll velocity: \\(velocity ?? 0) px/s\")\n    case .tap:\n        let duration = event.metrics[\"tap_duration_ms\"] as? Int\n        let longPress = event.metrics[\"long_press\"] as? Bool\n        print(\"Tap duration: \\(duration ?? 0) ms, long press: \\(longPress ?? false)\")\n    case .swipe:\n        let direction = event.metrics[\"direction\"] as? String\n        let velocity = event.metrics[\"velocity\"] as? Double\n        print(\"Swipe direction: \\(direction ?? \"n/a\"), velocity: \\(velocity ?? 0) px/s\")\n    case .appSwitch:\n        let action = event.metrics[\"action\"] as? String\n        print(\"App switch action: \\(action ?? \"n/a\")\")\n    default:\n        break\n    }\n}\n```\n\nIf you prefer to receive events in batches (lower main-thread pressure for large sessions):\n\n```swift\nbehavior.setBatchEventHandler { events in\n    for event in events {\n        // process\n    }\n}\n```\n\n## 📊 Event Types\n\n`BehaviorEventType` has **eight canonical values**:\n`.scroll, .tap, .swipe, .appSwitch, .notification, .call, .typing,\n.clipboard`.\n\n- **.scroll**: Velocity, acceleration, direction, direction reversals\n- **.tap**: Duration, long-press detection. **Taps are not counted while the keyboard is open** (when a text field or text view is first responder), so typing interaction is not double-counted as tap events.\n- **.swipe**: Direction, distance, velocity, acceleration\n- **.appSwitch**: Foreground/background transitions, used for task-switch metrics\n- **.notification**: Received, opened, ignored (requires permission)\n- **.call**: Answered, ignored, dismissed (requires permission)\n- **.typing**: Speed, cadence, gap ratio, backspace count (no content)\n- **.clipboard**: Copy / paste / cut event counts (no content)\n\n\u003e This package is the **collector**. Higher-level behavioral metrics\n\u003e (focus hint, distraction score, burstiness, etc.) are computed by\n\u003e the Synheart Runtime when these events are fed into Synheart Core.\n\nEach event includes:\n\n- `eventId`: Unique identifier\n- `sessionId`: Associated session ID\n- `timestamp`: ISO 8601 timestamp\n- `type`: Event type (`.scroll`, `.tap`, `.swipe`, …)\n- `payload`: Event-specific metrics (velocity, duration, etc.)\n\n## 🔐 Permissions\n\n**Note**: Basic functionality (scroll, tap, swipe) requires **no permissions**. The following permissions are optional and only needed for notification and call tracking.\n\nNo content-level information is ever collected or stored. For notifications, the SDK does not record notification text, sender identity, application source, or semantic meaning. For phone calls, the SDK does not record audio, voice data, call content, or call participants.\n\nInstead, the SDK records only event-level metadata, such as:\n\n- the occurrence of a notification or call,\n- the timestamp of the event,\n- and the user's interaction outcome (e.g., opened, dismissed, ignored).\n\n### Notification Permission\n\nRequired for tracking notification interactions (received, opened, ignored). On iOS, request notification authorization via `UNUserNotificationCenter` in your host app, then forward the relevant `UNNotificationResponse` events through the SDK if you want fine-grained tracking.\n\n```swift\nimport UserNotifications\n\nUNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { granted, _ in\n    print(\"Notification authorization granted: \\(granted)\")\n}\n```\n\n### Call Permission\n\nRequired for tracking call interactions (answered, ignored). On iOS, the SDK uses `CXCallObserver` from CallKit, which does not require an explicit permission prompt — but your app must declare the appropriate CallKit entitlement and link `CallKit.framework` if you want call metadata in session summaries.\n\n## 🔧 Configuration\n\n### Initial Configuration\n\nConfigure the SDK during initialization:\n\n```swift\nlet config = BehaviorConfig(\n    // Enable/disable signal types\n    enableInputSignals: true,        // Scroll, tap, swipe gestures\n    enableAttentionSignals: true,    // App switching, idle gaps, session stability\n    enableMotionLite: true,          // Lightweight on-device motion classification\n\n    // Session configuration\n    sessionIdPrefix: \"MYAPP\",        // Custom session ID prefix (default: \"SESS\")\n\n    // User/device identifiers (optional, for custom tracking)\n    userId: \"user_123\",              // Optional: custom user identifier\n    deviceId: \"device_456\",          // Optional: custom device identifier\n\n    // SDK configuration\n    behaviorVersion: \"1.0.0\",        // SDK version identifier\n    consentBehavior: true,           // Consent flag for behavior tracking\n\n    // Advanced settings\n    eventBatchSize: 10,              // Events per batch (default: 10)\n    maxIdleGapSeconds: 10.0          // Max idle time before task drop (default: 10.0)\n)\n\nlet behavior = SynheartBehavior(config: config)\ntry behavior.initialize()\n```\n\n### Update Configuration at Runtime\n\nYou can update the configuration after initialization:\n\n```swift\n// Disable motion tracking to save battery\ntry behavior.updateConfig(BehaviorConfig(\n    enableInputSignals: true,\n    enableAttentionSignals: true,\n    enableMotionLite: false\n))\n```\n\n## 📈 Session Management\n\n### Starting a Session\n\n```swift\n// Start with auto-generated session ID\nlet sessionId = try behavior.startSession()\n\n// Or provide a custom session ID\nlet sessionId = try behavior.startSession(\n    sessionId: \"MYAPP-\\(Int(Date().timeIntervalSince1970 * 1000))\"\n)\n```\n\n### Ending a Session\n\nWhen a session ends, you receive a comprehensive summary:\n\n```swift\nlet summary = try behavior.endSession(sessionId: sessionId)\n\n// Session metadata\nprint(\"Session ID: \\(summary.sessionId)\")\nprint(\"Started: \\(summary.startTimestamp)\")\nprint(\"Ended: \\(summary.endTimestamp)\")\nprint(\"Duration: \\(summary.duration)ms\")\n\n// Activity summary\nprint(\"Total Events: \\(summary.eventCount)\")\nprint(\"App Switches: \\(summary.appSwitchCount)\")\n\n// Top-level shortcuts\nprint(\"Stability Index: \\(summary.stabilityIndex ?? 0)\")\nprint(\"Fragmentation Index: \\(summary.fragmentationIndex ?? 0)\")\nprint(\"Avg Scroll Velocity: \\(summary.averageScrollVelocity ?? 0)\")\nprint(\"Avg Typing Cadence: \\(summary.averageTypingCadence ?? 0)\")\n\n// Behavioral metrics (interactionIntensity, taskSwitchRate, idleRatio,\n// burstiness, notificationLoad, scrollJitterRate,\n// behavioralDistractionScore, behavioralFocusHint, …)\nif let metrics = summary.behavioralMetrics {\n    print(\"Interaction Intensity: \\(metrics[\"interaction_intensity\"] ?? 0)\")\n    print(\"Distraction Score: \\(metrics[\"behavioral_distraction_score\"] ?? 0)\")\n    print(\"Focus Hint: \\(metrics[\"behavioral_focus_hint\"] ?? 0)\")\n}\n\n// Typing metrics\nif let typing = summary.typingMetrics {\n    print(\"Typing Cadence: \\(typing[\"typing_cadence\"] ?? 0)\")\n    print(\"Mean Inter-Tap Interval: \\(typing[\"mean_inter_tap_interval_ms\"] ?? 0)\")\n}\n\n// Deep focus blocks\nprint(\"Deep Focus Blocks: \\(summary.deepFocusBlocks?.count ?? 0)\")\n```\n\n### On-Demand Metrics Calculation\n\nCalculate behavioral metrics for a custom time range within a session:\n\n```swift\nlet metrics = try behavior.calculateMetricsForTimeRange(\n    startTimestampSeconds: 1767688063,\n    endTimestampSeconds: 1767688130,\n    sessionId: sessionId\n)\n\nif let activity = metrics[\"activity_summary\"] as? [String: Any] {\n    print(\"Total events: \\(activity[\"total_events\"] ?? 0)\")\n    print(\"App switches: \\(activity[\"app_switch_count\"] ?? 0)\")\n}\n\nif let behavioral = metrics[\"behavioral_metrics\"] as? [String: Any] {\n    print(\"Interaction intensity: \\(behavioral[\"interaction_intensity\"] ?? 0)\")\n    print(\"Distraction score: \\(behavioral[\"behavioral_distraction_score\"] ?? 0)\")\n}\n```\n\n**Note**: The time range must be within the session's start and end times. The SDK validates this automatically and will throw an error if the range is out of bounds.\n\n### Current Statistics\n\nGet real-time statistics without ending a session:\n\n```swift\nlet stats = try behavior.getCurrentStats()\nprint(\"Typing cadence: \\(stats.typingCadence ?? 0)\")\nprint(\"Scroll velocity: \\(stats.scrollVelocity ?? 0)\")\nprint(\"App switches per minute: \\(stats.appSwitchesPerMinute)\")\nprint(\"Stability index: \\(stats.stabilityIndex ?? 0)\")\n```\n\n### Session Status\n\n```swift\n// Check current active session\nif let currentSessionId = behavior.getCurrentSessionId() {\n    print(\"Active session: \\(currentSessionId)\")\n}\n\n// Inspect events captured in the current session\nlet events = behavior.getSessionEvents()\nprint(\"Events so far: \\(events.count)\")\n```\n\n### Core Behavioral Metrics\n\nSession-level outputs include:\n\n- `interaction_intensity`: Overall interaction rate and engagement\n- `behavioral_distraction_score`: Behavioral proxy for distraction (0-1)\n- `behavioral_focus_hint`: Behavioral proxy for focus quality (0-1)\n- `task_switch_rate`: Frequency of app switching\n- `idle_ratio`: Proportion of idle time vs active interaction\n- `fragmented_idle_ratio`: Ratio of fragmented vs continuous idle periods\n- `burstiness`: Temporal clustering of interaction events\n- `notification_load`: Notification pressure and response patterns\n- `scroll_jitter_rate`: Scroll pattern irregularity\n\nPlus `deep_focus_blocks` (a list of sustained-engagement windows) on the summary itself.\n\nAll metrics are bounded, normalized, and numerically stable.\n\n## ⚙️ Additional Features\n\n### Custom Event Sending\n\nYou can manually send events to the SDK. Only the predefined event types are supported (scroll, tap, swipe, notification, call, typing, clipboard, appSwitch):\n\n```swift\nlet event = BehaviorEvent.tap(\n    sessionId: behavior.getCurrentSessionId() ?? \"current\",\n    tapDurationMs: 120,\n    longPress: false\n)\n\nbehavior.sendEvent(event)\n```\n\nEach event type has a corresponding factory on `BehaviorEvent` (`.scroll(...)`, `.tap(...)`, `.swipe(...)`, `.notification(...)`, `.call(...)`, `.typing(...)`, `.clipboard(...)`, `.appSwitch(...)`).\n\n### Cleanup\n\nAlways dispose of the SDK when done to free resources:\n\n```swift\ndeinit {\n    behavior.dispose()\n}\n```\n\n## 🔒 Privacy \u0026 Compliance\n\nThe Synheart SDK is designed around privacy-by-design and data minimization principles. It captures only the minimum interaction metadata required to model digital behavior, without accessing personal, semantic, or content-level information.\n\n### Hard Guarantees\n\n✅ **No PII**: The SDK does not collect names, contacts, account identifiers, message content, or any user-identifying data. All signals are timing-based and structural.\n\n✅ **No content capture**: The SDK does not collect notification text/titles/sender identity, call audio/voice data/participants, or application UI content/screen data.\n\n✅ **No keystroke logging**: Text input is never recorded. Interactions with text fields are captured only as abstract tap events (timing and duration only), without any character-level data.\n\n✅ **No audio or visual recording**: The SDK does not access the screen buffer, screenshots, camera, microphone, or any form of visual/audio capture.\n\n✅ **Permission-scoped tracking only**: Behavioral data is collected exclusively from applications that explicitly receive user permission. The SDK does not monitor, infer, or aggregate behavior across the entire device or across unpermitted applications.\n\n✅ **No tracking across unconsented apps**: The SDK only tracks behavior within the app that integrates it and has received user consent.\n\n✅ **Event-level metadata only**: Collected data is limited to event type (tap, scroll, swipe, notification, call), timestamp, and non-semantic physical metrics (duration, velocity). No semantic interpretation is performed at the data collection stage.\n\n### Connectivity \u0026 System Access\n\n✅ **No internet connectivity required**: The SDK functions fully offline and does not require an active internet connection to perform behavioral capture or inference.\n\n✅ **Network availability state only**: The SDK may record a binary system-level indicator of whether network connectivity is present at a given time. This signal does not include network traffic, destinations, IPs, or content, does not trigger any data transmission, and is used solely as contextual metadata.\n\n✅ **No Bluetooth or external connectivity required**: The SDK does not depend on Bluetooth, NFC, or communication with external devices.\n\n✅ **No background network communication**: Behavioral computation and aggregation occur locally without initiating network requests. Any optional data transmission is explicitly controlled, consent-gated, and configurable.\n\n### Processing \u0026 Storage\n\n✅ **On-device computation by default**: Behavioral features and metrics are computed locally on the device, minimizing data exposure.\n\n✅ **Ephemeral data handling**: Raw interaction events are processed in-memory and are not persisted in long-term storage unless explicitly configured for research or debugging purposes.\n\n✅ **No third-party data sharing**: The SDK does not share raw or derived behavioral data with advertisers, analytics providers, or external third parties.\n\n### Regulatory alignment\n\nThe SDK is designed around the principles of data minimization,\npurpose limitation, user consent, and transparency. See the\n[privacy audit](https://docs.synheart.ai/privacy/behavior) for the\ndetailed static-review notes. This is a self-assessment, not a\nthird-party certification — legal sufficiency for your specific\ndeployment depends on how you wire consent in your host app.\n\nThe SDK does not track users across apps, does not collect device\nidentifiers, and does not share data with ad-network brokers. Whether\nyour host app needs to present an ATT prompt depends on the rest of\nthe app's behavior, not on this SDK alone.\n\n## 📱 Platform Support\n\n- ✅ **iOS**: Swift 5.9+, iOS 13.0+\n- ✅ **Build**: Xcode 15.0+, Swift Package Manager\n\n## ⚡ Performance\n\nThe SDK is designed for continuous background operation with minimal\nresource impact: events are processed on background queues, and there\nis no persistent storage layer to flush. Specific CPU / memory /\nbattery numbers are deployment-dependent — earlier docs published\nfixed targets, but those were design goals, not measured runtime\nnumbers. Profile your integration with Instruments on the iOS device\nclass you ship.\n\n## 🏗️ Architecture\n\n```text\n┌──────────────────────────────────────────────────────┐\n│                    Your iOS App                       │\n│                                                       │\n│  ┌─────────────────────────────────────────────────┐  │\n│  │           SynheartBehavior SDK                   │  │\n│  │                                                  │  │\n│  │  BehaviorConfig ──► SynheartBehavior(config:)    │  │\n│  │                           │                      │  │\n│  │       ┌───────────────────┼───────────────┐      │  │\n│  │       ▼                   ▼               ▼      │  │\n│  │  InputSignal      ScrollSignal       Attention   │  │\n│  │  Collector        Collector          Collector   │  │\n│  │  (typing, taps,   (scroll dynamics)  (app switch,│  │\n│  │   gestures)                          idle, notif)│  │\n│  │       │                   │               │      │  │\n│  │       └─────────┬─────────┘───────────────┘      │  │\n│  │                 ▼                                 │  │\n│  │          EventBatcher ──► Event Handlers          │  │\n│  │                 │                                 │  │\n│  │                 ▼                                 │  │\n│  │     SessionManager ──► BehaviorSessionSummary     │  │\n│  └─────────────────────────────────────────────────┘  │\n└──────────────────────────────────────────────────────┘\n         │\n         ▼ (events forwarded to Synheart Core for HSI ingestion)\n```\n\nSignals flow: **Collectors → EventBatcher → SessionManager → Summary**.\nThe SDK never generates HSI directly — it collects and normalizes behavioral signals.\n\n## 🧪 Testing\n\n```bash\nswift build\nswift test\n```\n\nTests are in `Tests/SynheartBehaviorTests/` covering models (config, event, session, stats), SDK initialization, and event factories.\n\n## 📋 Requirements\n\n- **Swift**: 5.9+\n- **Xcode**: 15.0+\n- **iOS**: 12.0+\n\n## 🔍 Troubleshooting\n\n### SDK Not Initializing\n\n**Problem**: `try behavior.initialize()` throws.\n\n**Solutions**:\n\n- Make sure you only call `initialize()` once per `SynheartBehavior` instance.\n- Verify the iOS deployment target meets the requirement (12.0+).\n- Catch and log the underlying `BehaviorError` — `.invalidConfiguration` indicates a config issue, `.notInitialized` means another call slipped in before init completed.\n\n### No Events Being Collected\n\n**Problem**: The event handler is not firing.\n\n**Solutions**:\n\n- Confirm `setEventHandler(_:)` was called after `initialize()`.\n- Verify a session is started with `try behavior.startSession()`.\n- Check that `enableInputSignals` or `enableAttentionSignals` is `true` in your config.\n- For notifications/calls, ensure permissions are granted in the host app.\n\n### Permission Requests Not Working\n\n**Problem**: Notification or call events never arrive.\n\n**Solutions**:\n\n- **Notifications**: ensure `UNUserNotificationCenter` authorization was granted and forward `UNNotificationResponse` outcomes through the SDK's notification factory.\n- **Calls**: link `CallKit.framework` and confirm the app has the appropriate CallKit entitlement.\n- Test on a real device — the iOS simulator does not deliver call events.\n\n### Session End Fails\n\n**Problem**: `try behavior.endSession(sessionId:)` throws `.sessionNotFound` or another error.\n\n**Solutions**:\n\n- Make sure you pass the same `sessionId` returned by `startSession()`.\n- Sessions are tracked by ID, not as opaque handles — keep that ID alive on your side.\n- Wrap end-session calls in `do/catch` and log the error type.\n\n### Build Errors\n\n```bash\nswift package reset\nswift package update\nswift build\n```\n\nIf Xcode complains about resolution, close Xcode, delete `.swiftpm/` and `~/Library/Developer/Xcode/DerivedData/\u003cyour-app\u003e-*`, then re-resolve.\n\n## 🧪 Example App\n\nA complete example app demonstrating all SDK features is available in the [`Example/`](Example/) directory.\n\nTo run the example:\n\n```bash\ncd Example\nxcodegen generate    # if you use XcodeGen with project.yml\nopen ExampleApp.xcodeproj\n```\n\nThe example app includes:\n\n- Real-time event visualization\n- Session management UI\n- Time-range selection for on-demand metrics\n- Comprehensive session results display\n\n## 📚 API Reference\n\n### SynheartBehavior\n\n```swift\npublic class SynheartBehavior {\n    public init(config: BehaviorConfig)\n    public func initialize() throws\n    public func dispose()\n\n    // Sessions\n    public func startSession(sessionId: String? = nil) throws -\u003e String\n    public func endSession(sessionId: String) throws -\u003e BehaviorSessionSummary\n    public func getCurrentSessionId() -\u003e String?\n    public func getSessionEvents() -\u003e [BehaviorEvent]\n    public func getCurrentStats() throws -\u003e BehaviorStats\n\n    // Events\n    public func setEventHandler(_ handler: @escaping (BehaviorEvent) -\u003e Void)\n    public func setBatchEventHandler(_ handler: @escaping ([BehaviorEvent]) -\u003e Void)\n    public func sendEvent(_ event: BehaviorEvent)\n\n    // On-demand metrics\n    public func calculateMetricsForTimeRange(\n        startTimestampSeconds: Int,\n        endTimestampSeconds: Int,\n        sessionId: String?\n    ) throws -\u003e [String: Any]\n\n    // Configuration\n    public func updateConfig(_ config: BehaviorConfig) throws\n}\n```\n\n### Key Types\n\n| Type | Description |\n|---|---|\n| `BehaviorConfig` | SDK configuration (signals, batching, consent) |\n| `BehaviorEvent` | Single behavioral event with type and payload |\n| `BehaviorEventType` | `.scroll`, `.tap`, `.swipe`, `.notification`, `.call`, `.typing`, `.clipboard`, `.appSwitch` |\n| `BehaviorSession` | Active session handle (returned by `startSession()`'s session id) |\n| `BehaviorSessionSummary` | Aggregated session metrics (activity, behavioral, typing, deep focus blocks) |\n| `BehaviorStats` | Real-time metrics snapshot (cadence, velocity, stability) |\n| `BehaviorError` | `.notInitialized`, `.invalidConfiguration`, `.sessionNotFound` |\n\n## 📚 Documentation\n\nFull reference docs live at **[docs.synheart.ai/synheart-behavior/swift](https://docs.synheart.ai/synheart-behavior/swift)** — metric definitions, model card, threat model, error reference, and the cross-platform overview.\n\n## Contributing\n\nThis is a source-available repository. Issues and feature requests are\nwelcome; pull requests are not accepted at this time. See\n[CONTRIBUTING.md](CONTRIBUTING.md) for the rationale and the supported\ncontribution path.\n\n## 📄 License\n\nApache 2.0 License - see [LICENSE](LICENSE) file for details.\n\n## 🔗 Links\n\n- 📦 [Swift Package Index](https://swiftpackageindex.com/synheart-ai/synheart-behavior-swift)\n- 🔗 [GitHub repository](https://github.com/synheart-ai/synheart-behavior-swift)\n- 🔗 [Parent specification repository](https://github.com/synheart-ai/synheart-behavior)\n- 📖 [Example App Guide](Example/GUIDE.md)\n- 🔒 [Privacy audit](https://docs.synheart.ai/privacy/behavior)\n\n## 🔗 Related Projects\n\n| Repository | Description |\n|---|---|\n| [synheart-behavior](https://github.com/synheart-ai/synheart-behavior) | Specification \u0026 docs (Source of Truth) |\n| [synheart-behavior-flutter](https://github.com/synheart-ai/synheart-behavior-flutter) | Flutter/Dart SDK |\n| [synheart-behavior-kotlin](https://github.com/synheart-ai/synheart-behavior-kotlin) | Android/Kotlin SDK |\n| [synheart-behavior-chrome](https://github.com/synheart-ai/synheart-behavior-chrome) | Chrome extension |\n\n## Patent Pending Notice\n\nThis project is provided under an open-source license. Certain underlying systems, methods, and architectures described or implemented herein may be covered by one or more pending patent applications.\n\nNothing in this repository grants any license, express or implied, to any patents or patent applications, except as provided by the applicable open-source license.\n\n## Not a Medical Device\n\nThis SDK is intended for wellness and research use only. It is not a medical device, is not intended to diagnose, treat, cure, or prevent any disease or condition, and has not been evaluated by the FDA or any other regulatory body.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsynheart-ai%2Fsynheart-behavior-swift","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsynheart-ai%2Fsynheart-behavior-swift","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsynheart-ai%2Fsynheart-behavior-swift/lists"}