This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
mobilecritical PriorityID: kmp-coroutine-priority-inversion-fence-swift6

KMP Coroutine Priority Inversion Fence for Swift 6 Actor Interop

Prevents catastrophic main-actor thread starvation when bridging Kotlin Multiplatform (KMP) coroutines on Dispatchers.Default with Swift 6 structured concurrency. Enforces non-blocking cooperative hops, thread pool bounds isolation, and strict async-bridge fences to ensure Kotlin coroutine dispatchers do not saturate libdispatch worker threads or invert MainActor priorities.

Prohibited Anti-Pattern: Unbounded Dispatchers.Default Bridge Saturating Darwin Dispatch Queues and Inducing MainActor Starvation

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: KMP Coroutine Priority Inversion Fence for Swift 6 Actor Interop - Prevents catastrophic main-actor thread starvation when bridging Kotlin Multiplatform (KMP) coroutines on Dispatchers.Default with Swift 6 structured concurrency. Enforces non-blocking cooperative hops, thread pool bounds isolation, and strict async-bridge fences to ensure Kotlin coroutine dispatchers do not saturate libdispatch worker threads or invert MainActor priorities.
globs: **/*.kt, **/*.swift, shared/src/commonMain/**/*.kt, shared/src/iosMain/**/*.kt, iosApp/**/*.swift
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/kmp-coroutine-priority-inversion-fence-swift6"
---

# KMP Coroutine Priority Inversion Fence for Swift 6 Actor Interop

> **Severity**: CRITICAL | **Category**: mobile
> **Anti-Pattern Warning**: Unbounded Dispatchers.Default Bridge Saturating Darwin Dispatch Queues and Inducing MainActor Starvation

## System Constraints
You are a Principal Engineer and Concurrency Systems Architect enforcing thread safety and dead-lock prevention between Kotlin Multiplatform and Swift 6 runtime systems. Mandate strict execution fences across the Kotlin Native/Objective-C/Swift boundary to eliminate cooperative pool exhaustion, QOS priority inversion, and MainActor blocking.

## Strict Guidelines
- Engineers MUST ALWAYS bridge Kotlin suspend functions into Swift 6 via explicit detached non-isolated Tasks or SKIE-generated async wrappers with explicit TaskPriority bounds.
- Engineers MUST NOT synchronously block on Kotlin Coroutine Jobs or runBlocking within Swift @MainActor or UI-bound execution contexts.
- Kotlin side iosMain dispatchers MUST NOT saturate the shared Darwin GCD background worker pool; custom worker dispatchers must constrain concurrency using limitedParallelism.
- Services exposing suspend functions to Swift MUST explicitly isolate heavy computations behind Dispatchers.Default with cooperative cancellation checks (ensureActive / yield) at deterministic checkpoints.
- Swift caller code NEVER invokes KMP suspend callbacks directly while holding an actor lock or inside a critical transaction block to prevent synchronous thread starvation.

## Bad vs Good Implementations
### Bridging Kotlin Suspend Function into Swift 6 Actor Context

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Directly awaiting a Kotlin suspend bridge on the @MainActor propagates libdispatch cooperative scheduling constraints onto the Kotlin runtime. If Dispatchers.Default blocks or enters a long computation without cooperative yield, it ties up Darwin dispatch workers, causing MainActor hangs and Watchdog termination (0x8badf00d).
```swift
// CRITICAL FAILURE: Awaiting KMP suspend directly inside @MainActor or custom Actor
// synchronously inherits QoS, locking the libdispatch worker pool and starving MainActor
@MainActor
final class DashboardViewModel: ObservableObject {
    @Published private(set) var data: String = ""
    private let repository: KmpDataRepository = KmpDataRepository()

    func loadData() async {
        // Unbounded KMP Dispatchers.Default interop invoked directly on MainActor thread context
        do {
            let result = try await repository.fetchHeavyPayload()
            self.data = result
        } catch {
            // Priority inversion: Main thread blocks awaiting GCD worker pool reclamation
        }
    }
}
```

#### Production Standard (Correct)
> **Standard**: Using Task.detached with an explicit .userInitiated priority acts as a strict priority fence. It prevents the Kotlin coroutine from piggybacking on the Swift MainActor queue context, isolating runtime scheduler latencies to secondary worker threads.
```swift
// RESILIENT FIX: Explicit task detachment with QoS fence and re-entrant actor handoff
@MainActor
final class DashboardViewModel: ObservableObject {
    @Published private(set) var data: String = ""
    private let repository: KmpDataRepository = KmpDataRepository()

    func loadData() async {
        // Fence: Decouple from MainActor execution thread via background task priority
        let resultTask = Task.detached(priority: .userInitiated) { [repository] () -> String in
            // Kotlin suspend executes safely isolated on background worker pool
            return try await repository.fetchHeavyPayload()
        }

        do {
            let payload = try await resultTask.value
            // Non-blocking re-entry back to MainActor
            self.data = payload
        } catch {
            // Structured cancellation or error handling handled without starvation
        }
    }
}
```

