diff --git a/docs/handover-game-dev.md b/docs/handover-game-dev.md new file mode 100644 index 0000000..60a6dce --- /dev/null +++ b/docs/handover-game-dev.md @@ -0,0 +1,222 @@ +# 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.us` → `10.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°E–38°E / 28°N–48°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 0–1 + 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 integration** — `data/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.*