12 KiB
Handover — OTIVM Game Development
Date: 2026-05-03
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 the human
commits and pushes from the otivm shell.
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.
Workflow — files you produce go to the human, not Claude Code. Claude Code is expensive. The human writes files to disk directly from the otivm shell and runs git commands copy-pasted from chat. Always provide the exact git commands in chat, ready to copy-paste. Never require manual editing or renaming.
1. Read these files before writing any code
In order:
CLAUDE.md— workflow, ground rules, deployment factsdocs/architecture/infrastructure.md— container topology, API protocoldocs/architecture/terminology.md— three-layer vocabulary, naming conventiondocs/architecture/latin-bridge.md— Latin terms, admission standard, semantic entriesdocs/parameter-registry.md— canonical parameters, scope, layer, maturitydocs/parameter-registry-additions.md— 44 additional tokens from corpus reviewdocs/actors/CHARACTER-FRAMEWORK.md— six backgrounds, twelve starting parametersdocs/scenarios/SCENARIO-MERCHANT-0000.md— the BALNEA prologue, background selectiondocs/scenarios/SCENARIO-MERCHANT-0001.mdthrough0003.md— the founding trilogydocs/cities/CITY-OSTIA-0001.md— Ostia as pressure field, not backdropdocs/Roadmap-OTIVM-IV.md— OTIVM-IV scope and file inventory (approved)docs/roadmap.md— where the game is going- 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 - 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)
| 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)
- Proxies
otium.civicus.us→10.110.0.18:3000
Gitea
- Repo:
https://gitea.barternetwork.us/TheRON/OTIVM - Branch:
main(direct push) - MCP: connected via
mcp.civicus.us
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 .
Backups
- Command:
vzdump 1105 --compress zstd --storage local --mode snapshoton srv-a (root shell) - Document every backup in
docs/archives.mdimmediately after - 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) - Bootstrap 5.3.3 (vendored, MIT, pinned) — layout and components
- Bootstrap Icons 1.11.3 (vendored, MIT, pinned)
data/otivm.sqlite3— TESSERA physical data, read-only (better-sqlite3)data/saves/— per-player save files (gitignored)- OTIVM-I/II:
{token}.json - OTIVM-III+:
{token}.sqlite3(created fromdata/create_player_db.sql) - Both formats coexist. JSON files are never deleted.
- OTIVM-I/II:
data/create_player_db.sql— per-player schema (schema version 5)data/repair_player_db_fk.sql— repair script for pre-v5 databases- PM2 under
otivmuser (never root)
Frontend file structure (OTIVM-IV)
src/
config/
contexts.json ← dropdown definition
context-actor.json ← ACTOR layout and section config
context-forum.json ← FORUM layout and section config
context-map.json ← MAP layout and section config
components/
Shell.jsx ← sidebar + dropdown + layout grid (built once)
Section.jsx ← generic panel renderer (built once)
ParameterRow.jsx ← one parameter row
CostRow.jsx ← one cost line
DriftEntry.jsx ← one drift log entry
screens/
Actor.jsx ← ACTOR context screen
Forum.jsx ← FORUM context screen
Map.jsx ← MAP context (unchanged from OTIVM-II)
App.jsx ← Shell wired, three contexts
App.css ← project overrides only (Bootstrap handles layout)
constants.js ← routes, waypoints, BACKGROUNDS, MS_PER_SIM_DAY
gameState.js ← frontend game state logic
api.js ← save API calls
4. Current game state — as of 2026-05-03
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
Map live and rendering from real TESSERA data. Fog-of-war SVG, H7 land cells at real geographic positions, progressive reveal by chapter.
OTIVM-III — complete and live
Per-player SQLite live. Schema version 5. Background selection, parameter seeding, ventures, venture_legs, parameter_drift_log all recording correctly.
OTIVM-IV — complete and live at 3700f5a
The situation instrument is live.
Server startup message: OTIVM server running on port 3000 — OTIVM-IV
What was built:
-
Bootstrap 5.3.3 + Bootstrap Icons 1.11.3 — vendored, pinned.
-
App.css— reduced to project overrides. Roman palette as CSS custom properties. All classes prefixedotivm-. -
Shell architecture —
Shell.jsxandSection.jsxbuilt once. Sidebar with context dropdown replaces tab navigation. Four layout types:single,two-col,three-col,map. Nine panel types in Section.jsx. -
Context JSON files — four files in
src/config/. Adding a new context requires one JSON file + one thin screen file. No shell changes. -
Sub-components —
ParameterRow.jsx,CostRow.jsx,DriftEntry.jsx. -
Actor.jsx— background selection (whenbackground_id = null) or full parameter instrument view (three-col: identity/liquiditas, auctoritas three faces/parameters, obligations/drift log). -
Forum.jsx— dispatch and otium decisions. Full cost breakdown (vectura/portoria/other) visible on route cards. Periodic expenditures panel. Journal collapsible. -
App.jsx— Shell wired. Three contexts: ACTOR, FORUM, MAP. -
server/index.js— three named otium expenditure trigger types:otium_access_fee(2 dn),personal_maintenance(4 dn),officia_obligation(2 dn). Each writes a separate drift log entry. -
Retired —
Prologue.jsxandLedger.jsxdeleted.
Otium expenditure constants — source: docs/economy/cost-calibration-model.md:
const OTIUM_ACCESS_FEE_DN = 2.00 // LOW confidence
const PERSONAL_MAINTENANCE_DN = 4.00 // MEDIUM confidence
const OFFICIA_OBLIGATION_DN = 2.00 // LOW confidence
const OTIUM_CYCLE_TOTAL_DN = 8.00
Change only in server/index.js constants block and Forum.jsx.
Economic calibration documents in docs/economy/:
cost-calibration-model.md— ceramic cup baseline, reference wagescost-calibration-additional-goods.md— garum, grain, amber, marble capital
Five good patterns:
batch_craft · perishable_batch · bulk_staple · import_luxury · commission_heavy
Market architectural constraints (deferred — must not be violated):
observable_levelon everyactor_parametersrow is the Market visibility gatevalue_true= server ground truth.value_perceived= ledger truth. Never conflate.- Every drift log entry must be meaningful to an external reader.
Known deferred items:
- Real cost model — 60/25/15 split is a placeholder
- Transformation routes (grain→bread) and barter — architecture defined, not built
- Market reader — deferred, constraints documented
- H7 cells as circles — hex geometry deferred pending h3-js
- Map coastline — five isolated H5 clusters
- Terrain — modern WorldCover, restoration layer not yet built
What OTIVM-V is
Not yet defined. Project owner decides scope before development begins. Take a backup and document it before OTIVM-V begins.
5. Design corpus
Scenarios (docs/scenarios/):
SCENARIO-MERCHANT-0000.md— The BALNEA ConversationSCENARIO-MERCHANT-0001.md— The Bronze Forge FireSCENARIO-MERCHANT-0002.md— The Capuan Timber Yard FireSCENARIO-MERCHANT-0003.md— The FAENUS Offer
Actors (docs/actors/):
CHARACTER-FRAMEWORK.md— twelve parameters, hidden traits, background rulesBACKGROUND-0001throughBACKGROUND-0006— six asymmetric starting lives
Cities (docs/cities/):
CITY-OSTIA-0001.md— Ostia substrate
Architecture (docs/architecture/):
infrastructure.md,terminology.md,latin-bridge.mdparameter-registry.md,parameter-registry-additions.mdsimulation-clock.md—MS_PER_SIM_DAY = 3_000
Economic calibration (docs/economy/):
cost-calibration-model.mdcost-calibration-additional-goods.md
6. The SVCCINUM thread
The amber (SVCCINUM) in the grain route cargo is the first explicit
connection between OTIVM and CIVICVS. It originated in Maglemoisian forests
in approximately 8000 BCE. 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 origin_h3_r5 in constants.js, through the
SVCCINUM entry in latin-bridge.md, through occ_flag in the registry,
through to OTIVM-VIII and OTIVM-IX. Do not lose it.
7. Workflow — one file, one step, one confirmation
- Claude chat produces one downloadable file
- Human writes to disk:
cp filename src/path/filename - If code:
npm run build(thenpm2 restart otivmif server or frontend) - Human runs the exact git commands provided in chat — copy-paste, no editing
- Human confirms
- Claude chat proceeds
One file. One step. One confirmation. Never batch.
Git add rule: Always name the exact file. Never git add .
File naming rule: Downloaded filename = destination filename. No renaming.
8. Hard rules
- Never run PM2 as root — always as otivm user
- Never commit secrets
- Never push without building
- Per-player SQLite for player state
- JSON saves coexist — never deleted, never overwritten
- H3 IDs on every location — never a coordinate pair alone
- Never assume disk state — always read from Gitea MCP first
- Uncertainty is a first-class record, not a comment
- The data warehouse is the product — the game is the public interface
- Real weather only in CIVICVS — DWD data always
- Design one step ahead
- Bootstrap is vendored and pinned — never use a CDN reference
9. Commit message convention
Imperative mood, present tense, under 72 characters.
10. What the dataset assistant is doing in parallel
See docs/handover-dataset.md for full detail. Current state:
data/otivm.sqlite3live — 12,005 rows,paleo_epochspopulated, FK clean- Four datasets pending download (BGR IGME5000, HYDE 3.3, KK10, HydroRivers)
- Per-H5 pipeline designed (RFC-TESSERA-4.0-001), not yet coded
When otivm.sqlite3 is expanded with new H5 hexes, the game development
assistant will be told. The /api/map/:h5/:epoch endpoint needs no changes.
Handover 2026-05-03 — game development track Claude chat designs. Claude Code implements. The human decides.