docs(ui): finalize MVP plan structure and de-archaeologize topic docs
MVP web client (Phases 1-30) is complete; reorganize planning + living docs around that. - PLAN.md kept as the staged MVP record (1-30) with a status block + pointers; removed the 31-36 stages, regression scenarios, and deferred-TODO section (moved out); fixed a stale cross-machine plan path. - ui/PLAN-finalize.md (new): active web-finalization plan in 8 stages (visual system, a11y, i18n, error UX, PWA, build hygiene, docs, owner manual-QA loop); absorbs former Phases 33 and 35. - ui/ROADMAP.md (new): post-MVP (Wails, Capacitor, realistic projection, acceptance + regression scenarios) and triaged deferred follow-ups. - ui/docs/README.md (new): grouped topic-doc index. - De-archaeologized all 20 ui/docs topic docs + ui/README.md + ui/core/README.md: stripped Phase-N build history, rewritten as current-state; deferred work now points at ROADMAP.md / PLAN-finalize.md. Docs-only; no code change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+156
@@ -0,0 +1,156 @@
|
||||
# UI Client — Post-MVP Roadmap
|
||||
|
||||
The MVP web client (Phases 1–30 of [PLAN.md](PLAN.md)) is complete. The
|
||||
near-term web **finalization** pass — visual system, accessibility,
|
||||
localisation, error UX, PWA, docs — is tracked separately in
|
||||
[PLAN-finalize.md](PLAN-finalize.md).
|
||||
|
||||
This roadmap holds the work deliberately deferred until after the web
|
||||
client is finalized: the native platform wrappers, the realistic
|
||||
multi-turn projection (a feature, not polish), the cross-platform
|
||||
acceptance pass, and a set of non-blocking follow-ups. Items keep their
|
||||
original PLAN.md phase numbers for continuity; their full original specs
|
||||
live in the PLAN.md git history.
|
||||
|
||||
---
|
||||
|
||||
## Phase 31 — Wails Desktop Wrapper
|
||||
|
||||
Goal: native desktop app (macOS, Windows, Linux) running the same
|
||||
frontend bundle, with `ui/core` embedded as Go instead of WASM.
|
||||
|
||||
Key artifacts: `ui/desktop/` Wails entry + IPC bindings; per-OS secure
|
||||
storage (macOS Keychain, Windows DPAPI, Linux Secret Service with a
|
||||
`0600` file fallback); `modernc.org/sqlite` cache; `WailsCore` /
|
||||
`WailsKeyStore` / `WailsCache` adapters; OS icons; `ui/Makefile`
|
||||
`desktop-*` targets; `ui/docs/desktop-secure-storage.md`. Re-evaluate
|
||||
Wails v2 vs v3 at phase start.
|
||||
|
||||
Depends on: Phase 6 (KeyStore/Cache interfaces) and the web form of
|
||||
Phases 7–30. Acceptance: all three OS binaries launch, log in, and
|
||||
persist the keypair on a fresh profile from one codebase; Linux file
|
||||
fallback activates without libsecret and writes `0600`.
|
||||
|
||||
## Phase 32 — Capacitor Mobile Wrapper
|
||||
|
||||
Goal: native iOS and Android apps running the same frontend bundle,
|
||||
calling a gomobile-compiled `ui/core`.
|
||||
|
||||
Key artifacts: `ui/mobile-bridge/bridge.go` gomobile façade;
|
||||
`ui/Makefile` `gomobile`/`ios`/`android` targets; Capacitor project +
|
||||
custom `galaxy-core` plugin (Swift + Kotlin); `CapacitorCore` /
|
||||
`CapacitorKeyStore` / `CapacitorCache` adapters (secure-storage +
|
||||
sqlite community plugins); app icons + splash; `ui/docs/mobile-bridge.md`.
|
||||
|
||||
Depends on: Phase 6 and the web form of Phases 7–30. Acceptance: iOS
|
||||
Simulator and Android Emulator launch, log in, and persist the keypair
|
||||
across restarts (manual smoke); same `Core`/`Storage` TS interfaces as
|
||||
web/desktop. Full Appium automation lands in Phase 36.
|
||||
|
||||
## Phase 34 — Multi-Turn Projection (realistic planet forecast)
|
||||
|
||||
Goal: a realistic multi-turn planet projection, surfaced in the planet
|
||||
inspector and the calculator's planet area. (Reach circles already
|
||||
shipped in Phase 30; this phase no longer owns them.)
|
||||
|
||||
The Phase 30 planet area is single-turn (MAT-only). This phase makes it
|
||||
realistic and multi-turn by extracting the planet economy into `pkg/calc`
|
||||
(single-sourced, engine delegates): `PlanetProduction`,
|
||||
`ProducePopulation`, `UnpackColonists`, `UnpackCapital`, reusing
|
||||
`ProduceShipsInTurn`; plus a `ProjectPlanetBuild` projector ("K ships in
|
||||
M turns" under guaranteed per-turn supply) mirroring `MakeTurn` steps
|
||||
09/12/14/15. CAP and COL only affect future turns (post-production
|
||||
unpacking), so they become meaningful here and join MAT as supply inputs
|
||||
in the calculator's planet area.
|
||||
|
||||
Key artifacts: the `pkg/calc` economy extraction + bridges + `Core`
|
||||
typings; planet-inspector forecast section (next-turn population,
|
||||
industry, materials, progress); calculator planet area gains CAP/COL
|
||||
supply; `ui/docs/multi-turn-projection.md`.
|
||||
|
||||
Depends on: Phases 17, 18, 30. Acceptance: projector output byte-
|
||||
identical to running the engine's per-turn planet update over the same
|
||||
turns (Go parity); inspector + calculator readouts consistent with it.
|
||||
|
||||
## Phase 36 — Acceptance Pass
|
||||
|
||||
Goal: reconcile implementation, documentation, and regression coverage
|
||||
before declaring the client ready for technical beta.
|
||||
|
||||
Key artifacts: final cross-platform regression run on a release
|
||||
candidate; `ui/docs/release-checklist.md`; visual-regression baselines;
|
||||
Appium harness (iOS Simulator + Android Emulator) covering login, push,
|
||||
and a full turn loop, wired into a macOS-runner CI job as a pre-release
|
||||
gate; a docs/README/ARCHITECTURE/FUNCTIONAL drift sweep.
|
||||
|
||||
Depends on: Phases 1–35 (incl. the finalization plan). Acceptance:
|
||||
implementation matches every documented contract; the cross-cutting
|
||||
regression scenarios below pass on web, desktop, and mobile; Appium
|
||||
smoke passes on iOS and Android in CI.
|
||||
|
||||
### Cross-cutting regression scenarios
|
||||
|
||||
- A fresh device generates a keypair, completes email-code login, and
|
||||
signs a follow-up authenticated request on every platform.
|
||||
- A returning device resumes its session without re-login, preserves
|
||||
queued orders, and keeps receiving push events without gaps.
|
||||
- Server-side session revocation tears down the push stream and forces
|
||||
re-login on every platform within one second.
|
||||
- Tampering with `payload_bytes`, `payload_hash`, `request_id`,
|
||||
`message_type`, or any signature byte is rejected by `ui/core` with a
|
||||
stable error code.
|
||||
- Requests outside the freshness window are rejected before network; a
|
||||
clock-skew warning surfaces when the local clock disagrees beyond it.
|
||||
- The map renderer holds 60 fps with a 1000-primitive fixture on web
|
||||
(Chrome, Edge, Safari, Firefox), desktop (Wails on mac/win/linux),
|
||||
and mobile (latest iPhone, mid-range Android).
|
||||
- The sidebar preserves tool state across tab switches; the active view
|
||||
preserves state across view switches.
|
||||
- Order draft survives reloads, view switches, network drops, and
|
||||
history-mode entry/exit.
|
||||
- Orders queued offline flush in order on reconnect; a turn-cutoff
|
||||
conflict surfaces as a failed-order banner without retrying forever.
|
||||
- History mode applies to every view; the order tab disappears in
|
||||
history mode and the prior draft is restored on return.
|
||||
- The calculator's math matches `pkg/calc/` byte-for-byte; drift fails
|
||||
CI.
|
||||
- Linux desktop without Secret Service completes login via the `0600`
|
||||
file fallback.
|
||||
- The web service worker invalidates on app update and never serves
|
||||
stale code on the first load after deploy.
|
||||
- Push-event signature verification is mandatory; any failure tears
|
||||
down the stream and reconnects with backoff.
|
||||
- Locale switch persists across reloads and applies to every visible
|
||||
string on every platform.
|
||||
|
||||
---
|
||||
|
||||
## Deferred follow-ups (non-blocking)
|
||||
|
||||
Explicit deferral decisions, to fold into the phase noted when it lands.
|
||||
(The "build core.wasm in CI / drop the committed artefact" follow-up
|
||||
moved to [PLAN-finalize.md](PLAN-finalize.md) F6, since it is timely.)
|
||||
|
||||
- **Restore `js.CopyBytesToGo`** when TinyGo fixes the
|
||||
`instanceof Uint8Array` check — the per-element loop in
|
||||
`ui/wasm/main.go::copyBytesFromJS` is a TinyGo 0.41 workaround. Track
|
||||
upstream and revert once a fixed release is pinned.
|
||||
- **Migrate TS codegen to the Connect-ES v2 BSR plugin** once published —
|
||||
`ui/buf.gen.yaml` runs `protoc-gen-es` v2 locally because
|
||||
`buf.build/connectrpc/es` still emits v1-incompatible imports.
|
||||
- **Rename `gateway/internal/grpcapi/` → `connectapi/`** — historical
|
||||
name; the package serves Connect/gRPC/gRPC-Web. Pure rename. (Fold
|
||||
into the next gateway change; not a UI task.)
|
||||
- **Rename `GATEWAY_AUTHENTICATED_GRPC_*` env vars** to drop the `GRPC`
|
||||
infix — they label the authenticated edge tier, not the wire protocol.
|
||||
(Coordinate with the rename above; not a UI task.)
|
||||
- **Add a Docker-stack Connect end-to-end integration test** —
|
||||
`integration/connect_call_test.go` exercising a unary + a
|
||||
server-streaming Connect call through `testenv.Bootstrap`.
|
||||
- **Battle viewer — push event `game.battle.new`** — emit a backend
|
||||
notification intent (idempotency
|
||||
`battle-new:<game_id>:<turn>:<battle_id>`) so the shell shows a toast
|
||||
deep-linking into the Battle Viewer. Needs an engine emit-side change.
|
||||
- **Battle viewer — richer ship-class visuals** — derive shape/scale
|
||||
from mass, armament, shields, and ship count instead of the MVP
|
||||
one-circle-plus-label per `(race, className)`.
|
||||
Reference in New Issue
Block a user