hoi4-agent-tools 3.10.0 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/CHANGELOG.md +131 -0
  2. package/README.md +91 -147
  3. package/dist/bin/http.js +10 -0
  4. package/dist/bin/setup.js +3 -2
  5. package/dist/bin/stdio.js +10 -0
  6. package/dist/hoi4_agent_tools/core/artifacts.js +40 -5
  7. package/dist/hoi4_agent_tools/core/canonical.js +18 -4
  8. package/dist/hoi4_agent_tools/core/condition-evaluator.js +18 -0
  9. package/dist/hoi4_agent_tools/core/configuration.js +7 -0
  10. package/dist/hoi4_agent_tools/core/domain-scan-patterns.js +12 -0
  11. package/dist/hoi4_agent_tools/core/domain-tools.js +65 -0
  12. package/dist/hoi4_agent_tools/core/domain-validation.js +5 -2
  13. package/dist/hoi4_agent_tools/core/engine.js +29 -2
  14. package/dist/hoi4_agent_tools/core/index.js +2 -2
  15. package/dist/hoi4_agent_tools/core/job-executor.js +14 -1
  16. package/dist/hoi4_agent_tools/core/job-operation-registration.js +15 -7
  17. package/dist/hoi4_agent_tools/core/job-store.js +78 -5
  18. package/dist/hoi4_agent_tools/core/job-transactions.js +31 -2
  19. package/dist/hoi4_agent_tools/core/job-worker-host.js +314 -127
  20. package/dist/hoi4_agent_tools/core/job-worker.js +96 -37
  21. package/dist/hoi4_agent_tools/core/operation-result.js +123 -10
  22. package/dist/hoi4_agent_tools/core/operation-tasks.js +49 -89
  23. package/dist/hoi4_agent_tools/core/persistent-analysis-cache.js +25 -21
  24. package/dist/hoi4_agent_tools/core/server-registry.js +22 -5
  25. package/dist/hoi4_agent_tools/core/shared-request-capacity.js +26 -1
  26. package/dist/hoi4_agent_tools/core/source/cache.js +20 -10
  27. package/dist/hoi4_agent_tools/core/source/lexer.js +11 -3
  28. package/dist/hoi4_agent_tools/core/temporary-directories.js +293 -0
  29. package/dist/hoi4_agent_tools/core/transactions.js +114 -23
  30. package/dist/hoi4_agent_tools/core/worker-exit.js +80 -0
  31. package/dist/hoi4_agent_tools/core/workspace.js +84 -8
  32. package/dist/hoi4_agent_tools/decision/ai.js +1 -1
  33. package/dist/hoi4_agent_tools/decision/service.js +28 -0
  34. package/dist/hoi4_agent_tools/decision/source-inventory.js +7 -5
  35. package/dist/hoi4_agent_tools/event/job-operations.js +9 -5
  36. package/dist/hoi4_agent_tools/event/operations.js +14 -1
  37. package/dist/hoi4_agent_tools/focus/job-operations.js +1 -2
  38. package/dist/hoi4_agent_tools/focus/tool-operations.js +1 -1
  39. package/dist/hoi4_agent_tools/gui/assets.js +3 -0
  40. package/dist/hoi4_agent_tools/gui/dds.js +8 -4
  41. package/dist/hoi4_agent_tools/gui/layout.js +45 -5
  42. package/dist/hoi4_agent_tools/gui/native-state.js +244 -0
  43. package/dist/hoi4_agent_tools/gui/renderer.js +12 -7
  44. package/dist/hoi4_agent_tools/gui/source-graph.js +17 -4
  45. package/dist/hoi4_agent_tools/gui/studio.js +33 -21
  46. package/dist/hoi4_agent_tools/gui/validators.js +8 -6
  47. package/dist/hoi4_agent_tools/map/bmp.js +1 -1
  48. package/dist/hoi4_agent_tools/map/derived.js +748 -0
  49. package/dist/hoi4_agent_tools/map/job-operations.js +7 -3
  50. package/dist/hoi4_agent_tools/map/model.js +103 -0
  51. package/dist/hoi4_agent_tools/map/operations.js +427 -58
  52. package/dist/hoi4_agent_tools/map/references.js +483 -0
  53. package/dist/hoi4_agent_tools/map/service.js +136 -61
  54. package/dist/hoi4_agent_tools/map/tool-operations.js +2 -1
  55. package/dist/hoi4_agent_tools/map/validation.js +3 -0
  56. package/dist/hoi4_agent_tools/map/world.js +1280 -0
  57. package/dist/hoi4_agent_tools/mcp/prompts/probability.js +2 -2
  58. package/dist/hoi4_agent_tools/mcp/server/argument-errors.js +72 -0
  59. package/dist/hoi4_agent_tools/mcp/server/create-modern-operations.js +23 -5
  60. package/dist/hoi4_agent_tools/mcp/server/create.js +7 -0
  61. package/dist/hoi4_agent_tools/mcp/server/instructions.js +1 -1
  62. package/dist/hoi4_agent_tools/mcp/server/request-lifecycle.js +24 -30
  63. package/dist/hoi4_agent_tools/mcp/server/tool-listing.js +45 -0
  64. package/dist/hoi4_agent_tools/mcp/tools/analysis.js +28 -8
  65. package/dist/hoi4_agent_tools/mcp/tools/event.js +19 -30
  66. package/dist/hoi4_agent_tools/mcp/tools/focus.js +5 -13
  67. package/dist/hoi4_agent_tools/mcp/tools/gui.js +6 -6
  68. package/dist/hoi4_agent_tools/mcp/tools/job.js +4 -4
  69. package/dist/hoi4_agent_tools/mcp/tools/map.js +15 -18
  70. package/dist/hoi4_agent_tools/mcp/tools/probability.js +42 -48
  71. package/dist/hoi4_agent_tools/mcp/tools/reference.js +26 -9
  72. package/dist/hoi4_agent_tools/mcp/tools/technology.js +17 -30
  73. package/dist/hoi4_agent_tools/mcp/transports/http.js +28 -4
  74. package/dist/hoi4_agent_tools/mcp/transports/stdio-lifetime.js +31 -8
  75. package/dist/hoi4_agent_tools/probability/job-operations.js +4 -9
  76. package/dist/hoi4_agent_tools/probability/operations.js +175 -13
  77. package/dist/hoi4_agent_tools/probability/source-analysis.js +24 -1
  78. package/dist/hoi4_agent_tools/reference/error-log.js +359 -0
  79. package/dist/hoi4_agent_tools/reference/known-mistakes.js +307 -0
  80. package/dist/hoi4_agent_tools/reference/known-mistakes.json +154 -0
  81. package/dist/hoi4_agent_tools/reference/mod-index.js +101 -0
  82. package/dist/hoi4_agent_tools/reference/operations.js +88 -19
  83. package/dist/hoi4_agent_tools/reference/player-text.js +4 -3
  84. package/dist/hoi4_agent_tools/reference/script-validation.js +19 -1
  85. package/dist/hoi4_agent_tools/reference/service.js +6 -0
  86. package/dist/hoi4_agent_tools/runtime.js +14 -1
  87. package/dist/hoi4_agent_tools/schemas/event.js +78 -19
  88. package/dist/hoi4_agent_tools/schemas/focus-requests.js +10 -0
  89. package/dist/hoi4_agent_tools/schemas/lenient-arguments.js +266 -0
  90. package/dist/hoi4_agent_tools/schemas/map-requests.js +63 -20
  91. package/dist/hoi4_agent_tools/schemas/map.js +122 -3
  92. package/dist/hoi4_agent_tools/schemas/mod-tools.js +181 -0
  93. package/dist/hoi4_agent_tools/schemas/probability-requests.js +119 -9
  94. package/dist/hoi4_agent_tools/schemas/reference.js +13 -0
  95. package/dist/hoi4_agent_tools/schemas/scenarios.js +1 -3
  96. package/dist/hoi4_agent_tools/schemas/script-validation.js +13 -6
  97. package/dist/hoi4_agent_tools/schemas/technology.js +79 -21
  98. package/dist/hoi4_agent_tools/technology/job-operations.js +3 -4
  99. package/dist/hoi4_agent_tools/technology/operations.js +14 -1
  100. package/dist/hoi4_agent_tools/version.js +1 -1
  101. package/docs/README.md +7 -4
  102. package/docs/analysis.md +15 -2
  103. package/docs/configuration.md +281 -0
  104. package/docs/development.md +26 -2
  105. package/docs/events.md +29 -6
  106. package/docs/examples.md +13 -28
  107. package/docs/focus.md +127 -5
  108. package/docs/gui.md +105 -21
  109. package/docs/helper-expansion.md +9 -9
  110. package/docs/http.md +3 -1
  111. package/docs/jobs.md +23 -14
  112. package/docs/map.md +199 -7
  113. package/docs/mechanics.md +6 -2
  114. package/docs/probability.md +46 -16
  115. package/docs/reference.md +73 -5
  116. package/docs/setup.md +45 -14
  117. package/docs/technology.md +28 -4
  118. package/docs/third-party-notices.md +11 -0
  119. package/docs/tools.md +150 -42
  120. package/docs/troubleshooting.md +61 -0
  121. package/examples/clients/codex-config.toml +5 -2
  122. package/examples/clients/generic.json +2 -2
  123. package/examples/config/config.json +7 -0
  124. package/npm-shrinkwrap.json +151 -156
  125. package/package.json +13 -8
  126. package/schemas/configuration.schema.json +144 -128
  127. package/schemas/continuous-focus-palette.schema.json +1 -1
  128. package/schemas/custom-weighted-pool.schema.json +1 -1
  129. package/schemas/decision-inspect-input.schema.json +1 -1
  130. package/schemas/error-log-input.schema.json +55 -0
  131. package/schemas/event-feature-manifest.schema.json +1 -1
  132. package/schemas/focus-plan.schema.json +1 -1
  133. package/schemas/focus-planning-sidecar.schema.json +1 -1
  134. package/schemas/gui-animation-source.schema.json +1 -1
  135. package/schemas/gui-helper.schema.json +1 -1
  136. package/schemas/gui-scenario.schema.json +1 -1
  137. package/schemas/helper-expansion-request.schema.json +1 -1
  138. package/schemas/helper-expansion-summary.schema.json +1 -1
  139. package/schemas/impact-inspect-input.schema.json +1 -1
  140. package/schemas/map-operation.schema.json +597 -126
  141. package/schemas/mechanic-test-input.schema.json +1 -1
  142. package/schemas/mod-index-input.schema.json +51 -0
  143. package/schemas/operation-result.schema.json +2 -2
  144. package/schemas/package-check-input.schema.json +1 -1
  145. package/schemas/package-manifest.schema.json +1 -1
  146. package/schemas/probability-analysis-result.schema.json +1 -1
  147. package/schemas/probability-compare-input.schema.json +1 -1
  148. package/schemas/probability-evaluate-input.schema.json +1 -1
  149. package/schemas/probability-inspect-input.schema.json +1 -1
  150. package/schemas/probability-render-input.schema.json +1 -1
  151. package/schemas/probability-scenario-set.schema.json +1 -1
  152. package/schemas/probability-sequence-input.schema.json +1 -1
  153. package/schemas/probability-simulate-input.schema.json +1 -1
  154. package/schemas/probability-sweep-input.schema.json +1 -1
  155. package/schemas/reference-context-input.schema.json +1 -1
  156. package/schemas/reference-read-input.schema.json +1 -1
  157. package/schemas/reference-search-input.schema.json +1 -1
  158. package/schemas/scenario-suite.schema.json +3 -5
  159. package/schemas/scenario-test-input.schema.json +3 -5
  160. package/schemas/script-validate-input.schema.json +1 -1
  161. package/schemas/shared-scenario.schema.json +1 -1
  162. package/schemas/source-lookup-input.schema.json +1 -1
  163. package/server.json +3 -3
