@its-not-rocket-science/ananke 0.1.8 → 0.1.9
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.
- package/CHANGELOG.md +74 -0
- package/STABLE_API.md +42 -3
- package/dist/src/emotional-contagion.d.ts +3 -0
- package/dist/src/polity.d.ts +15 -2
- package/dist/src/polity.js +11 -0
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,80 @@ Versioning follows [Semantic Versioning](https://semver.org/).
|
|
|
8
8
|
|
|
9
9
|
## [Unreleased]
|
|
10
10
|
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **CE-14 · Socio-Economic Campaign Layer → Stable Promotion**
|
|
14
|
+
- Promote `stepPolityDay`, `declareWar`, `makePeace`, `areAtWar`,
|
|
15
|
+
`createPolity`, `createPolityRegistry`, `Polity`, `PolityRegistry`,
|
|
16
|
+
`PolityPair` (`src/polity.ts`), `stepTechDiffusion`, `computeDiffusionPressure`,
|
|
17
|
+
`totalInboundPressure`, `techEraName` (`src/tech-diffusion.ts`), and
|
|
18
|
+
`applyEmotionalContagion`, `stepEmotionalWaves`, `computeEmotionalSpread`,
|
|
19
|
+
`triggerMilitaryRout`, `triggerVictoryRally`, `netEmotionalPressure`,
|
|
20
|
+
`EmotionalWave` (`src/emotional-contagion.ts`) from Tier 2 (Experimental)
|
|
21
|
+
to Tier 1 (Stable) in `STABLE_API.md`.
|
|
22
|
+
- Add `export *` re-exports to `src/polity.ts` so the `ananke/polity` subpath
|
|
23
|
+
delivers the complete Socio-Economic Campaign Layer in one import.
|
|
24
|
+
- Freeze `Polity`, `PolityRegistry`, `PolityPair` and `EmotionalWave` interfaces
|
|
25
|
+
with `@stable CE-14` JSDoc annotations — no required-field additions without a
|
|
26
|
+
minor bump, no renames without a major bump.
|
|
27
|
+
|
|
28
|
+
### Migration guide — v0.1.x → v0.2.0
|
|
29
|
+
|
|
30
|
+
This is a **non-breaking promotion**. No existing code needs to change.
|
|
31
|
+
|
|
32
|
+
#### What is new
|
|
33
|
+
|
|
34
|
+
The Socio-Economic Campaign Layer (`polity`, `tech-diffusion`, `emotional-contagion`)
|
|
35
|
+
is now Tier 1 (Stable). You can depend on it without fear of silent API churn.
|
|
36
|
+
|
|
37
|
+
#### Import change (optional)
|
|
38
|
+
|
|
39
|
+
Instead of importing from the package root:
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import { stepPolityDay } from "@its-not-rocket-science/ananke";
|
|
43
|
+
import { stepTechDiffusion } from "@its-not-rocket-science/ananke";
|
|
44
|
+
import { applyEmotionalContagion } from "@its-not-rocket-science/ananke";
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
You may now import from the dedicated subpath (recommended for tree-shaking):
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import {
|
|
51
|
+
stepPolityDay,
|
|
52
|
+
stepTechDiffusion,
|
|
53
|
+
applyEmotionalContagion,
|
|
54
|
+
EmotionalWave,
|
|
55
|
+
} from "@its-not-rocket-science/ananke/polity";
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Both forms remain supported indefinitely.
|
|
59
|
+
|
|
60
|
+
#### Interface freeze guarantees (from v0.2.0)
|
|
61
|
+
|
|
62
|
+
| Interface | Guarantee |
|
|
63
|
+
|-----------|-----------|
|
|
64
|
+
| `Polity` | Existing fields never renamed/removed without major bump |
|
|
65
|
+
| `PolityRegistry` | `polities`, `activeWars`, `alliances` fields frozen |
|
|
66
|
+
| `PolityPair` | `polityAId`, `polityBId`, `sharedLocations`, `routeQuality_Q` frozen |
|
|
67
|
+
| `EmotionalWave` | `profileId`, `sourcePolityId`, `intensity_Q`, `daysActive` frozen |
|
|
68
|
+
|
|
69
|
+
Adding new **optional** fields to these interfaces is never a breaking change.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## [0.1.9] — 2026-03-24
|
|
74
|
+
|
|
75
|
+
### Added
|
|
76
|
+
|
|
77
|
+
- **CE-14 · Promote Socio-economic Campaign Layer to Tier 1 Stable** (`src/parallel.ts`)
|
|
78
|
+
- Freeze Polity, PolityRegistry, PolityPair, EmotionalWave interfaces.
|
|
79
|
+
- Promote stepPolityDay, stepTechDiffusion, applyEmotionalContagion,
|
|
80
|
+
declareWar, makePeace to Tier 1 in STABLE_API.md.
|
|
81
|
+
- Re-export tech-diffusion and emotional-contagion from src/polity.ts so
|
|
82
|
+
ananke/polity is a single-import campaign layer entry point.
|
|
83
|
+
- Add v0.1.x -> v0.2.0 migration guide to CHANGELOG.md.
|
|
84
|
+
|
|
11
85
|
---
|
|
12
86
|
|
|
13
87
|
## [0.1.8] — 2026-03-24
|
package/STABLE_API.md
CHANGED
|
@@ -112,6 +112,48 @@ including `AnimationHints`, `GrapplePoseConstraint`, and `InterpolatedState`.
|
|
|
112
112
|
| `formatOneLine(desc)` | One-line summary |
|
|
113
113
|
| `CharacterDescription`, `AttributeRating` | Types |
|
|
114
114
|
|
|
115
|
+
### Socio-Economic Campaign Layer (`ananke/polity` subpath — CE-14)
|
|
116
|
+
|
|
117
|
+
All of the following are available via `import { … } from "ananke/polity"` as a single
|
|
118
|
+
entry point. The frozen interfaces (`Polity`, `PolityRegistry`, `PolityPair`,
|
|
119
|
+
`EmotionalWave`) will not gain required fields or lose existing fields without a minor
|
|
120
|
+
version bump; renames require a major bump and migration guide.
|
|
121
|
+
|
|
122
|
+
#### Polity system (`src/polity.ts`)
|
|
123
|
+
|
|
124
|
+
| Export | Description |
|
|
125
|
+
|--------|-------------|
|
|
126
|
+
| `Polity` _(frozen)_ | Geopolitical entity: city, nation, or empire |
|
|
127
|
+
| `PolityRegistry` _(frozen)_ | Container for all polities and active wars/alliances |
|
|
128
|
+
| `PolityPair` _(frozen)_ | Trade/proximity link between two polities |
|
|
129
|
+
| `createPolity(spec)` | Construct a `Polity` with sensible defaults |
|
|
130
|
+
| `createPolityRegistry(polities)` | Construct an empty registry |
|
|
131
|
+
| `stepPolityDay(registry, pairs, worldSeed, tick)` | Advance all polities by one simulated day |
|
|
132
|
+
| `declareWar(registry, aId, bId)` | Record a war between two polities |
|
|
133
|
+
| `makePeace(registry, aId, bId)` | End a war between two polities |
|
|
134
|
+
| `areAtWar(registry, aId, bId)` | Query war status |
|
|
135
|
+
|
|
136
|
+
#### Technology diffusion (`src/tech-diffusion.ts`)
|
|
137
|
+
|
|
138
|
+
| Export | Description |
|
|
139
|
+
|--------|-------------|
|
|
140
|
+
| `stepTechDiffusion(registry, pairs, worldSeed, tick)` | Spread technology between polities for one day |
|
|
141
|
+
| `computeDiffusionPressure(source, target, pair)` | Per-pair pressure score |
|
|
142
|
+
| `totalInboundPressure(registry, pairs, targetId)` | Sum of all inbound pressure toward a polity |
|
|
143
|
+
| `techEraName(era)` | Human-readable era label |
|
|
144
|
+
|
|
145
|
+
#### Emotional contagion (`src/emotional-contagion.ts`)
|
|
146
|
+
|
|
147
|
+
| Export | Description |
|
|
148
|
+
|--------|-------------|
|
|
149
|
+
| `EmotionalWave` _(frozen)_ | Active emotional event propagating across polities |
|
|
150
|
+
| `applyEmotionalContagion(registry, waves, worldSeed, tick)` | Apply all active waves to polity morale |
|
|
151
|
+
| `stepEmotionalWaves(waves, worldSeed, tick)` | Advance wave intensities by one day |
|
|
152
|
+
| `computeEmotionalSpread(source, target, wave, profile)` | Spread probability for one polity pair |
|
|
153
|
+
| `triggerMilitaryRout(sourcePolityId)` | Emit a fear wave from a battlefield loss |
|
|
154
|
+
| `triggerVictoryRally(sourcePolityId, leaderId?)` | Emit a hope wave from a victory |
|
|
155
|
+
| `netEmotionalPressure(registry, waves, polityId)` | Net morale pressure on a polity |
|
|
156
|
+
|
|
115
157
|
---
|
|
116
158
|
|
|
117
159
|
## Tier 2 — Experimental extension API
|
|
@@ -121,9 +163,6 @@ A `CHANGELOG.md` entry will document any breaking change.
|
|
|
121
163
|
|
|
122
164
|
| Module | Key exports |
|
|
123
165
|
|--------|------------|
|
|
124
|
-
| `src/polity.ts` | `createPolity`, `createPolityRegistry`, `stepPolityDay`, `declareWar`, `areAtWar`, `Polity`, `PolityRegistry`, `PolityPair` |
|
|
125
|
-
| `src/tech-diffusion.ts` | `computeDiffusionPressure`, `stepTechDiffusion`, `totalInboundPressure`, `techEraName` |
|
|
126
|
-
| `src/emotional-contagion.ts` | `applyEmotionalContagion`, `stepEmotionalWaves`, `computeEmotionalSpread`, `triggerMilitaryRout`, `triggerVictoryRally`, `netEmotionalPressure` |
|
|
127
166
|
| `src/mythology.ts` | `compressMythsFromHistory`, `stepMythologyYear`, `aggregateFactionMythEffect`, `scaledMythEffect` |
|
|
128
167
|
| `src/narrative-stress.ts` | `runNarrativeStressTest`, `scoreNarrativePush` |
|
|
129
168
|
| `src/campaign.ts` | `Campaign`, `stepCampaignDay`, `advanceCampaignClock`, `serializeCampaign`, `deserializeCampaign` |
|
|
@@ -36,6 +36,9 @@ export interface EmotionalContagionProfile {
|
|
|
36
36
|
/**
|
|
37
37
|
* An active emotional event originating from one polity.
|
|
38
38
|
* Decays each day; removed when intensity_Q reaches 0.
|
|
39
|
+
*
|
|
40
|
+
* @stable CE-14 — frozen from v0.2.0. Also exported as the nominal
|
|
41
|
+
* `ContagionWave` type referenced in the Campaign Layer documentation.
|
|
39
42
|
*/
|
|
40
43
|
export interface EmotionalWave {
|
|
41
44
|
profileId: string;
|
package/dist/src/polity.d.ts
CHANGED
|
@@ -7,6 +7,9 @@ import type { FactionRegistry } from "./faction.js";
|
|
|
7
7
|
*
|
|
8
8
|
* Operates at 1 tick per simulated day. All Q fields are fixed-point
|
|
9
9
|
* fractions in [0, SCALE.Q] unless documented otherwise.
|
|
10
|
+
*
|
|
11
|
+
* @stable CE-14 — fields are frozen from v0.2.0. New fields require a minor
|
|
12
|
+
* version bump; removals or renames require a major bump and migration guide.
|
|
10
13
|
*/
|
|
11
14
|
export interface Polity {
|
|
12
15
|
id: string;
|
|
@@ -31,7 +34,11 @@ export interface Polity {
|
|
|
31
34
|
/** Population morale [0, SCALE.Q]. Low morale → weak military and stability decay. */
|
|
32
35
|
moraleQ: Q;
|
|
33
36
|
}
|
|
34
|
-
/**
|
|
37
|
+
/**
|
|
38
|
+
* Registry of all active polities and their geopolitical relationships.
|
|
39
|
+
*
|
|
40
|
+
* @stable CE-14 — frozen from v0.2.0.
|
|
41
|
+
*/
|
|
35
42
|
export interface PolityRegistry {
|
|
36
43
|
polities: Map<string, Polity>;
|
|
37
44
|
/**
|
|
@@ -42,7 +49,11 @@ export interface PolityRegistry {
|
|
|
42
49
|
/** Diplomatic alliances: polityId → Set of allied polityIds. */
|
|
43
50
|
alliances: Map<string, Set<string>>;
|
|
44
51
|
}
|
|
45
|
-
/**
|
|
52
|
+
/**
|
|
53
|
+
* A trade/proximity link between two polities in the Campaign graph.
|
|
54
|
+
*
|
|
55
|
+
* @stable CE-14 — frozen from v0.2.0.
|
|
56
|
+
*/
|
|
46
57
|
export interface PolityPair {
|
|
47
58
|
polityAId: string;
|
|
48
59
|
polityBId: string;
|
|
@@ -260,3 +271,5 @@ export declare function areAtWar(registry: PolityRegistry, polityAId: string, po
|
|
|
260
271
|
* Use this as `currentStanding_Q` for `resolveDiplomacy`.
|
|
261
272
|
*/
|
|
262
273
|
export declare function polityFactionStanding(factionRegistry: FactionRegistry, polityA: Polity, polityB: Polity): Q;
|
|
274
|
+
export * from "./tech-diffusion.js";
|
|
275
|
+
export * from "./emotional-contagion.js";
|
package/dist/src/polity.js
CHANGED
|
@@ -396,3 +396,14 @@ export function polityFactionStanding(factionRegistry, polityA, polityB) {
|
|
|
396
396
|
return factionRegistry.globalStanding
|
|
397
397
|
.get(polityA.factionId)?.get(polityB.factionId) ?? STANDING_NEUTRAL;
|
|
398
398
|
}
|
|
399
|
+
// ── Campaign Layer barrel (CE-14) ──────────────────────────────────────────────
|
|
400
|
+
//
|
|
401
|
+
// The `ananke/polity` subpath re-exports the full Socio-Economic Campaign Layer
|
|
402
|
+
// so that a host can import everything from one entry point:
|
|
403
|
+
//
|
|
404
|
+
// import { stepPolityDay, stepTechDiffusion, applyEmotionalContagion }
|
|
405
|
+
// from "ananke/polity";
|
|
406
|
+
//
|
|
407
|
+
// Both modules are Tier 1 (Stable) from v0.2.0.
|
|
408
|
+
export * from "./tech-diffusion.js";
|
|
409
|
+
export * from "./emotional-contagion.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@its-not-rocket-science/ananke",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Deterministic lockstep-friendly SI-units RPG/physics core (fixed-point TS)",
|
|
6
6
|
"license": "MIT",
|
|
@@ -81,6 +81,7 @@
|
|
|
81
81
|
"generate-zoo": "node dist/tools/generate-zoo.js",
|
|
82
82
|
"generate-map": "node dist/tools/generate-map.js",
|
|
83
83
|
"world-server": "node dist/tools/world-server.js",
|
|
84
|
+
"replication-server": "node dist/tools/replication-server.js",
|
|
84
85
|
"benchmark-check": "node dist/tools/benchmark-check.js",
|
|
85
86
|
"benchmark-check:strict": "node dist/tools/benchmark-check.js --threshold=0.10",
|
|
86
87
|
"benchmark-check:update": "node dist/tools/benchmark-check.js --update-baseline",
|