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

KMP-Swift Concurrency Lifespan & Cooperative Cancellation Guardrail

Enforces deterministic lifecycle synchronization, thread-safe memory boundaries, and bidirectional cooperative cancellation between Kotlin Coroutines and Swift Structured Concurrency. Prevents orphaned background jobs, GC root retention leaks across the Objective-C export bridge, and cooperative thread pool starvation.

Prohibited Anti-Pattern: Dangling Kotlin Coroutine Jobs and Leaked Native GC Roots via Unstructured Swift Task Wrappers

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: KMP-Swift Concurrency Lifespan & Cooperative Cancellation Guardrail - Enforces deterministic lifecycle synchronization, thread-safe memory boundaries, and bidirectional cooperative cancellation between Kotlin Coroutines and Swift Structured Concurrency. Prevents orphaned background jobs, GC root retention leaks across the Objective-C export bridge, and cooperative thread pool starvation.
globs: iosApp/**/*.swift, ios/**/*.swift, shared/src/iosMain/**/*.kt, **/interop/**/*.swift
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/kmp-swift-concurrency-lifespan-bridge-guardrail"
---

# KMP-Swift Concurrency Lifespan & Cooperative Cancellation Guardrail

> **Severity**: CRITICAL | **Category**: mobile
> **Anti-Pattern Warning**: Dangling Kotlin Coroutine Jobs and Leaked Native GC Roots via Unstructured Swift Task Wrappers

## System Constraints
You are a Principal Mobile Architect specializing in Kotlin Multiplatform (KMP) and Swift Concurrency runtime interoperability. Enforce strict invariants regarding bidirectional cancellation propagation, GC-ARC root boundaries, and cooperative thread safety when bridging Kotlin Coroutines to Swift Async/Await.

## Strict Guidelines
- Engineers MUST ALWAYS propagate Swift Task cancellation to Kotlin Coroutine Jobs using withTaskCancellationHandler or certified runtime toolchains (e.g., SKIE).
- Engineers MUST NOT block Swift's cooperative thread pool by calling blocking KMP functions or invoking runBlocking across the foreign function interface.
- Swift bridging code MUST clean up active Kotlin Flows by binding their Job lifecycle to AsyncThrowingStream.onTermination to prevent unbounded collection leaks.
- Engineers MUST NEVER introduce strong retain cycles across the Swift ARC and Kotlin Native GC barrier; closures capturing bridged Kotlin references must be scoped to deterministic Lifetimes.
- Kotlin suspend functions exposed via the Objective-C interop MUST be consumed with explicit error handling for Kotlin CancellationException to avoid false positive error states in Swift.

## Bad vs Good Implementations
### Bridging a KMP Flow to a Swift AsyncSequence with Bidirectional Cancellation

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: The Kotlin coroutine continues collecting the Flow indefinitely in the background even if the consumer terminates the Swift AsyncStream or cancels the parent Swift Task. Furthermore, the strong reference to the repository and watcher closure remains rooted in memory, leaking across the ARC/K-N GC boundary.
```swift
import Shared

// Anti-pattern: Leaks Kotlin Job and ignores Swift Task cancellation.
// Consumes flow via raw closure; if caller cancels Swift Task, Kotlin Flow remains active.
func observeUserProfile(userId: String) -> AsyncStream<UserProfile> {
    AsyncStream { continuation in
        let repository = UserRepositoryCompanion.shared.create()
        // Raw export creates an unmanaged coroutine job in KMP
        repository.observeProfile(userId: userId).watch { profile in
            if let profile = profile {
                continuation.yield(profile)
            }
        }
        // Failure: No onTermination hook to cancel the underlying Kotlin coroutine
    }
}
```

