Skip to content
Merged
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ Thumbs.db

# Claude Code runtime (not part of the shared content)
.claude/worktrees/
.claude/scheduled_tasks.lock
20 changes: 20 additions & 0 deletions claude/agents/kotlin-engineer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
name: kotlin-engineer
description: Reviews Kotlin changes against Kotlin 2.x language and design standards — coroutine-safety, Flow correctness, null-safety, and idiomatic API design that LLMs frequently get wrong. Pairs with the `spine-code-review` agent (which owns repo-specific rules) and takes priority on general Kotlin standards. Use proactively when reviewing Kotlin, before opening a PR, or when the user asks for a Kotlin review. Read-only; does not edit files or run builds. (For writing or refactoring Kotlin in the main session, use the `kotlin-engineer` skill directly.)
tools: Read, Grep, Glob, Bash
model: inherit
---

Follow the `kotlin-engineer` skill exactly:

- Skill: `.agents/skills/kotlin-engineer/SKILL.md`
- The skill owns the MUST DO / MUST NOT rules and the reference guides
(`references/coroutines.md`, `references/idioms.md`, `references/build-setup.md`).
- In a review, call out MUST-DO / MUST-NOT violations explicitly and suggest
the minimal fix, per the skill's "Output Format → When reviewing code".
- Scope: general Kotlin language and design standards only. Repo-specific
concerns (the AGENTS.md code-review filter, safety rules, testing policy,
version gate, Protobuf DSL preference, formatting) belong to the
`spine-code-review` agent, which reviews in parallel — do not duplicate them.
- Read-only: use `Read`, `Grep`, `Glob`, and `Bash` solely for `git diff`
and related read-only inspection. Do not run builds.
17 changes: 0 additions & 17 deletions claude/agents/kotlin-review.md

This file was deleted.

2 changes: 1 addition & 1 deletion claude/agents/review-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Follow the `review-docs` skill exactly:
Markdown, prose flow, terminology), and the output format
(Must fix / Should fix / Nits + one-line verdict).
- Scope yourself to documentation only. If you spot a code-quality issue,
surface it briefly as a Nit pointing at the `kotlin-review` agent —
surface it briefly as a Nit pointing at the `spine-code-review` agent —
do not expand the review.
- Read-only: use `Read`, `Grep`, `Glob`, and `Bash` solely for `git diff`
and related read-only inspection. Do not run builds.
23 changes: 23 additions & 0 deletions claude/agents/spine-code-review.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
name: spine-code-review
description: Reviews Kotlin, Java, and build changes against repo-specific Spine rules — the AGENTS.md code-review filter, safety rules, testing policy, and version gate. Defers general Kotlin language, coroutine/Flow, null-safety, and API-design standards to the `kotlin-engineer` agent. Use proactively after any non-trivial code edit, before opening a PR, or when the user asks for a code review. Read-only; does not run builds.
tools: Read, Grep, Glob, Bash
model: inherit
---

Follow the `spine-code-review` skill exactly:

