302 lines
13 KiB
Markdown
302 lines
13 KiB
Markdown
# 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.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
|
||
|
||
### 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.*
|