hoi4-agent-tools 4.6.3 → 4.6.5

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 (56) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/hoi4_agent_tools/core/artifacts.js +9 -2
  3. package/dist/hoi4_agent_tools/core/changed-summary.js +41 -0
  4. package/dist/hoi4_agent_tools/core/domain-scan-patterns.js +9 -1
  5. package/dist/hoi4_agent_tools/core/job-transactions.js +24 -2
  6. package/dist/hoi4_agent_tools/core/job-worker-host.js +5 -1
  7. package/dist/hoi4_agent_tools/core/transaction-execution.js +12 -0
  8. package/dist/hoi4_agent_tools/map/references.js +26 -1
  9. package/dist/hoi4_agent_tools/map/render.js +29 -3
  10. package/dist/hoi4_agent_tools/map/service.js +3 -0
  11. package/dist/hoi4_agent_tools/map/tool-operations.js +5 -0
  12. package/dist/hoi4_agent_tools/version.js +1 -1
  13. package/docs/map.md +5 -2
  14. package/docs/troubleshooting.md +12 -11
  15. package/npm-shrinkwrap.json +2 -2
  16. package/package.json +1 -1
  17. package/schemas/configuration.schema.json +1 -1
  18. package/schemas/continuous-focus-palette.schema.json +1 -1
  19. package/schemas/custom-weighted-pool.schema.json +1 -1
  20. package/schemas/decision-inspect-input.schema.json +1 -1
  21. package/schemas/error-log-input.schema.json +1 -1
  22. package/schemas/event-feature-manifest.schema.json +1 -1
  23. package/schemas/focus-plan.schema.json +1 -1
  24. package/schemas/focus-planning-sidecar.schema.json +1 -1
  25. package/schemas/geography-model.schema.json +1 -1
  26. package/schemas/gui-animation-source.schema.json +1 -1
  27. package/schemas/gui-helper.schema.json +1 -1
  28. package/schemas/gui-scenario.schema.json +1 -1
  29. package/schemas/helper-expansion-request.schema.json +1 -1
  30. package/schemas/helper-expansion-summary.schema.json +1 -1
  31. package/schemas/impact-inspect-input.schema.json +1 -1
  32. package/schemas/map-operation.schema.json +1 -1
  33. package/schemas/mechanic-test-input.schema.json +1 -1
  34. package/schemas/mod-index-input.schema.json +1 -1
  35. package/schemas/operation-result.schema.json +1 -1
  36. package/schemas/package-check-input.schema.json +1 -1
  37. package/schemas/package-manifest.schema.json +1 -1
  38. package/schemas/probability-analysis-result.schema.json +1 -1
  39. package/schemas/probability-compare-input.schema.json +1 -1
  40. package/schemas/probability-evaluate-input.schema.json +1 -1
  41. package/schemas/probability-inspect-input.schema.json +1 -1
  42. package/schemas/probability-render-input.schema.json +1 -1
  43. package/schemas/probability-scenario-set.schema.json +1 -1
  44. package/schemas/probability-sequence-input.schema.json +1 -1
  45. package/schemas/probability-simulate-input.schema.json +1 -1
  46. package/schemas/probability-sweep-input.schema.json +1 -1
  47. package/schemas/reference-context-input.schema.json +1 -1
  48. package/schemas/reference-read-input.schema.json +1 -1
  49. package/schemas/reference-search-input.schema.json +1 -1
  50. package/schemas/reference-sheets.schema.json +1 -1
  51. package/schemas/scenario-suite.schema.json +1 -1
  52. package/schemas/scenario-test-input.schema.json +1 -1
  53. package/schemas/script-validate-input.schema.json +1 -1
  54. package/schemas/shared-scenario.schema.json +1 -1
  55. package/schemas/source-lookup-input.schema.json +1 -1
  56. package/server.json +2 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## 4.6.5 - 2026-11-01
