@its-not-rocket-science/ananke 0.1.69 → 0.5.4

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 (165) hide show
  1. package/CHANGELOG.md +288 -0
  2. package/README.md +150 -432
  3. package/STABLE_API.md +113 -490
  4. package/conformance/README.md +46 -44
  5. package/conformance/lockstep-sequence.json +395 -395
  6. package/conformance/phase-order.json +21 -0
  7. package/conformance/replay-parity.json +65 -65
  8. package/conformance/state-hash-regression.json +39 -0
  9. package/conformance/state-hash.json +23 -22
  10. package/dist/src/conformance.d.ts +8 -2
  11. package/dist/src/content/index.d.ts +3 -0
  12. package/dist/src/content/index.js +2 -0
  13. package/dist/src/content/injector.d.ts +19 -0
  14. package/dist/src/content/injector.js +61 -0
  15. package/dist/src/content/loader.d.ts +3 -0
  16. package/dist/src/content/loader.js +170 -0
  17. package/dist/src/content/types.d.ts +56 -0
  18. package/dist/src/content/types.js +1 -0
  19. package/dist/src/content/validator.d.ts +6 -0
  20. package/dist/src/content/validator.js +14 -0
  21. package/dist/src/content-pack.d.ts +3 -2
  22. package/dist/src/content-pack.js +205 -10
  23. package/dist/src/data-governance.d.ts +73 -0
  24. package/dist/src/data-governance.js +188 -0
  25. package/dist/src/debug.d.ts +6 -0
  26. package/dist/src/debug.js +9 -0
  27. package/dist/src/determinism.d.ts +12 -0
  28. package/dist/src/determinism.js +93 -0
  29. package/dist/src/dialogue.d.ts +41 -0
  30. package/dist/src/dialogue.js +113 -2
  31. package/dist/src/economy.d.ts +97 -3
  32. package/dist/src/economy.js +191 -37
  33. package/dist/src/history/autosave.d.ts +19 -0
  34. package/dist/src/history/autosave.js +98 -0
  35. package/dist/src/history/timetravel.d.ts +28 -0
  36. package/dist/src/history/timetravel.js +61 -0
  37. package/dist/src/index.d.ts +19 -31
  38. package/dist/src/index.js +20 -38
  39. package/dist/src/model3d.js +63 -2
  40. package/dist/src/narrative/combat-logger.d.ts +25 -0
  41. package/dist/src/narrative/combat-logger.js +97 -0
  42. package/dist/src/narrative/plausibility.d.ts +30 -0
  43. package/dist/src/narrative/plausibility.js +70 -0
  44. package/dist/src/narrative-layer.d.ts +2 -0
  45. package/dist/src/narrative-layer.js +2 -0
  46. package/dist/src/navigation/causal-chain.d.ts +26 -0
  47. package/dist/src/navigation/causal-chain.js +74 -0
  48. package/dist/src/netcode.d.ts +1 -1
  49. package/dist/src/netcode.js +1 -1
  50. package/dist/src/performance/adaptive-tick.d.ts +23 -0
  51. package/dist/src/performance/adaptive-tick.js +50 -0
  52. package/dist/src/plugins/loader.d.ts +23 -0
  53. package/dist/src/plugins/loader.js +86 -0
  54. package/dist/src/plugins/registry.d.ts +11 -0
  55. package/dist/src/plugins/registry.js +28 -0
  56. package/dist/src/plugins/types.d.ts +31 -0
  57. package/dist/src/plugins/types.js +7 -0
  58. package/dist/src/replay.js +5 -2
  59. package/dist/src/scenario.js +2 -1
  60. package/dist/src/serialization/binary.d.ts +5 -0
  61. package/dist/src/serialization/binary.js +193 -0
  62. package/dist/src/session.d.ts +115 -0
  63. package/dist/src/session.js +228 -0
  64. package/dist/src/sim/ai/decide.js +1 -1
  65. package/dist/src/sim/ai/personality.js +2 -2
  66. package/dist/src/sim/bodyplan.d.ts +30 -0
  67. package/dist/src/sim/context.d.ts +2 -0
  68. package/dist/src/sim/kernel.js +80 -1294
  69. package/dist/src/sim/normalization.d.ts +12 -0
  70. package/dist/src/sim/normalization.js +92 -0
  71. package/dist/src/sim/resolvers/attack-resolver.d.ts +30 -0
  72. package/dist/src/sim/resolvers/attack-resolver.js +310 -0
  73. package/dist/src/sim/resolvers/capability-resolver.d.ts +15 -0
  74. package/dist/src/sim/resolvers/capability-resolver.js +270 -0
  75. package/dist/src/sim/resolvers/grapple-resolver.d.ts +28 -0
  76. package/dist/src/sim/resolvers/grapple-resolver.js +70 -0
  77. package/dist/src/sim/resolvers/shoot-resolver.d.ts +27 -0
  78. package/dist/src/sim/resolvers/shoot-resolver.js +212 -0
  79. package/dist/src/sim/resolvers/treat-resolver.d.ts +16 -0
  80. package/dist/src/sim/resolvers/treat-resolver.js +77 -0
  81. package/dist/src/sim/step/apply/intents.d.ts +6 -0
  82. package/dist/src/sim/step/apply/intents.js +83 -0
  83. package/dist/src/sim/step/kernel-pipeline.d.ts +9 -0
  84. package/dist/src/sim/step/kernel-pipeline.js +15 -0
  85. package/dist/src/sim/step/phases/capability-phase.d.ts +8 -0
  86. package/dist/src/sim/step/phases/capability-phase.js +65 -0
  87. package/dist/src/sim/step/phases/cooldowns-phase.d.ts +3 -0
  88. package/dist/src/sim/step/phases/cooldowns-phase.js +37 -0
  89. package/dist/src/sim/step/phases/prepare-phase.d.ts +10 -0
  90. package/dist/src/sim/step/phases/prepare-phase.js +33 -0
  91. package/dist/src/sim/step/pipeline.d.ts +2 -0
  92. package/dist/src/sim/step/pipeline.js +15 -0
  93. package/dist/src/sim/step/resolvers/impact-resolver.d.ts +9 -0
  94. package/dist/src/sim/step/resolvers/impact-resolver.js +55 -0
  95. package/dist/src/sim/step/world-phases.d.ts +7 -0
  96. package/dist/src/sim/step/world-phases.js +15 -0
  97. package/dist/src/sim/step/world-step-context.d.ts +23 -0
  98. package/dist/src/sim/step/world-step-context.js +1 -0
  99. package/dist/src/sim/systemic-toxicology.js +1 -1
  100. package/dist/src/sim/team.js +2 -2
  101. package/dist/src/sim/testing.js +4 -3
  102. package/dist/src/sim/toxicology.d.ts +1 -1
  103. package/dist/src/sim/toxicology.js +1 -1
  104. package/dist/src/sim/world.d.ts +17 -24
  105. package/dist/src/snapshot.js +3 -6
  106. package/dist/src/tier2.d.ts +19 -0
  107. package/dist/src/tier2.js +21 -0
  108. package/dist/src/tier3.d.ts +10 -0
  109. package/dist/src/tier3.js +12 -0
  110. package/dist/src/version.d.ts +6 -0
  111. package/dist/src/version.js +8 -0
  112. package/dist/src/wasm/bridge.d.ts +14 -0
  113. package/dist/src/wasm/bridge.js +84 -0
  114. package/dist/src/wasm-kernel.d.ts +2 -0
  115. package/dist/src/wasm-kernel.js +1 -0
  116. package/dist/src/world-evolution-backend/engine.d.ts +4 -0
  117. package/dist/src/world-evolution-backend/engine.js +347 -0
  118. package/dist/src/world-evolution-backend/host-schema.d.ts +145 -0
  119. package/dist/src/world-evolution-backend/host-schema.js +375 -0
  120. package/dist/src/world-evolution-backend/index.d.ts +1 -0
  121. package/dist/src/world-evolution-backend/index.js +1 -0
  122. package/dist/src/world-evolution-backend/open-world-host-adapter.d.ts +96 -0
  123. package/dist/src/world-evolution-backend/open-world-host-adapter.js +208 -0
  124. package/dist/src/world-evolution-backend/profiles.d.ts +4 -0
  125. package/dist/src/world-evolution-backend/profiles.js +136 -0
  126. package/dist/src/world-evolution-backend/public.d.ts +11 -0
  127. package/dist/src/world-evolution-backend/public.js +7 -0
  128. package/dist/src/world-evolution-backend/reproducibility.d.ts +8 -0
  129. package/dist/src/world-evolution-backend/reproducibility.js +35 -0
  130. package/dist/src/world-evolution-backend/timeline.d.ts +6 -0
  131. package/dist/src/world-evolution-backend/timeline.js +337 -0
  132. package/dist/src/world-evolution-backend/types.d.ts +138 -0
  133. package/dist/src/world-evolution-backend/types.js +1 -0
  134. package/dist/src/world-evolution-host-backend.d.ts +51 -0
  135. package/dist/src/world-evolution-host-backend.js +97 -0
  136. package/dist/src/world-evolution.d.ts +201 -0
  137. package/dist/src/world-evolution.js +543 -0
  138. package/dist/src/world-factory.js +2 -1
  139. package/dist/tools/pack-cli.js +55 -2
  140. package/docs/bridge-contract.md +140 -332
  141. package/docs/completion-evidence-dashboard.md +63 -0
  142. package/docs/host-contract.md +86 -310
  143. package/docs/host-world-evolution-schema.md +155 -0
  144. package/docs/integration-primer.md +29 -22
  145. package/docs/migration-monolith-to-modular.md +102 -120
  146. package/docs/package-architecture.md +116 -323
  147. package/docs/plugins/README.md +42 -0
  148. package/docs/plugins/hooks.md +22 -0
  149. package/docs/plugins/publishing.md +29 -0
  150. package/docs/plugins/security-model.md +273 -0
  151. package/docs/project-overview.md +30 -30
  152. package/docs/release-dashboard.md +47 -0
  153. package/docs/session-api.md +127 -0
  154. package/docs/stable-api-manifest.json +52 -0
  155. package/docs/trust-dashboard.md +37 -0
  156. package/docs/versioning.md +256 -245
  157. package/docs/wire-protocol.md +140 -209
  158. package/docs/world-evolution-backend.md +200 -0
  159. package/docs/world-evolution-engine.md +150 -0
  160. package/docs/world-evolution-host-backend.md +70 -0
  161. package/docs/world-evolution-orchestration.md +248 -0
  162. package/package.json +125 -6
  163. package/schema/content-pack.schema.json +85 -0
  164. package/schema/plugin.schema.json +57 -0
  165. package/schema/world-evolution-input.schema.json +196 -0
