hoi4-agent-tools 2.2.0 → 2.3.0

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 (62) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +30 -21
  3. package/dist/bin/stdio.js +0 -4
  4. package/dist/hoi4_agent_tools/core/clausewitz-evaluation.js +90 -0
  5. package/dist/hoi4_agent_tools/core/engine.js +5 -0
  6. package/dist/hoi4_agent_tools/core/index.js +57 -1
  7. package/dist/hoi4_agent_tools/core/source/ast-path.js +41 -0
  8. package/dist/hoi4_agent_tools/core/source/index.js +1 -0
  9. package/dist/hoi4_agent_tools/event/limits.js +1 -1
  10. package/dist/hoi4_agent_tools/mcp/server/create.js +3 -1
  11. package/dist/hoi4_agent_tools/mcp/tools/probability.js +413 -0
  12. package/dist/hoi4_agent_tools/probability/adapters.js +344 -0
  13. package/dist/hoi4_agent_tools/probability/compare.js +178 -0
  14. package/dist/hoi4_agent_tools/probability/evaluation.js +649 -0
  15. package/dist/hoi4_agent_tools/probability/index.js +13 -0
  16. package/dist/hoi4_agent_tools/probability/model.js +5 -0
  17. package/dist/hoi4_agent_tools/probability/rational.js +145 -0
  18. package/dist/hoi4_agent_tools/probability/render.js +307 -0
  19. package/dist/hoi4_agent_tools/probability/sequence.js +858 -0
  20. package/dist/hoi4_agent_tools/probability/service.js +1168 -0
  21. package/dist/hoi4_agent_tools/probability/simulation.js +545 -0
  22. package/dist/hoi4_agent_tools/probability/source-analysis.js +458 -0
  23. package/dist/hoi4_agent_tools/probability/sweep.js +265 -0
  24. package/dist/hoi4_agent_tools/probability/trigger-evaluator.js +280 -0
  25. package/dist/hoi4_agent_tools/probability/value-evaluator.js +357 -0
  26. package/dist/hoi4_agent_tools/schemas/probability.js +930 -0
  27. package/dist/hoi4_agent_tools/version.js +1 -1
  28. package/docs/README.md +1 -0
  29. package/docs/development.md +2 -0
  30. package/docs/probability.md +80 -0
  31. package/docs/research/probability-adapter-evidence.md +64 -0
  32. package/examples/clients/codex-config.toml +3 -0
  33. package/examples/clients/generic.json +8 -0
  34. package/examples/probability/adaptive-event-pool.json +92 -0
  35. package/examples/probability/adaptive-event-sequence-input.json +57 -0
  36. package/examples/probability/event-mtth-scenarios.json +57 -0
  37. package/examples/probability/event-mtth-simulate-input.json +37 -0
  38. package/examples/probability/focus-route-scenarios.json +61 -0
  39. package/examples/probability/focus-route-sweep-input.json +36 -0
  40. package/package.json +17 -8
  41. package/schemas/configuration.schema.json +747 -0
  42. package/schemas/continuous-focus-palette.schema.json +325 -0
  43. package/schemas/custom-weighted-pool.schema.json +298 -0
  44. package/schemas/event-feature-manifest.schema.json +63 -0
  45. package/schemas/focus-plan.schema.json +927 -0
  46. package/schemas/focus-planning-sidecar.schema.json +407 -0
  47. package/schemas/gui-animation-source.schema.json +176 -0
  48. package/schemas/gui-helper.schema.json +301 -0
  49. package/schemas/gui-scenario.schema.json +298 -0
  50. package/schemas/map-operation.schema.json +2284 -0
  51. package/schemas/operation-result.schema.json +327 -0
  52. package/schemas/probability-analysis-result.schema.json +2211 -0
  53. package/schemas/probability-compare-input.schema.json +664 -0
  54. package/schemas/probability-evaluate-input.schema.json +665 -0
  55. package/schemas/probability-inspect-input.schema.json +97 -0
  56. package/schemas/probability-render-input.schema.json +141 -0
  57. package/schemas/probability-scenario-set.schema.json +430 -0
  58. package/schemas/probability-sequence-input.schema.json +886 -0
  59. package/schemas/probability-simulate-input.schema.json +691 -0
  60. package/schemas/probability-sweep-input.schema.json +702 -0
  61. package/server.json +3 -3
  62. package/dist/hoi4_agent_tools/mcp/tools/chaosx.js +0 -530
@@ -1,6 +1,6 @@
1
1
  import { LATEST_PROTOCOL_VERSION } from '@modelcontextprotocol/sdk/types.js';
