MaestroClient covers the daemon's REST surface: sessions CRUD, rename,
kill (with force), focus reporting, dirs/recent-dirs/projects/gitroot/
names/branches lookups, and the structured-session endpoints (prompt,
attachment upload, cancel, config, approval).
MaestroWebSocket covers all three WS connections — /api/events
(catalog deltas), /api/attach/:id (binary PTY frames both directions
plus ClientControl text frames for resize/ping), and
/api/structured/:id (transcript/state projections) — each exposing a
Flow of decoded events behind a connection handle.
Adds kotlinx-coroutines-android explicitly rather than relying on it
being pulled in transitively via lifecycle-runtime-ktx.
Compiled and exercised standalone against the same library versions
(no Android SDK available in this environment to run the app module
itself) to verify wire-format handling before landing.
Kotlin data classes mirroring maestro-protocol's wire types (Session,
CatalogEvent, ClientControl, structured-session projections, etc.),
@Serializable with kotlinx-serialization. ActivityState and NameSource
carry custom lenient deserializers matching the Rust side's forward-
compat behavior: an unknown variant degrades to the neutral default
instead of failing the whole payload.
Verified against fixtures mirrored from maestro-protocol's own test
suite (tag placement, snake_case renames, legacy-payload defaults).
Greenfield Gradle project under android/ — single-activity, Compose-only
UI, Kotlin DSL + version catalog throughout. MainActivity shows a
placeholder screen; no daemon connection yet (#262).
minSdk 26, targetSdk 34. OkHttp and kotlinx-serialization-json wired in
for the upcoming daemon client. Debug signing config uses a committed
debug.keystore so the APK installs without extra setup.