# 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.*