Implements M2 of docs/android/PLAN.md §6.2 (functional pass): the public
shard surface over /api/v1/public/shard/*, plus the live SSE feed with
reconnect/backoff and graceful degradation (§7).
- Shard DTOs (status/economy/feed/online/presence/champs/guilds/governors/
houses) mirroring public/shard.controller.js; ignoreUnknownKeys keeps
additive backend fields safe, and the live *.update frames decode into the
same board DTOs.
- PublicApi: the /public/shard/* GETs (status, feed, economy, online,
presence, champs, guilds, governors + history, houses).
- ShardStreamClient: OkHttp SSE over /public/shard/stream. Unlike the browser
EventSource it reconnects itself — a cold Flow<ShardStreamEvent> with
growing backoff (reset on open), no read timeout for the idle keepalive,
and clean teardown on cancel so a dropped feed degrades to "offline".
- ShardRepository: typed ApiResult snapshot reads + the shared live feed and
frame decoders.
- Screens: a Shard hub (status/online count/economy/presence/staff + live
activity feed with a live indicator) linking to live boards for champion
spawns, guilds, governors (+ on-demand term history) and falling houses
(IDOC). Boards seed from a snapshot then merge SSE deltas in place via a
reusable LiveBoard, mirroring the website's merge semantics. Wired into the
shared navigation drawer (§5); all strings externalized (§2).
- Tests (28): DTO/frame decode, LiveBoard merge, event-text formatting, and
SSE frame parsing.
Co-Authored-By: Claude <noreply@anthropic.com>