#### Production Standard (Correct)
> **Standard**: By capturing the underlying SharedCancellable and hooking into continuation.onTermination, any cancellation of the Swift Task or consumer teardown deterministically cancels the Kotlin coroutine Job, severing the retain cycle across the Objective-C bridge and allowing Kotlin Native GC to reclaim references.
```swift
import Shared

// Production standard: Bidirectional cooperative cancellation and lifecycle cleanup.
func observeUserProfile(userId: String) -> AsyncThrowingStream<UserProfile, Error> {
    AsyncThrowingStream { continuation in
        let repository = UserRepositoryCompanion.shared.create()
        
        // Explicitly retain the Kotlin Cancellable/Job reference
        let watcherJob: SharedCancellable = repository.observeProfile(userId: userId).watch(
            onEach: { profile in
                continuation.yield(profile)
            },
            onCompletion: { error in
                if let error = error {
                    continuation.finish(throwing: error.asNSError())
                } else {
                    continuation.finish()
                }
            }
        )
        
        // Guarantee termination cleanup when Swift Task or downstream consumer drops the stream
        continuation.onTermination = { @Sendable _ in
            watcherJob.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: KMP-Swift Concurrency Lifespan & Cooperative Cancellation Guardrail

KMP-Swift Concurrency Lifespan & Cooperative Cancellation Guardrail defines an industrial-grade behavioral standard for mobile engineering. Enforces deterministic lifecycle synchronization, thread-safe memory boundaries, and bidirectional cooperative cancellation between Kotlin Coroutines and Swift Structured Concurrency. Prevents orphaned background jobs, GC root retention leaks across the Objective-C export bridge, and cooperative thread pool starvation. 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: Dangling Kotlin Coroutine Jobs and Leaked Native GC Roots via Unstructured Swift Task Wrappers 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 DriftDangling Kotlin Coroutine Jobs and Leaked Native GC Roots via Unstructured Swift Task WrappersCritical
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 propagate Swift Task cancellation to Kotlin Coroutine Jobs using withTaskCancellationHandler or certified runtime toolchains (e.g., SKIE).

Engineers MUST ALWAYS propagate Swift Task cancellation to Kotlin Coroutine Jobs using withTaskCancellationHandler or certified runtime toolchains (e.g., SKIE).

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 block Swift's cooperative thread pool by calling blocking KMP functions or invoking runBlocking across the foreign function interface.

Engineers MUST NOT block Swift's cooperative thread pool by calling blocking KMP functions or invoking runBlocking across the foreign function interface.

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 bridging code MUST clean up active Kotlin Flows by binding their Job lifecycle to AsyncThrowingStream.onTermination to prevent unbounded collection leaks.

Swift bridging code MUST clean up active Kotlin Flows by binding their Job lifecycle to AsyncThrowingStream.onTermination to prevent unbounded collection leaks.

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

Engineers MUST NEVER introduce strong retain cycles across the Swift ARC and Kotlin Native GC barrier

Engineers MUST NEVER introduce strong retain cycles across the Swift ARC and Kotlin Native GC barrier; closures capturing bridged Kotlin references must be scoped to deterministic Lifetimes.

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

Kotlin suspend functions exposed via the Objective-C interop MUST be consumed with explicit error handling for Kotlin CancellationException to avoid false positive error states in Swift.

Kotlin suspend functions exposed via the Objective-C interop MUST be consumed with explicit error handling for Kotlin CancellationException to avoid false positive error states in 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.
Technical Questions & Answers

Frequently Asked Technical Questions

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

Q:Why is KMP-Swift Concurrency Lifespan & Cooperative Cancellation Guardrail critical for AI coding assistants?

Enforces deterministic lifecycle synchronization, thread-safe memory boundaries, and bidirectional cooperative cancellation between Kotlin Coroutines and Swift Structured Concurrency. Prevents orphaned background jobs, GC root retention leaks across the Objective-C export bridge, and cooperative thread pool starvation. 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 (Dangling Kotlin Coroutine Jobs and Leaked Native GC Roots via Unstructured Swift Task Wrappers) 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-Swift