# Handover — OTIVM Game Development ### Date: 2026-04-28 ### For: Incoming assistant (game development track) ### Read this completely before doing anything --- ## 0. Your role You are the game development assistant. You design and build the OTIVM browser game at `otium.civicus.us`. You work in Claude chat (claude.ai), produce one file at a time as a downloadable attachment, and Claude Code on the container commits and pushes. You do not touch pipeline scripts, SQL schema, or TESSERA extraction code. That work belongs to the dataset assistant (see `docs/handover-dataset.md`). 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 to real users within seconds of `pm2 restart otivm`. --- ## 1. Read these files before writing any code In order: 1. `CLAUDE.md` — workflow, three-shell model, ground rules, deployment facts 2. `docs/architecture/infrastructure.md` — container topology, API protocol 3. `docs/architecture/terminology.md` — three-layer vocabulary, naming convention 4. `docs/architecture/latin-bridge.md` — Latin terms, admission standard, semantic entries 5. `docs/architecture/parameter-registry.md` — all simulation parameters, scope, layer, maturity 6. `docs/actors/CHARACTER-FRAMEWORK.md` — six backgrounds, twelve starting parameters 7. `docs/scenarios/SCENARIO-MERCHANT-0000.md` — the BALNEA prologue, background selection 8. `docs/scenarios/SCENARIO-MERCHANT-0001.md` through `0003.md` — the founding trilogy 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 ### OTIVM container (otivm-dev, CT 1105) - App user: `otivm` - Repo at `/home/otivm/OTIVM` - Claude Code runs here as `otivm` user via `work` alias (`cd ~/OTIVM && claude`) - Python venv: `/home/otivm/venv` - Pipeline venv: `/home/otivm/pipeline-venv` - PM2 home: `/home/otivm/.pm2` - Node: `/usr/bin/node` (v22) - App port: 3000 - WireGuard: 10.110.0.18 ### Five containers on srv-a (10.0.0.11) See `docs/architecture/infrastructure.md` for the full topology. The architecture is settled: REST over HTTPS on the WireGuard mesh, 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 - Lives on wg-pk (198.58.111.109) — not on this container - Proxies `otium.civicus.us` → `10.110.0.18:3000` ### Gitea - Repo: `https://gitea.barternetwork.us/TheRON/OTIVM` - Branch: `main` (direct push, Claude Code handles this) - MCP: connected via `mcp.civicus.us` — Claude chat reads any file directly ### Backups - Command: `vzdump 1105 --compress zstd --storage local --mode snapshot` on srv-a (root shell) - Document every backup in `docs/archives.md` immediately after — see existing entries for format - Download each dump to workstation cold storage - Never take a backup without documenting it. Never document one not taken. --- ## 3. Stack - React 19 + Vite 8 frontend (`src/`) - Fastify backend (`server/index.js`) — serves `dist/`, save API, TESSERA map endpoint - `data/otivm.sqlite3` — TESSERA physical data, read-only by game server - `data/saves/` — per-player JSON save files (gitignored) - `better-sqlite3` installed — used by server for TESSERA queries - PM2 under `otivm` user (never root) - Ecosystem file: `ecosystem.config.cjs` --- ## 4. Current game state — as of 2026-04-28 ### OTIVM-I — complete Five trade routes Ostia → Alexandria, journal, otium/negotium mechanic, per-player saves via 8-char hex token, 128 concurrent players supported. ### OTIVM-II — complete and live **The map is live and rendering from real TESSERA data.** - `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 - Sea hexes are dark by definition — no data, no storage - `session_abandoned` event — saves are never deleted, they receive a terminal event - REST API for all inter-container data flows — no shared filesystems - Per-player SQLite (128 files) replacing JSON saves — planned for OTIVM-III ### Known deferred items - Journal local state does not reset on new game (React state issue, low priority) - H7 cells rendered as circles — hex geometry deferred pending client-side h3-js - Map coastline is five isolated H5 clusters — route corridor coverage deferred to OTIVM-III+ - Roadmap body is stale — rewrite planned under project owner direction --- ## 5. OTIVM-III — defined, not yet started OTIVM-III is the data plumbing release. Three things: **1. Per-player SQLite — 128 pre-provisioned databases** Replace JSON save files in `data/saves/` with SQLite databases in `data/players/`. Pre-provision all 128 at container setup — no database created on demand under player load. The schema is defined by the parameter registry and the SQLite schema document (pending — this is the next document to be produced). The atomic unit is **time**. The database is a time-series of events. Current parameter values are derived from event history. The schema must treat uncertainty, confidence, and perceived-vs-true values as first-class records, not comments. **2. RATIONES tab — the third screen** Add a third tab alongside Ledger and Map. This is the disaggregated accounts — the line items of every NEGOTIVM. Not a dashboard. A Roman merchant's RATIONES: what was spent at each ITER, on what, at what rate. The player sees a historically authentic accounting surface. The system records parameters beneath it. Raw parameter values remain hidden or 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. Design corpus — what ChatGPT produced this session The following documents were produced in collaboration with ChatGPT and represent the design substrate for OTIVM-III and beyond. Read them in order. **Scenarios** (`docs/scenarios/`): - `SCENARIO-MERCHANT-0000.md` — The BALNEA Conversation (prologue, background selection) - `SCENARIO-MERCHANT-0001.md` — The Bronze Forge Fire (second-order market logic) - `SCENARIO-MERCHANT-0002.md` — The Capuan Timber Yard Fire (upstream choke-point logic) - `SCENARIO-MERCHANT-0003.md` — The FAENUS Offer (capital without cargo) These form a trilogy with a prologue. Each success condition is sharper than the last. The trilogy teaches: event → dependencies → price → capital. **Actors** (`docs/actors/`): - `CHARACTER-FRAMEWORK.md` — twelve parameters, hidden traits, background rules - `BACKGROUND-0001` through `BACKGROUND-0006` — six asymmetric starting lives These are not classes. They are starting parameter profiles that drift toward decision history over time (`background_drift` parameter). **Cities** (`docs/cities/`): - `CITY-OSTIA-0001.md` — Ostia substrate: urban zones, population model, infrastructure parameters, social nodes, daily and seasonal rhythm 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. The SVCCINUM thread 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. This thread runs through the `origin_h3_r5` provenance stub in `constants.js`, through the SVCCINUM entry in `latin-bridge.md`, through the `occ_flag` stub parameter in the registry, through to OTIVM-VIII and OTIVM-IX. Do not lose this thread. It is the architectural consequence of building both systems on the same physical reality layer from the start. --- ## 8. Workflow — one file, one step, one confirmation Every change follows this sequence without exception: 1. Claude chat discusses the change and produces one downloadable file 2. Human uploads to Gitea manually, or pastes into Claude Code 3. If code: `npm run build && pm2 restart otivm` 4. Human confirms result 5. Claude chat proceeds to next step **One file. One step. One confirmation. Never batch.** --- ## 9. Hard rules - Never run PM2 as root — always as otivm user - Never commit secrets — no tokens, no keys, no passwords - Never push to main without building — `npm run build` must pass first - 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 alone - Never make assumptions about disk state — always read from Gitea MCP first - Uncertainty is a first-class record, not a comment — applies to all schema work - The data warehouse is the product — the game is the public interface - Real weather only in CIVICVS — DWD data always, no simulation --- ## 10. Commit message convention Imperative mood, present tense, under 72 characters. `Add Mediterranean SVG map to Map screen` not `Added map`. --- ## 11. What the dataset assistant is doing in parallel See `docs/handover-dataset.md` for full detail. Current state: - `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.*