Update handover-game-dev.md

OTIVM-II complete, OTIVM-III defined, full design corpus documented
This commit is contained in:
2026-04-28 11:56:16 -04:00
parent 890cc8e303
commit e199f88d4a

View File

@@ -1,5 +1,5 @@
# Handover — OTIVM Game Development # Handover — OTIVM Game Development
### Date: 2026-04-27 ### Date: 2026-04-28
### For: Incoming assistant (game development track) ### For: Incoming assistant (game development track)
### Read this completely before doing anything ### Read this completely before doing anything
@@ -26,239 +26,205 @@ 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` — **read with the warnings in Section 5 of this 2. `docs/architecture/infrastructure.md` — container topology, API protocol
document in mind. The roadmap needs rewriting. Do not treat it as 3. `docs/architecture/terminology.md` — three-layer vocabulary, naming convention
current.** 4. `docs/architecture/latin-bridge.md` — Latin terms, admission standard, semantic entries
3. `docs/RFC-TESSERA-4.0-001.md` — the database schema all future 5. `docs/architecture/parameter-registry.md` — all simulation parameters, scope, layer, maturity
releases depend on 6. `docs/actors/CHARACTER-FRAMEWORK.md` — six backgrounds, twelve starting parameters
4. `docs/TESSERA-dataset-registry.md` — what data exists, what is 7. `docs/scenarios/SCENARIO-MERCHANT-0000.md` — the BALNEA prologue, background selection
pending, and critically: the restoration layer concept 8. `docs/scenarios/SCENARIO-MERCHANT-0001.md` through `0003.md` — the founding trilogy
5. This file 9. `docs/cities/CITY-OSTIA-0001.md` — Ostia as pressure field, not backdrop
10. `docs/roadmap.md` — where the game is going (warning: body is stale, vision and principles still valid)
11. This file
The parameter registry is the bridge between the design documents and the
schema. Read it before touching any database code.
--- ---
## 2. Infrastructure ## 2. Infrastructure
### OTIVM container (otium-dev, 10.0.0.23) ### OTIVM container (otivm-dev, CT 1105)
- 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 - Claude Code runs here as `otivm` user via `work` alias (`cd ~/OTIVM && claude`)
(`cd ~/OTIVM && claude`) - Python venv: `/home/otivm/venv`
- Python venv (game): `/home/otivm/venv` - Pipeline venv: `/home/otivm/pipeline-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 ### Five containers on srv-a (10.0.0.11)
- **proliant-dev (srv-a, 10.0.0.11)** — development work happens here See `docs/architecture/infrastructure.md` for the full topology.
- **staging box** — validation before production The architecture is settled: REST over HTTPS on the WireGuard mesh,
- **production box** — live game served from here one write domain per container, no shared filesystems between containers.
| CT | Role |
|---|---|
| 1101 | tessera-pipeline |
| 1102 | tessera-store (master database) |
| 1103 | tessera-dev (aggregation) |
| 1104 | apt-cache |
| 1105 | otivm-dev (this container) |
### 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`
- Do not look for a vhost on the container
### 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 - MCP: connected via `mcp.civicus.us` — Claude chat reads any file directly
directly
### Backups ### Backups
- `vzdump 1105 --compress zstd --storage local --mode snapshot` - Command: `vzdump 1105 --compress zstd --storage local --mode snapshot` on srv-a (root shell)
on srv-a (root shell) - Document every backup in `docs/archives.md` immediately after — see existing entries for format
- Document every backup in `docs/archives.md` immediately after - Download each dump to workstation cold storage
- Never take a backup without documenting it. Never document one - Never take a backup without documenting it. Never document one not taken.
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 - Fastify backend (`server/index.js`) — serves `dist/`, save API, TESSERA map endpoint
on port 3000 - `data/otivm.sqlite3` — TESSERA physical data, read-only by game server
- Player state: JSON flat files in `data/saves/` — no database - `data/saves/` — per-player JSON save files (gitignored)
- TESSERA data: `data/otivm.sqlite3` — read-only by game server, - `better-sqlite3` installed — used by server for TESSERA queries
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 - Ecosystem file: `ecosystem.config.cjs`
`"type": "module"`)
--- ---
## 4. Current game state — as of 2026-04-27 ## 4. Current game state — as of 2026-04-28
### OTIVM-I — complete ### OTIVM-I — complete
- Fastify backend serving `dist/` and save API on port 3000 Five trade routes Ostia → Alexandria, journal, otium/negotium mechanic,
- Five trade routes, Ostia → Alexandria, all working per-player saves via 8-char hex token, 128 concurrent players supported.
- Journal entries firing on dispatch milestones
- Otium/negotium mechanic working
- 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
- 128 concurrent players supported
### Navigation scaffold — complete
- `src/screens/` directory established
- Game.jsx renamed to `src/screens/Ledger.jsx`
- `App.jsx` manages screen state — ledger and map
- Both screens stay mounted — no state lost on switch
### OTIVM-II — complete and live ### OTIVM-II — complete and live
- `src/screens/Map.jsx` — Mediterranean SVG map **The map is live and rendering from real TESSERA data.**
- Two-polygon land outline (Europe + Asia Minor, North Africa) —
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
- Route lines between waypoints — gold when unlocked, muted dashed
when locked
- 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`
These are stub values today — become live TESSERA queries in
OTIVM-III
- `src/gameState.js` — structural additions:
- `active_dispatch: null` — records in-progress dispatch
- `events: []` — append-only event log
Each entry: `{ type, route_id, timestamp_utc }`
Types: `dispatch_start`, `dispatch_complete`, `otium`,
`chapter_advance`, `journal_unlock`
This is the sequencing substrate for OTIVM-IX attestation
- `galleyProgress(active_dispatch, now_ms)` — pure function,
returns 01 progress float. Returns null if no dispatch active.
- All apply* functions now append to `events` and set/clear
`active_dispatch`
### Architecture decisions locked - `src/screens/Map.jsx` — fog-of-war SVG map
- H7 land cells rendered at real geographic positions (lat/lon from API)
- Progressive reveal by chapter — only visited waypoints are visible
- Sea = permanent darkness — no data needed, no storage needed
- `/api/map/:h5/:epoch` endpoint — H7 land/sea classification with centroids
- Epoch parameterised — default `roman_14bce` (sl_offset_cm = -10)
- `data/otivm.sqlite3` — 12,005 H9 rows, five H5 waypoints, `paleo_epochs` table live
- Session lifecycle — `session_abandoned` event written on new game, old saves preserved
- `active_dispatch`, `events[]` in save state — sequencing substrate for future releases
- `galleyProgress()` utility in gameState.js
- Provenance fields on all routes (`origin_h3_r5`, `origin_region`, `cultural_note`)
### Architecture decisions locked in OTIVM-II
- H3 IDs on all waypoints — permanent, TESSERA-compatible - H3 IDs on all waypoints — permanent, TESSERA-compatible
- `constants.js` / `gameState.js` / `api.js` separation — permanent - Sea hexes are dark by definition — no data, no storage
- Virtual screens via `display:none` — state preserved in browser - `session_abandoned` event — saves are never deleted, they receive a terminal event
- Save on meaningful events only — not on every tick - REST API for all inter-container data flows — no shared filesystems
- H3 cell centre coordinates hardcoded in `Map.jsx` — h3-js is - Per-player SQLite (128 files) replacing JSON saves — planned for OTIVM-III
server-side only
- Two-polygon land outline — to be replaced in OTIVM-III
- Two polygons not one — avoids cross-sea rendering lines
### Known issue — recorded ### Known deferred items
- Claude Code collapsed `INITIAL_STATE` onto one line during a prior - Journal local state does not reset on new game (React state issue, low priority)
session, causing a Vite build failure. Fixed in commit 34176dc. - H7 cells rendered as circles — hex geometry deferred pending client-side h3-js
- Going forward: Claude Code writes content exactly as received, - Map coastline is five isolated H5 clusters — route corridor coverage deferred to OTIVM-III+
regardless of how it arrives. - Roadmap body is stale — rewrite planned under project owner direction
--- ---
## 5. The roadmap — needs rewriting ⚠ ## 5. OTIVM-III — defined, not yet started
**Read `docs/roadmap.md` but do not treat it as authoritative.** OTIVM-III is the data plumbing release. Three things:
The roadmap was written before the TESSERA 4.0 architecture was
decided. The following assumptions in the current roadmap are now
wrong:
**1. It assumes a completed global TESSERA database.** **1. Per-player SQLite — 128 pre-provisioned databases**
The global database (tessera.db) no longer exists on a reachable
server. `data/otivm.sqlite3` is a purpose-built per-waypoint database
(TESSERA 4.0 model). New hexes are added one H5 at a time by the
dataset assistant as the game expands. The roadmap must reflect this.
**2. It does not mention the restoration layer.** Replace JSON save files in `data/saves/` with SQLite databases in
`terrain` in `otivm.sqlite3` is modern WorldCover 2021 data. It is `data/players/`. Pre-provision all 128 at container setup — no database
wrong for any historical period. The Mediterranean was 6070% forested created on demand under player load. The schema is defined by the parameter
in Roman times and Mesolithic times. Today the same cells are registry and the SQLite schema document (pending — this is the next
classified as built-up, cropland, or drained wetland. document to be produced).
The restoration layer (HYDE 3.3 + KK10 datasets, not yet on drives) The atomic unit is **time**. The database is a time-series of events.
will correct `terrain` to historically appropriate values. Until that Current parameter values are derived from event history. The schema must
layer is active, the game must not present terrain data as treat uncertainty, confidence, and perceived-vs-true values as first-class
historically accurate. records, not comments.
This affects the roadmap significantly — terrain-dependent features **2. RATIONES tab — the third screen**
(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.** Add a third tab alongside Ledger and Map. This is the disaggregated
OTIVM-III in the current roadmap describes "The Factor" (NPC model). accounts — the line items of every NEGOTIVM. Not a dashboard. A Roman
The actual next release should establish the SQLite server connection merchant's RATIONES: what was spent at each ITER, on what, at what rate.
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 The player sees a historically authentic accounting surface. The system
assistant.** Do not write code until the roadmap is current. The records parameters beneath it. Raw parameter values remain hidden or
project owner will direct the rewrite. available only in advanced view.
**3. Internal API for aggregation (1103)**
1105 exposes an internal endpoint that 1103 can call on a schedule to
collect player event snapshots for aggregation. Anonymised behavioral
data only — no save file contents transferred raw.
**Before any OTIVM-III code is written:**
Read `docs/architecture/parameter-registry.md` in full. The schema
must not flatten AVCTORITAS into an integer. Uncertainty, observability,
and perceived-vs-true are structural requirements, not optional features.
--- ---
## 6. The database — what the game can and cannot do ## 6. Design corpus — what ChatGPT produced this session
`data/otivm.sqlite3` is present on the container. It is read-only The following documents were produced in collaboration with ChatGPT and
from the game's perspective. The dataset assistant owns it. represent the design substrate for OTIVM-III and beyond. Read them in order.
### What is in the database **Scenarios** (`docs/scenarios/`):
- 12,005 H9 rows across five waypoints, all `status=2` (current) - `SCENARIO-MERCHANT-0000.md` — The BALNEA Conversation (prologue, background selection)
- `paleo_epochs` table — 9 epochs from Eemian to present with sea - `SCENARIO-MERCHANT-0001.md` — The Bronze Forge Fire (second-order market logic)
level offsets - `SCENARIO-MERCHANT-0002.md` — The Capuan Timber Yard Fire (upstream choke-point logic)
- `SCENARIO-MERCHANT-0003.md` — The FAENUS Offer (capital without cargo)
### Five waypoints These form a trilogy with a prologue. Each success condition is sharper
| City | H5 TEXT | H9 cells | than the last. The trilogy teaches: event → dependencies → price → capital.
|---|---|---|
| Ostia | `851e805bfffffff` | 2401 |
| Capua | `851e8333fffffff` | 2401 |
| Brundisium | `851e8ba3fffffff` | 2401 |
| Carthago | `85386e23fffffff` | 2401 |
| Alexandria | `853f5ba7fffffff` | 2401 |
### The canonical game query **Actors** (`docs/actors/`):
Only use cells from complete, current H5 hexes: - `CHARACTER-FRAMEWORK.md` — twelve parameters, hidden traits, background rules
```sql - `BACKGROUND-0001` through `BACKGROUND-0006` — six asymmetric starting lives
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 These are not classes. They are starting parameter profiles that drift
| Field | Trust level | Reason | toward decision history over time (`background_drift` parameter).
|---|---|---|
| `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 **Cities** (`docs/cities/`):
H3 IDs are stored as INTEGER (64-bit) in the database. - `CITY-OSTIA-0001.md` — Ostia substrate: urban zones, population model,
In JavaScript: `h3.indexToCell(BigInt(row.h9))` to convert to string. infrastructure parameters, social nodes, daily and seasonal rhythm
Server-side only — h3-js is not available in the browser bundle.
Ostia functions as a pressure field. It is not scenery. Every parameter
in the city document connects to actor parameters and scenario triggers.
**Architecture** (`docs/architecture/`):
- `infrastructure.md` — settled container topology and API protocol
- `terminology.md` — three-layer vocabulary, rejected terms, naming rules
- `latin-bridge.md` — Latin term admission standard and full semantic entries
- `research-brief-roman-venture.md` — ChatGPT research instructions
- `parameter-registry.md` — all parameters, scope, layer, maturity
--- ---
## 7. Dataset assistant — what they are doing in parallel ## 7. The SVCCINUM thread
The dataset assistant owns the pipeline. Current status: The amber (`SVCCINUM`) in the grain route cargo is not merely a goods label.
It is the first explicit connection between OTIVM and CIVICVS. The amber
originated in Maglemoisian forests in approximately 8000 BCE — the same
territory and period that CIVICVS models. When both simulations share a
TESSERA substrate, the amber in the MERCATOR's hold will be traceable to a
specific H3 cell where a CIVICVS Constructor gathered or traded it.
- `data/otivm.sqlite3` — production database, 12,005 rows ✅ This thread runs through the `origin_h3_r5` provenance stub in `constants.js`,
- `data/staging_otivm.sqlite3` — their working copy, not in git through the SVCCINUM entry in `latin-bridge.md`, through the `occ_flag` stub
- `pipeline/seed_extract.py` — old extractor, do not re-run ✅ parameter in the registry, through to OTIVM-VIII and OTIVM-IX.
- `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:** Do not lose this thread. It is the architectural consequence of building
1. Four datasets to be added to USB Drive 1 (project owner action) both systems on the same physical reality layer from the start.
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`.
--- ---
@@ -267,17 +233,10 @@ pipeline scripts. You do not touch `pipeline/` or `data/create_otivm_db.sql`.
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 2. Human uploads to Gitea manually, or pastes into Claude Code
message) 3. If code: `npm run build && pm2 restart otivm`
3. The file body contains the exact content to write to disk 4. Human confirms result
4. Human downloads from Claude chat and pastes into Claude Code 5. Claude chat proceeds to next step
(Shell 1)
5. Claude Code writes to the specified path, commits, pushes
6. Human runs `npm run build` in Shell 2 (otivm shell)
7. Human runs `pm2 restart otivm` in Shell 2
8. Human confirms in browser at https://otium.civicus.us
9. Human reports result back to Claude chat
10. Claude chat proceeds to the next step
**One file. One step. One confirmation. Never batch.** **One file. One step. One confirmation. Never batch.**
@@ -286,31 +245,39 @@ Every change follows this sequence without exception:
## 9. 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
- 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 - JSON flat files for player state — until OTIVM-III replaces them with SQLite
- H3 IDs on every location — never a coordinate pair or string name - H3 IDs on every location — never a coordinate pair or string name alone
alone - Never make assumptions about disk state — always read from Gitea MCP first
- One change confirmed before the next — no batching steps - Uncertainty is a first-class record, not a comment — applies to all schema work
- Never print file contents or code blocks in chat — always - The data warehouse is the product — the game is the public interface
downloadable attachments - Real weather only in CIVICVS — DWD data always, no simulation
- 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
--- ---
## 10. Commit messages ## 10. Commit message convention
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`. `Add Mediterranean SVG map to Map screen` not `Added map`.
--- ---
*Handover 2026-04-27 — game development track* ## 11. What the dataset assistant is doing in parallel
*Database present, paleo_epochs added, 12,005 current rows.*
*Roadmap needs rewriting — first task before any code.* See `docs/handover-dataset.md` for full detail. Current state:
*terrain field is modern WorldCover — not historically accurate yet.*
- `data/otivm.sqlite3` live — 12,005 rows, `paleo_epochs` populated, FK clean
- `staging_otivm.sqlite3` in sync
- Pipeline venv provisioned at `/home/otivm/pipeline-venv`
- Four datasets pending download to Drive 1 (BGR IGME5000, HYDE 3.3, KK10, HydroRivers)
- Per-H5 pipeline architecture not yet designed — next dataset session task
When `otium.sqlite3` is expanded with new H5 hexes (OTIVM-III first new
waypoint), the game development assistant will be told. The `/api/map/:h5/:epoch`
endpoint requires no changes — it is already parameterised by H5 ID.
---
*Handover 2026-04-28 — game development track*
*Claude chat designs. Claude Code implements. The human decides.* *Claude chat designs. Claude Code implements. The human decides.*