package/docs/map.md CHANGED
@@ -1,10 +1,11 @@
1
1
  # Maps
2
2
 
3
- Use `hoi4.map_inspect`, `hoi4.map_render`, and `hoi4.map_rewrite` for provinces, states, strategic regions, adjacency, supply nodes, railways, positions, ownership, cores, claims, resources, buildings, and localisation.
3
+ Generate a new world, split states and reshape provinces. Preview the map and update the scripts that refer to it.
4
+ Use `hoi4.map_inspect` and `hoi4.map_rewrite` for provinces, states, regions, supply, railways, positions, ownership, resources, buildings and localisation.
4
5
 
5
6
  ## Inspect and navigate the complete map
6
7
 
7
- `hoi4.map_inspect` validates the map and returns a full-map PNG plus a searchable, clickable HTML navigator by default. The navigator supports pan, zoom, fit-to-map, search by numeric ID, localisation key, or localised name, and exact click lookup for province, state, and strategic-region IDs. Hovering reports both top-left bitmap coordinates and bottom-left HOI4 map coordinates.
8
+ `hoi4.map_inspect` finds map problems and returns a full-map PNG plus a searchable, clickable HTML navigator by default. The navigator supports pan, zoom, fit-to-map, search by numeric ID, localisation key, or localised name, and exact click lookup for province, state, and strategic-region IDs. Hovering reports both top-left bitmap coordinates and bottom-left HOI4 map coordinates.
8
9
 
9
10
  The linked JSON catalog contains every active province definition, state, and strategic region with resolved names, alternate localisation values, source paths and lines, raster bounds and centers, memberships, neighbors, victory points, resources, buildings, ports, supply nodes, railways, normal and special adjacencies, building positions, unit positions, weather positions, and entity locators. Large catalog and render data remain in MCP resources instead of filling the agent prompt.
10
11
 
@@ -12,9 +13,25 @@ Use `query` for a compact name or ID result list and `coordinates` for exact pix
12
13
 
13
14
  Set `lookupOnly: true` for coordinate, query, and selected-ID lookups without full validation, the complete catalog artifact, overview rendering, or province geometry export. The lookup artifact contains only the requested matches and source revision. Use full inspection for allocation previews or province row runs.
14
15
 
15
- `hoi4.map_render` creates the same complete catalog and navigator with a chosen base layer and overlays. Base layers include province, state, strategic region, terrain, continent, owner, controller, cores, claims, and coast. Overlays include coastlines, ports, victory points, resources, state and province buildings, supply nodes, railways, adjacencies, and building, unit, and weather positions.
16
+ `hoi4.map_inspect` accepts these fields:
16
17
 