2
2
  export const PACKAGE_NAME = 'hoi4-agent-tools';
3
- export const PACKAGE_VERSION = '2.2.0';
3
+ export const PACKAGE_VERSION = '2.3.0';
4
4
  export const MCP_PROTOCOL_VERSION = LATEST_PROTOCOL_VERSION;
5
5
  export const CONFIG_VERSION = 1;
6
6
  export const TRANSACTION_VERSION = 1;
package/docs/README.md CHANGED
@@ -3,6 +3,7 @@
3
3
  - [Setup](setup.md): install the server, configure HOI4 paths, and connect an MCP client.
4
4
  - [Event chains](events.md): inspect, trace, lint, render, and compare event chains.
5
5
  - [Technology trees](technology.md): inspect, trace, lint, render, and compare technologies and doctrines.
6
+ - [AI and MTTH analysis](probability.md): evaluate weighted logic, timing, uncertainty, sequences, and patches.
6
7
  - [Focus trees](focus.md): inspect, create, render, and clean national or continuous focus content.
7
8
  - [Scripted GUIs](gui.md): inspect linked UI source, render states, and create or repair GUIs.
8
9
  - [Maps](map.md): inspect and edit provinces, states, regions, adjacency, supply, and railways.
@@ -23,6 +23,8 @@ The event-chain acceptance fixture contains more than 300 project-owned event de
23
23
 
24
24
  The technology acceptance fixture contains 1,040 project-owned technologies across 13 folders and exercises classic and current doctrines, prerequisites, exclusive branches, multiple placements, unlocks, bonuses, grants, assets, unresolved references, rendering, and comparison.
25
25
 
26
+ The probability fixture contains more than 150 weighted blocks, 250 scenarios, and a declared stateful pool. Run `npm run benchmark` after analyzer changes. On the July 22, 2026 reference run, cold indexing took 28 ms, a cached block evaluation 29 ms, the 250-row matrix 85 ms, one million draws 9 ms, 3/12/25-candidate sequence cases 20/2,079/356 ms, and retrieval of a 1.84 MB result 3 ms. Review budgets are 250 ms, 150 ms, 750 ms, 100 ms, 200/10,000/3,000 ms, and 100 ms respectively; accuracy, method metadata, and omitted probability must not be weakened to meet them.
27
+
26
28
  Local opt-in tests can also read an installed game and an external mod without copying their sources:
27
29
 
