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

Kotlin Native and Swift Async/Await Memory & Coroutine Lifecycle Boundary Contract

Enforces strict lifecycle-aware termination, cooperative cancellation, and ownership boundaries across the Apple ARC and Kotlin/Native Concurrent Garbage Collector (GC) interface. Prevents detached Task retain cycles, uncollected Job reference leaks, and worker thread deadlocks caused by bidirectional reference holding across asynchronous Swift-to-Kotlin bridges.

Prohibited Anti-Pattern: Bridging Kotlin Suspend Functions Directly to Swift Tasks Without Cooperative Cancellation and Scope Deallocation Handlers

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Kotlin Native and Swift Async/Await Memory & Coroutine Lifecycle Boundary Contract - Enforces strict lifecycle-aware termination, cooperative cancellation, and ownership boundaries across the Apple ARC and Kotlin/Native Concurrent Garbage Collector (GC) interface. Prevents detached Task retain cycles, uncollected Job reference leaks, and worker thread deadlocks caused by bidirectional reference holding across asynchronous Swift-to-Kotlin bridges.
globs: iosApp/**/*.swift, shared/src/iosMain/**/*.kt, shared/src/commonMain/**/*.kt
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/kmp-swift-coroutines-memory-concurrency-contract"
---

# Kotlin Native and Swift Async/Await Memory & Coroutine Lifecycle Boundary Contract

> **Severity**: CRITICAL | **Category**: mobile
> **Anti-Pattern Warning**: Bridging Kotlin Suspend Functions Directly to Swift Tasks Without Cooperative Cancellation and Scope Deallocation Handlers

## System Constraints
You are a Principal Mobile Architect enforcing the Kotlin Multiplatform (KMP) Swift-Coroutines Memory Concurrency Contract. You must eliminate all unbounded Kotlin CoroutineScope bridges inside Apple platforms. Mandate explicit cancellation token propagation, zero cross-runtime strong reference cycles between Swift ARC objects and Kotlin Native objects, and ensure all Kotlin Flow-to-Swift AsyncSequence collectors tie their lifecycles strictly to SwiftUI view lifecycles or structured Swift Task hierarchies.

## Strict Guidelines
- Engineers MUST ALWAYS bridge Kotlin Flows using an explicit `Closeable` or `Disposable` handle that hooks into Swift's `withTaskCancellationHandler` to immediately cancel the underlying Kotlin `Job` upon Swift `Task` deallocation.
- Engineers MUST NOT expose naked global `CoroutineScope` instances (such as `GlobalScope`) or unbound singletons across the Objective-C/Swift export boundary.
- Code MUST wrap native Swift closures interacting with long-running Kotlin suspend calls in `[weak self]` or pass decoupled immutable value types to prevent ARC strong reference cycles from escaping into the Kotlin Native heap root sets.
- Services MUST ensure that UI-bound Kotlin `ViewModel` or `Presenter` instances exposed to Swift implement an explicit `clear()` or `onCleared()` method invoked within the SwiftUI `.onDisappear` or UIKit `deinit` hooks.
- Components NEVER bridge raw Objective-C completion handlers that capture strong references to Kotlin Coroutine `CancellableContinuation` without invoking completion exactly once during thread teardown, preventing native thread exhaustion.

## Bad vs Good Implementations
### SwiftUI Consumption of Kotlin Coroutines and Flows across ARC/Native GC Bridge

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Creating an unstructured Swift `Task` capturing `self` strongly keeps both the Swift observable object and the Kotlin Native iterator alive indefinitely. When the SwiftUI view dismisses, the Kotlin coroutine continues collecting in the background, anchoring native memory in the Kotlin GC root set and leaking ARC objects.
```swift
import SwiftUI
import SharedKit

final class UserObservableModel: ObservableObject {
    @Published var state: UserState = .idle
    private let repository = UserRepository()

    func observeData() {
        // CRITICAL BUG: Detached task captures strong self reference and leaks
        // the underlying Kotlin Job. The Kotlin runtime creates a root reference
        // preventing ARC deallocation, while Kotlin coroutine collector never terminates.
        Task {
            for await user in self.repository.userFlow {
                self.state = .success(user)
            }
        }
    }
}
```