4
+
5
+ - Say how much a map rewrite changed when its file list is cut. The inline result lists at most a bounded number of changed files, so a world write of thousands of files could read as if little or nothing changed. Every applied map rewrite now adds `data.changedSummary`: the total of changed files, how many were created, removed and modified, and the same counts for the 40 folders with the most changes (two levels deep, largest first, `omittedFolders` for the rest). The full list stays in the transaction artifacts.
6
+ - Write a world over an existing world of the same size. The review renders stored before the write listed every building, unit and weather position twice (before and proposed, JSON and HTML, about 90 MB each for a 5120 x 2560 world), and a replaced world changes every position, so the batch passed the fixed 512 MiB in-memory ceiling (`ARTIFACT_LOGICAL_BATCH_LIMIT`) or ran the worker out of memory. The before and proposed renders now count positions instead of listing them (the pictures still draw them), and `map-diff.json` lists at most 2,000 changed positions per kind with the full count in `positionChanges`. On the measured ZIN world the position records were 64 MB of each 88 MB render catalog. `ARTIFACT_LOGICAL_BATCH_LIMIT` and `ARTIFACT_STORAGE_LIMIT` now name the size reached, the limit and the three largest artifacts, and `JOB_WORKER_EXIT` adds the job's last progress message.
7
+ - Stop two false map reference findings from `hoi4.map_inspect` with `references: true`. `state = 0`, as in `NOT = { state = 0 }`, tests for a valid state and is no longer an error for a missing state 0 (8 errors on Chaos Redux). A province id in a `prioritize` list, which the effects documentation gives state ids only (vanilla `prioritize = { 521 7564 }`, 26 entries), is now its own finding `MAP_SCRIPT_PRIORITIZE_PROVINCE` (a warning in the mod's files, information in game files) and no longer counts as a missing state. On Chaos Redux the missing references fall from 36 to the 2 that are real.
8
+
9
+ ## 4.6.4 - 2026-11-01
10
+
11
+ - Write a large world without hitting the scan limit. The check after a map write read every changed file again, bitmaps and textures included, with the base game's files of the same names: 270 MB for a 5120 x 2560 world, past the default `scanMaxBytes` of 256 MiB, so the write was restored after seven minutes with `SCAN_BYTE_LIMIT`. It now reads the changed text files only. See the amendment to ADR 0047.
12
+ - Name what a scan limit error crossed. A restored rewrite stopped by `SCAN_BYTE_LIMIT` or `SCAN_FILE_LIMIT` now says which file, how many bytes were read and the limit in its message, and a file larger than `scanMaxFileBytes` stops the rewrite before anything is written.
13
+
3
14
  ## 4.6.3 - 2026-11-01
4
15
 
5
16
  - Write a world over a mod whose output inventory lists files the world does not manage. `.hoi4-agent-world.json` could record files that were never outputs of a generated world (for example country tag files and localisation files registered by the mod's own tooling), and one such entry made every write fail with `MANAGED_OUTPUT_MANIFEST_INVALID`. A safe relative path outside the allow-list is now left alone (never read, compared, edited or deleted), dropped from the next inventory and reported (`MAP_WORLD_OUTPUT_RECORD_IGNORED`, `data.outputs`). A path that could leave the workspace, or a duplicate, still refuses the inventory. See the amendment to ADR 0052.
@@ -10,6 +21,7 @@
10
21
 
11
22
  ## Unreleased
12
23
 
24
+ - Add the shared Rust HOI4 engine in `engine/` (ADR 0074): a lossless parser that round-trips all 7,717 vanilla 1.19.3.0 script and localisation files byte for byte, a symbol index over the game, DLC folders, dependencies and the mod in load order, a reference closure that reports every reference as resolved, unresolved or unknown with coverage per kind, lints whose vocabulary is read from the installed game's documentation, an override and `replace_path` audit that reports dropped definitions and `on_actions` hooks, a findings baseline that fails only on new findings, and the `hoi4-engine` command for the modding kit's `check.py`. Harvested from Hagane Studio with written permission: span repair plans, finding deltas, the dead-flag and DLC rules and a draw.io focus importer (`engine/PROVENANCE.md`). The CWTools MD Edition spike is in `docs/research/cwtools-md-edition-spike.md`. No MCP tool uses the engine yet, and the npm package is unchanged.
13
25
  - Raise the pinned overrides of three transitive dependencies to their fixed releases, clearing every `npm audit --omit=dev` advisory: `fast-uri` 3.1.9 (GHSA-w74x-v6f9-j3xg, GHSA-xhq7-xmqj-769h, GHSA-wjr9-j795-jxcr, GHSA-333x-w4r6-6crp), `hono` 4.13.13 (GHSA-5r4p-p66f-jhc7) and `ip-address` 10.7.4 (GHSA-rxp7-6hxx-x8q5). No source or schema change.
14
26
 
15
27
  ## 4.6.1 - 2026-10-26
@@ -268,9 +268,16 @@ async function preflightArtifactBatch(writes, limits, signal) {
268
268
  const preparationCeiling = Math.min(maxBytes, artifactLogicalBatchMaxBytes);
269
269
  if (totalBytes > preparationCeiling) {
270
270
  const fixedCeilingApplies = artifactLogicalBatchMaxBytes <= maxBytes;
271
- throw new ServiceError(fixedCeilingApplies ? 'ARTIFACT_LOGICAL_BATCH_LIMIT' : 'ARTIFACT_STORAGE_LIMIT', fixedCeilingApplies
271
+ const largest = writes
272
+ .map(({ name }, index) => ({ name, size: contentLengths[index] }))
273
+ .sort((left, right) => right.size - left.size || compareCodeUnits(left.name, right.name))
274
+ .slice(0, 3);
275
+ const mib = (bytes) => `${(bytes / 1_048_576).toFixed(1)} MiB`;
276
+ throw new ServiceError(fixedCeilingApplies ? 'ARTIFACT_LOGICAL_BATCH_LIMIT' : 'ARTIFACT_STORAGE_LIMIT', `${fixedCeilingApplies
272
277
  ? 'Logical artifact batch exceeds the fixed in-memory preparation ceiling'
273
- : 'Logical artifact batch exceeds the configured aggregate artifact-byte limit', { size: totalBytes, maximumBytes: preparationCeiling });
278
+ : 'Logical artifact batch exceeds the configured aggregate artifact-byte limit'} (${mib(totalBytes)} in ${writes.length} artifacts, limit ${mib(preparationCeiling)}; largest: ${largest
279
+ .map(({ name, size }) => `${name} ${mib(size)}`)
280
+ .join(', ')})`, { size: totalBytes, maximumBytes: preparationCeiling, artifacts: writes.length, largest });
274
281
  }
275
282
  if (projectedEntries > maxEntries) {
276
283
  throw new ServiceError('ARTIFACT_STORAGE_LIMIT', 'Artifact batch exceeds the configured artifact-entry limit', { projectedEntries, maximumEntries: maxEntries });
@@ -0,0 +1,41 @@
1
+ /** The folder a path is counted in: its directory, at most two levels deep (`.` for the root). */
2
+ function folderOf(relativePath) {
3
+ const parts = relativePath.replaceAll('\\', '/').split('/');
4
+ parts.pop();
5
+ return parts.length === 0 ? '.' : parts.slice(0, 2).join('/');
6
+ }
7
+ /**
8
+ * A bounded count of what a rewrite changed, so a response whose file list is cut still says how
9
+ * much changed: created, removed and modified files in total and per folder. Deterministic.
10
+ */
11
+ export function summarizeChangedFiles(files, limit = 40) {
12
+ const byFolder = new Map();
13
+ let created = 0;
14
+ let removed = 0;
15
+ let modified = 0;
16
+ for (const file of files) {
17
+ const kind = file.beforeSha256 === null ? 'created' : file.afterSha256 === null ? 'removed' : 'modified';
18
+ if (kind === 'created')
19
+ created += 1;
20
+ else if (kind === 'removed')
21
+ removed += 1;
22
+ else
23
+ modified += 1;
24
+ const folder = folderOf(file.relativePath);
25
+ const entry = byFolder.get(folder) ?? { folder, created: 0, removed: 0, modified: 0 };
26
+ entry[kind] += 1;
27
+ byFolder.set(folder, entry);
28
+ }
29
+ const ranked = [...byFolder.values()].sort((left, right) => right.created +
30
+ right.removed +
31
+ right.modified -
32
+ (left.created + left.removed + left.modified) || (left.folder < right.folder ? -1 : 1));
33
+ return {
34
+ total: files.length,
35
+ created,
36
+ removed,
37
+ modified,
38
+ folders: ranked.slice(0, limit),
39
+ omittedFolders: Math.max(0, ranked.length - limit),
40
+ };
41
+ }
@@ -83,9 +83,17 @@ export function countryAssetDiscoveryPatterns(workspace) {
83
83
  * lists provinces that `map/definition.csv` defines, usually in the base game, so a scan of the
84
84
  * changed files alone would report every listed province as unresolved.
85
85
  */
86
+ /** Bitmaps, textures and flags carry no script to parse; the map validation reads the ones it needs. */
87
+ const BINARY_EXTENSION = /\.(?:bmp|dds|tga|png|jpg|jpeg|gif|wav|ogg|mp3|ttf|otf)$/iu;
88
+ /**
89
+ * What the check after a map write reads: the changed text files, without the large binary files of
90
+ * a world (a 5120 x 2560 world is 150 MB of bitmaps and textures, 270 MB with the base game's files
91
+ * of the same names, past the default scan limit). The map validation that follows reads the
92
+ * bitmaps it needs itself.
93
+ */
86
94
  export function mapChangeScanPatterns(relativePaths) {
87
95
  return uniquePatterns([
88
- ...exactChangedFilePatterns(relativePaths),
96
+ ...exactChangedFilePatterns(relativePaths.filter((path) => !BINARY_EXTENSION.test(path))),
89
97
  'map/default.map',
90
98
  'map/*.csv',
91
99
  ]);
@@ -128,12 +128,34 @@ export class JobTransactions {
128
128
  * Why the write stopped: the error code and message of a service error, else only the error
129
129
  * kind, followed by the first check or diagnostic of the transaction that failed validation.
130
130
  */
131
- function failureCause(error, transaction) {
131
+ /** The size figures of a scan limit error, so the message names the file and the limit. */
132
+ function scanLimitText(details) {
133
+ if (details === undefined)
134
+ return '';
135
+ const mb = (value) => typeof value === 'number' ? `${(value / 1_048_576).toFixed(1)} MiB` : '?';
136
+ const parts = [];
137
+ if (typeof details.file === 'string')
138
+ parts.push(`file ${details.file}${details.fileBytes === undefined ? '' : ` (${mb(details.fileBytes)})`}`);
139
+ if (details.bytes !== undefined && details.limit !== undefined)
140
+ parts.push(`${mb(details.bytes)} read of the ${mb(details.limit)} scan limit`);
141
+ if (details.perFileLimit !== undefined)
142
+ parts.push(`per-file limit ${mb(details.perFileLimit)}`);
143
+ if (typeof details.files === 'number' &&
144
+ typeof details.limit === 'number' &&
145
+ details.bytes === undefined)
146
+ parts.push(`${details.files} files against the limit of ${details.limit}`);
147
+ return parts.length === 0 ? '' : ` [${parts.join('; ')}]`;
148
+ }
149
+ export function failureCause(error, transaction) {
132
150
  const recorded = transaction.failure === undefined
133
151
  ? ''
134
152
  : `${transaction.failure.code}: ${transaction.failure.message}`;
153
+ // A rewrite that was restored wraps the error that stopped it; the wrapped error is the cause.
154
+ const inner = error?.details?.cause;
135
155
  const cause = error instanceof ServiceError
136
- ? `${error.code}: ${error.message}`
156
+ ? inner?.code === undefined
157
+ ? `${error.code}: ${error.message}`
158
+ : `${inner.code}: ${inner.message ?? error.message}${inner.code.startsWith('SCAN_') ? scanLimitText(inner.details) : ''}`
137
159
  : error instanceof Error
138
160
  ? error.name
139
161
  : recorded;
@@ -326,7 +326,11 @@ export class JobWorkerHost {
326
326
  }
327
327
  if (child.exitCode !== null || child.signalCode !== null) {
328
328
  const evidence = await this.exits.get(child);
329
- throw new ServiceError('JOB_WORKER_EXIT', evidence === undefined ? WORKER_EXIT_MESSAGE : classifyWorkerExit(evidence).message);
329
+ const message = evidence === undefined ? WORKER_EXIT_MESSAGE : classifyWorkerExit(evidence).message;
330
+ // The job's last progress report says how far the worker got before it stopped.
331
+ throw new ServiceError('JOB_WORKER_EXIT', record.progress === undefined
332
+ ? message
333
+ : `${message}; last progress: ${record.progress.message.slice(0, 160)}`);
330
334
  }
331
335
  await delay(100);
332
336
  }
@@ -17,6 +17,7 @@ export class AutonomousRewriteError extends ServiceError {
17
17
  : 'Rewrite failed and automatic recovery could not be completed', {
18
18
  execution: 'failed',
19
19
  automaticRecovery: restored ? 'restored' : 'incomplete',
20
+ cause: { code: cause.code, message: cause.message, details: cause.details },
20
21
  });
21
22
  this.manifest = manifest;
22
23
  this.artifacts = artifacts;
@@ -71,6 +72,16 @@ export function autonomousResultArtifacts(execution) {
71
72
  ...execution.transaction.artifacts,
72
73
  ]);
73
74
  }
75
+ /**
76
+ * A written file larger than the per-file scan limit could never be read back by a later scan, so
77
+ * the rewrite stops before it writes anything, naming the file and the limit.
78
+ */
79
+ function assertFilesWithinScanLimit(engine, transaction) {
80
+ const limit = engine.resolver.config().scanMaxFileBytes;
81
+ const over = transaction.files.find(({ afterSize }) => (afterSize ?? 0) > limit);
82
+ if (over !== undefined)
83
+ throw new ServiceError('SCAN_BYTE_LIMIT', `${over.relativePath} would be ${over.afterSize} bytes, above the per-file scan limit of ${limit} bytes (scanMaxFileBytes); raise the limit in the server configuration or shrink the file`, { file: over.relativePath, fileBytes: over.afterSize, perFileLimit: limit });
84
+ }
74
85
  /**
75
86
  * Complete a validated domain rewrite inside one MCP tool call. Hash checks, durable recovery,
76
87
  * post-write validation, and automatic failure recovery remain internal guarantees.
@@ -82,6 +93,7 @@ export async function executePlannedTransaction(engine, transaction, principal,
82
93
  if (transaction.files.length === 0)
83
94
  return { transaction, outcome: 'unchanged', artifacts: [] };
84
95
  signal?.throwIfAborted();
96
+ assertFilesWithinScanLimit(engine, transaction);
85
97
  await hooks.beforeApply?.(transaction);
86
98
  signal?.throwIfAborted();
87
99
  let executionArtifacts = [];
@@ -194,6 +194,9 @@ export function collectMapScriptReferences(files) {
194
194
  const entity = fieldEntity(file.relativePath, key);
195
195
  if (entity === undefined)
196
196
  return;
197
+ // State ids start at 1: `state = 0` (usually `NOT = { state = 0 }`) tests for a valid state.
198
+ if (entity === 'state' && Number(entry.value.value) === 0)
199
+ return;
197
200
  references.push({
198
201
  entity,
199
202
  id: Number(entry.value.value),
@@ -216,6 +219,28 @@ export function missingMapReferenceDiagnostics(references, exists) {
216
219
  if (exists[reference.entity](reference.id))
217
220
  continue;
218
221
  const owned = reference.file.rootKind === 'mod' || reference.file.rootKind === 'fixture';
222
+ if (reference.entity === 'state' &&
223
+ reference.form === 'list' &&
224
+ STATE_LIST_BLOCKS.has(reference.key) &&
225
+ exists.province(reference.id)) {
226
+ // The game's documentation gives `prioritize` state ids only; a province id there (vanilla
227
+ // pairs a state with a port, `prioritize = { 521 7564 }`) is a separate, milder finding.
228
+ diagnostics.push({
229
+ code: 'MAP_SCRIPT_PRIORITIZE_PROVINCE',
230
+ severity: owned ? 'warning' : 'info',
231
+ category: 'map',
232
+ message: `${reference.file.relativePath} lists ${reference.id} in prioritize, which the map defines as a province, not a state; the effects documentation gives prioritize state ids only`,
233
+ location: nodeLocation(reference.document, reference.node),
234
+ details: {
235
+ entity: reference.entity,
236
+ id: reference.id,
237
+ key: reference.key,
238
+ form: reference.form,
239
+ layer: reference.file.rootKind,
240
+ },
241
+ });
242
+ continue;
243
+ }
219
244
  diagnostics.push({
220
245
  code: 'MAP_SCRIPT_REFERENCE_MISSING',
221
246
  severity: owned ? 'error' : 'warning',
@@ -433,7 +458,7 @@ export function mapScriptConsistency(index) {
433
458
  province: (id) => index.definitionsById.has(id),
434
459
  'strategic-region': (id) => index.regionsById.has(id),
435
460
  });
436
- const missing = diagnostics.length;
461
+ const missing = diagnostics.filter(({ code }) => code === 'MAP_SCRIPT_REFERENCE_MISSING').length;
437
462
  const tags = declaredCountryTags(index.sourceFiles);
438
463
  if (tags !== undefined)
439
464
  for (const state of index.states) {
@@ -6,6 +6,8 @@ import { borderQualityInputFromIndex } from './border-quality-input.js';
6
6
  import { borderEdgePixels, forEachBorderEdge, measureBorderNaturalness } from './border-quality.js';
7
7
  import { buildMapCatalog } from './catalog.js';
8
8
  import { validateMapAsync } from './validation.js';
9
+ /** Position records named in a review diff artifact, per kind; the rest are counted. */
10
+ export const MAP_DIFF_POSITION_RECORD_LIMIT = 2_000;
9
11
  function stableColor(key) {
10
12
  const hash = sha256Bytes(key);
11
13
  const first = Number.parseInt(hash.slice(0, 2), 16);
@@ -313,10 +315,13 @@ async function applyOverlays(index, bytes, overlays, signal) {
313
315
  }
314
316
  }
315
317
  }
316
- async function renderMetadata(index, options, signal) {
318
+ async function renderMetadata(index, options, signal, positionRecords = 'all') {
317
319
  const catalog = buildMapCatalog(index);
318
320
  return {
319
321
  ...catalog,
322
+ ...(positionRecords === 'counts'
323
+ ? { buildingPositions: [], unitPositions: [], weatherPositions: [], positionRecords }
324
+ : {}),
320
325
  renderer: 'hoi4-agent-tools-map-workbench',
321
326
  layer: options.layer,
322
327
  overlays: options.overlays,
@@ -486,7 +491,7 @@ export async function renderMap(index, options = {}) {
486
491
  }
487
492
  const png = await encodePng(raw, raster.width, raster.height, resolved.scale);
488
493
  options.signal?.throwIfAborted();
489
- const json = `${canonicalJson(await renderMetadata(index, resolved, options.signal))}\n`;
494
+ const json = `${canonicalJson(await renderMetadata(index, resolved, options.signal, options.positionRecords))}\n`;
490
495
  const provinceHitMap = await encodeProvinceHitMap(index);
491
496
  const html = htmlDocument(`HOI4 map - ${resolved.layer}`, png, provinceHitMap, json, resolved.scale);
492
497
  return {
@@ -693,6 +698,27 @@ export function semanticMapDiff(before, after) {
693
698
  normalAdjacenciesChanged: normalAdjacencies.length > 0,
694
699
  };
695
700
  }
701
+ /**
702
+ * The semantic diff for the artifact, with at most `MAP_DIFF_POSITION_RECORD_LIMIT` building,
703
+ * unit and weather position changes listed per kind: a replaced world changes every position,
704
+ * which would make the review artifact hundreds of megabytes. The counts stay complete.
705
+ */
706
+ export function boundedPositionDiffs(semantic) {
707
+ const kinds = ['buildingPositions', 'unitPositions', 'weatherPositions'];
708
+ const over = kinds.filter((kind) => semantic[kind].length > MAP_DIFF_POSITION_RECORD_LIMIT);
709
+ if (over.length === 0)
710
+ return { semantic };
711
+ const bounded = { ...semantic };
712
+ const positionChanges = {};
713
+ for (const kind of over) {
714
+ bounded[kind] = semantic[kind].slice(0, MAP_DIFF_POSITION_RECORD_LIMIT);
715
+ positionChanges[kind] = {
716
+ total: semantic[kind].length,
717
+ listed: MAP_DIFF_POSITION_RECORD_LIMIT,
718
+ };
719
+ }
720
+ return { semantic: bounded, positionChanges };
721
+ }
696
722
  function uniqueNumbers(values) {
697
723
  return [...new Set(values)].sort((left, right) => left - right);
698
724
  }
@@ -744,7 +770,7 @@ export async function renderMapDiff(before, after, options = {}) {
744
770
  renderer: 'hoi4-agent-tools-map-diff',
745
771
  changedBounds: changedBounds ?? null,
746
772
  changedProvinceIds: [...changedProvinceIds].sort((a, b) => a - b),
747
- semantic,
773
+ ...boundedPositionDiffs(semantic),
748
774
  ...(options.review === undefined ? {} : { review: options.review }),
749
775
  };
750
776
  const json = `${canonicalJson(metadata)}\n`;
@@ -577,6 +577,7 @@ async function wholeMapDiff(after, options) {
577
577
  const rendered = await renderMap(after, {
578
578
  layer: 'state',
579
579
  overlays: ['coastlines', 'ports', 'victory-points', 'supply-nodes', 'railways'],
580
+ positionRecords: 'counts',
580
581
  ...(options?.scale === undefined ? {} : { scale: options.scale }),
581
582
  ...(options?.signal === undefined ? {} : { signal: options.signal }),
582
583
  ...(options?.budget === undefined ? {} : { budget: options.budget }),
@@ -1238,6 +1239,7 @@ export class AgentNudger {
1238
1239
  ? renderMap(snapshot.index, {
1239
1240
  layer: 'state',
1240
1241
  overlays: [...comparisonOverlays],
1242
+ positionRecords: 'counts',
1241
1243
  ...(options.scale === undefined ? {} : { scale: options.scale }),
1242
1244
  ...(options.signal === undefined ? {} : { signal: options.signal }),
1243
1245
  budget,
@@ -1246,6 +1248,7 @@ export class AgentNudger {
1246
1248
  renderMap(plan.finalIndex, {
1247
1249
  layer: 'state',
1248
1250
  overlays: [...comparisonOverlays],
1251
+ positionRecords: 'counts',
1249
1252
  ...(options.scale === undefined ? {} : { scale: options.scale }),
1250
1253
  ...(options.signal === undefined ? {} : { signal: options.signal }),
1251
1254
  budget,
@@ -6,6 +6,7 @@ import { autonomousResultArtifacts, } from '../core/transaction-execution.js';
6
6
  import { emptyServiceResult, ServiceError } from '../core/result.js';
7
7
  import { setInlineFilesScanned } from '../core/operation-result.js';
8
8
  import { PACKAGE_VERSION } from '../version.js';
9
+ import { summarizeChangedFiles } from '../core/changed-summary.js';
9
10
  import { allocateMapIdentifiersAsync, WORLD_OUTPUT_PATH_SAMPLE, } from './operations.js';
10
11
  import { compactTerritoryReport } from './territory-operations.js';
11
12
  import { borderQualityDiagnostics } from './border-quality.js';
@@ -360,6 +361,10 @@ export function completeMapRewrite(workspaceId, execution, recipe) {
360
361
  ...parsed.data,
361
362
  fileCount: transaction.files.length,
362
363
  artifactCount: transaction.artifacts.length,
364
+ // The file list is cut to 100 and a long response is cut again; the counts always arrive.
365
+ ...(execution.outcome === 'applied'
366
+ ? { changedSummary: summarizeChangedFiles(transaction.files) }
367
+ : {}),
363
368
  });
364
369
  result.status = transaction.validation.passed ? 'ok' : 'blocked';
365
370
  result.code =
@@ -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 = '4.6.3';
3
+ export const PACKAGE_VERSION = '4.6.5';
4
4
  export const MCP_PROTOCOL_VERSION = LATEST_PROTOCOL_VERSION;
5
5
  export const CONFIG_VERSION = 1;
6
6
  export const TRANSACTION_VERSION = 2;
package/docs/map.md CHANGED
@@ -426,14 +426,15 @@ Measured on project-owned synthetic fixtures (ADR 0060): country-border enrichme
426
426
 
427
427
  `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.
428
428
 
429
- 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.
429
+ 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. The before and proposed renders (`map-before.*`, `map-proposed.*`) draw every overlay but list building, unit and weather positions only as counts (`positionRecords: "counts"`); `hoi4.map_inspect` returns the records. `map-diff.json` lists at most 2,000 changed building, unit and weather positions per kind and gives the full number in `positionChanges`. The review of a replaced world, where every position changes, would otherwise reach hundreds of megabytes.
430
430
 
431
431
  ## Check script references
432
432
 
433
433
  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.
434
434
  It reports:
435
435
 
436
- - `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;
436
+ - `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; `state = 0` (as in `NOT = { state = 0 }`, a test for a valid state) is not a reference;
437
+ - `MAP_SCRIPT_PRIORITIZE_PROVINCE`: a number in a `prioritize` list that the map defines as a province, not a state; `prioritize` takes state ids, so the entry is reported on its own (a warning in the mod's files, information in game or dependency files) and not as a missing reference;
437
438
  - `MAP_STATE_TAG_UNKNOWN`: a state owner, controller, core or claim whose tag no `common/country_tags` file declares;
438
439
  - `MAP_COUNTRY_CAPITAL_NOT_OWNED`: a country that owns states but has its capital in another country's state.
439
440
 
@@ -517,6 +518,8 @@ The operation writes `provinces.bmp`, `definition.csv`, `default.map`, `continen
517
518
 
518
519
  Each write records its generated files in `.hoi4-agent-world.json`. A later `create_world` deletes the recorded files it no longer writes (retires them) in the same transaction and refuses with `MANAGED_OUTPUT_EDITED` when a recorded file was edited since. `MAP_WORLD_OUTPUTS_RECONCILED` and `data.outputs` give the counts of written, retired and released files with up to 200 paths each; `map-world-outputs.json` lists them all.
519
520
 
521
+ Every applied map rewrite also returns `data.changedSummary` with the number of changed files (`total`, `created`, `removed`, `modified`) and the same counts for the 40 folders with the most changes (two levels deep, `.` for the mod root, `omittedFolders` for the rest), so the size of a write is visible even when the inline `changedFiles` list is cut.
522
+
520
523
  ### Countries the mod already owns
521
524
 
522
525
  A mod that writes its own country tags, country files, histories, orders of battle, flags and names gives `countries` as an object instead of an array (ADR 0069):
@@ -37,17 +37,18 @@ This page lists the codes you are most likely to meet, then the checks for probl
37
37
 
38
38
  Use the error code to find what prevented a focus, GUI or map edit.
39
39
 
40
- | Code | Cause and fix |
41
- | ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
42
- | `TRANSACTION_STALE` | A source file changed after the review was made. Inspect again and repeat the rewrite on the current source. |
43
- | `TRANSACTION_RECOVERY_REQUIRED` | An earlier rewrite was interrupted and its journal could not be recovered yet. Reads still work; the message names the reason. Restart the server, and repair the named file if it persists. |
44
- | `TRANSACTION_ROLLBACK_STALE` | A file changed since the rewrite, so it cannot be rolled back safely. Restore the file from version control. |
45
- | `MAP_STATE_DISTRIBUTION_REQUIRED` | A state operation was given an incomplete explicit policy. Omit `distribution` for the automatic land-share policy, or send every field (see [Maps](map.md)). |
46
- | `MAP_STATE_REGION_DISTRIBUTION_CONFLICT` | Moved or merged provinces lie in different strategic regions. Use `strategicRegion: "move-to-target-region"`, or move the provinces between regions first. |
47
- | `MAP_EXTERNAL_REFERENCE_READ_ONLY` | Base-game or dependency scripts name a changed state. Repeat with `remapReferences` or `readOnlySources` set to `override` to copy them into the mod with the numbers changed. |
48
- | `MAP_DATED_STATE_HISTORY_CONFLICT` | A dated block (`1939.1.1 = { ... }`) overrides the value you are changing. Edit that block, or change the later date's value deliberately. |
49
- | `MAP_SCRIPT_REFERENCE_MISSING` (error) | A script names a state, province or region the map does not define. Remap it with `remap_map_references`, or correct the script. |
50
- | `MAP_REFERENCE_NEEDS_REVIEW` (info) | A single-valued argument such as `capital = 64` had no single successor and was left as it was. Choose its new target by hand. |
40
+ | Code | Cause and fix |
41
+ | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
42
+ | `TRANSACTION_STALE` | A source file changed after the review was made. Inspect again and repeat the rewrite on the current source. |
43
+ | `TRANSACTION_RECOVERY_REQUIRED` | An earlier rewrite was interrupted and its journal could not be recovered yet. Reads still work; the message names the reason. Restart the server, and repair the named file if it persists. |
44
+ | `TRANSACTION_ROLLBACK_STALE` | A file changed since the rewrite, so it cannot be rolled back safely. Restore the file from version control. |
45
+ | `MAP_STATE_DISTRIBUTION_REQUIRED` | A state operation was given an incomplete explicit policy. Omit `distribution` for the automatic land-share policy, or send every field (see [Maps](map.md)). |
46
+ | `MAP_STATE_REGION_DISTRIBUTION_CONFLICT` | Moved or merged provinces lie in different strategic regions. Use `strategicRegion: "move-to-target-region"`, or move the provinces between regions first. |
47
+ | `MAP_EXTERNAL_REFERENCE_READ_ONLY` | Base-game or dependency scripts name a changed state. Repeat with `remapReferences` or `readOnlySources` set to `override` to copy them into the mod with the numbers changed. |
48
+ | `MAP_DATED_STATE_HISTORY_CONFLICT` | A dated block (`1939.1.1 = { ... }`) overrides the value you are changing. Edit that block, or change the later date's value deliberately. |
49
+ | `MAP_SCRIPT_REFERENCE_MISSING` (error) | A script names a state, province or region the map does not define. Remap it with `remap_map_references`, or correct the script. |
50
+ | `MAP_SCRIPT_PRIORITIZE_PROVINCE` | A `prioritize = { ... }` list holds a province id where the effects documentation gives state ids only (vanilla pairs states with ports, `prioritize = { 521 7564 }`). Replace it with the state that holds the province. |
51
+ | `MAP_REFERENCE_NEEDS_REVIEW` (info) | A single-valued argument such as `capital = 64` had no single successor and was left as it was. Choose its new target by hand. |
51
52
 
52
53
  ## Game and live testing
53
54
 
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "hoi4-agent-tools",
3
- "version": "4.6.3",
3
+ "version": "4.6.5",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "hoi4-agent-tools",
9
- "version": "4.6.3",
9
+ "version": "4.6.5",
10
10
  "license": "Apache-2.0",
11
11
  "dependencies": {
12
12
  "@fontsource-variable/roboto": "5.3.0",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "hoi4-agent-tools",
3
3
  "mcpName": "io.github.klimPaskov/hoi4-agent-tools",
4
- "version": "4.6.3",
4
+ "version": "4.6.5",
5
5
  "description": "Build HOI4 mods: focus trees, events, decisions, worlds, GUI previews, docs and AI balance.",
6
6
  "type": "module",
7
7
  "license": "Apache-2.0",
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/configuration.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/configuration.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/continuous-focus-palette.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/continuous-focus-palette.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/custom-weighted-pool.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/custom-weighted-pool.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/decision-inspect-input.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/decision-inspect-input.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/error-log-input.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/error-log-input.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/event-feature-manifest.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/event-feature-manifest.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/focus-plan.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/focus-plan.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/focus-planning-sidecar.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/focus-planning-sidecar.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/geography-model.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/geography-model.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/gui-animation-source.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/gui-animation-source.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/gui-helper.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/gui-helper.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/gui-scenario.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/gui-scenario.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/helper-expansion-request.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/helper-expansion-request.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/helper-expansion-summary.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/helper-expansion-summary.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/impact-inspect-input.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/impact-inspect-input.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/map-operation.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/map-operation.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "oneOf": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/mechanic-test-input.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/mechanic-test-input.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/mod-index-input.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/mod-index-input.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/operation-result.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/operation-result.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/package-check-input.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/package-check-input.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/package-manifest.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/package-manifest.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/probability-analysis-result.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/probability-analysis-result.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/probability-compare-input.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/probability-compare-input.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/probability-evaluate-input.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/probability-evaluate-input.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/probability-inspect-input.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/probability-inspect-input.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/probability-render-input.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/probability-render-input.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/probability-scenario-set.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/probability-scenario-set.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/probability-sequence-input.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/probability-sequence-input.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/probability-simulate-input.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/probability-simulate-input.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/probability-sweep-input.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/probability-sweep-input.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/reference-context-input.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/reference-context-input.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/reference-read-input.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/reference-read-input.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/reference-search-input.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/reference-search-input.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/reference-sheets.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/reference-sheets.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/scenario-suite.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/scenario-suite.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/scenario-test-input.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/scenario-test-input.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/script-validate-input.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/script-validate-input.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/shared-scenario.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/shared-scenario.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.3/schemas/source-lookup-input.schema.json",
2
+ "$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v4.6.5/schemas/source-lookup-input.schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "type": "object",
5
5
  "properties": {
package/server.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "name": "io.github.klimPaskov/hoi4-agent-tools",
4
4
  "title": "HOI4 Agent Tools",
5
5
  "description": "Build HOI4 mods: focus trees, events, decisions, worlds, GUI previews, docs and AI balance.",
6
- "version": "4.6.3",
6
+ "version": "4.6.5",
7
7
  "repository": {
8
8
  "url": "https://github.com/klimPaskov/hoi4-agent-tools",
9
9
  "source": "github"
@@ -13,7 +13,7 @@
13
13
  {
14
14
  "registryType": "npm",
15
15
  "identifier": "hoi4-agent-tools",
16
- "version": "4.6.3",
16
+ "version": "4.6.5",
17
17
  "transport": {
18
18
  "type": "stdio"
19
19
  }