Replace game dev handover with corrected and complete version

This commit is contained in:
otivm
2026-04-27 09:28:33 +00:00
parent e92e1bf980
commit 49b8843821

View File

@@ -1,5 +1,5 @@
# Handover — OTIVM Game Development # Handover — OTIVM Game Development
### Date: 2026-04-26 ### Date: 2026-04-27
### For: Incoming assistant (game development track) ### For: Incoming assistant (game development track)
### Read this completely before doing anything ### Read this completely before doing anything
@@ -13,7 +13,7 @@ produce one file at a time as a downloadable attachment, and Claude Code
on the container commits and pushes. on the container commits and pushes.
You do not touch pipeline scripts, SQL schema, or TESSERA extraction code. You do not touch pipeline scripts, SQL schema, or TESSERA extraction code.
That work belongs to the dataset assistant (see `docs/handover-seed-extraction.md`). That work belongs to the dataset assistant (see `docs/handover-dataset.md`).
You share the OTIVM Gitea repo but work on different files. You share the OTIVM Gitea repo but work on different files.
The game is live. The server is running. Every change you make is visible The game is live. The server is running. Every change you make is visible
@@ -26,13 +26,14 @@ to real users within seconds of `pm2 restart otivm`.
In order: In order:
1. `CLAUDE.md` — workflow, three-shell model, ground rules, deployment facts 1. `CLAUDE.md` — workflow, three-shell model, ground rules, deployment facts
2. `docs/roadmap.md`where the game is going through OTIVM-X 2. `docs/roadmap.md`**read with the warnings in Section 5 of this
3. `docs/RFC-TESSERA-4.0-001.md` — the data schema that OTIVM-III onward depends on document in mind. The roadmap needs rewriting. Do not treat it as
4. This file current.**
3. `docs/RFC-TESSERA-4.0-001.md` — the database schema all future
The roadmap is the product plan. The RFC is the data contract. CLAUDE.md is releases depend on
the operational contract. Do not deviate from any of them without explicit 4. `docs/TESSERA-dataset-registry.md` — what data exists, what is
project owner instruction. pending, and critically: the restoration layer concept
5. This file
--- ---
@@ -41,13 +42,20 @@ project owner instruction.
### OTIVM container (otium-dev, 10.0.0.23) ### OTIVM container (otium-dev, 10.0.0.23)
- App user: `otivm` - App user: `otivm`
- Repo at `/home/otivm/OTIVM` - Repo at `/home/otivm/OTIVM`
- Claude Code runs here as `otivm` user via `work` alias (`cd ~/OTIVM && claude`) - Claude Code runs here as `otivm` user via `work` alias
- Python venv: `/home/otivm/venv` (`cd ~/OTIVM && claude`)
- Python venv (game): `/home/otivm/venv`
- Python venv (pipeline — do not use): `/home/otivm/pipeline-venv`
- PM2 home: `/home/otivm/.pm2` - PM2 home: `/home/otivm/.pm2`
- Node: `/usr/bin/node` (v22) - Node: `/usr/bin/node` (v22)
- App port: 3000 - App port: 3000
- WireGuard: 10.110.0.18 - WireGuard: 10.110.0.18
### Three Proxmox boxes
- **proliant-dev (srv-a, 10.0.0.11)** — development work happens here
- **staging box** — validation before production
- **production box** — live game served from here
### Nginx proxy ### Nginx proxy
- Lives on wg-pk (198.58.111.109) — not on this container - Lives on wg-pk (198.58.111.109) — not on this container
- Proxies `otium.civicus.us``10.110.0.18:3000` - Proxies `otium.civicus.us``10.110.0.18:3000`
@@ -56,27 +64,33 @@ project owner instruction.
### Gitea ### Gitea
- Repo: `https://gitea.barternetwork.us/TheRON/OTIVM` - Repo: `https://gitea.barternetwork.us/TheRON/OTIVM`
- Branch: `main` (direct push, Claude Code handles this) - Branch: `main` (direct push, Claude Code handles this)
- MCP: connected via `mcp.civicus.us` — Claude chat reads any file directly - MCP: connected via `mcp.civicus.us` — Claude chat reads any file
directly
### Backups ### Backups
- `vzdump 1105 --compress zstd --storage local --mode snapshot` on srv-a (root shell) - `vzdump 1105 --compress zstd --storage local --mode snapshot`
on srv-a (root shell)
- Document every backup in `docs/archives.md` immediately after - Document every backup in `docs/archives.md` immediately after
- Never take a backup without documenting it. Never document one not taken. - Never take a backup without documenting it. Never document one
not taken.
--- ---
## 3. Stack ## 3. Stack
- React 19 + Vite 8 frontend (`src/`) - React 19 + Vite 8 frontend (`src/`)
- Fastify backend (`server/index.js`) — serves `dist/` and save API on port 3000 - Fastify backend (`server/index.js`) — serves `dist/` and save API
- No database for player state — JSON flat files in `data/saves/` on port 3000
- `data/otivm.sqlite3` — TESSERA physical-world data, read-only by the game server - Player state: JSON flat files in `data/saves/` — no database
- TESSERA data: `data/otivm.sqlite3` — read-only by game server,
owned and populated by dataset assistant
- PM2 under `otivm` user (never root) - PM2 under `otivm` user (never root)
- Ecosystem file: `ecosystem.config.cjs` (must be `.cjs` — Vite sets `"type": "module"`) - Ecosystem file: `ecosystem.config.cjs` (must be `.cjs` — Vite sets
`"type": "module"`)
--- ---
## 4. Current game state — as of 2026-04-26 ## 4. Current game state — as of 2026-04-27
### OTIVM-I — complete ### OTIVM-I — complete
- Fastify backend serving `dist/` and save API on port 3000 - Fastify backend serving `dist/` and save API on port 3000
@@ -84,7 +98,8 @@ project owner instruction.
- Journal entries firing on dispatch milestones - Journal entries firing on dispatch milestones
- Otium/negotium mechanic working - Otium/negotium mechanic working
- Per-player save files in `data/saves/` via 8-char hex token - Per-player save files in `data/saves/` via 8-char hex token
- Token displayed in UI — player can record it to resume on another device - Token displayed in UI — player can record it to resume on another
device
- 128 concurrent players supported - 128 concurrent players supported
### Navigation scaffold — complete ### Navigation scaffold — complete
@@ -95,98 +110,168 @@ project owner instruction.
### OTIVM-II — complete and live ### OTIVM-II — complete and live
- `src/screens/Map.jsx` — Mediterranean SVG map - `src/screens/Map.jsx` — Mediterranean SVG map
- Two-polygon land outline (Europe + Asia Minor, North Africa) — accurate mainland coastline - Two-polygon land outline (Europe + Asia Minor, North Africa) —
- Bounding box: 5°E38°E / 28°N48°N, equirectangular projection, 800×460 canvas placeholder coastline, accurate mainland only
- Bounding box: 5°E38°E / 28°N48°N, equirectangular projection,
800×460 canvas
- Five waypoints plotted at hardcoded H3 res-5 cell centres - Five waypoints plotted at hardcoded H3 res-5 cell centres
- Route lines between waypoints — gold when unlocked, muted dashed when locked - Route lines between waypoints — gold when unlocked, muted dashed
- Current chapter waypoint highlighted in gold, reached waypoints in green when locked
- `src/constants.js` — provenance fields added to all four routes: - Current chapter waypoint highlighted in gold, reached waypoints
in green
- `src/constants.js` — provenance fields added to all routes:
`origin_h3_r5`, `origin_region`, `cultural_note` `origin_h3_r5`, `origin_region`, `cultural_note`
These are stub H3 IDs today — become live TESSERA API queries in OTIVM-III These are stub values today — become live TESSERA queries in
OTIVM-III
- `src/gameState.js` — structural additions: - `src/gameState.js` — structural additions:
- `active_dispatch: null` in `INITIAL_STATE` — records in-progress dispatch - `active_dispatch: null` — records in-progress dispatch
for position tracking and real-time duration (OTIVM-IV) - `events: []` — append-only event log
- `events: []` in `INITIAL_STATE` — append-only event log
Each entry: `{ type, route_id, timestamp_utc }` Each entry: `{ type, route_id, timestamp_utc }`
Types: `dispatch_start`, `dispatch_complete`, `otium`, `chapter_advance`, `journal_unlock` Types: `dispatch_start`, `dispatch_complete`, `otium`,
`chapter_advance`, `journal_unlock`
This is the sequencing substrate for OTIVM-IX attestation This is the sequencing substrate for OTIVM-IX attestation
- `galleyProgress(active_dispatch, now_ms)` — pure function, returns 01 - `galleyProgress(active_dispatch, now_ms)` — pure function,
progress float for a dispatched galley. Returns null if no dispatch active. returns 01 progress float. Returns null if no dispatch active.
OTIVM-IV plugs real durations in. OTIVM-VII plugs H3 waypoints in. - All apply* functions now append to `events` and set/clear
- All apply* functions now append to `events` and set/clear `active_dispatch` `active_dispatch`
### Architecture decisions locked ### Architecture decisions locked
- H3 IDs on all waypoints — permanent, TESSERA-compatible - H3 IDs on all waypoints — permanent, TESSERA-compatible
- `constants.js` / `gameState.js` / `api.js` separation — permanent - `constants.js` / `gameState.js` / `api.js` separation — permanent
- Virtual screens via `display:none` — state preserved in browser - Virtual screens via `display:none` — state preserved in browser
- Save on meaningful events only — not on every tick - Save on meaningful events only — not on every tick
- H3 cell centre coordinates hardcoded in `Map.jsx` — h3-js is server-side only - H3 cell centre coordinates hardcoded in `Map.jsx` — h3-js is
- Mediterranean map to be replaced in OTIVM-III (moved up from OTIVM-VII) server-side only
- Two-polygon land outline (not one) — avoids cross-sea lines - Two-polygon land outline — to be replaced in OTIVM-III
- Two polygons not one — avoids cross-sea rendering lines
### Known issue — recorded ### Known issue — recorded
- Claude Code collapsed `INITIAL_STATE` onto one line during a prior session, - Claude Code collapsed `INITIAL_STATE` onto one line during a prior
causing a Vite build failure. Fixed in commit 34176dc. session, causing a Vite build failure. Fixed in commit 34176dc.
- Going forward: Claude Code writes content exactly as received, regardless - Going forward: Claude Code writes content exactly as received,
of how it arrives. This note exists in the project owner's memory. regardless of how it arrives.
--- ---
## 5. OTIVM-III — defined, not yet started ## 5. The roadmap — needs rewriting ⚠
OTIVM-III moves two items forward from their original roadmap positions: **Read `docs/roadmap.md` but do not treat it as authoritative.**
The roadmap was written before the TESSERA 4.0 architecture was
decided. The following assumptions in the current roadmap are now
wrong:
1. **SQLite integration**`data/otivm.sqlite3` arrives on the container **1. It assumes a completed global TESSERA database.**
from the dataset assistant. The Fastify server gets a read-only SQLite The global database (tessera.db) no longer exists on a reachable
connection (better-sqlite3). A `/api/cell/:h9` endpoint exposes TESSERA server. `data/otivm.sqlite3` is a purpose-built per-waypoint database
data for individual H9 cells. The game UI does not yet surface this data (TESSERA 4.0 model). New hexes are added one H5 at a time by the
directly — the plumbing is established and verified working. dataset assistant as the game expands. The roadmap must reflect this.
2. **Accurate map** — the placeholder two-polygon coastline is replaced **2. It does not mention the restoration layer.**
with a Natural Earth or equivalent accurate coastline, including major `terrain` in `otivm.sqlite3` is modern WorldCover 2021 data. It is
islands (Sicily, Sardinia, Crete, Cyprus). The map remains SVG, wrong for any historical period. The Mediterranean was 6070% forested
equirectangular, same bounding box and canvas size. in Roman times and Mesolithic times. Today the same cells are
classified as built-up, cropland, or drained wetland.
These two items belong together in OTIVM-III because the database arrival The restoration layer (HYDE 3.3 + KK10 datasets, not yet on drives)
on the container is the trigger for both — once `otivm.sqlite3` is present, will correct `terrain` to historically appropriate values. Until that
the map replacement and server plumbing happen in the same release. layer is active, the game must not present terrain data as
historically accurate.
OTIVM-III scope must be confirmed with the project owner before code is written. This affects the roadmap significantly — terrain-dependent features
(city physical character, environmental hazard, resource availability)
cannot be implemented correctly until the restoration layer is in
place.
**3. Release numbering is out of date.**
OTIVM-III in the current roadmap describes "The Factor" (NPC model).
The actual next release should establish the SQLite server connection
and replace the map coastline — both triggered by the database arriving
on the container. Discuss scope with the project owner before any code.
**The roadmap rewrite is the first task for the game development
assistant.** Do not write code until the roadmap is current. The
project owner will direct the rewrite.
--- ---
## 6. What the dataset assistant is doing in parallel ## 6. The database — what the game can and cannot do
The dataset assistant is working on TESSERA 4.0 seed extraction: `data/otivm.sqlite3` is present on the container. It is read-only
- `data/create_otivm_db.sql` — schema for `otium.sqlite3` ✅ committed from the game's perspective. The dataset assistant owns it.
- `pipeline/seed_extract.py` — extracts five waypoint H3 cells from tessera.db ✅ committed
- `pipeline/seed_promote.py` — promotes draft rows to current ✅ committed
- `docs/RFC-TESSERA-4.0-001.md` — normative schema ✅ committed
- `docs/handover-seed-extraction.md` — dataset track orientation ✅ committed
The output will be `data/otivm.sqlite3` — a SQLite database with TESSERA ### What is in the database
physical-world data for the five OTIVM waypoint H5 hexes. - 12,005 H9 rows across five waypoints, all `status=2` (current)
- `paleo_epochs` table — 9 epochs from Eemian to present with sea
level offsets
**Verified row counts (from `data/create_otivm_db.sql` and confirmed by dataset assistant):** ### Five waypoints
- H3 resolution hierarchy res-5 → res-9: 7⁴ = 2,401 H9 cells per H5 hex | City | H5 TEXT | H9 cells |
- Five waypoints × 2,401 = **12,005 total H9 rows** |---|---|---|
- All five H5 hexes are within the completed portion of tessera.db | Ostia | `851e805bfffffff` | 2401 |
(Mediterranean is fully populated through stage 04) | Capua | `851e8333fffffff` | 2401 |
- `occ_flag` is 0 for all seed rows — stage 06 (occupation evidence) not yet run | Brundisium | `851e8ba3fffffff` | 2401 |
| Carthago | `85386e23fffffff` | 2401 |
| Alexandria | `853f5ba7fffffff` | 2401 |
You do not run extraction scripts. You do not touch pipeline files. ### The canonical game query
When `otivm.sqlite3` arrives on the container, you will be told. Only use cells from complete, current H5 hexes:
```sql
SELECT tc.*
FROM tessera_cells tc
JOIN h5_coverage h5c ON tc.h5 = h5c.h5
WHERE h5c.status = 2
AND tc.status = 2
AND tc.h5 = ?
```
### Field status — what the game can trust
| Field | Trust level | Reason |
|---|---|---|
| `elev_cm` | ✅ Use — with epoch offset | GEBCO 2025, modern MSL. Apply `sl_offset_cm` from `paleo_epochs` for historical periods. |
| `terrain` | ⚠ Modern only | WorldCover 2021. Wrong for Roman/Mesolithic. Do not present as historical until restoration layer is active. |
| `hydro` | ✅ Use with caution | HydroSHEDS v1.1. Rivers have migrated — major drainage correct, fine detail approximate. |
| `geo_dep` | ✅ Use | USGS MRDS. Sparse in places but correct where present. |
| `geo_flag` | ✅ Use | BGR IGME5000. European coverage only. |
| `occ_flag` | ❌ Do not use | Placeholder 0x00 everywhere. Stage 06 not written. |
### H3 conversion in JavaScript
H3 IDs are stored as INTEGER (64-bit) in the database.
In JavaScript: `h3.indexToCell(BigInt(row.h9))` to convert to string.
Server-side only — h3-js is not available in the browser bundle.
--- ---
## 7. Workflow — one file, one step, one confirmation ## 7. Dataset assistant — what they are doing in parallel
The dataset assistant owns the pipeline. Current status:
- `data/otivm.sqlite3` — production database, 12,005 rows ✅
- `data/staging_otivm.sqlite3` — their working copy, not in git
- `pipeline/seed_extract.py` — old extractor, do not re-run ✅
- `pipeline/seed_promote.py` — old promotion script, do not re-run ✅
- `docs/TESSERA-dataset-registry.md` — full dataset inventory ✅
- `docs/handover-dataset.md` — their track orientation ✅
**Next dataset work:**
1. Four datasets to be added to USB Drive 1 (project owner action)
2. Per-H5 pipeline to be designed and built
3. Restoration layer — HYDE 3.3 + KK10 integration
You will be told when the database is updated. You do not run
pipeline scripts. You do not touch `pipeline/` or `data/create_otivm_db.sql`.
---
## 8. Workflow — one file, one step, one confirmation
Every change follows this sequence without exception: Every change follows this sequence without exception:
1. Claude chat discusses the change and produces one downloadable file 1. Claude chat discusses the change and produces one downloadable file
2. The file header contains the Claude Code instruction (path, commit message) 2. The file header contains the Claude Code instruction (path, commit
message)
3. The file body contains the exact content to write to disk 3. The file body contains the exact content to write to disk
4. Human downloads from Claude chat and pastes into Claude Code (Shell 1) 4. Human downloads from Claude chat and pastes into Claude Code
(Shell 1)
5. Claude Code writes to the specified path, commits, pushes 5. Claude Code writes to the specified path, commits, pushes
6. Human runs `npm run build` in Shell 2 (otivm shell) 6. Human runs `npm run build` in Shell 2 (otivm shell)
7. Human runs `pm2 restart otivm` in Shell 2 7. Human runs `pm2 restart otivm` in Shell 2
@@ -198,25 +283,34 @@ Every change follows this sequence without exception:
--- ---
## 8. Hard rules ## 9. Hard rules
- Never run PM2 as root — always as otivm user - Never run PM2 as root — always as otivm user
- Never commit secrets — no tokens, no keys, no passwords in any file - Never commit secrets — no tokens, no keys, no passwords in any file
- Never push to main without building — `npm run build` must pass first - Never push to main without building — `npm run build` must pass first
- No database for player state — JSON flat files only (`data/saves/`) - No database for player state — JSON flat files only
- H3 IDs on every location — never a coordinate pair or string name alone - H3 IDs on every location — never a coordinate pair or string name
alone
- One change confirmed before the next — no batching steps - One change confirmed before the next — no batching steps
- Never print file contents or code blocks in chat — always downloadable attachments - Never print file contents or code blocks in chat — always
- Never make assumptions about what is on disk — always read from Gitea MCP first downloadable attachments
- Never make assumptions about what is on disk — always read from
Gitea MCP first
- Do not query `otivm.sqlite3` with raw coordinates — always H3 IDs
- Do not present `terrain` as historically accurate until the
restoration layer is confirmed active by the dataset assistant
--- ---
## 9. Commit messages ## 10. Commit messages
Imperative mood, present tense, under 72 characters. Imperative mood, present tense, under 72 characters.
Example: `Add Mediterranean SVG map to Map screen` not `Added map`. Example: `Add Mediterranean SVG map to Map screen` not `Added map`.
--- ---
*Handover 2026-04-26 — game development track* *Handover 2026-04-27 — game development track*
*Database present, paleo_epochs added, 12,005 current rows.*
*Roadmap needs rewriting — first task before any code.*
*terrain field is modern WorldCover — not historically accurate yet.*
*Claude chat designs. Claude Code implements. The human decides.* *Claude chat designs. Claude Code implements. The human decides.*