Move territory from whole-country (ISO_A3) to individual sub-region id
granularity (PR 3 of #16):
- new server/regions.ts (turf-free): loadRegions (boot), expandTerritory
(game creation), migrateTerritoryToRegions (legacy games on db.load),
regionNamesFor / regionLabel (LLM prompt), graceful ISO_A3 fallback
- game creation expands each preset nation's ISO_A3 list to its sub-region
ids; pre-v0.19 saved games migrate transparently on read (idempotent)
- LLM contract: territoryChanges gain/lose sub-region ids (one region at a
time; gain moves out of the prior owner; lost-without-gainer = unowned);
user prompt carries a top-level regions reference table
({id: 'name (parent)'} over the state's territory ids)
- WorldMap: choropleth fill per sub-region (countries can split between
nations), ownership via properties.regionId through the shared
mapFeatureOwner, flash lights exactly the changed features
(featuresByRegionIds)
- deterministic stub: one region-level move per non-empty round (player
annexes the lexicographically-first region of the first other nation)
- tests: new server/regions.test.ts (real geo + fallback + seams);
map/engine tests re-pinned to region ids; scripts/regions.test.ts stays green
Measured full wwii-1939 user prompt (411 regions): ~24.7k chars / ~6.2k
tokens — far under the 80k frontier limit, so the full regions table is
always sent (no frontier-limited mode needed).
Part of #16
- DELETE /api/games/:id route + Db.delete() (404 when absent)
- PresetPicker: per-saved-game trash button + confirm dialog (Cancel/Delete)
- App: runDeleteGame; useSse onError -> goHome on 'deleted'/'not found'
(a deleted/missing game now returns the live tab and any deep link home)
- DeleteGameResponse in shared/protocol.ts; api.deleteGame()
- unit test (Db.delete) + 2 e2e tests (home-screen delete; in-flight delete
returns the active tab home and a fresh deep link lands on home)
- version 0.7.0 -> 0.8.0 + changelog
Fixes#20
- Add .gitea/workflows/ci.yml: typecheck -> lint -> unit -> build -> deterministic
Playwright e2e against the dev webServer (LLM_STUB=1). No dind/docker/static IP.
- package-lock.json is committed (reproducible `npm ci`); verified npm install is a no-op.
- Add CHANGELOG.md, set version 0.1.0, add .env (gitignored) + .env.example placeholder.
- Document the mandatory feature-branch -> PR -> CI -> auto-merge workflow in
AGENTS.md + README.md (e2e now runs in CI on every PR).
- Add Playwright html/json reporters (playwright-report/, test-results/e2e.json)
for the CI E2E-results summary step and the failure artifact upload.