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

KMP 2.1 and Swift 6 Strict Concurrency Isolation and Sendable Interop Boundary

Enforces complete data race safety across the Kotlin Multiplatform 2.1 and Swift 6 language boundary by isolating Objective-C export interfaces within strict Swift actors. Prevents passing non-Sendable Kotlin reference types across asynchronous boundaries and mandates thread-safe Sendable DTO contracts or SKIE-generated Swift concurrency wrappers for all exported Coroutine flows and suspend functions.

Prohibited Anti-Pattern: Passing Non-Sendable Kotlin Reference Types and Unisolated Completion Handlers Across Swift 6 Actor Boundaries

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: KMP 2.1 and Swift 6 Strict Concurrency Isolation and Sendable Interop Boundary - Enforces complete data race safety across the Kotlin Multiplatform 2.1 and Swift 6 language boundary by isolating Objective-C export interfaces within strict Swift actors. Prevents passing non-Sendable Kotlin reference types across asynchronous boundaries and mandates thread-safe Sendable DTO contracts or SKIE-generated Swift concurrency wrappers for all exported Coroutine flows and suspend functions.
globs: **/*.kt, **/*.swift, **/build.gradle.kts
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/kmp-swift6-strict-concurrency-isolation-guardrail"
---

# KMP 2.1 and Swift 6 Strict Concurrency Isolation and Sendable Interop Boundary

> **Severity**: CRITICAL | **Category**: mobile
> **Anti-Pattern Warning**: Passing Non-Sendable Kotlin Reference Types and Unisolated Completion Handlers Across Swift 6 Actor Boundaries

## System Constraints
You are a Principal Mobile Architect specializing in Kotlin Multiplatform 2.1 and Swift 6 strict concurrency. Your mandate is to enforce zero data-race runtime exceptions and eliminate Swift 6 compiler concurrency diagnostics (`-strict-concurrency=complete`). Ensure all bridged Kotlin classes, suspend functions, and Flow emissions cross the FFI boundary exclusively as thread-safe Sendable primitives, actor-confined instances, or verified immutable models.

## Strict Guidelines
- Engineers MUST ALWAYS compile Swift targets with `SWIFT_STRICT_CONCURRENCY = complete` to catch bridge-crossing Sendable violations at compile-time.
- Engineers MUST NOT pass raw Kotlin mutable reference classes across Swift actor boundaries without an explicit Swift actor isolation or `@Sendable` value-type transformation.
- Engineers MUST ensure all bridged Kotlin suspend functions invoked from Swift 6 are isolated to the caller's actor (typically `@MainActor`) or wrapped in an actor-isolated facade.
- Kotlin shared domain models intended for Swift cross-boundary dispatch MUST be deeply immutable (consisting solely of primitive types, immutable strings, or nested immutable data classes).
- Teams MUST use SKIE or explicit Swift concurrency wrappers to convert Kotlin `StateFlow` and `SharedFlow` into `AsyncSequence` conforming to Swift 6 Sendable requirements.
- Components NEVER bridge Kotlin mutable collections (`MutableList`, `MutableMap`, `MutableSet`) to Swift; collections must be exported as immutable collections and copied to Swift native value types (`Array`, `Dictionary`, `Set`) at the boundary.
- Engineers MUST NOT apply `@unchecked Sendable` to Kotlin Objective-C bridged classes unless the Kotlin class is provably immutable, thread-confined, or internally synchronized with cross-platform primitives.

## Bad vs Good Implementations
### Swift 6 Interop Boundary with KMP Shared State and Coroutines

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Kotlin Native exports classes to Objective-C as reference types that do not conform to Swift 6's Sendable protocol. Accessing unconfined Kotlin objects inside a detached Task or raw completion handler triggers strict concurrency compiler errors and causes undefined behavior when mutable Kotlin state is accessed concurrently across OS threads.
```swift
// Swift 6 with SWIFT_STRICT_CONCURRENCY = complete
import SharedKit

// ANTI-PATTERN: Direct exposure of un-isolated Kotlin reference type across concurrency domains.
class ProfileViewModel: ObservableObject {
    // Non-Sendable Kotlin class imported via ObjC bridge creates data races across threads
    private let repository = UserRepository() 

    func loadUser(id: String) {
        Task.detached {
            // Violation: Calling unisolated Kotlin completion-based suspend function
            // captures non-Sendable Kotlin reference in concurrent Task
            self.repository.fetchUser(id: id) { user, error in
                DispatchQueue.main.async {
                    // Race condition on shared state mutation
                    print("Loaded: \(String(describing: user?.name))")
                }
            }
        }
    }
}
```

