@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.
Files changed (165) hide show
  1. package/CHANGELOG.md +254 -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
@@ -1,245 +1,256 @@
1
- # Ananke — Versioning Policy
2
-
3
- *Platform Hardening PH-2 — Versioning Policy Unification*
4
-
5
- ---
6
-
7
- ## Which version do I use?
8
-
9
- **Short answer: put the semver tag in your `package.json`.**
10
-
11
- ```json
12
- { "dependencies": { "ananke": "^0.1.0" } }
13
- ```
14
-
15
- If you need byte-for-byte replay determinism across patch releases, also record the
16
- exact commit hash in your project's `UPSTREAM.md`. See [commit-hash pinning](#commit-hash-pinning) below.
17
-
18
- ---
19
-
20
- ## Canonical versioning policy
21
-
22
- Ananke uses **semantic versioning (semver)** as the public contract:
23
-
24
- | Version change | Meaning |
25
- |---------------|---------|
26
- | Patch (`0.1.x`) | Bug fixes, documentation corrections, and internal refactors that do not change observable simulation output |
27
- | Minor (`0.x.0`) | Additive changes: new exports, new optional fields, new simulation phases. **Tier 1 (Stable) exports are not broken.** Tier 2 (Experimental) exports may change with a `CHANGELOG.md` entry |
28
- | Major (`x.0.0`) | Breaking changes to Tier 1 exports. A migration guide accompanies every major bump |
29
-
30
- > **Pre-1.0 note:** The project is currently at `0.1.0`. Tier 1 exports will not break
31
- > within the `0.x` line without a minor-version bump and a migration guide in `CHANGELOG.md`.
32
- > The `1.0` release will lock the Tier 1 surface under full semver guarantees.
33
-
34
- ---
35
-
36
- ## API stability tiers
37
-
38
- Every export in `src/index.ts` is tagged with a stability tier.
39
- The full tier table is in [`STABLE_API.md`](../STABLE_API.md).
40
-
41
- | Tier | Label | Guarantee |
42
- |------|-------|-----------|
43
- | 1 | **Stable** | No breaking changes without major version bump + migration guide |
44
- | 2 | **Experimental** | May change between minor versions; `CHANGELOG.md` entry required |
45
- | 3 | **Internal** | No stability guarantee; may change at any time |
46
-
47
- ---
48
-
49
- ## Commit-hash pinning (supplementary)
50
-
51
- Semver tags are the recommended pinning mechanism for most projects. For hosts that
52
- require absolute replay determinism across patch releases (e.g. tournament servers, archived
53
- experiment results), you may also pin to a specific commit hash.
54
-
55
- ### npm / package.json
56
-
57
- ```json
58
- {
59
- "dependencies": {
60
- "ananke": "github:its-not-rocket-science/ananke#<commit-sha>"
61
- }
62
- }
63
- ```
64
-
65
- Replace `<commit-sha>` with the full 40-character hash you have validated.
66
-
67
- ### Git submodule
68
-
69
- ```bash
70
- git submodule add https://github.com/its-not-rocket-science/ananke.git vendor/ananke
71
- cd vendor/ananke && git checkout <commit-sha>
72
- git add vendor/ananke && git commit -m "pin ananke to <commit-sha>"
73
- ```
74
-
75
- ### Why keep the option at all?
76
-
77
- Semver patch releases may adjust a tuning constant in ways that are technically
78
- non-breaking (same function signatures, same output format) but shift simulation
79
- balance. If you run long-lived archived replays that must be reproduced identically
80
- years later, commit-hash pinning is the stronger guarantee.
81
-
82
- ---
83
-
84
- ## What constitutes a breaking change
85
-
86
- ### Tier 1 Always breaking (requires major version bump)
87
-
88
- | Change | Example |
89
- |--------|---------|
90
- | Rename or remove a field on `Entity` | `entity.injury` → `entity.wounds` |
91
- | Rename or remove a field on `WorldState` | `world.entities` array shape change |
92
- | Change a field's unit or scale | `position_m` stored at a different `SCALE` |
93
- | Remove or rename a Tier 1 exported function | `stepWorld` signature change |
94
- | Change the interpretation of a constant | `SCALE.Q` value changed |
95
- | Change determinism same seed, different outcome | Any RNG, ordering, or arithmetic change |
96
-
97
- ### Tier 2Potentially breaking (noted in CHANGELOG.md, migration hint provided)
98
-
99
- | Change | Example |
100
- |--------|---------|
101
- | Add a required field to `Entity` | New mandatory `age?: AgeState` that existing entity helpers don't initialise |
102
- | Change a constant value that affects tuning | `SURF_J` adjusted |
103
- | Add an optional field that changes default behaviour when absent | New optional context field with a non-neutral default |
104
- | Change snapshot test output | Simulation output shifted for at least one seed |
105
-
106
- ### Tier 3Non-breaking (no migration required)
107
-
108
- - Adding new exported functions or types
109
- - Adding optional fields to interfaces (with `exactOptionalPropertyTypes`-safe defaults)
110
- - Adding new built-in archetypes, weapons, or body plans
111
- - Adding new `tools/` scripts or `docs/` files
112
- - Improving test coverage without changing logic
113
- - Fixing bugs where the previous behaviour was demonstrably wrong
114
-
115
- ---
116
-
117
- ## Changelog format
118
-
119
- Breaking and potentially breaking changes are recorded in `CHANGELOG.md`.
120
- Each entry follows:
121
-
122
- ```markdown
123
- ## <semver-tag> <YYYY-MM-DD>
124
-
125
- ### Breaking
126
- - `Entity.someField` renamed to `Entity.newField`.
127
- Migration: search `.someField` and replace with `.newField`.
128
-
129
- ### Potentially breaking
130
- - `SURF_J` constant changed from 120 to 110.
131
- Re-run `npm run validation` to check calibration impact.
132
-
133
- ### Added
134
- - `src/sim/widget.ts` Widget System (Phase N).
135
- ```
136
-
137
- ---
138
-
139
- ## Upgrade review cadence
140
-
141
- When upgrading your pinned semver tag or commit hash:
142
-
143
- 1. **Read the CHANGELOG** — check all entries since your previous version for Tier 1 / Tier 2 items
144
- 2. **Diff the source** — `git diff <old-tag>..<new-tag> -- src/` to see what changed
145
- 3. **Run your integration build** — `npm run build`
146
- 4. **Run the validation suite** — `npm run validation` to confirm calibration scenarios pass
147
- 5. **Run the full test suite** — `npm run test:coverage`
148
- 6. **Update your pin** — commit the new tag/hash to your dependency manifest
149
-
150
- A quarterly review cadence is a reasonable default for a production project. Determinism
151
- corrections warrant an out-of-cycle upgrade.
152
-
153
- ---
154
-
155
- ## Snapshot tests and determinism
156
-
157
- `test/snapshots/kernel_behaviour_snapshot.json` is a deterministic regression lock.
158
- If it changes in an upstream commit, that commit has shifted simulation output for at
159
- least one entity and seed combination. Treat snapshot changes as **Tier 2** by default;
160
- verify they are intentional before upgrading.
161
-
162
- To regenerate your snapshot baseline after a deliberate constant change:
163
-
164
- ```bash
165
- rm test/snapshots/kernel_behaviour_snapshot.json
166
- npm run test:coverage
167
- ```
168
-
169
- ---
170
-
171
- ## Internal fork guidance
172
-
173
- If you need to diverge from upstream (custom damage channels, proprietary AI, non-standard
174
- body plan hooks):
175
-
176
- 1. Fork at a pinned tag (or commit hash) — do not fork from an untagged tip
177
- 2. Namespace your extensions: prefix custom fields and modules with your project identifier
178
- (e.g. `entity.myproject_customField`) to avoid conflicts on upstream merges
179
- 3. Keep an `UPSTREAM.md` at your fork root noting your base version and a diff summary
180
- 4. Periodically rebase onto upstream Tier 3 commits to collect non-breaking improvements;
181
- treat Tier 1/2 commits as explicit migration tasks to schedule
182
-
183
- ---
184
-
185
- ## Deprecation lifecycle
186
-
187
- Symbols are deprecated rather than removed immediately so downstream projects have time
188
- to migrate. The lifecycle follows a three-phase pattern:
189
-
190
- ### 1 Mark deprecated (current version)
191
-
192
- Add a structured JSDoc tag to the symbol:
193
-
194
- ```typescript
195
- /**
196
- * @deprecated since 0.1.50 — use `newFunction` instead. Removes at 0.3.0.
197
- */
198
- export function oldFunction() { }
199
- ```
200
-
201
- The **required format** is:
202
-
203
- ```
204
- @deprecated since {version} — use {replacement} instead. Removes at {removeAfter}.
205
- ```
206
-
207
- | Field | Meaning |
208
- |-------|---------|
209
- | `since` | Version in which the deprecation was introduced |
210
- | `replacement` | Short description or code reference of what to use instead |
211
- | `removeAfter` | Version at which the symbol will be deleted — must be a future version |
212
-
213
- `removeAfter` must satisfy `> current` at publish time; `npm publish` runs
214
- `audit-deprecations --check` and fails if any symbol is overdue.
215
-
216
- ### 2 — Migration window
217
-
218
- During the migration window the symbol still works but emits a TypeScript deprecation
219
- warning in IDEs (the `@deprecated` tag triggers the strikethrough).
220
-
221
- The migration window is at least one **minor** version for Tier 2 symbols
222
- and at least one **major** version for Tier 1 (Stable) symbols.
223
-
224
- ### 3 Remove at removeAfter
225
-
226
- When the engine reaches `removeAfter`, the symbol is deleted and a CHANGELOG entry is
227
- added under a `### Removed` heading. The `since` version and the replacement are
228
- included in the removal note so the changelog is self-contained.
229
-
230
- ### Auditing
231
-
232
- ```bash
233
- npm run audit-deprecations # human-readable table
234
- npm run audit-deprecations -- --json # machine-readable JSON
235
- npm run audit-deprecations -- --check # exit 1 if any overdue
236
- ```
237
-
238
- The `--check` flag is run automatically by `npm run prepublishOnly`.
239
-
240
- ### Adding a new deprecation (checklist)
241
-
242
- - [ ] Add the structured `@deprecated` JSDoc tag with `since`, replacement, and `removeAfter`.
243
- - [ ] Run `npm run audit-deprecations` to confirm the tag is detected and not overdue.
244
- - [ ] Add a CHANGELOG entry under `### Deprecated`.
245
- - [ ] Surface the replacement in the relevant `docs/` file or `STABLE_API.md`.
1
+ # Ananke — Versioning Policy
2
+
3
+ *Platform Hardening PH-2 — Versioning Policy Unification*
4
+
5
+ ---
6
+
7
+ ## Which version do I use?
8
+
9
+ **Short answer: put the semver tag in your `package.json`.**
10
+
11
+ ```json
12
+ { "dependencies": { "ananke": "^<current-ananke-version>" } }
13
+ ```
14
+
15
+ If you need byte-for-byte replay determinism across patch releases, also record the
16
+ exact commit hash in your project's `UPSTREAM.md`. See [commit-hash pinning](#commit-hash-pinning-supplementary) below.
17
+
18
+ ---
19
+
20
+ ## Canonical versioning policy
21
+
22
+ Ananke uses **semantic versioning (semver)** as the public contract:
23
+
24
+ | Version change | Meaning |
25
+ |---------------|---------|
26
+ | Patch (`0.1.x`) | Bug fixes, documentation corrections, and internal refactors that do not change observable simulation output |
27
+ | Minor (`0.x.0`) | Additive changes: new exports, new optional fields, new simulation phases. **Tier 1 (Stable) exports are not broken.** Tier 2 (Experimental) exports may change with a `CHANGELOG.md` entry |
28
+ | Major (`x.0.0`) | Breaking changes to Tier 1 exports. A migration guide accompanies every major bump |
29
+
30
+ > **Pre-1.0 note:** While the project major is `0`, Tier 1 exports do not break
31
+ > within the current minor line without a documented minor-version bump and a migration guide in `CHANGELOG.md`.
32
+ > The `1.0` release will lock the Tier 1 surface under full semver guarantees.
33
+
34
+ ---
35
+
36
+
37
+ ## Canonical runtime version source
38
+
39
+ Runtime compatibility checks use `ANANKE_ENGINE_VERSION` from `src/version.ts`, which is
40
+ a generated file. The **only authoritative source** is `package.json` `"version"`; run
41
+ `npm run sync-version` to regenerate `src/version.ts` after any version bump.
42
+
43
+ CI enforces this with `npm run check-version-sync` to prevent drift between publish
44
+ versioning, runtime compat checks, and generated docs/tooling outputs.
45
+
46
+ ---
47
+ ## API stability tiers
48
+
49
+ Every export in `src/index.ts` is tagged with a stability tier.
50
+ The full tier table is in [`STABLE_API.md`](../STABLE_API.md).
51
+
52
+ | Tier | Label | Guarantee |
53
+ |------|-------|-----------|
54
+ | 1 | **Stable** | No breaking changes without major version bump + migration guide |
55
+ | 2 | **Experimental** | May change between minor versions; `CHANGELOG.md` entry required |
56
+ | 3 | **Internal** | No stability guarantee; may change at any time |
57
+
58
+ ---
59
+
60
+ ## Commit-hash pinning (supplementary)
61
+
62
+ Semver tags are the recommended pinning mechanism for most projects. For hosts that
63
+ require absolute replay determinism across patch releases (e.g. tournament servers, archived
64
+ experiment results), you may also pin to a specific commit hash.
65
+
66
+ ### npm / package.json
67
+
68
+ ```json
69
+ {
70
+ "dependencies": {
71
+ "ananke": "github:its-not-rocket-science/ananke#<commit-sha>"
72
+ }
73
+ }
74
+ ```
75
+
76
+ Replace `<commit-sha>` with the full 40-character hash you have validated.
77
+
78
+ ### Git submodule
79
+
80
+ ```bash
81
+ git submodule add https://github.com/its-not-rocket-science/ananke.git vendor/ananke
82
+ cd vendor/ananke && git checkout <commit-sha>
83
+ git add vendor/ananke && git commit -m "pin ananke to <commit-sha>"
84
+ ```
85
+
86
+ ### Why keep the option at all?
87
+
88
+ Semver patch releases may adjust a tuning constant in ways that are technically
89
+ non-breaking (same function signatures, same output format) but shift simulation
90
+ balance. If you run long-lived archived replays that must be reproduced identically
91
+ years later, commit-hash pinning is the stronger guarantee.
92
+
93
+ ---
94
+
95
+ ## What constitutes a breaking change
96
+
97
+ ### Tier 1Always breaking (requires major version bump)
98
+
99
+ | Change | Example |
100
+ |--------|---------|
101
+ | Rename or remove a field on `Entity` | `entity.injury` `entity.wounds` |
102
+ | Rename or remove a field on `WorldState` | `world.entities` array shape change |
103
+ | Change a field's unit or scale | `position_m` stored at a different `SCALE` |
104
+ | Remove or rename a Tier 1 exported function | `stepWorld` signature change |
105
+ | Change the interpretation of a constant | `SCALE.Q` value changed |
106
+ | Change determinismsame seed, different outcome | Any RNG, ordering, or arithmetic change |
107
+
108
+ ### Tier 2 Potentially breaking (noted in CHANGELOG.md, migration hint provided)
109
+
110
+ | Change | Example |
111
+ |--------|---------|
112
+ | Add a required field to `Entity` | New mandatory `age?: AgeState` that existing entity helpers don't initialise |
113
+ | Change a constant value that affects tuning | `SURF_J` adjusted |
114
+ | Add an optional field that changes default behaviour when absent | New optional context field with a non-neutral default |
115
+ | Change snapshot test output | Simulation output shifted for at least one seed |
116
+
117
+ ### Tier 3 — Non-breaking (no migration required)
118
+
119
+ - Adding new exported functions or types
120
+ - Adding optional fields to interfaces (with `exactOptionalPropertyTypes`-safe defaults)
121
+ - Adding new built-in archetypes, weapons, or body plans
122
+ - Adding new `tools/` scripts or `docs/` files
123
+ - Improving test coverage without changing logic
124
+ - Fixing bugs where the previous behaviour was demonstrably wrong
125
+
126
+ ---
127
+
128
+ ## Changelog format
129
+
130
+ Breaking and potentially breaking changes are recorded in `CHANGELOG.md`.
131
+ Each entry follows:
132
+
133
+ ```markdown
134
+ ## <semver-tag><YYYY-MM-DD>
135
+
136
+ ### Breaking
137
+ - `Entity.someField` renamed to `Entity.newField`.
138
+ Migration: search `.someField` and replace with `.newField`.
139
+
140
+ ### Potentially breaking
141
+ - `SURF_J` constant changed from 120 to 110.
142
+ Re-run `npm run run:validation` to check calibration impact.
143
+
144
+ ### Added
145
+ - `src/sim/widget.ts` Widget System (Phase N).
146
+ ```
147
+
148
+ ---
149
+
150
+ ## Upgrade review cadence
151
+
152
+ When upgrading your pinned semver tag or commit hash:
153
+
154
+ 1. **Read the CHANGELOG** — check all entries since your previous version for Tier 1 / Tier 2 items
155
+ 2. **Diff the source** — `git diff <old-tag>..<new-tag> -- src/` to see what changed
156
+ 3. **Run your integration build** — `npm run build`
157
+ 4. **Run the validation suite** — `npm run run:validation` to confirm calibration scenarios pass
158
+ 5. **Run the full test suite** `npm run test:coverage`
159
+ 6. **Update your pin** commit the new tag/hash to your dependency manifest
160
+
161
+ A quarterly review cadence is a reasonable default for a production project. Determinism
162
+ corrections warrant an out-of-cycle upgrade.
163
+
164
+ ---
165
+
166
+ ## Snapshot tests and determinism
167
+
168
+ `test/snapshots/kernel_behaviour_snapshot.json` is a deterministic regression lock.
169
+ If it changes in an upstream commit, that commit has shifted simulation output for at
170
+ least one entity and seed combination. Treat snapshot changes as **Tier 2** by default;
171
+ verify they are intentional before upgrading.
172
+
173
+ To regenerate your snapshot baseline after a deliberate constant change:
174
+
175
+ ```bash
176
+ rm test/snapshots/kernel_behaviour_snapshot.json
177
+ npm run test:coverage
178
+ ```
179
+
180
+ ---
181
+
182
+ ## Internal fork guidance
183
+
184
+ If you need to diverge from upstream (custom damage channels, proprietary AI, non-standard
185
+ body plan hooks):
186
+
187
+ 1. Fork at a pinned tag (or commit hash) do not fork from an untagged tip
188
+ 2. Namespace your extensions: prefix custom fields and modules with your project identifier
189
+ (e.g. `entity.myproject_customField`) to avoid conflicts on upstream merges
190
+ 3. Keep an `UPSTREAM.md` at your fork root noting your base version and a diff summary
191
+ 4. Periodically rebase onto upstream Tier 3 commits to collect non-breaking improvements;
192
+ treat Tier 1/2 commits as explicit migration tasks to schedule
193
+
194
+ ---
195
+
196
+ ## Deprecation lifecycle
197
+
198
+ Symbols are deprecated rather than removed immediately so downstream projects have time
199
+ to migrate. The lifecycle follows a three-phase pattern:
200
+
201
+ ### 1 Mark deprecated (current version)
202
+
203
+ Add a structured JSDoc tag to the symbol:
204
+
205
+ ```typescript no-check-example
206
+ /**
207
+ * @deprecated since 0.1.50 — use `newFunction` instead. Removes at 0.3.0.
208
+ */
209
+ export function oldFunction() { }
210
+ ```
211
+
212
+ The **required format** is:
213
+
214
+ ```
215
+ @deprecated since {version} — use {replacement} instead. Removes at {removeAfter}.
216
+ ```
217
+
218
+ | Field | Meaning |
219
+ |-------|---------|
220
+ | `since` | Version in which the deprecation was introduced |
221
+ | `replacement` | Short description or code reference of what to use instead |
222
+ | `removeAfter` | Version at which the symbol will be deleted must be a future version |
223
+
224
+ `removeAfter` must satisfy `> current` at publish time; `npm publish` runs
225
+ `audit-deprecations --check` and fails if any symbol is overdue.
226
+
227
+ ### 2 Migration window
228
+
229
+ During the migration window the symbol still works but emits a TypeScript deprecation
230
+ warning in IDEs (the `@deprecated` tag triggers the strikethrough).
231
+
232
+ The migration window is at least one **minor** version for Tier 2 symbols
233
+ and at least one **major** version for Tier 1 (Stable) symbols.
234
+
235
+ ### 3 Remove at removeAfter
236
+
237
+ When the engine reaches `removeAfter`, the symbol is deleted and a CHANGELOG entry is
238
+ added under a `### Removed` heading. The `since` version and the replacement are
239
+ included in the removal note so the changelog is self-contained.
240
+
241
+ ### Auditing
242
+
243
+ ```bash
244
+ npm run audit-deprecations # human-readable table
245
+ npm run audit-deprecations -- --json # machine-readable JSON
246
+ npm run audit-deprecations -- --check # exit 1 if any overdue
247
+ ```
248
+
249
+ The `--check` flag is run automatically by `npm run prepublishOnly`.
250
+
251
+ ### Adding a new deprecation (checklist)
252
+
253
+ - [ ] Add the structured `@deprecated` JSDoc tag with `since`, replacement, and `removeAfter`.
254
+ - [ ] Run `npm run audit-deprecations` to confirm the tag is detected and not overdue.
255
+ - [ ] Add a CHANGELOG entry under `### Deprecated`.
256
+ - [ ] Surface the replacement in the relevant `docs/` file or `STABLE_API.md`.