From skainet-contributor-skills
Use ONLY when editing build scripts INSIDE the SKaiNET repository — `SKaiNET/build.gradle.kts`, `SKaiNET/settings.gradle.kts`, `SKaiNET/gradle/libs.versions.toml`, anything under `SKaiNET/build-logic/`, or adding/renaming/removing a `skainet-*` module within SKaiNET. Enforces version-catalog-only references, convention-plugin reuse, BOM registration, binary-compatibility-validator, vanniktech maven-publish, kover. Do NOT fire on a CONSUMER project's build script that just depends on `sk.ainet:skainet-bom` — that's the `skainet-consumer-setup` skill.
How this skill is triggered — by the user, by Claude, or both
Slash command
/skainet-contributor-skills:gradle-multimoduleThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Rules for editing the SKaiNET multi-module Gradle build. The project is a Gradle composite build: `build-logic/` is included via `includeBuild` and contributes convention plugins; every module under `skainet-*/` is included from `settings.gradle.kts`; all dependency coordinates resolve through `gradle/libs.versions.toml`.
Rules for editing the SKaiNET multi-module Gradle build. The project is a Gradle composite build: build-logic/ is included via includeBuild and contributes convention plugins; every module under skainet-*/ is included from settings.gradle.kts; all dependency coordinates resolve through gradle/libs.versions.toml.
build.gradle.kts, settings.gradle.kts, or *.gradle.kts under build-logic/.gradle/libs.versions.toml (versions, libraries, plugins, bundles).kmp.kotlin.skainet-testing owns assertion APIs and source-set placement for tests.build.gradle.kts MUST go through libs.versions.<x>, libs.<library>, or libs.plugins.<plugin>. Hard-coded version strings ("1.10.2", version = "2.3.21") MUST NOT appear in module build scripts.alias(libs.plugins.<x>). Direct id("...") version "..." is reserved for two cases only: (a) the sk.ainet.documentation convention plugin (no version because it's local), (b) plugins in build-logic/build.gradle.kts itself.skainet-foo module: (a) create skainet-foo/build.gradle.kts, (b) add include("skainet-foo") (or the nested form) to settings.gradle.kts, (c) register it in skainet-bom/build.gradle.kts if it ships as a published artifact.sk.ainet.dokka convention plugin. Modules apply it via id("sk.ainet.dokka"), not by configuring Dokka directly. Convention plugins live in build-logic/convention/src/main/kotlin/.binary-compatibility-validator is applied on every published module. Don't suppress it locally; if the API dump changes, regenerate via ./gradlew :module:apiDump and commit the diff (see kotlin skill, api-stability reference).compilerOptions { jvmTarget.set(JvmTarget.JVM_11) } inside the android { } block and inherited elsewhere through KMP defaults. Do not set higher.api(...) only when the dependency's types appear in a module's public Kotlin signatures. Default to implementation(...). KSP-generated source goes through add("kspCommonMainMetadata", project(":skainet-...:...-ksp-processor")).skainet-lang, skainet-data, skainet-io, skainet-backends, skainet-compile, skainet-models, skainet-pipeline, skainet-apps, skainet-test).build.gradle.kts that mirrors the closest sibling. Apply the same plugin set (kotlinMultiplatform, vanniktech.mavenPublish, binary.compatibility.validator, sk.ainet.dokka, optionally ksp, kotlinx-benchmark).include("skainet-<group>:<module>") to settings.gradle.kts in the matching // ====== <GROUP> section.skainet-bom/build.gradle.kts../gradlew :skainet-<group>:<module>:assemble to validate the wiring../gradlew :skainet-<group>:<module>:apiDump and commit the dump.Module build.gradle.kts — KMP library with KSP and Dokka:
plugins {
alias(libs.plugins.kotlinMultiplatform)
alias(libs.plugins.androidMultiplatformLibrary)
alias(libs.plugins.vanniktech.mavenPublish)
alias(libs.plugins.binary.compatibility.validator)
alias(libs.plugins.ksp)
id("sk.ainet.dokka")
id("org.jetbrains.kotlinx.benchmark")
}
kotlin {
explicitApi()
// ... target list goes here — see kmp skill ...
sourceSets {
commonMain {
kotlin.srcDir("build/generated/ksp/metadata/commonMain/kotlin")
dependencies {
api(project(":skainet-lang:skainet-lang-ksp-annotations"))
}
}
jvmMain.dependencies {
implementation(libs.kotlinx.benchmark.runtime)
}
commonTest.dependencies {
implementation(libs.kotlin.test)
}
}
}
// from: SKaiNET/skainet-lang/skainet-lang-core/build.gradle.kts:4-69
Catalog entries — every coordinate routed through libs.versions.toml:
[versions]
kotlin = "2.3.21"
ksp = "2.3.6"
dokka = "2.1.0"
kotest = "6.1.11"
kover = "0.9.8"
binaryCompatibilityValidator = "0.18.1"
[libraries]
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
kotest-runner-junit5 = { module = "io.kotest:kotest-runner-junit5", version.ref = "kotest" }
kotlinpoet = { module = "com.squareup:kotlinpoet", version.ref = "kotlinpoet" }
[plugins]
kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
skainet-docs = { id = "sk.ainet.documentation" }
// from: SKaiNET/gradle/libs.versions.toml:1-95
settings.gradle.kts — module registration, grouped by area:
includeBuild("build-logic")
// ====== LANG
include("skainet-lang:skainet-lang-core")
include("skainet-lang:skainet-lang-models")
include("skainet-lang:skainet-lang-ksp-annotations")
include("skainet-lang:skainet-lang-ksp-processor")
include("skainet-lang:skainet-lang-dag")
// ====== DATA
include("skainet-data:skainet-data-api")
include("skainet-data:skainet-data-transform")
include("skainet-data:skainet-data-simple")
include("skainet-data:skainet-data-media")
// ====== TEST
include("skainet-test:skainet-test-groundtruth")
include("skainet-test:skainet-test-java")
// from: SKaiNET/settings.gradle.kts:21-73
expect/actual placement — see ../kmp/SKILL.md.../kotlin/SKILL.md.../skainet-testing/SKILL.md.// WRONG — hard-coded coordinate / version
implementation("io.kotest:kotest-runner-junit5:6.1.11")
// RIGHT — catalog reference
implementation(libs.kotest.runner.junit5)
// WRONG — applying Dokka by id
plugins { id("org.jetbrains.dokka") version "2.1.0" }
// RIGHT — apply the convention plugin (it configures Dokka)
plugins { id("sk.ainet.dokka") }
// WRONG — adding a new module without registering it
// (skainet-io/skainet-io-newformat/build.gradle.kts created, but settings.gradle.kts unchanged)
// RIGHT — also edit settings.gradle.kts AND skainet-bom in the same change
include("skainet-io:skainet-io-newformat") // in settings.gradle.kts
references/catalog-aliases.md — version, library, and plugin aliases pulled from libs.versions.toml.references/convention-plugins.md — what sk.ainet.documentation / sk.ainet.dokka does and how to add a new convention plugin.npx claudepluginhub skainet-developers/skainet-coding-skills --plugin skainet-contributor-skillsProvides a checklist for code reviews covering functionality, security, performance, maintainability, tests, and quality. Use for pull requests, audits, team standards, and developer training.