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:
Ilia Denisov
2026-05-10 11:08:13 +02:00
parent 8f320010c6
commit f5ac9fac59
2 changed files with 69 additions and 0 deletions
+19
View File
@@ -99,6 +99,25 @@ The intended v1 architecture is:
format-compatible with GitHub Actions). Linux runners cover Tier 1
tests; a macOS runner is provisioned only when Tier 2 iOS smoke is
needed.
- **Synthetic-report parser parity is a global rule.** A DEV-only
loader on the lobby (`import.meta.env.DEV`) lets the developer feed
the UI a JSON file that mimics a server `Report`, so the map and
inspectors can be exercised against rich game states without playing
many turns end-to-end. The JSON is produced by the Go CLI in
`tools/local-dev/legacy-report/`, which converts legacy text
reports under `tools/local-dev/reports/` into the shape of
`pkg/model/report.Report` (whatever subset the UI currently
decodes). Every phase that **extends the server→UI report contract**
— adding decoding for a new `Report` field in
`ui/frontend/src/api/game-state.ts` — must, in the same PR, extend
the legacy parser to populate that field, **or** explicitly note in
the parser's `README.md` that the field cannot be derived from the
legacy text format and is left empty in synthetic JSON. The point
is to keep `tools/local-dev/legacy-report/` a faithful (and
type-checked, via `pkg/model/report` import) generator of test
inputs as the UI grows; otherwise synthetic data silently lags
behind the contract and visual tests stop covering the new
behaviour.
## Information Architecture and Navigation