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

KMP SKIE Bidirectional Cooperative Concurrency & Task Cancellation

Enforces strict cooperative cancellation semantics and lifecycle binding across the Kotlin Multiplatform (KMP) Coroutine and Swift async/await runtime boundary using SKIE. Guarantees that Swift structured task cancellations propagate downward into Kotlin Job cancellation without unhandled CancellationExceptions, and that Kotlin cancellation propagates upward to Swift without orphan background work.

Prohibited Anti-Pattern: Silent Thread Leaks and Broken Task Propagation Across the KMP-Swift Concurrency Barrier

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: KMP SKIE Bidirectional Cooperative Concurrency & Task Cancellation - Enforces strict cooperative cancellation semantics and lifecycle binding across the Kotlin Multiplatform (KMP) Coroutine and Swift async/await runtime boundary using SKIE. Guarantees that Swift structured task cancellations propagate downward into Kotlin Job cancellation without unhandled CancellationExceptions, and that Kotlin cancellation propagates upward to Swift without orphan background work.
globs: **/*.kt, **/*.swift, **/build.gradle.kts
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/kmp-skie-swift-structured-concurrency-bridge"
---

# KMP SKIE Bidirectional Cooperative Concurrency & Task Cancellation

> **Severity**: CRITICAL | **Category**: mobile
> **Anti-Pattern Warning**: Silent Thread Leaks and Broken Task Propagation Across the KMP-Swift Concurrency Barrier

## System Constraints
You are a Principal Mobile Architect specializing in Kotlin Multiplatform and iOS native integration. Enforce uncompromising architectural invariants on KMP SKIE (Swift-Kotlin Interop Enhancer) bridges, ensuring bidirectional cooperative cancellation between Kotlin Coroutines and Swift Structured Concurrency (async/await, Task, TaskGroup). Prevent coroutine leaks, unhandled CancellationExceptions traversing foreign FFI boundaries, and detached tasks.

## Strict Guidelines
- Engineers MUST ALWAYS leverage SKIE's native Swift async/await code generation rather than bridging coroutines via raw completion handlers or unmanaged callbacks.
- Engineers MUST NOT swallow `CancellationException` in Kotlin catch blocks; caught `CancellationException` must be rethrown immediately to maintain CoroutineScope cancellation semantics.
- Swift callers MUST ALWAYS invoke bridged Kotlin suspend functions within an active Swift `Task` context or forward structured concurrency scopes so that `withTaskCancellationHandler` or SKIE bridge wrappers can invoke `Job.cancel()`.
- Engineers MUST NEVER use `GlobalScope` or `NonCancellable` in shared KMP repositories without explicit documented justification and isolation boundaries.
- Kotlin Flow streams bridged to Swift `AsyncSequence` via SKIE MUST terminate gracefully on task cancellation without leaking inner coroutine subscriptions or throwing unhandled Objective-C exceptions across the runtime boundary.
- Swift code MUST NOT spin up detached tasks (`Task.detached`) to invoke bridged KMP functions unless an explicit `Job` lifecycle handle is captured and manually torn down upon view disposal.

## Bad vs Good Implementations
### Kotlin Coroutine Exception Handling and Suspension

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Catching generic `Exception` catches `kotlinx.coroutines.CancellationException`. When Swift cancels the calling `Task`, SKIE triggers coroutine cancellation, but this swallowed exception causes the coroutine to complete normally with null rather than aborting, leaking execution and violating cooperative cancellation.
```kotlin
class UserRepository(private val api: ApiService) {
    // ANTI-PATTERN: Generic catch swallows CancellationException,
    // breaking Swift structured task cancellation propagation.
    suspend fun fetchUserProfile(userId: String): UserProfile? {
        return try {
            api.getUser(userId)
        } catch (e: Exception) {
            null // Coroutine cancellation is silently swallowed
        }
    }
}
```

#### Production Standard (Correct)
> **Standard**: Explicitly re-throwing `CancellationException` guarantees that when the parent Swift `Task` is cancelled, the Kotlin `Job` terminates cooperatively and signals cancellation back to the SKIE bridge runtime without triggering unhandled exceptions.
```kotlin
import kotlinx.coroutines.CancellationException

class UserRepository(private val api: ApiService) {
    // PRODUCTION INVARIANT: Cooperative cancellation preserved.
    suspend fun fetchUserProfile(userId: String): UserProfile? {
        return try {
            api.getUser(userId)
        } catch (e: CancellationException) {
            throw e // Re-throw to allow SKIE and Kotlin runtime to cancel cleanly
        } catch (e: Exception) {
            null // Handle expected network or domain failures
        }
    }
}
```

