This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
mobilecritical PriorityID: kmp-darwin-main-flow-conflation-standard

KMP Darwin Main RunLoop SharedFlow Conflation Guardrail

Enforces a strict buffer-drop-oldest conflation boundary on Kotlin Multiplatform SharedFlow and StateFlow bridges exposed to Darwin (iOS) runloops. Prevents dispatch queue saturation, runaway micro-tasks, and CADisplayLink frame hitches caused by bridging unbuffered high-frequency Kotlin coroutine emissions directly into Swift/SwiftUI main-thread observers.

Prohibited Anti-Pattern: Bridging Unconflated High-Frequency Kotlin SharedFlow to Darwin Main Dispatcher Causing Main RunLoop Starvation and Frame Hitches

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: KMP Darwin Main RunLoop SharedFlow Conflation Guardrail - Enforces a strict buffer-drop-oldest conflation boundary on Kotlin Multiplatform SharedFlow and StateFlow bridges exposed to Darwin (iOS) runloops. Prevents dispatch queue saturation, runaway micro-tasks, and CADisplayLink frame hitches caused by bridging unbuffered high-frequency Kotlin coroutine emissions directly into Swift/SwiftUI main-thread observers.
globs: **/commonMain/**/viewmodel/**/*.kt, **/commonMain/**/presentation/**/*.kt, **/darwinMain/**/*.kt, **/iosApp/**/*.swift, **/iosMain/**/*.kt
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/kmp-darwin-main-flow-conflation-standard"
---

# KMP Darwin Main RunLoop SharedFlow Conflation Guardrail

> **Severity**: CRITICAL | **Category**: mobile
> **Anti-Pattern Warning**: Bridging Unconflated High-Frequency Kotlin SharedFlow to Darwin Main Dispatcher Causing Main RunLoop Starvation and Frame Hitches

## System Constraints
You are a Principal Mobile Architect specializing in Kotlin Multiplatform (KMP) runtime interop. Your role is to mandate explicit backpressure conflation barriers on all cross-boundary SharedFlow and StateFlow streams destined for Darwin runloops. You must prevent thread saturation on Apple platforms by ensuring all Darwin-bound flows use DROP_OLDEST buffer overflow strategies, prevent synchronous bridging via Dispatchers.Main, and eliminate rapid-fire UI hitching.

## Strict Guidelines
- Engineers MUST ALWAYS apply `.buffer(capacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)` or `.conflate()` on high-frequency SharedFlow instances before bridging to Darwin (iOS/macOS) platforms.
- Engineers MUST NOT expose raw, unbounded `MutableSharedFlow(replay = 0)` directly to Swift consumers without an explicit conflation wrapper adapter.
- Code bridging flows into Swift `AsyncSequence` or Combine publishers MUST collect on a background coroutine context (`Dispatchers.Default`) before dispatching state transformations onto `@MainActor` or the Darwin Main RunLoop.
- Bridging adapters MUST cancel the underlying Kotlin `Job` immediately when the Swift subscriber is deallocated or cancels its task, preventing orphaned coroutines pumping events into defunct Darwin dispatch queues.
- Shared UI state models MUST prefer `StateFlow` with value deduplication (`distinctUntilChanged()`) over high-frequency event streams to guarantee the main thread processes only renderable delta frames.

## Bad vs Good Implementations
### Kotlin Multiplatform High-Frequency Flow Bridging for Darwin UI

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Default MutableSharedFlow does not drop old emissions. When bridged across the Objective-C/Swift interop boundary to the iOS main runloop, rapid emissions back up in Darwin's main dispatch queue, triggering CADisplayLink hitching, UI unresponsiveness, and extreme memory pressure.
```kotlin
class SensorViewModel : BaseViewModel() {
    // ANTI-PATTERN: Unbounded SharedFlow with default SUSPEND overflow strategy
    // High-frequency sensor or socket ticks will saturate Darwin dispatch queue
    private val _telemetry = MutableSharedFlow<TelemetryData>()
    val telemetry: SharedFlow<TelemetryData> = _telemetry.asSharedFlow()

    fun onSensorTick(data: TelemetryData) {
        viewModelScope.launch {
            // Rapid emissions queue micro-tasks on Darwin Main RunLoop without backpressure
            _telemetry.emit(data)
        }
    }
}
```

#### Production Standard (Correct)
> **Standard**: Explicitly configuring `extraBufferCapacity = 1` and `onBufferOverflow = BufferOverflow.DROP_OLDEST` creates a safe backpressure barrier. Fast ticks drop intermediate values during hitch intervals, and `tryEmit` guarantees zero suspension overhead on high-frequency producer threads.
```kotlin
class SensorViewModel : BaseViewModel() {
    // INVARIANT: Conflated buffer barrier with DROP_OLDEST ensures Darwin UI runloop
    // drops intermediate stale frames when frame drops or main thread delays occur
    private val _telemetry = MutableSharedFlow<TelemetryData>(
        replay = 1,
        extraBufferCapacity = 1,
        onBufferOverflow = BufferOverflow.DROP_OLDEST
    )
    val telemetry: Flow<TelemetryData> = _telemetry
        .distinctUntilChanged()
        .flowOn(Dispatchers.Default)

    fun onSensorTick(data: TelemetryData) {
        // tryEmit guarantees non-blocking publication, dropping oldest if buffer is full
        _telemetry.tryEmit(data)
    }
}
```

