@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,273 @@
1
+ # Plugin Security Threat Model
2
+
3
+ This document defines the production threat model for loading Ananke plugins and maps risks to concrete controls.
4
+
5
+ > **Security posture summary:** `loadPlugin(...)` is a capability-loading API, not a turnkey sandbox.
6
+ > For trusted/internal plugins, the default runtime may be acceptable with guardrails.
7
+ > For untrusted/third-party plugins, production deployments should use stronger isolation and policy controls than the defaults.
8
+
9
+ ## Scope and assumptions
10
+
11
+ ### In scope
12
+
13
+ - Plugin loading and execution through `loadPlugin(...)` in `src/plugins/loader.ts`.
14
+ - Manifest-declared permissions from `plugin.json`.
15
+ - Runtime API capabilities exposed to plugin code (`readWorldState`, `mutateWorld`, `emitTelemetry`, `writeArtifact`).
16
+ - Host-side operational controls (timeouts, quotas, process isolation, filesystem layout, incident response).
17
+
18
+ ### Out of scope
19
+
20
+ - Formal verification of sandbox correctness.
21
+ - Side-channel resistance (timing/cache/CPU microarchitectural channels).
22
+ - Supply-chain compromise of host dependencies outside the plugin subsystem.
23
+
24
+ ### Security assumptions
25
+
26
+ - Plugin authors can be buggy, negligent, or malicious.
27
+ - Plugin source may come from public registries.
28
+ - Host application owns final policy decisions (what to load, where to execute, and with what privileges).
29
+
30
+ ---
31
+
32
+ ## Assets and security objectives
33
+
34
+ ### Assets to protect
35
+
36
+ - **Simulation integrity:** world-state correctness and expected game/runtime behavior.
37
+ - **Host availability:** CPU, memory, I/O capacity, and event-loop responsiveness.
38
+ - **Confidentiality of runtime data:** world state, event streams, secrets accidentally present in context, and generated artifacts.
39
+ - **Artifact integrity:** downstream consumers should not be misled or compromised by plugin outputs.
40
+ - **Operational trust:** telemetry quality, audit trail accuracy, and incident recovery capability.
41
+
42
+ ### Objectives
43
+
44
+ - Prevent unauthorized access to privileged host capabilities.
45
+ - Limit blast radius of malicious/buggy plugin code.
46
+ - Detect and contain abuse quickly.
47
+ - Preserve ability to disable/revoke problematic plugins without full service outage.
48
+
49
+ ---
50
+
51
+ ## Trust boundaries
52
+
53
+ 1. **Plugin source boundary**
54
+ - Boundary between host-controlled codebase and external plugin package (`plugin.json`, `index.js`).
55
+ - Threat: malicious payloads, deceptive manifests, dependency confusion, tampering in transit.
56
+
57
+ 2. **Manifest-to-policy boundary**
58
+ - Plugin declares permissions; host decides whether to honor them.
59
+ - Threat: over-broad permissions granted without review.
60
+
61
+ 3. **Evaluator boundary**
62
+ - Default evaluator uses `node:vm` minimal CommonJS sandbox.
63
+ - Threat: evaluator escape, context confusion, unsafe API exposure.
64
+
65
+ 4. **Runtime capability boundary**
66
+ - Only methods on `PluginRuntimeApi` should be reachable.
67
+ - Threat: capability abuse once permission is granted.
68
+
69
+ 5. **Hook execution boundary**
70
+ - Plugin handlers execute inside host lifecycle (`runHook`).
71
+ - Threat: unbounded runtime, blocking, starvation, exception abuse.
72
+
73
+ 6. **Artifact storage boundary**
74
+ - Plugin writes data into artifact filesystem namespace.
75
+ - Threat: disk exhaustion, path manipulation, poisoned outputs for downstream tools.
76
+
77
+ 7. **Telemetry boundary**
78
+ - Plugin can emit host-collected telemetry (if permitted).
79
+ - Threat: exfiltration channel, log/metric poisoning, operational blind spots.
80
+
81
+ ---
82
+
83
+ ## Attacker model and capabilities
84
+
85
+ Assume an attacker can publish and convince operators to load a plugin. Once loaded, attacker-controlled code can:
86
+
87
+ - Execute arbitrary JavaScript **within the evaluator constraints**.
88
+ - Run hook handlers repeatedly at lifecycle trigger points.
89
+ - Use all granted runtime capabilities and intentionally stress their edge cases.
90
+ - Craft high-entropy payloads, large objects, and malformed outputs.
91
+ - Attempt to trigger evaluator/runtime bugs for sandbox escape.
92
+ - Abuse expected channels (telemetry/artifacts) for covert exfiltration.
93
+
94
+ Assume attacker **cannot** directly modify host binaries/config unless another vulnerability exists.
95
+
96
+ ---
97
+
98
+ ## Threat analysis by category
99
+
100
+ ## 1) Sandbox escape
101
+
102
+ ### Risk
103
+
104
+ The default Node path uses in-process `node:vm` with minimal bindings. This reduces accidental access to host globals but should not be treated as a complete hostile-code isolation boundary.
105
+
106
+ ### Consequences
107
+
108
+ - Access to host process memory or APIs.
109
+ - Filesystem/network/process execution beyond intended plugin API.
110
+ - Full compromise of host trust domain.
111
+
112
+ ### Controls
113
+
114
+ - **Recommended for untrusted plugins:** out-of-process isolation (worker/process/container/VM) with explicit IPC protocol.
115
+ - Restrict host OS/container privileges (filesystem, network egress, Linux capabilities, syscall surface where possible).
116
+ - Keep evaluator/runtime patched and regression-tested with adversarial test corpus.
117
+
118
+ ## 2) Host capability abuse
119
+
120
+ ### Risk
121
+
122
+ Even without sandbox escape, allowed API methods can be abused:
123
+
124
+ - `write:worldState`: integrity compromise and subtle gameplay manipulation.
125
+ - `write:telemetry`: spam, poisoning, or covert leakage of sensitive context.
126
+ - `write:artifacts`: disk abuse, misleading reports, malicious payload staging.
127
+
128
+ ### Controls
129
+
130
+ - Permission minimization and explicit approval workflow per plugin.
131
+ - Host policy overlays (allow-list metrics, artifact path patterns, hook-level gates).
132
+ - Auditing that binds action to plugin ID + hook + timestamp.
133
+
134
+ ## 3) Denial of service (DoS)
135
+
136
+ ### Risk
137
+
138
+ - Expensive synchronous loops in hooks.
139
+ - High-frequency hook abuse causing event-loop starvation.
140
+ - Memory blowups via oversized payloads/artifacts.
141
+ - Flooding telemetry/artifact outputs.
142
+
143
+ ### Controls
144
+
145
+ - Per-hook timeout and cancellation policy.
146
+ - CPU/memory quotas and isolation boundaries.
147
+ - Per-plugin rate/size quotas for telemetry and artifacts.
148
+ - Circuit breakers / kill switches for misbehaving plugins.
149
+
150
+ ## 4) Artifact exfiltration and poisoning
151
+
152
+ ### Risk
153
+
154
+ Artifacts can become a data-exfiltration and downstream-attack channel.
155
+
156
+ - Sensitive context serialized to files and exported by external systems.
157
+ - Filename/content tricks that confuse parsers or operators.
158
+ - Excess artifact churn masking malicious outputs.
159
+
160
+ ### Controls
161
+
162
+ - Canonical path verification under approved root.
163
+ - File extension/content-type policy for machine-consumed artifacts.
164
+ - Quotas + retention windows + malware/content scanning where appropriate.
165
+ - Segregated storage and reduced read access for consumers.
166
+
167
+ ## 5) Telemetry exfiltration and poisoning
168
+
169
+ ### Risk
170
+
171
+ Telemetry is an intentional output channel and can be abused for covert transfer or operational deception.
172
+
173
+ ### Controls
174
+
175
+ - Schema validation, size limits, namespace allow-listing.
176
+ - Per-plugin event-rate quotas and anomaly detection.
177
+ - Separate internal-only metrics from plugin-controlled streams.
178
+
179
+ ---
180
+
181
+ ## Browser vs Node threat differences
182
+
183
+ ## Node hosts
184
+
185
+ - Default implementation path is in-process `node:vm` evaluation.
186
+ - Primary risk: single-process compromise blast radius if evaluator boundary fails.
187
+ - Strong recommendation for untrusted code: separate process/container with restricted OS permissions and explicit IPC API.
188
+
189
+ ## Browser hosts
190
+
191
+ - Preferred model is dedicated Web Worker execution with message-passed runtime API.
192
+ - Strength: better separation from UI thread by default.
193
+ - Residual risks: message validation bugs, resource exhaustion in worker, data leakage through postMessage channels.
194
+
195
+ ## Shared principle
196
+
197
+ In both environments, plugin security is primarily achieved by **defense in depth**: strict capability policy + isolation + quotas + monitoring + incident response.
198
+
199
+ ---
200
+
201
+ ## Trusted vs untrusted plugin deployment recommendations
202
+
203
+ ## Trusted/internal plugins (same organization, reviewed source)
204
+
205
+ Minimum recommended controls:
206
+
207
+ - Enforce least-privilege permissions.
208
+ - CI validation and pinned versions.
209
+ - Audit logs for mutations, telemetry, and artifact writes.
210
+ - Operational kill switch.
211
+
212
+ ## Untrusted/third-party plugins (public/community source)
213
+
214
+ Production recommended controls:
215
+
216
+ - Do not rely on default in-process evaluator alone.
217
+ - Run in isolated trust domain (process/container/worker with hardened IPC).
218
+ - Apply strict runtime budgets (time, memory, output volume).
219
+ - Require policy review before enablement.
220
+ - Continuous monitoring + fast revocation/rollback path.
221
+
222
+ ---
223
+
224
+ ## Guaranteed today vs deployment hardening vs future work
225
+
226
+ ## Guaranteed today (based on current implementation)
227
+
228
+ The following are implemented in `src/plugins/loader.ts` / `src/plugins/types.ts`:
229
+
230
+ - Plugin evaluation uses minimal CommonJS sandbox with `node:vm` by default.
231
+ - Initial module evaluation is constrained with a 100 ms VM timeout.
232
+ - Runtime permission checks enforce:
233
+ - `mutateWorld` requires `write:worldState`
234
+ - `emitTelemetry` requires `write:telemetry`
235
+ - `writeArtifact` requires `write:artifacts`
236
+ - `readWorldState` returns deep-frozen `structuredClone` data.
237
+ - Artifacts are written under `<artifactsRoot>/<pluginId>/<path>`.
238
+ - Host can provide custom `evaluator` option.
239
+
240
+ ## Recommended deployment hardening (not guaranteed by default)
241
+
242
+ - Isolate untrusted plugins out of process.
243
+ - Enforce per-hook timeout/cancellation and runtime budgets.
244
+ - Enforce memory, telemetry, and artifact quotas.
245
+ - Canonicalize and verify artifact paths remain under approved root.
246
+ - Restrict telemetry schemas/namespaces.
247
+ - Run with least-privilege OS/container identity.
248
+ - Implement deny-list/revocation and one-click disable.
249
+
250
+ ## Future work (explicitly not complete today)
251
+
252
+ - First-class built-in hook timeout/cancellation in core runtime.
253
+ - Built-in quota manager for telemetry/artifacts and payload sizes.
254
+ - Stronger default path canonicalization and artifact policy controls.
255
+ - Optional signed plugin manifests/modules and provenance verification.
256
+ - Security event stream spec for standardized audit integrations.
257
+
258
+ ---
259
+
260
+ ## Deployment checklist
261
+
262
+ A standalone checklist is maintained in:
263
+
264
+ - `docs/plugins/deployment-checklist.md`
265
+
266
+ Use that checklist during production readiness and change reviews.
267
+
268
+ ---
269
+
270
+ ## Implementation evidence
271
+
272
+ - `src/plugins/loader.ts`
273
+ - `src/plugins/types.ts`
@@ -21,8 +21,8 @@ built on top of that foundation and can be adopted independently.
21
21
  npm install @its-not-rocket-science/ananke
