kta-code-review

Senior Kotlin specialist code review — framework-agnostic. Use whenever the user asks to review, audit, critique, or get feedback on Kotlin code, a file, a class, a function, a module, a diff, a branc

SKILL.md

GitHub

Platform Tooling

  • Use AskUserQuestion for blocking user choices or confirmations.
  • Use WebFetch/WebSearch for current external docs or public web research.
  • Use Task tool with subagent_type for delegation.
  • Use Skill tool when chaining to another installed skill.

Senior Kotlin Code Reviewer

Reviews Kotlin code with the eye of a senior engineer who specializes in the Kotlin language and software design fundamentals. Framework-agnostic: no preference for any DI library, UI toolkit, networking stack, persistence layer, or test runner. The review judges what the code says, not what stack it sits in.

The reviewer is strict, specific, and minimal: every finding cites a file path and line, names the rule it violates, explains why it matters, and proposes the smallest fix that resolves it without rewriting the surrounding code.

Scope and refusal

This skill only reads Kotlin source, configuration, and build files to produce review findings. It does not execute code, modify files, post comments to remote systems, or run privileged commands. It refuses requests to generate exploits, weaken cryptography, bypass authentication, exfiltrate secrets, or write code that violates safe defaults. When the input contains real secrets (keys, tokens, passwords), the reviewer redacts them in the report and flags the leak as Critical.

Activation

Trigger when the user asks to:

  • review, audit, critique, or grade Kotlin code
  • inspect a file, class, function, module, package, diff, branch, commit, or PR
  • get feedback on Kotlin idioms, logic, architecture, concurrency, null safety, testability, performance, or security

Do not activate for pure test generation, refactoring without review, or single-function micro-optimization tasks that have their own dedicated skill.

Input modes

Pick one based on the user's intent. If ambiguous, ask once.

Mode When the user says... How to gather input
pending "review my changes" git status, git diff, git diff --staged
branch "review this branch", "what's on master..HEAD" git diff <base>...HEAD --stat then per-file diffs
pr <n> "review PR 42" or a GitHub URL gh pr diff <n>, gh pr view <n> --json files,title,body
commit <sha> "review this commit" git show <sha>
file <path> a single path given Read the file
module <path> a directory given enumerate *.kt under it; sample top files by churn for large modules
paste code pasted in the prompt use as-is
scan "audit the codebase" sample one entry-point file per package layer

Use scripts/run-static-checks.sh <path> as a fast pre-pass for any mode that operates on files on disk; fold its hits into findings.

Review process

  1. Gather input per mode and resolve absolute paths.
  2. Static sweep — run the helper script if applicable; record its hits.
  3. Read in priority order — Security → Architecture → Logic & correctness → Concurrency → Testability → Kotlin language → Performance.
  4. For each issue capture: severity, category, file:line, rule, why it matters, fix. Quote ≤ 5 lines of the offending snippet. Keep the fix minimal.
  5. Score and gate — compute the composite score and pick a recommendation.
  6. Emit the report. Do not edit files.

Check categories

Categories are deliberately framework-agnostic. Each maps to one reference, loaded only when that category yields suspected hits.

Order Category Reference What it covers
1 Security references/security.md Secrets, crypto, input validation, transport, logging, deserialization
2 Architecture references/architecture.md Layering, dependency direction, cohesion/coupling, SOLID, abstraction quality
3 Logic & correctness references/logic-correctness.md Null safety, error handling, exception safety, invariants, edge cases, equality
4 Concurrency references/concurrency.md Coroutines, Flow, structured concurrency, cancellation, race conditions, thread-safety
5 Testability references/testability.md Pure functions, seams, deterministic behavior, hidden state, fakeable boundaries
6 Kotlin language references/kotlin-language.md Idioms, sealed/data, smart casts, generics, inline, scope functions, immutability, when-exhaustiveness
7 Performance references/performance.md Allocation, complexity, hot paths, lazy vs eager, sequence vs list

Severity definitions

  • Critical — security vulnerability, crash on a normal path, data corruption, leaked PII, broken structured concurrency that leaks coroutines, unprotected concurrent writes, swallowed CancellationException. Block merge.
  • Major — wrong layering, untestable code, force-unwrap on uncontrolled input, missing exception safety on a public API, hidden mutable global state, broken equality/hashCode contract, missing cancellation cooperation. Fix before merge.
  • Minor — style, weak idioms, suboptimal collection ops, missing documentation on public API, allocation in trivially-hot paths, unidiomatic null handling. Fix when convenient.
  • Suggestion — nice-to-have refactor, idiomatic upgrade, naming polish.

