From cebcb8ad333d04fff279d89a3870ae03a4be9310 Mon Sep 17 00:00:00 2001 From: Jan Petykiewicz Date: Fri, 17 Apr 2026 12:02:59 -0700 Subject: [PATCH] Rehost cargo selector analysis surfaces --- README.md | 5 +- .../rt3-1.06/economy-cargo-sources.json | 2069 +++++++++++++++++ crates/rrt-cli/src/main.rs | 10 +- crates/rrt-runtime/src/economy.rs | 324 ++- crates/rrt-runtime/src/lib.rs | 6 +- docs/README.md | 6 +- docs/runtime-rehost-plan.md | 6 +- 7 files changed, 2414 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 84b24f3..0e24950 100644 --- a/README.md +++ b/README.md @@ -67,8 +67,9 @@ corpus has `41`, so neither static set closes the `71`-row named price strip on offline cargo-source inspector now pushes that groundwork further in rehosted code: the checked-in `artifacts/exports/rt3-1.06/economy-cargo-sources.json` report parses both `CargoTypes` and the `Cargo106.PK4` `cargoSkin` descriptors, normalizes localized `~####Name` tokens into visible -names, and shows that the current 1.06 visible-name union is `80`, not `71`, so source recovery -alone still does not prove the live price-selector ordering. The +names, builds a merged live cargo registry, and derives an exact named cargo-production selector +from the checked-in bindings. It also shows that the current 1.06 visible-name union is `80`, not +`71`, so source recovery alone still does not prove the live price-selector ordering. The add-building strip `503..519` is now explicitly classified as recovered shell-owned descriptor parity rather than generic unresolved residue. The first grounded condition-side unlock now exists for negative-sentinel `raw_condition_id = -1` company scopes, and diff --git a/artifacts/exports/rt3-1.06/economy-cargo-sources.json b/artifacts/exports/rt3-1.06/economy-cargo-sources.json index 8b46807..95f6100 100644 --- a/artifacts/exports/rt3-1.06/economy-cargo-sources.json +++ b/artifacts/exports/rt3-1.06/economy-cargo-sources.json @@ -50,6 +50,2075 @@ "Wine", "Wire" ], + "live_registry_count": 80, + "live_registry_entries": [ + { + "visible_name": "Alcohol", + "raw_names": [ + "Alcohol" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Aluminum", + "raw_names": [ + "Aluminum" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Ammunition", + "raw_names": [ + "Ammunition" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Automobiles", + "raw_names": [ + "Automobiles" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Bauxite", + "raw_names": [ + "Bauxite" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Beer", + "raw_names": [ + "~4459Beer" + ], + "localized_string_ids": [ + 4459 + ], + "source_kinds": [ + "cargo_skin" + ] + }, + { + "visible_name": "Candidates", + "raw_names": [ + "~4464Candidates" + ], + "localized_string_ids": [ + 4464 + ], + "source_kinds": [ + "cargo_skin" + ] + }, + { + "visible_name": "Ceramics", + "raw_names": [ + "~4465Ceramics" + ], + "localized_string_ids": [ + 4465 + ], + "source_kinds": [ + "cargo_types" + ] + }, + { + "visible_name": "Cheese", + "raw_names": [ + "Cheese" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Chemicals", + "raw_names": [ + "Chemicals" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "China", + "raw_names": [ + "~4466China" + ], + "localized_string_ids": [ + 4466 + ], + "source_kinds": [ + "cargo_skin" + ] + }, + { + "visible_name": "Clothing", + "raw_names": [ + "Clothing" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Coal", + "raw_names": [ + "Coal" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Coffee", + "raw_names": [ + "Coffee" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Concrete", + "raw_names": [ + "~4467Concrete" + ], + "localized_string_ids": [ + 4467 + ], + "source_kinds": [ + "cargo_types" + ] + }, + { + "visible_name": "Containers", + "raw_names": [ + "~4468Containers" + ], + "localized_string_ids": [ + 4468 + ], + "source_kinds": [ + "cargo_skin" + ] + }, + { + "visible_name": "Corn", + "raw_names": [ + "Corn" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Cotton", + "raw_names": [ + "Cotton" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Crystals", + "raw_names": [ + "~4469Crystals" + ], + "localized_string_ids": [ + 4469 + ], + "source_kinds": [ + "cargo_types" + ] + }, + { + "visible_name": "Detergents", + "raw_names": [ + "~4471Detergents" + ], + "localized_string_ids": [ + 4471 + ], + "source_kinds": [ + "cargo_skin" + ] + }, + { + "visible_name": "Deuterium", + "raw_names": [ + "~4472Deuterium" + ], + "localized_string_ids": [ + 4472 + ], + "source_kinds": [ + "cargo_skin" + ] + }, + { + "visible_name": "Diesel", + "raw_names": [ + "Diesel" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Dye", + "raw_names": [ + "~4475Dye" + ], + "localized_string_ids": [ + 4475 + ], + "source_kinds": [ + "cargo_types" + ] + }, + { + "visible_name": "Electronics", + "raw_names": [ + "~4476Electronics" + ], + "localized_string_ids": [ + 4476 + ], + "source_kinds": [ + "cargo_types" + ] + }, + { + "visible_name": "Energy", + "raw_names": [ + "~4477Energy" + ], + "localized_string_ids": [ + 4477 + ], + "source_kinds": [ + "cargo_skin" + ] + }, + { + "visible_name": "Fertilizer", + "raw_names": [ + "Fertilizer" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Fish", + "raw_names": [ + "~4478Fish" + ], + "localized_string_ids": [ + 4478 + ], + "source_kinds": [ + "cargo_skin" + ] + }, + { + "visible_name": "Food", + "raw_names": [ + "~4479Food" + ], + "localized_string_ids": [ + 4479 + ], + "source_kinds": [ + "cargo_skin" + ] + }, + { + "visible_name": "Furniture", + "raw_names": [ + "Furniture" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Glass", + "raw_names": [ + "~4481Glass" + ], + "localized_string_ids": [ + 4481 + ], + "source_kinds": [ + "cargo_skin" + ] + }, + { + "visible_name": "Goods", + "raw_names": [ + "Goods" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Grain", + "raw_names": [ + "Grain" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Gravel", + "raw_names": [ + "~4482Gravel" + ], + "localized_string_ids": [ + 4482 + ], + "source_kinds": [ + "cargo_skin" + ] + }, + { + "visible_name": "Ingots", + "raw_names": [ + "~4488Ingots" + ], + "localized_string_ids": [ + 4488 + ], + "source_kinds": [ + "cargo_types" + ] + }, + { + "visible_name": "Iron", + "raw_names": [ + "Iron" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Livestock", + "raw_names": [ + "Livestock" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Logs", + "raw_names": [ + "Logs" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Lumber", + "raw_names": [ + "Lumber" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Machinery", + "raw_names": [ + "~4493Machinery" + ], + "localized_string_ids": [ + 4493 + ], + "source_kinds": [ + "cargo_types" + ] + }, + { + "visible_name": "Mail", + "raw_names": [ + "Mail" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Meat", + "raw_names": [ + "Meat" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Medicine", + "raw_names": [ + "~4494Medicine" + ], + "localized_string_ids": [ + 4494 + ], + "source_kinds": [ + "cargo_types" + ] + }, + { + "visible_name": "Milk", + "raw_names": [ + "Milk" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Money", + "raw_names": [ + "~4495Money" + ], + "localized_string_ids": [ + 4495 + ], + "source_kinds": [ + "cargo_skin" + ] + }, + { + "visible_name": "Newspaper", + "raw_names": [ + "~4497Newspaper" + ], + "localized_string_ids": [ + 4497 + ], + "source_kinds": [ + "cargo_skin" + ] + }, + { + "visible_name": "Oil", + "raw_names": [ + "Oil" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Ore", + "raw_names": [ + "~4505Ore" + ], + "localized_string_ids": [ + 4505 + ], + "source_kinds": [ + "cargo_types" + ] + }, + { + "visible_name": "Paint", + "raw_names": [ + "~4507Paint" + ], + "localized_string_ids": [ + 4507 + ], + "source_kinds": [ + "cargo_skin" + ] + }, + { + "visible_name": "Paper", + "raw_names": [ + "Paper" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Passengers", + "raw_names": [ + "Passengers" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Perfume", + "raw_names": [ + "~4508Perfume" + ], + "localized_string_ids": [ + 4508 + ], + "source_kinds": [ + "cargo_skin" + ] + }, + { + "visible_name": "Plastic", + "raw_names": [ + "Plastic" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Potash", + "raw_names": [ + "~4509Potash" + ], + "localized_string_ids": [ + 4509 + ], + "source_kinds": [ + "cargo_skin" + ] + }, + { + "visible_name": "Pottery", + "raw_names": [ + "~4510Pottery" + ], + "localized_string_ids": [ + 4510 + ], + "source_kinds": [ + "cargo_skin" + ] + }, + { + "visible_name": "Prisoners", + "raw_names": [ + "~4511Prisoners" + ], + "localized_string_ids": [ + 4511 + ], + "source_kinds": [ + "cargo_skin" + ] + }, + { + "visible_name": "Produce", + "raw_names": [ + "Produce" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Pulpwood", + "raw_names": [ + "Pulpwood" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Rice", + "raw_names": [ + "Rice" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Rock", + "raw_names": [ + "~4513Rock" + ], + "localized_string_ids": [ + 4513 + ], + "source_kinds": [ + "cargo_types" + ] + }, + { + "visible_name": "Rubber", + "raw_names": [ + "Rubber" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Salt", + "raw_names": [ + "~4515Salt" + ], + "localized_string_ids": [ + 4515 + ], + "source_kinds": [ + "cargo_skin" + ] + }, + { + "visible_name": "Sand", + "raw_names": [ + "~4516Sand" + ], + "localized_string_ids": [ + 4516 + ], + "source_kinds": [ + "cargo_skin" + ] + }, + { + "visible_name": "Spaceships", + "raw_names": [ + "~4518Spaceships" + ], + "localized_string_ids": [ + 4518 + ], + "source_kinds": [ + "cargo_skin" + ] + }, + { + "visible_name": "Steel", + "raw_names": [ + "Steel" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Sugar", + "raw_names": [ + "Sugar" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Syrup", + "raw_names": [ + "~4520Syrup" + ], + "localized_string_ids": [ + 4520 + ], + "source_kinds": [ + "cargo_skin" + ] + }, + { + "visible_name": "Tea", + "raw_names": [ + "~4523Tea" + ], + "localized_string_ids": [ + 4523 + ], + "source_kinds": [ + "cargo_skin" + ] + }, + { + "visible_name": "Tin", + "raw_names": [ + "~4525Tin" + ], + "localized_string_ids": [ + 4525 + ], + "source_kinds": [ + "cargo_skin" + ] + }, + { + "visible_name": "Tires", + "raw_names": [ + "Tires" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Tobacco", + "raw_names": [ + "~4529Tobacco" + ], + "localized_string_ids": [ + 4529 + ], + "source_kinds": [ + "cargo_skin" + ] + }, + { + "visible_name": "Tools", + "raw_names": [ + "~4530Tools" + ], + "localized_string_ids": [ + 4530 + ], + "source_kinds": [ + "cargo_skin" + ] + }, + { + "visible_name": "Toys", + "raw_names": [ + "Toys" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Troops", + "raw_names": [ + "Troops" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Uranium", + "raw_names": [ + "Uranium" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Valuables", + "raw_names": [ + "~4538Valuables" + ], + "localized_string_ids": [ + 4538 + ], + "source_kinds": [ + "cargo_skin" + ] + }, + { + "visible_name": "Waste", + "raw_names": [ + "Waste" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Weapons", + "raw_names": [ + "Weapons" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "visible_name": "Wine", + "raw_names": [ + "~4541Wine" + ], + "localized_string_ids": [ + 4541 + ], + "source_kinds": [ + "cargo_skin" + ] + }, + { + "visible_name": "Wire", + "raw_names": [ + "~4542Wire" + ], + "localized_string_ids": [ + 4542 + ], + "source_kinds": [ + "cargo_skin" + ] + }, + { + "visible_name": "Wool", + "raw_names": [ + "Wool" + ], + "localized_string_ids": [], + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + } + ], + "production_selector": { + "selector_kind": "named_cargo_production", + "exact_resolution": true, + "selector_row_count": 50, + "candidate_registry_count": 80, + "notes": [ + "This selector is grounded from the checked-in named cargo production bindings artifact.", + "The current grounded order matches the 50-row named cargo-production descriptor strip." + ], + "entries": [ + { + "selector_index": 1, + "descriptor_id": 180, + "visible_name": "Alcohol", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 2, + "descriptor_id": 181, + "visible_name": "Aluminum", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 3, + "descriptor_id": 182, + "visible_name": "Ammunition", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 4, + "descriptor_id": 183, + "visible_name": "Automobiles", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 5, + "descriptor_id": 184, + "visible_name": "Bauxite", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 6, + "descriptor_id": 185, + "visible_name": "Ceramics", + "source_kinds": [ + "cargo_types" + ] + }, + { + "selector_index": 7, + "descriptor_id": 186, + "visible_name": "Cheese", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 8, + "descriptor_id": 187, + "visible_name": "Chemicals", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 9, + "descriptor_id": 188, + "visible_name": "Clothing", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 10, + "descriptor_id": 189, + "visible_name": "Coal", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 11, + "descriptor_id": 190, + "visible_name": "Coffee", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 12, + "descriptor_id": 191, + "visible_name": "Concrete", + "source_kinds": [ + "cargo_types" + ] + }, + { + "selector_index": 13, + "descriptor_id": 192, + "visible_name": "Corn", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 14, + "descriptor_id": 193, + "visible_name": "Cotton", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 15, + "descriptor_id": 194, + "visible_name": "Crystals", + "source_kinds": [ + "cargo_types" + ] + }, + { + "selector_index": 16, + "descriptor_id": 195, + "visible_name": "Diesel", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 17, + "descriptor_id": 196, + "visible_name": "Dye", + "source_kinds": [ + "cargo_types" + ] + }, + { + "selector_index": 18, + "descriptor_id": 197, + "visible_name": "Electronics", + "source_kinds": [ + "cargo_types" + ] + }, + { + "selector_index": 19, + "descriptor_id": 198, + "visible_name": "Fertilizer", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 20, + "descriptor_id": 199, + "visible_name": "Furniture", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 21, + "descriptor_id": 200, + "visible_name": "Goods", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 22, + "descriptor_id": 201, + "visible_name": "Grain", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 23, + "descriptor_id": 202, + "visible_name": "Ingots", + "source_kinds": [ + "cargo_types" + ] + }, + { + "selector_index": 24, + "descriptor_id": 203, + "visible_name": "Iron", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 25, + "descriptor_id": 204, + "visible_name": "Livestock", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 26, + "descriptor_id": 205, + "visible_name": "Logs", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 27, + "descriptor_id": 206, + "visible_name": "Lumber", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 28, + "descriptor_id": 207, + "visible_name": "Machinery", + "source_kinds": [ + "cargo_types" + ] + }, + { + "selector_index": 29, + "descriptor_id": 208, + "visible_name": "Mail", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 30, + "descriptor_id": 209, + "visible_name": "Meat", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 31, + "descriptor_id": 210, + "visible_name": "Medicine", + "source_kinds": [ + "cargo_types" + ] + }, + { + "selector_index": 32, + "descriptor_id": 211, + "visible_name": "Milk", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 33, + "descriptor_id": 212, + "visible_name": "Oil", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 34, + "descriptor_id": 213, + "visible_name": "Ore", + "source_kinds": [ + "cargo_types" + ] + }, + { + "selector_index": 35, + "descriptor_id": 214, + "visible_name": "Paper", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 36, + "descriptor_id": 215, + "visible_name": "Passengers", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 37, + "descriptor_id": 216, + "visible_name": "Plastic", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 38, + "descriptor_id": 217, + "visible_name": "Produce", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 39, + "descriptor_id": 218, + "visible_name": "Pulpwood", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 40, + "descriptor_id": 219, + "visible_name": "Rice", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 41, + "descriptor_id": 220, + "visible_name": "Rubber", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 42, + "descriptor_id": 221, + "visible_name": "Steel", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 43, + "descriptor_id": 222, + "visible_name": "Sugar", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 44, + "descriptor_id": 223, + "visible_name": "Tires", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 45, + "descriptor_id": 224, + "visible_name": "Toys", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 46, + "descriptor_id": 225, + "visible_name": "Troops", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 47, + "descriptor_id": 226, + "visible_name": "Uranium", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 48, + "descriptor_id": 227, + "visible_name": "Waste", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 49, + "descriptor_id": 228, + "visible_name": "Weapons", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 50, + "descriptor_id": 229, + "visible_name": "Wool", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + } + ] + }, + "price_selector": { + "selector_kind": "named_cargo_price_candidate_registry", + "exact_resolution": false, + "selector_row_count": 71, + "candidate_registry_count": 80, + "notes": [ + "This is the current merged visible-name registry, sorted lexicographically, not a claimed reproduction of the original price selector.", + "The merged visible-name registry has 80 entries, so the exact 71-row price-selector binding remains unresolved by static source recovery alone.", + "Current unresolved gap is 9 excess candidate names relative to the descriptor strip." + ], + "entries": [ + { + "selector_index": 1, + "descriptor_id": null, + "visible_name": "Alcohol", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 2, + "descriptor_id": null, + "visible_name": "Aluminum", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 3, + "descriptor_id": null, + "visible_name": "Ammunition", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 4, + "descriptor_id": null, + "visible_name": "Automobiles", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 5, + "descriptor_id": null, + "visible_name": "Bauxite", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 6, + "descriptor_id": null, + "visible_name": "Beer", + "source_kinds": [ + "cargo_skin" + ] + }, + { + "selector_index": 7, + "descriptor_id": null, + "visible_name": "Candidates", + "source_kinds": [ + "cargo_skin" + ] + }, + { + "selector_index": 8, + "descriptor_id": null, + "visible_name": "Ceramics", + "source_kinds": [ + "cargo_types" + ] + }, + { + "selector_index": 9, + "descriptor_id": null, + "visible_name": "Cheese", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 10, + "descriptor_id": null, + "visible_name": "Chemicals", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 11, + "descriptor_id": null, + "visible_name": "China", + "source_kinds": [ + "cargo_skin" + ] + }, + { + "selector_index": 12, + "descriptor_id": null, + "visible_name": "Clothing", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 13, + "descriptor_id": null, + "visible_name": "Coal", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 14, + "descriptor_id": null, + "visible_name": "Coffee", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 15, + "descriptor_id": null, + "visible_name": "Concrete", + "source_kinds": [ + "cargo_types" + ] + }, + { + "selector_index": 16, + "descriptor_id": null, + "visible_name": "Containers", + "source_kinds": [ + "cargo_skin" + ] + }, + { + "selector_index": 17, + "descriptor_id": null, + "visible_name": "Corn", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 18, + "descriptor_id": null, + "visible_name": "Cotton", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 19, + "descriptor_id": null, + "visible_name": "Crystals", + "source_kinds": [ + "cargo_types" + ] + }, + { + "selector_index": 20, + "descriptor_id": null, + "visible_name": "Detergents", + "source_kinds": [ + "cargo_skin" + ] + }, + { + "selector_index": 21, + "descriptor_id": null, + "visible_name": "Deuterium", + "source_kinds": [ + "cargo_skin" + ] + }, + { + "selector_index": 22, + "descriptor_id": null, + "visible_name": "Diesel", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 23, + "descriptor_id": null, + "visible_name": "Dye", + "source_kinds": [ + "cargo_types" + ] + }, + { + "selector_index": 24, + "descriptor_id": null, + "visible_name": "Electronics", + "source_kinds": [ + "cargo_types" + ] + }, + { + "selector_index": 25, + "descriptor_id": null, + "visible_name": "Energy", + "source_kinds": [ + "cargo_skin" + ] + }, + { + "selector_index": 26, + "descriptor_id": null, + "visible_name": "Fertilizer", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 27, + "descriptor_id": null, + "visible_name": "Fish", + "source_kinds": [ + "cargo_skin" + ] + }, + { + "selector_index": 28, + "descriptor_id": null, + "visible_name": "Food", + "source_kinds": [ + "cargo_skin" + ] + }, + { + "selector_index": 29, + "descriptor_id": null, + "visible_name": "Furniture", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 30, + "descriptor_id": null, + "visible_name": "Glass", + "source_kinds": [ + "cargo_skin" + ] + }, + { + "selector_index": 31, + "descriptor_id": null, + "visible_name": "Goods", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 32, + "descriptor_id": null, + "visible_name": "Grain", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 33, + "descriptor_id": null, + "visible_name": "Gravel", + "source_kinds": [ + "cargo_skin" + ] + }, + { + "selector_index": 34, + "descriptor_id": null, + "visible_name": "Ingots", + "source_kinds": [ + "cargo_types" + ] + }, + { + "selector_index": 35, + "descriptor_id": null, + "visible_name": "Iron", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 36, + "descriptor_id": null, + "visible_name": "Livestock", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 37, + "descriptor_id": null, + "visible_name": "Logs", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 38, + "descriptor_id": null, + "visible_name": "Lumber", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 39, + "descriptor_id": null, + "visible_name": "Machinery", + "source_kinds": [ + "cargo_types" + ] + }, + { + "selector_index": 40, + "descriptor_id": null, + "visible_name": "Mail", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 41, + "descriptor_id": null, + "visible_name": "Meat", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 42, + "descriptor_id": null, + "visible_name": "Medicine", + "source_kinds": [ + "cargo_types" + ] + }, + { + "selector_index": 43, + "descriptor_id": null, + "visible_name": "Milk", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 44, + "descriptor_id": null, + "visible_name": "Money", + "source_kinds": [ + "cargo_skin" + ] + }, + { + "selector_index": 45, + "descriptor_id": null, + "visible_name": "Newspaper", + "source_kinds": [ + "cargo_skin" + ] + }, + { + "selector_index": 46, + "descriptor_id": null, + "visible_name": "Oil", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 47, + "descriptor_id": null, + "visible_name": "Ore", + "source_kinds": [ + "cargo_types" + ] + }, + { + "selector_index": 48, + "descriptor_id": null, + "visible_name": "Paint", + "source_kinds": [ + "cargo_skin" + ] + }, + { + "selector_index": 49, + "descriptor_id": null, + "visible_name": "Paper", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 50, + "descriptor_id": null, + "visible_name": "Passengers", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 51, + "descriptor_id": null, + "visible_name": "Perfume", + "source_kinds": [ + "cargo_skin" + ] + }, + { + "selector_index": 52, + "descriptor_id": null, + "visible_name": "Plastic", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 53, + "descriptor_id": null, + "visible_name": "Potash", + "source_kinds": [ + "cargo_skin" + ] + }, + { + "selector_index": 54, + "descriptor_id": null, + "visible_name": "Pottery", + "source_kinds": [ + "cargo_skin" + ] + }, + { + "selector_index": 55, + "descriptor_id": null, + "visible_name": "Prisoners", + "source_kinds": [ + "cargo_skin" + ] + }, + { + "selector_index": 56, + "descriptor_id": null, + "visible_name": "Produce", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 57, + "descriptor_id": null, + "visible_name": "Pulpwood", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 58, + "descriptor_id": null, + "visible_name": "Rice", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 59, + "descriptor_id": null, + "visible_name": "Rock", + "source_kinds": [ + "cargo_types" + ] + }, + { + "selector_index": 60, + "descriptor_id": null, + "visible_name": "Rubber", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 61, + "descriptor_id": null, + "visible_name": "Salt", + "source_kinds": [ + "cargo_skin" + ] + }, + { + "selector_index": 62, + "descriptor_id": null, + "visible_name": "Sand", + "source_kinds": [ + "cargo_skin" + ] + }, + { + "selector_index": 63, + "descriptor_id": null, + "visible_name": "Spaceships", + "source_kinds": [ + "cargo_skin" + ] + }, + { + "selector_index": 64, + "descriptor_id": null, + "visible_name": "Steel", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 65, + "descriptor_id": null, + "visible_name": "Sugar", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 66, + "descriptor_id": null, + "visible_name": "Syrup", + "source_kinds": [ + "cargo_skin" + ] + }, + { + "selector_index": 67, + "descriptor_id": null, + "visible_name": "Tea", + "source_kinds": [ + "cargo_skin" + ] + }, + { + "selector_index": 68, + "descriptor_id": null, + "visible_name": "Tin", + "source_kinds": [ + "cargo_skin" + ] + }, + { + "selector_index": 69, + "descriptor_id": null, + "visible_name": "Tires", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 70, + "descriptor_id": null, + "visible_name": "Tobacco", + "source_kinds": [ + "cargo_skin" + ] + }, + { + "selector_index": 71, + "descriptor_id": null, + "visible_name": "Tools", + "source_kinds": [ + "cargo_skin" + ] + }, + { + "selector_index": 72, + "descriptor_id": null, + "visible_name": "Toys", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 73, + "descriptor_id": null, + "visible_name": "Troops", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 74, + "descriptor_id": null, + "visible_name": "Uranium", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 75, + "descriptor_id": null, + "visible_name": "Valuables", + "source_kinds": [ + "cargo_skin" + ] + }, + { + "selector_index": 76, + "descriptor_id": null, + "visible_name": "Waste", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 77, + "descriptor_id": null, + "visible_name": "Weapons", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + }, + { + "selector_index": 78, + "descriptor_id": null, + "visible_name": "Wine", + "source_kinds": [ + "cargo_skin" + ] + }, + { + "selector_index": 79, + "descriptor_id": null, + "visible_name": "Wire", + "source_kinds": [ + "cargo_skin" + ] + }, + { + "selector_index": 80, + "descriptor_id": null, + "visible_name": "Wool", + "source_kinds": [ + "cargo_types", + "cargo_skin" + ] + } + ] + }, "notes": [ "Named cargo-price descriptors 106..176 span 71 rows, while named cargo-production descriptors 180..229 span 50 rows.", "The inspected CargoTypes corpus exposes 51 visible names, the inspected cargoSkin corpus exposes 70 visible names, and their union exposes 80 visible names.", diff --git a/crates/rrt-cli/src/main.rs b/crates/rrt-cli/src/main.rs index 7ccc472..0809a46 100644 --- a/crates/rrt-cli/src/main.rs +++ b/crates/rrt-cli/src/main.rs @@ -25,7 +25,7 @@ use rrt_runtime::{ SAVE_SLICE_DOCUMENT_FORMAT_VERSION, SNAPSHOT_FORMAT_VERSION, SmpClassicPackedProfileBlock, SmpInspectionReport, SmpLoadedSaveSlice, SmpRt3105PackedProfileBlock, SmpSaveLoadSummary, WinInspectionReport, execute_step_command, extract_pk4_entry_file, inspect_campaign_exe_file, - inspect_cargo_economy_sources, inspect_cargo_skin_pk4, inspect_cargo_types_dir, + inspect_cargo_economy_sources_with_bindings, inspect_cargo_skin_pk4, inspect_cargo_types_dir, inspect_pk4_file, inspect_smp_file, inspect_win_file, load_runtime_snapshot_document, load_runtime_state_import, load_save_slice_file, project_save_slice_to_runtime_state_import, save_runtime_overlay_import_document, save_runtime_save_slice_document, @@ -1583,10 +1583,16 @@ fn run_runtime_inspect_cargo_economy_sources( cargo_types_dir: &Path, cargo_skin_pk4_path: &Path, ) -> Result<(), Box> { + let cargo_bindings_path = + Path::new("artifacts/exports/rt3-1.06/event-effects-cargo-bindings.json"); let report = RuntimeCargoEconomyInspectionOutput { cargo_types_dir: cargo_types_dir.display().to_string(), cargo_skin_pk4_path: cargo_skin_pk4_path.display().to_string(), - inspection: inspect_cargo_economy_sources(cargo_types_dir, cargo_skin_pk4_path)?, + inspection: inspect_cargo_economy_sources_with_bindings( + cargo_types_dir, + cargo_skin_pk4_path, + Some(cargo_bindings_path), + )?, }; println!("{}", serde_json::to_string_pretty(&report)?); Ok(()) diff --git a/crates/rrt-runtime/src/economy.rs b/crates/rrt-runtime/src/economy.rs index c30d8a2..0acfdaa 100644 --- a/crates/rrt-runtime/src/economy.rs +++ b/crates/rrt-runtime/src/economy.rs @@ -67,11 +67,62 @@ pub struct CargoEconomySourceReport { pub visible_name_union_count: usize, pub cargo_type_only_visible_names: Vec, pub cargo_skin_only_visible_names: Vec, + pub live_registry_count: usize, + pub live_registry_entries: Vec, + pub production_selector: Option, + pub price_selector: CargoSelectorReport, pub notes: Vec, pub cargo_type_entries: Vec, pub cargo_skin_entries: Vec, } +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum CargoRegistrySourceKind { + CargoTypes, + CargoSkin, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct CargoLiveRegistryEntry { + pub visible_name: String, + pub raw_names: Vec, + pub localized_string_ids: Vec, + pub source_kinds: Vec, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct CargoSelectorEntry { + pub selector_index: usize, + #[serde(default)] + pub descriptor_id: Option, + pub visible_name: String, + pub source_kinds: Vec, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct CargoSelectorReport { + pub selector_kind: String, + pub exact_resolution: bool, + pub selector_row_count: usize, + pub candidate_registry_count: usize, + pub notes: Vec, + pub entries: Vec, +} + +#[derive(Debug, Clone, PartialEq, Eq, Deserialize)] +struct CargoBindingArtifact { + bindings: Vec, +} + +#[derive(Debug, Clone, PartialEq, Eq, Deserialize)] +struct CargoBindingRow { + descriptor_id: u32, + band: String, + cargo_name: String, + binding_index: usize, +} + pub fn inspect_cargo_types_dir( path: &Path, ) -> Result> { @@ -167,15 +218,29 @@ pub fn inspect_cargo_skin_pk4( pub fn inspect_cargo_economy_sources( cargo_types_dir: &Path, cargo_skin_pk4_path: &Path, +) -> Result> { + inspect_cargo_economy_sources_with_bindings(cargo_types_dir, cargo_skin_pk4_path, None) +} + +pub fn inspect_cargo_economy_sources_with_bindings( + cargo_types_dir: &Path, + cargo_skin_pk4_path: &Path, + cargo_bindings_path: Option<&Path>, ) -> Result> { let cargo_types = inspect_cargo_types_dir(cargo_types_dir)?; let cargo_skins = inspect_cargo_skin_pk4(cargo_skin_pk4_path)?; - Ok(build_cargo_economy_source_report(cargo_types, cargo_skins)) + let cargo_bindings = load_cargo_bindings(cargo_bindings_path)?; + Ok(build_cargo_economy_source_report( + cargo_types, + cargo_skins, + cargo_bindings.as_deref(), + )) } fn build_cargo_economy_source_report( cargo_types: CargoTypeInspectionReport, cargo_skins: CargoSkinInspectionReport, + cargo_bindings: Option<&[CargoBindingRow]>, ) -> CargoEconomySourceReport { let cargo_type_visible_names = cargo_types .entries @@ -202,6 +267,11 @@ fn build_cargo_economy_source_report( .difference(&cargo_type_visible_names) .cloned() .collect::>(); + let live_registry_entries = + build_live_registry_entries(&cargo_types.entries, &cargo_skins.entries); + let production_selector = + cargo_bindings.map(|bindings| build_production_selector(bindings, &live_registry_entries)); + let price_selector = build_price_selector(&live_registry_entries); let mut notes = Vec::new(); notes.push(format!( @@ -241,12 +311,187 @@ fn build_cargo_economy_source_report( visible_name_union_count, cargo_type_only_visible_names, cargo_skin_only_visible_names, + live_registry_count: live_registry_entries.len(), + live_registry_entries, + production_selector, + price_selector, notes, cargo_type_entries: cargo_types.entries, cargo_skin_entries: cargo_skins.entries, } } +fn build_live_registry_entries( + cargo_type_entries: &[CargoTypeEntry], + cargo_skin_entries: &[CargoSkinDescriptorEntry], +) -> Vec { + let mut visible_names = cargo_type_entries + .iter() + .map(|entry| entry.name.visible_name.clone()) + .chain( + cargo_skin_entries + .iter() + .map(|entry| entry.name.visible_name.clone()), + ) + .collect::>() + .into_iter() + .collect::>(); + visible_names.sort(); + + visible_names + .into_iter() + .map(|visible_name| { + let mut raw_names = cargo_type_entries + .iter() + .filter(|entry| entry.name.visible_name == visible_name) + .map(|entry| entry.name.raw_name.clone()) + .chain( + cargo_skin_entries + .iter() + .filter(|entry| entry.name.visible_name == visible_name) + .map(|entry| entry.name.raw_name.clone()), + ) + .collect::>() + .into_iter() + .collect::>(); + raw_names.sort(); + + let localized_string_ids = cargo_type_entries + .iter() + .filter(|entry| entry.name.visible_name == visible_name) + .filter_map(|entry| entry.name.localized_string_id) + .chain( + cargo_skin_entries + .iter() + .filter(|entry| entry.name.visible_name == visible_name) + .filter_map(|entry| entry.name.localized_string_id), + ) + .collect::>() + .into_iter() + .collect::>(); + + let mut source_kinds = Vec::new(); + if cargo_type_entries + .iter() + .any(|entry| entry.name.visible_name == visible_name) + { + source_kinds.push(CargoRegistrySourceKind::CargoTypes); + } + if cargo_skin_entries + .iter() + .any(|entry| entry.name.visible_name == visible_name) + { + source_kinds.push(CargoRegistrySourceKind::CargoSkin); + } + + CargoLiveRegistryEntry { + visible_name, + raw_names, + localized_string_ids, + source_kinds, + } + }) + .collect() +} + +fn build_production_selector( + bindings: &[CargoBindingRow], + live_registry_entries: &[CargoLiveRegistryEntry], +) -> CargoSelectorReport { + let mut rows = bindings + .iter() + .filter(|binding| binding.band == "cargo_production_named") + .collect::>(); + rows.sort_by_key(|binding| binding.binding_index); + + let entries = rows + .into_iter() + .map(|binding| CargoSelectorEntry { + selector_index: binding.binding_index, + descriptor_id: Some(binding.descriptor_id), + visible_name: binding.cargo_name.clone(), + source_kinds: live_registry_entries + .iter() + .find(|entry| entry.visible_name == binding.cargo_name) + .map(|entry| entry.source_kinds.clone()) + .unwrap_or_default(), + }) + .collect::>(); + + CargoSelectorReport { + selector_kind: "named_cargo_production".to_string(), + exact_resolution: entries.len() == NAMED_CARGO_PRODUCTION_DESCRIPTOR_ROW_COUNT, + selector_row_count: NAMED_CARGO_PRODUCTION_DESCRIPTOR_ROW_COUNT, + candidate_registry_count: live_registry_entries.len(), + notes: vec![ + "This selector is grounded from the checked-in named cargo production bindings artifact." + .to_string(), + "The current grounded order matches the 50-row named cargo-production descriptor strip." + .to_string(), + ], + entries, + } +} + +fn build_price_selector(live_registry_entries: &[CargoLiveRegistryEntry]) -> CargoSelectorReport { + let entries = live_registry_entries + .iter() + .enumerate() + .map(|(index, entry)| CargoSelectorEntry { + selector_index: index + 1, + descriptor_id: None, + visible_name: entry.visible_name.clone(), + source_kinds: entry.source_kinds.clone(), + }) + .collect::>(); + let candidate_registry_count = entries.len(); + let exact_resolution = candidate_registry_count == NAMED_CARGO_PRICE_DESCRIPTOR_ROW_COUNT; + let mut notes = Vec::new(); + notes.push( + "This is the current merged visible-name registry, sorted lexicographically, not a claimed reproduction of the original price selector." + .to_string(), + ); + if exact_resolution { + notes.push( + "The merged visible-name registry cardinality matches the 71-row named cargo-price descriptor strip." + .to_string(), + ); + } else { + notes.push(format!( + "The merged visible-name registry has {} entries, so the exact 71-row price-selector binding remains unresolved by static source recovery alone.", + candidate_registry_count + )); + let excess = + candidate_registry_count.saturating_sub(NAMED_CARGO_PRICE_DESCRIPTOR_ROW_COUNT); + notes.push(format!( + "Current unresolved gap is {} excess candidate names relative to the descriptor strip.", + excess + )); + } + + CargoSelectorReport { + selector_kind: "named_cargo_price_candidate_registry".to_string(), + exact_resolution, + selector_row_count: NAMED_CARGO_PRICE_DESCRIPTOR_ROW_COUNT, + candidate_registry_count, + notes, + entries, + } +} + +fn load_cargo_bindings( + path: Option<&Path>, +) -> Result>, Box> { + let Some(path) = path else { + return Ok(None); + }; + if !path.exists() { + return Ok(None); + } + let artifact: CargoBindingArtifact = serde_json::from_str(&fs::read_to_string(path)?)?; + Ok(Some(artifact.bindings)) +} + fn parse_cargo_type_entry( file_name: &str, bytes: &[u8], @@ -402,9 +647,10 @@ mod tests { ], }; - let report = build_cargo_economy_source_report(cargo_types, cargo_skins); + let report = build_cargo_economy_source_report(cargo_types, cargo_skins, None); assert_eq!(report.shared_visible_name_count, 1); assert_eq!(report.visible_name_union_count, 3); + assert_eq!(report.live_registry_count, 3); assert_eq!( report.cargo_type_only_visible_names, vec!["Coal".to_string()] @@ -413,5 +659,79 @@ mod tests { report.cargo_skin_only_visible_names, vec!["Beer".to_string()] ); + assert!(!report.price_selector.exact_resolution); + assert_eq!(report.price_selector.candidate_registry_count, 3); + assert!(report.production_selector.is_none()); + } + + #[test] + fn builds_exact_production_selector_from_bindings() { + let cargo_types = CargoTypeInspectionReport { + directory_path: "CargoTypes".to_string(), + entry_count: 2, + unique_visible_name_count: 2, + notes: Vec::new(), + entries: vec![ + CargoTypeEntry { + file_name: "Alcohol.cty".to_string(), + file_size: 16, + file_size_hex: "0x10".to_string(), + header_magic: CARGO_TYPE_MAGIC, + header_magic_hex: format!("0x{CARGO_TYPE_MAGIC:08x}"), + name: parse_cargo_name_token("Alcohol"), + }, + CargoTypeEntry { + file_name: "Coal.cty".to_string(), + file_size: 16, + file_size_hex: "0x10".to_string(), + header_magic: CARGO_TYPE_MAGIC, + header_magic_hex: format!("0x{CARGO_TYPE_MAGIC:08x}"), + name: parse_cargo_name_token("Coal"), + }, + ], + }; + let cargo_skins = CargoSkinInspectionReport { + pk4_path: "Cargo106.PK4".to_string(), + entry_count: 1, + unique_visible_name_count: 1, + notes: Vec::new(), + entries: vec![CargoSkinDescriptorEntry { + pk4_entry_name: "Alcohol.dsc".to_string(), + payload_len: 20, + payload_len_hex: "0x14".to_string(), + descriptor_kind: "cargoSkin".to_string(), + name: parse_cargo_name_token("Alcohol"), + }], + }; + let bindings = vec![ + CargoBindingRow { + descriptor_id: 180, + band: "cargo_production_named".to_string(), + cargo_name: "Alcohol".to_string(), + binding_index: 1, + }, + CargoBindingRow { + descriptor_id: 181, + band: "cargo_production_named".to_string(), + cargo_name: "Coal".to_string(), + binding_index: 2, + }, + ]; + + let report = build_cargo_economy_source_report(cargo_types, cargo_skins, Some(&bindings)); + let selector = report + .production_selector + .expect("production selector should exist"); + assert_eq!(selector.entries.len(), 2); + assert_eq!(selector.entries[0].descriptor_id, Some(180)); + assert_eq!(selector.entries[0].visible_name, "Alcohol"); + assert_eq!( + selector.entries[0].source_kinds, + vec![ + CargoRegistrySourceKind::CargoTypes, + CargoRegistrySourceKind::CargoSkin + ] + ); + assert_eq!(selector.entries[1].visible_name, "Coal"); } } diff --git a/crates/rrt-runtime/src/lib.rs b/crates/rrt-runtime/src/lib.rs index 6ce0ccb..d60c8d9 100644 --- a/crates/rrt-runtime/src/lib.rs +++ b/crates/rrt-runtime/src/lib.rs @@ -16,10 +16,12 @@ pub use campaign_exe::{ OBSERVED_CAMPAIGN_SCENARIO_NAMES, inspect_campaign_exe_bytes, inspect_campaign_exe_file, }; pub use economy::{ - CARGO_TYPE_MAGIC, CargoEconomySourceReport, CargoNameToken, CargoSkinDescriptorEntry, + CARGO_TYPE_MAGIC, CargoEconomySourceReport, CargoLiveRegistryEntry, CargoNameToken, + CargoRegistrySourceKind, CargoSelectorEntry, CargoSelectorReport, CargoSkinDescriptorEntry, CargoSkinInspectionReport, CargoTypeEntry, CargoTypeInspectionReport, NAMED_CARGO_PRICE_DESCRIPTOR_ROW_COUNT, NAMED_CARGO_PRODUCTION_DESCRIPTOR_ROW_COUNT, - inspect_cargo_economy_sources, inspect_cargo_skin_pk4, inspect_cargo_types_dir, + inspect_cargo_economy_sources, inspect_cargo_economy_sources_with_bindings, + inspect_cargo_skin_pk4, inspect_cargo_types_dir, }; pub use import::{ OVERLAY_IMPORT_DOCUMENT_FORMAT_VERSION, RuntimeOverlayImportDocument, diff --git a/docs/README.md b/docs/README.md index 7b4ad78..2a3bb7b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -134,8 +134,10 @@ The highest-value next passes are now: checked-in offline cargo-source report at `artifacts/exports/rt3-1.06/economy-cargo-sources.json` now parses both `CargoTypes` and the `Cargo106.PK4` `cargoSkin` descriptors through rehosted code, normalizes localized - `~####Name` tokens into visible names, and shows that the current 1.06 visible-name union is - `80`, so source recovery alone still does not prove the live price-selector ordering + `~####Name` tokens into visible names, builds a merged live cargo registry, and derives an exact + named cargo-production selector from the checked-in bindings; it also shows that the current + 1.06 visible-name union is `80`, so source recovery alone still does not prove the live + price-selector ordering - the add-building strip `503..519` is now explicitly classified as recovered shell-owned parity, with tracked fixture coverage, instead of generic unresolved descriptor residue - widen real packed-event executable coverage descriptor by descriptor after identity, target mask, diff --git a/docs/runtime-rehost-plan.md b/docs/runtime-rehost-plan.md index 6e9fd70..02d9946 100644 --- a/docs/runtime-rehost-plan.md +++ b/docs/runtime-rehost-plan.md @@ -95,8 +95,10 @@ Implemented today: a new checked-in offline cargo-source report at `artifacts/exports/rt3-1.06/economy-cargo-sources.json` now parses both `CargoTypes` and the `Cargo106.PK4` `cargoSkin` descriptors through rehosted code, normalizes localized - `~####Name` tokens into visible names, and shows that the current 1.06 visible-name union is - `80`, so source recovery alone still does not prove the live price-selector ordering + `~####Name` tokens into visible names, builds a merged live cargo registry, and derives an exact + named cargo-production selector from the checked-in bindings; it also shows that the current + 1.06 visible-name union is `80`, so source recovery alone still does not prove the live + price-selector ordering - the add-building strip `503..519` is now explicitly classified as recovered shell-owned parity with tracked fixture coverage, not generic unresolved descriptor residue - a minimal event-owned train surface and an opaque economic-status lane now exist in runtime