This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
mobilecritical PriorityID: kmp-skie-swift-concurrency-coroutine-bridge-invariant

KMP SKIE Swift Concurrency and Coroutine Memory-Safe Cancellation Invariant

Enforces strict bidirectional cancellation propagation and deterministic lifecycle deallocation between Kotlin/Native Coroutines and Swift async/await via Touchlab SKIE. Prevents silent coroutine thread leaks and retain cycles caused by detached Swift Tasks holding strong Kotlin Job references across the foreign runtime boundary.

Prohibited Anti-Pattern: Detached Swift Task Leaks Kotlin Coroutine Scope and Traps Native ARC Retain Cycles

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: KMP SKIE Swift Concurrency and Coroutine Memory-Safe Cancellation Invariant - Enforces strict bidirectional cancellation propagation and deterministic lifecycle deallocation between Kotlin/Native Coroutines and Swift async/await via Touchlab SKIE. Prevents silent coroutine thread leaks and retain cycles caused by detached Swift Tasks holding strong Kotlin Job references across the foreign runtime boundary.
globs: iosApp/**/*.swift, shared/src/commonMain/kotlin/**/*.kt, shared/src/iosMain/kotlin/**/*.kt
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/kmp-skie-swift-concurrency-coroutine-bridge-invariant"
---

# KMP SKIE Swift Concurrency and Coroutine Memory-Safe Cancellation Invariant

> **Severity**: CRITICAL | **Category**: mobile
> **Anti-Pattern Warning**: Detached Swift Task Leaks Kotlin Coroutine Scope and Traps Native ARC Retain Cycles

## System Constraints
You are a Principal Mobile Architect enforcing bulletproof Kotlin Multiplatform (KMP) to Swift concurrency bindings via SKIE. You must ensure that every suspend function call, async stream, and Flow exposed to Swift strictly observes structured concurrency, guarantees cancellation propagation in both directions, and prevents object graph retain cycles across the ARC and Kotlin/Native GC boundary.

## Strict Guidelines
- Engineers MUST ALWAYS invoke SKIE-generated async Swift functions within an enclosing structured concurrency Task or AsyncSequence context that automatically propagates cancellation.
- Engineers MUST NOT bridge raw Kotlin CoroutineScope instances to Swift without explicit, deterministic cancellation hooks bound to iOS ViewController/View deinitialization.
- Swift code consuming SKIE-wrapped Kotlin Flows MUST consume them via SKIE's `AsyncSequence` interface and ensure iterating Tasks break upon cancellation.
- Kotlin suspend functions exposed via SKIE MUST NOT perform blocking or non-cancellable operations without checking `currentCoroutineContext().ensureActive()` before bridging back to Swift.
- Components NEVER capture self strongly in Swift closures bridging to Kotlin async APIs; always specify `[weak self]` or enforce structured parent-child task lifecycles.

## Bad vs Good Implementations
### Consuming SKIE Flow in Swift without Retain Cycle or Coroutine Leak

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Task.detached creates an un-scoped async operation that strongly retains self, leaking the ViewModel. Furthermore, if the SwiftUI view unmounts, the underlying Kotlin coroutine flow collector continues emitting indefinitely across the bridge.
```swift
import SwiftUI
import SharedKit

@MainActor
final class UserViewModel: ObservableObject {
    @Published var state: UserState = .initial
    private let repository: UserRepository

    init(repository: UserRepository) {
        self.repository = repository
        // ANTI-PATTERN: Detached task unlinked from lifecycle; ignores Task cancellation
        Task.detached {
            for await user in self.repository.userFlow {
                self.state = user
            }
        }
    }
}
```

#### Production Standard (Correct)
> **Standard**: Utilizes a manageable structured Task with weak self reference. Cancelling the Swift Task triggers SKIE's native bridge to cancel the underlying Kotlin Job immediately, releasing both ARC and Kotlin GC handles.
```swift
import SwiftUI
import SharedKit

@MainActor
final class UserViewModel: ObservableObject {
    @Published private(set) var state: UserState = .initial
    private let repository: UserRepository
    private var observationTask: Task<Void, Never>?

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

    func startObserving() {
        observationTask?.cancel()
        // Structured cancellation bound to ViewModel lifecycle
        observationTask = Task { [weak self] in
            do {
                for await user in self?.repository.userFlow ?? [] {
                    guard !Task.isCancelled else { break }
                    self?.state = user
                }
            } catch {
                // Handles CancellationError and SKIE bridge exceptions gracefully
            }
        }
    }

    deinit {
        // Explicitly cancels Swift task, triggering SKIE coroutine Job cancellation
        observationTask?.cancel()
    }
}
```

