ui/synthetic-report: PLAN parity rule + testing doc
Locks in the synthetic-report parity rule as a global "Assumptions and Defaults" entry in ui/PLAN.md: every phase that extends the server->UI report contract must also extend the legacy parser in the same PR (or document in tools/local-dev/legacy-report/README.md why the new field cannot be derived from legacy text). The Go side already enforces shape compatibility via the pkg/model/report import; this rule extends that mechanical guard to "did we remember to wire the new field through". ui/docs/testing.md grows a "Synthetic reports for visual testing" section with the full conversion -> load -> compose loop and the two operational gotchas (no network on synthetic ids, page reload clears the in-memory map). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -109,6 +109,56 @@ mode off, troubleshooting common boot issues).
|
||||
The local-dev stack is independent from the local-ci stack below;
|
||||
they bind different ports and can run side by side.
|
||||
|
||||
## Synthetic reports for visual testing (DEV)
|
||||
|
||||
For visual checks of the map, inspectors and order-overlay against
|
||||
rich game states, the lobby exposes a DEV-only "Load synthetic
|
||||
report" affordance (`import.meta.env.DEV`). The flow is:
|
||||
|
||||
1. Convert a legacy text report (`tools/local-dev/reports/{dg,gplus}/`)
|
||||
to JSON with the Go CLI:
|
||||
|
||||
```sh
|
||||
go run ./tools/local-dev/legacy-report/cmd/legacy-report-to-json \
|
||||
--in tools/local-dev/reports/dg/KNNTS039.REP \
|
||||
--out /tmp/dg39.json
|
||||
```
|
||||
|
||||
See [`../../tools/local-dev/legacy-report/README.md`](../../tools/local-dev/legacy-report/README.md)
|
||||
for what the parser populates today and how to extend it when a
|
||||
new UI phase decodes a new `Report` field.
|
||||
|
||||
2. Run the UI dev server (`pnpm -C ui/frontend dev`), open the lobby,
|
||||
and use the "Load JSON…" file picker in the **Synthetic test
|
||||
reports (DEV)** section. The page navigates to
|
||||
`/games/synthetic-<uuid>/map` with the report wired into the
|
||||
in-game shell.
|
||||
|
||||
In synthetic mode:
|
||||
|
||||
- The map view, inspectors and races view render against the loaded
|
||||
report exactly as they would for a real game.
|
||||
- Composing orders works locally (overlay applies through
|
||||
`applyOrderOverlay` as usual), but **nothing is sent to the
|
||||
gateway** — `OrderDraftStore.scheduleSync` short-circuits because
|
||||
the synthetic id is not a UUID and the layout deliberately does
|
||||
not bind a `GalaxyClient` for this game.
|
||||
- The order draft is persisted into the platform `Cache` under the
|
||||
same `order-drafts` namespace as real games, keyed by the
|
||||
synthetic id, so navigating back into the same synthetic session
|
||||
restores the draft. The cache is cleared with
|
||||
`__galaxyDebug.clearOrderDraft(gameId)` (DEV debug surface).
|
||||
- A page reload loses the in-memory report registry; opening the
|
||||
same synthetic id afterwards redirects to /lobby. Re-load the JSON
|
||||
to reseed.
|
||||
|
||||
The synthetic-report parity rule (see [`../PLAN.md`](../PLAN.md) §
|
||||
Assumptions and Defaults) requires every UI phase that extends
|
||||
`decodeReport` to also extend the legacy parser in lockstep, or to
|
||||
record in the parser's `README.md` that the new field cannot be
|
||||
derived from legacy text. This keeps the synthetic-mode coverage in
|
||||
step with the contract as the UI grows.
|
||||
|
||||
## Local CI verification
|
||||
|
||||
`tools/local-ci/` ships a self-contained Gitea + Actions runner via
|
||||
|
||||
Reference in New Issue
Block a user