This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
mobilecritical PriorityID: kmp-kotlin-2-1-swift-export-memory-fence-standard

Kotlin 2.1 Swift Export & Swift 6 Actor Memory Fence Standard

Establishes deterministic bidirectional memory boundaries between Kotlin 2.1 Swift Export runtimes and Swift 6 actor-isolated domains. Eliminates untracked retain cycles between Swift ARC and Kotlin/Native Garbage Collector by enforcing weak bridges, Sendable decoupling, and explicit lifecycle disposal fences.

Prohibited Anti-Pattern: Cross-Runtime Retain Cycles Between Swift 6 Actor State and Kotlin Native GC Observers

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Kotlin 2.1 Swift Export & Swift 6 Actor Memory Fence Standard - Establishes deterministic bidirectional memory boundaries between Kotlin 2.1 Swift Export runtimes and Swift 6 actor-isolated domains. Eliminates untracked retain cycles between Swift ARC and Kotlin/Native Garbage Collector by enforcing weak bridges, Sendable decoupling, and explicit lifecycle disposal fences.
globs: **/*.kt, **/*.swift, **/build.gradle.kts
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/kmp-kotlin-2-1-swift-export-memory-fence-standard"
---

# Kotlin 2.1 Swift Export & Swift 6 Actor Memory Fence Standard

> **Severity**: CRITICAL | **Category**: mobile
> **Anti-Pattern Warning**: Cross-Runtime Retain Cycles Between Swift 6 Actor State and Kotlin Native GC Observers

## System Constraints
You are a Principal Mobile Architect enforcing the Kotlin Multiplatform (KMP) 2.1 Swift Export Memory Fence Standard. You must prevent memory leaks and concurrency crashes caused by disjoint memory management architectures: Swift ARC and Kotlin/Native Mark & Sweep GC do not share an object graph or cycle collector. You must ensure that Swift 6 actor-isolated boundaries never form direct, strong circular references with Kotlin-exported objects, enforcing explicit disposable tokens, weak boundary wrappers, and strict Sendable-checked bridging.

## Strict Guidelines
- Engineers MUST ALWAYS implement an explicit cancellation or disposal pattern (e.g., `Job.cancel()`, `DisposableToken`, or `AutoCloseable`) when binding Swift observers to Kotlin 2.1 exported flows or interfaces.
- Engineers MUST NOT allow a Swift 6 actor or class to retain a Kotlin service while simultaneously passing a strong closure capture of `self` into that Kotlin service's callback registry.
- Swift 6 boundary adapters MUST capture dependencies weakly (`[weak self]`) within event-handling closures and immediately handle deallocation scenarios.
- Kotlin-exported interfaces consumed by Swift MUST expose non-retaining or detached subscriber mechanisms to prevent GC roots from pinning Swift actor graphs in memory.
- Engineers MUST NEVER mark Kotlin Swift Export references as unchecked `@unchecked Sendable` without establishing a synchronized memory fence or thread-confinement guarantee across Native GC threads and Swift Cooperative Thread Pools.
- Shared multiplatform callbacks SHOULD pass pure value types (`Sendable struct`) rather than reference types across the interop boundary to decouple object graph lifecycles.

## Bad vs Good Implementations
### Swift 6 Actor Observing Kotlin 2.1 Exported State Flow

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: The Swift class holds a strong ARC reference to `sessionManager`. The Kotlin Native `sessionManager` registers a callback that strongly captures `self`. Because Kotlin Native's Garbage Collector cannot traverse into the Swift ARC heap to detect cycles spanning both runtimes, neither object can ever be collected, leaking the entire actor-isolated tree.
```swift
import SharedCore

@MainActor
final class UserProfileViewModel {
    private let sessionManager: SessionManager // Kotlin 2.1 Exported Object

    init(sessionManager: SessionManager) {
        self.sessionManager = sessionManager
        // ANTI-PATTERN: Strong capture of Swift actor domain by Kotlin-exported callback.
        // ARC and Kotlin Native GC cannot detect this cross-runtime cycle.
        self.sessionManager.registerObserver {
            self.handleStateChange()
        }
    }

    private func handleStateChange() {
        // Update UI state
    }
}
```

#### Production Standard (Correct)
> **Standard**: The strong circular graph is severed. The Swift Task weakly captures `self` to eliminate the ARC cycle, while the lifecycle is explicitly bound to Swift via `Task.cancel()` on `deinit`. Kotlin's GC and Swift ARC maintain autonomous lifecycles separated by a pure async sequence memory fence.
```swift
import SharedCore

@MainActor
final class UserProfileViewModel {
    private let sessionManager: SessionManager
    private var subscriptionTask: Task<Void, Never>?

    init(sessionManager: SessionManager) {
        self.sessionManager = sessionManager
        
        // MEMORY FENCE: Decouple reference graph via structured Swift Task and weak capture.
        self.subscriptionTask = Task { [weak self] in
            // Kotlin 2.1 Swift Export exposes async sequence or explicit cancellable observer
            let observerToken = sessionManager.createObserverToken()
            for await state in observerToken.stateSequence {
                guard let self else { break }
                self.handleStateChange(state)
            }
        }
    }

    deinit {
        subscriptionTask?.cancel()
    }

    private func handleStateChange(_ state: SessionState) {
        // Update UI state
    }
}
```

