This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
mobilecritical PriorityID: kmp-deterministic-state-engine-sync

Deterministic KMP State Machine Synchronization with SQLDelight Offline Stores

Enforces strict mathematical determinism across Kotlin Multiplatform shared state engines interfacing with transactional SQLite persistence (e.g., SQLDelight) and Coroutine/Flow state bridges. Prevents race conditions, state divergence, non-atomic database mutations, and non-thread-safe native memory leaks across iOS (Native), Android (JVM), and Web (Wasm/JS).

Prohibited Anti-Pattern: Non-Atomic Side-Effects and Race Conditions in Multiplatform State Machine Transitions

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Deterministic KMP State Machine Synchronization with SQLDelight Offline Stores - Enforces strict mathematical determinism across Kotlin Multiplatform shared state engines interfacing with transactional SQLite persistence (e.g., SQLDelight) and Coroutine/Flow state bridges. Prevents race conditions, state divergence, non-atomic database mutations, and non-thread-safe native memory leaks across iOS (Native), Android (JVM), and Web (Wasm/JS).
globs: shared/**/src/commonMain/kotlin/**/*.kt, shared/**/src/iosMain/kotlin/**/*.kt, shared/**/src/androidMain/kotlin/**/*.kt
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/kmp-deterministic-state-engine-sync"
---

# Deterministic KMP State Machine Synchronization with SQLDelight Offline Stores

> **Severity**: CRITICAL | **Category**: mobile
> **Anti-Pattern Warning**: Non-Atomic Side-Effects and Race Conditions in Multiplatform State Machine Transitions

## System Constraints
You are a Principal Engineer enforcing Kotlin Multiplatform (KMP) Deterministic State Engine Synchronization. Mandate invariants that ensure UI state machines are pure, single-source-of-truth actors with idempotent events, atomic transactional persistence via SQLDelight/Room-KMP, and strict isolation of platform dispatchers. Never allow platform-specific concurrency primitives or non-confined mutable state to leak outside the deterministic state loop.

## Strict Guidelines
- Engineers MUST ALWAYS drive state transitions exclusively via unidirectional, immutable Action -> Reducer/StateMachine -> State pipelines executed on a serial Mutex or single-threaded background CoroutineDispatcher.
- Engineers MUST wrap all database mutations and subsequent state emissions inside an atomic transaction block (e.g., dbQuery.transaction { ... }) to prevent state-persistence desynchronization during app kill or crash events.
- Engineers MUST NOT expose MutableStateFlow or raw database queries to platform boundary layers (Swift, Jetpack Compose, or JS); consumers must consume read-only StateFlow<T> or immutable shared wrapper types.
- Code SHOULD handle concurrency conflicts using optimistic locking with monotonically increasing version counters on domain entities before writing to the local SQLite store.
- Services MUST isolate platform-dependent thread dispatchers behind an expect/actual CoroutineDispatchers provider, defaulting background compute to a confined serial worker on Darwin to avoid freeze/race anomalies.
- Components NEVER trigger side effects directly inside StateMachine reducers; reducers MUST remain pure functions returning (NextState, SideEffectCommand).

## Bad vs Good Implementations
### KMP State Machine with Atomic Transactional Offline Sync

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Directly mutating an unconfined MutableStateFlow prior to un-transactional persistence allows memory state to diverge permanently from disk if an interruption occurs. It introduces data races when multiple dispatchers call the method concurrently.
```kotlin
class AccountStateManager(private val db: Database) {
    // ANTI-PATTERN: Mutable state exposed; unconfined dispatchers;
    // side effects and DB mutations are non-atomic and race-prone.
    val state = MutableStateFlow<AccountState>(AccountState.Idle)
    private val scope = CoroutineScope(Dispatchers.Default)

    fun dispatch(action: AccountAction) {
        scope.launch {
            when (action) {
                is AccountAction.Deposit -> {
                    // Non-atomic read-modify-write
                    val current = db.accountQueries.getAccount(action.id).executeAsOne()
                    val newBalance = current.balance + action.amount
                    
                    // UI state updates before DB write succeeds
                    state.value = AccountState.Success(newBalance)
                    
                    // Crash here desynchronizes memory state from disk state
                    db.accountQueries.updateBalance(newBalance, action.id)
                }
            }
        }
    }
}
```

