Files
otivm/docs/Roadmap-OTIVM-IV.md
2026-05-03 10:12:28 -04:00

502 lines
18 KiB
Markdown

# OTIVM-IV — Roadmap
### Date: 2026-05-03
### Status: APPROVED — implementation begins after this document is committed
### Supersedes: roadmap-OTIVM-IV-draft.md
---
## 0. What OTIVM-IV is, in one sentence
OTIVM-IV replaces the idler interface with a situation instrument:
a screen that shows the merchant's full economic and social state,
structured costs, active decisions, and transformation economics —
the first thing a Simulator participant would recognise as their
working environment.
---
## 1. Why the roadmap definition changed
The original roadmap defined OTIVM-IV as "The Seasons" — real
dispatch durations, DWD weather, route closures. That definition
is superseded by two decisions:
1. Weather from Berlin projected onto the Roman Mediterranean is not
a meaningful signal until the restoration layer (HYDE 3.3 + KK10)
and route corridor H5 hexes exist. Weather belongs in a later
release.
2. The game is evolving toward the Simulator, not toward a richer
idler. The interface must evolve with it.
OTIVM-IV therefore covers: interface architecture, economic model,
transformation routes, and barter mechanics. The roadmap's Section 2
narrative for OTIVM-IV is superseded. Sections 1, 3, and 5 are
unchanged.
---
## 2. Governing constraints — gates, not preferences
**No throw-away code.** Every component, route, and data structure
built in OTIVM-IV must be legible from the Simulator. If it would
not exist in the Simulator interface, it does not get built now.
**File growth control.** Before any new file is created: can this
live inside an existing file? Consolidation is preferred over
addition. The JSON configuration pattern is the primary tool for
controlling file growth — screens are data, not code.
**Vendored dependencies.** No CDN references. Every library is
pinned to a specific version, installed via npm with a fixed version
string. The build must be reproducible from `npm install` alone.
- Bootstrap 5.3.3 (MIT — local copy permitted)
- Bootstrap Icons 1.11.3 (MIT — local copy permitted)
**Painstaking precision.** This document is the gate. No file is
touched that is not named in Section 7. No feature is built that
is not specified here. Design is complete before implementation
begins.
**One file. One step. One confirmation.** Every change follows this
sequence without exception. When a commit requires two files, both
must be fully specified in the instruction header before Claude Code
touches anything.
---
## 3. The shell architecture
The central architectural decision of OTIVM-IV is the separation
of structure from content. The shell is built once and never changes.
Content is driven by JSON configuration files committed to the repo.
### The shell
The shell consists of three components written once:
**`Shell.jsx`** — the persistent sidebar containing the application
title, the context dropdown, and the save token. The dropdown reads
`src/config/contexts.json`. Selecting a context loads the
corresponding `context-{id}.json`, applies the specified layout
grid, and renders the appropriate screen component. The sidebar
never grows — new contexts appear in the dropdown automatically.
**`Section.jsx`** — a generic panel renderer. It receives a section
definition from the context JSON and renders the appropriate
sub-component based on `type`. It does not know what it is showing.
**`contexts.json`** — the dropdown definition. One entry per
context. Each entry names the context, its layout type, and its
sub-items. Adding a new context in a future release requires one
new JSON file and one thin screen file — nothing else changes.
### The layout types
Four layout types, specified in context JSON, applied by Shell.jsx:
| Layout | Grid | Use |
|---|---|---|
| `single` | one full-width column | simple reference screens |
| `two-col` | 40% left + 60% right | decision screens |
| `three-col` | 25% + 50% + 25% | dense instrument screens |
| `map` | 30% sidebar + 70% canvas | map context |
### The section types
Section.jsx renders one panel. Type determines sub-component:
| Type | Renders |
|---|---|
| `parameter-list` | actor_parameters rows |
| `cost-table` | cost items with source citations |
| `drift-log` | parameter_drift_log entries |
| `status-block` | key/value status pairs |
| `action-bar` | action buttons |
| `route-list` | trade route cards with cost breakdowns |
| `map-canvas` | TESSERA fog-of-war map |
| `text-block` | narrative text, collapsible |
New section types are added by extending Section.jsx only — no
shell changes required.
### Why this controls file growth
A session that adds a new context touches exactly two files:
`src/config/context-X.json` and `src/screens/X.jsx`. The shell,
the server, the existing contexts — untouched. The screen file is
thin because it delegates all rendering to Section.jsx. The JSON
file is not code and does not need to be debugged.
---
## 4. The three contexts
### ACTOR
*Who am I and where do I stand?*
Layout: `three-col`
The Simulator's Constructor profile in Roman dress. Shows:
- Background identity (from `actor_profile.background_id`)
- Twelve parameters with `value_perceived` band and `confidence_tag`
- Parameters where `value_true ≠ value_perceived` are visually flagged
- Auctoritas in three faces: `value_true`, `value_perceived`,
`value_social`
- `liquiditas` with structured breakdown: available, committed,
next otium cost
- Officia burden prominently shown
- Recent drift log entries
The ACTOR context replaces the Prologue tab. Once a background is
chosen, the background selection UI appears within the ACTOR context
(`background_id = null` state). After selection, the ACTOR context
shows the read-only instrument view permanently.
### FORUM
*What decisions are in front of me?*
Layout: `two-col`
The decision surface. Shows:
- Active venture status (route, cargo, leg, elapsed sim days,
expected return) — a dispatch record, not a progress bar
- Trade routes with full cost breakdown visible:
vectura / portoria / other / revenue / net
- Transformation routes (new in OTIVM-IV): routes where the
merchant ships a raw good and receives a transformed good
- Expenditure decisions: periodic costs debited per otium cycle
- Otium shown as a deliberate investment, not a rest button
- Journal as a collapsible panel within FORUM, not a separate screen
### MAP
*Where have I been?*
Layout: `map`
Unchanged in function from OTIVM-III. The fog-of-war SVG map
renders from TESSERA H7 data via `/api/map/:h5/:epoch`. The MAP
context is a thin wrapper around the existing `Map.jsx` component.
No map code changes in OTIVM-IV.
---
## 5. The economic model
### Foundation documents
Two calibration documents are committed to `docs/economy/`:
- `cost-calibration-model.md` — ceramic cup baseline, periodic costs,
reference wages
- `cost-calibration-additional-goods.md` — garum, grain, amber,
marble capital
These are the permanent calibration substrate. All cost constants
derive from them.
### Five good patterns
Every good in OTIVM is one of five patterns:
| Pattern | Example | Core equation |
|---|---|---|
| `batch_craft` | Ceramic cup | raw + labour + kiln + overhead + market |
| `perishable_batch` | Garum | raw + salt + vessel + time + spoilage + quality |
| `bulk_staple` | Grain | origin + freight + storage + loss + low margin |
| `import_luxury` | Amber | acquisition + risk + information asymmetry + markup |
| `commission_heavy` | Marble capital | block + labour + heavy transport + agent fee + risk |
### Periodic operating costs — implemented in OTIVM-IV
Three named trigger types, debited per otium cycle:
```
OTIUM_ACCESS_FEE_DN = 2.00 // otium_access_fee trigger
PERSONAL_MAINTENANCE_DN = 4.00 // personal_maintenance trigger
OFFICIA_OBLIGATION_DN = 2.00 // officia_obligation trigger
OTIUM_CYCLE_TOTAL_DN = 8.00
```
Each writes a separate `parameter_drift_log` row with its own
`trigger_type`. The 8 dn total is preserved from the existing
model; it is now decomposed into citable components.
### Route cost split — already live, made visible in OTIVM-IV
```
COST_VECTURA_RATIO = 0.60 // VECTVRA — freight charge
COST_PORTORIA_RATIO = 0.25 // PORTORIUM — customs duty
// cost_other = 0.15 // horreum, incidentals
PORTORIA_RATE = 0.025 // ad valorem default
```
These values are already recorded in `venture_legs`. OTIVM-IV
makes them visible to the player in the FORUM route cards.
### Labour multipliers — for future goods implementation
```
LABOUR_MULTIPLIER_UNSKILLED = 1.00 // 0.50 dn/day
LABOUR_MULTIPLIER_SKILLED_STANDARD = 1.00 // 1.00 dn/day
LABOUR_MULTIPLIER_SPECIALIST_FOOD = 1.20 // garum maker
LABOUR_MULTIPLIER_STONECUTTER = 2.00
LABOUR_MULTIPLIER_SCULPTOR_DETAIL = 2.50
```
### Transformation routes — new in OTIVM-IV
The merchant can ship a raw good and receive a transformed good
at destination. Examples: grain → bread, raw clay → vessels,
raw wool → cloth.
Mechanics:
- Transformation ratio is a LOW confidence placeholder constant
(same pattern as spoilage rates in calibration documents)
- Goods-on-hand are represented as a coin-equivalent delta in
`liquiditas` — no new table, no new parameter
- Transformation is recorded in `parameter_drift_log` with
`trigger_type = 'exchange_complete'`
- The drift log entry records: input good, output good,
ratio applied, coin-equivalent delta, and route label
This keeps the schema unchanged while making the transformation
economically visible in the sub-trace.
### Barter — new in OTIVM-IV
The merchant can exchange goods directly for other goods at an
agreed ratio. No coin moves. The mechanism is identical to
transformation: coin-equivalent delta applied to `liquiditas`,
`exchange_complete` trigger type in drift log.
### The Market — architectural constraints (deferred)
The Market will periodically read player databases to derive
supply and demand and set prices. This is the cooperative
simulation layer. Implementation is deferred but the architectural
constraints must not be violated:
**What the Market can read:** `value_perceived` and parameters
with `observable_level = 'full'` or `'partial'`.
**What the Market cannot read:** parameters with
`observable_level = 'hidden'`. This is the deception handle —
a merchant can mark a shipment as hidden and it does not appear
in Market aggregation.
**Ledger fraud:** `value_true ≠ value_perceived` is the second
deception handle. The merchant's ledger shows `value_perceived`.
The Market reads `value_perceived`. `value_true` is the server's
ground truth. A sunk shipment entered as delivered has
`value_perceived = delivered`, `value_true = lost`.
Both deception patterns are already supported by the schema.
No schema changes are needed when the Market is built.
### Known calibration flags
From the cross-good calibration notes:
1. Current route margins (grain at 67%) are early-game abstraction.
They will need revision when real goods economics are implemented
in full.
2. Grain private trade margin under annona pressure is approximately
10.8% — much lower than current game abstraction.
3. Commission pattern (marble) requires `commission_mode` flag and
distinct route handling — deferred to a future release.
4. Quality grade multiplier needed for garum and similar goods —
deferred to a future release.
---
## 6. What OTIVM-IV explicitly does not include
- DWD weather integration — blocked, see Section 1
- New trade routes or waypoints — blocked on per-H5 pipeline
- The Factor (NPC model) — deferred
- Scenario triggers — deferred
- Ranking or achievements — explicitly deferred in SIMULATOR-vision.md
- H3 hex geometry on the map — deferred pending client-side h3-js
- Real-time dispatch durations (hours not seconds) — deferred
- Market reader implementation — deferred (constraints documented)
- Commission route pattern — deferred
- Quality grade multiplier — deferred
- Any changes to `data/create_player_db.sql` — schema is correct,
do not alter without project owner instruction
- Any changes to `data/create_otivm_db.sql` — world schema unchanged
- Any changes to `server/index.js` TESSERA map endpoint
---
## 7. File inventory — complete and authoritative
### Files added (new)
| File | Purpose |
|---|---|
| `src/config/contexts.json` | Dropdown definition — what contexts exist |
| `src/config/context-actor.json` | ACTOR layout, sections, labels |
| `src/config/context-forum.json` | FORUM layout, sections, labels |
| `src/config/context-map.json` | MAP layout |
| `src/components/Shell.jsx` | Sidebar + dropdown + layout grid — built once |
| `src/components/Section.jsx` | Generic panel renderer — built once |
| `src/components/ParameterRow.jsx` | Renders one parameter from actor_parameters |
| `src/components/CostRow.jsx` | Renders one cost line |
| `src/components/DriftEntry.jsx` | Renders one drift log entry |
| `src/screens/Actor.jsx` | ACTOR context — thin, reads context-actor.json |
| `src/screens/Forum.jsx` | FORUM context — thin, reads context-forum.json |
### Files modified (existing)
| File | What changes |
|---|---|
| `src/App.jsx` | Shell replaces current tab navigation. Three contexts wired. Expenditure logic added. Background selection state moved to ACTOR context. |
| `src/App.css` | Reduced to project-specific overrides only. Bootstrap handles layout. Roman palette CSS variables retained and extended. |
| `src/constants.js` | Expenditure constants added. Transformation ratio placeholders added. Labour multipliers added. |
| `server/index.js` | Periodic expenditure debit logic added. Three new trigger_type values: `otium_access_fee`, `personal_maintenance`, `officia_obligation`. `exchange_complete` trigger type for transformation and barter. |
| `package.json` | Bootstrap 5.3.3 and Bootstrap Icons 1.11.3 added as pinned dependencies. |
### Files retired (to be deleted)
| File | Reason |
|---|---|
| `src/screens/Prologue.jsx` | ACTOR context absorbs both selection UI and read-only summary. One context per function. |
| `src/screens/Ledger.jsx` | Replaced by Forum.jsx. Dispatch logic migrated. |
### Files not touched
| File | Reason |
|---|---|
| `src/screens/Map.jsx` | No map changes in OTIVM-IV |
| `src/gameState.js` | Game state shape unchanged |
| `src/api.js` | API calls unchanged |
| `data/create_player_db.sql` | Schema correct, do not alter |
| `data/create_otivm_db.sql` | World schema unchanged |
| `data/repair_player_db_fk.sql` | Repair script, unchanged |
| All `docs/` files | Documentation unchanged except this file |
---
## 8. Implementation sequence
One file, one step, one confirmation. In this order:
**Step 1 — Dependencies**
`package.json` — add Bootstrap 5.3.3 and Bootstrap Icons 1.11.3.
Confirm `npm install` and build pass before proceeding.
**Step 2 — CSS foundation**
`src/App.css` — reduce to project overrides. Bootstrap imported.
Roman palette as CSS custom properties. Build and confirm.
**Step 3 — Shell components**
`src/components/Shell.jsx` — sidebar, dropdown, layout grid.
`src/components/Section.jsx` — generic panel renderer.
These two files are the foundation. Nothing else is built until
they render correctly with placeholder content.
Two files, one commit.
**Step 4 — Context configuration**
`src/config/contexts.json`
`src/config/context-actor.json`
`src/config/context-forum.json`
`src/config/context-map.json`
Four files, one commit. No rebuild needed after this step —
JSON only. Confirm files are present in repo before proceeding.
**Step 5 — Sub-components**
`src/components/ParameterRow.jsx`
`src/components/CostRow.jsx`
`src/components/DriftEntry.jsx`
Three files, one commit.
**Step 6 — Screen files**
`src/screens/Actor.jsx`
`src/screens/Forum.jsx`
Two files, one commit.
**Step 7 — App.jsx**
`src/App.jsx` — Shell replaces tab navigation. Three contexts
wired. Expenditure logic added.
One file, one commit.
**Step 8 — Server**
`server/index.js` — periodic expenditure debit logic. New
trigger types. Exchange_complete for transformation and barter.
One file, one commit. pm2 restart required.
**Step 9 — Retire old files**
Delete `src/screens/Prologue.jsx` and `src/screens/Ledger.jsx`.
Confirm build passes without them.
One commit.
**Step 10 — Verify**
Play a full game cycle. Inspect database. Confirm all three
trigger types appear in parameter_drift_log. Confirm ACTOR,
FORUM, and MAP contexts render correctly. Confirm background
selection still works for new players.
---
## 9. Mockup reference
Two mockup files were produced during design and are available
for reference. They are not committed to the repo — design
artefacts only:
- `otivm-iv-mockup.html` — first mockup, three-tab layout
- `otivm-iv-architecture-mockup.html` — shell architecture mockup
with dropdown, variable layouts, and embedded ChatGPT brief
The architecture mockup is the definitive visual reference for
the shell. The CONTEXT_CONFIG object in that file is the direct
source for the four context JSON files in Step 4.
---
## 10. Economic calibration reference
All cost constants derive from two committed documents:
```
docs/economy/cost-calibration-model.md
docs/economy/cost-calibration-additional-goods.md
```
Do not invent cost values. Do not change cost values without
updating the calibration documents and noting the source and
confidence level. Every constant in `src/constants.js` that
relates to economics must have a corresponding entry in the
calibration documents.
---
## 11. Market architectural constraints — do not violate
Even though the Market is deferred, these constraints govern
every implementation decision in OTIVM-IV:
1. `observable_level` on every `actor_parameters` row is the
Market visibility gate. Set it correctly from the start.
`full` = Market can read. `partial` = Market sees band only.
`hidden` = Market cannot see.
2. `value_true` is always server ground truth.
`value_perceived` is always what the actor's ledger shows.
Never conflate them. Never store only one.
3. Every event written to `parameter_drift_log` will eventually
be readable by the Market. Write it as if the Market is
already watching. The trigger_type and delta_note must be
meaningful to an external reader, not just to the game.
---
*OTIVM-IV Roadmap — approved 2026-05-03*
*Calibration documents committed to docs/economy/.*
*Mockups produced and available for reference.*
*Claude chat designs. Claude Code implements. The human decides.*