### Kotlin 2.1 Swift-Exported Listener Decoupling via Disposable

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Kotlin Native holds closures bridged from Swift Export indefinitely in a persistent list. If the Swift caller fails to unregister, the closure wrapper keeps the Swift context permanently rooted in the Kotlin Native GC global root graph.
```kotlin
// Shared KMP Module (Kotlin 2.1)
package com.company.shared.session

class SessionManager {
    // ANTI-PATTERN: Persisting raw Swift closure handles in a persistent collection without disposal guarantees
    private val listeners = mutableListOf<() -> Unit>()

    fun registerObserver(listener: () -> Unit) {
        listeners.add(listener)
    }
}
```

#### Production Standard (Correct)
> **Standard**: Returns a deterministic `DisposableSubscription` handle to the Swift export consumer. Swift can bind this handle to its RAII or actor lifecycle (e.g., in `deinit`), ensuring that references are unhooked from the Kotlin Native GC root set upon Swift object teardown.
```kotlin
// Shared KMP Module (Kotlin 2.1)
package com.company.shared.session

interface DisposableSubscription {
    fun dispose()
}

class SessionManager {
    private val listeners = mutableListOf<() -> Unit>()

    fun registerObserver(listener: () -> Unit): DisposableSubscription {
        listeners.add(listener)
        return object : DisposableSubscription {
            override fun dispose() {
                listeners.remove(listener)
            }
        }
    }
}
```

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: Kotlin 2.1 Swift Export & Swift 6 Actor Memory Fence Standard

Kotlin 2.1 Swift Export & Swift 6 Actor Memory Fence Standard defines an industrial-grade behavioral standard for mobile engineering. Establishes deterministic bidirectional memory boundaries between Kotlin 2.1 Swift Export runtimes and Swift 6 actor-isolated domains. Eliminates untracked retain cycles between Swift ARC and Kotlin/Native Garbage Collector by enforcing weak bridges, Sendable decoupling, and explicit lifecycle disposal fences. 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: Cross-Runtime Retain Cycles Between Swift 6 Actor State and Kotlin Native GC Observers 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 DriftCross-Runtime Retain Cycles Between Swift 6 Actor State and Kotlin Native GC ObserversCritical
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 implement an explicit cancellation or disposal pattern (e.g., `Job.cancel()`, `DisposableToken`, or `AutoCloseable`) when binding Swift observers to Kotlin 2.1 exported flows or interfaces.

Engineers MUST ALWAYS implement an explicit cancellation or disposal pattern (e.g., `Job.cancel()`, `DisposableToken`, or `AutoCloseable`) when binding Swift observers to Kotlin 2.1 exported flows or interfaces.

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 allow a Swift 6 actor or class to retain a Kotlin service while simultaneously passing a strong closure capture of `self` into that Kotlin service's callback registry.

Engineers MUST NOT allow a Swift 6 actor or class to retain a Kotlin service while simultaneously passing a strong closure capture of `self` into that Kotlin service's callback registry.

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 6 boundary adapters MUST capture dependencies weakly (`[weak self]`) within event-handling closures and immediately handle deallocation scenarios.

Swift 6 boundary adapters MUST capture dependencies weakly (`[weak self]`) within event-handling closures and immediately handle deallocation scenarios.

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

Kotlin-exported interfaces consumed by Swift MUST expose non-retaining or detached subscriber mechanisms to prevent GC roots from pinning Swift actor graphs in memory.

Kotlin-exported interfaces consumed by Swift MUST expose non-retaining or detached subscriber mechanisms to prevent GC roots from pinning Swift actor graphs in memory.

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

Engineers MUST NEVER mark Kotlin Swift Export references as unchecked `@unchecked Sendable` without establishing a synchronized memory fence or thread-confinement guarantee across Native GC threads and Swift Cooperative Thread Pools.

Engineers MUST NEVER mark Kotlin Swift Export references as unchecked `@unchecked Sendable` without establishing a synchronized memory fence or thread-confinement guarantee across Native GC threads and Swift Cooperative Thread Pools.

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

Shared multiplatform callbacks SHOULD pass pure value types (`Sendable struct`) rather than reference types across the interop boundary to decouple object graph lifecycles.

Shared multiplatform callbacks SHOULD pass pure value types (`Sendable struct`) rather than reference types across the interop boundary to decouple object graph lifecycles.

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 Kotlin 2.1 Swift Export & Swift 6 Actor Memory Fence Standard critical for AI coding assistants?

Establishes deterministic bidirectional memory boundaries between Kotlin 2.1 Swift Export runtimes and Swift 6 actor-isolated domains. Eliminates untracked retain cycles between Swift ARC and Kotlin/Native Garbage Collector by enforcing weak bridges, Sendable decoupling, and explicit lifecycle disposal fences. 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 (Cross-Runtime Retain Cycles Between Swift 6 Actor State and Kotlin Native GC Observers) 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

Kotlin