#### Production Standard (Correct)
> **Standard**: The good pattern binds the Kotlin Flow iterator to a structured Swift `Task`, leverages `withTaskCancellationHandler` to immediately close the Kotlin native stream upon Swift task termination, and uses `[weak self]` to eliminate cross-runtime reference cycle pinning between Swift ARC and Kotlin Native GC.
```swift
import SwiftUI
import SharedKit

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

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

    func observeData() {
        observationTask?.cancel()
        observationTask = Task { [weak self] in
            // Cooperative cancellation bridge using Swift Task cancellation token
            let stream = self?.repository.userFlowStream()
            await withTaskCancellationHandler {
                do {
                    guard let stream = stream else { return }
                    for try await user in stream {
                        guard !Task.isCancelled else { break }
                        self?.state = .success(user)
                    }
                } catch {
                    self?.state = .failure(error)
                }
            } onCancel: {
                stream?.close()
            }
        }
    }

    func cancelObservation() {
        observationTask?.cancel()
        observationTask = nil
    }

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

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: Kotlin Native and Swift Async/Await Memory & Coroutine Lifecycle Boundary Contract

Kotlin Native and Swift Async/Await Memory & Coroutine Lifecycle Boundary Contract defines an industrial-grade behavioral standard for mobile engineering. Enforces strict lifecycle-aware termination, cooperative cancellation, and ownership boundaries across the Apple ARC and Kotlin/Native Concurrent Garbage Collector (GC) interface. Prevents detached Task retain cycles, uncollected Job reference leaks, and worker thread deadlocks caused by bidirectional reference holding across asynchronous Swift-to-Kotlin bridges. 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: Bridging Kotlin Suspend Functions Directly to Swift Tasks Without Cooperative Cancellation and Scope Deallocation Handlers 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 DriftBridging Kotlin Suspend Functions Directly to Swift Tasks Without Cooperative Cancellation and Scope Deallocation HandlersCritical
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 bridge Kotlin Flows using an explicit `Closeable` or `Disposable` handle that hooks into Swift's `withTaskCancellationHandler` to immediately cancel the underlying Kotlin `Job` upon Swift `Task` deallocation.

Engineers MUST ALWAYS bridge Kotlin Flows using an explicit `Closeable` or `Disposable` handle that hooks into Swift's `withTaskCancellationHandler` to immediately cancel the underlying Kotlin `Job` upon Swift `Task` deallocation.

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 naked global `CoroutineScope` instances (such as `GlobalScope`) or unbound singletons across the Objective-C/Swift export boundary.

Engineers MUST NOT expose naked global `CoroutineScope` instances (such as `GlobalScope`) or unbound singletons across the Objective-C/Swift export 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.
3

Code MUST wrap native Swift closures interacting with long-running Kotlin suspend calls in `[weak self]` or pass decoupled immutable value types to prevent ARC strong reference cycles from escaping into the Kotlin Native heap root sets.

Code MUST wrap native Swift closures interacting with long-running Kotlin suspend calls in `[weak self]` or pass decoupled immutable value types to prevent ARC strong reference cycles from escaping into the Kotlin Native heap root sets.

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

Services MUST ensure that UI-bound Kotlin `ViewModel` or `Presenter` instances exposed to Swift implement an explicit `clear()` or `onCleared()` method invoked within the SwiftUI `.onDisappear` or UIKit `deinit` hooks.

Services MUST ensure that UI-bound Kotlin `ViewModel` or `Presenter` instances exposed to Swift implement an explicit `clear()` or `onCleared()` method invoked within the SwiftUI `.onDisappear` or UIKit `deinit` hooks.

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 bridge raw Objective-C completion handlers that capture strong references to Kotlin Coroutine `CancellableContinuation` without invoking completion exactly once during thread teardown, preventing native thread exhaustion.

Components NEVER bridge raw Objective-C completion handlers that capture strong references to Kotlin Coroutine `CancellableContinuation` without invoking completion exactly once during thread teardown, preventing native thread exhaustion.

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 Kotlin Native and Swift Async/Await Memory & Coroutine Lifecycle Boundary Contract critical for AI coding assistants?

Enforces strict lifecycle-aware termination, cooperative cancellation, and ownership boundaries across the Apple ARC and Kotlin/Native Concurrent Garbage Collector (GC) interface. Prevents detached Task retain cycles, uncollected Job reference leaks, and worker thread deadlocks caused by bidirectional reference holding across asynchronous Swift-to-Kotlin bridges. 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 (Bridging Kotlin Suspend Functions Directly to Swift Tasks Without Cooperative Cancellation and Scope Deallocation Handlers) 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

Kotlin