#### Production Standard (Correct)
> **Standard**: Mutations are strictly serialized via a Mutex on the IO context, ensuring deterministic sequential processing. Writes use SQL transactions with optimistic locking; the public read-only StateFlow is updated only upon verified transaction commit.
```kotlin
sealed interface AccountIntent {
    data class Deposit(val accountId: String, val amount: Long, val idempotencyKey: String) : AccountIntent
}

@Immutable
data class AccountState(
    val accountId: String,
    val balance: Long,
    val version: Long,
    val isProcessing: Boolean = false
)

class DeterministicAccountEngine(
    private val database: AppDatabase,
    private val dispatchers: AppCoroutineDispatchers
) {
    private val _state = MutableStateFlow<AccountState>(AccountState("", 0L, 0L))
    val state: StateFlow<AccountState> = _state.asStateFlow()
    
    private val mutex = Mutex()

    suspend fun processIntent(intent: AccountIntent) = withContext(dispatchers.io) {
        mutex.withLock {
            when (intent) {
                is AccountIntent.Deposit -> {
                    database.transactionWithResult {
                        val current = database.accountQueries
                            .selectById(intent.accountId)
                            .executeAsOne()
                            
                        val nextVersion = current.version + 1
                        val nextBalance = current.balance + intent.amount

                        database.accountQueries.updateWithOptimisticLock(
                            balance = nextBalance,
                            version = nextVersion,
                            id = intent.accountId,
                            expectedVersion = current.version
                        )

                        val committedState = AccountState(
                            accountId = intent.accountId,
                            balance = nextBalance,
                            version = nextVersion
                        )
                        _state.value = committedState
                        committedState
                    }
                }
            }
        }
    }
}
```

Recommended MCP Servers (mcp-serverlist.com)

Equip agent with system tools to verify code for this stack.

Architectural Specification & Invariant Rationale

Architectural Invariant Design: Deterministic KMP State Machine Synchronization with SQLDelight Offline Stores

Deterministic KMP State Machine Synchronization with SQLDelight Offline Stores defines an industrial-grade behavioral standard for mobile engineering. Enforces strict mathematical determinism across Kotlin Multiplatform shared state engines interfacing with transactional SQLite persistence (e.g., SQLDelight) and Coroutine/Flow state bridges. Prevents race conditions, state divergence, non-atomic database mutations, and non-thread-safe native memory leaks across iOS (Native), Android (JVM), and Web (Wasm/JS). 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: Non-Atomic Side-Effects and Race Conditions in Multiplatform State Machine Transitions 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 DriftNon-Atomic Side-Effects and Race Conditions in Multiplatform State Machine TransitionsCritical
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 drive state transitions exclusively via unidirectional, immutable Action -> Reducer/StateMachine -> State pipelines executed on a serial Mutex or single-threaded background CoroutineDispatcher.

Engineers MUST ALWAYS drive state transitions exclusively via unidirectional, immutable Action -> Reducer/StateMachine -> State pipelines executed on a serial Mutex or single-threaded background CoroutineDispatcher.

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 wrap all database mutations and subsequent state emissions inside an atomic transaction block (e.g., dbQuery.transaction { ... }) to prevent state-persistence desynchronization during app kill or crash events.

Engineers MUST wrap all database mutations and subsequent state emissions inside an atomic transaction block (e.g., dbQuery.transaction { ... }) to prevent state-persistence desynchronization during app kill or crash events.

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 NOT expose MutableStateFlow or raw database queries to platform boundary layers (Swift, Jetpack Compose, or JS)

Engineers MUST NOT expose MutableStateFlow or raw database queries to platform boundary layers (Swift, Jetpack Compose, or JS); consumers must consume read-only StateFlow<T> or immutable shared wrapper types.

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

Code SHOULD handle concurrency conflicts using optimistic locking with monotonically increasing version counters on domain entities before writing to the local SQLite store.

Code SHOULD handle concurrency conflicts using optimistic locking with monotonically increasing version counters on domain entities before writing to the local SQLite store.

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

Services MUST isolate platform-dependent thread dispatchers behind an expect/actual CoroutineDispatchers provider, defaulting background compute to a confined serial worker on Darwin to avoid freeze/race anomalies.

Services MUST isolate platform-dependent thread dispatchers behind an expect/actual CoroutineDispatchers provider, defaulting background compute to a confined serial worker on Darwin to avoid freeze/race anomalies.

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

Components NEVER trigger side effects directly inside StateMachine reducers

Components NEVER trigger side effects directly inside StateMachine reducers; reducers MUST remain pure functions returning (NextState, SideEffectCommand).

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 Deterministic KMP State Machine Synchronization with SQLDelight Offline Stores critical for AI coding assistants?

Enforces strict mathematical determinism across Kotlin Multiplatform shared state engines interfacing with transactional SQLite persistence (e.g., SQLDelight) and Coroutine/Flow state bridges. Prevents race conditions, state divergence, non-atomic database mutations, and non-thread-safe native memory leaks across iOS (Native), Android (JVM), and Web (Wasm/JS). 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 (Non-Atomic Side-Effects and Race Conditions in Multiplatform State Machine Transitions) 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

Deterministic