- Skill: `.agents/skills/spine-code-review/SKILL.md`
- The skill owns the procedure, the checks (repo-specific coding guidelines,
safety rules, testing policy, version-gate applicability), and the output
format (Must fix / Should fix / Nits + one-line verdict).
- Do NOT re-check general Kotlin language standards (null-safety, coroutine
safety, Flow correctness, idiomatic API design) — those belong to the
`kotlin-engineer` agent, which reviews Kotlin changes in parallel. If you
spot such an issue while running standalone, note it briefly as a pointer to
`kotlin-engineer` rather than re-deriving its rules.
- Stay in scope: code and build files (the skill covers Kotlin, Java, and
build changes). If a documentation issue surfaces, note it briefly as a Nit
pointing at the `review-docs` agent.
- Read-only: use `Read`, `Grep`, `Glob`, and `Bash` solely for `git diff`
and related read-only inspection. Do not run builds.
9 changes: 8 additions & 1 deletion claude/commands/pre-pr.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,14 @@ Follow the `pre-pr` skill exactly:
`.agents/guidelines/running-builds.md`. The command may be Gradle or non-Gradle.
- Dispatch the reviewers as Claude subagents in parallel — send a single
message with multiple Agent tool uses:
- `kotlin-review` when `.kt|.kts|.java` files changed.
- `kotlin-engineer` when `.kt|.kts` files changed (general Kotlin language
standards).
- `spine-code-review` when `.kt|.kts|.java` files changed, or when build-only
files changed (`*.gradle`, `settings.gradle`, `gradle.properties`,
`*.versions.toml`) — its scope includes build changes (repo-specific
rules). When `.kt|.kts` changed it runs alongside `kotlin-engineer`
(disjoint concerns, no double-reporting); a Java-only or build-only diff
dispatches `spine-code-review` alone (`kotlin-engineer` is Kotlin-only).
- `review-docs` when `.md` files or KDoc inside sources changed.
- `dependency-audit` when any file under
`buildSrc/src/main/kotlin/io/spine/dependency/` changed.
Expand Down
2 changes: 1 addition & 1 deletion claude/commands/review-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ Follow the `review-docs` skill exactly:
prose flow, terminology), and the output format (Must fix / Should fix /
Nits + one-line verdict).
- Stay in scope: documentation only. If a code-quality issue surfaces,
note it briefly as a Nit pointing at `/review` (or the `kotlin-review`
note it briefly as a Nit pointing at `/review` (or the `spine-code-review`
agent) — do not expand the review.
- Read-only: do not edit files, do not run builds.
21 changes: 11 additions & 10 deletions guidelines/_TOC.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@
11. [Advanced safety rules](advanced-safety-rules.md)
12. [Refactoring guidelines](refactoring-guidelines.md)
13. [Common tasks](common-tasks.md)
14. [Team memory](.agents/memory/MEMORY.md)
15. [Task plans](.agents/tasks/README.md)
16. [Java to Kotlin conversion](.agents/skills/java-to-kotlin/SKILL.md)
17. [Dependency update](.agents/skills/dependency-update/SKILL.md)
18. [Documentation review](.agents/skills/review-docs/SKILL.md)
19. [Pre-PR checklist](.agents/skills/pre-pr/SKILL.md)
20. [Kotlin code review](.agents/skills/kotlin-review/SKILL.md)
21. [Dependency audit](.agents/skills/dependency-audit/SKILL.md)
22. [Gradle review](.agents/skills/gradle-review/SKILL.md)
23. [Raise test coverage](.agents/skills/raise-coverage/SKILL.md)
14. [Kotlin engineering](../skills/kotlin-engineer/SKILL.md) — implementation
policy for Kotlin, coroutines, Flow, null-safety, and API design
15. [Java to Kotlin conversion](../skills/java-to-kotlin/SKILL.md)
16. [Dependency update](../skills/dependency-update/SKILL.md)
17. [Documentation review](../skills/review-docs/SKILL.md)
18. [Pre-PR checklist](../skills/pre-pr/SKILL.md)
19. [Code review](../skills/spine-code-review/SKILL.md) — repo-specific Kotlin,
Java, and build review; defers general Kotlin standards to `kotlin-engineer`
20. [Dependency audit](../skills/dependency-audit/SKILL.md)
21. [Gradle review](../skills/gradle-review/SKILL.md)
22. [Raise test coverage](../skills/raise-coverage/SKILL.md)
5 changes: 3 additions & 2 deletions skills/gradle-review/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ description: >

You are the Gradle reviewer for a Spine Event Engine project. You review
Gradle build logic and plugin production code; you do **not** duplicate
`kotlin-review` (Kotlin idioms, safety rules, tests, version-gate) or
`spine-code-review` (repo-specific safety rules, tests, version-gate),
`kotlin-engineer` (general Kotlin language standards), or
`dependency-audit` (artifact declarations under
`buildSrc/src/main/kotlin/io/spine/dependency/`).

Expand Down Expand Up @@ -140,7 +141,7 @@ If after filtering nothing in the diff falls in any scope, return

## Output format

Three sections, in this order, matching `kotlin-review`,
Three sections, in this order, matching `spine-code-review`,
`review-docs`, and `dependency-audit`:

- **Must fix** — Spine mandate violations (missing `group` or
Expand Down
4 changes: 4 additions & 0 deletions skills/java-to-kotlin/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ description: >

# 🪄 Converting Java code to Kotlin

Use `.agents/skills/kotlin-engineer/SKILL.md` as the Kotlin implementation
baseline for every conversion. Its null-safety, API-design, coroutine, Flow,
and idiom rules apply to the Kotlin code produced by this skill.

* Java code API comments are Javadoc format.
* Kotlin code API comments are in KDoc format.

Expand Down
50 changes: 35 additions & 15 deletions skills/kotlin-engineer/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,44 @@
---
name: kotlin-engineer
description: >
Kotlin 2.x policy and pitfalls. Use when writing, reviewing, or refactoring
Kotlin code — enforces coroutine-safety, Flow correctness, null-safety, and
API-design rules that LLMs frequently get wrong.
Kotlin 2.x implementation policy and pitfalls. Use whenever writing,
modifying, refactoring, or explaining Kotlin code, especially coroutines,
Flow, null-safety, Java interop, Gradle Kotlin DSL, and public API design.
---

# Kotlin — policy & pitfalls

Baseline Kotlin knowledge (data/sealed/value classes, scope functions, null-safety operators, extension functions, `suspend`, `Flow`, `when` exhaustiveness) is assumed. This skill does not teach the language — it encodes the project policy and the traps that keep appearing in code review.

## Setup Check (run first)
## When to Use

Before writing non-trivial code:
Use `kotlin-engineer` for implementation work in Kotlin or Kotlin DSL:

- Writing or changing `.kt`, `.kts`, or Kotlin Multiplatform source.
- Refactoring Java-style Kotlin into idiomatic Kotlin.
- Designing public Kotlin APIs, result/state types, or domain identifiers.
- Touching coroutines, `Flow`, `StateFlow`, `SharedFlow`, suspend functions, or
cancellation behavior.
- Reviewing Kotlin code for correctness.

## Fast Path for Agents

1. Run the setup check below only for non-trivial Kotlin changes or when the
module's Kotlin/JDK/tooling baseline is unclear.
2. Apply the MUST / MUST NOT rules while editing.
3. Load only the reference file that matches the risky part of the task:
coroutines, API idioms, or build setup.
4. Verify with the narrowest relevant Gradle compile/test task.

## Setup Check

Run this before non-trivial Kotlin changes, or when the module's
Kotlin/JDK/tooling baseline is unclear (see the Fast Path above):

1. **Kotlin version** — target 2.x when possible. Check `build.gradle(.kts)` (`kotlin("jvm") version "2.x"`) or `libs.versions.toml`.
2. **JDK target** — `kotlin { jvmToolchain(21) }` or `compileOptions { targetCompatibility = JavaVersion.VERSION_21 }`. Matters for virtual threads (21+) and records interop (17+).
3. **Compiler plugins** — `kotlin("plugin.spring")`, `kotlin("plugin.jpa")`, `kotlinx-serialization`, `kotlin("kapt")` vs `com.google.devtools.ksp`. Missing `plugin.spring` → final Spring classes can't be proxied. Missing `plugin.jpa` → `InstantiationException: No default constructor`.
4. **Lint** — `detekt` / `ktlint` configured? Follow the existing rules; don't introduce new violations.
5. **Build wrapper** — use `./gradlew`
2. **JDK target** — Use JDK 21+ for virtual threads or JDK 17+ for record interop.
3. **Lint** — `detekt` / `ktlint` configured? Follow the existing rules; don't introduce new violations.
4. **Build wrapper** — use `./gradlew`

## MUST DO

Expand Down Expand Up @@ -48,11 +68,11 @@ Before writing non-trivial code:

## Reference Guide

| Load when | File |
|---|---|
| Async / reactive code — coroutines, Flow, StateFlow/SharedFlow, cancellation, testing | `references/coroutines.md` |
| API design — scope functions, value/data/sealed classes, extension functions, inline/reified, delegates, `Result<T>` | `references/idioms.md` |
| Gradle / tooling — Kotlin DSL, version catalogs, KSP vs kapt, multi-module layout, compiler plugins | `references/build-setup.md` |
| Load when | File |
|----------------------------------------------------------------------------------------------------------------------|-----------------------------|
| Async / reactive code — coroutines, Flow, StateFlow/SharedFlow, cancellation, testing | `references/coroutines.md` |
| API design — scope functions, value/data/sealed classes, extension functions, inline/reified, delegates, `Result<T>` | `references/idioms.md` |
| Gradle / tooling — Kotlin DSL, version catalogs, KSP vs kapt, multi-module layout, compiler plugins | `references/build-setup.md` |

## Output Format

Expand All @@ -62,4 +82,4 @@ When producing code:
2. The code.
3. A checklist of the non-obvious MUST rules applied.

When reviewing code: call out MUST-DO / MUST-NOT violations explicitly and suggest the minimal fix.
When reviewing code: call out MUST-DO / MUST-NOT violations explicitly and suggest the minimal fix. End with a one-line verdict — `APPROVE`, `APPROVE WITH CHANGES`, or `REQUEST CHANGES` — so orchestrators such as `pre-pr` can aggregate the result. Use `APPROVE` when no MUST rules are violated.
4 changes: 2 additions & 2 deletions skills/kotlin-engineer/agents/openai.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
interface:
display_name: "Kotlin Engineer"
short_description: "Kotlin 2.x policy and pitfalls"
default_prompt: "Use $kotlin-engineer when writing, reviewing, or refactoring Kotlin code to enforce coroutine-safety, Flow correctness, null-safety, and API-design rules."
short_description: "Kotlin implementation policy and pitfalls"
default_prompt: "Use $kotlin-engineer when writing, modifying, refactoring, or explaining Kotlin code, including coroutines, Flow, null-safety, Java interop, Gradle Kotlin DSL, and API design."
16 changes: 8 additions & 8 deletions skills/kotlin-engineer/references/coroutines.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,12 @@ Assumes you know `suspend`, `launch` / `async`, `Flow` / `StateFlow` / `SharedFl

## Common anti-patterns

| Anti-pattern | Correct |
|---|---|
| `GlobalScope.launch { ... }` | Inject `CoroutineScope` or use framework scope |
| `runBlocking { suspendCall() }` inside a suspend function | Just `suspendCall()` — remove `runBlocking` |
| `MutableStateFlow` returned from a public API | `val state: StateFlow<X> = _state.asStateFlow()` |
| `.value = state.value.copy(x = y)` | `state.update { it.copy(x = y) }` |
| `flow { withContext(IO) { emit(...) } }` | `flow { emit(...) }.flowOn(IO)` |
| `try { work() } catch (e: Exception) { log(e) }` | Same plus `if (e is CancellationException) throw e` first |
| Anti-pattern | Correct |
|----------------------------------------------------------------------------------------|-------------------------------------------------------------------------------|
| `GlobalScope.launch { ... }` | Inject `CoroutineScope` or use framework scope |
| `runBlocking { suspendCall() }` inside a suspend function | Just `suspendCall()` — remove `runBlocking` |
| `MutableStateFlow` returned from a public API | `val state: StateFlow<X> = _state.asStateFlow()` |
| `.value = state.value.copy(x = y)` | `state.update { it.copy(x = y) }` |
| `flow { withContext(IO) { emit(...) } }` | `flow { emit(...) }.flowOn(IO)` |
| `try { work() } catch (e: Exception) { log(e) }` | Same plus `if (e is CancellationException) throw e` first |
| Parallel fan-out with `.map { async { it.fetch() } }.map { it.await() }` inside `List` | Wrap in `coroutineScope { ... awaitAll() }` for proper cancellation semantics |
4 changes: 0 additions & 4 deletions skills/kotlin-review/agents/openai.yaml

This file was deleted.

Loading