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:
+59
-73
@@ -8,17 +8,16 @@ in Go under `pkg/calc/` and are surfaced to the UI through a
|
||||
Go → WASM → TypeScript bridge mounted under `ui/core/calc/` and a
|
||||
matching TS adapter in `ui/frontend/src/platform/core/`.
|
||||
|
||||
Phase 18 lands the **ship-math slice** of the bridge — everything
|
||||
the ship-class designer needs to render its preview pane. Phase 20
|
||||
extends it with `BlockUpgradeCost` so the ship-group inspector can
|
||||
preview modernize cost. Phase 30 extends it with the **combat,
|
||||
The bridge covers the **ship-math slice** (everything the ship-class
|
||||
designer needs to render its preview pane), `BlockUpgradeCost` (for
|
||||
the ship-group inspector's modernize-cost preview), and the **combat,
|
||||
planet-build, and goal-seek slice** for the ship-class calculator:
|
||||
`EffectiveAttack`, `EffectiveDefence`, `BombingPower`, `ShipBuildCost`,
|
||||
`ProduceShipsInTurn`, and the inverse solvers from `pkg/calc/solve.go`.
|
||||
Other slices (production/science forecast, the realistic multi-turn
|
||||
planet projection) remain deferred to dedicated future phases. This
|
||||
document is the running audit trail of what is live, what is missing,
|
||||
and how each function maps to its `pkg/calc/` source.
|
||||
planet projection) remain deferred. This document is the running audit
|
||||
trail of what is live, what is missing, and how each function maps to
|
||||
its `pkg/calc/` source.
|
||||
|
||||
## Live bridge surface
|
||||
|
||||
@@ -52,10 +51,10 @@ on the JS-side `globalThis.galaxyCore` (registered in
|
||||
| `ceil3` | `calc.Ceil3(value)` (`pkg/calc/number.go`) | `number` | calculator display rounding (round up to 3 dp) |
|
||||
|
||||
`BombingPower` and the per-turn build loop are no longer engine-only:
|
||||
Phase 30 extracted `BombingPower` from
|
||||
`game/internal/model/game/group.go` and the per-iteration build math
|
||||
from `controller.ProduceShip` into `pkg/calc` (`ProduceShipsInTurn`),
|
||||
and the engine now delegates to both — a true refactor, not a mirror.
|
||||
`BombingPower` was extracted from `game/internal/model/game/group.go`
|
||||
and the per-iteration build math from `controller.ProduceShip` into
|
||||
`pkg/calc` (`ProduceShipsInTurn`); the engine now delegates to both —
|
||||
a true refactor, not a mirror.
|
||||
The inverse solvers (`pkg/calc/solve.go`) invert the forward formulas
|
||||
for single-target goal-seek and return `null` when infeasible;
|
||||
`shieldsForDefence` uses bisection, the rest are analytic. Parity and
|
||||
@@ -77,12 +76,12 @@ same inputs and asserts byte-equal outputs.
|
||||
|
||||
## Still-deferred slices
|
||||
|
||||
Phase 18's Go-side bridge is intentionally narrow: it covers ship
|
||||
math and nothing else. Production forecasts, science, ship-build
|
||||
progress, and reach (`FligthDistance`) still depend on either
|
||||
inline TS arithmetic or the engine-shipped fields on `GameReport`.
|
||||
See the table further down for what is missing and the per-feature
|
||||
waivers below for the rationale on each deferral.
|
||||
The Go-side bridge is intentionally narrow: it covers ship math and
|
||||
the combat/planet-build/goal-seek slice. Production forecasts, science,
|
||||
and reach (`FligthDistance`) still depend on either inline TS arithmetic
|
||||
or the engine-shipped fields on `GameReport`. See the table further down
|
||||
for what is missing and the per-feature waivers below for the rationale
|
||||
on each deferral.
|
||||
|
||||
## Current `pkg/calc/` exports
|
||||
|
||||
@@ -91,7 +90,7 @@ waivers below for the rationale on each deferral.
|
||||
| `ShipProductionCost(shipEmptyMass float64) float64` | Production units required per unit of ship empty mass (×10). |
|
||||
| `PlanetProduceShipMass(L, Mat, Res float64) float64` | Ship mass produced per turn given free production `L`, material stockpile `Mat`, resources `Res`.|
|
||||
| `DriveEffective`, `Speed`, `EmptyMass`, `FullMass`, … | Ship-level derivations (`pkg/calc/ship.go`). |
|
||||
| `BlockUpgradeCost(blockMass, currentTech, target)` | Production cost of upgrading a single ship block (Phase 20 migrated this from `controller`). |
|
||||
| `BlockUpgradeCost(blockMass, currentTech, target)` | Production cost of upgrading a single ship block (migrated from `controller`). |
|
||||
| `FligthDistance(driveTech)`, `VisibilityDistance(...)` | Race-level reach formulas (`pkg/calc/race.go`). |
|
||||
| `ValidateShipTypeValues`, `CheckShipTypeValueDWSC` | Ship-design validators (`pkg/calc/validator.go`). |
|
||||
|
||||
@@ -105,83 +104,70 @@ never been exported.
|
||||
The table below tracks what UI features need from the bridge and
|
||||
whether the underlying Go function exists.
|
||||
|
||||
| UI feature | Go formula | In `pkg/calc/`? | Surfaced to TS? |
|
||||
| ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | :-------------: | :-------------: |
|
||||
| Ship-class designer preview (Phase 18) | `EmptyMass`, `FullMass`, `Speed`, `DriveEffective`, `CargoCapacity`, `CarryingMass`, `WeaponsBlockMass` (`pkg/calc/ship.go`) | yes | yes |
|
||||
| Ship-group modernize cost preview (Phase 20) | `BlockUpgradeCost` (`pkg/calc/ship.go`, migrated from `game/internal/controller/ship_group_upgrade.go`) | yes | yes |
|
||||
| Ship calculator combat (Phase 30) | `EffectiveAttack`, `EffectiveDefence`, `BombingPower` (`pkg/calc/ship.go`; `BombingPower` extracted from `model/game/group.go`) | yes | yes |
|
||||
| Ship calculator goal-seek (Phase 30) | inverse solvers in `pkg/calc/solve.go` | yes | yes |
|
||||
| Free production potential (`freeIndustry`) | `Planet.ProductionCapacity` → `industry*0.75 + population*0.25` (`game/internal/model/game/planet.go`) | no | no |
|
||||
| Industry production output per turn | `Planet.ProduceIndustry(freeProduction)` (`planet.go`); `freeProduction/5` modulo material constraint | no | no |
|
||||
| Materials production output per turn | `Planet.ProduceMaterial(freeProduction)` (`planet.go`); `freeProduction * resources` | no | no |
|
||||
| Per-tech research progress (DRIVE/WEAPONS/…) | `ResearchTech` (`game/internal/model/game/science.go`); `freeProduction / 5000` per tech level | no | no |
|
||||
| Custom-science progress | weighted form of `ResearchTech` driven by `Race.Sciences[].(Drive\|Weapons\|Shields\|Cargo)` (`science.go`) | no | no |
|
||||
| Ship build progress / planet build rate (Phase 30)| `ProduceShipsInTurn(L, Mat, Res, mass)` (`pkg/calc/planet.go`, extracted from `controller.ProduceShip`); `ShipBuildCost` | yes | yes |
|
||||
| UI feature | Go formula | In `pkg/calc/`? | Surfaced to TS? |
|
||||
| ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | :-------------: | :-------------: |
|
||||
| Ship-class designer preview | `EmptyMass`, `FullMass`, `Speed`, `DriveEffective`, `CargoCapacity`, `CarryingMass`, `WeaponsBlockMass` (`pkg/calc/ship.go`) | yes | yes |
|
||||
| Ship-group modernize cost preview | `BlockUpgradeCost` (`pkg/calc/ship.go`, migrated from `game/internal/controller/ship_group_upgrade.go`) | yes | yes |
|
||||
| Ship calculator combat | `EffectiveAttack`, `EffectiveDefence`, `BombingPower` (`pkg/calc/ship.go`; `BombingPower` extracted from `model/game/group.go`) | yes | yes |
|
||||
| Ship calculator goal-seek | inverse solvers in `pkg/calc/solve.go` | yes | yes |
|
||||
| Free production potential (`freeIndustry`) | `Planet.ProductionCapacity` → `industry*0.75 + population*0.25` (`game/internal/model/game/planet.go`) | no | no |
|
||||
| Industry production output per turn | `Planet.ProduceIndustry(freeProduction)` (`planet.go`); `freeProduction/5` modulo material constraint | no | no |
|
||||
| Materials production output per turn | `Planet.ProduceMaterial(freeProduction)` (`planet.go`); `freeProduction * resources` | no | no |
|
||||
| Per-tech research progress (DRIVE/WEAPONS/…) | `ResearchTech` (`game/internal/model/game/science.go`); `freeProduction / 5000` per tech level | no | no |
|
||||
| Custom-science progress | weighted form of `ResearchTech` driven by `Race.Sciences[].(Drive\|Weapons\|Shields\|Cargo)` (`science.go`) | no | no |
|
||||
| Ship build progress / planet build rate | `ProduceShipsInTurn(L, Mat, Res, mass)` (`pkg/calc/planet.go`, extracted from `controller.ProduceShip`); `ShipBuildCost` | yes | yes |
|
||||
|
||||
`partial` means the Go primitives exist in `pkg/calc/` but the
|
||||
composition (and the conversion of TS-side `ReportPlanet`/
|
||||
`ShipClass` to the formula inputs) is not implemented anywhere.
|
||||
|
||||
## Phase 15 waiver
|
||||
## Production forecast waiver
|
||||
|
||||
Phase 15 ships the inspector's planet production controls
|
||||
(segmented control + sub-pickers + collapse-by-`planetNumber`
|
||||
order command) but **deliberately does not surface the per-type
|
||||
forecast number**. The planning gate explicitly raised the gap as
|
||||
a blocker per the plan's audit clause ("if any are missing in
|
||||
`pkg/calc/`, raise as blocker") and the project owner approved
|
||||
deferring the forecast to a dedicated future bridge phase. The
|
||||
inspector still renders the existing `freeIndustry` row (free
|
||||
production potential) — that number is computed engine-side and
|
||||
ships in the report payload, so no calc-bridge access is required
|
||||
for it today.
|
||||
The inspector's planet production controls (segmented control +
|
||||
sub-pickers + collapse-by-`planetNumber` order command) do **not**
|
||||
surface the per-type forecast number. The inspector renders the
|
||||
existing `freeIndustry` row (free production potential) — that number
|
||||
is computed engine-side and ships in the report payload, so no
|
||||
calc-bridge access is required for it. The per-type forecast number
|
||||
is deferred pending promotion of the relevant formulas into
|
||||
`pkg/calc/`.
|
||||
|
||||
Acceptance criterion 3 of Phase 15 ("forecast output number
|
||||
reflects the chosen production type and matches `pkg/calc/`
|
||||
outputs") is therefore intentionally not satisfied; the rewritten
|
||||
Phase 15 stage text records this decision and points back at this
|
||||
document.
|
||||
## Reach formula waiver
|
||||
|
||||
## Phase 16 waiver
|
||||
|
||||
Phase 16 introduces ship-reach filtering for the cargo-route
|
||||
destination picker. The engine formula is trivial:
|
||||
Ship-reach filtering for the cargo-route destination picker uses
|
||||
a trivial engine formula:
|
||||
|
||||
```
|
||||
flightDistance = driveTech * 40
|
||||
```
|
||||
|
||||
The Go-side reference now lives in
|
||||
The Go-side reference lives in
|
||||
[`pkg/calc/race.go`](../../pkg/calc/race.go) as
|
||||
`FligthDistance(driveTech) float64` (alongside the matching
|
||||
`VisibilityDistance` for in-space group reports — used in later
|
||||
phases). The engine call sites
|
||||
(`game/internal/model/game/race.go.FlightDistance`,
|
||||
`VisibilityDistance` for in-space group reports). The engine call
|
||||
sites (`game/internal/model/game/race.go.FlightDistance`,
|
||||
`game/internal/controller/route.go.PlanetRouteSet`) still wrap the
|
||||
Go formula directly; promoting them to call `pkg/calc/` is a
|
||||
follow-up cleanup outside Phase 16's scope.
|
||||
pending cleanup.
|
||||
|
||||
The original Phase 16 stage text described surfacing this through
|
||||
`pkg/calc/` and `ui/core/calc/`; with the calc-bridge phase still
|
||||
deferred, implementing the WASM glue for one constant-time
|
||||
multiplication would be premature scaffolding. The picker
|
||||
therefore computes reach inline in TypeScript using
|
||||
`torusShortestDelta(planet.x, candidate.x, mapWidth)` and
|
||||
`Math.hypot` against `40 * report.localPlayerDrive`, where
|
||||
`localPlayerDrive` is decoded from the report's `Player` block by
|
||||
matching `Player.name` to `report.race`
|
||||
Implementing the WASM glue for one constant-time multiplication
|
||||
would be premature scaffolding, so the picker computes reach inline
|
||||
in TypeScript using `torusShortestDelta(planet.x, candidate.x,
|
||||
mapWidth)` and `Math.hypot` against `40 * report.localPlayerDrive`,
|
||||
where `localPlayerDrive` is decoded from the report's `Player` block
|
||||
by matching `Player.name` to `report.race`
|
||||
(`api/game-state.ts.findLocalPlayerDrive`).
|
||||
|
||||
When the calc-bridge phase ships, the inline formula is replaced
|
||||
with a single call into the bridge — `calc.FligthDistance(driveTech)`
|
||||
becomes the source of truth for both the picker and the
|
||||
cargo-route auto-removal at turn cutoff. Until then, the UI
|
||||
duplicates `flightDistance` knowingly — same precedent as the
|
||||
production forecast deferral above.
|
||||
When the remaining bridge work ships, the inline formula will be
|
||||
replaced with a single call into the bridge —
|
||||
`calc.FligthDistance(driveTech)` becomes the source of truth for
|
||||
both the picker and the cargo-route auto-removal at turn cutoff.
|
||||
Until then, the UI duplicates `flightDistance` knowingly — same
|
||||
precedent as the production forecast deferral above.
|
||||
|
||||
## Planned bridge growth (follow-up phases)
|
||||
## Planned bridge growth
|
||||
|
||||
Phase 18 set up the canonical bridge layout (Go subpackage + WASM
|
||||
The canonical bridge layout is established (Go subpackage + WASM
|
||||
registration + typed `Core` interface + parity tests). Future calc
|
||||
work follows the same shape:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user