OTIVM-III complete

This commit is contained in:
2026-05-03 05:34:52 -04:00
parent d1e1b98fa5
commit 260db3f492

View File

@@ -1,5 +1,5 @@
# Handover — OTIVM Game Development
### Date: 2026-05-02
### Date: 2026-05-03
### For: Incoming assistant (game development track)
### Read this completely before doing anything
@@ -111,14 +111,15 @@ NEVER: commit without fetching and merging first.
- 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)
- `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 player databases
- `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
## 4. Current game state — as of 2026-05-03
### OTIVM-I — complete
Five trade routes Ostia → Alexandria, journal, otium/negotium mechanic,
@@ -146,46 +147,83 @@ per-player saves via 8-char hex token, 128 concurrent players supported.
- 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
### OTIVM-III — complete and live at `d1e1b98`
**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.
**The sub-trace is live. The behavioral record is real.**
**What OTIVM-III requires — in order:**
Current HEAD: `d1e1b98`. Server startup message: `OTIVM-III complete`.
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.
**What was built, in order:**
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.
1. **Schema** (`data/create_player_db.sql`) — schema version 5. 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). `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.
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.
2. **Background selection** (`src/screens/Prologue.jsx`, `src/App.jsx`,
`src/constants.js`) — Prologue tab added as a third tab alongside Ledger
and Map. Player chooses one of six backgrounds before first dispatch.
`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.
**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
3. **Backend wiring** (`server/index.js`) — per-player SQLite live. On new
player creation, seeds `actor_parameters` from `background_starting_values`
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.
### Known deferred items
4. **Ventures and venture legs** — on `dispatch_start`, creates a `ventures`
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
change with correct trigger types:
- `dispatch_cost` — den decreases at dispatch start (cost deducted)
- `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:**
- `actor_profile.background_id` — correct canonical identifier
- `actor_parameters` — all 12 parameters seeded from `background_starting_values`
- `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):**
```javascript
const COST_VECTURA_RATIO = 0.60 // VECTVRA — freight charge
const COST_PORTORIA_RATIO = 0.25 // PORTORIUM — customs duty
// cost_other = remainder = 0.15 // horreum, incidentals
```
**Known deferred items from OTIVM-III:**
- Cost model: 60/25/15 split is a placeholder. A real model based on route
distance, cargo type, and epoch should be designed before OTIVM-IV touches
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 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.
- 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
Per the roadmap: **The Seasons** — dispatches take real hours, weather affects
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
`docs/archives.md`.
---
@@ -213,6 +251,7 @@ The following documents are the design substrate for OTIVM-III and beyond.
- `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
- `simulation-clock.md` — integer time constraints, `MS_PER_SIM_DAY = 3_000`
**Corpus** (`docs/training/corpus/`):
- 20 Layer 0 primitive facts (commerce domain)
@@ -226,9 +265,9 @@ The following documents are the design substrate for OTIVM-III and beyond.
---
## 6. The SVCCINVM thread
## 6. The SVCCINUM thread
The amber (`SVCCINVM`) in the grain route cargo is not merely a goods label.
The amber (`SVCCINUM`) 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
@@ -236,7 +275,7 @@ 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
through the SVCCINUM 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
@@ -256,6 +295,11 @@ Every change follows this sequence without exception:
**One file. One step. One confirmation. Never batch.**
When a commit requires two files (e.g. paired .jsx and .css), both files must
carry their full content in the instruction header, or the instruction must
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
@@ -297,5 +341,5 @@ endpoint requires no changes — it is already parameterised by H5 ID.
---
*Handover 2026-05-02 — game development track*
*Handover 2026-05-03 — game development track*
*Claude chat designs. Claude Code implements. The human decides.*