From 915f0a285e5bbf82491f80cf1f7884130f142151 Mon Sep 17 00:00:00 2001 From: TheRON Date: Wed, 6 May 2026 12:56:06 -0400 Subject: [PATCH] docs: add OTIVM-V roadmap --- docs/Roadmap-OTIVM-V.md | 353 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 353 insertions(+) create mode 100644 docs/Roadmap-OTIVM-V.md diff --git a/docs/Roadmap-OTIVM-V.md b/docs/Roadmap-OTIVM-V.md new file mode 100644 index 0000000..e088ee0 --- /dev/null +++ b/docs/Roadmap-OTIVM-V.md @@ -0,0 +1,353 @@ +# OTIVM-V — Roadmap +### Date: 2026-05-03 +### Status: DRAFT — awaiting project owner approval before any code is written +### Supersedes: nothing — OTIVM-IV is complete at Gitea HEAD 3700f5a + +--- + +## 0. What OTIVM-V is, in one sentence + +OTIVM-V makes goods real: the merchant holds physical inventory, transforms +raw goods into finished goods, barters goods for goods, and the Simulator +can read every transaction from the behavioral record. + +--- + +## 1. Governing constraints — gates, not preferences + +**No schema change to `data/create_player_db.sql` without explicit project +owner instruction.** All goods mechanics are expressed through existing +tables: `ventures`, `venture_legs`, `parameter_drift_log`, `events`. + +**No artificial values.** Every constant is sourced from the calibration +documents or marked LOW confidence with a named revision trigger. The Market +will balance against real equations. Placeholders that cannot survive Market +pressure are not placeholders — they are errors deferred. + +**JSON `delta_note` on every `exchange_complete` entry.** The +`parameter_drift_log.delta_note` column is TEXT and holds a JSON object +today without schema change. CT 1103 (aggregation / Market) parses this +JSON when it reads player databases. The player UI renders selected fields +as human-readable text. Consistency with `events.payload` is mandatory. + +**CT 1103 is not constrained to SQLite.** The Market database may be +PostgreSQL, MySQL, or any engine that serves the aggregation workload. +The API boundary between CT 1105 and CT 1103 is REST over WireGuard — +what sits behind that endpoint is CT 1103's internal decision. OTIVM-V +does not touch CT 1103. It produces records that CT 1103 can read. + +**The shell architecture is unchanged.** `Shell.jsx` and `Section.jsx` +are built once. One new section type (`goods-list`) is added to +`Section.jsx` only. No other shell changes. + +**One file. One step. One confirmation. Never batch.** + +--- + +## 2. What OTIVM-V builds + +### 2.1 — Transformation route: grain→bread + +The merchant dispatches the grain route (Brundisium → Carthago) with grain +cargo. At destination, instead of receiving raw coin profit, he contracts a +transformation: a baker converts the grain to bread at an agreed ratio. The +merchant receives bread as a tradeable good. He then sells the bread on the +next otium cycle or on a subsequent route. + +**Transformation mechanics:** +- The dispatch and venture mechanics are unchanged. The merchant still + dispatches the grain route and waits for completion. +- On venture completion, instead of (or in addition to) the standard + `venture_complete` coin delta, a transformation may be applied if the + player selected a transformation route. +- The transformation is recorded as `trigger_type = 'exchange_complete'` + in `parameter_drift_log`. +- The coin-equivalent delta (bread value minus grain value minus baker fee) + is applied to `liquiditas`. +- The goods-on-hand state is derived from these records — no new table. + +**Transformation constants** (to be added to `src/constants.js` and +documented in `docs/economy/otivm_v_transformation_goods.md`): + +```javascript +// Grain → Bread transformation +// Source: docs/economy/otivm_v_transformation_goods.md +// Confidence: LOW — placeholder pending Market price signals +// Revision trigger: when CT 1103 provides real destination bread prices +const GRAIN_BREAD_TRANSFORMATION_RATIO = 1.15 // bread coin-value / grain coin-value at destination +const GRAIN_BREAD_BAKER_FEE_DN = 3.00 // per 100 modii, baker's transformation fee +// Net delta on 100 modii grain route: +// revenue_grain = 75.00 dn (GRAIN_DEST_WHOLESALE_100_DN) +// bread_value = 75.00 * 1.15 = 86.25 dn +// baker_fee = 3.00 dn +// net_delta = 86.25 - 75.00 - 3.00 = +8.25 dn above raw grain return +// Confidence: LOW. This is economically implausible at scale — the baker +// captures the real margin. Revision required when annona pressure and +// destination scarcity signals are available from the Market. +``` + +**Structured `delta_note` for grain→bread `exchange_complete`:** + +```json +{ + "event": "transformation", + "good_input": "grain", + "good_input_pattern": "bulk_staple", + "quantity_input_unit": "modius", + "quantity_input": 100, + "good_output": "bread", + "good_output_pattern": "bulk_staple", + "quantity_output_unit": "modius_equivalent", + "quantity_output_coin_dn": 86.25, + "baker_fee_dn": 3.00, + "transformation_ratio": 1.15, + "coin_delta_dn": 8.25, + "route": "grain", + "origin_h3": "851e8ba3fffffff", + "destination_h3": "853386e23fffffff", + "acquisition_ts": "" +} +``` + +### 2.2 — Barter: grain for garum at Carthago + +The merchant arrives at Carthago with grain. A counterparty holds garum. +No coin moves. The merchant surrenders grain and receives garum at an agreed +ratio. Both goods change hands. The coin-equivalent spread is the delta. + +**Barter mechanics:** +- Same `exchange_complete` trigger type as transformation. +- Coin-equivalent delta: value of garum received minus value of grain + surrendered at calibration-document price anchors. +- Applied to `liquiditas` as a signed delta. +- Base exchange ratio: 50 modii grain : 4 amphorae garum (LOW confidence). +- Coin equivalent: 50 modii grain at 0.75 dn/modius = 37.50 dn. + 4 amphorae garum at 9.00 dn/amphora wholesale = 36.00 dn. + Delta: −1.50 dn. The merchant accepts a slight loss for liquidity — + he holds a more portable, higher-margin good. + +**Structured `delta_note` for barter `exchange_complete`:** + +```json +{ + "event": "barter", + "good_given": "grain", + "good_given_pattern": "bulk_staple", + "quantity_given_unit": "modius", + "quantity_given": 50, + "quantity_given_coin_dn": 37.50, + "good_received": "garum", + "good_received_pattern": "perishable_batch", + "quantity_received_unit": "amphora", + "quantity_received": 4, + "quantity_received_coin_dn": 36.00, + "coin_delta_dn": -1.50, + "exchange_ratio_note": "50 modii grain : 4 amphorae garum", + "route": "grain", + "location_h3": "853386e23fffffff", + "acquisition_ts": "" +} +``` + +### 2.3 — Goods-on-hand panel in ACTOR context + +A new panel appears in the right column of the ACTOR context, between +"Periodic obligations" and "Drift log". Title: "Goods on hand". + +The panel shows the merchant's current physical inventory derived from +completed venture records and open `exchange_complete` events. It is a +derived view — no new table, no new parameter token. + +**What the panel shows per good held:** + +| Field | Source | Purpose | +|---|---|---| +| Good type | `delta_note.good_output` or `delta_note.good_received` | Player reads | +| Pattern | `delta_note.good_output_pattern` | CT 1103 reads | +| Quantity | derived from delta events | Player reads | +| Unit | `delta_note.quantity_output_unit` | Both read | +| Origin route | `delta_note.route` | CT 1103 reads | +| Origin H3 | `delta_note.origin_h3` | CT 1103 reads | +| Acquired at | `delta_note.acquisition_ts` | CT 1103 reads | +| Coin equivalent | derived from calibration constants | Player reads | + +**What the panel does NOT show:** +- Any field not derivable from existing records. +- Speculative future prices. +- Market-side data (CT 1103 is not live in OTIVM-V). + +**New section type:** `goods-list` added to `Section.jsx`. This is the +only change to the shell components. + +--- + +## 3. Known architectural debt — named, not hidden + +**No materialized inventory table.** Current holdings are reconstructed by +replaying `parameter_drift_log` exchange events. For a single player this +is fast. When CT 1103 reads 127 player databases on a polling schedule, this +becomes expensive if holdings are complex. + +The correct solution — when the Market goes live — is an `actor_inventory` +table in the player schema: one row per good held, updated by the game server +on every `exchange_complete` event. That is a schema version 6 change, +justified by the Market requirement, made at the release when CT 1103 goes +live. Not now. + +This debt is recorded here so the decision is deliberate. + +--- + +## 4. What OTIVM-V explicitly does not include + +- CT 1103 implementation — deferred +- The Roman Market itself — deferred +- Real destination price signals — deferred (Market provides these) +- New waypoints or map expansion — blocked on per-H5 pipeline +- Weather integration — blocked on restoration layer +- The Factor (NPC model) — deferred +- Scenario triggers — deferred +- Quality grade multipliers (garum luxury tier, fine vs common) — deferred +- Commission route pattern (marble) — deferred +- Any changes to the TESSERA map endpoint — unchanged +- H3 hex geometry on the map — deferred pending h3-js +- `actor_inventory` materialized table — deferred to Market release + +--- + +## 5. New calibration document + +`docs/economy/otivm_v_transformation_goods.md` — documents the grain→bread +transformation ratio and barter exchange rates as LOW confidence placeholders, +with explicit revision triggers keyed to Market price signal availability. +This document follows the same method as the existing calibration documents: +source-backed anchors where possible, explicit calibration flags where not. + +--- + +## 6. File inventory — complete and authoritative + +### Files added (new) + +| File | Purpose | +|---|---| +| `docs/economy/otivm_v_transformation_goods.md` | Calibration document for transformation and barter constants | +| `docs/Roadmap-OTIVM-V.md` | This document | + +### Files modified (existing) + +| File | What changes | +|---|---| +| `src/constants.js` | Transformation ratio constants, baker fee, barter ratio constants added | +| `src/config/context-actor.json` | New `goods-list` section added to right column between obligations and drift log | +| `src/components/Section.jsx` | New `goods-list` panel type added | +| `src/screens/Actor.jsx` | Goods-on-hand data constructed and passed to Section | +| `src/screens/Forum.jsx` | Transformation and barter options added to route dispatch UI | +| `server/index.js` | `exchange_complete` handler added — writes structured JSON `delta_note`; goods-on-hand read endpoint added; server startup message updated to OTIVM-V | + +### Files not touched + +| File | Reason | +|---|---| +| `src/components/Shell.jsx` | Shell is built once — no changes | +| `src/screens/Map.jsx` | No map changes in OTIVM-V | +| `src/gameState.js` | Game state shape unchanged | +| `src/api.js` | API calls unchanged | +| `data/create_player_db.sql` | Schema unchanged — no modification without project owner instruction | +| `data/create_otivm_db.sql` | World schema unchanged | +| All TESSERA-related server code | Unchanged | +| `src/config/context-forum.json` | Forum layout JSON unchanged — Forum.jsx handles transformation/barter directly | +| `src/config/context-map.json` | Unchanged | +| `src/config/contexts.json` | No new contexts in OTIVM-V | + +--- + +## 7. Implementation sequence + +One file. One step. One confirmation. In this order: + +**Step 1 — Calibration document** +`docs/economy/otivm_v_transformation_goods.md` +No rebuild needed. Commit and confirm before proceeding. + +**Step 2 — Constants** +`src/constants.js` — transformation and barter constants added. +No rebuild needed for constants alone, but confirm file is committed. + +**Step 3 — Section shell extension** +`src/components/Section.jsx` — `goods-list` panel type added. +This is the only shell change. Build and confirm renders before proceeding. + +**Step 4 — Context config** +`src/config/context-actor.json` — `goods-list` section added to right +column. No rebuild needed for JSON alone. Confirm file is committed. + +**Step 5 — Actor screen** +`src/screens/Actor.jsx` — goods-on-hand data construction added. +Build and confirm goods panel renders with placeholder data. + +**Step 6 — Server** +`server/index.js` — `exchange_complete` handler, JSON `delta_note` writes, +goods-on-hand read endpoint, startup message updated to OTIVM-V. +`pm2 restart otivm` required. No npm build needed for server changes alone. + +**Step 7 — Forum screen** +`src/screens/Forum.jsx` — transformation and barter route options added +to dispatch UI. Build and confirm full cycle: dispatch → transformation → +goods panel updates → barter available. + +**Step 8 — Verify** +Play a full cycle: dispatch grain route with transformation selected → +verify `exchange_complete` entry in `parameter_drift_log` with correct JSON +`delta_note` → verify goods panel shows bread held → trigger barter → +verify second `exchange_complete` entry → verify goods panel updates. +Inspect player SQLite directly to confirm records are CT 1103-readable. + +**Step 9 — Roadmap document** +`docs/Roadmap-OTIVM-V.md` — commit the approved version of this document. + +--- + +## 8. Before OTIVM-V development begins + +Per `CLAUDE.md` and the handover document: + +**Take a backup before any OTIVM-V code is written.** + +```bash +vzdump 1105 --compress zstd --storage local --mode snapshot +``` + +Run on srv-a as root. Document immediately in `docs/archives.md`. +A backup for OTIVM-IV completion already exists at +`vzdump-lxc-1105-2026_05_03-14_08_13.tar.zst`. Take a second backup +at the start of OTIVM-V work to capture any player data accumulated +between the two sessions. + +--- + +## 9. Market architectural constraints — do not violate + +These constraints govern every implementation decision in OTIVM-V, even +though the Market itself is not built here: + +1. Every `exchange_complete` entry in `parameter_drift_log` writes a + structured JSON object as `delta_note`. This is the Market's read + target. A human-readable string is not acceptable. + +2. `observable_level` on every `actor_parameters` row is the Market + visibility gate. Goods derived from `exchange_complete` events inherit + the `observable_level` of the `liquiditas` parameter they modify. + +3. `value_true` is always server ground truth. `value_perceived` is what + the actor's ledger shows. Never conflate. Goods-on-hand is derived from + `value_true` — the server knows what the merchant actually holds. + +4. The API boundary between CT 1105 and CT 1103 is REST over WireGuard. + CT 1103's internal database engine is CT 1103's decision. OTIVM-V + writes clean records. CT 1103 reads them. + +--- + +*OTIVM-V Roadmap — draft 2026-05-03* +*Claude chat designs. Claude Code implements. The human decides.*