17
- Pass `tile: { x, y, width, height }` to `hoi4.map_render` for a reusable bounded PNG, JSON, and HTML view of one top-left bitmap area. The tile preserves the selected base layer and overlays, and its JSON records raster dimensions and province IDs in the area. Identical source revisions and render settings produce identical artifact hashes.
18
+ | Field | Default and limits | Meaning |
19
+ | -------------------- | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
20
+ | `provinceIds` | `[]`, at most 32 | Province records to return, with exact geometry row runs. |
21
+ | `stateIds` | `[]`, at most 1,000 | State records to return. |
22
+ | `regionIds` | `[]`, at most 1,000 | Strategic-region records to return. |
23
+ | `query` | optional, at most 256 characters | Name, localisation key, or ID search. |
24
+ | `queryLimit` | 100, range 1 to 1,000 | Maximum `query` matches. |
25
+ | `coordinates` | `[]`, at most 100 | `{ "kind": "pixel", "x", "y" }` with top-left bitmap pixels, or `{ "kind": "map", "x", "z" }` with HOI4 map coordinates. |
26
+ | `lookupOnly` | `false` | Return only the requested lookups, as described above. |
27
+ | `includeOverview` | `true` | Render the full-map PNG and navigator; set `false` to skip the overview render. |
28
+ | `allocationRequests` | `[]`, at most 100 | Preview the next free identifiers: `{ "kind": "state", "requestedId"? }` or `{ "kind": "province", "requestedId"?, "requestedColor"? }`, where `requestedColor` is `{ "r", "g", "b" }`. Not accepted with `lookupOnly`. |
29
+
30
+ Give `hoi4.map_inspect` a `layer`, `overlays`, `scale`, `tile` or `area` to render that view instead of validating; the result is the same complete catalog and navigator drawn with the chosen base layer and overlays, and lookups (`query`, `coordinates`, IDs) belong in a separate call. Base layers include province, state, strategic region, terrain, continent, owner, controller, cores, claims, and coast. Overlays include coastlines, ports, victory points, resources, state and province buildings, supply nodes, railways, adjacencies, and building, unit, and weather positions.
31
+
32
+ A rendered view takes `layer` (default `province`), up to 12 `overlays`, and an integer `scale` from 1 to 16 (default 1).
33
+
34
+ Pass `tile: { x, y, width, height }` for a reusable bounded PNG, JSON, and HTML view of one top-left bitmap area. The tile preserves the selected base layer and overlays, and its JSON records raster dimensions and province IDs in the area. Identical source revisions and render settings produce identical artifact hashes.
18
35
 
19
36
  Pass `area: { provinceIds, stateIds, regionIds, padding }` to render the exact bounding area of those map entities with optional pixel padding. The result reports the resolved tile coordinates. An unknown ID or an area larger than 2,048 pixels in either direction is explicit, so a narrower selection can be requested.
20
37
 
@@ -28,9 +45,45 @@ When no terrain category file is available, seas and lakes are checked against t
28
45
  The engine stops reading `adjacencies.csv` at its first `-1` row.
29
46
  Rows after it are not read and report `MAP_ADJACENCY_AFTER_TERMINATOR`; a file without that row reports `MAP_ADJACENCY_TERMINATOR_MISSING` as a warning, because the offline wiki describes it as required although at least one published mod omits it.
30
47
 
48
+ ## Rewrite requests
49
+
50
+ `hoi4.map_rewrite` takes an ordered list of 1 to 100 operations in `operations`, an optional integer `diffScale` from 1 to 16 for the comparison render (default 1), and an optional `requestKey` for background retries:
51
+
52
+ ```json
53
+ {
54
+ "operations": [
55
+ {
56
+ "id": "create-western-state",
57
+ "kind": "create_state",
58
+ "provinceIds": [120, 121, 122],
59
+ "displayName": "Western State"
60
+ }
61
+ ],
62
+ "diffScale": 2
63
+ }
64
+ ```
65
+
66
+ An operation list may hold up to 100 operations and is applied in order.
67
+ Every operation has a unique `id` (1 to 256 characters), an optional `summary`, and a `kind`.
68
+ The supported kinds are:
69
+
70
+ - whole maps: `create_world`;
71
+ - states: `create_state`, `split_state`, `merge_states`, `move_state_provinces`, `update_state`;
72
+ - provinces: `create_province`, `split_province`, `merge_provinces`, `remove_province`, `update_province_definition`;
73
+ - strategic regions: `move_region_provinces`;
74
+ - identifiers and script references: `renumber_map_entity`, `remap_map_references`;
75
+ - derived data: `regenerate_map_positions`, `rebuild_supply`;
76
+ - adjacency: `add_normal_adjacency`, `remove_normal_adjacency`, `add_adjacency`, `remove_adjacency`;
77
+ - supply and railways: `add_supply_node`, `remove_supply_node`, `add_railway`, `remove_railway`;
78
+ - positions: `upsert_building_position`, `remove_building_position`, `upsert_unit_position`, `remove_unit_position`, `upsert_weather_position`, `remove_weather_position`;
79
+ - entity locators: `update_entity_locator`.
80
+
81
+ The complete operation schema is [map-operation.schema.json](../schemas/map-operation.schema.json).
82
+ The examples below show single operations; each goes inside the `operations` array.
83
+
31
84
  ## Create states
32
85
 
33
- The compact `create_state` form needs selected provinces and a display name:
86
+ The compact `create_state` form needs selected provinces and a `displayName` or `name`:
34
87
 
35
88
  ```json
36
89
  {
@@ -41,7 +94,7 @@ The compact `create_state` form needs selected provinces and a display name:
41
94
  }
42
95
  ```
43
96
 
44
- When all selected provinces belong to one state, the tool infers that source state, allocates the state ID, creates `STATE_<id>` localisation, divides manpower, resources, and state buildings by land-pixel share, copies owner, controller, cores, and claims, and moves province-bound records with their provinces. Supply, railway, port, victory-point, building-position, and strategic-region references remain connected.
97
+ When all selected provinces belong to one state, the tool infers that source state, allocates the state ID, creates `STATE_<id>` localisation, divides manpower, resources, and slot buildings (factories, dockyards, refineries and other buildings that share state slots) by land-pixel share in whole units, keeps level buildings such as infrastructure, air bases, anti-air and radar at their level in both parts, carries dated history to both parts, copies owner, controller, cores, and claims, and moves province-bound records with their provinces. Supply, railway, port, victory-point, building-position, and strategic-region references remain connected.
45
98
 
46
99
  Pass `sourceStateId`, `stateId`, `name`, `fileName`, `localisation`, or the complete distribution object when the defaults are not the intended design. `split_state` retains the explicit contract for callers that want every policy written out.
47
100
 
@@ -87,16 +140,155 @@ Renumbering also inspects active event, focus, decision, scripted helper, on-act
87
140
 
88
141
  Set `collision` to `reject` to require an unused destination. Set `renameLocalisation` to `false` only when custom localisation-key handling is intentional.
89
142
 