@@ -0,0 +1,337 @@
1
+ import { SCALE } from "../units.js";
2
+ const CATEGORY_ORDER = {
3
+ polity: 0,
4
+ governance: 1,
5
+ diplomacy: 2,
6
+ economy: 3,
7
+ infrastructure: 4,
8
+ migration: 5,
9
+ conflict: 6,
10
+ climate: 7,
11
+ disease: 8,
12
+ mythology_culture: 9,
13
+ };
14
+ const CATEGORY_WEIGHT = {
15
+ polity: 16,
16
+ migration: 14,
17
+ conflict: 20,
18
+ diplomacy: 12,
19
+ economy: 10,
20
+ disease: 18,
21
+ climate: 15,
22
+ infrastructure: 8,
23
+ governance: 11,
24
+ mythology_culture: 7,
25
+ };
26
+ export function buildEvolutionTimeline(result, options = {}) {
27
+ const includeSummaryText = options.includeSummaryText === true;
28
+ const events = [];
29
+ let previousMetrics;
30
+ let sequence = 0;
31
+ for (const stepEvent of result.timeline) {
32
+ const metricsDelta = deriveMetricsDelta(previousMetrics, stepEvent.metrics);
33
+ appendTradeEvents(events, result.initialSnapshot.worldSeed, stepEvent, includeSummaryText, () => sequence++);
34
+ appendConflictEvents(events, result.initialSnapshot.worldSeed, stepEvent, includeSummaryText, () => sequence++);
35
+ appendMigrationEvents(events, result.initialSnapshot.worldSeed, stepEvent, includeSummaryText, () => sequence++);
36
+ appendClimateEvents(events, result.initialSnapshot.worldSeed, stepEvent, includeSummaryText, () => sequence++);
37
+ appendDiseaseEvents(events, result.initialSnapshot.worldSeed, stepEvent, includeSummaryText, () => sequence++);
38
+ appendMetricDerivedEvents(events, result.initialSnapshot.worldSeed, stepEvent, metricsDelta, includeSummaryText, () => sequence++);
39
+ previousMetrics = stepEvent.metrics;
40
+ }
41
+ return events.sort((a, b) => a.tick - b.tick
42
+ || a.step - b.step
43
+ || CATEGORY_ORDER[a.category] - CATEGORY_ORDER[b.category]
44
+ || a.sequence - b.sequence
45
+ || a.id.localeCompare(b.id));
46
+ }
47
+ export function sortTimelineEventsBySignificance(events) {
48
+ return [...events].sort((a, b) => b.significance - a.significance
49
+ || b.severity - a.severity
50
+ || a.tick - b.tick
51
+ || a.id.localeCompare(b.id));
52
+ }
53
+ function appendTradeEvents(target, worldSeed, step, includeSummaryText, nextSequence) {
54
+ for (let index = 0; index < step.trade.length; index++) {
55
+ const trade = step.trade[index];
56
+ if (!trade)
57
+ continue;
58
+ const severity = clampPercent(Math.floor(trade.incomeEach_cu / 250));
59
+ target.push(makeEvent({
60
+ worldSeed,
61
+ step,
62
+ category: "economy",
63
+ severity,
64
+ significanceBoost: 5,
65
+ entityIds: [trade.polityAId, trade.polityBId],
66
+ factRefs: [factRef("trade", step, index)],
67
+ detail: { incomeEach_cu: trade.incomeEach_cu },
68
+ includeSummaryText,
69
+ summary: `Trade volume expanded between ${trade.polityAId} and ${trade.polityBId} (+${trade.incomeEach_cu} cu each).`,
70
+ sequence: nextSequence(),
71
+ localIndex: index,
72
+ }));
73
+ }
74
+ }
75
+ function appendConflictEvents(target, worldSeed, step, includeSummaryText, nextSequence) {
76
+ for (let index = 0; index < step.wars.length; index++) {
77
+ const war = step.wars[index];
78
+ if (!war)
79
+ continue;
80
+ const territoryPressure = Math.abs(war.territoryGained.length) * 8;
81
+ const severity = clampPercent(35 + territoryPressure + Math.floor((Math.abs(war.stabilityDeltaAttacker) + Math.abs(war.stabilityDeltaDefender)) * 100 / SCALE.Q));
82
+ target.push(makeEvent({
83
+ worldSeed,
84
+ step,
85
+ category: "conflict",
86
+ severity,
87
+ significanceBoost: 12,
88
+ entityIds: [war.attackerId, war.defenderId],
89
+ factRefs: [factRef("wars", step, index)],
90
+ detail: { attackerWins: war.attackerWins, territoryGained: [...war.territoryGained] },
91
+ includeSummaryText,
92
+ summary: `${war.attackerId} ${war.attackerWins ? "prevailed over" : "failed against"} ${war.defenderId}.`,
93
+ sequence: nextSequence(),
94
+ localIndex: index,
95
+ }));
96
+ }
97
+ }
98
+ function appendMigrationEvents(target, worldSeed, step, includeSummaryText, nextSequence) {
99
+ for (let index = 0; index < step.migrations.length; index++) {
100
+ const migration = step.migrations[index];
101
+ if (!migration)
102
+ continue;
103
+ const severity = clampPercent(Math.floor(migration.population / 40));
104
+ target.push(makeEvent({
105
+ worldSeed,
106
+ step,
107
+ category: "migration",
108
+ severity,
109
+ significanceBoost: 8,
110
+ entityIds: [migration.fromPolityId, migration.toPolityId],
111
+ factRefs: [factRef("migrations", step, index)],
112
+ detail: { population: migration.population },
113
+ includeSummaryText,
114
+ summary: `${migration.population} people migrated from ${migration.fromPolityId} to ${migration.toPolityId}.`,
115
+ sequence: nextSequence(),
116
+ localIndex: index,
117
+ }));
118
+ }
119
+ }
120
+ function appendClimateEvents(target, worldSeed, step, includeSummaryText, nextSequence) {
121
+ for (let index = 0; index < step.climateEventIds.length; index++) {
122
+ const climateEventId = step.climateEventIds[index];
123
+ if (!climateEventId)
124
+ continue;
125
+ const severity = clampPercent(30 + Math.floor(climateEventId.length / 3));
126
+ target.push(makeEvent({
127
+ worldSeed,
128
+ step,
129
+ category: "climate",
130
+ severity,
131
+ significanceBoost: 10,
132
+ entityIds: [],
133
+ factRefs: [factRef("climateEventIds", step, index)],
134
+ detail: { climateEventId },
135
+ includeSummaryText,
136
+ summary: `Climate pressure event triggered (${climateEventId}).`,
137
+ sequence: nextSequence(),
138
+ localIndex: index,
139
+ }));
140
+ }
141
+ }
142
+ function appendDiseaseEvents(target, worldSeed, step, includeSummaryText, nextSequence) {
143
+ if (step.epidemicPopulationDelta === 0)
144
+ return;
145
+ const severity = clampPercent(Math.floor(Math.abs(step.epidemicPopulationDelta) / 20));
146
+ target.push(makeEvent({
147
+ worldSeed,
148
+ step,
149
+ category: "disease",
150
+ severity,
151
+ significanceBoost: 14,
152
+ entityIds: [],
153
+ factRefs: [factRef("epidemicPopulationDelta", step)],
154
+ detail: { epidemicPopulationDelta: step.epidemicPopulationDelta },
155
+ includeSummaryText,
156
+ summary: `Epidemic pressure shifted population by ${step.epidemicPopulationDelta}.`,
157
+ sequence: nextSequence(),
158
+ localIndex: 0,
159
+ }));
160
+ }
161
+ function appendMetricDerivedEvents(target, worldSeed, step, metricsDelta, includeSummaryText, nextSequence) {
162
+ const metricFacts = [factRef("metrics", step)];
163
+ if (metricsDelta.totalPopulation !== 0) {
164
+ const severity = clampPercent(Math.floor(Math.abs(metricsDelta.totalPopulation) / 60));
165
+ target.push(makeEvent({
166
+ worldSeed,
167
+ step,
168
+ category: "polity",
169
+ severity,
170
+ significanceBoost: 7,
171
+ entityIds: [],
172
+ factRefs: metricFacts,
173
+ detail: { totalPopulationDelta: metricsDelta.totalPopulation },
174
+ includeSummaryText,
175
+ summary: `Aggregate polity population changed by ${metricsDelta.totalPopulation}.`,
176
+ sequence: nextSequence(),
177
+ localIndex: 0,
178
+ }));
179
+ }
180
+ if (metricsDelta.activeTreaties !== 0) {
181
+ target.push(makeEvent({
182
+ worldSeed,
183
+ step,
184
+ category: "diplomacy",
185
+ severity: clampPercent(25 + Math.abs(metricsDelta.activeTreaties) * 20),
186
+ significanceBoost: 6,
187
+ entityIds: [],
188
+ factRefs: metricFacts,
189
+ detail: { activeTreatiesDelta: metricsDelta.activeTreaties },
190
+ includeSummaryText,
191
+ summary: `Diplomatic treaty count shifted by ${metricsDelta.activeTreaties}.`,
192
+ sequence: nextSequence(),
193
+ localIndex: 1,
194
+ }));
195
+ }
196
+ if (metricsDelta.avgStability_Q !== 0) {
197
+ target.push(makeEvent({
198
+ worldSeed,
199
+ step,
200
+ category: "governance",
201
+ severity: clampPercent(Math.floor(Math.abs(metricsDelta.avgStability_Q) * 100 / SCALE.Q)),
202
+ significanceBoost: 4,
203
+ entityIds: [],
204
+ factRefs: metricFacts,
205
+ detail: { avgStabilityDelta_Q: metricsDelta.avgStability_Q },
206
+ includeSummaryText,
207
+ summary: `Governance stability shifted by ${metricsDelta.avgStability_Q}.`,
208
+ sequence: nextSequence(),
209
+ localIndex: 2,
210
+ }));
211
+ }
212
+ if (metricsDelta.viableTradeRoutes !== 0) {
213
+ target.push(makeEvent({
214
+ worldSeed,
215
+ step,
216
+ category: "infrastructure",
217
+ severity: clampPercent(20 + Math.abs(metricsDelta.viableTradeRoutes) * 15),
218
+ significanceBoost: 5,
219
+ entityIds: [],
220
+ factRefs: metricFacts,
221
+ detail: { viableTradeRoutesDelta: metricsDelta.viableTradeRoutes },
222
+ includeSummaryText,
223
+ summary: `Infrastructure connectivity changed by ${metricsDelta.viableTradeRoutes} viable routes.`,
224
+ sequence: nextSequence(),
225
+ localIndex: 3,
226
+ }));
227
+ }
228
+ if (metricsDelta.totalTreasury_cu !== 0 && step.trade.length === 0) {
229
+ target.push(makeEvent({
230
+ worldSeed,
231
+ step,
232
+ category: "economy",
233
+ severity: clampPercent(Math.floor(Math.abs(metricsDelta.totalTreasury_cu) / 500)),
234
+ significanceBoost: 3,
235
+ entityIds: [],
236
+ factRefs: metricFacts,
237
+ detail: { totalTreasuryDelta_cu: metricsDelta.totalTreasury_cu },
238
+ includeSummaryText,
239
+ summary: `Macro treasury shifted by ${metricsDelta.totalTreasury_cu} cu.`,
240
+ sequence: nextSequence(),
241
+ localIndex: 4,
242
+ }));
243
+ }
244
+ if (metricsDelta.avgMorale_Q !== 0) {
245
+ target.push(makeEvent({
246
+ worldSeed,
247
+ step,
248
+ category: "mythology_culture",
249
+ severity: clampPercent(Math.floor(Math.abs(metricsDelta.avgMorale_Q) * 100 / SCALE.Q)),
250
+ significanceBoost: 2,
251
+ entityIds: [],
252
+ factRefs: metricFacts,
253
+ detail: { avgMoraleDelta_Q: metricsDelta.avgMorale_Q },
254
+ includeSummaryText,
255
+ summary: `Cultural sentiment moved by ${metricsDelta.avgMorale_Q}.`,
256
+ sequence: nextSequence(),
257
+ localIndex: 5,
258
+ }));
259
+ }
260
+ }
261
+ function makeEvent(args) {
262
+ const fingerprint = JSON.stringify({
263
+ seed: args.worldSeed,
264
+ step: args.step.step,
265
+ tick: args.step.tick,
266
+ category: args.category,
267
+ index: args.localIndex,
268
+ entities: [...args.entityIds].sort((a, b) => a.localeCompare(b)),
269
+ detail: args.detail,
270
+ facts: args.factRefs.map((ref) => `${ref.subsystem}:${ref.step}:${ref.tick}:${ref.index ?? -1}`),
271
+ });
272
+ const hash = stableHashHex(fingerprint);
273
+ const significance = clampPercent(args.severity + CATEGORY_WEIGHT[args.category] + args.significanceBoost);
274
+ return {
275
+ id: `evo.${args.step.step}.${args.category}.${hash.slice(0, 12)}`,
276
+ hash,
277
+ step: args.step.step,
278
+ tick: args.step.tick,
279
+ category: args.category,
280
+ severity: args.severity,
281
+ significance,
282
+ entityIds: [...args.entityIds].sort((a, b) => a.localeCompare(b)),
283
+ factRefs: args.factRefs.map((ref) => ({ ...ref })),
284
+ ...(args.includeSummaryText ? { summary: args.summary } : {}),
285
+ sequence: args.sequence,
286
+ };
287
+ }
288
+ function factRef(subsystem, step, index) {
289
+ return {
290
+ subsystem,
291
+ step: step.step,
292
+ tick: step.tick,
293
+ ...(index != null ? { index } : {}),
294
+ };
295
+ }
296
+ function deriveMetricsDelta(prev, next) {
297
+ if (prev == null) {
298
+ return {
299
+ totalPopulation: next.totalPopulation,
300
+ totalTreasury_cu: next.totalTreasury_cu,
301
+ avgStability_Q: next.avgStability_Q,
302
+ avgMorale_Q: next.avgMorale_Q,
303
+ activeWars: next.activeWars,
304
+ activeTreaties: next.activeTreaties,
305
+ viableTradeRoutes: next.viableTradeRoutes,
306
+ activeEpidemics: next.activeEpidemics,
307
+ activeClimateEvents: next.activeClimateEvents,
308
+ migrationsThisStep: next.migrationsThisStep,
309
+ migrationsTotalPopulation: next.migrationsTotalPopulation,
310
+ };
311
+ }
312
+ return {
313
+ totalPopulation: next.totalPopulation - prev.totalPopulation,
314
+ totalTreasury_cu: next.totalTreasury_cu - prev.totalTreasury_cu,
315
+ avgStability_Q: next.avgStability_Q - prev.avgStability_Q,
316
+ avgMorale_Q: next.avgMorale_Q - prev.avgMorale_Q,
317
+ activeWars: next.activeWars - prev.activeWars,
318
+ activeTreaties: next.activeTreaties - prev.activeTreaties,
319
+ viableTradeRoutes: next.viableTradeRoutes - prev.viableTradeRoutes,
320
+ activeEpidemics: next.activeEpidemics - prev.activeEpidemics,
321
+ activeClimateEvents: next.activeClimateEvents - prev.activeClimateEvents,
322
+ migrationsThisStep: next.migrationsThisStep - prev.migrationsThisStep,
323
+ migrationsTotalPopulation: next.migrationsTotalPopulation - prev.migrationsTotalPopulation,
324
+ };
325
+ }
326
+ function clampPercent(value) {
327
+ return Math.max(0, Math.min(100, Math.floor(value)));
328
+ }
329
+ function stableHashHex(input) {
330
+ let hash = 0x811c9dc5;
331
+ for (let i = 0; i < input.length; i++) {
332
+ hash ^= input.charCodeAt(i);
333
+ hash = Math.imul(hash, 0x01000193);
334
+ }
335
+ const normalized = hash >>> 0;
336
+ return normalized.toString(16).padStart(8, "0");
337
+ }
@@ -0,0 +1,138 @@
1
+ import type { ActiveClimateEvent } from "../climate.js";
2
+ import type { Treaty } from "../diplomacy.js";
3
+ import type { PolityEpidemicState } from "../epidemic.js";
4
+ import type { GovernanceState, LawCode } from "../governance.js";
5
+ import type { MigrationFlow } from "../migration.js";
6
+ import type { Polity, PolityPair, PolityTradeResult, PolityWarResult } from "../polity.js";
7
+ import type { TradeRoute } from "../trade-routes.js";
8
+ import type { DiseaseProfile } from "../sim/disease.js";
9
+ import type { Q } from "../units.js";
10
+ export declare const WORLD_EVOLUTION_BACKEND_SCHEMA_VERSION: "ananke.world-evolution-backend.v1";
11
+ export type WorldEvolutionRulesetId = "minimal_world_history" | "polity_dynamics" | "conflict_heavy" | "climate_and_migration" | "full_world_evolution" | "balanced" | "resilience" | "expansion";
12
+ export interface EvolutionRulesetProfile {
13
+ id: WorldEvolutionRulesetId;
14
+ name: string;
15
+ description: string;
16
+ /**
17
+ * Explicit deterministic execution order for active subsystems.
18
+ * Hosts can inspect this to verify reproducible orchestration order.
19
+ */
20
+ pipelineOrder: readonly [
21
+ "polity",
22
+ "governance",
23
+ "diplomacy",
24
+ "trade",
25
+ "migration",
26
+ "climate",
27
+ "epidemic"
28
+ ];
29
+ polityDayEnabled: boolean;
30
+ governanceEnabled: boolean;
31
+ diplomacyEnabled: boolean;
32
+ tradeEnabled: boolean;
33
+ migrationEnabled: boolean;
34
+ epidemicEnabled: boolean;
35
+ climateEnabled: boolean;
36
+ governanceStabilityDaysPerStep: number;
37
+ treatyStrengthBoost_Q: Q;
38
+ routeEfficiencyBoost_Q: Q;
39
+ epidemicHealthBuffer_Q: Q;
40
+ }
41
+ export type WorldEvolutionRulesetProfile = EvolutionRulesetProfile;
42
+ export interface WorldEvolutionSnapshot {
43
+ schemaVersion: typeof WORLD_EVOLUTION_BACKEND_SCHEMA_VERSION;
44
+ worldSeed: number;
45
+ tick: number;
46
+ polities: Polity[];
47
+ pairs: PolityPair[];
48
+ activeWars: Array<[string, string]>;
49
+ treaties: Treaty[];
50
+ tradeRoutes: TradeRoute[];
51
+ governanceStates: GovernanceState[];
52
+ governanceLawRegistry: LawCode[];
53
+ epidemics: PolityEpidemicState[];
54
+ diseases: DiseaseProfile[];
55
+ climateByPolity: Array<{
56
+ polityId: string;
57
+ active: ActiveClimateEvent[];
58
+ }>;
59
+ }
60
+ export interface WorldEvolutionRunRequest {
61
+ snapshot: WorldEvolutionSnapshot;
62
+ steps: number;
63
+ profileId?: WorldEvolutionRulesetId;
64
+ profile?: WorldEvolutionRulesetProfile;
65
+ includeDeltas?: boolean;
66
+ checkpointInterval?: number;
67
+ }
68
+ export interface WorldEvolutionMetrics {
69
+ totalPopulation: number;
70
+ totalTreasury_cu: number;
71
+ avgStability_Q: Q;
72
+ avgMorale_Q: Q;
73
+ activeWars: number;
74
+ activeTreaties: number;
75
+ viableTradeRoutes: number;
76
+ activeEpidemics: number;
77
+ activeClimateEvents: number;
78
+ migrationsThisStep: number;
79
+ migrationsTotalPopulation: number;
80
+ }
81
+ export interface WorldEvolutionStepEvent {
82
+ step: number;
83
+ tick: number;
84
+ trade: PolityTradeResult[];
85
+ wars: PolityWarResult[];
86
+ migrations: MigrationFlow[];
87
+ climateEventIds: string[];
88
+ epidemicPopulationDelta: number;
89
+ metrics: WorldEvolutionMetrics;
90
+ }
91
+ export interface WorldEvolutionDelta {
92
+ step: number;
93
+ tick: number;
94
+ polityDeltas: Array<{
95
+ polityId: string;
96
+ populationDelta: number;
97
+ treasuryDelta_cu: number;
98
+ stabilityDelta_Q: number;
99
+ moraleDelta_Q: number;
100
+ }>;
101
+ }
102
+ export interface WorldEvolutionCheckpoint {
103
+ step: number;
104
+ tick: number;
105
+ snapshot: WorldEvolutionSnapshot;
106
+ }
107
+ export type EvolutionTimelineCategory = "polity" | "migration" | "conflict" | "diplomacy" | "economy" | "disease" | "climate" | "infrastructure" | "governance" | "mythology_culture";
108
+ export interface EvolutionTimelineFactRef {
109
+ subsystem: "trade" | "wars" | "migrations" | "climateEventIds" | "epidemicPopulationDelta" | "metrics";
110
+ step: number;
111
+ tick: number;
112
+ index?: number;
113
+ }
114
+ export interface EvolutionTimelineEvent {
115
+ id: string;
116
+ hash: string;
117
+ step: number;
118
+ tick: number;
119
+ category: EvolutionTimelineCategory;
120
+ /** 0..100 host-friendly intensity score. */
121
+ severity: number;
122
+ /** 0..100 host-friendly relevance score for surfacing highlights. */
123
+ significance: number;
124
+ /** Stable timeline order in the normalized stream. */
125
+ sequence: number;
126
+ entityIds: string[];
127
+ factRefs: EvolutionTimelineFactRef[];
128
+ summary?: string;
129
+ }
130
+ export interface WorldEvolutionRunResult {
131
+ initialSnapshot: WorldEvolutionSnapshot;
132
+ finalSnapshot: WorldEvolutionSnapshot;
133
+ profile: WorldEvolutionRulesetProfile;
134
+ timeline: WorldEvolutionStepEvent[];
135
+ metrics: WorldEvolutionMetrics;
136
+ deltas?: WorldEvolutionDelta[];
137
+ checkpoints?: WorldEvolutionCheckpoint[];
138
+ }
@@ -0,0 +1 @@
1
+ export const WORLD_EVOLUTION_BACKEND_SCHEMA_VERSION = "ananke.world-evolution-backend.v1";
@@ -0,0 +1,51 @@
1
+ import { type EvolutionTimelineEvent, type HostAdapterContext, type OpenWorldHostInput, type WorldEvolutionInput, type WorldEvolutionRulesetId, type WorldEvolutionRulesetProfile, type WorldEvolutionRunResult, type EvolutionRunReproducibilityRecord } from "./world-evolution-backend/public.js";
2
+ import { type CreateEvolutionBranchInput, type EvolutionBranch, type EvolutionCheckpoint, type EvolutionRequest, type EvolutionRunResult, type EvolutionSession, type ResumeEvolutionOptions } from "./world-evolution.js";
3
+ /**
4
+ * Host-facing deterministic backend wrapper: adapt + validate + run + timeline projection.
5
+ *
6
+ * Stability boundary:
7
+ * - Additive API (non Tier-1) exposed only via `@.../world-evolution-host-backend`.
8
+ * - Reuses authoritative world-evolution backend + orchestration modules without replacing them.
9
+ */
10
+ export interface HostDeterministicRunRequest {
11
+ input: WorldEvolutionInput | OpenWorldHostInput;
12
+ steps: number;
13
+ profileId?: WorldEvolutionRulesetId;
14
+ profile?: WorldEvolutionRulesetProfile;
15
+ includeDeltas?: boolean;
16
+ checkpointInterval?: number;
17
+ includeSummaryText?: boolean;
18
+ }
19
+ export interface HostDeterministicRunResult {
20
+ normalizedInput: WorldEvolutionInput;
21
+ adapterContext: HostAdapterContext;
22
+ run: WorldEvolutionRunResult;
23
+ history: EvolutionTimelineEvent[];
24
+ }
25
+ export interface HostDeterministicRunWithReplayProofResult extends HostDeterministicRunResult {
26
+ reproducibility: EvolutionRunReproducibilityRecord;
27
+ }
28
+ export interface HostOrchestrationSessionConfig {
29
+ input: WorldEvolutionInput | OpenWorldHostInput;
30
+ rulesetId?: WorldEvolutionRulesetId;
31
+ ruleset?: WorldEvolutionRulesetProfile;
32
+ checkpointInterval?: number;
33
+ includeDeltas?: boolean;
34
+ label?: string;
35
+ }
36
+ export interface HostOrchestrationRunRequest extends EvolutionRequest {
37
+ }
38
+ export interface HostOrchestrationRunResult {
39
+ session: EvolutionSession;
40
+ result: EvolutionRunResult;
41
+ }
42
+ export declare function runHostDeterministicEvolution(request: HostDeterministicRunRequest): HostDeterministicRunResult;
43
+ export declare function createHostEvolutionSession(config: HostOrchestrationSessionConfig): EvolutionSession;
44
+ export declare function runHostEvolutionSession(session: EvolutionSession, request: HostOrchestrationRunRequest): HostOrchestrationRunResult;
45
+ export declare function resumeHostEvolutionSessionFromCheckpoint(checkpoint: EvolutionCheckpoint, request: HostOrchestrationRunRequest, options?: ResumeEvolutionOptions): HostOrchestrationRunResult;
46
+ export declare function createHostEvolutionBranch(config: HostOrchestrationSessionConfig & {
47
+ metadata: CreateEvolutionBranchInput["metadata"];
48
+ baseStep?: number;
49
+ }): EvolutionBranch;
50
+ export declare function runHostEvolutionBranch(branch: EvolutionBranch, request: HostOrchestrationRunRequest): EvolutionRunResult;
51
+ export declare function runHostDeterministicEvolutionWithReplayProof(request: HostDeterministicRunRequest): HostDeterministicRunWithReplayProofResult;
@@ -0,0 +1,97 @@
1
+ import { buildEvolutionTimeline, mapOpenWorldHostToEvolutionInput, normalizeHostWorldInput, runWorldEvolution, toAnankeEvolutionState, toWorldEvolutionRunRequest, buildEvolutionRunReproducibilityRecord, } from "./world-evolution-backend/public.js";
2
+ import { createEvolutionBranch, createEvolutionSession, resumeEvolutionSessionFromCheckpoint, runEvolution, runEvolutionOnBranch, } from "./world-evolution.js";
3
+ export function runHostDeterministicEvolution(request) {
4
+ const hostInput = normalizeHostBackendInput(request.input);
5
+ const normalizedInput = normalizeHostWorldInput({
6
+ ...hostInput,
7
+ ...(request.profileId != null ? { profileId: request.profileId } : {}),
8
+ });
9
+ const adapterState = toAnankeEvolutionState(normalizedInput);
10
+ const runRequest = toWorldEvolutionRunRequest(normalizedInput, request.steps, {
11
+ ...(request.profileId != null ? { profileId: request.profileId } : {}),
12
+ ...(request.profile != null ? { profile: request.profile } : {}),
13
+ ...(request.includeDeltas != null ? { includeDeltas: request.includeDeltas } : {}),
14
+ ...(request.checkpointInterval != null ? { checkpointInterval: request.checkpointInterval } : {}),
15
+ });
16
+ const run = runWorldEvolution(runRequest);
17
+ const history = buildEvolutionTimeline(run, {
18
+ ...(request.includeSummaryText != null ? { includeSummaryText: request.includeSummaryText } : {}),
19
+ });
20
+ return {
21
+ normalizedInput,
22
+ adapterContext: adapterState.context,
23
+ run,
24
+ history,
25
+ };
26
+ }
27
+ export function createHostEvolutionSession(config) {
28
+ const hostInput = normalizeHostBackendInput(config.input);
29
+ const normalizedInput = normalizeHostWorldInput({
30
+ ...hostInput,
31
+ ...(config.rulesetId != null ? { profileId: config.rulesetId } : {}),
32
+ });
33
+ const runRequest = toWorldEvolutionRunRequest(normalizedInput, 0, {
34
+ ...(config.rulesetId != null ? { profileId: config.rulesetId } : {}),
35
+ ...(config.ruleset != null ? { profile: config.ruleset } : {}),
36
+ ...(config.checkpointInterval != null ? { checkpointInterval: config.checkpointInterval } : {}),
37
+ ...(config.includeDeltas != null ? { includeDeltas: config.includeDeltas } : {}),
38
+ });
39
+ return createEvolutionSession({
40
+ seed: runRequest.snapshot.worldSeed,
41
+ canonicalSnapshot: runRequest.snapshot,
42
+ ...(config.rulesetId != null ? { rulesetId: config.rulesetId } : {}),
43
+ ...(config.ruleset != null ? { ruleset: config.ruleset } : {}),
44
+ ...(config.checkpointInterval != null ? { checkpointInterval: config.checkpointInterval } : {}),
45
+ ...(config.includeDeltas != null ? { includeDeltas: config.includeDeltas } : {}),
46
+ ...(config.label != null ? { label: config.label } : {}),
47
+ });
48
+ }
49
+ export function runHostEvolutionSession(session, request) {
50
+ return {
51
+ session,
52
+ result: runEvolution(session, request),
53
+ };
54
+ }
55
+ export function resumeHostEvolutionSessionFromCheckpoint(checkpoint, request, options = {}) {
56
+ const resumedSession = resumeEvolutionSessionFromCheckpoint(checkpoint, options);
57
+ return {
58
+ session: resumedSession,
59
+ result: runEvolution(resumedSession, request),
60
+ };
61
+ }
62
+ export function createHostEvolutionBranch(config) {
63
+ const session = createHostEvolutionSession(config);
64
+ return createEvolutionBranch({
65
+ baseSnapshot: session.canonicalInitialSnapshot,
66
+ metadata: {
67
+ ...config.metadata,
68
+ rulesetProfile: config.metadata.rulesetProfile ?? session.ruleset,
69
+ },
70
+ ...(config.baseStep != null ? { baseStep: config.baseStep } : {}),
71
+ });
72
+ }
73
+ export function runHostEvolutionBranch(branch, request) {
74
+ return runEvolutionOnBranch(branch, request);
75
+ }
76
+ function normalizeHostBackendInput(input) {
77
+ if (isOpenWorldHostInput(input)) {
78
+ return mapOpenWorldHostToEvolutionInput(input).input;
79
+ }
80
+ return input;
81
+ }
82
+ function isOpenWorldHostInput(input) {
83
+ const candidate = input;
84
+ return Array.isArray(candidate.regions) && Array.isArray(candidate.settlements) && Array.isArray(candidate.factions);
85
+ }
86
+ export function runHostDeterministicEvolutionWithReplayProof(request) {
87
+ const result = runHostDeterministicEvolution(request);
88
+ return {
89
+ ...result,
90
+ reproducibility: buildEvolutionRunReproducibilityRecord(toWorldEvolutionRunRequest(result.normalizedInput, request.steps, {
91
+ ...(request.profileId != null ? { profileId: request.profileId } : {}),
92
+ ...(request.profile != null ? { profile: request.profile } : {}),
93
+ ...(request.includeDeltas != null ? { includeDeltas: request.includeDeltas } : {}),
94
+ ...(request.checkpointInterval != null ? { checkpointInterval: request.checkpointInterval } : {}),
95
+ }), result.run),
96
+ };
97
+ }