This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
mobilecritical PriorityID: kmp-swift-coroutines-memory-isolation-guardrail

KMP to Swift Memory Isolation and Coroutine Dispatch Bridge Invariants

Prevents memory corruption, thread confinement violations, and runtime crashes when bridging Kotlin Coroutines/Flows with Swift async/await and GCD across Darwin runtimes. Enforces strict boundary dispatching via KMP-native wrappers, eliminating raw Objective-C interop pointer leaks and concurrent unconfined mutation of shared state.

Prohibited Anti-Pattern: Unconfined Kotlin Flow Collection Across Swift Dispatch Queues Causing Native Heap Corruption

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: KMP to Swift Memory Isolation and Coroutine Dispatch Bridge Invariants - Prevents memory corruption, thread confinement violations, and runtime crashes when bridging Kotlin Coroutines/Flows with Swift async/await and GCD across Darwin runtimes. Enforces strict boundary dispatching via KMP-native wrappers, eliminating raw Objective-C interop pointer leaks and concurrent unconfined mutation of shared state.
globs: shared/**/commonMain/**/*.kt, shared/**/iosMain/**/*.kt, iosApp/**/*.swift
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/kmp-swift-coroutines-memory-isolation-guardrail"
---

# KMP to Swift Memory Isolation and Coroutine Dispatch Bridge Invariants

> **Severity**: CRITICAL | **Category**: mobile
> **Anti-Pattern Warning**: Unconfined Kotlin Flow Collection Across Swift Dispatch Queues Causing Native Heap Corruption

## System Constraints
You are a Principal Mobile Architect enforcing Kotlin Multiplatform (KMP) Swift-Coroutines Memory Isolation Bridge standards. Mandate strictly isolated cross-runtime async models, zero thread leaks between Swift Task contexts and Kotlin Dispatchers, immutable snapshot transfers across the Objective-C interop boundary, and deterministic lifecycle cancellation.

## Strict Guidelines
- Engineers MUST ALWAYS expose Kotlin Flows to Swift through an explicit SKIE bridge, KMP-NativeCoroutines wrapper, or an actor-confined observable bridge that confines consumption to the Swift MainActor or a designated Serial Executor.
- Engineers MUST NOT expose raw mutable Kotlin state containers (such as MutableStateFlow or mutable collections) across the Objective-C interop boundary to Swift.
- Swift clients MUST bind Kotlin coroutine cancellation tokens directly to Swift Task lifecycles to prevent detached orphan coroutines retaining Swift deallocated reference contexts.
- Kotlin iosMain platform bridges MUST explicitly declare thread affinity using Dispatchers.Main.immediate or Dispatchers.Default and NEVER execute work on unconfined threads crossing into native Darwin callbacks.
- Shared domain payloads crossing the interop boundary MUST be deeply immutable data classes or primitive value types to prevent multi-threaded data races under native Darwin thread sanitizers.

## Bad vs Good Implementations
### Bridging Kotlin StateFlow to Swift AsyncSequence without Native Thread Violations

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Directly exposing raw MutableStateFlow allows Swift to mutate and observe cross-platform state across arbitrary threads without synchronization, violating Darwin memory barriers and leading to native race conditions.
```kotlin
// shared/src/iosMain/kotlin/UserBridge.kt
import kotlinx.coroutines.flow.MutableStateFlow

// ANTI-PATTERN: Exposing raw MutableStateFlow directly to Objective-C/Swift interop
class UserRepositoryBridge {
    val userState = MutableStateFlow<String>("Initial")
    
    fun mutateState(value: String) {
        // Unconfined mutation across arbitrary native threads
        userState.value = value
    }
}
```

#### Production Standard (Correct)
> **Standard**: Encapsulates state mutability within a structured Kotlin coroutine scope pinned to Dispatchers.Main.immediate. Swift consumes an immutable StateFlow, eliminating concurrent raw memory corruption across Darwin thread runtimes.
```kotlin
// shared/src/iosMain/kotlin/UserBridge.kt
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

// PRODUCTION FIX: Confine emission to Dispatchers.Main and expose immutable read-only wrappers
class UserRepositoryBridge private constructor(
    private val scope: CoroutineScope
) {
    constructor() : this(CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate))

    private val _userState = MutableStateFlow<String>("Initial")
    val userState: StateFlow<String> = _userState.asStateFlow()

    fun update(value: String) {
        scope.launch {
            _userState.value = value
        }
    }

    fun close() {
        scope.cancel()
    }
}
```