143
+ ## Move provinces between states
144
+
145
+ `move_state_provinces` hands provinces from one state to another.
146
+ Without a `distribution` (or with `"distribution": "proportional"`) the values follow the land: the target receives the moved provinces' share of the source's land pixels of its manpower (the state's population), resources and slot buildings (factories, dockyards, refineries and the like), in whole units.
147
+ Level buildings (infrastructure, air bases, anti-air, radar) stay at their level in the source, and the target takes the higher level of the two.
148
+ Victory points and province buildings follow their province, and the moved provinces take the target's owner, controller, cores and claims because they are now part of the target.
149
+ The provinces must share the target's strategic region, or the operation stops; set `strategicRegion: "move-to-target-region"` in a full `distribution` to move them to the target's region.
150
+ Pass a full `distribution` with `stateValues: "retain-in-current-states"` to leave manpower, resources and buildings where they are, or `"proportional-by-land-pixels"` to write the automatic choice out.
151
+
152
+ ```json
153
+ {
154
+ "id": "give-province-to-neighbour",
155
+ "kind": "move_state_provinces",
156
+ "sourceStateId": 64,
157
+ "targetStateId": 65,
158
+ "provinceIds": [3314]
159
+ }
160
+ ```
161
+
162
+ Nothing is lost or duplicated: for any split, merge or move, the sums of manpower, each resource and each slot building over all states are the same before and after.
163
+
90
164
  ## Other map changes
91
165
 
92
166
  `hoi4.map_rewrite` also moves and merges states, moves provinces between strategic regions, merges or removes provinces, changes province definitions and types, adds or removes normal and special adjacency, and updates supply, railway, building, unit, weather, and entity-locator records. Send one ordered operation list when several connected changes belong together.
93
167
 
94
168
  Every rewrite returns changed-area, changed-ID, semantic, affected-file, diagnostic, and rendered comparison evidence. A failed operation does not leave a partial multi-file result.
95
169
 
170
+ ## Check script references
171
+
172
+ Set `references: true` on `hoi4.map_inspect` to also read events, focuses, decisions, scripted effects and triggers, on-actions, ideas, characters, AI strategies and areas, and country and unit history.
173
+ It reports:
174
+
175
+ - `MAP_SCRIPT_REFERENCE_MISSING`: a state, province or strategic region named by number that the map does not define, as `owns_state = 64`, `has_full_control_of_state = 64`, `transfer_state = 64`, `set_state_controller = 64`, `capital = 64`, a state scope `64 = { ... }`, a `prioritize = { 64 65 }` list, a `state`, `to_state` or `start_state` argument, a province argument such as `set_province_controller` or `province = { id = 3314 }`, a strategic region in `region = 12` or `ships_in_area`, a unit `location`, or an AI area's `strategic_regions`; an error in the mod's own files and a warning in game or dependency files;
176
+ - `MAP_STATE_TAG_UNKNOWN`: a state owner, controller, core or claim whose tag no `common/country_tags` file declares;
177
+ - `MAP_COUNTRY_CAPITAL_NOT_OWNED`: a country that owns states but has its capital in another country's state.
178
+
179
+ The data's `scriptReferences` counts the references checked and the missing ones. Numeric keys inside `random_list` and other weighted blocks are weights and are not read as states.
180
+
181
+ ## Keep scripts in step with geography
182
+
183
+ `remap_map_references` rewrites the script references of one entity kind after a split, merge, removal or renumbering:
184
+
185
+ ```json
186
+ {
187
+ "id": "brandenburg-split",
188
+ "kind": "remap_map_references",
189
+ "entity": "state",
190
+ "mapping": [
191
+ { "from": 64, "to": [64, 1082] },
192
+ { "from": 917, "to": null }
193
+ ],
194
+ "readOnlySources": "override"
195
+ }
196
+ ```
197
+
198
+ One target replaces the number. Several targets keep the first and copy the whole referencing assignment for each further target, so `64 = { add_core_of = ROOT }` becomes one block per successor and `owns_state = 64` becomes one condition per successor. In a list such as `prioritize = { 64 65 }` the extra targets join the list.
199
+ Keys that take exactly one value (`capital`, `state`, `to_state`, `start_state`, `province`, `region` and the like) are never copied or deleted: they change to the first target, and when their state has no successor they stay as they are and are reported as `MAP_REFERENCE_NEEDS_REVIEW` with the file and line, so that you choose the new target. They also remain visible to `references: true`. `null` removes the referencing assignment. Game and dependency files are never edited: with `readOnlySources: override` the files that need the change are copied into the mod with it, and otherwise the operation refuses and lists them. `pathPrefixes` limits the rewrite to some folders. Run it in the same request as the split so the review shows both.
200
+
201
+ `merge_states`, `create_state` and `split_state` can do this themselves: add `"remapReferences": "refuse"` (or `"override"`, which copies the game files that need it into the mod) and the merged-away states are renamed to the survivor, or the source state's references are extended to the new part, in the same plan.
202
+
203
+ ## Positions and supply
204
+
205
+ `regenerate_map_positions` places building, unit-stack and weather positions from province geometry. By default (`mode: missing`) it only adds what is absent: positions for each building model a state or province lacks (from `show_on_map` and the spawn points in `common/buildings`), a full unit-stack set for provinces without one, and a small and a big weather object for strategic regions without one. `mode: replace` rewrites the positions of the selected `stateIds`, `provinceIds` and `regionIds`. Interior points keep away from province borders, naval bases face the sea province they open onto, and floating harbours sit on the water and name their land province. `positions` limits it to `buildings`, `units` or `weather`; heights come from the heightmap.
206
+
207
+ `rebuild_supply` places a supply node in a state's capital province (its `capital`, else its highest victory point, else its largest land province) and joins nodes to their country's hub, the state with the most victory points, by the cheapest railway through land that belongs to a state, preferring the country's own provinces and avoiding impassable borders. `mode: connect` (the default) handles named `stateIds`, or without them only states with a supply gap: no node within three land provinces. `mode: replace` rebuilds the whole network. `railwayLevel` (default 1) and `capitalRailwayLevel` (default 3, for lines through the hub) set railway levels.
208
+
209
+ ## Create a new world
210
+
211
+ `create_world` writes a complete map for a total-conversion mod:
212
+
213
+ ```json
214
+ {
215
+ "id": "world",
216
+ "kind": "create_world",
217
+ "width": 2048,
218
+ "height": 1024,
219
+ "seed": 7,
220
+ "landCoverage": 0.35,
221
+ "continents": 3,
222
+ "countries": [
223
+ { "tag": "AUR", "name": "Aurelia" },
224
+ { "tag": "BOR", "name": "Borea", "share": 2, "ideology": "democratic" },
225
+ { "tag": "CAL", "name": "Calder", "color": { "r": 160, "g": 40, "b": 40 } }
226
+ ],
227
+ "continentNames": ["Aster", "Brum", "Corvel"]
228
+ }
229
+ ```
230
+
231
+ Width and height are multiples of 256 with at most 13,238,272 pixels. Land comes from noise around `continents` centres to the requested `landCoverage`, or from `landPolygons` in pixel coordinates; the map's east-west seam and polar rows stay sea. Provinces grow evenly from spread seeds (`landProvincePixels`, default 400, and `seaProvincePixels`, default 2,500, both capped so no province exceeds an eighth of the map), stay connected, avoid four-province corners and are at least 20 pixels. Enclosed water becomes land or, when large, a lake.
232
+
233
+ The operation writes `provinces.bmp`, `definition.csv`, `default.map`, `continent.txt`, `heightmap.bmp`, `terrain.bmp`, `rivers.bmp` (rivers run downhill to the coast), `trees.bmp`, `cities.bmp`, `world_normal.bmp`, the land and water colour maps, `adjacencies.csv`, strategic regions (`landProvincesPerRegion`, `seaProvincesPerRegion`) with weather by latitude, states (`provincesPerState`) with population, category, buildings, resources, victory points and ports, country tags, country files, history and three-band flags, a bookmark, localisation, and every position, supply node and railway. Countries grow from spread-out capitals in proportion to `share`; each state lies within one country and one strategic region.
234
+
235
+ With `replaceBaseGame` (default `true`) it adds `replace_path` lines for `history/states`, `history/countries`, `history/units`, `map/strategicregions`, `map/supplyareas` and `common/bookmarks` to `descriptor.mod`, and its info diagnostic reminds you that the launcher's `.mod` file beside the mod folder needs the same lines. Base-game events, focuses and decisions still name base-game states; `map_inspect` with `references: true` lists them for replacement or remapping. The same seed always gives the same world. Refine it with the other operations.
236
+
237
+ ## Worked example: build a world, then reshape it
238
+
239
+ 1. Create the world. The same seed always gives the same world.
240
+
241
+ ```json
242
+ {
243
+ "operations": [
244
+ {
245
+ "id": "world",
246
+ "kind": "create_world",
247
+ "width": 1024,
248
+ "height": 512,
249
+ "seed": 11,
250
+ "countries": [
251
+ { "tag": "AUR", "name": "Aurelia" },
252
+ { "tag": "BOR", "name": "Borea", "share": 2 }
253
+ ]
254
+ }
255
+ ]
256
+ }
257
+ ```
258
+
259
+ 2. Inspect it. `hoi4.map_inspect` with `references: true` lists scripts that still name base-game states. Fix those with `remap_map_references` (to a new state) or by replacing the script.
260
+
261
+ 3. Reorganise in one request. The merge folds state 12 into state 11 and rewrites every script that named 12; the move gives one province to a neighbour with its share of population, resources and factories.
262
+
263
+ ```json
264
+ {
265
+ "operations": [
266
+ {
267
+ "id": "merge",
268
+ "kind": "merge_states",
269
+ "targetStateId": 11,
270
+ "sourceStateIds": [12],
271
+ "remapReferences": "override"
272
+ },
273
+ {
274
+ "id": "move",
275
+ "kind": "move_state_provinces",
276
+ "sourceStateId": 11,
277
+ "targetStateId": 13,
278
+ "provinceIds": [402]
279
+ }
280
+ ]
281
+ }
282
+ ```
283
+
284
+ 4. Repair what a change leaves behind. `rebuild_supply` joins new or changed states to their country's supply network, `regenerate_map_positions` adds missing building, unit and weather positions, and `hoi4.map_inspect` with `references: true` must report no `MAP_SCRIPT_REFERENCE_MISSING` and no `MAP_REFERENCE_NEEDS_REVIEW` follow-ups before the mod is released.
285
+
286
+ `tests/unit/map-reorganise.test.ts` runs this sequence on a generated world and checks that totals of manpower, resources and factories are unchanged.
287
+
96
288
  ## Dated state history
97
289
 
98
290
  Map inspection reads active `common/bookmarks/*.txt` sources and uses the earliest valid bookmark date as the state-history basis. Supported owner, controller, core, claim, victory-point, and building commands in earlier dated blocks contribute to the inspected state and its rendered owner or controller layer. If no bookmark date is available, dated state fields retain their direct values and inspection reports `MAP_STATE_DATED_HISTORY_UNRESOLVED`.
99
291
 
100
- Map rewrites preserve dated source blocks byte-for-byte. An update to a field overridden by an applicable dated block returns `MAP_DATED_STATE_HISTORY_CONFLICT`. Province membership changes also block when a dated victory point or building entry would need remapping. Splitting or merging a source state with dated history returns `MAP_DATED_STATE_DISTRIBUTION_UNSUPPORTED`, because copying or deleting that history would change its later meaning. A direct edit with only later dated changes may proceed; those later commands remain and can supersede the direct value at later bookmarks. Edit the dated source deliberately when that later behavior is the intended change.
292
+ Map rewrites preserve dated source blocks byte-for-byte. An update to a field overridden by an applicable dated block returns `MAP_DATED_STATE_HISTORY_CONFLICT`. Province membership changes also block when a dated victory point or building entry would need remapping. A split divides dated blocks like the undated values: dated ownership, cores and other effects apply to both parts, dated victory points and province buildings follow their provinces, level buildings keep their level and slot buildings divide by the same land share. A merge carries the source states' dated blocks into the target, but refuses a source whose dated history sets building levels (`MAP_DATED_STATE_DISTRIBUTION_UNSUPPORTED`), because each part's later value replaces its own and the two cannot be combined; move those provinces with `move_state_provinces` or edit the block first. A merge keeps the highest level building and sums slot buildings, and its distribution policy may be omitted. A direct edit with only later dated changes may proceed; those later commands remain and can supersede the direct value at later bookmarks. Edit the dated source deliberately when that later behavior is the intended change.
101
293
 
102
294
  `floating_harbor` placement rows differ from fixed `naval_base_spawn` ports. Their XYZ coordinates normally identify a sea placement, while the final numeric field names a land target. The map catalog does not count floating-harbor placements as starting naval-base locators. A missing or non-land target is an error. An off-sea position or an unusual state/coastal association is a review warning because those patterns also occur in installed vanilla map data; the warning retains the exact source line.
package/docs/mechanics.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Mechanic tests, package checks, and scenario suites
2
2
 
3
- `hoi4.mechanic_test`, `hoi4.package_check`, and `hoi4.scenario_test` read authorized HOI4 source and return linked, revision-bound evidence.
4
- They do not launch the game or change source files.
3
+ Test scripted effects, find missing pieces of a feature and run repeatable scenarios.
4
+ `hoi4.mechanic_test`, `hoi4.package_check` and `hoi4.scenario_test` evaluate mod source and return reports tied to that source revision.
5
5
  Supply `expectedRevision` when continuing analysis against a reviewed scan.
6
6
 
7
7
  ## Test an effect
@@ -39,6 +39,8 @@ An `advance_days` step only expires modeled timed flags; it never runs on action
39
39
  }
