Files
otivm/docs/handover-game-dev.md

12 KiB
Raw Blame History

Handover — OTIVM Game Development

Date: 2026-04-27

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/roadmap.mdread with the warnings in Section 5 of this document in mind. The roadmap needs rewriting. Do not treat it as current.
  3. docs/RFC-TESSERA-4.0-001.md — the database schema all future releases depend on
  4. docs/TESSERA-dataset-registry.md — what data exists, what is pending, and critically: the restoration layer concept
  5. This file

2. Infrastructure

OTIVM container (otium-dev, 10.0.0.23)

  • App user: otivm
  • Repo at /home/otivm/OTIVM
  • Claude Code runs here as otivm user via work alias (cd ~/OTIVM && claude)
  • Python venv (game): /home/otivm/venv
  • Python venv (pipeline — do not use): /home/otivm/pipeline-venv
  • PM2 home: /home/otivm/.pm2
  • Node: /usr/bin/node (v22)
  • App port: 3000
  • 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

  • Lives on wg-pk (198.58.111.109) — not on this container
  • Proxies otium.civicus.us10.110.0.18:3000
  • Do not look for a vhost on the container

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

  • vzdump 1105 --compress zstd --storage local --mode snapshot on srv-a (root shell)
  • Document every backup in docs/archives.md immediately after
  • 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/ and save API on port 3000
  • 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)
  • Ecosystem file: ecosystem.config.cjs (must be .cjs — Vite sets "type": "module")

4. Current game state — as of 2026-04-27

OTIVM-I — complete

  • Fastify backend serving dist/ and save API on port 3000
  • Five trade routes, Ostia → Alexandria, all working
  • 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

  • src/screens/Map.jsx — Mediterranean SVG map
  • 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

  • H3 IDs on all waypoints — permanent, TESSERA-compatible
  • constants.js / gameState.js / api.js separation — permanent
  • Virtual screens via display:none — state preserved in browser
  • Save on meaningful events only — not on every tick
  • H3 cell centre coordinates hardcoded in Map.jsx — h3-js is 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

  • Claude Code collapsed INITIAL_STATE onto one line during a prior session, causing a Vite build failure. Fixed in commit 34176dc.
  • Going forward: Claude Code writes content exactly as received, regardless of how it arrives.

5. The roadmap — needs rewriting ⚠

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. It assumes a completed global TESSERA database. 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. terrain in otivm.sqlite3 is modern WorldCover 2021 data. It is wrong for any historical period. The Mediterranean was 6070% forested in Roman times and Mesolithic times. Today the same cells are classified as built-up, cropland, or drained wetland.

The restoration layer (HYDE 3.3 + KK10 datasets, not yet on drives) will correct terrain to historically appropriate values. Until that layer is active, the game must not present terrain data as historically accurate.

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. The database — what the game can and cannot do

data/otivm.sqlite3 is present on the container. It is read-only from the game's perspective. The dataset assistant owns it.

What is in the database

  • 12,005 H9 rows across five waypoints, all status=2 (current)
  • paleo_epochs table — 9 epochs from Eemian to present with sea level offsets

Five waypoints

City H5 TEXT H9 cells
Ostia 851e805bfffffff 2401
Capua 851e8333fffffff 2401
Brundisium 851e8ba3fffffff 2401
Carthago 85386e23fffffff 2401
Alexandria 853f5ba7fffffff 2401

The canonical game query

Only use cells from complete, current H5 hexes:

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. 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:

  1. Claude chat discusses the change and produces one downloadable file
  2. The file header contains the Claude Code instruction (path, commit message)
  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)
  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.


9. Hard rules

  • Never run PM2 as root — always as otivm user
  • Never commit secrets — no tokens, no keys, no passwords in any file
  • Never push to main without building — npm run build must pass first
  • No database for player state — JSON flat files only
  • H3 IDs on every location — never a coordinate pair or string name alone
  • One change confirmed before the next — no batching steps
  • Never print file contents or code blocks in chat — always 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

10. Commit messages

Imperative mood, present tense, under 72 characters. Example: Add Mediterranean SVG map to Map screen not Added map.


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.