#### Production Standard (Correct)
> **Standard**: The view model is isolated to `@MainActor`, eliminating data races on published state. The Kotlin suspend call is invoked within structured concurrency, and the received Kotlin object is immediately mapped into an immutable, `Sendable` Swift struct before traversing any further asynchronous boundaries.
```swift
// Swift 6 with SWIFT_STRICT_CONCURRENCY = complete
import SharedKit

// PRODUCTION FIX: Confinement to @MainActor and conversion to immutable Sendable models
@MainActor
final class ProfileViewModel: ObservableObject {
    @Published private(set) var userState: UserUiModel? = nil
    private let repository: UserRepository

    init(repository: UserRepository) {
        self.repository = repository
    }

    func loadUser(id: String) async {
        do {
            // Suspended within @MainActor context using SKIE-generated async bridge
            // or isolated async wrapper returning an immutable model
            let kotlinUser = try await repository.fetchUser(id: id)
            
            // Map Kotlin reference to a native, Sendable Swift Struct immediately
            self.userState = UserUiModel(from: kotlinUser)
        } catch {
            // Structured error handling respecting Swift 6 cancellation
            self.userState = nil
        }
    }
}

// Swift-native Sendable DTO boundary
struct UserUiModel: Sendable, Equatable {
    let id: String
    let name: String

    init(from kotlinUser: SharedKit.User) {
        self.id = kotlinUser.id
        self.name = kotlinUser.name
    }
}
```

### Kotlin Multiplatform 2.1 Immutable Boundary Export

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Exposing mutable state (`MutableMap`, `MutableList`) directly to Swift breaks thread-safety invariants under Kotlin Native's memory model and causes Swift 6 data races when invoked concurrently.
```kotlin
// Kotlin Multiplatform Shared Module
package com.example.shared

// ANTI-PATTERN: Mutable state exposed over Obj-C/Swift bridge
class UserRepository {
    var cachedUsers: MutableMap<String, User> = mutableMapOf()

    // Exposes mutable Kotlin collection to Swift
    fun getCachedUserList(): MutableList<User> {
        return cachedUsers.values.toMutableList()
    }

    suspend fun fetchUser(id: String): User {
        val user = apiCall(id)
        cachedUsers[id] = user // Unsynchronized mutation across platform threads
        return user
    }
}
```

#### Production Standard (Correct)
> **Standard**: Kotlin state mutations are guarded with a Coroutine Mutex on `Dispatchers.Default`. The exposed contracts use immutable `data class` models and immutable `List` structures, ensuring zero race conditions when crossed into Swift 6.
```kotlin
// Kotlin Multiplatform Shared Module
package com.example.shared

import kotlinx.coroutines.withContext
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock

// PRODUCTION FIX: Deeply immutable data contracts with protected concurrent mutations
data class User(
    val id: String,
    val name: String
) // Immutable value type

class UserRepository {
    private val mutex = Mutex()
    private val cachedUsers = mutableMapOf<String, User>()

    // Return an immutable snapshot list to Swift
    suspend fun getCachedUserList(): List<User> = mutex.withLock {
        cachedUsers.values.toList()
    }

    suspend fun fetchUser(id: String): User = withContext(Dispatchers.Default) {
        val user = apiCall(id)
        mutex.withLock {
            cachedUsers[id] = user
        }
        user
    }
}
```

Recommended MCP Servers (mcp-serverlist.com)

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

Recommended Agent Skills (askills.dev)

Ready-to-use executable skill functions tailored to this stack.

Architectural Specification & Invariant Rationale

