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

13 KiB
Raw Blame History

Handover — OTIVM Game Development

Date: 2026-05-02

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/parameter-registry.md — canonical parameters, scope, layer, maturity
  6. docs/parameter-registry-additions.md — 44 additional tokens from corpus review
  7. docs/actors/CHARACTER-FRAMEWORK.md — six backgrounds, twelve starting parameters
  8. docs/scenarios/SCENARIO-MERCHANT-0000.md — the BALNEA prologue, background selection
  9. docs/scenarios/SCENARIO-MERCHANT-0001.md through 0003.md — the founding trilogy
  10. docs/cities/CITY-OSTIA-0001.md — Ostia as pressure field, not backdrop
  11. docs/roadmap.md — where the game is going
  12. 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.us10.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

Git protocol — mandatory, non-negotiable

Before touching any file:

git fetch origin main
git merge origin/main

After making changes:

git add [specific named files only — never git add .]
git commit -m "scope: description"
git push origin main

NEVER: --rebase, --force, git stash, git reset --hard, git add . NEVER: commit without fetching and merging first.

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 (better-sqlite3)
  • data/saves/ — per-player save files (gitignored)
    • OTIVM-I/II: {token}.json
    • OTIVM-III+: {token}.sqlite3 (created from data/create_player_db.sql)
    • Both formats coexist during migration. JSON files are never deleted.
  • data/create_otivm_db.sql — TESSERA world schema (read-only reference)
  • data/create_player_db.sql — per-player schema (OTIVM-III, committed at 17e82d0)
  • better-sqlite3 installed — used by server for TESSERA queries and player databases
  • PM2 under otivm user (never root)
  • Ecosystem file: ecosystem.config.cjs

4. Current game state — as of 2026-05-02

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 replacing JSON saves — schema committed, wiring is OTIVM-III

OTIVM-III — schema committed, wiring not yet started

Schema: data/create_player_db.sql committed at 17e82d0. Eight tables: actor_profile, actor_parameters, parameter_drift_log, ventures, venture_legs, scenario_state, events, background_starting_values. Pre-seeded with 72 rows (12 parameters × 6 backgrounds). Validated clean.

What OTIVM-III requires — in order:

  1. Backend wiring: server/index.js opens or creates data/saves/{token}.sqlite3 using create_player_db.sql on first access. Same GET/POST /api/save/:token interface — frontend does not change.

  2. JSON migration: On GET /api/save/:token, if {token}.json exists but {token}.sqlite3 does not, import JSON into SQLite automatically. One-time, transparent to the player. JSON files left in place — never deleted.

  3. Parameter initialisation: On new game creation, player chooses background. Seed actor_parameters from background_starting_values for the chosen background. value_true, value_perceived, confidence_tag, and observable_level all correctly populated. auctoritas gets value_social as a third record. No parameter flattened to a single integer.

Non-negotiable schema rules (from parameter-registry.md):

  • value_true and value_perceived are always separate columns
  • confidence_tag is always a first-class column, never a comment
  • auctoritas has three records: value_true, value_perceived, value_social
  • Timestamp column is always recorded_at
  • Rows are never deleted — only archived or superseded
  • Scenario parameters must not leak into actor parameters as permanent values

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+
  • Terrain in data/otivm.sqlite3 is modern WorldCover — restoration layer (HYDE 3.3 + KK10) not yet built. No release may present terrain as historically accurate.

5. Design corpus

The following documents are the design substrate for OTIVM-III and beyond.

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)

Actors (docs/actors/):

  • CHARACTER-FRAMEWORK.md — twelve parameters, hidden traits, background rules
  • BACKGROUND-0001 through BACKGROUND-0006 — six asymmetric starting lives

Cities (docs/cities/):

  • CITY-OSTIA-0001.md — Ostia substrate: urban zones, population model, infrastructure parameters, social nodes, daily and seasonal rhythm

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
  • parameter-registry.md — all parameters, scope, layer, maturity
  • parameter-registry-additions.md — 44 additional tokens from corpus review

Corpus (docs/training/corpus/):

  • 20 Layer 0 primitive facts (commerce domain)
  • 5 Layer 1 worked examples
  • 1 sketch awaiting promotion
  • commerce_chunks.jsonl — 230 training chunks, 5 layers

Law and commerce dialogues (docs/law/, docs/commerce/, docs/economy/):

  • 37 dialogues reviewed, sanitized, and cleared for use
  • Source material for the parameter registry additions

6. The SVCCINVM thread

The amber (SVCCINVM) 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 SVCCINVM 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.


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


8. 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
  • Per-player SQLite for player state — data/saves/{token}.sqlite3 from data/create_player_db.sql
  • JSON saves coexist during migration — never deleted, never overwritten
  • 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
  • Design one step ahead — no release planned beyond the next confirmed step

9. Commit message convention

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


10. 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 designed (RFC-TESSERA-4.0-001), not yet coded

When otivm.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-05-02 — game development track Claude chat designs. Claude Code implements. The human decides.