Follow-up hotfix to #16 P1 (v0.19.0): v0.19.0 shipped, but region-level ownership did not activate in the production image.
Root cause
The server-side loader server/regions.ts::loadRegions only looked for region-keys.json / regions.geo.json in public/. In the Docker image, Vite copies public/* → dist/ at build time and no public/ directory is kept, so loadRegions found nothing, expandCountriesToKeys degraded to a no-op, and freshly-created games kept raw ISO_A3 codes (DEU, GBR,IRL,IND, …) instead of expanding to region keys. The choropleth therefore still rendered whole-country ownership and the model's region-key contract was inactive in prod. (The client's own /region-keys.json fetch still worked — the client is served from dist/ — which is why the manifest endpoint looked healthy even though the server could not read the file.)
Caught by a post-deploy verification against https://history.dev.kkhost.pl (created a fresh game and checked /api/games/:id/map — territories were still ISO_A3).
Fix
loadRegions now probes public/ (dev) → dist/ (prod, == clientDir) → root and uses the first directory holding both files. One build now works in both environments. A new test covers the prod-only (dist/ without public/), dev (public/), and empty-root (no data) layouts.
Notes
#16 stays open (referenced, not closed) — P2 (LLM tools / function-calling) and the no-man's-land rename/split/merge phases still follow.
⚠ Deploy:docker compose down -v (drops history-data) then up -d --build; pre-v0.19 saves already dropped by v0.19.0 are dropped again.
Versioning: this repo bumps 0.N.0 for every change (no 0.N.Y patches), so the fix is v0.20.0 rather than a v0.19.x patch — it completes v0.19.0's prod behavior.
Verification
Typecheck, lint, and the unit suite (now 74 tests / 7 files) pass; production build clean. The deterministic LLM_STUB and format-agnostic e2e are unchanged (covered by CI).
Follow-up hotfix to #16 P1 (v0.19.0): v0.19.0 shipped, but **region-level ownership did not activate in the production image**.
## Root cause
The server-side loader `server/regions.ts::loadRegions` only looked for `region-keys.json` / `regions.geo.json` in `public/`. In the Docker image, Vite copies `public/*` → `dist/` at build time and **no `public/` directory is kept**, so `loadRegions` found nothing, `expandCountriesToKeys` degraded to a no-op, and freshly-created games kept raw **ISO_A3** codes (`DEU`, `GBR,IRL,IND`, …) instead of expanding to region keys. The choropleth therefore still rendered whole-country ownership and the model's region-key contract was inactive in prod. (The client's own `/region-keys.json` fetch still worked — the client is served from `dist/` — which is why the manifest endpoint looked healthy even though the server could not read the file.)
Caught by a post-deploy verification against `https://history.dev.kkhost.pl` (created a fresh game and checked `/api/games/:id/map` — territories were still ISO_A3).
## Fix
`loadRegions` now probes **`public/` (dev) → `dist/` (prod, == `clientDir`) → root** and uses the first directory holding both files. One build now works in both environments. A new test covers the prod-only (`dist/` without `public/`), dev (`public/`), and empty-root (no data) layouts.
## Notes
- **#16 stays open** (referenced, not closed) — P2 (LLM tools / function-calling) and the no-man's-land rename/split/merge phases still follow.
- **⚠ Deploy:** `docker compose down -v` (drops `history-data`) then `up -d --build`; pre-v0.19 saves already dropped by v0.19.0 are dropped again.
- Versioning: this repo bumps `0.N.0` for every change (no `0.N.Y` patches), so the fix is **v0.20.0** rather than a v0.19.x patch — it completes v0.19.0's prod behavior.
## Verification
Typecheck, lint, and the unit suite (now **74 tests / 7 files**) pass; production build clean. The deterministic `LLM_STUB` and format-agnostic e2e are unchanged (covered by CI).
v0.19.0's region-level ownership did not activate in the production image:
server/regions.ts loadRegions only looked in public/, but the Docker image keeps
only dist/ (Vite copies public/* -> dist/ at build), so the loader found nothing
and expandCountriesToKeys degraded to a no-op — fresh games kept raw ISO_A3 codes
instead of region keys (the client's own /region-keys.json fetch still worked,
since the client is served from dist/).
loadRegions now probes public/ (dev) then dist/ (prod, == clientDir) and uses the
first directory holding both files. A new test covers the prod-only (dist/), dev
(public/), and empty-root (no data) layouts.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Follow-up hotfix to #16 P1 (v0.19.0): v0.19.0 shipped, but region-level ownership did not activate in the production image.
Root cause
The server-side loader
server/regions.ts::loadRegionsonly looked forregion-keys.json/regions.geo.jsoninpublic/. In the Docker image, Vite copiespublic/*→dist/at build time and nopublic/directory is kept, soloadRegionsfound nothing,expandCountriesToKeysdegraded to a no-op, and freshly-created games kept raw ISO_A3 codes (DEU,GBR,IRL,IND, …) instead of expanding to region keys. The choropleth therefore still rendered whole-country ownership and the model's region-key contract was inactive in prod. (The client's own/region-keys.jsonfetch still worked — the client is served fromdist/— which is why the manifest endpoint looked healthy even though the server could not read the file.)Caught by a post-deploy verification against
https://history.dev.kkhost.pl(created a fresh game and checked/api/games/:id/map— territories were still ISO_A3).Fix
loadRegionsnow probespublic/(dev) →dist/(prod, ==clientDir) → root and uses the first directory holding both files. One build now works in both environments. A new test covers the prod-only (dist/withoutpublic/), dev (public/), and empty-root (no data) layouts.Notes
docker compose down -v(dropshistory-data) thenup -d --build; pre-v0.19 saves already dropped by v0.19.0 are dropped again.0.N.0for every change (no0.N.Ypatches), so the fix is v0.20.0 rather than a v0.19.x patch — it completes v0.19.0's prod behavior.Verification
Typecheck, lint, and the unit suite (now 74 tests / 7 files) pass; production build clean. The deterministic
LLM_STUBand format-agnostic e2e are unchanged (covered by CI).