Architectural Invariant Design: KMP 2.1 and Swift 6 Strict Concurrency Isolation and Sendable Interop Boundary

KMP 2.1 and Swift 6 Strict Concurrency Isolation and Sendable Interop Boundary defines an industrial-grade behavioral standard for mobile engineering. Enforces complete data race safety across the Kotlin Multiplatform 2.1 and Swift 6 language boundary by isolating Objective-C export interfaces within strict Swift actors. Prevents passing non-Sendable Kotlin reference types across asynchronous boundaries and mandates thread-safe Sendable DTO contracts or SKIE-generated Swift concurrency wrappers for all exported Coroutine flows and suspend functions. 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: Passing Non-Sendable Kotlin Reference Types and Unisolated Completion Handlers Across Swift 6 Actor Boundaries 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 DriftPassing Non-Sendable Kotlin Reference Types and Unisolated Completion Handlers Across Swift 6 Actor BoundariesCritical
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 compile Swift targets with `SWIFT_STRICT_CONCURRENCY = complete` to catch bridge-crossing Sendable violations at compile-time.

Engineers MUST ALWAYS compile Swift targets with `SWIFT_STRICT_CONCURRENCY = complete` to catch bridge-crossing Sendable violations at compile-time.

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 pass raw Kotlin mutable reference classes across Swift actor boundaries without an explicit Swift actor isolation or `@Sendable` value-type transformation.

Engineers MUST NOT pass raw Kotlin mutable reference classes across Swift actor boundaries without an explicit Swift actor isolation or `@Sendable` value-type transformation.

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

Engineers MUST ensure all bridged Kotlin suspend functions invoked from Swift 6 are isolated to the caller's actor (typically `@MainActor`) or wrapped in an actor-isolated facade.

Engineers MUST ensure all bridged Kotlin suspend functions invoked from Swift 6 are isolated to the caller's actor (typically `@MainActor`) or wrapped in an actor-isolated facade.

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 shared domain models intended for Swift cross-boundary dispatch MUST be deeply immutable (consisting solely of primitive types, immutable strings, or nested immutable data classes).

Kotlin shared domain models intended for Swift cross-boundary dispatch MUST be deeply immutable (consisting solely of primitive types, immutable strings, or nested immutable data classes).

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

Teams MUST use SKIE or explicit Swift concurrency wrappers to convert Kotlin `StateFlow` and `SharedFlow` into `AsyncSequence` conforming to Swift 6 Sendable requirements.

Teams MUST use SKIE or explicit Swift concurrency wrappers to convert Kotlin `StateFlow` and `SharedFlow` into `AsyncSequence` conforming to Swift 6 Sendable requirements.

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

Components NEVER bridge Kotlin mutable collections (`MutableList`, `MutableMap`, `MutableSet`) to Swift

Components NEVER bridge Kotlin mutable collections (`MutableList`, `MutableMap`, `MutableSet`) to Swift; collections must be exported as immutable collections and copied to Swift native value types (`Array`, `Dictionary`, `Set`) at the boundary.

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

Engineers MUST NOT apply `@unchecked Sendable` to Kotlin Objective-C bridged classes unless the Kotlin class is provably immutable, thread-confined, or internally synchronized with cross-platform primitives.

Engineers MUST NOT apply `@unchecked Sendable` to Kotlin Objective-C bridged classes unless the Kotlin class is provably immutable, thread-confined, or internally synchronized with cross-platform primitives.

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 2.1 and Swift 6 Strict Concurrency Isolation and Sendable Interop Boundary critical for AI coding assistants?

Enforces complete data race safety across the Kotlin Multiplatform 2.1 and Swift 6 language boundary by isolating Objective-C export interfaces within strict Swift actors. Prevents passing non-Sendable Kotlin reference types across asynchronous boundaries and mandates thread-safe Sendable DTO contracts or SKIE-generated Swift concurrency wrappers for all exported Coroutine flows and suspend functions. 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 (Passing Non-Sendable Kotlin Reference Types and Unisolated Completion Handlers Across Swift 6 Actor Boundaries) 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