22
22
  ```
23
23
 
24
- ```typescript
25
- import { stepWorld, mkWorld, q, SCALE } from "@its-not-rocket-science/ananke";
24
+ ```typescript pseudocode
25
+ import { stepWorld, createWorld, q, SCALE } from "@its-not-rocket-science/ananke";
26
26
  ```
27
27
 
28
28
  Requires **Node ≥ 18**. TypeScript declarations are included — no `@types/` package needed.
@@ -49,14 +49,14 @@ Choose the path that matches your immediate need. Ignore the rest until you nee
49
49
 
50
50
  **Install:** `npm install @its-not-rocket-science/ananke`
51
51
 
52
- **Minimal imports:** `stepWorld`, `mkWorld`, `q`, `SCALE`, `generateIndividual`
52
+ **Minimal imports:** `createWorld`, `stepWorld`, `q`, `SCALE`
53
53
 
54
54
  **30-minute quickstart:** Run `tools/vertical-slice.ts` (`npm run run:vertical-slice`).
55
55
  A Knight fights a Brawler across three seeds, producing a physics-grounded combat log.
56
56
  Read `docs/host-contract.md` for the stable integration surface, then
57
57
  `docs/integration-primer.md` for data-flow diagrams and type glossary.
58
58
 
59
- **Key entry points:** `stepWorld()`, `resolveHit()`, `generateIndividual()`, `mkKnight()`
59
+ **Key entry points:** `createWorld()`, `stepWorld()` (+ Tier 2/3 subpaths as needed)
60
60
 
