@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.
- package/CHANGELOG.md +288 -0
- package/README.md +150 -432
- package/STABLE_API.md +113 -490
- package/conformance/README.md +46 -44
- package/conformance/lockstep-sequence.json +395 -395
- package/conformance/phase-order.json +21 -0
- package/conformance/replay-parity.json +65 -65
- package/conformance/state-hash-regression.json +39 -0
- package/conformance/state-hash.json +23 -22
- package/dist/src/conformance.d.ts +8 -2
- package/dist/src/content/index.d.ts +3 -0
- package/dist/src/content/index.js +2 -0
- package/dist/src/content/injector.d.ts +19 -0
- package/dist/src/content/injector.js +61 -0
- package/dist/src/content/loader.d.ts +3 -0
- package/dist/src/content/loader.js +170 -0
- package/dist/src/content/types.d.ts +56 -0
- package/dist/src/content/types.js +1 -0
- package/dist/src/content/validator.d.ts +6 -0
- package/dist/src/content/validator.js +14 -0
- package/dist/src/content-pack.d.ts +3 -2
- package/dist/src/content-pack.js +205 -10
- package/dist/src/data-governance.d.ts +73 -0
- package/dist/src/data-governance.js +188 -0
- package/dist/src/debug.d.ts +6 -0
- package/dist/src/debug.js +9 -0
- package/dist/src/determinism.d.ts +12 -0
- package/dist/src/determinism.js +93 -0
- package/dist/src/dialogue.d.ts +41 -0
- package/dist/src/dialogue.js +113 -2
- package/dist/src/economy.d.ts +97 -3
- package/dist/src/economy.js +191 -37
- package/dist/src/history/autosave.d.ts +19 -0
- package/dist/src/history/autosave.js +98 -0
- package/dist/src/history/timetravel.d.ts +28 -0
- package/dist/src/history/timetravel.js +61 -0
- package/dist/src/index.d.ts +19 -31
- package/dist/src/index.js +20 -38
- package/dist/src/model3d.js +63 -2
- package/dist/src/narrative/combat-logger.d.ts +25 -0
- package/dist/src/narrative/combat-logger.js +97 -0
- package/dist/src/narrative/plausibility.d.ts +30 -0
- package/dist/src/narrative/plausibility.js +70 -0
- package/dist/src/narrative-layer.d.ts +2 -0
- package/dist/src/narrative-layer.js +2 -0
- package/dist/src/navigation/causal-chain.d.ts +26 -0
- package/dist/src/navigation/causal-chain.js +74 -0
- package/dist/src/netcode.d.ts +1 -1
- package/dist/src/netcode.js +1 -1
- package/dist/src/performance/adaptive-tick.d.ts +23 -0
- package/dist/src/performance/adaptive-tick.js +50 -0
- package/dist/src/plugins/loader.d.ts +23 -0
- package/dist/src/plugins/loader.js +86 -0
- package/dist/src/plugins/registry.d.ts +11 -0
- package/dist/src/plugins/registry.js +28 -0
- package/dist/src/plugins/types.d.ts +31 -0
- package/dist/src/plugins/types.js +7 -0
- package/dist/src/replay.js +5 -2
- package/dist/src/scenario.js +2 -1
- package/dist/src/serialization/binary.d.ts +5 -0
- package/dist/src/serialization/binary.js +193 -0
- package/dist/src/session.d.ts +115 -0
- package/dist/src/session.js +228 -0
- package/dist/src/sim/ai/decide.js +1 -1
- package/dist/src/sim/ai/personality.js +2 -2
- package/dist/src/sim/bodyplan.d.ts +30 -0
- package/dist/src/sim/context.d.ts +2 -0
- package/dist/src/sim/kernel.js +80 -1294
- package/dist/src/sim/normalization.d.ts +12 -0
- package/dist/src/sim/normalization.js +92 -0
- package/dist/src/sim/resolvers/attack-resolver.d.ts +30 -0
- package/dist/src/sim/resolvers/attack-resolver.js +310 -0
- package/dist/src/sim/resolvers/capability-resolver.d.ts +15 -0
- package/dist/src/sim/resolvers/capability-resolver.js +270 -0
- package/dist/src/sim/resolvers/grapple-resolver.d.ts +28 -0
- package/dist/src/sim/resolvers/grapple-resolver.js +70 -0
- package/dist/src/sim/resolvers/shoot-resolver.d.ts +27 -0
- package/dist/src/sim/resolvers/shoot-resolver.js +212 -0
- package/dist/src/sim/resolvers/treat-resolver.d.ts +16 -0
- package/dist/src/sim/resolvers/treat-resolver.js +77 -0
- package/dist/src/sim/step/apply/intents.d.ts +6 -0
- package/dist/src/sim/step/apply/intents.js +83 -0
- package/dist/src/sim/step/kernel-pipeline.d.ts +9 -0
- package/dist/src/sim/step/kernel-pipeline.js +15 -0
- package/dist/src/sim/step/phases/capability-phase.d.ts +8 -0
- package/dist/src/sim/step/phases/capability-phase.js +65 -0
- package/dist/src/sim/step/phases/cooldowns-phase.d.ts +3 -0
- package/dist/src/sim/step/phases/cooldowns-phase.js +37 -0
- package/dist/src/sim/step/phases/prepare-phase.d.ts +10 -0
- package/dist/src/sim/step/phases/prepare-phase.js +33 -0
- package/dist/src/sim/step/pipeline.d.ts +2 -0
- package/dist/src/sim/step/pipeline.js +15 -0
- package/dist/src/sim/step/resolvers/impact-resolver.d.ts +9 -0
- package/dist/src/sim/step/resolvers/impact-resolver.js +55 -0
- package/dist/src/sim/step/world-phases.d.ts +7 -0
- package/dist/src/sim/step/world-phases.js +15 -0
- package/dist/src/sim/step/world-step-context.d.ts +23 -0
- package/dist/src/sim/step/world-step-context.js +1 -0
- package/dist/src/sim/systemic-toxicology.js +1 -1
- package/dist/src/sim/team.js +2 -2
- package/dist/src/sim/testing.js +4 -3
- package/dist/src/sim/toxicology.d.ts +1 -1
- package/dist/src/sim/toxicology.js +1 -1
- package/dist/src/sim/world.d.ts +17 -24
- package/dist/src/snapshot.js +3 -6
- package/dist/src/tier2.d.ts +19 -0
- package/dist/src/tier2.js +21 -0
- package/dist/src/tier3.d.ts +10 -0
- package/dist/src/tier3.js +12 -0
- package/dist/src/version.d.ts +6 -0
- package/dist/src/version.js +8 -0
- package/dist/src/wasm/bridge.d.ts +14 -0
- package/dist/src/wasm/bridge.js +84 -0
- package/dist/src/wasm-kernel.d.ts +2 -0
- package/dist/src/wasm-kernel.js +1 -0
- package/dist/src/world-evolution-backend/engine.d.ts +4 -0
- package/dist/src/world-evolution-backend/engine.js +347 -0
- package/dist/src/world-evolution-backend/host-schema.d.ts +145 -0
- package/dist/src/world-evolution-backend/host-schema.js +375 -0
- package/dist/src/world-evolution-backend/index.d.ts +1 -0
- package/dist/src/world-evolution-backend/index.js +1 -0
- package/dist/src/world-evolution-backend/open-world-host-adapter.d.ts +96 -0
- package/dist/src/world-evolution-backend/open-world-host-adapter.js +208 -0
- package/dist/src/world-evolution-backend/profiles.d.ts +4 -0
- package/dist/src/world-evolution-backend/profiles.js +136 -0
- package/dist/src/world-evolution-backend/public.d.ts +11 -0
- package/dist/src/world-evolution-backend/public.js +7 -0
- package/dist/src/world-evolution-backend/reproducibility.d.ts +8 -0
- package/dist/src/world-evolution-backend/reproducibility.js +35 -0
- package/dist/src/world-evolution-backend/timeline.d.ts +6 -0
- package/dist/src/world-evolution-backend/timeline.js +337 -0
- package/dist/src/world-evolution-backend/types.d.ts +138 -0
- package/dist/src/world-evolution-backend/types.js +1 -0
- package/dist/src/world-evolution-host-backend.d.ts +51 -0
- package/dist/src/world-evolution-host-backend.js +97 -0
- package/dist/src/world-evolution.d.ts +201 -0
- package/dist/src/world-evolution.js +543 -0
- package/dist/src/world-factory.js +2 -1
- package/dist/tools/pack-cli.js +55 -2
- package/docs/bridge-contract.md +140 -332
- package/docs/completion-evidence-dashboard.md +63 -0
- package/docs/host-contract.md +86 -310
- package/docs/host-world-evolution-schema.md +155 -0
- package/docs/integration-primer.md +29 -22
- package/docs/migration-monolith-to-modular.md +102 -120
- package/docs/package-architecture.md +116 -323
- package/docs/plugins/README.md +42 -0
- package/docs/plugins/hooks.md +22 -0
- package/docs/plugins/publishing.md +29 -0
- package/docs/plugins/security-model.md +273 -0
- package/docs/project-overview.md +30 -30
- package/docs/release-dashboard.md +47 -0
- package/docs/session-api.md +127 -0
- package/docs/stable-api-manifest.json +52 -0
- package/docs/trust-dashboard.md +37 -0
- package/docs/versioning.md +256 -245
- package/docs/wire-protocol.md +140 -209
- package/docs/world-evolution-backend.md +200 -0
- package/docs/world-evolution-engine.md +150 -0
- package/docs/world-evolution-host-backend.md +70 -0
- package/docs/world-evolution-orchestration.md +248 -0
- package/package.json +125 -6
- package/schema/content-pack.schema.json +85 -0
- package/schema/plugin.schema.json +57 -0
- package/schema/world-evolution-input.schema.json +196 -0
package/docs/wire-protocol.md
CHANGED
|
@@ -1,209 +1,140 @@
|
|
|
1
|
-
# Ananke
|
|
2
|
-
|
|
3
|
-
This
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
|
16
|
-
|
|
17
|
-
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
| `
|
|
134
|
-
|
|
135
|
-
| `
|
|
136
|
-
| `
|
|
137
|
-
| `
|
|
138
|
-
| `
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
Use the built-in tick counter and entity count as a cheap hash for divergence
|
|
143
|
-
detection:
|
|
144
|
-
|
|
145
|
-
```typescript
|
|
146
|
-
function stateHash(world: WorldState): number {
|
|
147
|
-
return world.tick * 0x10000 + (world.entities.length & 0xFFFF);
|
|
148
|
-
}
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
A full structural hash is more robust but expensive; use it only on resync.
|
|
152
|
-
|
|
153
|
-
### 4.3 Lockstep loop
|
|
154
|
-
|
|
155
|
-
```
|
|
156
|
-
┌──────────────────────────────────────────────────────────┐
|
|
157
|
-
│ Client Server │
|
|
158
|
-
│ │
|
|
159
|
-
│ collect commands ──── cmd ──► apply to authoritative │
|
|
160
|
-
│ state │
|
|
161
|
-
│ ◄── ack ─── broadcast stateHash │
|
|
162
|
-
│ verify hash │
|
|
163
|
-
│ if mismatch ─── resync req ─► send full snapshot │
|
|
164
|
-
│ ◄── resync ── │
|
|
165
|
-
│ restore snapshot │
|
|
166
|
-
└──────────────────────────────────────────────────────────┘
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
### 4.4 Transport encoding
|
|
170
|
-
|
|
171
|
-
Use JSON for development and debugging. For production, encode wire messages
|
|
172
|
-
as CBOR (RFC 8949) or MessagePack for ~30% size reduction. The message
|
|
173
|
-
structure is identical; only the outer encoding changes.
|
|
174
|
-
|
|
175
|
-
---
|
|
176
|
-
|
|
177
|
-
## 5. Save File Recommendations
|
|
178
|
-
|
|
179
|
-
| Scenario | Format | Compression |
|
|
180
|
-
|----------|--------|-------------|
|
|
181
|
-
| Development / debugging | JSON (pretty-printed) | none |
|
|
182
|
-
| Production saves | JSON (compact) | gzip or zstd |
|
|
183
|
-
| Network sync (full state) | JSON or CBOR | none (already compact) |
|
|
184
|
-
| Network sync (incremental) | Binary diff (`packDiff`) | none |
|
|
185
|
-
| Replay archives | JSON replay schema | zstd |
|
|
186
|
-
|
|
187
|
-
---
|
|
188
|
-
|
|
189
|
-
## 6. Migration
|
|
190
|
-
|
|
191
|
-
Load a save and bring it to the current schema version before simulating:
|
|
192
|
-
|
|
193
|
-
```typescript
|
|
194
|
-
import {
|
|
195
|
-
migrateWorld, validateSnapshot, stampSnapshot,
|
|
196
|
-
} from "@its-not-rocket-science/ananke/schema";
|
|
197
|
-
|
|
198
|
-
function loadSave(json: string): WorldState {
|
|
199
|
-
const raw = JSON.parse(json) as Record<string, unknown>;
|
|
200
|
-
const migrated = migrateWorld(raw); // no-op until 0.2 is released
|
|
201
|
-
const errors = validateSnapshot(migrated);
|
|
202
|
-
if (errors.length > 0) {
|
|
203
|
-
throw new Error(`Invalid save: ${errors.map(e => `${e.path}: ${e.message}`).join("; ")}`);
|
|
204
|
-
}
|
|
205
|
-
return migrated as WorldState;
|
|
206
|
-
}
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
See `docs/migration-monolith-to-modular.md` for package-level migration guidance.
|
|
1
|
+
# Ananke Wire Protocol & Schema Formats
|
|
2
|
+
|
|
3
|
+
This page documents only what is currently shipped in code. It avoids treating roadmap ideas as current protocol guarantees.
|
|
4
|
+
|
|
5
|
+
For maintainer promises/non-promises and pinning recommendations, see `docs/support-boundaries.md`.
|
|
6
|
+
|
|
7
|
+
Status badge legend:
|
|
8
|
+
- 🟢 **Implemented + public**: implemented and exported on documented package entrypoints.
|
|
9
|
+
- 🟡 **Partial**: implemented API exists, but completeness/coverage is intentionally limited.
|
|
10
|
+
- 🟠 **Implemented + internal**: implemented and exported only on internal/advanced surfaces.
|
|
11
|
+
- 🔵 **Planned**: not shipped as a canonical helper/module.
|
|
12
|
+
|
|
13
|
+
## Compatibility table (current)
|
|
14
|
+
|
|
15
|
+
| Surface | Status | Current contract |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| Save format | 🟢 Implemented + public | JSON snapshots stamped with `_ananke_version`/`_schema` via `stampSnapshot` on `@its-not-rocket-science/ananke/schema` (and `./schema-migration` alias). |
|
|
18
|
+
| Replay format | 🟢 Implemented + public | `Replay` JSON via `serializeReplay` / `deserializeReplay` on root entrypoint `@its-not-rocket-science/ananke`. |
|
|
19
|
+
| Schema migration | 🟡 Partial | `migrateWorld` + `registerMigration` are shipped; only explicitly registered migration edges run (no built-in universal chain). |
|
|
20
|
+
| Binary diff | 🟠 Implemented + internal | `diffWorldState` / `packDiff` / `unpackDiff` / `applyDiff` are shipped on `@its-not-rocket-science/ananke/tier3` (advanced/internal surface). |
|
|
21
|
+
| Lockstep messages | 🔵 Planned | No canonical exported lockstep message envelope/type module. Hosts define their own message schema today. |
|
|
22
|
+
|
|
23
|
+
Versioning note: production hosts should pin exact patch versions for schema migration and any non-root protocol helpers.
|
|
24
|
+
|
|
25
|
+
## 1) Save snapshots (JSON)
|
|
26
|
+
|
|
27
|
+
**Status:** 🟢 Implemented + public
|
|
28
|
+
|
|
29
|
+
Shipped helpers:
|
|
30
|
+
- `stampSnapshot(snapshot, schemaKind)`
|
|
31
|
+
- `validateSnapshot(snapshot)`
|
|
32
|
+
- `detectVersion(snapshot)`
|
|
33
|
+
- `isValidSnapshot(snapshot)`
|
|
34
|
+
|
|
35
|
+
Entrypoints:
|
|
36
|
+
- `@its-not-rocket-science/ananke/schema`
|
|
37
|
+
- `@its-not-rocket-science/ananke/schema-migration` (alias)
|
|
38
|
+
|
|
39
|
+
Example:
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import { stampSnapshot, validateSnapshot } from "@its-not-rocket-science/ananke/schema";
|
|
43
|
+
|
|
44
|
+
const world = {} as Parameters<typeof stampSnapshot>[0];
|
|
45
|
+
const stamped = stampSnapshot(world, "world");
|
|
46
|
+
const errors = validateSnapshot(stamped);
|
|
47
|
+
if (errors.length > 0) throw new Error("invalid snapshot");
|
|
48
|
+
const json = JSON.stringify(stamped);
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Notes:
|
|
52
|
+
- `validateSnapshot` validates core structural fields required by simulation, and permits extra host fields.
|
|
53
|
+
- Canonical schema files are shipped in `schema/world.schema.json` and `schema/replay.schema.json`.
|
|
54
|
+
|
|
55
|
+
## 2) Replay format
|
|
56
|
+
|
|
57
|
+
**Status:** 🟢 Implemented + public
|
|
58
|
+
|
|
59
|
+
Shipped helpers (root entrypoint):
|
|
60
|
+
- `ReplayRecorder`
|
|
61
|
+
- `replayTo`
|
|
62
|
+
- `serializeReplay`
|
|
63
|
+
- `deserializeReplay`
|
|
64
|
+
|
|
65
|
+
Example:
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
import { ReplayRecorder, serializeReplay, deserializeReplay, replayTo } from "@its-not-rocket-science/ananke";
|
|
69
|
+
|
|
70
|
+
const world = {} as ConstructorParameters<typeof ReplayRecorder>[0];
|
|
71
|
+
const ctx = {} as Parameters<typeof replayTo>[2];
|
|
72
|
+
const recorder = new ReplayRecorder(world);
|
|
73
|
+
// ... record frames while stepping
|
|
74
|
+
const json = serializeReplay(recorder.toReplay());
|
|
75
|
+
const replay = deserializeReplay(json);
|
|
76
|
+
const worldAt100 = replayTo(replay, 100, ctx);
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Notes:
|
|
80
|
+
- Replay JSON includes custom Map handling used by serializer/reviver.
|
|
81
|
+
- This is the shipped deterministic replay contract.
|
|
82
|
+
|
|
83
|
+
## 3) Schema migration
|
|
84
|
+
|
|
85
|
+
**Status:** 🟡 Partial
|
|
86
|
+
|
|
87
|
+
Shipped helpers:
|
|
88
|
+
- `registerMigration(fromVersion, toVersion, fn)`
|
|
89
|
+
- `migrateWorld(snapshot, toVersion?)`
|
|
90
|
+
|
|
91
|
+
Behavior today:
|
|
92
|
+
- If snapshot version equals target version, `migrateWorld` returns unchanged.
|
|
93
|
+
- If no migration is registered for the requested edge, `migrateWorld` throws.
|
|
94
|
+
- Legacy snapshots without `_ananke_version` are treated as `"0.0"`.
|
|
95
|
+
|
|
96
|
+
This is a real API, but migration coverage is only as complete as registered migration paths.
|
|
97
|
+
|
|
98
|
+
## 4) Binary diff format
|
|
99
|
+
|
|
100
|
+
**Status:** 🟠 Implemented + internal
|
|
101
|
+
|
|
102
|
+
Shipped helpers (Tier 3 surface):
|
|
103
|
+
- `diffWorldState(prev, next)`
|
|
104
|
+
- `packDiff(diff)`
|
|
105
|
+
- `unpackDiff(bytes)`
|
|
106
|
+
- `applyDiff(base, diff)`
|
|
107
|
+
|
|
108
|
+
Entrypoint:
|
|
109
|
+
- `@its-not-rocket-science/ananke/tier3`
|
|
110
|
+
|
|
111
|
+
Scope:
|
|
112
|
+
- Useful for incremental state transport/storage.
|
|
113
|
+
- Not part of Tier-1 root stability contract.
|
|
114
|
+
|
|
115
|
+
## 5) Lockstep message protocol
|
|
116
|
+
|
|
117
|
+
**Status:** 🔵 Planned
|
|
118
|
+
|
|
119
|
+
Current code provides deterministic primitives (`stepWorld`, replay, and `hashWorldState` in netcode), but **does not** provide a canonical exported lockstep message protocol module with fixed message kinds/envelopes.
|
|
120
|
+
|
|
121
|
+
Roadmap/proposed protocol details have been moved to `docs/planned-protocol-work.md`.
|
|
122
|
+
|
|
123
|
+
## 6) Helper/path audit (docs ↔ code)
|
|
124
|
+
|
|
125
|
+
| Item | Exists in code | Exported | Classification |
|
|
126
|
+
|---|---|---|---|
|
|
127
|
+
| `stampSnapshot` (`src/schema-migration.ts`) | yes | `./schema`, `./schema-migration` | implemented + public |
|
|
128
|
+
| `validateSnapshot` (`src/schema-migration.ts`) | yes | `./schema`, `./schema-migration` | implemented + public |
|
|
129
|
+
| `migrateWorld` (`src/schema-migration.ts`) | yes | `./schema`, `./schema-migration` | partial |
|
|
130
|
+
| `registerMigration` (`src/schema-migration.ts`) | yes | `./schema`, `./schema-migration` | implemented + public |
|
|
131
|
+
| `serializeReplay` (`src/replay.ts`) | yes | root `.` | implemented + public |
|
|
132
|
+
| `deserializeReplay` (`src/replay.ts`) | yes | root `.` | implemented + public |
|
|
133
|
+
| `diffWorldState` (`src/snapshot.ts`) | yes | `./tier3` | implemented + internal |
|
|
134
|
+
| `packDiff` (`src/snapshot.ts`) | yes | `./tier3` | implemented + internal |
|
|
135
|
+
| `unpackDiff` (`src/snapshot.ts`) | yes | `./tier3` | implemented + internal |
|
|
136
|
+
| `applyDiff` (`src/snapshot.ts`) | yes | `./tier3` | implemented + internal |
|
|
137
|
+
| `schema/world.schema.json` | yes | package file artifact | implemented + public artifact |
|
|
138
|
+
| `schema/replay.schema.json` | yes | package file artifact | implemented + public artifact |
|
|
139
|
+
| Canonical lockstep message module | no | n/a | planned |
|
|
140
|
+
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# World Evolution Backend (Host Integration)
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
`world-evolution-backend` is an additive, deterministic composition layer for host platforms (for example OpenWorldBuilder) that need reproducible world-scale progression runs.
|
|
6
|
+
|
|
7
|
+
It does **not** replace existing systems. It orchestrates existing modules and emits host-facing outputs:
|
|
8
|
+
|
|
9
|
+
- final world snapshot
|
|
10
|
+
- per-step timeline/event log
|
|
11
|
+
- summary metrics
|
|
12
|
+
- optional deltas/checkpoints
|
|
13
|
+
|
|
14
|
+
## Stable import path
|
|
15
|
+
|
|
16
|
+
Preferred additive subpath export:
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
import {
|
|
20
|
+
runWorldEvolution,
|
|
21
|
+
listAvailableWorldEvolutionProfiles,
|
|
22
|
+
} from "@its-not-rocket-science/ananke/world-evolution-engine";
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Compatibility alias (still supported):
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
import { runWorldEvolution } from "@its-not-rocket-science/ananke/world-evolution-backend";
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
No Tier-1 root exports were changed.
|
|
32
|
+
|
|
33
|
+
## Host flow
|
|
34
|
+
|
|
35
|
+
1. Build an initial `WorldEvolutionSnapshot` (canon state).
|
|
36
|
+
2. Pick a profile (`minimal_world_history`, `polity_dynamics`, `conflict_heavy`, `climate_and_migration`, `full_world_evolution`) and optionally layer deterministic host overrides on top.
|
|
37
|
+
3. Run `runWorldEvolution({ snapshot, steps, ... })`.
|
|
38
|
+
4. Read:
|
|
39
|
+
- `finalSnapshot`
|
|
40
|
+
- `timeline`
|
|
41
|
+
- `metrics`
|
|
42
|
+
- optional `deltas`/`checkpoints`
|
|
43
|
+
|
|
44
|
+
## Canon vs derived timelines
|
|
45
|
+
|
|
46
|
+
- `initialSnapshot` is treated as canonical input.
|
|
47
|
+
- simulation mutations occur on an isolated runtime clone.
|
|
48
|
+
- `finalSnapshot` and timeline artifacts are derived outputs.
|
|
49
|
+
|
|
50
|
+
This keeps lore/canon source state separate from generated timeline projections.
|
|
51
|
+
|
|
52
|
+
## Composition architecture (additive)
|
|
53
|
+
|
|
54
|
+
The backend composes existing systems in deterministic order per step:
|
|
55
|
+
|
|
56
|
+
1. **Polity core**: `stepPolityDay` (trade, war, morale/stability baseline)
|
|
57
|
+
2. **Governance**: `stepGovernanceCooldown`, `stepGovernanceStability`, `computeGovernanceModifiers`
|
|
58
|
+
3. **Diplomacy**: treaty strength/expiry progression
|
|
59
|
+
4. **Trade routes**: efficiency step + `applyDailyTrade`
|
|
60
|
+
5. **Migration**: `resolveMigration` + `applyMigrationFlows`
|
|
61
|
+
6. **Climate**: deterministic `generateClimateEvent`, aggregate effects, lifecycle stepping
|
|
62
|
+
7. **Epidemic**: `stepEpidemic` + death pressure application
|
|
63
|
+
|
|
64
|
+
All sequencing is deterministic and order-stable (sorted IDs, no `Math.random`).
|
|
65
|
+
|
|
66
|
+
## Deterministic profile presets
|
|
67
|
+
|
|
68
|
+
Profiles are explicit additive controls over existing modules and all share the same explicit pipeline order:
|
|
69
|
+
|
|
70
|
+
1. `polity`
|
|
71
|
+
2. `governance`
|
|
72
|
+
3. `diplomacy`
|
|
73
|
+
4. `trade`
|
|
74
|
+
5. `migration`
|
|
75
|
+
6. `climate`
|
|
76
|
+
7. `epidemic`
|
|
77
|
+
|
|
78
|
+
Preset intent:
|
|
79
|
+
|
|
80
|
+
- `minimal_world_history`: only core polity day stepping.
|
|
81
|
+
- `polity_dynamics`: polity + governance + diplomacy + trade.
|
|
82
|
+
- `conflict_heavy`: polity/governance/diplomacy/trade/migration with no climate/epidemic load.
|
|
83
|
+
- `climate_and_migration`: polity + migration + climate + epidemic pressure.
|
|
84
|
+
- `full_world_evolution`: all currently integrated world-scale subsystems enabled.
|
|
85
|
+
|
|
86
|
+
Legacy IDs (`balanced`, `resilience`, `expansion`) are kept as deterministic aliases to `full_world_evolution` for compatibility.
|
|
87
|
+
|
|
88
|
+
### Profile matrix (explicit ruleset behavior)
|
|
89
|
+
|
|
90
|
+
| Profile | Polity | Governance | Diplomacy | Trade | Migration | Climate | Epidemic | Intended host use |
|
|
91
|
+
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
92
|
+
| `minimal_world_history` | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | Lowest-cost long-horizon history baselines |
|
|
93
|
+
| `polity_dynamics` | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | Political/economic simulation without environmental load |
|
|
94
|
+
| `conflict_heavy` | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | War/mobility-driven scenarios with reduced overhead |
|
|
95
|
+
| `climate_and_migration` | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | Environmental stress, displacement, and disease pressure studies |
|
|
96
|
+
| `full_world_evolution` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | Full-stack world simulation for maximal systemic richness |
|
|
97
|
+
|
|
98
|
+
All presets preserve the same deterministic subsystem execution order and only enable/disable or tune existing mechanics.
|
|
99
|
+
|
|
100
|
+
## Host overrides layered on profile
|
|
101
|
+
|
|
102
|
+
Hosts can provide:
|
|
103
|
+
|
|
104
|
+
- `profileId` to select a preset
|
|
105
|
+
- `ruleOverrides` to override specific fields deterministically
|
|
106
|
+
|
|
107
|
+
Overrides are applied additively to the resolved profile; no random behavior is introduced.
|
|
108
|
+
|
|
109
|
+
Example:
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
import {
|
|
113
|
+
resolveWorldEvolutionProfile,
|
|
114
|
+
runWorldEvolution,
|
|
115
|
+
} from "@its-not-rocket-science/ananke/world-evolution-backend";
|
|
116
|
+
|
|
117
|
+
const snapshot = {} as any;
|
|
118
|
+
const baseProfile = resolveWorldEvolutionProfile("polity_dynamics");
|
|
119
|
+
|
|
120
|
+
const result = runWorldEvolution({
|
|
121
|
+
snapshot,
|
|
122
|
+
steps: 90,
|
|
123
|
+
profile: {
|
|
124
|
+
...baseProfile,
|
|
125
|
+
governanceStabilityDaysPerStep: 2,
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
The resolved profile remains deterministic for a fixed snapshot/seed + override object.
|
|
131
|
+
|
|
132
|
+
## Profile comparison example
|
|
133
|
+
|
|
134
|
+
See `examples/world-evolution-profiles-comparison.ts` for a side-by-side run comparing multiple profiles over the same input state and seed.
|
|
135
|
+
|
|
136
|
+
## Determinism notes
|
|
137
|
+
|
|
138
|
+
- Uses fixed-point arithmetic and existing deterministic world primitives.
|
|
139
|
+
- Iteration order is normalized by IDs before applying updates.
|
|
140
|
+
- same snapshot + same profile + same step count => byte-for-byte equal result object.
|
|
141
|
+
|
|
142
|
+
## Minimal API
|
|
143
|
+
|
|
144
|
+
- `createWorldEvolutionSnapshot(snapshot)`
|
|
145
|
+
- `runWorldEvolution(request)`
|
|
146
|
+
- `listAvailableWorldEvolutionProfiles()`
|
|
147
|
+
- plus profile helpers/types via the same subpath.
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
## Host timeline/event layer for readable world history
|
|
152
|
+
|
|
153
|
+
For UI-facing history rendering, use the presentation-oriented event stream builder:
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
import {
|
|
157
|
+
runWorldEvolution,
|
|
158
|
+
buildEvolutionTimeline,
|
|
159
|
+
sortTimelineEventsBySignificance,
|
|
160
|
+
} from "@its-not-rocket-science/ananke/world-evolution-backend";
|
|
161
|
+
import type { WorldEvolutionSnapshot } from "@its-not-rocket-science/ananke/world-evolution-backend";
|
|
162
|
+
|
|
163
|
+
declare const snapshot: WorldEvolutionSnapshot;
|
|
164
|
+
|
|
165
|
+
const result = runWorldEvolution({ snapshot, steps: 180, profileId: "full_world_evolution" });
|
|
166
|
+
const timeline = buildEvolutionTimeline(result, { includeSummaryText: true });
|
|
167
|
+
const highlights = sortTimelineEventsBySignificance(timeline).slice(0, 10);
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
`buildEvolutionTimeline` converts subsystem output into a **stable chronological stream** with:
|
|
171
|
+
|
|
172
|
+
- deterministic `id` and `hash`
|
|
173
|
+
- event categories (`polity`, `migration`, `conflict`, `diplomacy`, `economy`, `disease`, `climate`, `infrastructure`, `governance`, `mythology_culture`)
|
|
174
|
+
- `severity` / `significance` scoring for host ranking
|
|
175
|
+
- optional summary text for direct UI rendering
|
|
176
|
+
- fact references (`factRefs`) pointing back to originating step/subsystem facts
|
|
177
|
+
|
|
178
|
+
### Raw engine state vs presentation-oriented timeline events
|
|
179
|
+
|
|
180
|
+
- **Raw engine state** (`finalSnapshot`, step metrics, per-step subsystem arrays):
|
|
181
|
+
- canonical simulation outputs
|
|
182
|
+
- optimized for correctness/replay/integrity
|
|
183
|
+
- rich but not directly UI-friendly
|
|
184
|
+
|
|
185
|
+
- **Presentation timeline events** (`buildEvolutionTimeline` output):
|
|
186
|
+
- additive read-only projection layer
|
|
187
|
+
- normalized shape for host feeds, journals, and map overlays
|
|
188
|
+
- stable ordering + identity for caching/diffing in external platforms
|
|
189
|
+
- preserves links back to raw subsystem facts through `factRefs`
|
|
190
|
+
|
|
191
|
+
This separation lets hosts keep simulation truth in snapshots while rendering an approachable “world history” layer for players.
|
|
192
|
+
|
|
193
|
+
## Session orchestration layer
|
|
194
|
+
|
|
195
|
+
For hosts that need a session-oriented API (`createEvolutionSession`, `stepEvolution`, serialization helpers), use `@its-not-rocket-science/ananke/world-evolution` and see `docs/world-evolution-orchestration.md`.
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
## Host canonical schema
|
|
199
|
+
|
|
200
|
+
For external platform integrators, see `docs/host-world-evolution-schema.md` and `schema/world-evolution-input.schema.json`.
|