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

9.3 KiB
Raw Blame History

Handover — OTIVM Game Development

Date: 2026-04-26

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-seed-extraction.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.md — where the game is going through OTIVM-X
  3. docs/RFC-TESSERA-4.0-001.md — the data schema that OTIVM-III onward depends on
  4. This file

The roadmap is the product plan. The RFC is the data contract. CLAUDE.md is the operational contract. Do not deviate from any of them without explicit project owner instruction.


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: /home/otivm/venv
  • PM2 home: /home/otivm/.pm2
  • Node: /usr/bin/node (v22)
  • App port: 3000
  • WireGuard: 10.110.0.18

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
  • No database for player state — JSON flat files in data/saves/
  • data/otivm.sqlite3 — TESSERA physical-world data, read-only by the game server
  • 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-26

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) — accurate mainland coastline
  • 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 four routes: origin_h3_r5, origin_region, cultural_note These are stub H3 IDs today — become live TESSERA API queries in OTIVM-III
  • src/gameState.js — structural additions:
    • active_dispatch: null in INITIAL_STATE — records in-progress dispatch for position tracking and real-time duration (OTIVM-IV)
    • events: [] in INITIAL_STATE — 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 for a dispatched galley. 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 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
  • Mediterranean map to be replaced in OTIVM-III (moved up from OTIVM-VII)
  • Two-polygon land outline (not one) — avoids cross-sea 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. This note exists in the project owner's memory.

5. OTIVM-III — defined, not yet started

OTIVM-III moves two items forward from their original roadmap positions:

  1. SQLite integrationdata/otivm.sqlite3 arrives on the container from the dataset assistant. The Fastify server gets a read-only SQLite connection (better-sqlite3). A /api/cell/:h9 endpoint exposes TESSERA data for individual H9 cells. The game UI does not yet surface this data directly — the plumbing is established and verified working.

  2. Accurate map — the placeholder two-polygon coastline is replaced with a Natural Earth or equivalent accurate coastline, including major islands (Sicily, Sardinia, Crete, Cyprus). The map remains SVG, equirectangular, same bounding box and canvas size.

These two items belong together in OTIVM-III because the database arrival on the container is the trigger for both — once otivm.sqlite3 is present, the map replacement and server plumbing happen in the same release.

OTIVM-III scope must be confirmed with the project owner before code is written.


6. What the dataset assistant is doing in parallel

The dataset assistant is working on TESSERA 4.0 seed extraction:

  • data/create_otivm_db.sql — schema for otium.sqlite3 committed
  • 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 physical-world data for the five OTIVM waypoint H5 hexes.

Verified row counts (from data/create_otivm_db.sql and confirmed by dataset assistant):

  • H3 resolution hierarchy res-5 → res-9: 7⁴ = 2,401 H9 cells per H5 hex
  • Five waypoints × 2,401 = 12,005 total H9 rows
  • All five H5 hexes are within the completed portion of tessera.db (Mediterranean is fully populated through stage 04)
  • occ_flag is 0 for all seed rows — stage 06 (occupation evidence) not yet run

You do not run extraction scripts. You do not touch pipeline files. When otivm.sqlite3 arrives on the container, you will be told.


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


8. 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 (data/saves/)
  • 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

9. Commit messages

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


Handover 2026-04-26 — game development track Claude chat designs. Claude Code implements. The human decides.