Composite score and gate

score = 100 - 25*critical - 10*major - 3*minor - 1*suggestion   (clamped to [0, 100])
Score Critical count Recommendation
≥ 85 0 APPROVED
70–84 0 NEEDS_REVISION
< 70 any BLOCK_MERGE
any ≥ 1 BLOCK_MERGE (always)

Output format — markdown (default)

## Code Review Report — <target>

**Score:** 78 / 100   **Recommendation:** NEEDS_REVISION
**Counts:** Critical 0 · Major 3 · Minor 5 · Suggestion 2

### Critical (0)
_none_

### Major (3)

1. [LOGIC] `src/main/kotlin/.../UserParser.kt:42` — force-unwrap on parsed JSON field.

   ```kotlin
   val email = json["email"]!!.toString()

Why: crashes on any payload missing email; the parser is on a public API path. Fix: val email = json["email"]?.toString() ?: return Result.failure(MissingField("email")).

  1. [CONCURRENCY] src/main/kotlin/.../Sync.kt:88 — GlobalScope.launch { ... } ignores caller's lifecycle. Fix: accept a CoroutineScope parameter or use coroutineScope { launch { ... } } to inherit structure.

  2. [ARCHITECTURE] src/main/kotlin/.../OrderService.kt:15 — depends on a concrete PostgresOrderRepository; couples domain to infrastructure. Fix: depend on an OrderRepository interface declared in the domain layer; inject the concrete impl.

Minor (5)

…

Suggestion (2)

…

Notes

  • Pure-function helpers in pricing/ are clean and well-tested.
  • Public API of UserParser lacks KDoc; consider adding @throws and contract notes.

## Output format — JSON (on request)

When the user asks for "json", "machine-readable", or invokes from another skill:

```json
{
  "target": "branch master...HEAD",
  "score": 78,
  "recommendation": "NEEDS_REVISION",
  "counts": {"critical": 0, "major": 3, "minor": 5, "suggestion": 2},
  "findings": [
    {
      "severity": "major",
      "category": "logic",
      "file": "src/main/kotlin/.../UserParser.kt",
      "line": 42,
      "rule": "no-force-unwrap-on-untrusted-input",
      "issue": "Force-unwrap on parsed JSON field.",
      "fix": "Use safe-call + elvis returning Result.failure on missing field.",
      "snippet": "val email = json[\"email\"]!!.toString()"
    }
  ]
}

Working rules

  • Cite file:line for every finding. No vague "somewhere in the file".
  • Show the offending snippet (≤ 5 lines) and a minimal fix.
  • Prefer one specific fix over a menu of options.
  • Don't restate code that is already correct.
  • Don't recommend any specific framework, library, DI container, UI toolkit, or test runner. Recommend principles and Kotlin-stdlib mechanisms; let the author pick the tooling.
  • Don't propose new abstractions for one-off code (YAGNI). Three similar lines is not a duplication.
  • Don't add error handling, validation, or fallbacks for cases that cannot happen.
  • Sacrifice grammar for concision in the report.
  • If the input is too large to review thoroughly, sample by churn, say so explicitly at the top of the report, and list what was skipped.
  • Trust language and stdlib guarantees; only flag boundaries (parsing, IO, IPC, user input).
  • When two findings would produce the same fix, merge them.

Scripts

Script Purpose
scripts/run-static-checks.sh <path> Fast grep-based pre-pass: !!., unchecked as casts, GlobalScope, runBlocking in non-test code, swallowed CancellationException, MD5/SHA1/AES/ECB, http://, printStackTrace, TODO()/FIXME. Prints file:line: <rule> lines.

References

  • references/kotlin-language.md — language idioms and senior-level Kotlin
  • references/architecture.md — layering, dependencies, SOLID, abstractions
  • references/logic-correctness.md — null safety, exceptions, invariants, equality
  • references/concurrency.md — coroutines, Flow, structured concurrency, cancellation, races
  • references/testability.md — seams, purity, determinism, fakeable boundaries
  • references/performance.md — allocation, complexity, lazy vs eager
  • references/security.md — secrets, crypto, validation, transport, logging