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

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:

  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.