28
30
  ```bash
@@ -0,0 +1,80 @@
1
+ # AI and MTTH scenario analysis
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.
4
+
5
+ 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
+ | Tool | Use |
8
+ | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
9
+ | `hoi4.probability_inspect` | Discover weighted blocks, 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. |
16
+
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.
18
+
19
+ ## Scenarios
20
+
21
+ 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`.
22
+
23
+ ```json
24
+ {
25
+ "schemaVersion": "1.0",
26
+ "id": "route_states",
27
+ "scenarios": [
28
+ {
29
+ "id": "defensive_war",
30
+ "actor": "EXM",
31
+ "date": "1939.9.1",
32
+ "state": {
33
+ "has_war": true,
34
+ "variable.foreign_influence": 45,
35
+ "focus.external_factors_complete": true
36
+ },
37
+ "flags": ["route_independent"]
38
+ }
39
+ ]
40
+ }
41
+ ```
42
+
43
+ Focus, technology, and doctrine probabilities require a complete candidate pool. Their engine rule is an independent uniform score race, not weight divided by total weight. Focus scenarios use `focus.external_factors_complete: true` only after the caller has supplied every relevant prerequisite and strategy factor. Technology and doctrine scenarios use `technology.external_factors_complete: true` only after cost, date, bonus, strategy, and candidate effects are accounted for.
44
+
45
+ Decision and mission adapters intentionally return scores and ranks without inventing normalized probabilities. Event-option and `random_list` adapters normalize only their complete local pools. Direct random remains an independent percentage. MTTH horizon chance uses the versioned game timing model and returns a bound when an inactive-to-active polling phase is unknown.
46
+
47
+ 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.
48
+
49
+ ## Results
50
+
51
+ Authoritative JSON keeps these fields separate:
52
+
53
+ - eligibility;
54
+ - raw value or raw interval;
55
+ - conditional selection probability or deterministic probability interval;
56
+ - effective MTTH and cumulative time chance;
57
+ - sampled frequency and statistical confidence interval;
58
+ - scenario prevalence.
59
+
60
+ Every candidate includes source provenance with a stable AST path, an ordered modifier trace, support level, and unresolved analysis. `external` support means the parsed candidate is valid but its surrounding game factors were not fully declared. The tool response stays compact; complete matrices, traces, simulations, comparisons, and visuals are linked MCP resources.
61
+
62
+ 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.
63
+
64
+ 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.
65
+
66
+ ## Proposed patches
67
+
68
+ 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.
69
+
70
+ ## Declared sequences
71
+
72
+ Sequence analysis accepts a `customPoolManifest`. The manifest is the complete model boundary: candidates, selection mode, cadence, state, recovery, caps, cooldowns, removals, resets, timer changes, and terminal states. Small finite systems use exact state distributions, bounded systems expose omitted beam mass, and large systems use deterministic seeded Monte Carlo. Results include per-candidate and per-category next-choice probability, expected selections, ever-selected probability, starvation, and expected first-selection day. The analyzer never executes event effects or infers wider campaign state.
73
+
74
+ ## Visual review
75
+
76
+ `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.
77
+
78
+ Adapter evidence and known boundaries are recorded in [probability-adapter-evidence.md](research/probability-adapter-evidence.md).
79
+
80
+ Callable argument examples are in [`examples/probability`](../examples/probability). Generated JSON Schemas for every operation, scenario sets, custom pools, and authoritative results are in [`schemas`](../schemas).
@@ -0,0 +1,64 @@
1
+ # Probability adapter evidence
2
+
3
+ The AI and MTTH Scenario Analyzer targets Hearts of Iron IV **Operation Postern 1.19.2.0 (checksum d245)**. Adapter behavior is versioned as `hoi4-1.19.2.v1`; results always include that adapter version and game build.
4
+
5
+ This review used the installed game's documentation, vanilla source examples, and an offline Paradox wiki snapshot. Paths below are relative to a Hearts of Iron IV installation or to the offline snapshot. SHA-256 values identify the exact files reviewed on 2026-07-22.
6
+
7
+ ## Adapter semantics
8
+
9
+ | Adapter | Proven interpretation | Exact probability conditions | Deliberate boundary |
10
+ | ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
11
+ | `event_mean_time_to_happen` | Ordered `base`, `add`, and `factor` operations produce an effective duration. When the trigger is active, `M` days is the median of daily checks, so daily hazard is `1 - 2^(-1/M)`. Inactive event triggers are polled every 20 days. | A time-horizon chance is exact only while trigger state, every modifier input, scheduled change, and any inactive-to-active polling phase are declared. | It does not execute events or infer state changes. Missing poll phase produces a 0–20 day activation bound. |
12
+ | `event_option_ai_chance` | Options form one proportional categorical pool. An omitted block has weight 1. An all-zero pool selects the first option. | Every option and eligibility result for the event must be present. | The engine's d100 selection granularity is reported for effective shares below one percent. |
13
+ | `decision_ai_will_do` and `mission_ai_will_do` | Ordered source modifiers produce a raw desirability score after eligibility. | No normalized probability is claimed. | Local documentation does not prove a complete categorical denominator or a universal selection formula. |
14
+ | `national_focus_ai_will_do` | Each eligible focus receives an independent uniform draw from zero to its evaluated score; the maximum wins. A just-completed prerequisite and AI strategy focus factors can change the score. | The complete eligible candidate pool and every external focus factor must be declared. Exact probabilities use the independent-uniform maximum race, not `weight / sum(weight)`. | Ordered AI strategy plans can override weighted choice and are reported rather than simulated. |
15
+ | `technology_ai_will_do` and `doctrine_ai_will_do` | Eligible candidates use the independent-uniform maximum-score race. Research factors, cost, date, bonuses, and forced strategy choices can alter or override ranking. | The complete eligible pool and all external research factors must be declared. | Research duration is not selection probability. Forced research strategies and wider research-slot scheduling are not simulated. |
16
+ | `direct_random` | `chance` is an independent percentage in `[0,100]`. | The chance expression must resolve. | It is never normalized against neighboring blocks. |
17
+ | `random_list` | Entries form the complete local proportional weight pool. Nested entries retain their immediate conditional share and multiply through enclosing lists for a full path probability. | Every entry, enclosing list, and modifier on the selected path must resolve. | Dynamic entry identifiers, dynamic parent paths, or effect-derived values remain unresolved unless supplied explicitly. |
18
+ | `ai_strategy_factor` | Supported strategy types modify a target score. `research_weight_factor` is a percentage factor; positive `research_tech` forces prioritization. | Raw factor evaluation is exact when the strategy and target are explicit. | A strategy definition is not itself normalized into a probability pool. |
19
+ | `custom_weighted_pool` | The manifest declares categorical or independent selection plus recovery, caps, cooldowns, removals, resets, timer changes, and terminal states. | Exact finite-state analysis is used while the state space stays bounded; otherwise the result is explicitly beam-bounded or seeded Monte Carlo. | Only declared state transitions run. Gameplay effects and campaign state are never inferred or executed. |
20
+
21
+ ## Installed documentation reviewed
22
+
23
+ | Relative path | SHA-256 | Used for |
24
+ | ----------------------------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------- |
25
+ | `launcher-settings.json` | `f99265973bba12f30906cc98629d8520218ff8cd90a5f9d1d82e7f00fb737b9e` | Installed game version and checksum |
26
+ | `common/decisions/_documentation.md` | `5e7e686b5582f32c38d898d805e17171e88f3bfeee4a030deb1884f9726de019` | Decision scopes, eligibility surfaces, and evaluation cadence |
27
+ | `common/doctrines/_documentation.md` | `f0d1b7ad1f1dc8afe59942a406784a2d72c0c73dd42963c2502f89961eea85d4` | Current doctrine definitions and AI fields |
28
+ | `common/script_constants/documentation.md` | `e2812efbddc7961038e1f1f2b6dd6b059bdc70704ec87d1fe530835d9141be1c` | `constant:` schema and nested constant paths |
29
+ | `documentation/script_concept_documentation.md` | `884bfe9f9207ea4b25b36b5129d0f77d11d4b2f7eb0592587767ec58d24930c7` | Script constants and dynamic script concepts |
30
+ | `documentation/effects_documentation.md` | `2cdc93d26775990468eed167442f7a416b13059fb8fe07d139b54250b79209af` | `random_list` and AI strategy effect syntax |
31
+ | `common/ai_strategy/_documentation.md` | `70f5d755ae7ed4060e49cc64a393d1a0dc5611b3acc8abc6dfb4538781c915a1` | `research_tech` and `research_weight_factor` behavior |
32
+
33
+ The offline wiki pages `AI modding`, `Data structures`, `Decision modding`, `Event modding`, `National focus modding`, `Scopes`, and `Technology modding` were reviewed in parallel. Their respective SHA-256 values were `f1fdb9fd…a14f`, `20a03385…a14f`, `500e8161…68c`, `b0186d9b…e00`, `b1c7f624…6faf`, `04866815…fdc`, and `48050261…fdc`.
34
+
35
+ ## Vanilla examples reviewed
36
+
37
+ | Surface | Relative path and line | SHA-256 |
38
+ | ----------------------------- | -------------------------------------------------------------- | ------------------------------------------------------------------ |
39
+ | Event MTTH | `events/Yugoslavia.txt:49` | `138279b294ef0d567e477efe2f0ebb72c5c0a7f2920ed3fd03d2792749624dbc` |
40
+ | Event option `ai_chance` | `events/AAT_Generic_Events.txt:44` | `e718d19edba2d56c75a5bbf1fa0c51bbb6cda54e0919434c4490fec9dabcea69` |
41
+ | Decision `ai_will_do` | `common/decisions/_generic_decisions.txt:56` | `83cd276f8fd2c0c90470225c996d7afee7b8c08437289dd23d819a4a29edb187` |
42
+ | Focus `ai_will_do` | `common/national_focus/austria.txt:122` | `0f197e321cb9e0c267a11c78bccb570ef42d1fc251e7af05fb4f385de27a1059` |
43
+ | Technology `ai_will_do` | `common/technologies/industry.txt:30` | `06d45f11a0bfdee35ef72b935b2bee3b0083a49eb771e5c6b9391c087ed7d94f` |
44
+ | Current doctrine `ai_will_do` | `common/doctrines/grand_doctrines/land_grand_doctrines.txt:14` | `cd81a877366c582f096422320cd7fcf9fb259afcc8d45d3dbb887b37792b329d` |
45
+ | `random_list` | `events/AAT_Sweden.txt:1760` | `8fad5c10d147afab27eb42c78f3261c804cd6149f1c81927418ab0bbe3b8bf29` |
46
+ | Direct `random` | `events/BBA_Switzerland.txt:1197` | `4331bbe2ea7d0844eb357ecd73f915c1ba3e5a0b115ae62ea5b95a8011e1145e` |
47
+ | AI research strategy factor | `common/ai_strategy/ENG.txt:3206` | `f6fed5347c68ab2a3b79e4864dc5d72490c9cabe46a16e865932d2e5a37716d9` |
48
+
49
+ The installed vanilla inventory contained 71 event files with MTTH, 101 with `ai_chance`, 86 decision files with `ai_will_do`, 76 national-focus files, 13 technology files, 19 doctrine files, 38 event files with `random_list`, and 9 AI strategy files with `research_weight_factor`. These counts were used to select examples and to test discovery breadth; they are not runtime assumptions.
50
+
51
+ ## Unsupported constructs
52
+
53
+ When a game root is configured, adapter execution verifies `launcher-settings.json` against the supported raw version and checksum and fails closed on a missing, unreadable, or different build. Without a configured game root, results identify the adapter target without claiming that an installed build was verified.
54
+
55
+ The analyzer reports, but does not guess or execute:
56
+
57
+ - arbitrary effects used to calculate later weights;
58
+ - unprovided scopes, event targets, game rules, DLC state, dynamic identifiers, meta effects, or scripted-localisation results;
59
+ - parameterized scripted triggers whose arguments cannot be resolved from the selected source;
60
+ - recursive MTTH variables or helper cycles;
61
+ - incomplete focus, technology, doctrine, event-option, or random-list candidate pools;
62
+ - categorical or discrete correlation requests; numeric ranges and numeric distributions are supported by the correlation sampler;
63
+ - invalid or non-positive-semidefinite correlation matrices;
64
+ - full strategic AI planning, research-slot scheduling, event-effect execution, or campaign simulation.
@@ -0,0 +1,3 @@
1
+ [mcp_servers.hoi4_agent_tools]
2
+ command = "npx"
3
+ args = ["-y", "hoi4-agent-tools@latest"]
@@ -0,0 +1,8 @@
1
+ {
2
+ "mcpServers": {
3
+ "hoi4_agent_tools": {
4
+ "command": "npx",
5
+ "args": ["-y", "hoi4-agent-tools@latest"]
6
+ }
7
+ }
8
+ }
@@ -0,0 +1,92 @@
1
+ {
2
+ "schemaVersion": "1.0",
3
+ "id": "adaptive_event_pool_example",
4
+ "description": "Declared pool with recovery, repeat caps, category growth, reset, removal, and timer compression.",
5
+ "selection": {
6
+ "mode": "categorical_weighted",
7
+ "cadence": "timer",
8
+ "timerMinDays": 45,
9
+ "timerMaxDays": 60,
10
+ "rounding": "nearest"
11
+ },
12
+ "state": {
13
+ "minor_events_since_major": 0,
14
+ "major_gain": 150,
15
+ "timer_compression": 0
16
+ },
17
+ "candidates": [
18
+ {
19
+ "id": "minor_fire_once",
20
+ "category": "fire_once",
21
+ "weight": 1000,
22
+ "cap": 1000,
23
+ "eligibleWhen": "not selected.minor_fire_once",
24
+ "oneTime": true
25
+ },
26
+ {
27
+ "id": "minor_repeatable",
28
+ "category": "repeatable",
29
+ "weight": 1000,
30
+ "cap": 1000,
31
+ "eligibleWhen": "true",
32
+ "cooldownDays": 0
33
+ },
34
+ {
35
+ "id": "major_crisis",
36
+ "category": "major",
37
+ "weight": 0,
38
+ "cap": 1000,
39
+ "eligibleWhen": "not selected.major_crisis",
40
+ "oneTime": true
41
+ }
42
+ ],
43
+ "recovery": [
44
+ {
45
+ "cadence": "monthly",
46
+ "target": "candidate.minor_repeatable.weight",
47
+ "amount": 20,
48
+ "cap": "candidate.minor_repeatable.cap"
49
+ }
50
+ ],
51
+ "transitions": [
52
+ {
53
+ "when": "selected.category != major",
54
+ "actions": [
55
+ { "operation": "add", "target": "state.minor_events_since_major", "value": 1 },
56
+ {
57
+ "operation": "add",
58
+ "target": "candidate.major_crisis.weight",
59
+ "value": "state.major_gain"
60
+ },
61
+ {
62
+ "operation": "compress_timer",
63
+ "target": "selection.timer_max_days",
64
+ "value": "floor(state.minor_events_since_major / 3)"
65
+ }
66
+ ]
67
+ },
68
+ {
69
+ "when": "selected.id == minor_repeatable",
70
+ "actions": [
71
+ { "operation": "multiply", "target": "candidate.minor_repeatable.cap", "value": 0.5 },
72
+ {
73
+ "operation": "cap",
74
+ "target": "candidate.minor_repeatable.weight",
75
+ "value": "candidate.minor_repeatable.cap"
76
+ }
77
+ ]
78
+ },
79
+ {
80
+ "when": "selected.category == major",
81
+ "actions": [
82
+ { "operation": "set", "target": "state.minor_events_since_major", "value": 0 },
83
+ { "operation": "reset_category", "target": "category.major", "value": 0 },
84
+ { "operation": "reset_timer", "target": "selection", "value": null }
85
+ ]
86
+ },
87
+ {
88
+ "when": "selected.one_time == true",
89
+ "actions": [{ "operation": "remove", "target": "selected.candidate", "value": null }]
90
+ }
91
+ ]
92
+ }
@@ -0,0 +1,57 @@
1
+ {
2
+ "scenarioSet": {
3
+ "schemaVersion": "1.0",
4
+ "id": "pool_baseline",
5
+ "scenarios": [{ "id": "baseline", "state": {} }]
6
+ },
7
+ "customPoolManifest": {
8
+ "schemaVersion": "1.0",
9
+ "id": "adaptive_event_pool_example",
10
+ "selection": {
11
+ "mode": "categorical_weighted",
12
+ "cadence": "timer",
13
+ "timerMinDays": 45,
14
+ "timerMaxDays": 60,
15
+ "rounding": "nearest"
16
+ },
17
+ "state": { "minor_events_since_major": 0, "major_gain": 150 },
18
+ "candidates": [
19
+ { "id": "minor_repeatable", "category": "minor", "weight": 1000, "cap": 1000 },
20
+ { "id": "major_crisis", "category": "major", "weight": 0, "cap": 1000, "oneTime": true }
21
+ ],
22
+ "recovery": [
23
+ {
24
+ "cadence": "monthly",
25
+ "target": "candidate.minor_repeatable.weight",
26
+ "amount": 20,
27
+ "cap": "candidate.minor_repeatable.cap"
28
+ }
29
+ ],
30
+ "transitions": [
31
+ {
32
+ "when": "selected.category != major",
33
+ "actions": [
34
+ {
35
+ "operation": "add",
36
+ "target": "candidate.major_crisis.weight",
37
+ "value": "state.major_gain"
38
+ },
39
+ { "operation": "compress_timer", "target": "selection.timer_max_days", "value": 1 }
40
+ ]
41
+ },
42
+ {
43
+ "when": "selected.category == major",
44
+ "actions": [
45
+ { "operation": "reset_category", "target": "category.major", "value": 0 },
46
+ { "operation": "reset_timer", "target": "selection", "value": null }
47
+ ]
48
+ }
49
+ ]
50
+ },
51
+ "horizonDays": 720,
52
+ "maxSteps": 1000,
53
+ "samples": 250000,
54
+ "seed": 3601,
55
+ "confidenceLevel": 0.95,
56
+ "outputs": ["json", "ranking", "timing", "sequence", "unresolved"]
57
+ }
@@ -0,0 +1,57 @@
1
+ {
2
+ "schemaVersion": "1.0",
3
+ "id": "event_mtth_timeline_examples",
4
+ "surfaceHint": "event_mean_time_to_happen",
5
+ "scenarios": [
6
+ {
7
+ "id": "contained_outbreak",
8
+ "label": "Contained outbreak with later containment failure",
9
+ "actor": "EXM",
10
+ "date": "1940.1.1",
11
+ "state": {
12
+ "variable.outbreak_pressure": 25,
13
+ "variable.chaos": 350,
14
+ "has_war": false
15
+ },
16
+ "flags": ["outbreak_active", "containment_program_active"],
17
+ "schedule": [
18
+ {
19
+ "atDay": 60,
20
+ "set": { "variable.outbreak_pressure": 45 }
21
+ },
22
+ {
23
+ "atDay": 120,
24
+ "set": { "variable.chaos": 650 },
25
+ "clearFlags": ["containment_program_active"]
26
+ }
27
+ ]
28
+ },
29
+ {
30
+ "id": "uncertain_pressure",
31
+ "label": "Pressure and war state sampled",
32
+ "actor": "EXM",
33
+ "date": "1940.1.1",
34
+ "state": { "variable.chaos": 500 },
35
+ "flags": ["outbreak_active"],
36
+ "uncertainInputs": [
37
+ {
38
+ "path": "variable.outbreak_pressure",
39
+ "distribution": {
40
+ "kind": "triangular",
41
+ "min": 20,
42
+ "mode": 50,
43
+ "max": 90
44
+ }
45
+ },
46
+ {
47
+ "path": "has_war",
48
+ "distribution": {
49
+ "kind": "categorical",
50
+ "values": [true, false],
51
+ "probabilities": [0.35, 0.65]
52
+ }
53
+ }
54
+ ]
55
+ }
56
+ ]
57
+ }
@@ -0,0 +1,37 @@
1
+ {
2
+ "adapter": "event_mean_time_to_happen",
3
+ "source": { "identifier": "example_outbreak.42" },
4
+ "scenarioSet": {
5
+ "schemaVersion": "1.0",
6
+ "id": "outbreak_simulation",
7
+ "surfaceHint": "event_mean_time_to_happen",
8
+ "scenarios": [
9
+ {
10
+ "id": "uncertain_pressure",
11
+ "actor": "EXM",
12
+ "date": "1940.1.1",
13
+ "state": { "variable.chaos": 500 },
14
+ "flags": ["outbreak_active"],
15
+ "uncertainInputs": [
16
+ {
17
+ "path": "variable.outbreak_pressure",
18
+ "distribution": { "kind": "triangular", "min": 20, "mode": 50, "max": 90 }
19
+ },
20
+ {
21
+ "path": "has_war",
22
+ "distribution": {
23
+ "kind": "categorical",
24
+ "values": [true, false],
25
+ "probabilities": [0.35, 0.65]
26
+ }
27
+ }
28
+ ]
29
+ }
30
+ ]
31
+ },
32
+ "horizonDays": 365,
33
+ "samples": 100000,
34
+ "seed": 19400101,
35
+ "confidenceLevel": 0.95,
36
+ "outputs": ["json", "timing", "waterfall", "unresolved"]
37
+ }
@@ -0,0 +1,61 @@
1
+ {
2
+ "schemaVersion": "1.0",
3
+ "id": "focus_route_choice_examples",
4
+ "surfaceHint": "national_focus_ai_will_do",
5
+ "description": "Representative country states for evaluating the next focus choice.",
6
+ "scenarios": [
7
+ {
8
+ "id": "peace_low_industry",
9
+ "label": "Peace with weak industry",
10
+ "actor": "EXM",
11
+ "date": "1938.1.1",
12
+ "state": {
13
+ "has_war": false,
14
+ "num_of_military_factories": 8,
15
+ "stability": 0.62,
16
+ "world_tension": 0.28,
17
+ "focus.external_factors_complete": true
18
+ },
19
+ "flags": ["route_independent"]
20
+ },
21
+ {
22
+ "id": "defensive_war",
23
+ "label": "Defensive war under pressure",
24
+ "actor": "EXM",
25
+ "date": "1939.9.1",
26
+ "state": {
27
+ "has_war": true,
28
+ "is_in_defensive_war": true,
29
+ "num_of_military_factories": 12,
30
+ "stability": 0.45,
31
+ "world_tension": 0.74,
32
+ "focus.external_factors_complete": true
33
+ },
34
+ "flags": ["route_independent", "border_crisis_active"]
35
+ },
36
+ {
37
+ "id": "uncertain_foreign_support",
38
+ "label": "Foreign support uncertain",
39
+ "actor": "EXM",
40
+ "date": "1939.3.1",
41
+ "state": {
42
+ "has_war": false,
43
+ "num_of_military_factories": 10,
44
+ "stability": 0.55,
45
+ "world_tension": 0.52,
46
+ "focus.external_factors_complete": true
47
+ },
48
+ "flags": ["route_independent"],
49
+ "uncertainInputs": [
50
+ {
51
+ "path": "has_flag.foreign_support_secured",
52
+ "alternatives": [true, false]
53
+ },
54
+ {
55
+ "path": "variable.foreign_influence",
56
+ "range": { "min": 20, "max": 80 }
57
+ }
58
+ ]
59
+ }
60
+ ]
61
+ }
@@ -0,0 +1,36 @@
1
+ {
2
+ "adapter": "national_focus_ai_will_do",
3
+ "source": { "identifier": "EXM_prepare_the_border" },
4
+ "scenarioSet": {
5
+ "schemaVersion": "1.0",
6
+ "id": "focus_route_sweep",
7
+ "surfaceHint": "national_focus_ai_will_do",
8
+ "scenarios": [
9
+ {
10
+ "id": "uncertain_foreign_support",
11
+ "actor": "EXM",
12
+ "date": "1939.3.1",
13
+ "state": {
14
+ "has_war": false,
15
+ "stability": 0.55,
16
+ "world_tension": 0.52,
17
+ "focus.external_factors_complete": true
18
+ },
19
+ "uncertainInputs": [
20
+ {
21
+ "path": "variable.foreign_influence",
22
+ "range": { "min": 20, "max": 80 }
23
+ }
24
+ ]
25
+ }
26
+ ]
27
+ },
28
+ "candidatePool": ["EXM_expand_industry", "EXM_prepare_the_border", "EXM_seek_foreign_support"],
29
+ "sweep": {
30
+ "paths": ["variable.foreign_influence"],
31
+ "steps": 25,
32
+ "pairwise": false,
33
+ "findRankReversals": true
34
+ },
35
+ "outputs": ["json", "ranking", "matrix", "waterfall", "sensitivity", "unresolved"]
36
+ }
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "hoi4-agent-tools",
3
3
  "mcpName": "io.github.klimPaskov/hoi4-agent-tools",
4
- "version": "2.2.0",
5
- "description": "Analyze HOI4 events and technology trees; create and clean focus trees, GUIs, and maps.",
4
+ "version": "2.3.0",
5
+ "description": "Analyze HOI4 events, tech trees, AI weights, and MTTH; build focus trees, GUIs, and maps.",
6
6
  "type": "module",
7
7
  "license": "Apache-2.0",
8
8
  "author": "HOI4 Agent Tools contributors",
@@ -24,6 +24,9 @@
24
24
  "event-chains",
25
25
  "technology-trees",
26
26
  "doctrines",
27
+ "ai-weights",
28
+ "mtth",
29
+ "probability-analysis",
27
30
  "hoi4-events",
28
31
  "scripted-gui",
29
32
  "hoi4-map"
@@ -37,11 +40,16 @@
37
40
  "docs/setup.md",
38
41
  "docs/events.md",
39
42
  "docs/technology.md",
43
+ "docs/probability.md",
44
+ "docs/research/probability-adapter-evidence.md",
40
45
  "docs/focus.md",
41
46
  "docs/gui.md",
42
47
  "docs/map.md",
43
48
  "docs/http.md",
44
49
  "docs/development.md",
50
+ "examples/clients/",
51
+ "examples/probability/",
52
+ "schemas/",
45
53
  "server.json",
46
54
  "README.md",
47
55
  "CHANGELOG.md",
@@ -66,12 +74,13 @@
66
74
  "test:local": "tsx scripts/run-local-tests.ts",
67
75
  "test:coverage": "vitest run --coverage",
68
76
  "benchmark": "node --expose-gc --import tsx scripts/benchmark.ts",
69
- "fixtures:generate": "npm run fixtures:generate:focus && npm run fixtures:generate:gui && npm run fixtures:generate:map && npm run fixtures:generate:event && npm run fixtures:generate:technology",
77
+ "fixtures:generate": "npm run fixtures:generate:focus && npm run fixtures:generate:gui && npm run fixtures:generate:map && npm run fixtures:generate:event && npm run fixtures:generate:technology && npm run fixtures:generate:probability",
70
78
  "fixtures:generate:focus": "tsx scripts/generate-fixtures.ts",
71
79
  "fixtures:generate:gui": "tsx scripts/generate-gui-fixture.ts",
72
80
  "fixtures:generate:map": "tsx scripts/generate-map-fixture.ts",
73
81
  "fixtures:generate:event": "tsx scripts/generate-event-fixture.ts",
74
82
  "fixtures:generate:technology": "tsx scripts/generate-technology-fixture.ts",
83
+ "fixtures:generate:probability": "tsx scripts/generate-probability-fixture.ts",
75
84
  "fixtures:check": "npm run fixtures:generate && tsx scripts/check-generated.ts fixtures",
76
85
  "schemas:generate": "tsx scripts/generate-schemas.ts",
77
86
  "schemas:check": "tsx scripts/generate-schemas.ts && tsx scripts/check-generated.ts schemas",
@@ -92,13 +101,13 @@
92
101
  "fast-glob": "3.3.3",
93
102
  "fontkit": "2.0.4",
94
103
  "iconv-lite": "0.7.3",
95
- "jose": "6.2.3",
104
+ "jose": "6.2.4",
96
105
  "sharp": "0.35.3",
97
106
  "zod": "4.4.3"
98
107
  },
99
108
  "devDependencies": {
100
109
  "@eslint/js": "10.0.1",
101
- "@modelcontextprotocol/inspector": "0.22.0",
110
+ "@modelcontextprotocol/inspector": "1.0.0",
102
111
  "@types/express": "5.0.6",
103
112
  "@types/fontkit": "2.0.9",
104
113
  "@types/node": "22.20.1",
@@ -109,10 +118,10 @@
109
118
  "eslint": "10.7.0",
110
119
  "fast-check": "4.9.0",
111
120
  "pixelmatch": "7.2.0",
112
- "prettier": "3.9.5",
113
- "tsx": "4.23.0",
121
+ "prettier": "3.9.6",
122
+ "tsx": "4.23.1",
114
123
  "typescript": "6.0.3",
115
- "typescript-eslint": "8.63.0",
124
+ "typescript-eslint": "8.65.0",
116
125
  "vitest": "4.1.10"
117
126
  },
118
127
  "overrides": {