@its-not-rocket-science/ananke 0.1.69 → 0.5.1
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 +254 -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
|
@@ -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`
|
package/docs/project-overview.md
CHANGED
|
@@ -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,
|
|
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:** `
|
|
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:** `
|
|
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
|
|
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`
|