### Swift Darwin Consumption Adapter with MainActor Yield Protection

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Directly awaiting unconflated emissions inside a MainActor task locks the main runloop in a continuous dispatch loop, blocking layout passes, gesture handling, and core animation commits.
```swift
// ANTI-PATTERN: Direct synchronous dispatch of every flow emission to MainActor
func bindTelemetry(flow: SkieSwiftFlow<TelemetryData>) {
    Task {
        for await data in flow {
            // Floods SwiftUI MainActor with micro-updates faster than 120Hz display refresh
            self.state = data
        }
    }
}
```

#### Production Standard (Correct)
> **Standard**: Uses structured task cancellation to terminate the Kotlin collection cleanly, dispatches state updates via `@MainActor`, and calls `Task.yield()` to allow the Darwin Main RunLoop to process CADisplayLink render frames smoothly without starvation.
```swift
// INVARIANT: Conflated lifecycle-aware task binding with runloop yield defense
func bindTelemetry(flow: SkieSwiftFlow<TelemetryData>) {
    telemetryTask?.cancel()
    telemetryTask = Task(priority: .userInitiated) { [weak self] in
        for await data in flow {
            guard !Task.isCancelled else { break }
            await MainActor.run { [weak self] in
                self?.state = data
            }
            // Yield control back to Darwin runloop to prioritize CoreAnimation render pass
            await Task.yield()
        }
    }
}
```

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 Darwin Main RunLoop SharedFlow Conflation Guardrail

KMP Darwin Main RunLoop SharedFlow Conflation Guardrail defines an industrial-grade behavioral standard for mobile engineering. Enforces a strict buffer-drop-oldest conflation boundary on Kotlin Multiplatform SharedFlow and StateFlow bridges exposed to Darwin (iOS) runloops. Prevents dispatch queue saturation, runaway micro-tasks, and CADisplayLink frame hitches caused by bridging unbuffered high-frequency Kotlin coroutine emissions directly into Swift/SwiftUI main-thread observers. 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 Unconflated High-Frequency Kotlin SharedFlow to Darwin Main Dispatcher Causing Main RunLoop Starvation and Frame Hitches 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 Unconflated High-Frequency Kotlin SharedFlow to Darwin Main Dispatcher Causing Main RunLoop Starvation and Frame HitchesCritical
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 apply `.buffer(capacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)` or `.conflate()` on high-frequency SharedFlow instances before bridging to Darwin (iOS/macOS) platforms.

Engineers MUST ALWAYS apply `.buffer(capacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)` or `.conflate()` on high-frequency SharedFlow instances before bridging to Darwin (iOS/macOS) platforms.

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 raw, unbounded `MutableSharedFlow(replay = 0)` directly to Swift consumers without an explicit conflation wrapper adapter.

Engineers MUST NOT expose raw, unbounded `MutableSharedFlow(replay = 0)` directly to Swift consumers without an explicit conflation wrapper adapter.

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 bridging flows into Swift `AsyncSequence` or Combine publishers MUST collect on a background coroutine context (`Dispatchers.Default`) before dispatching state transformations onto `@MainActor` or the Darwin Main RunLoop.

Code bridging flows into Swift `AsyncSequence` or Combine publishers MUST collect on a background coroutine context (`Dispatchers.Default`) before dispatching state transformations onto `@MainActor` or the Darwin Main RunLoop.

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

Bridging adapters MUST cancel the underlying Kotlin `Job` immediately when the Swift subscriber is deallocated or cancels its task, preventing orphaned coroutines pumping events into defunct Darwin dispatch queues.

Bridging adapters MUST cancel the underlying Kotlin `Job` immediately when the Swift subscriber is deallocated or cancels its task, preventing orphaned coroutines pumping events into defunct Darwin dispatch queues.

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

Shared UI state models MUST prefer `StateFlow` with value deduplication (`distinctUntilChanged()`) over high-frequency event streams to guarantee the main thread processes only renderable delta frames.

Shared UI state models MUST prefer `StateFlow` with value deduplication (`distinctUntilChanged()`) over high-frequency event streams to guarantee the main thread processes only renderable delta frames.

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 Darwin Main RunLoop SharedFlow Conflation Guardrail critical for AI coding assistants?

Enforces a strict buffer-drop-oldest conflation boundary on Kotlin Multiplatform SharedFlow and StateFlow bridges exposed to Darwin (iOS) runloops. Prevents dispatch queue saturation, runaway micro-tasks, and CADisplayLink frame hitches caused by bridging unbuffered high-frequency Kotlin coroutine emissions directly into Swift/SwiftUI main-thread observers. 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 Unconflated High-Frequency Kotlin SharedFlow to Darwin Main Dispatcher Causing Main RunLoop Starvation and Frame Hitches) 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