This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
mobilecritical PriorityID: kmp-compose-native-thread-isolation-guardrail

Compose Multiplatform Native Thread Isolation & Lock-Free State Confinement

Enforces strict thread confinement and deterministic lock-free mutations across Kotlin Multiplatform (JVM and Darwin) runtimes. Prevents UI thread stalls, Darwin Grand Central Dispatch deadlocks, and Snapshot State desynchronization by strictly isolating background mutations from Compose Snapshot state.

Prohibited Anti-Pattern: Mutating Shared Snapshot State from Background Dispatchers or Unconfined Native Threads

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Compose Multiplatform Native Thread Isolation & Lock-Free State Confinement - Enforces strict thread confinement and deterministic lock-free mutations across Kotlin Multiplatform (JVM and Darwin) runtimes. Prevents UI thread stalls, Darwin Grand Central Dispatch deadlocks, and Snapshot State desynchronization by strictly isolating background mutations from Compose Snapshot state.
globs: **/*.kt, **/commonMain/**/*.kt, **/iosMain/**/*.kt, **/androidMain/**/*.kt
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/kmp-compose-native-thread-isolation-guardrail"
---

# Compose Multiplatform Native Thread Isolation & Lock-Free State Confinement

> **Severity**: CRITICAL | **Category**: mobile
> **Anti-Pattern Warning**: Mutating Shared Snapshot State from Background Dispatchers or Unconfined Native Threads

## System Constraints
You are a Principal Mobile Architect enforcing strict thread confinement and lock-free state synchronization for Compose Multiplatform across JVM and Apple Darwin runtimes. Mandate that Compose Snapshot state mutations execute exclusively on Dispatchers.Main.immediate, while shared cross-platform background mutations use atomic references or channel-based actors to prevent native memory corruptions and UI lockups.

## Strict Guidelines
- Engineers MUST ALWAYS restrict Compose `MutableState` and snapshot write operations to `Dispatchers.Main.immediate` across all targets.
- Engineers MUST NOT mutate shared business state using platform-specific blocking primitives (such as `synchronized`, `java.util.concurrent.locks`, or Darwin `NSLock`) inside common code.
- Engineers MUST use lock-free atomic references (`kotlin.concurrent.atomics.AtomicReference` or `kotlinx.atomicfu.AtomicRef`) or serial `kotlinx.coroutines.channels.Channel` actors for background state management.
- Services MUST expose background state to UI layers as immutable `StateFlow<T>` or `SharedFlow<T>`, never exposing raw mutable references or mutable Compose snapshot states.
- Components NEVER collect coroutine flows directly in composables without lifecycle-aware main-thread binding (e.g., `collectAsStateWithLifecycle` or `collectAsState(context = Dispatchers.Main.immediate)`).

## Bad vs Good Implementations
### Unconfined Background Mutation vs Lock-Free Main-Confined State Emission

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Mutating Compose `MutableState` from `Dispatchers.Default` creates cross-thread snapshot races. On Darwin (iOS), mutating snapshot state outside GCD's main queue bypasses Compose's thread-local tracking, triggering snapshot invalidation bugs and main-thread stalls.
```kotlin
class FeedViewModel : ViewModel() {
    // ANTI-PATTERN: Exposing MutableState directly to background mutations
    val feedState = mutableStateOf<List<FeedItem>>(emptyList())

    fun fetchUpdates() {
        viewModelScope.launch(Dispatchers.Default) {
            val items = networkRepository.fetchFeed()
            // VIOLATION: Direct snapshot mutation from non-UI thread causes
            // Darwin thread race, InvalidSnapshotException, and UI stutter
            feedState.value = items
        }
    }
}
```

#### Production Standard (Correct)
> **Standard**: Separates concerns: network parsing runs on `Dispatchers.Default`, lock-free state progression occurs via `MutableStateFlow.update`, and Compose consumption binds deterministically via `collectAsState()` on the UI thread.
```kotlin
class FeedViewModel(
    private val networkRepository: FeedRepository
) : ViewModel() {
    private val _feedState = MutableStateFlow<List<FeedItem>>(emptyList())
    val feedState: StateFlow<List<FeedItem>> = _feedState.asStateFlow()

    fun fetchUpdates() {
        viewModelScope.launch {
            // Background work executed off the UI thread
            val items = withContext(Dispatchers.Default) {
                networkRepository.fetchFeed()
            }
            // State update is thread-safe via StateFlow
            _feedState.update { items }
        }
    }
}

@Composable
fun FeedScreen(viewModel: FeedViewModel) {
    // Conforms to main-thread snapshot consumption
    val items by viewModel.feedState.collectAsState()
    FeedList(items)
}
```