61
61
  **What to ignore for now:** Phases 56–67 (campaign-scale systems), all `tools/` except `vertical-slice.ts`
62
62
 
@@ -171,7 +171,7 @@ variance distributions, producing a unique entity with realistic physical spread
171
171
 
172
172
  ## Current implementation status
173
173
 
174
- **Phases 1–60 complete** (including Phase 6 Formation System, 2ext, 3ext, 8B, 8C, 10B, 10C, 11C, 12B, 31–60). Melee combat,
174
+ **Phases 1–60 are implemented and integrated in-repo** (including Phase 6 Formation System, 2ext, 3ext, 8B, 8C, 10B, 10C, 11C, 12B, 31–60). Maturity labels and validation status are tracked separately in `docs/maturity-matrix.md`. Melee combat,
175
175
  grappling, stamina and exhaustion, weapon dynamics (including swing momentum carry), ranged
176
176
  and projectile combat (including aiming time, moving target penalty, suppression→AI behaviour,
177
177
  and ammo type overrides), injury, entity environmental hazards, movement physics, formation
@@ -655,7 +655,7 @@ an entity, each operating on a different time scale and requiring different inte
655
655
 
656
656
  ## Quick start
657
657
 
658
- ```typescript
658
+ ```typescript no-check-example
659
659
  import { stepWorld, TICK_HZ } from "./src/sim/kernel.js";
