18 KiB
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:
-
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.
-
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_perceivedband andconfidence_tag - Parameters where
value_true ≠ value_perceivedare visually flagged - Auctoritas in three faces:
value_true,value_perceived,value_social liquiditaswith 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 wagescost-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_logwithtrigger_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:
-
Current route margins (grain at 67%) are early-game abstraction. They will need revision when real goods economics are implemented in full.
-
Grain private trade margin under annona pressure is approximately 10.8% — much lower than current game abstraction.
-
Commission pattern (marble) requires
commission_modeflag and distinct route handling — deferred to a future release. -
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.jsTESSERA 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 layoutotivm-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:
-
observable_levelon everyactor_parametersrow is the Market visibility gate. Set it correctly from the start.full= Market can read.partial= Market sees band only.hidden= Market cannot see. -
value_trueis always server ground truth.value_perceivedis always what the actor's ledger shows. Never conflate them. Never store only one. -
Every event written to
parameter_drift_logwill 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.