### Kotlin Coroutine Cancellation Check for Foreign SKIE Invocations

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: If Swift cancels the SKIE Task consuming this flow, the tight loop executing blocking native code fails to cooperative-cancel, causing the Kotlin Coroutine to run as a phantom worker thread in the background.
```kotlin
package com.example.shared

import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow

class DeviceMonitor {
    // ANTI-PATTERN: Heavy loop without yielding or checking cancellation
    fun observeMetrics(): Flow<MetricData> = flow {
        while (true) {
            val raw = pollHardwareBlocking()
            emit(raw.toMetric())
        }
    }
    private external fun pollHardwareBlocking(): RawHardwareData
}
```

#### Production Standard (Correct)
> **Standard**: Ensures that cancellation propagating across the SKIE runtime boundary from Swift async/await actively interrupts execution at `ensureActive()` and `yield()`.
```kotlin
package com.example.shared

import kotlinx.coroutines.currentCoroutineContext
import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.yield

class DeviceMonitor {
    // Guarantees SKIE cancellation signal from Swift immediately terminates the flow
    fun observeMetrics(): Flow<MetricData> = flow {
        while (true) {
            currentCoroutineContext().ensureActive()
            val raw = pollHardwareSuspendable()
            emit(raw.toMetric())
            yield()
        }
    }
    private suspend fun pollHardwareSuspendable(): RawHardwareData = TODO()
}
```

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 SKIE Swift Concurrency and Coroutine Memory-Safe Cancellation Invariant

KMP SKIE Swift Concurrency and Coroutine Memory-Safe Cancellation Invariant defines an industrial-grade behavioral standard for mobile engineering. Enforces strict bidirectional cancellation propagation and deterministic lifecycle deallocation between Kotlin/Native Coroutines and Swift async/await via Touchlab SKIE. Prevents silent coroutine thread leaks and retain cycles caused by detached Swift Tasks holding strong Kotlin Job references across the foreign runtime boundary. 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: Detached Swift Task Leaks Kotlin Coroutine Scope and Traps Native ARC Retain Cycles 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 DriftDetached Swift Task Leaks Kotlin Coroutine Scope and Traps Native ARC Retain CyclesCritical
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 invoke SKIE-generated async Swift functions within an enclosing structured concurrency Task or AsyncSequence context that automatically propagates cancellation.

Engineers MUST ALWAYS invoke SKIE-generated async Swift functions within an enclosing structured concurrency Task or AsyncSequence context that automatically propagates cancellation.

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 bridge raw Kotlin CoroutineScope instances to Swift without explicit, deterministic cancellation hooks bound to iOS ViewController/View deinitialization.

Engineers MUST NOT bridge raw Kotlin CoroutineScope instances to Swift without explicit, deterministic cancellation hooks bound to iOS ViewController/View deinitialization.

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 code consuming SKIE-wrapped Kotlin Flows MUST consume them via SKIE's `AsyncSequence` interface and ensure iterating Tasks break upon cancellation.

Swift code consuming SKIE-wrapped Kotlin Flows MUST consume them via SKIE's `AsyncSequence` interface and ensure iterating Tasks break upon cancellation.

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 suspend functions exposed via SKIE MUST NOT perform blocking or non-cancellable operations without checking `currentCoroutineContext().ensureActive()` before bridging back to Swift.

Kotlin suspend functions exposed via SKIE MUST NOT perform blocking or non-cancellable operations without checking `currentCoroutineContext().ensureActive()` before bridging back 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.
5

Components NEVER capture self strongly in Swift closures bridging to Kotlin async APIs

Components NEVER capture self strongly in Swift closures bridging to Kotlin async APIs; always specify `[weak self]` or enforce structured parent-child task lifecycles.

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 SKIE Swift Concurrency and Coroutine Memory-Safe Cancellation Invariant critical for AI coding assistants?

Enforces strict bidirectional cancellation propagation and deterministic lifecycle deallocation between Kotlin/Native Coroutines and Swift async/await via Touchlab SKIE. Prevents silent coroutine thread leaks and retain cycles caused by detached Swift Tasks holding strong Kotlin Job references across the foreign runtime boundary. 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 (Detached Swift Task Leaks Kotlin Coroutine Scope and Traps Native ARC Retain Cycles) 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