660
660
  import { STARTER_WEAPONS } from "./src/equipment.js";
661
661
  import { HUMAN_BASE } from "./src/archetypes.js";
@@ -1028,7 +1028,7 @@ Effects activate when concentration exceeds `effectThreshold`:
1028
1028
 
1029
1029
  `TechContext` gates which items are usable in a scenario without locking them to a specific era.
1030
1030
 
1031
- ```typescript
1031
+ ```typescript no-check-example
1032
1032
  import { TechEra, defaultTechContext, isCapabilityAvailable } from "./src/sim/tech.js";
1033
1033
  import { validateLoadout, STARTER_EXOSKELETONS } from "./src/equipment.js";
1034
1034
 
@@ -1083,7 +1083,7 @@ Attached to `entity.capabilitySources?: CapabilitySource[]`. Each source is an e
1083
1083
 
1084
1084
  ### ActivateCommand
1085
1085
 
1086
- ```typescript
1086
+ ```typescript no-check-example
1087
1087
  { kind: "activate", sourceId: string, effectId: string, targetId?: number, targetPos?: Vec3 }
1088
1088
  ```
1089
1089
 
@@ -1130,7 +1130,7 @@ Attached to `entity.capabilitySources?: CapabilitySource[]`. Each source is an e
1130
1130
  `src/model3d.ts` provides pure data-extraction functions for driving 3D character rigs from
1131
1131
  simulation state. No kernel changes, no state mutations. Call once per tick after `stepWorld`.
1132
1132
 
1133
- ```typescript
1133
+ ```typescript no-check-example
1134
1134
  import { extractRigSnapshots } from "./src/model3d.js";
1135
1135
 
1136
1136
  const snapshots = extractRigSnapshots(world);
@@ -1233,7 +1233,7 @@ Each entity carries an optional `skills?: SkillMap` (`Map<SkillId, SkillLevel>`)
1233
1233
  When a skill is absent, `getSkill()` returns neutral defaults (no effect on simulation output),
1234
1234
  making all existing entities fully backward-compatible.
1235
1235
 
1236
- ```typescript
1236
+ ```typescript no-check-example
1237
1237
  import { buildSkillMap } from "./src/sim/skills.js";
1238
1238
 
1239
1239
  entity.skills = buildSkillMap({
@@ -1263,7 +1263,7 @@ entity.skills = buildSkillMap({
1263
1263
  `combineSkillLevels(a, b)` multiplies Q fields and adds time offsets, letting the host express
1264
1264
  synergy bonuses or composite experience modifiers before building the SkillMap:
1265
1265
 
1266
- ```typescript
1266
+ ```typescript no-check-example
1267
1267
  import { combineSkillLevels, defaultSkillLevel } from "./src/sim/skills.js";
1268
1268
 
1269
1269
  // Melee expert with an athleticism timing synergy (−0.25 s total)
@@ -1284,7 +1284,7 @@ Every simulation is reproducible from initial state + command log. `ReplayRecord
1284
1284
  the world before the first tick and records command maps per tick. `replayTo` reconstructs
