OTIVM-IV complete

This commit is contained in:
2026-05-03 15:23:25 -04:00
parent bcb2bf5629
commit 63b2f6cf7b

View File

@@ -9,8 +9,8 @@
You are the game development assistant. You design and build the OTIVM 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), 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 produce one file at a time as a downloadable attachment, and the human
on the container commits and pushes. commits and pushes from the otivm shell.
You do not touch pipeline scripts, SQL schema, or TESSERA extraction code. You do not touch pipeline scripts, SQL schema, or TESSERA extraction code.
That work belongs to the dataset assistant (see `docs/handover-dataset.md`). That work belongs to the dataset assistant (see `docs/handover-dataset.md`).
@@ -19,13 +19,19 @@ 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 The game is live. The server is running. Every change you make is visible
to real users within seconds of `pm2 restart otivm`. 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 ## 1. Read these files before writing any code
In order: In order:
1. `CLAUDE.md` — workflow, three-shell model, ground rules, deployment facts 1. `CLAUDE.md` — workflow, ground rules, deployment facts
2. `docs/architecture/infrastructure.md` — container topology, API protocol 2. `docs/architecture/infrastructure.md` — container topology, API protocol
3. `docs/architecture/terminology.md` — three-layer vocabulary, naming convention 3. `docs/architecture/terminology.md` — three-layer vocabulary, naming convention
4. `docs/architecture/latin-bridge.md` — Latin terms, admission standard, semantic entries 4. `docs/architecture/latin-bridge.md` — Latin terms, admission standard, semantic entries
@@ -35,8 +41,9 @@ In order:
8. `docs/scenarios/SCENARIO-MERCHANT-0000.md` — the BALNEA prologue, background selection 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 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 10. `docs/cities/CITY-OSTIA-0001.md` — Ostia as pressure field, not backdrop
11. `docs/roadmap.md` — where the game is going 11. `docs/Roadmap-OTIVM-IV.md` — OTIVM-IV scope and file inventory (approved)
12. This file 12. `docs/roadmap.md` — where the game is going
13. This file
The parameter registry is the bridge between the design documents and the The parameter registry is the bridge between the design documents and the
schema. Read it before touching any database code. schema. Read it before touching any database code.
@@ -48,7 +55,6 @@ schema. Read it before touching any database code.
### OTIVM container (otivm-dev, CT 1105) ### OTIVM container (otivm-dev, CT 1105)
- App user: `otivm` - App user: `otivm`
- Repo at `/home/otivm/OTIVM` - Repo at `/home/otivm/OTIVM`
- Claude Code runs here as `otivm` user via `work` alias (`cd ~/OTIVM && claude`)
- Python venv: `/home/otivm/venv` - Python venv: `/home/otivm/venv`
- Pipeline venv: `/home/otivm/pipeline-venv` - Pipeline venv: `/home/otivm/pipeline-venv`
- PM2 home: `/home/otivm/.pm2` - PM2 home: `/home/otivm/.pm2`
@@ -57,9 +63,6 @@ schema. Read it before touching any database code.
- WireGuard: 10.110.0.18 - WireGuard: 10.110.0.18
### Five containers on srv-a (10.0.0.11) ### 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 | | CT | Role |
|---|---| |---|---|
@@ -70,13 +73,13 @@ one write domain per container, no shared filesystems between containers.
| 1105 | otivm-dev (this container) | | 1105 | otivm-dev (this container) |
### Nginx proxy ### Nginx proxy
- Lives on wg-pk (198.58.111.109) — not on this container - Lives on wg-pk (198.58.111.109)
- Proxies `otium.civicus.us``10.110.0.18:3000` - Proxies `otium.civicus.us``10.110.0.18:3000`
### Gitea ### Gitea
- Repo: `https://gitea.barternetwork.us/TheRON/OTIVM` - Repo: `https://gitea.barternetwork.us/TheRON/OTIVM`
- Branch: `main` (direct push, Claude Code handles this) - Branch: `main` (direct push)
- MCP: connected via `mcp.civicus.us` — Claude chat reads any file directly - MCP: connected via `mcp.civicus.us`
### Git protocol — mandatory, non-negotiable ### Git protocol — mandatory, non-negotiable
Before touching any file: Before touching any file:
@@ -91,11 +94,10 @@ git commit -m "scope: description"
git push origin main git push origin main
``` ```
NEVER: `--rebase`, `--force`, `git stash`, `git reset --hard`, `git add .` NEVER: `--rebase`, `--force`, `git stash`, `git reset --hard`, `git add .`
NEVER: commit without fetching and merging first.
### Backups ### Backups
- Command: `vzdump 1105 --compress zstd --storage local --mode snapshot` on srv-a (root shell) - 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 - Document every backup in `docs/archives.md` immediately after
- Download each dump to workstation cold storage - Download each dump to workstation cold storage
- Never take a backup without documenting it. Never document one not taken. - Never take a backup without documenting it. Never document one not taken.
@@ -104,18 +106,42 @@ NEVER: commit without fetching and merging first.
## 3. Stack ## 3. Stack
- React 19 + Vite 8 frontend (`src/`) - React 19 + Vite 8 frontend (`src/`)
- Fastify backend (`server/index.js`) — serves `dist/`, save API, TESSERA map endpoint - Fastify backend (`server/index.js`)
- `data/otivm.sqlite3` — TESSERA physical data, read-only by game server (`better-sqlite3`) - 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) - `data/saves/` — per-player save files (gitignored)
- OTIVM-I/II: `{token}.json` - OTIVM-I/II: `{token}.json`
- OTIVM-III+: `{token}.sqlite3` (created from `data/create_player_db.sql`) - OTIVM-III+: `{token}.sqlite3` (created from `data/create_player_db.sql`)
- Both formats coexist during migration. JSON files are never deleted. - Both formats coexist. JSON files are never deleted.
- `data/create_otivm_db.sql`TESSERA world schema (read-only reference) - `data/create_player_db.sql`per-player schema (schema version 5)
- `data/create_player_db.sql`per-player schema (schema version 5, committed at `b1de03f`) - `data/repair_player_db_fk.sql`repair script for pre-v5 databases
- `data/repair_player_db_fk.sql` — repair script for pre-v5 player databases
- `better-sqlite3` installed — used by server for TESSERA queries and player databases
- PM2 under `otivm` user (never root) - PM2 under `otivm` user (never root)
- Ecosystem file: `ecosystem.config.cjs`
### 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
```
--- ---
@@ -126,202 +152,162 @@ Five trade routes Ostia → Alexandria, journal, otium/negotium mechanic,
per-player saves via 8-char hex token, 128 concurrent players supported. per-player saves via 8-char hex token, 128 concurrent players supported.
### OTIVM-II — complete and live ### OTIVM-II — complete and live
**The map is live and rendering from real TESSERA data.** Map live and rendering from real TESSERA data. Fog-of-war SVG, H7 land
cells at real geographic positions, progressive reveal by chapter.
- `src/screens/Map.jsx` — fog-of-war SVG map ### OTIVM-III — complete and live
- H7 land cells rendered at real geographic positions (lat/lon from API) Per-player SQLite live. Schema version 5. Background selection, parameter
- Progressive reveal by chapter — only visited waypoints are visible seeding, ventures, venture_legs, parameter_drift_log all recording correctly.
- 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 ### OTIVM-IV — complete and live at `3700f5a`
- 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 — complete and live at `d1e1b98` **The situation instrument is live.**
**The sub-trace is live. The behavioral record is real.** Server startup message: `OTIVM server running on port 3000 — OTIVM-IV`
Current HEAD: `d1e1b98`. Server startup message: `OTIVM-III complete`. **What was built:**
**What was built, in order:** 1. **Bootstrap 5.3.3 + Bootstrap Icons 1.11.3** — vendored, pinned.
1. **Schema** (`data/create_player_db.sql`) — schema version 5. Eight tables: 2. **`App.css`** — reduced to project overrides. Roman palette as CSS custom
`actor_profile`, `actor_parameters`, `parameter_drift_log`, `ventures`, properties. All classes prefixed `otivm-`.
`venture_legs`, `scenario_state`, `events`, `background_starting_values`.
Pre-seeded with 72 rows (12 parameters × 6 backgrounds). `UNIQUE(actor_id)`
on `actor_profile` — required for FK references from child tables.
`data/repair_player_db_fk.sql` provided for pre-v5 database repair.
2. **Background selection** (`src/screens/Prologue.jsx`, `src/App.jsx`, 3. **Shell architecture**`Shell.jsx` and `Section.jsx` built once.
`src/constants.js`) — Prologue tab added as a third tab alongside Ledger Sidebar with context dropdown replaces tab navigation. Four layout types:
and Map. Player chooses one of six backgrounds before first dispatch. `single`, `two-col`, `three-col`, `map`. Nine panel types in Section.jsx.
`BACKGROUNDS` constant in `constants.js` — six entries with canonical IDs,
display names, Latin names, summaries, and starting den values.
`MS_PER_SIM_DAY = 3_000` defined in `constants.js` (1 simulated day = 3
real seconds). `INITIAL_STATE.background_id = null` — gates the Prologue.
3. **Backend wiring** (`server/index.js`) — per-player SQLite live. On new 4. **Context JSON files** — four files in `src/config/`. Adding a new context
player creation, seeds `actor_parameters` from `background_starting_values` requires one JSON file + one thin screen file. No shell changes.
for the chosen background. Profile patch: if `actor_profile` has
`background_id = 'unknown'` and a subsequent POST arrives with a real
background, the profile is patched and parameters are seeded. JSON migration
retained per roadmap — JSON files are never deleted.
4. **Ventures and venture legs** — on `dispatch_start`, creates a `ventures` 5. **Sub-components**`ParameterRow.jsx`, `CostRow.jsx`, `DriftEntry.jsx`.
row (`status='active'`) and a `venture_legs` row. Cost split applied:
`cost_vectura = 60%`, `cost_portoria = 25%`, `cost_other = 15%` — placeholder
pending a real cost model. `duration_days` stored as INTEGER (never REAL),
derived from `duration_ms / MS_PER_SIM_DAY`. On `dispatch_complete`, closes
both rows with `outcome_net` and `completed_at`.
5. **Parameter drift log**`parameter_drift_log` writes on every parameter 6. **`Actor.jsx`** — background selection (when `background_id = null`) or
change with correct trigger types: full parameter instrument view (three-col: identity/liquiditas, auctoritas
- `dispatch_cost` — den decreases at dispatch start (cost deducted) three faces/parameters, obligations/drift log).
- `venture_complete` — den increases at dispatch return (profit received)
- `interval_complete` — auctoritas band changes after otium
No drift log entry fires during initial seeding (null-check guard).
**Known schema state for new players:** 7. **`Forum.jsx`** — dispatch and otium decisions. Full cost breakdown
- `actor_profile.background_id` — correct canonical identifier (vectura/portoria/other) visible on route cards. Periodic expenditures
- `actor_parameters` — all 12 parameters seeded from `background_starting_values` panel. Journal collapsible.
- `ventures`, `venture_legs` — one row per dispatch cycle
- `parameter_drift_log` — one row per parameter change, with venture_id refs
- `events` — append-only, correct event_type sequence
**Cost split — placeholder values (change only in `server/index.js` constants block):** 8. **`App.jsx`** — Shell wired. Three contexts: ACTOR, FORUM, MAP.
9. **`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.
10. **Retired**`Prologue.jsx` and `Ledger.jsx` deleted.
**Otium expenditure constants — source: `docs/economy/cost-calibration-model.md`:**
```javascript ```javascript
const COST_VECTURA_RATIO = 0.60 // VECTVRA — freight charge const OTIUM_ACCESS_FEE_DN = 2.00 // LOW confidence
const COST_PORTORIA_RATIO = 0.25 // PORTORIUM — customs duty const PERSONAL_MAINTENANCE_DN = 4.00 // MEDIUM confidence
// cost_other = remainder = 0.15 // horreum, incidentals 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`.
**Known deferred items from OTIVM-III:** **Economic calibration documents in `docs/economy/`:**
- Cost model: 60/25/15 split is a placeholder. A real model based on route - `cost-calibration-model.md` — ceramic cup baseline, reference wages
distance, cargo type, and epoch should be designed before OTIVM-IV touches - `cost-calibration-additional-goods.md` — garum, grain, amber, marble capital
economics.
- 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
- 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.
### What OTIVM-IV is **Five good patterns:**
Per the roadmap: **The Seasons** — dispatches take real hours, weather affects `batch_craft` · `perishable_batch` · `bulk_staple` · `import_luxury` · `commission_heavy`
routes, DWD data drives conditions. This is a significant scope change.
The project owner decides whether to proceed with OTIVM-IV as defined in the
roadmap or redefine the scope before development begins.
Before OTIVM-IV begins: take a backup (`vzdump 1105`) and document it in **Market architectural constraints (deferred — must not be violated):**
`docs/archives.md`. - `observable_level` on every `actor_parameters` row is the Market visibility gate
- `value_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 ## 5. Design corpus
The following documents are the design substrate for OTIVM-III and beyond.
**Scenarios** (`docs/scenarios/`): **Scenarios** (`docs/scenarios/`):
- `SCENARIO-MERCHANT-0000.md` — The BALNEA Conversation (prologue, background selection) - `SCENARIO-MERCHANT-0000.md` — The BALNEA Conversation
- `SCENARIO-MERCHANT-0001.md` — The Bronze Forge Fire (second-order market logic) - `SCENARIO-MERCHANT-0001.md` — The Bronze Forge Fire
- `SCENARIO-MERCHANT-0002.md` — The Capuan Timber Yard Fire (upstream choke-point logic) - `SCENARIO-MERCHANT-0002.md` — The Capuan Timber Yard Fire
- `SCENARIO-MERCHANT-0003.md` — The FAENUS Offer (capital without cargo) - `SCENARIO-MERCHANT-0003.md` — The FAENUS Offer
**Actors** (`docs/actors/`): **Actors** (`docs/actors/`):
- `CHARACTER-FRAMEWORK.md` — twelve parameters, hidden traits, background rules - `CHARACTER-FRAMEWORK.md` — twelve parameters, hidden traits, background rules
- `BACKGROUND-0001` through `BACKGROUND-0006` — six asymmetric starting lives - `BACKGROUND-0001` through `BACKGROUND-0006` — six asymmetric starting lives
**Cities** (`docs/cities/`): **Cities** (`docs/cities/`):
- `CITY-OSTIA-0001.md` — Ostia substrate: urban zones, population model, - `CITY-OSTIA-0001.md` — Ostia substrate
infrastructure parameters, social nodes, daily and seasonal rhythm
**Architecture** (`docs/architecture/`): **Architecture** (`docs/architecture/`):
- `infrastructure.md` — settled container topology and API protocol - `infrastructure.md`, `terminology.md`, `latin-bridge.md`
- `terminology.md` — three-layer vocabulary, rejected terms, naming rules - `parameter-registry.md`, `parameter-registry-additions.md`
- `latin-bridge.md`Latin term admission standard and full semantic entries - `simulation-clock.md``MS_PER_SIM_DAY = 3_000`
- `parameter-registry.md` — all parameters, scope, layer, maturity
- `parameter-registry-additions.md` — 44 additional tokens from corpus review
- `simulation-clock.md` — integer time constraints, `MS_PER_SIM_DAY = 3_000`
**Corpus** (`docs/training/corpus/`): **Economic calibration** (`docs/economy/`):
- 20 Layer 0 primitive facts (commerce domain) - `cost-calibration-model.md`
- 5 Layer 1 worked examples - `cost-calibration-additional-goods.md`
- 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 SVCCINUM thread ## 6. The SVCCINUM thread
The amber (`SVCCINUM`) in the grain route cargo is not merely a goods label. The amber (`SVCCINUM`) in the grain route cargo is the first explicit
It is the first explicit connection between OTIVM and CIVICVS. The amber connection between OTIVM and CIVICVS. It originated in Maglemoisian forests
originated in Maglemoisian forests in approximately 8000 BCE — the same in approximately 8000 BCE. When both simulations share a TESSERA substrate,
territory and period that CIVICVS models. When both simulations share a the amber in the MERCATOR's hold will be traceable to a specific H3 cell
TESSERA substrate, the amber in the MERCATOR's hold will be traceable to a where a CIVICVS Constructor gathered or traded it.
specific H3 cell where a CIVICVS Constructor gathered or traded it.
This thread runs through the `origin_h3_r5` provenance stub in `constants.js`, This thread runs through `origin_h3_r5` in `constants.js`, through the
through the SVCCINUM entry in `latin-bridge.md`, through the `occ_flag` stub SVCCINUM entry in `latin-bridge.md`, through `occ_flag` in the registry,
parameter in the registry, through to OTIVM-VIII and OTIVM-IX. through to OTIVM-VIII and OTIVM-IX. Do not lose it.
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 ## 7. Workflow — one file, one step, one confirmation
Every change follows this sequence without exception: 1. Claude chat produces one downloadable file
2. Human writes to disk: `cp filename src/path/filename`
1. Claude chat discusses the change and produces one downloadable file 3. If code: `npm run build` (then `pm2 restart otivm` if server or frontend)
2. Human uploads to Gitea manually, or pastes into Claude Code 4. Human runs the exact git commands provided in chat — copy-paste, no editing
3. If code: `npm run build && pm2 restart otivm` 5. Human confirms
4. Human confirms result 6. Claude chat proceeds
5. Claude chat proceeds to next step
**One file. One step. One confirmation. Never batch.** **One file. One step. One confirmation. Never batch.**
When a commit requires two files (e.g. paired .jsx and .css), both files must **Git add rule:** Always name the exact file. Never `git add .`
carry their full content in the instruction header, or the instruction must **File naming rule:** Downloaded filename = destination filename. No renaming.
include an explicit STOP — do not proceed until the human pastes the second
file. Claude Code must never generate content for a missing file.
--- ---
## 8. Hard rules ## 8. Hard rules
- Never run PM2 as root — always as otivm user - Never run PM2 as root — always as otivm user
- Never commit secrets — no tokens, no keys, no passwords - Never commit secrets
- Never push to main without building`npm run build` must pass first - Never push without building
- Per-player SQLite for player state`data/saves/{token}.sqlite3` from `data/create_player_db.sql` - Per-player SQLite for player state
- JSON saves coexist during migration — never deleted, never overwritten - JSON saves coexist — never deleted, never overwritten
- H3 IDs on every location — never a coordinate pair or string name alone - H3 IDs on every location — never a coordinate pair alone
- Never make assumptions about disk state — always read from Gitea MCP first - Never assume disk state — always read from Gitea MCP first
- Uncertainty is a first-class record, not a comment — applies to all schema work - Uncertainty is a first-class record, not a comment
- The data warehouse is the product — the game is the public interface - The data warehouse is the product — the game is the public interface
- Real weather only in CIVICVS — DWD data always, no simulation - Real weather only in CIVICVS — DWD data always
- Design one step ahead — no release planned beyond the next confirmed step - Design one step ahead
- Bootstrap is vendored and pinned — never use a CDN reference
--- ---
## 9. Commit message convention ## 9. Commit message convention
Imperative mood, present tense, under 72 characters. Imperative mood, present tense, under 72 characters.
`Add Mediterranean SVG map to Map screen` not `Added map`.
--- ---
@@ -330,16 +316,13 @@ Imperative mood, present tense, under 72 characters.
See `docs/handover-dataset.md` for full detail. Current state: See `docs/handover-dataset.md` for full detail. Current state:
- `data/otivm.sqlite3` live — 12,005 rows, `paleo_epochs` populated, FK clean - `data/otivm.sqlite3` live — 12,005 rows, `paleo_epochs` populated, FK clean
- `staging_otivm.sqlite3` in sync - Four datasets pending download (BGR IGME5000, HYDE 3.3, KK10, HydroRivers)
- Pipeline venv provisioned at `/home/otivm/pipeline-venv` - Per-H5 pipeline designed (RFC-TESSERA-4.0-001), not yet coded
- 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 When `otivm.sqlite3` is expanded with new H5 hexes, the game development
waypoint), the game development assistant will be told. The `/api/map/:h5/:epoch` assistant will be told. The `/api/map/:h5/:epoch` endpoint needs no changes.
endpoint requires no changes — it is already parameterised by H5 ID.
--- ---
*Handover 2026-05-03 — game development track* *Handover 2026-05-03 — game development track*
*Claude chat designs. Claude Code implements. The human decides.* *Claude chat designs. Claude Code implements. The human decides.*