Phases 8 and 9 of docs/member-archive.md. The tests ran in the phases where the code they cover first existed -- the way the batch-signing note's did -- so this is what was missing from them, plus the rollout note, plus the plan marked built. **Compared row by row, not by count.** The end-to-end test asserted the two databases held the same *number* of artifacts, chapters and chunks. That is not the claim: two databases can hold the same counts and disagree about every row, and a rebuild that lost the group's signature -- or re-authored a row as whoever sent it -- would pass a count and fail the only thing an archive is for. It now compares `(id, author, signature)` per row across every archived kind, and then asserts each one is authored by the room and carries a signature. The artifact version is the one exception, and it has to be: nobody signs it, it is derived from the signed artifact on arrival. Which is exactly why it is not archived, and why a chapter's foreign key survives without it. **An old build does not ignore an archive page, it renders it.** Phase 9's first draft said an old build "files it as unsupported, exactly as it does today for anything it does not know" -- true, and it reads better than it lives. An unsupported row's content is `event.toJson()` and it renders as an ordinary chat bubble, so every member on an old build sees each archive page as a raw-JSON bubble of up to `MAX_PAGE_BYTES`, once per page. Nothing breaks and nothing is lost, but a group mid-upgrade gets a genuinely unpleasant transcript, and that is worth knowing before the first archive goes out. So the rollout rule is stated rather than implied: the receiving half ships safely on its own -- phases 1-4 send nothing -- and no member starts sending until every member understands kind 30327. The mitigation if that ever proves unacceptable is the one the appendix rejects for other reasons, and it is named there so the trade can be weighed rather than rediscovered. **The plan is marked built**, with a table of the five places the implementation chose differently from the plan and why: nine archivable kinds became six, a count cap that could never fire, queueing moved a phase later, a re-read that was never needed, and the rollout note above. Phase 8 also records the three tests that were not in the first draft, each written because something passed for the wrong reason -- a cap that could not fire, an out-of-order test on an archive that was never out of order, and a sweep whose "still missing" count included failures a later pass had already fixed. 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…