40
40
  ```
41
41
 
42
+ The complete input schema is [mechanic-test-input.schema.json](../schemas/mechanic-test-input.schema.json).
43
+
42
44
  The linked trace records applied, skipped, and unresolved source operations with before and after values.
43
45
  The `single_payment` assertion checks the named balance's final change and the number and size of its traced deductions, so a compensating grant cannot hide a second charge.
44
46
  Supported operations include documented persistent and unscoped temporary-variable arithmetic, exact `has_variable` presence checks, flags, event targets, arrays, conditionals, finite declared scope iteration, scripted helpers, safe meta substitutions, and selected balance effects.
@@ -55,6 +57,7 @@ Add expected `definitions` and `calls` as `{ "kind": "scripted_effect", "id": "t
55
57
  The report separates present, absent, shadowed, and unresolved links and includes source hashes and locations.
56
58
  Required cases are checked for declaration; run `hoi4.scenario_test` to evaluate them.
57
59
  The manifest accepts no source patches or executable commands.
60
+ The input and manifest schemas are [package-check-input.schema.json](../schemas/package-check-input.schema.json) and [package-manifest.schema.json](../schemas/package-manifest.schema.json).
58
61
 
59
62
  ## Run a suite
60
63
 
@@ -63,6 +66,7 @@ The suite has `schemaVersion: "1.0"`, an `id`, and named `cases` in the `mechani
63
66
  A mechanic case supplies the same `test` as `hoi4.mechanic_test`; a package case supplies a `manifest`.
64
67
  A tool case names one allowed inspect, render, or evaluate operation and supplies its typed `arguments`.
65
68
  Cases may declare `sourceSelectors`, output path assertions, and `views` (`summary`, `artifacts`, `diagnostics`).
69
+ The input and suite schemas are [scenario-test-input.schema.json](../schemas/scenario-test-input.schema.json) and [scenario-suite.schema.json](../schemas/scenario-suite.schema.json).
66
70
 
67
71
  Set `maxCases` to bound a batch.
68
72
  Each case receives a content-addressed result artifact; the batch returns its counts and, while cases remain, a `continuation`.
@@ -1,33 +1,58 @@
1
1
  # AI and MTTH scenario analysis
2
2
 
3
- The probability tools explain weighted HOI4 logic under explicit world-state scenarios. They inspect real mod source or proposed in-memory source, show which conditions and modifiers apply, calculate only probabilities supported by the selected HOI4 surface, and keep every unresolved input visible.
3
+ Find out why the AI favours one choice and ignores another. Compare weights, conditions and timing to help your agent balance events, decisions, focuses and research.
4
+ The tools evaluate existing or proposed source under declared game conditions and list any missing facts.
4
5
 
5
6
  Use them for event timing and option weights, decision and mission scores, focus selection, technology and doctrine selection, direct random chances, `random_list`, supported AI strategy factors, and declared custom weighted pools.
6
7
 
7
- | Tool | Use |
8
- | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
9
- | `hoi4.probability_inspect` | Discover weighted blocks, compatible adapters, candidates, provenance, capabilities, and unsupported constructs. |
10
- | `hoi4.probability_evaluate` | Evaluate eligibility, modifier traces, raw values, proven probabilities, and MTTH horizon chances across scenarios. |
11
- | `hoi4.probability_sweep` | Sweep declared ranges and locate sensitivity changes, breakpoints, and rank reversals. |
12
- | `hoi4.probability_simulate` | Sample declared distributions with a deterministic seed and confidence intervals. |
13
- | `hoi4.probability_sequence` | Analyze only recovery, caps, cooldowns, removal, resets, timers, and terminal states declared by a custom pool manifest. |
14
- | `hoi4.probability_compare` | Attribute changes in eligibility, modifiers, values, probabilities, timing, ranks, and unresolved analysis to a proposed patch. |
15
- | `hoi4.probability_render` | Render cached ranking, matrix, waterfall, timing, sensitivity, sequence, comparison, and unresolved views. |
8
+ | Tool | Use |
9
+ | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
10
+ | `hoi4.probability_inspect` | Find weighted logic by file, identifier or candidate IDs and evaluate it: each candidate's weight and probability per scenario, the strongest first, and the facts still missing. |
11
+ | `hoi4.probability_analyze` | Deeper analysis selected by `analysis`: `compare` a proposed or frozen source, `sweep` declared ranges, `simulate` uncertain inputs, `sequence` a declared pool over time, `render` a retained analysis. |
16
12
 
17
- All seven tools are read-only. Proposed source is parsed in memory and never written. When an installed game root is configured, evaluation fails closed unless `launcher-settings.json` identifies the supported HOI4 build and checksum. Results otherwise state that they target the adapter version without claiming local-game verification.
13
+ ## Game version
18
14
 
19
- Pass a source without an adapter when the surface type is not yet known. Inspection returns every compatible adapter, candidate counts, and example candidate IDs; its discovery artifact includes every candidate ID and source location. If a requested adapter, identifier, or candidate pool does not match the source, inspection returns the same discovery result with an explanation and suggested adapter instead of `PROBABILITY_SURFACE_EMPTY`.
15
+ When `gameRoot` is configured, `launcher-settings.json` must identify the supported HOI4 build and checksum for evaluation to run. Without a game root, results identify the adapter version. Proposed source is evaluated in memory.
16
+
17
+ ## One call for current weights
18
+
19
+ `hoi4.probability_inspect` finds the weighted surface and evaluates it in the same call.
20
+ Name what to inspect in whichever way is at hand:
21
+
22
+ - `source.path` (and `source.line`) for a file or one block in it;
23
+ - `source.identifier` for a decision, mission, focus, technology, event or `random_list` ID;
24
+ - `candidatePool` alone: its first ID finds the defining file, an event ID stands for all of its options, and a `random_list` ID for all of its entries.
25
+
26
+ Without `scenarioSet` the evaluation uses one scenario with no declared facts.
27
+ Conditions that need facts stay unresolved, and `missingInputs` lists the facts to declare in a `scenarioSet` for the next call.
28
+ The inline `ranking` shows, for up to four scenarios, the twelve strongest candidates with eligibility, weight, probability and MTTH; the linked resource holds every candidate's trace.
29
+
30
+ ```json
31
+ { "candidatePool": ["my_mod.12"] }
32
+ ```
33
+
34
+ ```json
35
+ {
36
+ "source": { "path": "common/decisions/my_decisions.txt" },
37
+ "candidatePool": ["my_decision_a", "my_decision_b"],
38
+ "scenarioSet": [{ "actor": "GER", "state": { "has_war": true } }]
39
+ }
40
+ ```
41
+
42
+ When a named adapter does not match the source, such as `decision_ai_will_do` for a mission, inspection switches to the matching adapter.
43
+ Set `evaluate: false` for the inventory alone: compatible adapters, candidate counts, example IDs, and the required inputs of the selected source.
20
44
 
21
45
  Source request paths are exact workspace-relative files, such as `common/decisions/example.txt`.
22
46
  The `mod:`, `game:`, and `dependency-N:` labels in returned source citations identify origins; they are not part of a probability request's `source.path`.
23
47
 
24
48
  For a selected source, `hoi4.probability_inspect` includes missing source-condition fields in compact `requiredInputPaths`, adapter-wide completeness flags in `adapterRequiredInputPaths`, and the full candidate catalog, source provenance, and per-candidate requirements in its JSON resource. Unsupported source constructs remain unresolved evidence rather than being presented as scenario inputs. Evaluation reports eligible, excluded, and unresolved candidate counts inline; the resource preserves each candidate's exact eligibility and unresolved reasons for every scenario.
25
49
 
26
- Evaluation, sweep, simulation, and source comparison also accept an omitted adapter. When a source selector identifies one unambiguous weighted surface, the analyzer selects that source-backed adapter automatically. If a caller supplies a mismatched adapter or `custom_weighted_pool` for a source-backed request, the analyzer corrects it when the source has exactly one match. `customPoolManifest`, `beforeManifest`, and `afterManifest` use the custom-pool adapter automatically; `PROBABILITY_SURFACE_EMPTY` is reserved for sources with no weighted surface, while genuinely multi-adapter sources ask the caller to narrow by identifier or line.
50
+ Inspection, sweeps, simulation and source comparison also accept an omitted adapter. When a source selector identifies one unambiguous weighted surface, the analyzer selects that source-backed adapter automatically. If a caller supplies a mismatched adapter or `custom_weighted_pool` for a source-backed request, the analyzer corrects it when the source has exactly one match. `customPoolManifest`, `beforeManifest`, and `afterManifest` use the custom-pool adapter automatically; `PROBABILITY_SURFACE_EMPTY` is reserved for sources with no weighted surface, while genuinely multi-adapter sources ask the caller to narrow by identifier or line.
27
51
 
28
52
  ## Scenarios
29
53
 
30
- A scenario contains only state the caller is willing to declare. Missing values stay unresolved. Alternatives and ranges produce exact branches or bounds; probability distributions require `hoi4.probability_simulate`.
54
+ A scenario contains only state the caller is willing to declare. Missing values stay unresolved. Alternatives and ranges produce exact branches or bounds; probability distributions require `hoi4.probability_analyze` with `analysis: simulate`.
55
+ A scenario set may be sent as a bare list of scenarios, and scenarios without `id` or `state` get `scenario-1`, `scenario-2` and an empty state.
31
56
 
32
57
  ```json
33
58
  {
@@ -99,6 +124,8 @@ Decision and mission adapters intentionally return scores and ranks without inve
99
124
 
100
125
  `candidateOverrides` declares candidate eligibility for a scenario. It does not force weight-modifier conditions to be true or false; those conditions still use the scenario's actual declared variables, flags, scopes, and controller facts. An overridden eligibility claim is an explicit scenario assumption, not evidence that the engine makes that candidate available.
101
126
 
127
+ `analysis: sweep` takes a `sweep` object with 1 to 32 input `paths`, `steps` from 2 to 10,000 (default 25), `pairwise` (default `false`), and `findRankReversals` (default `true`).
128
+
102
129
  Named acceptance bands and configurable diagnostic thresholds let a test suite state intended probability, timing, starvation, dominance, prevalence, and sensitivity limits. Evaluate, sweep, and simulation requests can name the metrics of interest; that set is retained in result metadata while the authoritative result keeps the eligibility and trace context required to explain them. Sweeps enumerate declared alternatives exactly, add trigger breakpoints and their adjacent values for continuous ranges, and report local elasticities, pairwise interactions, rank reversals, cliffs, and missed target bands. Sweep expansion is bounded and rejected before it can silently truncate the requested analysis.
103
130
 
104
131
  ## Results
@@ -118,11 +145,14 @@ Every evaluated scope pool is stored with the scenario in authoritative JSON. Po
118
145
 
119
146
  Nested `random_list` entries report both their conditional share inside the immediate list and their full path probability through every enclosing list. Dynamic parent paths remain explicit unresolved evidence.
120
147
 
148
+ `analysis: simulate` defaults to `samples: 100000` (range 100 to 10,000,000), `seed: 1` (any 32-bit signed integer), `confidenceLevel: 0.95` (range 0.5 to 0.9999), and `samplingMethod: "latin_hypercube"`; the other sampling method is `pseudo_random`.
149
+ `analysis: sequence` uses the same `samples`, `seed`, and `confidenceLevel` defaults, requires `horizonDays`, and defaults `maxSteps` to 1,000 (range 1 to 100,000).
150
+
121
151
  Deterministic simulation uses constant-memory Latin hypercube sampling by default, with seeded pseudo-random sampling available when requested. Numeric distributions can use a Gaussian copula correlation matrix. Discrete or categorical correlation requests are sampled independently and reported as unresolved instead of being approximated silently. Simulation reports Wilson intervals, effective sample count, global input importance, and HOI4 daily-hazard MTTH samples. Timing quantiles use a deterministic bounded reservoir and include their confidence basis and retained sample count.
122
152
 
123
153
  ## Proposed patches
124
154
 
125
- Pass `inlineClausewitz` or `virtualPatch` in a source selector to analyze text without writing it. `hoi4.probability_compare` evaluates the before and after source under the same scenarios and attributes each changed rank, score, probability, or uncertainty to its modifier trace.
155
+ Pass `inlineClausewitz` or `virtualPatch` in a source selector to analyze text without writing it. `hoi4.probability_analyze` with `analysis: compare` evaluates the before and after source under the same scenarios and attributes each changed rank, score, probability, or uncertainty to its modifier trace.
126
156
 
127
157
  For a frozen file stored outside its gameplay folder, set the source selector's `path` to its logical gameplay path, `snapshotPath` to the preserved workspace-relative file, and `expectedSourceHash` to the SHA-256 of that file's exact bytes. For example, a decision copy in `docs/evidence/decisions-before.txt` can be analyzed as `common/decisions/policy.txt`. The server verifies the frozen bytes and retains their physical source provenance while using the logical path for domain recognition. It never replaces the current file. Both paths must identify exact files inside authorized roots; traversal and wildcard selectors are rejected. Shared helpers and constants still come from the current configured workspace, so one frozen file is not a complete historical workspace snapshot.
128
158
 
@@ -132,7 +162,7 @@ Sequence analysis accepts a `customPoolManifest`. The manifest is the complete m
132
162
 
133
163
  ## Visual review
134
164
 
135
- `hoi4.probability_render` produces deterministic ranking, matrix, waterfall, timing-survival, sensitivity, threshold, sequence, comparison, and unresolved views. Filters can select scenarios, candidates, and metrics. Pass the scenario hash returned by evaluation as `expectedScenarioHash` when a caller needs a render bound to that exact analysis; a stale hash returns a structured stale-result diagnostic and no visual artifact.
165
+ `analysis: render` with the `analysisId` of a retained analysis produces deterministic ranking, matrix, waterfall, timing-survival, sensitivity, threshold, sequence, comparison, and unresolved views. Filters can select scenarios, candidates, and metrics. Pass the scenario hash returned by evaluation as `expectedScenarioHash` when a caller needs a render bound to that exact analysis; a stale hash returns a structured stale-result diagnostic and no visual artifact.
136
166
 
137
167
  Adapter evidence and known boundaries are recorded in [probability-adapter-evidence.md](research/probability-adapter-evidence.md).
138
168
 
package/docs/reference.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # Local references and source lookup
2
2
 
3
- The reference tools read only local, authorized sources. They do not fetch the Paradox Wiki or start Hearts of Iron IV. The installed game's documentation has the highest authority for current syntax; the offline wiki supplies broader modding guidance. A result identifies its source, path, exact lines, and SHA-256 revision so an agent can inspect only the relevant section.
3
+ Find the right modding rule and see how vanilla uses it. The tools search local game documentation, an offline wiki and your mod source.
4
+ The installed game docs define current syntax; the wiki supplies broader guidance. Each result includes its file, lines and source revision.
4
5
 
5
6
  The server discovers these directories for a workspace:
6
7
 
@@ -14,13 +15,13 @@ Markdown headings and recognizable standalone names in generated `.log` files fo
14
15
 
15
16
  ## Tools
16
17
 
17
- - `hoi4.reference_context`: request a surface such as `event`, `focus`, `technology`, `gui`, or `map`. It reserves citations for available installed documentation and offline wiki sources before adding further question matches. Supply `question` to select the best matching section within each required source. At a limit of two or more, both source kinds are represented when available; a one-result limit prioritizes installed documentation. `omittedSources` names required sources excluded by the result limit, while `missing` names sources absent from the configured roots. Increase the limit or search an omitted source directly before treating the bundle as sufficient. Citations are pointers and excerpts; read the pertinent sections before changing code.
18
+ - `hoi4.reference_context`: request one surface: `general`, `event`, `decision`, `idea`, `focus`, `technology`, `gui`, `map`, `localisation`, or `ai`. The default limit is 16 citations and the maximum is 24. It reserves citations for available installed documentation and offline wiki sources before adding further question matches. Supply `question` to select the best matching section within each required source. At a limit of two or more, both source kinds are represented when available; a one-result limit prioritizes installed documentation. `omittedSources` names required sources excluded by the result limit, while `missing` names sources absent from the configured roots. Increase the limit or search an omitted source directly before treating the bundle as sufficient. Citations are pointers and excerpts; read the pertinent sections before changing code.
18
19
  - `hoi4.reference_search`: search with plain words or exact script tokens. Ranking weighs headings above body text and rare words above common ones, and it matches identifiers both whole and by their words, so "check if a state is controlled by a country" can find `is_controlled_by`. A query that names an identifier only matches sections containing it, an exact heading ranks first, and installed documentation precedes the wiki when they rank equally. Each result's `matchLine` is the cited line that best matches the query; pass it as `startLine` to `hoi4.reference_read` to land on the answer inside a long section. When several sources document the same name, the first copy keeps its place and later copies follow other distinct answers. The default limit is six results and the maximum is twelve. Filter `sources` to `game_doc`, `wiki`, or `script_doc` when appropriate. Only selected authorities are scanned; `coverage.included = false` means that an authority was excluded from this query, not that it is missing.
19
- - `hoi4.reference_read`: provide a search/context result's `id` and `revision`. Optionally pass its `source` for a focused authority read; resident citations provide this hint automatically. Read up to 80 lines and 8,000 UTF-8 bytes, with JSON escaping also bounded. Continue with the returned `nextLine`, `nextColumn` as `startColumn`, and the same revision. Long source lines continue without losing characters. A changed source returns `REFERENCE_REVISION_STALE`.
20
+ - `hoi4.reference_read`: provide a search/context result's `id` and `revision`. Optionally pass its `source` for a focused authority read; resident citations provide this hint automatically. Read 40 lines by default, set `maxLines` up to 80, and at most 8,000 UTF-8 bytes, with JSON escaping also bounded. Continue with the returned `nextLine`, `nextColumn` as `startColumn`, and the same revision. Long source lines continue without losing characters. A changed source returns `REFERENCE_REVISION_STALE`.
20
21
  - `hoi4.source_lookup`: find exact definitions and indexed usages in the installed game and configured mod source. The response includes load order, override status, up to three source blocks bounded to 2,000 bytes each, a scan revision, and explicit reference counts and truncation. Follow `nextLine` and `nextColumn` as `fromLine` and `fromColumn`, with `expectedRevision`, to read more of the active definition.
21
22
  - When `hoi4.source_lookup` finds no definition, `suggestions` lists up to five indexed identifiers within three edits of the requested symbol, nearest first, which catches typos and near-miss names.
22
23
  - `hoi4.source_lookup` with `path` and `line` instead of `symbol` locates a source position, such as a diagnostic or a changed line in a diff. `path` may be a result path such as `mod:events/example.txt`, a path relative to a source root, or an absolute path inside one. The result names the file's layer and whether a later layer shadows it, the indexed definitions that contain the line, innermost first, and the chain of enclosing assignments with zero-based occurrences for repeated keys. Its `keyPath` starts inside the innermost definition: pass that definition's `id` as `symbol`, its `kind`, and the `keyPath` to read or list that exact block. Without `column`, the first non-blank character of the line is used. A file with parse errors returns its definitions but no structural chain. Only the requested file's folder is scanned, in every layer.
23
- - `hoi4.script_validate`: check a bounded effect or trigger body against installed native-command documentation. Supply the body in `source`, its `kind`, and its current `scope`. Results cover syntax, command kind, and declared scope, with exact documentation citations. They do not validate command parameters or prove game execution.
24
+ - `hoi4.script_validate`: check a bounded effect or trigger body against installed native-command documentation. Supply the body in `source`, its `kind`, and its current `scope` (`country`, `state`, `character`, `combatant`, `ace`, `strategic_region`, `operation`, `industrial_org`, `purchase_contract`, `raid_instance`, `special_project`, or `faction`). `limit` (1–32, default 12) bounds the returned findings. Results cover syntax, command kind, and declared scope, with exact documentation citations. They do not validate command parameters or prove game execution.
24
25
  - `hoi4.script_validate` with `path` instead of `source` checks a whole mod file: every effect and trigger body of an event, decision, national focus, scripted effect, scripted trigger, or on-action file, with the scope the file's structure fixes. It is meant to catch the game's own load errors before launch.
25
26
 
26
27
  ## Navigate a definition
@@ -96,11 +97,78 @@ File mode reports `SCRIPT_EVENT_POPUP_REPEATED` warnings for any family and adds
96
97
  A visible event fired inside an `every_*` loop reaches one player once per loop member when it is sent to a fixed recipient (`ROOT`, `FROM`, `PREV`, `global`, a tag, an `event_target:` or a `var:` scope), or when it is `major = yes` without `fire_only_once`, because a major event is shown to every country.
97
98
  An event sent to each loop member in turn, a hidden event, and an event the scanned sources do not define are not reported.
98
99
  Scripted effects called inside a loop are checked in their own file, not followed from the caller.
100
+
101
+ ### Known mistakes
102
+
103
+ File mode also applies a short, reviewed list of mistakes that the game accepts silently or reports with an unhelpful message, and adds `known_mistakes` to `checksPerformed`.
104
+ Each finding is `KNOWN_MISTAKE_<RULE>` with the symptom and the fix in its message.
105
+ A finding that makes a definition not work (`error`) sets `valid` to `false`; the others are warnings.
106
+
107
+ | Rule | Status | Flags |
108
+ | -------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------- |
109
+ | `event_namespace_missing` | error | An event id whose namespace no events file declares with `add_namespace` (the game logs "Malformed token"). |
110
+ | `event_numeric_id_invalid` | error | An event number that is not a whole number from 0 to 99999, so events share an internal id. |
111
+ | `event_triggered_only_with_mtth` | warning | `mean_time_to_happen` on an `is_triggered_only = yes` event, which never runs the timer. |
112
+ | `event_fires_every_day` | warning | An automatic, repeatable event with no `mean_time_to_happen` or one of a day or less. |
113
+ | `news_event_not_major` | warning | A `news_event` without `major = yes`, or one that also sets `fire_only_once = yes`. |
114
+ | `event_date_window_too_tight` | warning | An automatic event whose `date` bounds are less than the 20-day trigger check apart. |
115
+ | `temp_variable_scope_prefix` | warning | A scope prefix such as `ROOT.amount` on a variable the file only sets as a temporary variable. |
116
+
117
+ The rules come from the offline wiki's Event modding "Common mistakes" and Data structures pages; each rule in `src/hoi4_agent_tools/reference/known-mistakes.json` names its source page, heading and item, and has a detector that reads the parsed file.
118
+ `hoi4.reference_context` lists the rules of the requested surface as `knownMistakes` (id, title and fix) so an author can read them before editing, and `hoi4.error_log` adds `knownMistake` to a logged message that a rule explains.
119
+ The list is shipped with the server and changes only through a reviewed commit; see [Development](development.md#adding-a-known-mistake) for how a rule is added, and how one that no longer applies is resolved.
120
+
99
121
  Search and context replies also report `limitedByBytes` when metadata exceeds their reply budget.
100
122
  Read omitted required sources with targeted calls rather than repeatedly requesting the same oversized bundle.
101
123
  Reference text supports UTF-8, Windows-1252, and explicitly BOM-marked UTF-16; native engine source encoding rules remain separate.
102
124
 
103
- Example:
125
+ ## Read the game's error log
126
+
127
+ `hoi4.error_log` reads `logs/error.log` from the game's user folder, the folder that also holds `mod/` and `save games/`.
128
+ The server finds it from the configured `gameUserRoot`, then the user folder that contains the mod when the mod sits in its `mod/` folder, then the operating system's default user folder locations.
129
+ It reads the last 16 MiB of the log, joins continuation lines, and groups identical messages with a count.
130
+
131
+ Each entry has a `category`: `syntax`, `duplicate`, `localisation`, `effect`, `trigger`, `scope`, `graphics`, `interface`, `map`, `missing_reference`, or `other`.
132
+ When the message names a file, the entry gives the file, the line when known, and its layer (`mod`, `dependency`, `game`, or `unknown`).
133
+ `changedSinceLog` is `true` when that file was modified after the log was written, so the error may already be fixed; relaunch the game to confirm.
134
+ Mod entries are listed first.
135
+
136
+ Each category in `categories` carries a `hint` that says what usually fixes it and which tool narrows it down.
137
+ `patterns` groups messages that differ only in names, numbers, quoted values and paths, such as a run of missing localisation keys, so a flood of one mistake reads as one line with its count.
138
+ An entry whose message is one of the game's wording for a [known mistake](#known-mistakes) carries `knownMistake` with the rule id and the documented fix.
139
+
140
+ The server remembers the entries of each log it reads in its own cache, keyed by the log's write time.
141
+ When the game has been relaunched since, `sinceLastLaunch` says how many entries are new, how many persist and how many the last fixes removed, with examples of the removed ones, and every entry carries `new`.
142
+
143
+ Filter with `scope` (`all`, `mod` for entries in the mod's own files, or `unlocated` for entries naming no file), `category`, or a text `query`, and page with `limit` (1–50, default 20) and `offset`.
144
+
145
+ ```json
146
+ { "scope": "mod", "category": "scope", "limit": 10 }
147
+ ```
148
+
149
+ The tool reads the log the game wrote at its last launch; it never starts the game.
150
+ Run `hoi4.script_validate` with `path` on the reported file to check the same body before the next launch.
151
+
152
+ ## Index the mod and pick free IDs
153
+
154
+ `hoi4.mod_index` with `mode: "overview"` summarizes the mod without reading every file:
155
+
156
+ - `descriptor`: the `descriptor.mod` name, version, supported game version, tags, dependencies, `replace_path` entries and Workshop ID;
157
+ - `kinds`: how many definitions of each kind the mod contains, such as events, focuses, decisions and scripted effects;
158
+ - `folders`: file counts and sizes per top-level folder, and per `common/` subfolder;
159
+ - `namespaces`: each event namespace with its number of events, lowest and highest number, and file count.
160
+
161
+ Set `layer: "all"` to count active definitions across the game, DLC, dependencies and the mod instead of the mod alone.
162
+
163
+ `mode: "next_id"` finds the next free numbered identifier for an event `namespace` or any `prefix` of one `kind` (`event`, `focus`, `decision`, `idea`, `leader` or `technology`).
164
+ It checks every source layer, so a new ID never collides with a game or dependency definition.
165
+ The result gives `nextId` after the highest used number, and `firstGapId` when a lower number is unused.
166
+
167
+ ```json
168
+ { "mode": "next_id", "kind": "event", "namespace": "my_mod" }
169
+ ```
170
+
171
+ ## Example
104
172
 
105
173
  ```json
106
174
  { "workspaceId": "current", "surface": "event", "question": "save_event_target_as" }