### Swift Actor Consumption of KMP Flows with Strict Cancellation Binding

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Using Task.detached creates an unconfined concurrent task that bypasses MainActor isolation, and fails to handle Task cancellation, leaving KMP coroutine collectors active in the native runtime indefinitely.
```swift
// iosApp/StateObserver.swift
import SharedKit

// ANTI-PATTERN: Unconfined Task collection without lifecycle cancellation handling
class StateObserver {
    let bridge = UserRepositoryBridge()
    
    func listen() {
        Task.detached {
            // Leaks coroutine bridge and fails to sync with Darwin MainActor
            for await item in self.bridge.userState {
                print("Item: \(item)")
            }
        }
    }
}
```

#### Production Standard (Correct)
> **Standard**: Guarantees MainActor confinement for native Swift UI bindings, uses Task cancellation checking, and releases both Swift and Kotlin coroutine lifecycles upon object deallocation.
```swift
// iosApp/StateObserver.swift
import SharedKit
import SwiftUI

// PRODUCTION FIX: MainActor confined execution bound to Task lifecycle
@MainActor
final class StateObserver: ObservableObject {
    private let bridge: UserRepositoryBridge
    private var observationTask: Task<Void, Never>?
    @Published private(set) var currentState: String = ""

    init(bridge: UserRepositoryBridge = UserRepositoryBridge()) {
        self.bridge = bridge
    }

    func startObserving() {
        observationTask?.cancel()
        observationTask = Task { [weak self] in
            for await item in self?.bridge.userState ?? [] {
                guard !Task.isCancelled else { break }
                self?.currentState = item
            }
        }
    }

    deinit {
        observationTask?.cancel()
        bridge.close()
    }
}
```

Recommended MCP Servers (mcp-serverlist.com)

Equip agent with system tools to verify code for this stack.

Architectural Specification & Invariant Rationale

Architectural Invariant Design: KMP to Swift Memory Isolation and Coroutine Dispatch Bridge Invariants

KMP to Swift Memory Isolation and Coroutine Dispatch Bridge Invariants defines an industrial-grade behavioral standard for mobile engineering. Prevents memory corruption, thread confinement violations, and runtime crashes when bridging Kotlin Coroutines/Flows with Swift async/await and GCD across Darwin runtimes. Enforces strict boundary dispatching via KMP-native wrappers, eliminating raw Objective-C interop pointer leaks and concurrent unconfined mutation of shared state. Modern software architectures require strict adherence to deterministic patterns to guarantee high availability, maintainability, and zero security vulnerabilities.

Framework Paradigm Shift & Drift MechanicsLLMs are trained on millions of open-source repositories containing outdated code, legacy idioms, and unpatched antipatterns. When coding assistants generate implementations for this stack, they default to common statistical tokens: Unconfined Kotlin Flow Collection Across Swift Dispatch Queues Causing Native Heap Corruption Without an explicit system instruction file, developers spend hours debugging silent failures.
Failure Modes & Production Blast Radius

Hazard Analysis: What Breaks Without This Rule

The following failure modes have been cataloged from hundreds of hours of production code reviews where AI assistants produced non-compliant implementations:

Failure ModeAI Symptom (The Anti-Pattern)SeverityProduction Impact & Remedy
AI Hallucination & Deprecation DriftUnconfined Kotlin Flow Collection Across Swift Dispatch Queues Causing Native Heap CorruptionCritical
Violating this industrial standard introduces regression bugs, security risks, and unexpected runtime failures in production.
Enforce explicit behavioral system directives across all AI coding assistants in your repository.
Silent Architecture InconsistencyAI assistants produce mixed paradigms across files, creating fragmented codebase conventions.Medium
Increases cognitive load during code reviews and leads to maintenance debt across engineering teams.
Pin project conventions in .cursor/rules, CLAUDE.md, and AGENTS.md so all team agents follow identical guardrails.
Architectural Directives in Detail