### Low-Level Shared State: Platform Locks vs AtomicReference CAS

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Plain mutable references without memory barrier guarantees cause visibility issues between Darwin GCD threads and JVM threadpools, leading to dirty reads and stale cache states.
```kotlin
// ANTI-PATTERN: Attempting to use platform-dependent synchronization or volatile references
class SessionManager {
    private var sessionCache: Session? = null

    fun updateSession(newSession: Session) {
        // VIOLATION: Not portable across KMP targets, prone to deadlocks on Darwin runtimes
        kotlin.runCatching {
            sessionCache = newSession
        }
    }

    fun getSession(): Session? = sessionCache
}
```

#### Production Standard (Correct)
> **Standard**: Uses standard Kotlin multiplatform `AtomicReference` with lock-free compare-and-swap (CAS) semantics, ensuring memory visibility and safety across JVM and Native runtimes without OS thread blocking.
```kotlin
import kotlin.concurrent.atomics.AtomicReference
import kotlin.concurrent.atomics.update

// GOOD: Portable lock-free atomic state transition
class SessionManager {
    private val sessionRef = AtomicReference<Session?>(null)

    fun updateSession(newSession: Session) {
        sessionRef.update { current ->
            if (current == null || newSession.timestamp >= current.timestamp) {
                newSession
            } else {
                current
            }
        }
    }

    fun getSession(): Session? = sessionRef.load()
}
```

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: Compose Multiplatform Native Thread Isolation & Lock-Free State Confinement

Compose Multiplatform Native Thread Isolation & Lock-Free State Confinement defines an industrial-grade behavioral standard for mobile engineering. Enforces strict thread confinement and deterministic lock-free mutations across Kotlin Multiplatform (JVM and Darwin) runtimes. Prevents UI thread stalls, Darwin Grand Central Dispatch deadlocks, and Snapshot State desynchronization by strictly isolating background mutations from Compose Snapshot state. 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: Mutating Shared Snapshot State from Background Dispatchers or Unconfined Native Threads 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 DriftMutating Shared Snapshot State from Background Dispatchers or Unconfined Native ThreadsCritical
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 restrict Compose `MutableState` and snapshot write operations to `Dispatchers.Main.immediate` across all targets.

Engineers MUST ALWAYS restrict Compose `MutableState` and snapshot write operations to `Dispatchers.Main.immediate` across all targets.

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 mutate shared business state using platform-specific blocking primitives (such as `synchronized`, `java.util.concurrent.locks`, or Darwin `NSLock`) inside common code.

Engineers MUST NOT mutate shared business state using platform-specific blocking primitives (such as `synchronized`, `java.util.concurrent.locks`, or Darwin `NSLock`) inside common code.

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

Engineers MUST use lock-free atomic references (`kotlin.concurrent.atomics.AtomicReference` or `kotlinx.atomicfu.AtomicRef`) or serial `kotlinx.coroutines.channels.Channel` actors for background state management.

Engineers MUST use lock-free atomic references (`kotlin.concurrent.atomics.AtomicReference` or `kotlinx.atomicfu.AtomicRef`) or serial `kotlinx.coroutines.channels.Channel` actors for background state management.

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 expose background state to UI layers as immutable `StateFlow<T>` or `SharedFlow<T>`, never exposing raw mutable references or mutable Compose snapshot states.

Services MUST expose background state to UI layers as immutable `StateFlow<T>` or `SharedFlow<T>`, never exposing raw mutable references or mutable Compose snapshot states.

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 collect coroutine flows directly in composables without lifecycle-aware main-thread binding (e.g., `collectAsStateWithLifecycle` or `collectAsState(context = Dispatchers.Main.immediate)`).

Components NEVER collect coroutine flows directly in composables without lifecycle-aware main-thread binding (e.g., `collectAsStateWithLifecycle` or `collectAsState(context = Dispatchers.Main.immediate)`).

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 Compose Multiplatform Native Thread Isolation & Lock-Free State Confinement critical for AI coding assistants?

Enforces strict thread confinement and deterministic lock-free mutations across Kotlin Multiplatform (JVM and Darwin) runtimes. Prevents UI thread stalls, Darwin Grand Central Dispatch deadlocks, and Snapshot State desynchronization by strictly isolating background mutations from Compose Snapshot state. 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 (Mutating Shared Snapshot State from Background Dispatchers or Unconfined Native Threads) 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

Compose