### Swift Structured Concurrency UI Integration via SKIE

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: `Task.detached` breaks Swift Structured Concurrency. The task is not bound to the SwiftUI view hierarchy or an enclosing task scope, so view dismissal never triggers cancellation in either Swift or the underlying Kotlin coroutine.
```swift
import SwiftUI
import SharedKit

struct ProfileView: View {
    @State private var profile: UserProfile? = nil
    let repository: UserRepository
    let userId: String

    var body: some View {
        Text(profile?.name ?? "Loading...")
            .onAppear {
                // ANTI-PATTERN: Detached task decouples lifecycle from SwiftUI View.
                // When view disappears, Kotlin Coroutine continues running indefinitely.
                Task.detached {
                    self.profile = try? await self.repository.fetchUserProfile(userId: self.userId)
                }
            }
    }
}
```

#### Production Standard (Correct)
> **Standard**: Using `.task(id:)` binds the execution lifecycle directly to the SwiftUI runtime. When the view disappears or `userId` changes, SwiftUI cancels the `Task`. SKIE's runtime bridge receives this cancellation and cooperatively cancels the underlying Kotlin `Job` immediately.
```swift
import SwiftUI
import SharedKit

struct ProfileView: View {
    @State private var profile: UserProfile? = nil
    let repository: UserRepository
    let userId: String

    var body: some View {
        Text(profile?.name ?? "Loading...")
            // PRODUCTION INVARIANT: .task modifier is tied to SwiftUI view lifecycle.
            // Disappearance cancels the Swift Task, which SKIE bridges to Job.cancel().
            .task(id: userId) {
                do {
                    self.profile = try await repository.fetchUserProfile(userId: userId)
                } catch is CancellationError {
                    // Handled gracefully: Task was cancelled by view dismissal
                } catch {
                    // Handle domain/network errors
                }
            }
    }
}
```

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 Bidirectional Cooperative Concurrency & Task Cancellation

KMP SKIE Bidirectional Cooperative Concurrency & Task Cancellation defines an industrial-grade behavioral standard for mobile engineering. Enforces strict cooperative cancellation semantics and lifecycle binding across the Kotlin Multiplatform (KMP) Coroutine and Swift async/await runtime boundary using SKIE. Guarantees that Swift structured task cancellations propagate downward into Kotlin Job cancellation without unhandled CancellationExceptions, and that Kotlin cancellation propagates upward to Swift without orphan background work. 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: Silent Thread Leaks and Broken Task Propagation Across the KMP-Swift Concurrency Barrier 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 DriftSilent Thread Leaks and Broken Task Propagation Across the KMP-Swift Concurrency BarrierCritical
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 leverage SKIE's native Swift async/await code generation rather than bridging coroutines via raw completion handlers or unmanaged callbacks.

Engineers MUST ALWAYS leverage SKIE's native Swift async/await code generation rather than bridging coroutines via raw completion handlers or unmanaged 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.
2

Engineers MUST NOT swallow `CancellationException` in Kotlin catch blocks

Engineers MUST NOT swallow `CancellationException` in Kotlin catch blocks; caught `CancellationException` must be rethrown immediately to maintain CoroutineScope cancellation semantics.

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 callers MUST ALWAYS invoke bridged Kotlin suspend functions within an active Swift `Task` context or forward structured concurrency scopes so that `withTaskCancellationHandler` or SKIE bridge wrappers can invoke `Job.cancel()`.

Swift callers MUST ALWAYS invoke bridged Kotlin suspend functions within an active Swift `Task` context or forward structured concurrency scopes so that `withTaskCancellationHandler` or SKIE bridge wrappers can invoke `Job.cancel()`.

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 use `GlobalScope` or `NonCancellable` in shared KMP repositories without explicit documented justification and isolation boundaries.

Engineers MUST NEVER use `GlobalScope` or `NonCancellable` in shared KMP repositories without explicit documented justification and isolation boundaries.

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 Flow streams bridged to Swift `AsyncSequence` via SKIE MUST terminate gracefully on task cancellation without leaking inner coroutine subscriptions or throwing unhandled Objective-C exceptions across the runtime boundary.

Kotlin Flow streams bridged to Swift `AsyncSequence` via SKIE MUST terminate gracefully on task cancellation without leaking inner coroutine subscriptions or throwing unhandled Objective-C exceptions across the runtime 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.
6

Swift code MUST NOT spin up detached tasks (`Task.detached`) to invoke bridged KMP functions unless an explicit `Job` lifecycle handle is captured and manually torn down upon view disposal.

Swift code MUST NOT spin up detached tasks (`Task.detached`) to invoke bridged KMP functions unless an explicit `Job` lifecycle handle is captured and manually torn down upon view disposal.

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 Bidirectional Cooperative Concurrency & Task Cancellation critical for AI coding assistants?

Enforces strict cooperative cancellation semantics and lifecycle binding across the Kotlin Multiplatform (KMP) Coroutine and Swift async/await runtime boundary using SKIE. Guarantees that Swift structured task cancellations propagate downward into Kotlin Job cancellation without unhandled CancellationExceptions, and that Kotlin cancellation propagates upward to Swift without orphan background work. 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 (Silent Thread Leaks and Broken Task Propagation Across the KMP-Swift Concurrency Barrier) 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