@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
package/docs/bridge-contract.md
CHANGED
|
@@ -1,332 +1,140 @@
|
|
|
1
|
-
# Ananke Bridge Contract
|
|
2
|
-
|
|
3
|
-
|
|
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
|
-
const
|
|
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
|
-
| `shockQ` | `Q` | `0`–`SCALE.Q` — direct pass-through of `entity.injury.shock` | Drive screen shake, stagger blend, vignette intensity |
|
|
142
|
-
| `fearQ` | `Q` | `0`–`SCALE.Q` — direct pass-through of `entity.condition.fearQ` | Drive breathing rate, idle fidget blend, visual effects |
|
|
143
|
-
|
|
144
|
-
### Boolean state flags
|
|
145
|
-
|
|
146
|
-
| Field | Type | True when | Usage |
|
|
147
|
-
|---------------|-----------|-----------|-------|
|
|
148
|
-
| `prone` | `boolean` | `intent.prone` is true, OR grapple position is `"prone"` or `"pinned"` | Switch to prone animation layer |
|
|
149
|
-
| `unconscious` | `boolean` | `!dead` AND `consciousness < 0.20` (2000/10 000) | Switch to unconscious pose; suppress all locomotion |
|
|
150
|
-
| `dead` | `boolean` | `entity.injury.dead === true` | Switch to death pose; freeze all animation |
|
|
151
|
-
|
|
152
|
-
**Priority:** `dead` overrides `unconscious`; `unconscious` overrides locomotion.
|
|
153
|
-
When `dead` is `true`, all locomotion weights are `0` and `unconscious` is `false`.
|
|
154
|
-
|
|
155
|
-
### Interpolation behaviour
|
|
156
|
-
|
|
157
|
-
When interpolated by `BridgeEngine`, locomotion weights and condition Q values are lerped
|
|
158
|
-
linearly. Boolean flags (`prone`, `unconscious`, `dead`) snap to the new value when the
|
|
159
|
-
interpolation factor `t ≥ SCALE.Q / 2` (the midpoint of the tick interval).
|
|
160
|
-
|
|
161
|
-
---
|
|
162
|
-
|
|
163
|
-
## 5. `GrapplePoseConstraint` Usage Contract
|
|
164
|
-
|
|
165
|
-
`GrapplePoseConstraint` is derived by `deriveGrappleConstraint(entity)` and embedded in every
|
|
166
|
-
`RigSnapshot`. Use it to drive IK constraints or bone locks in your renderer when two entities
|
|
167
|
-
are grappling.
|
|
168
|
-
|
|
169
|
-
### Fields
|
|
170
|
-
|
|
171
|
-
| Field | Type | Description |
|
|
172
|
-
|--------------------|-------------------|-------------|
|
|
173
|
-
| `isHolder` | `boolean` | `true` when this entity is actively holding another |
|
|
174
|
-
| `holdingEntityId` | `number?` | ID of the entity being held; **present only when `isHolder === true`** |
|
|
175
|
-
| `isHeld` | `boolean` | `true` when this entity is being held by one or more others |
|
|
176
|
-
| `heldByIds` | `number[]` | IDs of entities currently holding this entity; empty array when `isHeld === false` |
|
|
177
|
-
| `position` | `GrapplePosition` | Current positional state: `"standing"` \| `"prone"` \| `"pinned"` \| `"mounted"` |
|
|
178
|
-
| `gripQ` | `Q` | Grip strength `[0, SCALE.Q]`; `0` when not grappling |
|
|
179
|
-
|
|
180
|
-
### Usage patterns
|
|
181
|
-
|
|
182
|
-
**Non-grappling entity (default state):**
|
|
183
|
-
```
|
|
184
|
-
isHolder: false
|
|
185
|
-
isHeld: false
|
|
186
|
-
heldByIds: []
|
|
187
|
-
position: "standing"
|
|
188
|
-
gripQ: 0
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
**Holder entity:**
|
|
192
|
-
```
|
|
193
|
-
isHolder: true
|
|
194
|
-
holdingEntityId: <target entity ID>
|
|
195
|
-
isHeld: false (unless simultaneously held by someone else)
|
|
196
|
-
position: "standing" | "mounted" | etc.
|
|
197
|
-
gripQ: > 0
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
**Held entity:**
|
|
201
|
-
```
|
|
202
|
-
isHolder: false (unless simultaneously holding someone else)
|
|
203
|
-
isHeld: true
|
|
204
|
-
heldByIds: [<holder entity ID>, ...]
|
|
205
|
-
position: "prone" | "pinned" | "standing" | etc.
|
|
206
|
-
gripQ: 0
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
### Renderer usage
|
|
210
|
-
|
|
211
|
-
1. For each render frame, call `deriveGrappleConstraint` (or read it from `RigSnapshot.grapple`).
|
|
212
|
-
2. If `isHolder === true` and `isHeld === false`: the holder drives the constraint; lock the
|
|
213
|
-
held entity's root to the holder's grip anchor point.
|
|
214
|
-
3. If `isHeld === true`: this entity's root is constrained; disable its root transform update
|
|
215
|
-
and apply the holder's transform instead.
|
|
216
|
-
4. `position` drives the animation layer: `"prone"` or `"pinned"` → floor-level pose.
|
|
217
|
-
5. `gripQ` can drive a blend towards a "full grip" animation pose for the holder.
|
|
218
|
-
|
|
219
|
-
**Important:** `holdingEntityId` is an optional property and is absent (not `undefined`)
|
|
220
|
-
when `isHolder === false` — do not read it without checking `isHolder` first.
|
|
221
|
-
|
|
222
|
-
**Interpolation behaviour:** Grapple constraints snap at `t ≥ SCALE.Q / 2` (no smooth
|
|
223
|
-
transition between grapple states).
|
|
224
|
-
|
|
225
|
-
---
|
|
226
|
-
|
|
227
|
-
## 6. `InterpolatedState` Shape
|
|
228
|
-
|
|
229
|
-
`BridgeEngine.getInterpolatedState(id, t)` returns `InterpolatedState | null`.
|
|
230
|
-
|
|
231
|
-
| Field | Type | Description |
|
|
232
|
-
|---------------------|-----------------|-------------|
|
|
233
|
-
| `entityId` | `number` | Entity ID |
|
|
234
|
-
| `tick` | `number` | Most recent simulation tick |
|
|
235
|
-
| `interpolationFactor` | `number` | The computed `t` value `[0, SCALE.Q]` |
|
|
236
|
-
| `position_m` | `{ x, y, z }` | World-space position in **real metres** (already divided by `SCALE.m`) |
|
|
237
|
-
| `velocity_mps` | `{ x, y, z }` | Velocity in metres per second |
|
|
238
|
-
| `facing` | `{ x, y, z }` | Unit facing vector (normalised) |
|
|
239
|
-
| `animation` | `AnimationHints` | Interpolated animation hints (see §4) |
|
|
240
|
-
| `poseModifiers` | `PoseModifier[]` | Per-segment injury deformation weights (one per mapped segment) |
|
|
241
|
-
| `grapple` | `GrapplePoseConstraint` | Grapple state (snaps at midpoint; see §5) |
|
|
242
|
-
| `condition` | `{ shockQ, fearQ, consciousnessQ, fluidLossQ }` | Interpolated condition scalars |
|
|
243
|
-
|
|
244
|
-
---
|
|
245
|
-
|
|
246
|
-
## 7. Scale Conventions
|
|
247
|
-
|
|
248
|
-
All lengths in the simulation are stored as **fixed-point integers** with `SCALE.m = 10 000`
|
|
249
|
-
(10 000 units = 1 metre). `InterpolatedState.position_m` has already been converted to real
|
|
250
|
-
metres by the bridge.
|
|
251
|
-
|
|
252
|
-
| What you receive | Unit | Conversion if needed |
|
|
253
|
-
|-----------------|------|----------------------|
|
|
254
|
-
| `position_m` from `InterpolatedState` | Real metres (float) | Already converted |
|
|
255
|
-
| `position_m` from raw `Entity` | `SCALE.m` units (integer) | Divide by `SCALE.m` |
|
|
256
|
-
| Q values (`shockQ`, `fearQ`, etc.) | `[0, SCALE.Q]` integer | Divide by `SCALE.Q` for `[0, 1]` float |
|
|
257
|
-
|
|
258
|
-
Always import and use `SCALE.m` / `SCALE.Q` rather than hardcoding `10000`:
|
|
259
|
-
```typescript
|
|
260
|
-
import { SCALE } from "ananke";
|
|
261
|
-
const shockFloat = hints.shockQ / SCALE.Q; // → [0, 1]
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
---
|
|
265
|
-
|
|
266
|
-
## 8. Quickstart Example
|
|
267
|
-
|
|
268
|
-
```typescript
|
|
269
|
-
import { mkWorld, mkKnight, stepWorld, q,
|
|
270
|
-
extractRigSnapshots, BridgeEngine } from "ananke";
|
|
271
|
-
|
|
272
|
-
// --- Setup ---
|
|
273
|
-
const world = mkWorld(42, [mkKnight(1, 1, 0, 0), mkKnight(2, 2, 10000, 0)]);
|
|
274
|
-
const engine = new BridgeEngine({ mappings: [], defaultBoneName: "root" });
|
|
275
|
-
const ctx = { tractionCoeff: q(0.80) };
|
|
276
|
-
|
|
277
|
-
engine.setEntityBodyPlan(1, "humanoid");
|
|
278
|
-
engine.setEntityBodyPlan(2, "humanoid");
|
|
279
|
-
|
|
280
|
-
// --- Simulation loop (20 Hz) ---
|
|
281
|
-
function simTick(): void {
|
|
282
|
-
const snapshots = extractRigSnapshots(world);
|
|
283
|
-
stepWorld(world, new Map(), ctx);
|
|
284
|
-
engine.update(snapshots);
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
// --- Render loop (60 Hz) ---
|
|
288
|
-
function renderFrame(renderTime_s: number): void {
|
|
289
|
-
const state = engine.getInterpolatedState(1, renderTime_s);
|
|
290
|
-
if (!state) return; // no snapshots yet
|
|
291
|
-
|
|
292
|
-
// state.position_m is already in metres
|
|
293
|
-
myRenderer.setPosition(state.position_m.x, state.position_m.y);
|
|
294
|
-
|
|
295
|
-
// Drive animations from AnimationHints
|
|
296
|
-
myAnimator.setIdleWeight(state.animation.idle / SCALE.Q);
|
|
297
|
-
myAnimator.setWalkWeight(state.animation.walk / SCALE.Q);
|
|
298
|
-
myAnimator.setRunWeight (state.animation.run / SCALE.Q);
|
|
299
|
-
myAnimator.setDead (state.animation.dead);
|
|
300
|
-
myAnimator.setProne (state.animation.prone);
|
|
301
|
-
|
|
302
|
-
// Drive per-region deformation
|
|
303
|
-
for (const mod of state.poseModifiers) {
|
|
304
|
-
myRenderer.setInjuryBlend(mod.boneName, mod.impairmentQ / SCALE.Q);
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
---
|
|
310
|
-
|
|
311
|
-
## 9. Stability Promise
|
|
312
|
-
|
|
313
|
-
All types and functions listed in this document are **Tier 1 (Stable)**. See
|
|
314
|
-
[`STABLE_API.md`](../STABLE_API.md) for the full tier table and breaking-change policy.
|
|
315
|
-
|
|
316
|
-
| Export | Source module |
|
|
317
|
-
|--------|---------------|
|
|
318
|
-
| `extractRigSnapshots` | `src/model3d.ts` |
|
|
319
|
-
| `deriveAnimationHints` | `src/model3d.ts` |
|
|
320
|
-
| `derivePoseModifiers` | `src/model3d.ts` |
|
|
321
|
-
| `deriveGrappleConstraint` | `src/model3d.ts` |
|
|
322
|
-
| `deriveMassDistribution` | `src/model3d.ts` |
|
|
323
|
-
| `deriveInertiaTensor` | `src/model3d.ts` |
|
|
324
|
-
| `BridgeEngine` | `src/bridge/bridge-engine.ts` |
|
|
325
|
-
| `BridgeConfig`, `BodyPlanMapping`, `SegmentMapping` | `src/bridge/types.ts` |
|
|
326
|
-
| `InterpolatedState` | `src/bridge/types.ts` |
|
|
327
|
-
| `AnimationHints` | `src/model3d.ts` |
|
|
328
|
-
| `GrapplePoseConstraint` | `src/model3d.ts` |
|
|
329
|
-
| `PoseModifier` | `src/model3d.ts` |
|
|
330
|
-
| `RigSnapshot` | `src/model3d.ts` |
|
|
331
|
-
|
|
332
|
-
*Generated by Claude Code during Platform Hardening PH-5, March 2026.*
|
|
1
|
+
# Ananke Bridge Contract
|
|
2
|
+
|
|
3
|
+
> **Source-of-truth for renderer bridge imports and stability.**
|
|
4
|
+
> Package name: `@its-not-rocket-science/ananke`.
|
|
5
|
+
|
|
6
|
+
For versioning policy see [`docs/versioning.md`](versioning.md) and [`STABLE_API.md`](../STABLE_API.md).
|
|
7
|
+
|
|
8
|
+
Maintainer support boundary details are in [`docs/support-boundaries.md`](support-boundaries.md).
|
|
9
|
+
|
|
10
|
+
<!-- CONTRACT:STABILITY_LABELS:start -->
|
|
11
|
+
```json
|
|
12
|
+
[
|
|
13
|
+
{ "kind": "subpath", "subject": ".", "status": "Tier 1 stable", "notes": "Root host API and stable bridge extraction helpers" },
|
|
14
|
+
{ "kind": "subpath", "subject": "./tier2", "status": "Experimental", "notes": "Bridge runtime and mapping APIs" }
|
|
15
|
+
]
|
|
16
|
+
```
|
|
17
|
+
<!-- CONTRACT:STABILITY_LABELS:end -->
|
|
18
|
+
|
|
19
|
+
## 1) Import-path and stability truth table
|
|
20
|
+
|
|
21
|
+
| Symbol | Import path | Stability |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| `createWorld`, `stepWorld`, `q`, `SCALE` | `@its-not-rocket-science/ananke` | Tier 1 stable |
|
|
24
|
+
| `extractRigSnapshots`, `deriveAnimationHints` | `@its-not-rocket-science/ananke` | Tier 1 stable |
|
|
25
|
+
| `RigSnapshot`, `AnimationHints` | `@its-not-rocket-science/ananke` | Tier 1 stable |
|
|
26
|
+
| `BridgeEngine` | `@its-not-rocket-science/ananke/tier2` | Experimental |
|
|
27
|
+
| `BridgeConfig`, `BodyPlanMapping`, `SegmentMapping`, `InterpolatedState`, `MappedPoseModifier` | `@its-not-rocket-science/ananke/tier2` | Experimental |
|
|
28
|
+
| `validateMappingCoverage` | `@its-not-rocket-science/ananke/tier2` | Experimental |
|
|
29
|
+
| `derivePoseModifiers`, `deriveGrappleConstraint`, `deriveMassDistribution`, `deriveInertiaTensor` | `@its-not-rocket-science/ananke/tier2` | Experimental |
|
|
30
|
+
| `PoseModifier`, `GrapplePoseConstraint` | `@its-not-rocket-science/ananke/tier2` | Experimental |
|
|
31
|
+
| `mkWorld`, `mkKnight` | _No package export path_ | Internal/test-only |
|
|
32
|
+
|
|
33
|
+
`BridgeEngine` is **not Tier-1 root**. Use `@its-not-rocket-science/ananke/tier2` and treat it as experimental.
|
|
34
|
+
|
|
35
|
+
If bridge correctness is production-critical, pin exact patch versions and re-run interpolation/mapping regression tests on every upgrade.
|
|
36
|
+
|
|
37
|
+
## 2) Minimum bridge integration (Tier 1 stable)
|
|
38
|
+
|
|
39
|
+
This is the lowest-friction, stable path: run simulation, extract rig snapshots, and derive animation hints.
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import {
|
|
43
|
+
createWorld,
|
|
44
|
+
stepWorld,
|
|
45
|
+
extractRigSnapshots,
|
|
46
|
+
deriveAnimationHints,
|
|
47
|
+
q,
|
|
48
|
+
SCALE,
|
|
49
|
+
} from "@its-not-rocket-science/ananke";
|
|
50
|
+
|
|
51
|
+
const world = createWorld(42, [
|
|
52
|
+
{ id: 1, teamId: 1, seed: 101, archetype: "KNIGHT_INFANTRY", weaponId: "wpn_longsword" },
|
|
53
|
+
{ id: 2, teamId: 2, seed: 202, archetype: "KNIGHT_INFANTRY", weaponId: "wpn_longsword", x_m: 1.0 },
|
|
54
|
+
]);
|
|
55
|
+
|
|
56
|
+
stepWorld(world, new Map(), { tractionCoeff: q(0.8) });
|
|
57
|
+
|
|
58
|
+
const snapshots = extractRigSnapshots(world);
|
|
59
|
+
const hints = deriveAnimationHints(world.entities[0]!);
|
|
60
|
+
|
|
61
|
+
console.log({
|
|
62
|
+
snapshotCount: snapshots.length,
|
|
63
|
+
idle01: hints.idle / SCALE.Q,
|
|
64
|
+
});
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## 3) Advanced bridge runtime (Experimental tier2)
|
|
68
|
+
|
|
69
|
+
Use `BridgeEngine` when you need interpolation/extrapolation between simulation ticks.
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
import { createWorld, stepWorld, extractRigSnapshots, q, SCALE } from "@its-not-rocket-science/ananke";
|
|
73
|
+
import {
|
|
74
|
+
BridgeEngine,
|
|
75
|
+
type BridgeConfig,
|
|
76
|
+
type BodyPlanMapping,
|
|
77
|
+
validateMappingCoverage,
|
|
78
|
+
} from "@its-not-rocket-science/ananke/tier2";
|
|
79
|
+
|
|
80
|
+
const humanoidMapping: BodyPlanMapping = {
|
|
81
|
+
bodyPlanId: "humanoid",
|
|
82
|
+
segments: [{ segmentId: "head", boneName: "Head" }],
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const missing = validateMappingCoverage(humanoidMapping, ["head", "torso"]);
|
|
86
|
+
console.log("missingSegments", missing);
|
|
87
|
+
|
|
88
|
+
const config: BridgeConfig = {
|
|
89
|
+
mappings: [humanoidMapping],
|
|
90
|
+
defaultBoneName: "root",
|
|
91
|
+
extrapolationAllowed: false,
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const world = createWorld(7, [
|
|
95
|
+
{ id: 1, teamId: 1, seed: 11, archetype: "KNIGHT_INFANTRY", weaponId: "wpn_longsword" },
|
|
96
|
+
]);
|
|
97
|
+
|
|
98
|
+
const engine = new BridgeEngine(config);
|
|
99
|
+
engine.setEntityBodyPlan(1, "humanoid");
|
|
100
|
+
|
|
101
|
+
stepWorld(world, new Map(), { tractionCoeff: q(0.8) });
|
|
102
|
+
engine.update(extractRigSnapshots(world));
|
|
103
|
+
|
|
104
|
+
stepWorld(world, new Map(), { tractionCoeff: q(0.8) });
|
|
105
|
+
engine.update(extractRigSnapshots(world));
|
|
106
|
+
|
|
107
|
+
const renderTime_s = engine.getLatestSimTime() - 1 / 40;
|
|
108
|
+
const state = engine.getInterpolatedState(1, renderTime_s);
|
|
109
|
+
|
|
110
|
+
if (state) {
|
|
111
|
+
console.log({
|
|
112
|
+
x_m: state.position_m.x / SCALE.m,
|
|
113
|
+
idle01: state.animation.idle / SCALE.Q,
|
|
114
|
+
fromTick: state.fromTick,
|
|
115
|
+
toTick: state.toTick,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### BridgeEngine behavior contract (Experimental)
|
|
121
|
+
|
|
122
|
+
- `update(snapshots, motion?, condition?)` shifts per-entity `curr` to `prev`, ingests new `curr`, and advances tick/time state.
|
|
123
|
+
- `getInterpolatedState(entityId, renderTime_s)` returns `null` if the entity has no snapshots.
|
|
124
|
+
- With only one snapshot for an entity, returned state is held (no interpolation).
|
|
125
|
+
- If `renderTime_s <= prevTime_s`, previous snapshot is held.
|
|
126
|
+
- If `renderTime_s >= currTime_s`:
|
|
127
|
+
- `extrapolationAllowed: false` => current snapshot is held.
|
|
128
|
+
- `extrapolationAllowed: true` => position extrapolates from current velocity.
|
|
129
|
+
- Numeric tracks interpolate in fixed-point Q-space.
|
|
130
|
+
- `animation.prone|unconscious|dead`, `condition.dead`, and `grapple` snap at midpoint (`t < SCALE.Q / 2` uses previous, otherwise current).
|
|
131
|
+
|
|
132
|
+
## 4) Compile-tested reference example
|
|
133
|
+
|
|
134
|
+
- `examples/bridge-minimal.ts` is a compile-tested bridge example that uses only package export paths.
|
|
135
|
+
- Run it after build:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
npm run build
|
|
139
|
+
node dist/examples/bridge-minimal.js
|
|
140
|
+
```
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Completion Evidence Dashboard (Artifact Status)
|
|
2
|
+
|
|
3
|
+
_Date: 2026-04-02_
|
|
4
|
+
|
|
5
|
+
This dashboard maps each maturity claim to explicit, machine-checkable evidence requirements.
|
|
6
|
+
|
|
7
|
+
## Evidence mapping table (status → proof)
|
|
8
|
+
|
|
9
|
+
| Maturity dimension | Status | Measurable criteria | Objective proof currently present |
|
|
10
|
+
|---|---|---|---|
|
|
11
|
+
| Deterministic combat kernel | verified | `>=3` deterministic/kernel tests, phase-order invariant test, `>=2` conformance fixtures, validation dashboard artifact. | `test/kernel_determinism.test.ts`, `test/kernel_phase_order.test.ts`, `test/determinism.test.ts`, `test/invariants.test.ts`, `conformance/lockstep-sequence.json`, `conformance/phase-order.json`, `docs/dashboard/validation-dashboard.json`. |
|
|
12
|
+
| Injury, medical, survivability | verified | `>=3` survivability tests, at least one published medical validation artifact. | `test/medical.test.ts`, `test/injury_totals.test.ts`, `test/wound-aging.test.ts`, `docs/validation-first-aid-saves-lives-2026-03-18T19-34-10.md`. |
|
|
13
|
+
| Environment, hazards, climate | verified | `>=3` hazard/climate/thermoregulation tests, at least one thermoregulation validation artifact. | `test/hazards.test.ts`, `test/climate.test.ts`, `test/thermoregulation.test.ts`, `docs/validation-thermoregulation-core-stability-2026-03-18T00-07-52.md`. |
|
|
14
|
+
| AI, perception, cognition | partially verified | `>=3` subsystem tests plus behaviour invariant coverage (no M4 validation artifact required yet). | `test/ai_system.test.ts`, `test/perception_phase4.test.ts`, `test/cognition.test.ts`, `test/behavior-trees.test.ts`. |
|
|
15
|
+
| Campaign/world simulation | partially verified | `>=3` campaign/world tests and at least one deterministic snapshot/fixture artifact. | `test/campaign.test.ts`, `test/world-generation.test.ts`, `test/scenarios.test.ts`, `test/snapshots/kernel_behaviour_snapshot.json`. |
|
|
16
|
+
| Bridge/replay/integration surfaces | verified | `>=3` bridge/replay/netcode tests, `>=2` replay/bridge conformance fixtures, bridge contract artifact. | `test/bridge/integration.test.ts`, `test/replay.test.ts`, `test/netcode.test.ts`, `conformance/replay-parity.json`, `conformance/bridge-snapshot.json`, `docs/bridge-contract.md`. |
|
|
17
|
+
| Tooling/benchmarks/release checks | verified | Performance regression test, release artifact(s), and coverage signal in CI. | `test/performance.test.ts`, `docs/release-dashboard.md`, `npm run test:coverage`. |
|
|
18
|
+
|
|
19
|
+
## Gap list (statuses that still exceed evidence quality)
|
|
20
|
+
|
|
21
|
+
1. **Coverage thresholds are still implicit**: we require `npm run test:coverage` to run, but no per-dimension minimum line/branch threshold is encoded yet.
|
|
22
|
+
2. **Freshness/SLA is not yet enforced**: evidence files exist, but we do not fail when validation/release artifacts become stale by date.
|
|
23
|
+
3. **Invariant depth is uneven**: only selected dimensions explicitly require invariant tests; some M4 areas still rely mostly on scenario tests.
|
|
24
|
+
4. **External reproducibility remains partial**: most evidence is in-repo and deterministic, but independent external rerun attestations are not required by CI.
|
|
25
|
+
|
|
26
|
+
## Missing tests to add next
|
|
27
|
+
|
|
28
|
+
1. Add explicit **AI decision determinism** test (fixed seed + identical action traces) to strengthen M3 AI evidence.
|
|
29
|
+
2. Add **campaign long-horizon regression** test (multi-turn economy/governance drift bound) for hardened campaign stability.
|
|
30
|
+
3. Add **bridge backward-compatibility matrix** test (current engine vs prior snapshot schema) to detect integration drift.
|
|
31
|
+
4. Add **release-check smoke fixture test** that validates release metadata/version freshness constraints.
|
|
32
|
+
|
|
33
|
+
## Missing validation artifacts to add next
|
|
34
|
+
|
|
35
|
+
1. Add a dedicated **AI/perception validation report** (`docs/validation-ai-perception-*.md`) so that AI can graduate from M3 to M4 on objective grounds.
|
|
36
|
+
2. Add a **campaign/world validation artifact** (scenario corpus or benchmark report) for M4 candidacy.
|
|
37
|
+
3. Add a machine-readable **artifact freshness ledger** (e.g., `docs/validation-artifact-index.json`) with `generatedAt`, producer tool, and scenario set hash.
|
|
38
|
+
|
|
39
|
+
## CI enforcement proposal
|
|
40
|
+
|
|
41
|
+
### Implemented gate
|
|
42
|
+
|
|
43
|
+
- New source of truth: `docs/maturity-evidence-map.json`.
|
|
44
|
+
- New CI script: `tools/check-maturity-evidence.mjs`.
|
|
45
|
+
- CI integration: `npm run check-maturity-evidence` is now part of `npm run ci`.
|
|
46
|
+
|
|
47
|
+
### Gate semantics (fail conditions)
|
|
48
|
+
|
|
49
|
+
The CI job fails when any of the following is true:
|
|
50
|
+
|
|
51
|
+
1. A subsystem in `docs/maturity-matrix.json` has no entry in `docs/maturity-evidence-map.json`.
|
|
52
|
+
2. A mapped subsystem claims a different maturity than `docs/maturity-matrix.json`.
|
|
53
|
+
3. Any required evidence path is missing (tests, fixtures, invariants, validation artifacts).
|
|
54
|
+
4. Any subsystem has zero `requiredTests` entries.
|
|
55
|
+
5. Any M3 subsystem has fewer than 3 required tests.
|
|
56
|
+
6. Any M4 subsystem lacks validation artifacts/conformance fixtures.
|
|
57
|
+
7. Any subsystem has fewer than 2 total evidence signals.
|
|
58
|
+
|
|
59
|
+
### Recommended next CI extensions (not yet implemented)
|
|
60
|
+
|
|
61
|
+
1. Enforce per-dimension coverage floors (`lines/branches/functions`) instead of run-only coverage.
|
|
62
|
+
2. Enforce artifact freshness windows (e.g., fail if release/validation artifact older than N days).
|
|
63
|
+
3. Enforce fixture ↔ test linkage (each required fixture must be referenced by at least one test).
|