wtclaude c14342aa51 chore(sonar): measure the theme resolvers instead of excluding them (M12 phase 8)
sonar.coverage.exclusions carried a ui/theme/** directory glob from the M11
coverage push (COVERAGE_PLAN.md §2 phase 0). At the time that directory held
only Color.kt, Type.kt and the composables, so excluding all of it cost nothing.

M12 put three pure resolvers in it. ShardPalette, ShardStructure and
ShardTypeface are the milestone's core logic, they are the reason phases 1-3
could prove the no-op invariant as a JVM assertion, and JaCoCo on edge measures
them at 98%, 100% and 100%. The directory glob was dropping all of that out of
the denominator, so a future change that deleted those tests would not move the
coverage number at all.

The glob is now the one file it was really about: Theme.kt, the composable
(52%). The rest of ui/theme/ is measured, all of it 93% or better.

This does not rescue the gate - M12's already-measured code (data/appearance/
and ui/navigation/) covers at 93-100% and clears new_coverage >= 50 on its own.
It makes the number honest about which code the tests actually hold.

ui/components/ stays excluded as a directory: BrandAssets.kt is 11%, and the
9 tests it does have are on brandAssetUrl, the one part of it that is not a
composable body.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-08 10:21:18 -05:00
2026-07-19 01:38:07 -05:00
2026-07-19 01:38:07 -05:00
2026-07-19 01:38:07 -05:00
2026-07-19 01:38:07 -05:00
2026-07-19 01:38:07 -05:00

Runic Gateway — Android app

A native Android client for a Runic Gateway shard's public site + player self-service. It is purely an API client of the website backend — it never talks to the link/ sidecar or the game shard directly, and it ships none of the shard/sidecar wiring. It surfaces the same content and player features as the website's browser client, minus every administrative/management console.

The authoritative design contract is docs/android/PLAN.md in the RunicGateway/docs repo. The authoritative API reference is the committed OpenAPI spec at website/server/swagger/swagger-output.json.

Status

M0 — repo scaffold. Gradle + Compose + Hilt skeleton with CI (lint + unit test + debug build). The functional Kotlin pass (M1M4) and the design pass (M5) follow — see the plan's milestones (§9).

Stack

Concern Choice
Language / UI Kotlin + Jetpack Compose (Material 3)
Navigation Navigation-Compose, single-activity
HTTP Retrofit + OkHttp, kotlinx.serialization
Async Coroutines + Flow
DI Hilt
Prefs / base URL Jetpack DataStore
Tokens at rest EncryptedSharedPreferences
Images Coil
Min SDK Android 10 (API 29)
Target / compile SDK 35

Dependency and plugin versions are pinned in gradle/libs.versions.toml.

Build

Requires JDK 17 and the Android SDK (ANDROID_HOME / local.properties).

./gradlew assembleDebug     # build a debug APK -> app/build/outputs/apk/debug/
./gradlew test              # JVM unit tests
./gradlew lint              # Android lint
./gradlew installDebug      # install on a connected device/emulator

The app self-configures its server URL on first run (PLAN.md §3), so a single build works against any shard's website — there is no compiled-in API host.

CI

.gitea/workflows/pr-checks.yml gates PRs into main with ./gradlew lint test assembleDebug on the org's self-hosted runner (JDK 17 + Android SDK). Debug builds are auto-signed, so the gate needs no secrets. This pipeline is verified green end-to-end on the runner (M0). A signed release APK attached to a Gitea release comes at M6.

The workflow carries a few runner-specific accommodations (each explained in comments in the file), because this self-hosted runner differs from a stock GitHub runner:

  • JDK 17 is installed via apt (not actions/setup-java) — the runner can't resolve api.adoptium.net, while the Ubuntu mirrors are reachable.
  • SDK packages are installed explicitly via sdkmanager, with set +o pipefail so yes dying of SIGPIPE doesn't fail the step.
  • gradlew is chmod +x'd in the run step — the runner's checkout does not preserve the git executable bit, so ./gradlew alone fails with "Permission denied".

Contributing

See CONTRIBUTING.md. AI-assisted contributions must be disclosed (org policy): tick the PR box naming the tool and add a Co-Authored-By trailer to AI-authored commits. Licensed GPL-3.0-or-later.

Description
No description provided
Readme 10 MiB
v0.5.0 Latest
2026-08-08 16:28:50 +00:00
Languages
Kotlin 99.8%
Python 0.2%