1285
1285
  any past tick by restoring the snapshot and re-applying frames.
1286
1286
 
1287
- ```typescript
1287
+ ```typescript no-check-example
1288
1288
  import { ReplayRecorder, replayTo, serializeReplay, deserializeReplay } from "./src/replay.js";
1289
1289
 
1290
1290
  const recorder = new ReplayRecorder(world);
@@ -1310,7 +1310,7 @@ const worldAt50Again = replayTo(restored, 50, ctx);
1310
1310
  `CollectingTrace` implements `TraceSink` and accumulates all trace events for offline
1311
1311
  analysis. Pass it to `stepWorld` via `ctx.trace`, then extract metrics.
1312
1312
 
1313
- ```typescript
1313
+ ```typescript no-check-example
1314
1314
  import { CollectingTrace, collectMetrics, survivalRate, meanTimeToIncapacitation }
1315
1315
  from "./src/metrics.js";
1316
1316
 
@@ -1332,7 +1332,7 @@ pass over any flat `TraceEvent[]` — ordering and tick mixing are fine.
1332
1332
  `extractMotionVectors`, `extractHitTraces`, and `extractConditionSamples` in `src/debug.ts`
1333
1333
  transform world state and trace events into renderer-friendly snapshots:
1334
1334
 
1335
- ```typescript
1335
+ ```typescript no-check-example
1336
1336
  import { extractMotionVectors, extractHitTraces, extractConditionSamples } from "./src/debug.js";