### Constrained Worker Dispatcher in Kotlin iosMain Bridge

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Unbounded Dispatchers.Default on Kotlin/Native leverages a global worker pool. When multiple Swift concurrent tasks call into this function, it can exhaust available GCD POSIX threads, causing high latency priority inversion for Swift tasks awaiting execution on concurrent queues.
```kotlin
// CRITICAL FAILURE: Unbounded Dispatchers.Default exposure directly to iOS Darwin runtime
package com.example.kmp.bridge

import kotlinx.coroutines.*

class KmpDataRepository {
    // Exposes unbounded global pool directly to Swift async calls
    suspend fun fetchHeavyPayload(): String = withContext(Dispatchers.Default) {
        // Heavy parsing or CPU computation without limited parallelism
        performIntensiveCalculations()
    }

    private fun performIntensiveCalculations(): String {
        var sum = 0L
        for (i in 0..10_000_000) { sum += i }
        return "Result: $sum"
    }
}
```

#### Production Standard (Correct)
> **Standard**: Using Dispatchers.Default.limitedParallelism(4) bounds the maximum number of underlying Darwin pthread workers consumed by KMP. Injecting ensureActive() and yield() establishes cooperative cancellation and scheduling fences across platform runtimes.
```kotlin
// RESILIENT FIX: Bounded parallelism dispatcher fence with cooperative yields
package com.example.kmp.bridge

import kotlinx.coroutines.*

class KmpDataRepository {
    // Guardrail: Restrict concurrent native threads to prevent libdispatch exhaustion
    private val boundedDispatcher = Dispatchers.Default.limitedParallelism(4)

    suspend fun fetchHeavyPayload(): String = withContext(boundedDispatcher) {
        ensureActive() // Cancellation invariant check
        val result = performIntensiveCalculations()
        yield() // Cooperative yield fence before crossing back to Objective-C/Swift bridge
        result
    }

    private fun performIntensiveCalculations(): String {
        var sum = 0L
        for (i in 0..10_000_000) { sum += i }
        return "Result: $sum"
    }
}
```

Architectural Specification & Invariant Rationale

Architectural Invariant Design: KMP Coroutine Priority Inversion Fence for Swift 6 Actor Interop

KMP Coroutine Priority Inversion Fence for Swift 6 Actor Interop defines an industrial-grade behavioral standard for mobile engineering. Prevents catastrophic main-actor thread starvation when bridging Kotlin Multiplatform (KMP) coroutines on Dispatchers.Default with Swift 6 structured concurrency. Enforces non-blocking cooperative hops, thread pool bounds isolation, and strict async-bridge fences to ensure Kotlin coroutine dispatchers do not saturate libdispatch worker threads or invert MainActor priorities. 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: Unbounded Dispatchers.Default Bridge Saturating Darwin Dispatch Queues and Inducing MainActor Starvation 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 DriftUnbounded Dispatchers.Default Bridge Saturating Darwin Dispatch Queues and Inducing MainActor StarvationCritical
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 suspend functions into Swift 6 via explicit detached non-isolated Tasks or SKIE-generated async wrappers with explicit TaskPriority bounds.

Engineers MUST ALWAYS bridge Kotlin suspend functions into Swift 6 via explicit detached non-isolated Tasks or SKIE-generated async wrappers with explicit TaskPriority bounds.

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 synchronously block on Kotlin Coroutine Jobs or runBlocking within Swift @MainActor or UI-bound execution contexts.

Engineers MUST NOT synchronously block on Kotlin Coroutine Jobs or runBlocking within Swift @MainActor or UI-bound execution contexts.

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

Kotlin side iosMain dispatchers MUST NOT saturate the shared Darwin GCD background worker pool

Kotlin side iosMain dispatchers MUST NOT saturate the shared Darwin GCD background worker pool; custom worker dispatchers must constrain concurrency using limitedParallelism.

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 exposing suspend functions to Swift MUST explicitly isolate heavy computations behind Dispatchers.Default with cooperative cancellation checks (ensureActive / yield) at deterministic checkpoints.

Services exposing suspend functions to Swift MUST explicitly isolate heavy computations behind Dispatchers.Default with cooperative cancellation checks (ensureActive / yield) at deterministic checkpoints.

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

Swift caller code NEVER invokes KMP suspend callbacks directly while holding an actor lock or inside a critical transaction block to prevent synchronous thread starvation.

Swift caller code NEVER invokes KMP suspend callbacks directly while holding an actor lock or inside a critical transaction block to prevent synchronous thread starvation.

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 Coroutine Priority Inversion Fence for Swift 6 Actor Interop critical for AI coding assistants?

Prevents catastrophic main-actor thread starvation when bridging Kotlin Multiplatform (KMP) coroutines on Dispatchers.Default with Swift 6 structured concurrency. Enforces non-blocking cooperative hops, thread pool bounds isolation, and strict async-bridge fences to ensure Kotlin coroutine dispatchers do not saturate libdispatch worker threads or invert MainActor priorities. 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 (Unbounded Dispatchers.Default Bridge Saturating Darwin Dispatch Queues and Inducing MainActor Starvation) 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