Correct H9 row count in game dev handover (2401 per H5, 12005 total)
This commit is contained in:
222
docs/handover-game-dev.md
Normal file
222
docs/handover-game-dev.md
Normal file
@@ -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.*
|
||||||
Reference in New Issue
Block a user