TranslationArtifactVersionIdTag.parse was declared to return DialectIdTag? and constructed one. The tag-name guard was right -- it compared against this class's own TAG_NAME -- so the event id came off the right slot of the right tag, and nothing behaved differently: all nine call sites reach straight through to .ref, and the two classes have identical shape. A caller that branched on the type, or collected parse results across the family, would have got a dialect reference where a translation reference belongs. The twenty-four tags in that package were written from one template, so the whole family was checked: this was the only mismatch. Every other parse returns and constructs its enclosing class. The wire names are a separate matter and stay as they are. Six tags carry a stray Tag suffix -- dialectIdTag, chapterIdTag, chunkIdTag, translationIdTag, translationChapterIdTag, translationChunkIdTag -- which ProjectIdTag already documents as a copy-paste slip that cannot be fixed, because those strings sit inside event ids the group has signed. Renaming one invalidates every signature over it. TagRoundTripTest covers all twenty-four, grouped by the four shapes they take, plus a matrix asserting no parse accepts any of the other twenty-three arrays -- the same template's other failure mode, a copied TAG_NAME. The mechanism is the type argument, and it has to be written out. The first draft of the test left T to inference and passed against the bug when it was reintroduced to check: T is read off the function reference, so a parse returning DialectIdTag simply makes T be DialectIdTag, every member the two classes share resolves, and assertIs<T> is a tautology. With the class named explicitly at each call site, a parse whose declared return type is a sibling no longer satisfies (Array<String>) -> T? and the file stops compiling on that tag's own line -- earlier and more precisely than any runtime check. Verified by re-breaking the file: the build fails naming the offending parse. The KDoc says so, because tidying the type argument away would silently defeat the test. One more test, on arrayOfNotNull rather than on the family: it strips only trailing nulls and writes "" for an interior one, so a reference assembled with an author but no relay hint is [name, id, "", author] and the author stays in slot 3. That is the shape most of these tags are assembled in, and if it ever changed every author would be read as a relay hint and dropped. 605 unit tests pass on --rerun-tasks, and m3Audit is clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This is a Kotlin Multiplatform project targeting Android, iOS, Desktop (JVM).
-
/composeApp is for code that will be shared across your Compose Multiplatform applications. It contains several subfolders:
- commonMain is for code that’s common for all targets.
- Other folders are for Kotlin code that will be compiled for only the platform indicated in the folder name. For example, if you want to use Apple’s CoreCrypto for the iOS part of your Kotlin app, the iosMain folder would be the right place for such calls. Similarly, if you want to edit the Desktop (JVM) specific part, the jvmMain folder is the appropriate location.
-
/iosApp contains iOS applications. Even if you’re sharing your UI with Compose Multiplatform, you need this entry point for your iOS app. This is also where you should add SwiftUI code for your project.
Build and Run Android Application
To build and run the development version of the Android app, use the run configuration from the run widget in your IDE’s toolbar or build it directly from the terminal:
- on macOS/Linux
./gradlew :composeApp:assembleDebug - on Windows
.\gradlew.bat :composeApp:assembleDebug
Build and Run Desktop (JVM) Application
To build and run the development version of the desktop app, use the run configuration from the run widget in your IDE’s toolbar or run it directly from the terminal:
- on macOS/Linux
./gradlew :composeApp:run - on Windows
.\gradlew.bat :composeApp:run
Build and Run iOS Application
To build and run the development version of the iOS app, use the run configuration from the run widget in your IDE’s toolbar or open the /iosApp directory in Xcode and run it from there.
Learn more about Kotlin Multiplatform…