17 KiB
KSLog Kotlin Toolchain migration report
Date: 2026-11-02
Base commit: 0b9fb30862c7319bb228039ee33eef9a0ddef95c
Kotlin Toolchain: v0.13.0 source commit
abc7a5f7579e9ef267107782048c76777f0bf932
Result
KSLog now has a checked-in, release-pinned Kotlin Toolchain project that loads,
builds every platform supported by Toolchain 0.13.0, runs real JVM tests,
generates both documentation formats, can publish signed KMP artifacts through
the configured mavenLocal destination, and is consumable by Gradle KMP and
Android projects. Migration validation redirects Maven Local to a temporary
repository; the destination itself is not inherently isolated. Toolchain Nexus
credentials/repository configuration is absent and resolved Maven Central
publishing is disabled.
This is not yet a publication-compatible full cutover. Toolchain 0.13.0
cannot represent linuxArm32Hfp and hard-codes the WasmJS artifact suffix as
-wasmjs instead of KSLog's released -wasm-js. The Gradle build is therefore
retained, mapped to the moved sources, and validated as the complete target and
publication fallback. No remote artifact, documentation, tag, or release was
published during this migration.
Implemented layout
kotlinandkotlin.batpreserve the official 0.13.0 wrapper content. Git attributes enforce LF forkotlin/Kotlin sources and CRLF forkotlin.bat. The wrappers select CLI0.13.0-dev-4444with the official pinned distribution SHA-256.project.yamlregisters the stableksloglibrary module and two local build plugin modules. The stable directory name prevents compiler module identity from depending on the checkout/worktree directory name.kslog/module.yamldeclares Android, JS, JVM, WasmJS, Linux x64/ARM64, and MinGW x64, plus Android/JDK/Kotlin settings and full publication metadata.- The 20 production files moved byte-for-byte into
kslog/src*Toolchain source roots.build.gradlemaps the retained Gradle source sets to those roots, including Linux ARM32. - Compiler module identities are pinned to the existing published identities:
JVM/Android
META-INF/dev.inmo_kslog.kotlin_module, leaf KLIBunique_name=dev.inmo:kslog, common metadatakslog_commonMain, and native metadatadev.inmo:kslog_nativeMain/kslog_nativeMain. kslog/test@jvm/CallbackKSLogTest.ktadds two focused tests covering exact callback forwarding and rejected lazy-message evaluation.plugins/dokkaadapts the official Apache-2.0 Toolchain Dokka plugin for KSLog's KMP graph and Dokka 2.2.0 HTML/GFM output. Each adapted Apache source carries a prominent KSLog modification/provenance notice, and cleanup rejects symbolic-link ancestors and requires real-path containment. Platform analysis receives JVM/common, JS, and WasmJS standard-library classpaths. Because the plugin API only exposes the JVM module classpath, the documented JS/WasmJS prebuild materializes the transformed Common and matching platform KLIBs for deterministic discovery. Generation fails before deployment if unresolved-type placeholders remain.plugins/github-releaseprovides an explicitgh release createcommand and a non-network dry-run mode. It runs the committed version consistency preflight first; no workflow invokes it.DEVELOPMENT.mddocuments Toolchain use, the Gradle fallback, isolated local publication, disabled Toolchain remotes, the retained Gradle release path, and release gating.verification/contains portable release/parser/wrapper checks plus the baseline/current Gradle publication, source-identity, public-signature, and consumer verifier used by CI.
Target and test matrix
| Target | Toolchain result | Runtime/test result | Contract notes |
|---|---|---|---|
| JVM | PASS | 2 tests found, 2 started, 2 passed | Bytecode major 52; 25-class list and public JVM method/field signatures from javap -public -s -constants match Gradle |
| Android | PASS | No device tests in the project; Android consumer compilation PASS | Bytecode major 61; 24-class list and public JVM method/field signatures match Gradle; minSdk 21, compileSdk/build tools 37 |
| JS | PASS | No test sources; Toolchain 0.13.0 exposes no browser/Node runner selection for a library | Gradle fallback keeps browser + Node declarations |
| WasmJS | PASS | No test sources; Toolchain 0.13.0 exposes no Node/d8 selection and only has browser test support | Gradle fallback keeps browser + Node + d8 declarations |
| linuxX64 | PASS | No test sources | Host-compilable KLIB |
| linuxArm64 | PASS | Cross-compiled; not runnable on this x64 host | KLIB publication produced |
| mingwX64 | PASS | Cross-compiled; not runnable on this Linux host | KLIB publication produced |
| linuxArm32Hfp | UNSUPPORTED | Gradle clean build compiles it; no tests | Absent from Toolchain 0.13.0 Platform; minimal model probe fails |
./kotlin check did not mistake empty platform suites for passing tests: the
report only claims the two JVM tests. Gradle reports JS, WasmJS, Android, and
native tests as NO-SOURCE or skipped, while still compiling all declared
targets, including Linux ARM32.
Verification evidence
The commands below are reproducible from the repository root. Temporary build logs and repositories are intentionally not part of the published report.
Model, build, checks, and compatibility
| Command | Result |
|---|---|
./kotlin show modules |
PASS; modules dokka, github-release, kslog |
./kotlin show settings -m kslog plus ./kotlin show tasks |
PASS; mavenCentral.enabled: false, only local publish repository configured, no Nexus/Central task references |
./kotlin show commands / show checks |
PASS; Dokka/release commands and builtin tests enumerated |
./kotlin clean && ./kotlin build |
PASS; all seven Toolchain platforms plus both plugin modules |
./kotlin check |
PASS; KSLog JVM tests 2/2 plus Dokka guard/classpath tests 4/4 |
./kotlin test -m dokka -p jvm |
PASS 4/4; transformed/platform classpath mapping, unresolved-output rejection, symlink containment, and scoped cleanup |
./gradlew --no-daemon clean build |
PASS; complete legacy build, including Linux ARM32 |
bash verification/verify_gradle_fallback.sh |
PASS; isolated baseline/current Gradle publication and committed consumer probe |
python3 verification/check_release_consistency.py and parser/wrapper checks |
PASS; four version copies, literal changelog heading, LF/CRLF attributes |
| Linux ARM32 minimal model probe | Expected failure: Product platforms list should not be empty at linuxArm32Hfp |
GitHub YAML, actionlint 1.7.7, shell syntax, git diff --check |
PASS |
ast-index rebuild |
PASS after final edits |
The Toolchain emits the existing insignificant inline warning. It also warns
that -module-name/-Xshort-module-name are passed more than once because the
built-in checkout-derived names are intentionally overridden; inspection of
the output JAR/KLIB manifests proves the last values match the released Gradle
module identities.
Source and ABI preservation
- All 20 production source files match the base commit byte-for-byte after their moves.
- The JVM 25-class and Android 24-class lists match; public JVM method/field
signature dumps from
javap -public -s -constantshave zero differences. - Gradle/Toolchain bytecode majors are JVM 52/52 and Android 61/61.
- Published JVM, common/native metadata, and supported leaf KLIB module identities match Gradle.
These checks are deliberately narrow. Source identity, consumer compilation, JVM class/signature comparison, and inspected module names are not a complete Kotlin metadata or KLIB ABI proof. Full cutover remains blocked and requires a dedicated metadata/KLIB compatibility review in addition to resolving the two upstream capability gaps.
Documentation and release command
| Command | Result |
|---|---|
./kotlin build -m kslog -p js -p wasmJs |
PASS; materializes the Common/JS/WasmJS analysis KLIBs required by the pinned plugin API |
./kotlin do dokkaHtml |
PASS; 156 files at build/dokka/html, zero unresolved-type placeholders |
./kotlin do dokkaGfm |
PASS; 101 files at build/dokka/gfm, zero unresolved-type placeholders |
| Output/link/platform inspection | PASS; canonical source links and Common/JVM/Android/JS/WasmJS/Native tabs |
KSLOG_GITHUB_RELEASE_DRY_RUN=true ./kotlin do githubRelease |
PASS; consistency preflight and v2.1.0 payload, no network mutation |
The legacy DOKKA_PATH override is intentionally not ported. It remains
available only through Gradle because Toolchain cleanup is restricted to direct
children of build/dokka.
Isolated publication and consumers
Toolchain publication used a temporary Maven repository selected with the JVM
maven.repo.local override, -m kslog, and a generated throwaway signing key.
The configured destination is named mavenLocal and would use the normal Maven
Local repository without that override. The temporary private key was deleted
after verification, and the normal Maven Local repository was not written.
| Check | Result |
|---|---|
./kotlin publish -m kslog mavenLocal |
PASS in an isolated repository |
| Toolchain artifact/signature inventory | 40 primary files and 40 detached signatures; 40/40 signatures verified with the throwaway public key |
| Toolchain required POM metadata comparison | PASS for root and every supported platform artifact |
| Gradle KMP consumer compile | PASS for JVM, JS, WasmJS, linuxX64, linuxArm64, mingwX64 |
| Gradle Android KMP consumer compile | PASS |
bash verification/verify_gradle_fallback.sh |
PASS; untouched-base and post-move Gradle outputs each contain the same 46 primary files, nine source JARs, and nine required-metadata POMs; no signing task/key/config is used |
Produced IDs are kslog, kslog-android, kslog-js, kslog-jvm,
kslog-linuxarm64, kslog-linuxx64, kslog-mingwx64, and kslog-wasmjs.
Root Gradle module metadata, Kotlin Tooling metadata, and sources are present.
Platform Toolchain publications contain placeholder Javadoc JARs, while the
root Toolchain Javadoc JAR is absent. The committed Gradle verifier uses a fresh
Gradle user home with only optional caches/wrapper links, an empty GnuPG
home, sanitized credential/signing environment variables, and separate Maven
repositories; it neither reads user Gradle signing configuration nor writes to
the normal Maven local repository.
Exact parity blockers and differences
- Linux ARM32:
linuxArm32Hfpis absent from the pinned 0.13.0Platformenum and schema. Adding it toproduct.platformsis rejected at model load, before compilation or publication can be customized. - Wasm artifact coordinate: built-in KMP publication maps
wasmJstokslog-wasmjs; there is no per-platform artifact-suffix override. KSLog's released coordinate iskslog-wasm-js. - Runtime declarations: JS browser/Node and WasmJS browser/Node/d8 runner selection are not exposed for this Toolchain library model. Compilation and publication work; those execution contracts stay in Gradle.
- POM shape: required name/description/URL/developers/license/SCM URL and
developer connection are preserved. Toolchain additionally generates the
SCM
connection. Its root KMP POM uses<packaging>pom</packaging>and akslog-jvmcompile dependency, while Gradle's root POM carries a Kotlin stdlib runtime dependency. The Toolchain Android POM additionally declareskotlin-stdlib-jdk7andkotlin-stdlib-jdk8; its JS POM omits Gradle'skotlin-dom-api-compat; and its Linux ARM64, Linux x64, and MinGW POMs move the Kotlin stdlib dependency from compile to runtime scope. Gradle module metadata consumer selection and the committed consumers passed, but direct POM consumers can observe these dependency/scope changes, so this is not publication-shape parity and requires review before full cutover. - Root Javadoc artifact: the 46-file Gradle publication has
kslog-2.1.0-javadoc.jar; the 40-file Toolchain publication omits it. This is the sixth missing primary file in addition to the five Linux ARM32 files. Toolchain platform Javadoc JARs contain a manifest plus a 78-byteREADME.mdplaceholder, while Gradle's Javadoc JARs contain only the manifest. - Android manifest and AAR layout: Gradle's manifest declares only
minSdkVersion=21; Toolchain additionally emitstargetSdkVersion=37. Gradle usesclasses.jar; Toolchain useslibs/kslog-jvm.jar. Both are valid AAR layouts, the bytecode level and compared public JVM method/field signatures match, and an Android KMP consumer compiles successfully. - JS manifest detail: public KLIB identity matches
unique_name=dev.inmo:kslog, but Toolchain's JS/Wasm KLIB does not include Gradle'sjsOutputName=kslogmanifest entry. - Android resource exclusions:
resourcePackagingis not accepted for a Toolchainkmp/lib. The produced AAR contains only the manifest and library JAR, so none of the three legacy serialization metadata exclusions are currently present. Gradle keeps the exclusions for the fallback. - Per-platform JVM release: Toolchain 0.13.0 does not allow
jvm.releaseto differ by platform. The module uses target-specific-jvm-target=1.8and-jvm-target=17; inspected bytecode proves majors 52 and 61. - Documentation output override: Gradle honors
DOKKA_PATH; Toolchain intentionally does not because arbitrary external cleanup would weaken the generated-output containment guarantee.
Because items 1 and 2 change released target/coordinate contracts, remote Toolchain publication must remain blocked until Toolchain gains the required capabilities or an explicitly reviewed compatibility implementation is added.
CI behavior
.github/workflows/build.ymlreplaces the stale workflow that attempted nonexistent Gitea/GitHub-Packages Gradle tasks on every push. Pushes and pull requests now run release/parser/wrapper preflights, Toolchain build/check, the complete retained Gradle build, and the isolated publication/API/consumer verifier. Checkout fetches full history so the verifier's pinned migration base commit is available. It has read-only repository permissions and no secrets or remote publication commands..github/workflows/kdocs.ymlremainsmaster-only. Its read-only generation job checks out withpersist-credentials: false, materializes the platform analysis KLIBs, runs Toolchain/Dokka, and uploads the generated artifact. A separate write-enabled job downloads only that artifact and deploys it tokdocs; project/plugin code never runs with a write credential.- All workflow actions are pinned to resolved commit SHAs.
- Hosted CI status is reported on draft PR #136; the local evidence above does not imply a hosted pass. SDK setup explicitly requests
platforms;android-37.0(API 37) and excludes the removed legacytoolspackage.
Remote-only checks not performed
- Inmo Nexus upload.
- Maven Central bundle upload/validation/release.
- GitHub release creation.
- Documentation deployment to the
kdocsbranch. - Android device tests and browser/Node/d8 tests (there are currently no such test sources); Linux ARM64 and MinGW runtime execution on matching hosts.
Recommended pull request
Suggested title:
build: add Kotlin Toolchain migration with compatibility fallback
Suggested body:
Summary
- add the pinned Kotlin Toolchain 0.13.0 wrappers and a stable
kslogKMP module- migrate source roots byte-for-byte and retain a validated Gradle fallback
- add real JVM tests, KMP-capable Dokka HTML/GFM tasks, and an explicit GitHub release command
- replace stale package-publishing CI with non-publishing Toolchain and full Gradle validation
- document isolated publication, release gating, and full verification evidence
Validation
- all Toolchain-supported targets build
- JVM tests: 2/2 pass
- retained Gradle clean build passes, including linuxArm32Hfp
- JVM/Android class lists and public JVM method/field signature diffs are empty; bytecode remains 8/17
- signed isolated KMP publication verified and consumed by Gradle KMP + Android projects
- Dokka HTML/GFM and GitHub release dry-run pass
Known blockers
Toolchain 0.13.0 has no linuxArm32Hfp platform and publishes
-wasmjsinstead of the released-wasm-jscoordinate. Therefore Gradle remains the publication fallback and remote Toolchain publication is not enabled. SeeMIGRATION_REPORT.mdfor the complete matrix and artifact differences.
This migration is ready only for a draft PR. Full Gradle removal is not review-ready and remains blocked by Toolchain 0.13.0's missing Linux ARM32 platform and incompatible Wasm artifact ID; the narrow checks above do not waive those requirements.