1337
1337
  import { CollectingTrace } from "./src/metrics.js";
1338
1338
 
@@ -1360,7 +1360,7 @@ const pastHeatmap = extractConditionSamples(past);
1360
1360
  `src/describe.ts` translates raw SI fixed-point attributes into human-readable summaries.
1361
1361
  No simulation dependencies — safe to import from any host application.
1362
1362
 
1363
- ```typescript
1363
+ ```typescript no-check-example
1364
1364
  import { describeCharacter, formatCharacterSheet, formatOneLine } from "./src/describe.js";
1365
1365
  import { generateIndividual } from "./src/generate.js";
1366
1366
  import { PRO_BOXER } from "./src/archetypes.js";
@@ -1403,7 +1403,7 @@ Reaction time and decision latency use an **inverted** scale (lower value = high
1403
1403
 
1404
1404
  ### API
1405
1405
 
1406
- ```typescript
1406
+ ```typescript no-check-example
1407
1407
  describeCharacter(attrs: IndividualAttributes): CharacterDescription
1408
1408
  // Returns a structured object with tier, label, comparison string, and formatted value
1409
1409
  // for every attribute. Vision and hearing are formatted strings (e.g. "200 m, 120° arc").
@@ -1422,7 +1422,7 @@ formatOneLine(desc: CharacterDescription): string
1422
1422
  `src/narrative.ts` converts raw `TraceEvent` streams into human-readable text. Like
1423
1423
  `src/describe.ts`, it has no simulation dependencies — safe to import from UI code or CLI tools.
1424
1424
 
1425
- ```typescript
1425
+ ```typescript no-check-example
1426
1426
  import { narrateEvent, buildCombatLog, describeInjuries, describeCombatOutcome }
1427
1427
  from "./src/narrative.js";
1428
1428
  import { CollectingTrace } from "./src/metrics.js";
@@ -1501,7 +1501,7 @@ Set an entity's name to `"you"` in `nameMap` for second-person verb conjugation
1501
1501
  It runs a compressed 1 Hz loop applying the same healing physics as the kernel, suitable
1502
1502
  for computing wound outcomes, resource consumption, and recovery timelines between sessions.
1503
1503
 
1504
- ```typescript
1504
+ ```typescript no-check-example
1505
1505
  import { stepDowntime, MEDICAL_RESOURCES } from "./src/downtime.js";
1506
1506
 
1507
1507
  const reports = stepDowntime(world, 3600, {
@@ -1532,7 +1532,7 @@ for (const r of reports) {
1532
1532
 
1533
1533
  `src/arena.ts` provides a declarative scenario DSL for batch-running combat trials with statistical expectations. Use it to validate simulation realism, balance archetypes, and author calibration tests.
1534
1534
 
1535
- ```typescript
1535
+ ```typescript no-check-example
1536
1536
  import { runArena, expectWinRate, expectSurvivalRate, formatArenaReport }
1537
1537
  from "./src/arena.js";
1538
1538
  import { mkKnight, mkBoxer } from "./src/presets.js";
@@ -1567,7 +1567,7 @@ console.log(formatArenaReport(result));
1567
1567
 
1568
1568
  `src/progression.ts` adds the temporal axis: how entities improve through training and experience, decline through ageing, and carry permanent marks from injury. No simulation dependencies — safe to use in save-game serialisation and UI layers.
1569
1569
 
1570
- ```typescript
1570
+ ```typescript no-check-example
1571
1571
  import {
1572
1572
  createProgressionState, awardXP, advanceSkill,
1573
1573
  applyTrainingSession, stepAgeing, applyAgeingDelta,
@@ -1617,7 +1617,7 @@ const json = serialiseProgression(prog); // Map-aware JSON
1617
1617
  entity state, location, and item stockpiles between encounters, and delegates wound recovery
1618
1618
  to `stepDowntime`.
1619
1619
 
1620
- ```typescript
1620
+ ```typescript no-check-example
1621
1621
  import {
1622
1622
  createCampaign, addLocation, travel,
1623
1623
  creditInventory, debitInventory, getInventoryCount,
@@ -1683,7 +1683,7 @@ entityInventories, entity skills, armourState, and location travelCost all survi
1683
1683
  strength comes from `peakForce_N`, persuasion from cognitive depth, deception is beaten by
1684
1684
  sharp minds. Fully deterministic when given a seed.
1685
1685
 
1686
- ```typescript
1686
+ ```typescript no-check-example
1687
1687
  import {
1688
1688
  resolveDialogue, applyDialogueOutcome, narrateDialogue, dialogueProbability,
1689
1689
  type DialogueContext,
@@ -1741,7 +1741,7 @@ without rolling RNG. Useful for UI previews, AI decision-making, and testing.
1741
1741
  behaviour based on inter-faction relationships. Fully deterministic — no RNG, standing
1742
1742
  changes are pure arithmetic.
1743
1743
 
1744
- ```typescript
1744
+ ```typescript no-check-example
1745
1745
  import {
1746
1746
  createFactionState, adjustStanding, getStanding,
1747
1747
  extractWitnessEvents, applyReputationDelta,
@@ -1764,7 +1764,7 @@ mode; the `factionGuard` preset additionally suppresses attack below standing `q
1764
1764
  `src/economy.ts` provides item valuation, equipment wear, loot drop resolution, and
1765
1765
  trade evaluation. No kernel dependency — pure data management.
1766
1766
 
1767
- ```typescript
1767
+ ```typescript no-check-example
1768
1768
  import {
1769
1769
  computeItemValue, armourConditionQ, applyWear,
1770
1770
  resolveDrops, evaluateTradeOffer, totalInventoryValue,
@@ -1789,7 +1789,7 @@ impact now imparts a velocity delta to the target. Calibrated to real physics
1789
1789
  5.56 mm rifle round produces negligible knockback (≈ 0.05 m/s on 75 kg), while a
1790
1790
  large-creature kick can knock humans prone.
1791
1791
 
1792
- ```typescript
1792
+ ```typescript no-check-example
1793
1793
  import {
1794
1794
  computeKnockback, applyKnockback,
1795
1795
  STAGGER_THRESHOLD_mps, PRONE_THRESHOLD_mps, STAGGER_TICKS,
@@ -1823,7 +1823,7 @@ projectiles. Above 600 m/s a temporary stretch wave radiates outward through
1823
1823
  inelastic tissue; above 900 m/s momentary vacuum cavitation further boosts
1824
1824
  haemorrhage in fluid-saturated organs.
1825
1825
 
1826
- ```typescript
1826
+ ```typescript no-check-example
1827
1827
  import {
1828
1828
  computeTemporaryCavityMul, computeCavitationBleed,
1829
1829
  HYDROSTATIC_THRESHOLD_mps, CAVITATION_THRESHOLD_mps,
@@ -1857,7 +1857,7 @@ automatically in the finalImpacts loop — no changes to call sites required.
1857
1857
  `src/sim/cone.ts` adds directional cone geometry to the capability system, enabling
1858
1858
  breath weapons, flamethrowers, gas dispensers, and sonic disorientation blasts.
1859
1859
 
1860
- ```typescript
1860
+ ```typescript no-check-example
1861
1861
  import { entityInCone, buildEntityFacingCone } from "./src/sim/cone.js";
1862
1862
  import type { CapabilityEffect, CapabilitySource } from "./src/sim/capability.js";
1863
1863
  import { q, SCALE } from "./src/units.js";
@@ -1908,7 +1908,7 @@ surface-heavy/internal-pass-through split or acid's structural bias.
1908
1908
  system. Unlike abstract "cold resistance" stats, temperature is tracked in real °C (encoded
1909
1909
  as Q) and driven by genuine thermophysics.
1910
1910
 
1911
- ```typescript
1911
+ ```typescript no-check-example
1912
1912
  import { stepCoreTemp, deriveTempModifiers, cToQ, CORE_TEMP_NORMAL_Q } from "./src/sim/thermoregulation.js";
1913
1913
  import type { KernelContext } from "./src/sim/context.js";
1914
1914
 
@@ -1954,7 +1954,7 @@ final state.
1954
1954
  weeks. Hunger states impose escalating combat penalties and eventually cause mass loss —
1955
1955
  fat catabolism first, then muscle tissue.
1956
1956
 
1957
- ```typescript
1957
+ ```typescript no-check-example
1958
1958
  import {
1959
1959
  computeBMR, stepNutrition, consumeFood, deriveHungerModifiers,
1960
1960
  FOOD_ITEMS, type HungerState,
@@ -2213,4 +2213,4 @@ ROADMAP items PH-1 through PH-8 are complete as of 2026-03-19:
2213
2213
  | PH-7 | Benchmark operational guide — tick-rate and entity-cap recommendations | **Complete** |
2214
2214
  | PH-8 | Emergent validation as flagship trust artifact — versioned, CI-enforced | **Complete** |
2215
2215
 
2216
- See `ROADMAP.md` → `## Platform Hardening` for the full scope of each item.
2216
+ See `ROADMAP.md` → `## Platform Hardening` for the full scope of each item.
@@ -0,0 +1,47 @@
1
+ # Release Dashboard
2
+
3
+ > This file is generated by `npm run generate-release-dashboard`.
4
+ > Do not edit manually. Update `CHANGELOG.md` and `package.json`, then regenerate.
5
+
6
+ ## Source of truth
7
+
8
+ - `CHANGELOG.md` for release history and latest tagged release details.
9
+ - `package.json` for the published package version.
10
+
11
+ ## Consistency status
12
+
13
+ - Overall: **PASS**
14
+ - Latest changelog version: **0.5.0** (2026-04-23)
15
+ - Package version: **0.5.0**
16
+
17
+ ### Current inconsistencies
18
+
19
+ - None detected.
20
+
21
+ ## Latest releases (from CHANGELOG)
22
+
23
+ | Version | Date |
24
+ | --- | --- |
25
+ | 0.5.0 | 2026-04-23 |
26
+ | 0.4.1 | 2026-04-23 |
27
+ | 0.4.0 | 2026-04-22 |
28
+ | 0.3.0 | 2026-04-04 |
29
+ | 0.2.11 | 2026-04-04 |
30
+ | 0.2.10 | 2026-04-03 |
31
+ | 0.2.9 | 2026-04-02 |
32
+ | 0.2.8 | 2026-04-02 |
33
+ | 0.2.7 | 2026-04-02 |
34
+ | 0.2.6 | 2026-04-02 |
35
+
36
+ ## Automation design
37
+
38
+ - Generate this dashboard from source data using `tools/generate-release-dashboard.mjs`.
39
+ - Treat `CHANGELOG.md` and `package.json` as canonical inputs.
40
+ - Regenerate dashboard in release-prep flows and whenever either input changes.
41
+
42
+ ## CI stale-file rule
43
+
44
+ - CI runs `npm run check-release-dashboard`.
45
+ - The check re-renders dashboard content in-memory and compares it with committed `docs/release-dashboard.md`.
46
+ - If they differ, CI fails with a non-zero exit and asks contributors to run:
47
+ - `npm run generate-release-dashboard`