Step-by-Step Production Directives

Each rule constraint below is injected into the AI agent's system prompt to establish deterministic boundaries:

1

Engineers MUST ALWAYS expose Kotlin Flows to Swift through an explicit SKIE bridge, KMP-NativeCoroutines wrapper, or an actor-confined observable bridge that confines consumption to the Swift MainActor or a designated Serial Executor.

Engineers MUST ALWAYS expose Kotlin Flows to Swift through an explicit SKIE bridge, KMP-NativeCoroutines wrapper, or an actor-confined observable bridge that confines consumption to the Swift MainActor or a designated Serial Executor.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
2

Engineers MUST NOT expose raw mutable Kotlin state containers (such as MutableStateFlow or mutable collections) across the Objective-C interop boundary to Swift.

Engineers MUST NOT expose raw mutable Kotlin state containers (such as MutableStateFlow or mutable collections) across the Objective-C interop boundary to Swift.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
3

Swift clients MUST bind Kotlin coroutine cancellation tokens directly to Swift Task lifecycles to prevent detached orphan coroutines retaining Swift deallocated reference contexts.

Swift clients MUST bind Kotlin coroutine cancellation tokens directly to Swift Task lifecycles to prevent detached orphan coroutines retaining Swift deallocated reference contexts.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
4

Kotlin iosMain platform bridges MUST explicitly declare thread affinity using Dispatchers.Main.immediate or Dispatchers.Default and NEVER execute work on unconfined threads crossing into native Darwin callbacks.

Kotlin iosMain platform bridges MUST explicitly declare thread affinity using Dispatchers.Main.immediate or Dispatchers.Default and NEVER execute work on unconfined threads crossing into native Darwin callbacks.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
5

Shared domain payloads crossing the interop boundary MUST be deeply immutable data classes or primitive value types to prevent multi-threaded data races under native Darwin thread sanitizers.

Shared domain payloads crossing the interop boundary MUST be deeply immutable data classes or primitive value types to prevent multi-threaded data races under native Darwin thread sanitizers.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
Technical Questions & Answers

Frequently Asked Technical Questions

Common questions developers face when configuring AI coding assistants for this stack:

Q:Why is KMP to Swift Memory Isolation and Coroutine Dispatch Bridge Invariants critical for AI coding assistants?

Prevents memory corruption, thread confinement violations, and runtime crashes when bridging Kotlin Coroutines/Flows with Swift async/await and GCD across Darwin runtimes. Enforces strict boundary dispatching via KMP-native wrappers, eliminating raw Objective-C interop pointer leaks and concurrent unconfined mutation of shared state. Without explicit behavioral boundaries, AI coding assistants (Cursor, Claude Code, Windsurf, Codex) rely on training data averages, which frequently produce deprecated, inefficient, or vulnerable code patterns.

Q:How does adopting this rule prevent AI hallucinations?

This rule explicitly declares what the AI must avoid (Unconfined Kotlin Flow Collection Across Swift Dispatch Queues Causing Native Heap Corruption) and prescribes verified positive examples. Grounding the LLM with negative and positive pairs eliminates guesswork.

Q:Which AI coding environments are supported?

This specification is multi-platform compatible: Cursor (.cursor/rules/*.mdc & .cursorrules), Anthropic Claude Code (CLAUDE.md), Windsurf (.windsurfrules), Codex / Cline (AGENTS.md), and GitHub Copilot (.github/copilot-instructions.md).

Q:Can I combine this rule with other technology stacks?

Yes. Use the Interactive Stack Builder or download an Agent Pack to merge this rule with other frontend, backend, database, security, and DevOps rules without syntax collision.

Open Specification · CC BY 4.0·Free for Personal, Team & Commercial In-Repo Use

Citation & Open Source Attribution Guidelines

This specification is licensed under Creative Commons Attribution 4.0 International (CC BY 4.0). You are completely free to adapt and share this rule in your workspace. If citing, including in public AI benchmark datasets, or redistributing, attribution to AgentRules.org is required.

Related MOBILE Rules

View all rules →
1 Rule in Stack

KMP