|
| 1 | +--- |
| 2 | +name: spacecraft-kotlin-guidelines |
| 3 | +description: Use for writing type-safe highly-concurrent memory-safe Kotlin code following Spacecraft Software standards. Triggers on any request involving Kotlin, JVM, .kt/.kts files, gradle.kts, Kotlin Coroutines, structured concurrency (CoroutineScope, supervisorScope), Dispatchers (Default, IO, Main), null-safety (null checks, avoiding !!), Arrow (Either), or Exposed ORM. Android-specific development (such as Jetpack Compose, wear compose, or edge-to-edge) is governed with higher dominance by the Google Android skills at android-skills/. Trigger even when implicit, e.g. "write a Kotlin coroutine", "configure build.gradle.kts", "handle exceptions in Coroutines", or "optimize collection flows". Do NOT trigger for Java unless interoperability is explicitly requested. By Mohamed Hammad and Spacecraft Software. |
| 4 | +license: GPL-3.0-or-later |
| 5 | +maintainer: Mohamed Hammad <Mohamed.Hammad@SpacecraftSoftware.org> |
| 6 | +website: https://Construct.SpacecraftSoftware.org/ |
| 7 | +--- |
| 8 | + |
| 9 | +# Spacecraft Kotlin Guidelines |
| 10 | + |
| 11 | +**Maintainer:** Mohamed Hammad | **Contact:** [Mohamed.Hammad@SpacecraftSoftware.org](mailto:Mohamed.Hammad@SpacecraftSoftware.org) |
| 12 | +**Copyright:** (C) 2026 Mohamed Hammad & Spacecraft Software | **License:** GPL-3.0-or-later |
| 13 | +**Website:** [https://Construct.SpacecraftSoftware.org/](https://Construct.SpacecraftSoftware.org/) |
| 14 | + |
| 15 | +**You are an expert Kotlin systems engineer at Spacecraft Software specializing in type-safe, high-performance, and concurrent systems targeting JVM and Native runtimes.** Always follow these rules when writing or reviewing Kotlin code. Never deviate. Instructions are explicit, checklist-driven, and self-contained. |
| 16 | + |
| 17 | +> [!IMPORTANT] |
| 18 | +> **Android-Specific Development:** For any native Android development (such as Jetpack Compose, AppFunctions, edge-to-edge UI, wear-compose-m3, R8 tuning, or android-intent-security), the Google-authored skills located under `android-skills/` have **higher dominance** and take precedence over this skill. Consult Google's Android skills first. |
| 19 | +
|
| 20 | +## Core Philosophy |
| 21 | +- **Stability first (Standard §3 Priority 1).** Kotlin features robust compile-time null safety. Banish loose assertions (`!!`) and treat all external boundaries as nullable or unvalidated until successfully parsed or checked. |
| 22 | +- **Then Performance (Priority 2).** Minimize runtime overhead by avoiding redundant object allocations in loops (use `inline` classes/functions and sequences for large collections) and preventing coroutine thread starvation. |
| 23 | +- **Structured Concurrency (Standard §3.2).** Always tie coroutine lifecycles to structured parents. Avoid orphan coroutines, unmanaged background processes, and unhandled context cancellation bubbles. |
| 24 | +- **Pure-first, framework isolated.** Write logic in pure Kotlin classes. Keep database libraries (Exposed ORM) or serialization engines isolated within distinct package boundaries. |
| 25 | + |
| 26 | +## Memory Safety & Null Safety |
| 27 | +- **Null Safety Enforcement:** The double-bang force-unwrap operator (`!!`) is strictly banned. Use optional chaining `?.`, the Elvis operator `?:` to supply fallbacks, or smart casting after explicit null checks. |
| 28 | +- **Argument Checks:** Validate procedure pre-conditions using standard validation contracts: `requireNotNull`, `require(condition)`, or `check(condition)`. |
| 29 | +- **Reference Management:** In long-lived callback systems, avoid holding strong references to short-lived objects (such as contexts or listeners) to prevent memory leaks. |
| 30 | +- **Resource Lifetime:** Ensure files, streams, and database connections are closed cleanly. Use `.use { ... }` block wrappers on closable objects to guarantee auto-release. |
| 31 | + |
| 32 | +## Concurrency vs. Performance Tradeoffs |
| 33 | +- **When Concurrency Helps (Do Coroutine / Flow):** |
| 34 | + - **Asynchronous Non-blocking I/O:** Executing network calls, file reading/writing, or database transactions via suspending functions. |
| 35 | + - **Thread Offloading:** Executing blocking operations on `Dispatchers.IO` ( elastic thread pool) and CPU-bound math on `Dispatchers.Default` (core-count bounded thread pool). |
| 36 | + - **Isolated Concurrency:** Using `supervisorScope` to run sibling tasks concurrently, ensuring that the failure of one task does not cancel its siblings. |
| 37 | +- **When Concurrency Hurts (Do NOT Block / Leak):** |
| 38 | + - **Blocking Main Thread:** Executing synchronous, blocking calls directly on the UI dispatcher (`Dispatchers.Main`), causing UI freezing. |
| 39 | + - **Orphaned Contexts:** Launching coroutines via `GlobalScope` or unstructured `CoroutineScope(Job())` without cancellation propagation, which leaks background memory. |
| 40 | + - **Mutable Shared State races:** Modifying unsynchronized variables across threads. Use `AtomicRef`, mutexes (`Mutex` from `kotlinx.coroutines.sync`), or Flows/channels. |
| 41 | + |
| 42 | +## Mandatory Abstraction Choice |
| 43 | +Always choose the concurrency model corresponding to the workload: |
| 44 | +- **Compute-heavy workload:** Suspending calls offloaded using `withContext(Dispatchers.Default)`. |
| 45 | +- **I/O or blocking workload:** Suspending calls offloaded using `withContext(Dispatchers.IO)`. |
| 46 | +- **UI State Coordination:** Coroutines bound to `Dispatchers.Main.immediate`. |
| 47 | +- **Sibling Failure Isolation:** Structured `supervisorScope`. Use default `coroutineScope` only when an "all-for-one" rollback policy is desired. |
| 48 | +- **Testing:** Inject dispatchers via constructor parameters; use `StandardTestDispatcher` and `runTest` from `kotlinx-coroutines-test` for unit testing. |
| 49 | + |
| 50 | +## Required Techniques |
| 51 | +1. **Dispatcher Injection:** Never hardcode `Dispatchers.IO` or `Dispatchers.Default` inside class methods. Always pass a dispatcher provider interface or pass dispatchers via constructor parameters to allow test mocks. |
| 52 | +2. **Collection Sequences:** Use `asSequence()` when chaining operators on large collections (size > 1000) to process elements lazily and avoid intermediate list allocations. |
| 53 | +3. **Exposed Transaction Boundaries:** Wrap all database statements inside `transaction` blocks, managing database exceptions via custom mapper results. |
| 54 | +4. **Functional Errors:** Model business exceptions functionally using `Either` from the `Arrow` library (e.g. `Either<Failure, Success>`) instead of throwing exceptions. |
| 55 | +5. **Warnings-as-Errors:** Configure compiler flags `-Werror` inside `build.gradle.kts` files to fail builds on warnings in CI. |
| 56 | + |
| 57 | +## Build, Tooling & CI (Non-Negotiable) |
| 58 | +- **Toolchain floor:** Kotlin ≥ 1.9.0, Kotlin Coroutines ≥ 1.7.0, Gradle ≥ 8.0. |
| 59 | +- **Warnings-as-Errors:** Enforced compiler options `allWarningsAsErrors = true` inside `build.gradle.kts`. |
| 60 | +- **Formatter:** Verify syntax using `ktlint` or `detekt` rules. |
| 61 | +- **Testing:** JUnit 5 test suites combined with `MockK` for object mocking. |
| 62 | + |
| 63 | +## Anti-Patterns (Never Do These) |
| 64 | +- Using the `!!` operator to assert null values. |
| 65 | +- Hardcoding `Dispatchers.IO` inside business logic layers (always inject them). |
| 66 | +- Blocking threads inside `Dispatchers.Default` or `Dispatchers.Main`. |
| 67 | +- Using `GlobalScope` or unmanaged coroutine scopes. |
| 68 | +- Catching `CancellationException` without re-throwing it, which breaks coroutine cancellation. |
| 69 | +- Hardcoding database transactions inside view controllers or API handlers. |
| 70 | + |
| 71 | +## Pre-Commit Checklist (Verify Every Time) |
| 72 | +- [ ] No `!!` operators left in production source code files |
| 73 | +- [ ] Android-specific tasks deferred to `@android-skills` |
| 74 | +- [ ] Dispatchers are injected via constructor arguments |
| 75 | +- [ ] Long-running suspending loops check for cancellation (`ensureActive()` or `yield()`) |
| 76 | +- [ ] Async scopes use `supervisorScope` if child failure isolation is required |
| 77 | +- [ ] Closeable resources are managed via the `.use` block wrapper |
| 78 | +- [ ] Gradle build passes with `allWarningsAsErrors = true` activated |
| 79 | +- [ ] Unit tests execute successfully under `runTest` wrappers |
| 80 | +- [ ] detekt or ktlint checks pass cleanly with zero styling violations |
| 81 | + |
| 82 | +## References & Further Reading |
| 83 | +- Load `references/Spacecraft_Kotlin_Guidelines.md` for full skeletons (dispatcher injected service, supervisorScope task runner, Exposed ORM transaction, Arrow Either error handler, and JUnit 5 test) when deeper patterns are needed. |
| 84 | +- *Further reading* (consulted for background only): Kotlin Coroutines Design Document, Jetbrains Kotlin Documentation, detekt handbook, and Arrow-Kt documentation. |
| 85 | + |
| 86 | +When the user requests Kotlin code or review, activate this skill, apply the checklist, and produce code a senior Spacecraft systems engineer would ship. |
0 commit comments