slither-sim 0.5.0__tar.gz
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.
- slither_sim-0.5.0/CHANGELOG.md +462 -0
- slither_sim-0.5.0/CONTRIBUTING.md +152 -0
- slither_sim-0.5.0/Cargo.lock +678 -0
- slither_sim-0.5.0/Cargo.toml +90 -0
- slither_sim-0.5.0/LICENSE +21 -0
- slither_sim-0.5.0/PKG-INFO +49 -0
- slither_sim-0.5.0/PYPI.md +34 -0
- slither_sim-0.5.0/README.md +139 -0
- slither_sim-0.5.0/assets/logo.svg +8 -0
- slither_sim-0.5.0/build.rs +15 -0
- slither_sim-0.5.0/docs/README.md +40 -0
- slither_sim-0.5.0/docs/bot-api.md +390 -0
- slither_sim-0.5.0/docs/c-api.md +96 -0
- slither_sim-0.5.0/docs/client-api.md +216 -0
- slither_sim-0.5.0/docs/configuration.md +484 -0
- slither_sim-0.5.0/docs/evidence-format.md +66 -0
- slither_sim-0.5.0/docs/maintainers/releasing.md +144 -0
- slither_sim-0.5.0/docs/performance-workloads.md +331 -0
- slither_sim-0.5.0/docs/performance.md +205 -0
- slither_sim-0.5.0/docs/provenance.md +75 -0
- slither_sim-0.5.0/docs/python.md +137 -0
- slither_sim-0.5.0/docs/raw-server.md +249 -0
- slither_sim-0.5.0/docs/research-workflow.md +439 -0
- slither_sim-0.5.0/docs/server-rules.md +192 -0
- slither_sim-0.5.0/examples/basic.rs +42 -0
- slither_sim-0.5.0/examples/bot.mjs +76 -0
- slither_sim-0.5.0/examples/bot.py +85 -0
- slither_sim-0.5.0/examples/cautious_bot.rs +75 -0
- slither_sim-0.5.0/examples/ffi_bot.py +149 -0
- slither_sim-0.5.0/examples/host_load.rs +175 -0
- slither_sim-0.5.0/examples/portable_bot.py +99 -0
- slither_sim-0.5.0/examples/portable_bot.rs +64 -0
- slither_sim-0.5.0/pyproject.toml +30 -0
- slither_sim-0.5.0/python/Cargo.toml +19 -0
- slither_sim-0.5.0/python/LICENSE +21 -0
- slither_sim-0.5.0/python/PYPI.md +34 -0
- slither_sim-0.5.0/python/examples/bot.py +47 -0
- slither_sim-0.5.0/python/examples/timing.py +145 -0
- slither_sim-0.5.0/python/slither_sim.pyi +166 -0
- slither_sim-0.5.0/python/src/lib.rs +500 -0
- slither_sim-0.5.0/python/tests/run.py +37 -0
- slither_sim-0.5.0/python/tests/test_session.py +585 -0
- slither_sim-0.5.0/slither_sim.pyi +166 -0
- slither_sim-0.5.0/src/bot/data/a1-overrides.json +31 -0
- slither_sim-0.5.0/src/bot/data/a4-mean-overrides.json +56 -0
- slither_sim-0.5.0/src/bot/data/resolved.json +171 -0
- slither_sim-0.5.0/src/bot/kernel.rs +2945 -0
- slither_sim-0.5.0/src/bot/mod.rs +83 -0
- slither_sim-0.5.0/src/bot/params.rs +150 -0
- slither_sim-0.5.0/src/bot/tests.rs +1453 -0
- slither_sim-0.5.0/src/boundary.rs +99 -0
- slither_sim-0.5.0/src/bounds_index.rs +183 -0
- slither_sim-0.5.0/src/client/challenge.rs +85 -0
- slither_sim-0.5.0/src/client/encode.rs +1039 -0
- slither_sim-0.5.0/src/client/fast_hash.rs +35 -0
- slither_sim-0.5.0/src/client/fixtures.rs +102 -0
- slither_sim-0.5.0/src/client/forager/conformance.rs +311 -0
- slither_sim-0.5.0/src/client/forager/tests.rs +175 -0
- slither_sim-0.5.0/src/client/forager.rs +113 -0
- slither_sim-0.5.0/src/client/hud.rs +171 -0
- slither_sim-0.5.0/src/client/latency.rs +689 -0
- slither_sim-0.5.0/src/client/minimap.rs +460 -0
- slither_sim-0.5.0/src/client/mod.rs +203 -0
- slither_sim-0.5.0/src/client/network.rs +540 -0
- slither_sim-0.5.0/src/client/presentation.rs +571 -0
- slither_sim-0.5.0/src/client/protocol.rs +1811 -0
- slither_sim-0.5.0/src/client/received.rs +507 -0
- slither_sim-0.5.0/src/client/server/bot_tests.rs +152 -0
- slither_sim-0.5.0/src/client/server.rs +3074 -0
- slither_sim-0.5.0/src/client/simulation/bot_tests.rs +135 -0
- slither_sim-0.5.0/src/client/simulation/broadcast.rs +774 -0
- slither_sim-0.5.0/src/client/simulation/config.rs +159 -0
- slither_sim-0.5.0/src/client/simulation/connection.rs +584 -0
- slither_sim-0.5.0/src/client/simulation/food.rs +446 -0
- slither_sim-0.5.0/src/client/simulation/markers.rs +108 -0
- slither_sim-0.5.0/src/client/simulation/pit_tests.rs +374 -0
- slither_sim-0.5.0/src/client/simulation/remote.rs +258 -0
- slither_sim-0.5.0/src/client/simulation/snakes.rs +463 -0
- slither_sim-0.5.0/src/client/simulation/tests.rs +3573 -0
- slither_sim-0.5.0/src/client/simulation.rs +582 -0
- slither_sim-0.5.0/src/client/transport.rs +231 -0
- slither_sim-0.5.0/src/client/visibility.rs +291 -0
- slither_sim-0.5.0/src/error.rs +231 -0
- slither_sim-0.5.0/src/food_grid.rs +603 -0
- slither_sim-0.5.0/src/json.rs +704 -0
- slither_sim-0.5.0/src/kiosk.rs +376 -0
- slither_sim-0.5.0/src/lib.rs +37 -0
- slither_sim-0.5.0/src/main.rs +142 -0
- slither_sim-0.5.0/src/model.rs +222 -0
- slither_sim-0.5.0/src/observation/mod.rs +558 -0
- slither_sim-0.5.0/src/parallel.rs +111 -0
- slither_sim-0.5.0/src/physics.rs +521 -0
- slither_sim-0.5.0/src/prey.rs +175 -0
- slither_sim-0.5.0/src/profiling.rs +68 -0
- slither_sim-0.5.0/src/simulator/checkpoint.rs +1261 -0
- slither_sim-0.5.0/src/simulator/initialization.rs +717 -0
- slither_sim-0.5.0/src/simulator/initialization_tests.rs +327 -0
- slither_sim-0.5.0/src/simulator/observation_tests.rs +275 -0
- slither_sim-0.5.0/src/simulator.rs +2957 -0
- slither_sim-0.5.0/src/spawn/safety.rs +468 -0
- slither_sim-0.5.0/src/spawn.rs +124 -0
- slither_sim-0.5.0/src/transport/frame.rs +721 -0
- slither_sim-0.5.0/src/transport/tests.rs +83 -0
- slither_sim-0.5.0/src/transport.rs +858 -0
- slither_sim-0.5.0/tests/fixtures/client-food-interest.json +122 -0
- slither_sim-0.5.0/tests/fixtures/client-hud-leaderboard.json +208 -0
- slither_sim-0.5.0/tests/fixtures/client-presentation.json +2572 -0
- slither_sim-0.5.0/tests/fixtures/client-reporting-cadence-near-server.json +68 -0
- slither_sim-0.5.0/tests/fixtures/client-reporting-cadence.json +29 -0
- slither_sim-0.5.0/tests/fixtures/forager-conformance.json +1 -0
- slither_sim-0.5.0/tests/fixtures/forager-native-parity.json +1 -0
- slither_sim-0.5.0/tests/fixtures/forager-oracle-linux-x86_64-gnu.json +1 -0
- slither_sim-0.5.0/tests/fixtures/forager-oracle-windows-x86_64-msvc.json +1 -0
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
## [0.5.0](https://github.com/NikitaMGrimm/slither-sim/compare/v0.4.0...v0.5.0) - 2026-10-26
|
|
6
|
+
|
|
7
|
+
### Breaking
|
|
8
|
+
|
|
9
|
+
- Host settings are grouped: `maxClients` → `players.max`, `bots` →
|
|
10
|
+
`bots.count`, `botThreads` → `bots.threads` and `simulation.latency` →
|
|
11
|
+
`bots.latency`. Sockets no longer inherit the simulation's latency;
|
|
12
|
+
`players.latency` sets their added link delay, with zero processing. Flat keys
|
|
13
|
+
and a non-default host `simulation.latency` are rejected
|
|
14
|
+
([HostConfig](docs/configuration.md#hostconfig)).
|
|
15
|
+
- Official worlds keep their initial radius, sized for their population. The
|
|
16
|
+
provisional dynamic controller, which did not match official servers, is
|
|
17
|
+
opt-in. Hosts, resets and simulation backends size official worlds for all
|
|
18
|
+
their snakes, scaling food with area and keeping the official prey density.
|
|
19
|
+
Fixed radii, sandbox and Battledome are unchanged
|
|
20
|
+
([population sizing](docs/configuration.md#population-sizing)).
|
|
21
|
+
- `SimulationConfig.broadcastTicks` is removed: gameplay updates go out every
|
|
22
|
+
tick, and configs that set it are rejected
|
|
23
|
+
([SimulationConfig](docs/configuration.md#simulationconfig)).
|
|
24
|
+
- `LatencyConfig.jitterSeconds` and `congestion` are replaced by `variation`
|
|
25
|
+
(lognormal per-message delay with a slow correlated part) and `pauses` (short
|
|
26
|
+
delivery holds per direction); the old fields are rejected.
|
|
27
|
+
`LatencyConfig::measured_route()` is fitted to one home connection to an
|
|
28
|
+
official server; near-server captures attribute its pauses to that connection
|
|
29
|
+
and its collector, not the server
|
|
30
|
+
([variation and pauses](docs/configuration.md#variation-and-pauses)).
|
|
31
|
+
- The portable `client` JSON protocol is now `slither-client-json-v2`, because
|
|
32
|
+
v0.4.0 requests with the removed broadcast and latency fields are rejected.
|
|
33
|
+
The frame contract stays `slither-client-v2`
|
|
34
|
+
([portable bots](docs/client-api.md#interface-versions)).
|
|
35
|
+
- Sessions tell a rejected step (state unchanged) from a terminal failure (all
|
|
36
|
+
worlds cleared; reset required). For example, a pickup that would overflow a
|
|
37
|
+
snake's mass completes its tick without the gain and stops the world. `serve`
|
|
38
|
+
uses `slither-sim-json-v3` with `sessionEnded` in error replies, Rust returns
|
|
39
|
+
`transport::StepError::{Rejected, Ended}`, C returns `SLITHER_ENDED` (4) and
|
|
40
|
+
Python raises `SessionEndedError`. Successful replies are unchanged
|
|
41
|
+
([session errors](docs/bot-api.md)).
|
|
42
|
+
- C ABI `slither-sim-abi-v2` (`SLITHER_ABI_VERSION` 2) adds `snake_kill_score`
|
|
43
|
+
after `snake_kills` in `slither_frame` and the `SLITHER_DEATH_PIT` death code;
|
|
44
|
+
rebuild against the new header ([C ABI](docs/c-api.md#compatibility)). Rust
|
|
45
|
+
adds `DeathReason::Pit`, and `transport::REASONS` has a third entry
|
|
46
|
+
([frames](docs/bot-api.md#frames)).
|
|
47
|
+
- With recording off, `NetworkBackend::drain_records` and the JSON `wire` op
|
|
48
|
+
return an error, as simulation already did
|
|
49
|
+
([recording](docs/client-api.md#recording-and-network-bounds)).
|
|
50
|
+
- Arbitrary caps are gone; each [limit](docs/configuration.md#limits) is a
|
|
51
|
+
representation bound, a warning or a named policy. Hosts and simulated clients
|
|
52
|
+
take up to 65,535 agents (was 128) and 65,536 prey (was 10,000). The caps on
|
|
53
|
+
`foodCount`, ambient refill, `serve` agents and worlds, decision ticks, and
|
|
54
|
+
latency, processing and network intervals are removed; `info` reports the
|
|
55
|
+
`serve` maxima. `radius` and `radiusUpdates[].radius` reject values above
|
|
56
|
+
`1e150`, matching checkpoints. Validation messages changed.
|
|
57
|
+
- Sliding boundaries need `dt` below 16 / 437.5 s (about 36.57 ms), so a
|
|
58
|
+
boosting minimum-size snake cannot pass its contact lead; this replaces the
|
|
59
|
+
32 ms cap. Hard boundaries accept steps up to about 6.3 × 10¹³ s.
|
|
60
|
+
`maxPerCell: 0` admits no food, and kiosk rates, prey speeds, prey turn rate
|
|
61
|
+
and nutrition factor may be zero ([limits](docs/configuration.md#limits)).
|
|
62
|
+
- Ticks long enough for a snake to outrun the incremental body window warn
|
|
63
|
+
instead of failing, and such snakes are resent in full. Incremental updates
|
|
64
|
+
carry up to three new anchors, up from two
|
|
65
|
+
([packet timing](docs/server-rules.md#packet-timing)).
|
|
66
|
+
- Simulated round trips are no longer clamped to 2 s, and pings slower than 2 s
|
|
67
|
+
are reported instead of dropped
|
|
68
|
+
([timing](docs/configuration.md#timing-and-ping)).
|
|
69
|
+
- The minimum Rust version is 1.99 (was 1.86).
|
|
70
|
+
- `Host::poll()` is removed. `Host::bind(config)?.start()?` returns a
|
|
71
|
+
`RunningHost` with load counters, `wait()` and `stop()`; dropping it stops the
|
|
72
|
+
host, and `Host::run()` starts and waits. Physics, sockets and bots run on
|
|
73
|
+
separate threads ([embedding](docs/raw-server.md#embedding-and-load-checks)).
|
|
74
|
+
- Rust `Simulator` state is private, with borrowed read accessors and checked
|
|
75
|
+
lifecycle, replay and food/prey edits. `WorldOptions` selects an empty,
|
|
76
|
+
dormant or placed initial population; `Placement` defaults to the existing
|
|
77
|
+
test ring. `add`, public `update_mass` and the two-call speed import are
|
|
78
|
+
removed. Typed `Session::prepare_reset`/`commit_reset` keeps rejected resets
|
|
79
|
+
atomic, and Python resets skip a full-frame JSON round trip. Config keys, wire
|
|
80
|
+
replies and contract IDs are unchanged
|
|
81
|
+
([Rust API](docs/bot-api.md#rust-library)).
|
|
82
|
+
- Continuation uses validated `Simulator::checkpoint`, `from_checkpoint` and
|
|
83
|
+
atomic `restore` instead of Simulator/runtime serde. Checkpoints use
|
|
84
|
+
`slither-sim-checkpoint-v1` / `slither-sim-rules-v1`; debug snapshots cannot
|
|
85
|
+
restore worlds.
|
|
86
|
+
- Core calls return `SimError`; `step`/`step_profiled` return
|
|
87
|
+
`CoreStepError::{Rejected, Stopped}`, and `transport::StepError` carries
|
|
88
|
+
`SimError` causes. Match `kind` or `code()` rather than message text, and read
|
|
89
|
+
`Simulator::status()` for the original stop cause. `ErrorCode`, `ErrorKind`
|
|
90
|
+
and `Constraint` are non-exhaustive, so matches need a wildcard arm. Wire
|
|
91
|
+
errors are unchanged ([Rust errors](docs/bot-api.md#rust-library)).
|
|
92
|
+
- `physics::crossed_anchor` drops its unused argument,
|
|
93
|
+
`physics::append_client_anchor` is removed, and `Minimap::from_snakes` returns
|
|
94
|
+
`Result` for an invalid side.
|
|
95
|
+
|
|
96
|
+
### Added
|
|
97
|
+
|
|
98
|
+
- A `bot` feature, on by default through `networking`, adds the frozen Forager
|
|
99
|
+
policy (`bot::Forager`) and `client::ForagerBot`. The default policy is A4
|
|
100
|
+
(A4-mean); A1 stays selectable. The [adoption evidence](https://github.com/NikitaMGrimm/slither-sim/blob/main/research/bots/2026-10-26-a4-adoption/REPORT.md)
|
|
101
|
+
records gameplay, cost and the maintainer's mean-cost gate. The
|
|
102
|
+
[`cautious_bot`](examples/cautious_bot.rs) example runs it.
|
|
103
|
+
- `pip install slither-sim`: the Python package is published to PyPI with each
|
|
104
|
+
crate release. Stable-ABI wheels cover CPython 3.11+ on Linux (x86-64, ARM64),
|
|
105
|
+
macOS (Apple silicon, Intel) and Windows (x86-64); other platforms build from
|
|
106
|
+
source with Rust 1.99+ ([Python guide](docs/python.md)).
|
|
107
|
+
- [Release archives](README.md#download-a-release) hold the CLI, the C ABI
|
|
108
|
+
library and header, and `SHA256SUMS`, for Linux (x86-64, ARM64; glibc 2.17+),
|
|
109
|
+
macOS (Apple silicon, Intel) and Windows (x86-64). They are unsigned.
|
|
110
|
+
- [Battledome](docs/configuration.md#battledome), our own mode:
|
|
111
|
+
`Config::battledome()` or `"preset": "battledome"` gives a fixed 3,584-unit
|
|
112
|
+
arena with a one-way pit, a permanent 400-point size floor (boosting at it is
|
|
113
|
+
free and drops nothing; death food returns only mass above it), a 15-minute
|
|
114
|
+
rolling kill score, no prey, and ambient refill that counts all food. Newborns
|
|
115
|
+
start in an outer 2,684–3,400-unit band once body, head path and departure are
|
|
116
|
+
clear; waiting socket players go before background bots. Other rules follow
|
|
117
|
+
the official preset. New world settings: `pit`, `spawnRadius`,
|
|
118
|
+
`spawnRadiusMax`, `killScoreSeconds`, `minScore` and
|
|
119
|
+
`ambientRefillCountsAllFood`.
|
|
120
|
+
- The stock browser shows a pit's edge as a ring of decorative pellets. Physics
|
|
121
|
+
and bot food are unchanged; socket bots get real food only by sending the
|
|
122
|
+
`X-SlitherSim-Food: physical` upgrade header
|
|
123
|
+
([Battledome](docs/configuration.md#battledome)).
|
|
124
|
+
- World configs take `"preset": "official" | "sandbox" | "battledome"` in
|
|
125
|
+
`serve` and Python resets, `host` config files and `client` simulation
|
|
126
|
+
requests; explicit fields override the preset
|
|
127
|
+
([presets](docs/configuration.md#presets)).
|
|
128
|
+
- Frames carry each snake's rolling kill score: `snakes.killScore` in `serve`
|
|
129
|
+
JSON (an additive `slither-sim-json-v3` column), `kill_score` in `FrameRef`,
|
|
130
|
+
`snake_kill_score` in Python and the C ABI, and `Simulator::kill_score` in
|
|
131
|
+
Rust ([frames](docs/bot-api.md#frames)).
|
|
132
|
+
- `Config::warnings`, `SimulationConfig::warnings` and `HostConfig::warnings`
|
|
133
|
+
flag valid but unmeasured settings: a `dt` outside the measured 6.94–7.07 ms
|
|
134
|
+
loop, or ticks long enough to outrun the incremental body window
|
|
135
|
+
(`dt × 437.5 ≥ 126`). `serve` returns them on reset, the CLI prints them, and
|
|
136
|
+
Python's `Session.reset` issues `UserWarning`s
|
|
137
|
+
([limits](docs/configuration.md#limits)).
|
|
138
|
+
- Host `bots.threads` (default 2) runs background bots on their own threads,
|
|
139
|
+
apart from physics and sockets. The `host_load` example measures simulation
|
|
140
|
+
load, deferred ticks and extra delivery delay
|
|
141
|
+
([hosting](docs/raw-server.md#embedding-and-load-checks)).
|
|
142
|
+
- `SimulationConfig.delivery` chooses when visible state is sent. The default,
|
|
143
|
+
`responsive`, is our own design and sends steering, speed and mass changes in
|
|
144
|
+
the next frame; `official` keeps the measured pacing. Train bots meant for
|
|
145
|
+
official servers with `official`
|
|
146
|
+
([SimulationConfig](docs/configuration.md#simulationconfig)).
|
|
147
|
+
- A localhost-only host/capture/compare command records transport baselines and
|
|
148
|
+
checks them against official-reference gates
|
|
149
|
+
([transport parity](docs/research-workflow.md#transport-parity)).
|
|
150
|
+
|
|
151
|
+
### Changed
|
|
152
|
+
|
|
153
|
+
- Gameplay updates go out every physics tick (7 ms by default). `official`
|
|
154
|
+
delivery uses measured per-family pacing: motion and standalone mass changes
|
|
155
|
+
at least 6 and 15 ticks apart per snake, anchors at once, ambient food on the
|
|
156
|
+
shared 504 ms maintenance cycle and prey corrections on one clock per prey.
|
|
157
|
+
These are partial models
|
|
158
|
+
([packet timing](docs/server-rules.md#packet-timing)).
|
|
159
|
+
- Minimaps and leaderboards follow server-wide clocks at the official mean
|
|
160
|
+
periods (`minimapIntervalSeconds` 2.504, `leaderboardIntervalSeconds` 3.008).
|
|
161
|
+
A join waits for each clock's next tick instead of getting an immediate board
|
|
162
|
+
([packet timing](docs/server-rules.md#packet-timing)).
|
|
163
|
+
- Input and pings that arrive during a tick take effect in that tick's frame,
|
|
164
|
+
and pongs lead it, removing a tick from input delay and measured ping
|
|
165
|
+
([timing](docs/configuration.md#timing-and-ping)).
|
|
166
|
+
- Host and native background bots and both Rust bot examples use the shared
|
|
167
|
+
default Forager, and boost-only changes are now sent
|
|
168
|
+
([portable bots](docs/client-api.md#rust)).
|
|
169
|
+
- Transport checks compare against timing recorded near the official servers
|
|
170
|
+
instead of home captures, whose delay spikes came from the home route. New
|
|
171
|
+
fixtures cover rare server timing exceptions; simulator cadence is unchanged
|
|
172
|
+
([reference audit](https://github.com/NikitaMGrimm/slither-sim/blob/main/research/fidelity/2026-10-26-server-timing-references/REPORT.md)).
|
|
173
|
+
- New S-shaped snake logo and square project icon, paired with SlitherClient's
|
|
174
|
+
C-shaped snake.
|
|
175
|
+
|
|
176
|
+
### Fixed
|
|
177
|
+
|
|
178
|
+
- A default `host` no longer refuses every player with `No clear spawn
|
|
179
|
+
position`. Host arenas start sized for all seats, and a crowded world places a
|
|
180
|
+
join at the most open spot ([hosting](docs/raw-server.md#presets)).
|
|
181
|
+
- A host no longer drops a healthy client when a message near the 1 MiB limit
|
|
182
|
+
follows a small one that is still waiting for its batch to fill.
|
|
183
|
+
- The host bounds raw socket reads per poll, so one long fragmented message
|
|
184
|
+
cannot stall other connections. A background bot whose decoder fails
|
|
185
|
+
reconnects alone, and stopping no longer waits out a long physics tick.
|
|
186
|
+
- A new world starts at its configured radius instead of one population step
|
|
187
|
+
smaller, so resetting with the returned config reproduces the first frame.
|
|
188
|
+
`Placement::TestRing` rejects initial bodies that extend outside a small
|
|
189
|
+
arena, and a refused hosted join says the candidate search was exhausted
|
|
190
|
+
rather than implying the arena is full.
|
|
191
|
+
- Prey respawn is no longer capped at one per tick, and a replacement waits a
|
|
192
|
+
full `respawnSeconds` after the catch. With a coarse `dt`, pickup follows each
|
|
193
|
+
prey motion step instead of the straight line between endpoints, and prey
|
|
194
|
+
motion that overflows ends the world with an error instead of producing NaN
|
|
195
|
+
positions.
|
|
196
|
+
- Prey whose IDs share the low 16 bits (such as 0 and 65536) no longer hide each
|
|
197
|
+
other on the wire; all 65,536 wire IDs can be live
|
|
198
|
+
([prey settings](docs/configuration.md#prey)).
|
|
199
|
+
- Prey catches can no longer make `fam` or `length` infinite: settings where one
|
|
200
|
+
catch overflows are rejected, and accumulated overflow stops the world
|
|
201
|
+
([limits](docs/configuration.md#limits)).
|
|
202
|
+
- Kiosk shrinkage no longer deletes pending growth: it removes only mass the
|
|
203
|
+
score shows, and a zero shrink rate changes nothing.
|
|
204
|
+
- A tiny food `cellSize` no longer merges distinct
|
|
205
|
+
[admission cells](docs/configuration.md#food-admission-limits).
|
|
206
|
+
- Native commands with processing delay apply in the tick they arrive instead of
|
|
207
|
+
one tick later. Cancelling or non-finite one-way legs fail validation, and
|
|
208
|
+
latency scheduling returns an error instead of hanging or producing
|
|
209
|
+
non-finite times.
|
|
210
|
+
- Native recording failures leave pending decisions and client clocks intact,
|
|
211
|
+
and rejected sends no longer suppress a later boost change.
|
|
212
|
+
- Unrepresentable `serve` columns, `worlds × agents` products and host client
|
|
213
|
+
counts return errors instead of panicking. A failed reset keeps the previous
|
|
214
|
+
session; a failed step frame ends it ([session errors](docs/bot-api.md)).
|
|
215
|
+
- A world stopped by mass overflow stays stopped after checkpoint restore
|
|
216
|
+
([limits](docs/configuration.md#limits)).
|
|
217
|
+
- `Config::deserialize` called directly from Rust accepts presets, like JSON
|
|
218
|
+
parsing ([presets](docs/configuration.md#presets)).
|
|
219
|
+
- Python `Session.reset` issues its warnings before replacing worlds, so a
|
|
220
|
+
warning raised as an error keeps the previous session
|
|
221
|
+
([Python](docs/python.md)).
|
|
222
|
+
|
|
223
|
+
### Performance
|
|
224
|
+
|
|
225
|
+
- The host uses about 5% less CPU per tick at 250 and 500 socket clients, with
|
|
226
|
+
byte-identical output. Unchanged food subscriptions stay in place, recipients
|
|
227
|
+
with the same history of a snake share one encoded delta, and delivered
|
|
228
|
+
frames reach the socket without an extra copy. 250 clients now narrowly meet
|
|
229
|
+
the 10 ms delivery grade on one core; 500 still fall behind
|
|
230
|
+
([study](https://github.com/NikitaMGrimm/slither-sim/blob/main/research/performance/2026-10-26-host-efficiency/REPORT.md)).
|
|
231
|
+
- The host hands players' frames to the socket thread before encoding bots'
|
|
232
|
+
frames. With 480 localhost bots, mean ping fell from about 8.3 to 7.1 ms and
|
|
233
|
+
p99 from 17–19 to 11–13 ms
|
|
234
|
+
([host load checks](docs/raw-server.md#embedding-and-load-checks)).
|
|
235
|
+
- Crowded hosts spend far less time choosing spawn positions: candidates stop
|
|
236
|
+
being scored once they cannot win, and the chosen pose is unchanged. A
|
|
237
|
+
64-seat Battledome host drops from about 45 to 3.5 ms per tick. Background
|
|
238
|
+
bots refused a spawn wait one second before retrying; socket players keep
|
|
239
|
+
their own join timing
|
|
240
|
+
([study](https://github.com/NikitaMGrimm/slither-sim/blob/main/research/performance/2026-10-25-battledome-spawn-cost/REPORT.md)).
|
|
241
|
+
- Batch observations (`observe_all_into`, `observe_selected_into`, transport
|
|
242
|
+
frames and `serve`) are 16–19% faster sequentially and 5–12% faster in
|
|
243
|
+
parallel in the 96- and 128-snake benchmark worlds, with identical results.
|
|
244
|
+
Synthetic worst cases are slower: up to 15% when food clusters away from
|
|
245
|
+
observers, 2.5–4% with sparse or narrow food
|
|
246
|
+
([study](https://github.com/NikitaMGrimm/slither-sim/blob/main/research/performance/2026-10-24-observation-food-index/REPORT.md)).
|
|
247
|
+
- A [native Linux capacity study](https://github.com/NikitaMGrimm/slither-sim/blob/main/research/performance/2026-10-26-host-capacity/REPORT.md)
|
|
248
|
+
finds that one core keeps official-like delivery for 100 socket clients and
|
|
249
|
+
real time for 500 background bots, and profiles where the host's CPU goes.
|
|
250
|
+
|
|
251
|
+
## [0.4.0](https://github.com/NikitaMGrimm/slither-sim/compare/v0.3.1...v0.4.0) - 2026-10-24
|
|
252
|
+
|
|
253
|
+
### Added
|
|
254
|
+
|
|
255
|
+
- *(python)* add an in-process Python package over transport sessions ([#64](https://github.com/NikitaMGrimm/slither-sim/pull/64))
|
|
256
|
+
- *(tools)* measure serve transport cost at Python and Node controllers ([#62](https://github.com/NikitaMGrimm/slither-sim/pull/62))
|
|
257
|
+
- *(transport)* drive sessions in-process and add a C ABI ([#63](https://github.com/NikitaMGrimm/slither-sim/pull/63))
|
|
258
|
+
- *(serve)* [**breaking**] replace slither-sim-json-v1 with columnar multi-world frames ([#61](https://github.com/NikitaMGrimm/slither-sim/pull/61))
|
|
259
|
+
- *(serve)* [**breaking**] add --parallel and pass ServeOptions to transport::serve ([#59](https://github.com/NikitaMGrimm/slither-sim/pull/59))
|
|
260
|
+
|
|
261
|
+
### Other
|
|
262
|
+
|
|
263
|
+
- cache Rust builds, lint once and add macOS jobs ([#67](https://github.com/NikitaMGrimm/slither-sim/pull/67))
|
|
264
|
+
- streamline user and contributor guides ([#65](https://github.com/NikitaMGrimm/slither-sim/pull/65))
|
|
265
|
+
|
|
266
|
+
### Breaking
|
|
267
|
+
|
|
268
|
+
- `slither-sim serve` speaks `slither-sim-json-v2`, and v1 is removed. Replies
|
|
269
|
+
carry one frame per world: everything any living slot sees, once, in columns,
|
|
270
|
+
with each slot's view as row indices into them. With 128 living snakes, replies
|
|
271
|
+
are about 12× smaller, the server answers about twice as fast and Python's
|
|
272
|
+
`json.loads` is about 11× faster.
|
|
273
|
+
- To migrate, send one `{"heading":[...],"boost":[...]}` step entry per world
|
|
274
|
+
(`null` headings for dead slots) and read `result.worlds[w].views[slot]`.
|
|
275
|
+
`observe` and `elapsedSeconds` are removed (use `ticks × config.dt`), and
|
|
276
|
+
`snapshot` takes `world`. See the [bot API](docs/bot-api.md).
|
|
277
|
+
- Frames round coordinates to 0.01 world units, headings to 0.0001 rad and speeds
|
|
278
|
+
to 0.01 units/s; other numbers stay exact. Real players mostly receive coarser
|
|
279
|
+
protocol-19 data, and the worst error is 0.05% of the smallest snake radius;
|
|
280
|
+
see the [observation precision study](https://github.com/NikitaMGrimm/slither-sim/blob/main/research/fidelity/2026-10-24-observation-precision/REPORT.md).
|
|
281
|
+
The simulation, snapshots, the portable client and the WebSocket host keep full
|
|
282
|
+
precision, so hosted players are unaffected.
|
|
283
|
+
|
|
284
|
+
### Added
|
|
285
|
+
|
|
286
|
+
- One `serve` session runs many worlds: `reset` takes `worlds` (up to 1,024),
|
|
287
|
+
world `w` uses seed `seed + w`, and worlds step in parallel on every core.
|
|
288
|
+
`slither-sim serve --threads N` caps the threads; replies do not depend on it.
|
|
289
|
+
- `transport::Session` drives `serve` sessions in-process. `request` answers a
|
|
290
|
+
JSON request line with the exact reply line `serve` writes. `step` takes
|
|
291
|
+
heading and boost slices for every slot of every world and writes no JSON;
|
|
292
|
+
`frame` then reads each world's frame as typed, read-only columns with the
|
|
293
|
+
values the JSON frame prints. See [in-process sessions](docs/bot-api.md#in-process-sessions).
|
|
294
|
+
- `slither-sim-abi-v1`, a C ABI over these sessions, in the unpublished
|
|
295
|
+
`slither-sim-ffi` workspace crate (`ffi/`, with a hand-written header). Any
|
|
296
|
+
language that can call C can reset through JSON, then step from typed arrays
|
|
297
|
+
and read frame columns through pointers. `examples/ffi_bot.py` drives it with
|
|
298
|
+
Python's standard-library `ctypes`. See the [C ABI guide](docs/c-api.md).
|
|
299
|
+
- The `slither-sim` Python package (`python/`, import `slither_sim`; not yet on
|
|
300
|
+
PyPI) runs these sessions in-process. `Session.step` takes float64 and
|
|
301
|
+
bool/uint8 buffers, such as numpy arrays, or plain sequences, and releases the
|
|
302
|
+
GIL; `Session.frame` returns the columns as `array.array` copies. With 128
|
|
303
|
+
agents, a Python decision loop took 0.27 ms per step against 0.56 ms through
|
|
304
|
+
JSON requests. It shares the crate's version, as does `slither-sim-ffi`, through
|
|
305
|
+
`[workspace.package]`. See the [Python guide](docs/python.md).
|
|
306
|
+
|
|
307
|
+
## [0.3.1](https://github.com/NikitaMGrimm/slither-sim/compare/v0.3.0...v0.3.1) - 2026-10-24
|
|
308
|
+
|
|
309
|
+
### Changed
|
|
310
|
+
|
|
311
|
+
- *(simulator)* reuse per-step buffers between steps ([#57](https://github.com/NikitaMGrimm/slither-sim/pull/57))
|
|
312
|
+
- *(transport)* write JSON replies without building a Value tree ([#55](https://github.com/NikitaMGrimm/slither-sim/pull/55))
|
|
313
|
+
- *(client)* share food sector listings and index known snakes by slot ([#54](https://github.com/NikitaMGrimm/slither-sim/pull/54))
|
|
314
|
+
- *(observation)* index batch observation food in a 2D grid ([#53](https://github.com/NikitaMGrimm/slither-sim/pull/53))
|
|
315
|
+
- *(simulator)* track food occupancy and pickup candidates across a step ([#52](https://github.com/NikitaMGrimm/slither-sim/pull/52))
|
|
316
|
+
- *(simulator)* add exact broad phases for collisions and prey pickup ([#51](https://github.com/NikitaMGrimm/slither-sim/pull/51))
|
|
317
|
+
|
|
318
|
+
### Added
|
|
319
|
+
|
|
320
|
+
- List benchmark workloads with `perf_baseline --list` from one registration table.
|
|
321
|
+
New synthetic steady-state workloads cover sandbox, official worlds at 30–500
|
|
322
|
+
snakes, a dense no-prey arena standing in for a future Battle Dome, and an
|
|
323
|
+
official in-process client path, with deaths, death food and respawns inside the
|
|
324
|
+
measured and traced windows. The six historical cases and their traces are unchanged.
|
|
325
|
+
See [performance workloads](docs/performance-workloads.md).
|
|
326
|
+
- Compare a base ref with the working tree in one command:
|
|
327
|
+
`tools/perf_compare.py --base REF` freezes both source snapshots, builds them
|
|
328
|
+
in separate targets, checks full-state trace parity, records phase profiles and
|
|
329
|
+
runs paired timings. Runners and PR comparisons take workloads, sample sizes
|
|
330
|
+
and trace windows from the catalog; PR CI times and traces its `ci` suite.
|
|
331
|
+
- Observe on several cores: `Simulator::set_parallel(true)` splits large
|
|
332
|
+
`observe_all` and `observe_selected` batches over the rayon thread pool, with
|
|
333
|
+
identical results. Off by default; needs the new default `parallel` feature.
|
|
334
|
+
`perf_baseline --parallel` times it.
|
|
335
|
+
- Refill a caller-owned buffer with `Simulator::observe_all_into` and
|
|
336
|
+
`observe_selected_into`. Observations are identical to `observe_all` and
|
|
337
|
+
`observe_selected`, but reuse the previous call's vectors; on Windows, bot
|
|
338
|
+
loops that observe every decision ran 1.8–3.5× faster than with `observe_all`.
|
|
339
|
+
`slither-sim serve` keeps one such buffer per session.
|
|
340
|
+
|
|
341
|
+
## [0.3.0](https://github.com/NikitaMGrimm/slither-sim/compare/v0.2.1...v0.3.0) - 2026-10-23
|
|
342
|
+
|
|
343
|
+
### Maintenance
|
|
344
|
+
|
|
345
|
+
- publish manual releases and reset the automatic timer
|
|
346
|
+
- clarify fidelity gaps and simplify navigation ([#46](https://github.com/NikitaMGrimm/slither-sim/pull/46))
|
|
347
|
+
- measure PRs only when measured inputs change ([#44](https://github.com/NikitaMGrimm/slither-sim/pull/44))
|
|
348
|
+
- separate maintained guides from research records ([#41](https://github.com/NikitaMGrimm/slither-sim/pull/41))
|
|
349
|
+
|
|
350
|
+
### Changed
|
|
351
|
+
|
|
352
|
+
- **Breaking Rust API:** replace `Config::realistic(n)` with `Config::official(n)`.
|
|
353
|
+
`Config::default()` and omitted JSON world settings now select the official
|
|
354
|
+
approximation, with population-driven radius and nonzero prey. Existing kiosk,
|
|
355
|
+
food-admission, sliding-boundary and retained-speed models remain enabled.
|
|
356
|
+
Use `Config::sandbox()` or explicit JSON settings for the previous compact,
|
|
357
|
+
fixed-radius scene. Model estimates and their limitations remain documented;
|
|
358
|
+
no exact official-server equivalence is claimed.
|
|
359
|
+
|
|
360
|
+
## [0.2.1](https://github.com/NikitaMGrimm/slither-sim/compare/v0.2.0...v0.2.1) - 2026-10-23
|
|
361
|
+
|
|
362
|
+
### Changes
|
|
363
|
+
|
|
364
|
+
- Bound food-sector clearing in bundled client frames, including preflight
|
|
365
|
+
validation, to avoid repeatedly scanning unrelated retained food.
|
|
366
|
+
- Bound minimap rasterization for extreme geometry while preserving ordinary
|
|
367
|
+
output, and reject frames exceeding the aggregate minimap decoding work budget.
|
|
368
|
+
- Reject protocol-19 simulation-client prey sizes that cannot fit the wire format.
|
|
369
|
+
- Index collision body bounds by stable snake slot and skip observation-index
|
|
370
|
+
construction when no selected snake is alive. Add reproducible offline
|
|
371
|
+
workloads, full-state parity traces and [fixture-specific performance reports](docs/performance.md).
|
|
372
|
+
- Add isolated observation-phase diagnostics, retained-client workloads and
|
|
373
|
+
optional whole-comparison deadlines with retained incomplete-run evidence.
|
|
374
|
+
- Automate compatible patch-release preparation and publication with a 12-hour
|
|
375
|
+
cooldown and protected checks for release-bot PRs; see [releasing](docs/maintainers/releasing.md).
|
|
376
|
+
- Add informational performance and fidelity comparisons to PR CI. Synthetic
|
|
377
|
+
comparisons do not establish official-server fidelity or general speedups.
|
|
378
|
+
- Reduce PR-comparison overhead and report reconnect work separately in
|
|
379
|
+
retained-client measurements.
|
|
380
|
+
|
|
381
|
+
## 0.2.0 (2026-10-23)
|
|
382
|
+
|
|
383
|
+
- Rust compatibility: `SimulationConfig` adds `local_records`, defaulting to
|
|
384
|
+
false. Update exhaustive struct literals or use `..Default::default()`.
|
|
385
|
+
The JSON protocol identifiers remain unchanged.
|
|
386
|
+
- Publish the current evidence-constrained host defaults: finite 1,500-unit
|
|
387
|
+
snake/prey coverage, retained food sectors, 136-cell minimaps and independent
|
|
388
|
+
minimap/leaderboard clocks. The compact default arena and provisional ecology remain
|
|
389
|
+
explicit; no exact official-server preset or overall accuracy is claimed.
|
|
390
|
+
- Retain paired-snake targets through bounded stale-pose pauses without granting
|
|
391
|
+
clean-route credit, and screen food-route corridors against complete received
|
|
392
|
+
bodies. Add controlled snake/food collectors, ordered sector diagnostics and
|
|
393
|
+
explicit paired capture budgets up to 3,600 seconds.
|
|
394
|
+
|
|
395
|
+
- Run declared paired-prey routes through the managed evidence collector and
|
|
396
|
+
verify route settings against the plan; retain process outcomes across audit errors.
|
|
397
|
+
|
|
398
|
+
- Move crossing acquisition's near waypoint inward and hold achieved endpoints
|
|
399
|
+
for observation; retain commanded hold offsets and release timing in metadata.
|
|
400
|
+
|
|
401
|
+
- Require fresh reference geometry before crossing endpoints advance; separate
|
|
402
|
+
the initial approach from completed legs and retain exact endpoint witnesses.
|
|
403
|
+
Record the paired visibility recheck's model failures without retuning physics.
|
|
404
|
+
|
|
405
|
+
- Hash and decode the same replay-source snapshot; retain protocol and tool
|
|
406
|
+
identities and distinguish replay-window checks from a full evidence audit.
|
|
407
|
+
|
|
408
|
+
- Compare verified evidence batches with bounded permutation tests and declared
|
|
409
|
+
exposure/effect gates; add manual, read-only CI intake for pinned bundles.
|
|
410
|
+
Keep measured calibration separate from synthetic prey/radius behavior tests.
|
|
411
|
+
|
|
412
|
+
- Keep empty food subscriptions internal and send per-connection minimap XOR
|
|
413
|
+
deltas when shorter. Add fixed diagonal collection routes and clarify the
|
|
414
|
+
source/evidence boundary, ecology models and offline collision rationale.
|
|
415
|
+
|
|
416
|
+
- Match the default prey turn setup to physics; give leaderboards independent
|
|
417
|
+
deadlines and bound prey reporting on gameplay broadcasts. Add an offline packet
|
|
418
|
+
census, source-pinned cadence fixture and generic localhost capture workflow;
|
|
419
|
+
keep recording ping timing through post-death observation and capture shutdown.
|
|
420
|
+
- Keep correcting predicted prey positions even when authoritative grid/motion
|
|
421
|
+
is unchanged, preventing drifting ghosts and later snap-backs.
|
|
422
|
+
- Use shared finite 1,500-unit snake/prey coverage and retained food-sector interest;
|
|
423
|
+
restore 136-cell minimaps with an independent clock. Require safe whole-body
|
|
424
|
+
admission for hosted startup, joins and respawns, with no cramped fallback.
|
|
425
|
+
- Make synthetic world-run records/victory entry opt-in (`localRecords`, default false).
|
|
426
|
+
|
|
427
|
+
- Restore source-linked pellet palettes, persistent ambient colors, birth types
|
|
428
|
+
and explicit pickup attribution from the earlier client presentation layer.
|
|
429
|
+
|
|
430
|
+
- Keep answering post-death pings so the stock browser's death fade and victory
|
|
431
|
+
entry do not trigger lag slowdown; document a local endpoint that survives Play Again.
|
|
432
|
+
- Continue opponent, food and prey updates through the stock death animation,
|
|
433
|
+
preserving broadcast cadence while suppressing repeated death and minimap reports.
|
|
434
|
+
|
|
435
|
+
- Keep configured prey sizes positive and within their bounds, ambient food
|
|
436
|
+
inside tiny arenas, and finite extreme respawn poses numerically usable.
|
|
437
|
+
- Disambiguate initial protocol timing headers and bound retained client bodies
|
|
438
|
+
and food with atomic frame rejection.
|
|
439
|
+
- Require the original v1 evidence source minimum and report replay targets
|
|
440
|
+
left unprocessed after early simulator death.
|
|
441
|
+
|
|
442
|
+
## 0.1.0 (2026-10-22)
|
|
443
|
+
|
|
444
|
+
- Deterministic headless Rust simulator with configurable worlds, geometric
|
|
445
|
+
observations and mechanics regression fixtures.
|
|
446
|
+
- Core-only library builds, selected-slot observations, supplied-body respawn
|
|
447
|
+
and runtime ambient refill-rate control.
|
|
448
|
+
- Portable bot frames (`slither-client-v2`) reconstructed by a shared
|
|
449
|
+
protocol-19 decoder, with simulator and WebSocket backends, receipt ages,
|
|
450
|
+
measured ping and simulated latency.
|
|
451
|
+
- JSON-lines interfaces for portable bots (`slither-client-json-v1`) and direct
|
|
452
|
+
world control (`slither-sim-json-v1`), with Rust, Python and JavaScript examples.
|
|
453
|
+
- Bounded shared-world WebSocket host with profiles, leaderboards, kill reports,
|
|
454
|
+
record messages and optional connection identifiers.
|
|
455
|
+
- Evidence tools for explicit-endpoint captures, decoding, auditing, recorded-input
|
|
456
|
+
replay and bundles containing frozen plans, attempt records and source snapshots.
|
|
457
|
+
- Offline worked study, documented fidelity limits, extraction provenance and
|
|
458
|
+
manual checks on Windows and Linux.
|
|
459
|
+
- Automatic pull-request checks, shared local/CI check commands, contributor
|
|
460
|
+
task guidance and protocol-labelled regression fixtures.
|
|
461
|
+
|
|
462
|
+
Interfaces remain experimental.
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Keep each PR focused on one problem. Discuss larger features or interface changes
|
|
4
|
+
with the maintainer before starting; small fixes can go straight to a PR.
|
|
5
|
+
Use one task, branch and worktree; preserve others' work.
|
|
6
|
+
Start with the [API guides](README.md#choose-an-interface) and
|
|
7
|
+
[rules and limits](docs/server-rules.md), or use the [documentation map](docs/README.md)
|
|
8
|
+
for research or maintenance tasks.
|
|
9
|
+
|
|
10
|
+
## Find the change
|
|
11
|
+
|
|
12
|
+
Paths are repository-relative. Read the guide, trace the source owner and callers,
|
|
13
|
+
then run the matching test.
|
|
14
|
+
|
|
15
|
+
| Task | Guide and source / tests | Focused check |
|
|
16
|
+
| --- | --- | --- |
|
|
17
|
+
| Mechanics, motion, food, prey | [Rules, limits and next steps](docs/server-rules.md#packaged-regression-evidence); `src/simulator.rs`, `src/physics.rs`, `src/prey.rs`; matching `tests/*.rs` and `tests/fixtures/` | `cargo test --locked --test movement_turns` (choose the affected test) |
|
|
18
|
+
| Custom Battledome rules and presets | [Battledome](docs/configuration.md#battledome); `src/simulator.rs`, `src/spawn.rs`; `tests/battledome.rs` | `cargo test --locked --test battledome` |
|
|
19
|
+
| Bot JSON API and lifecycle | [Client API](docs/client-api.md), [direct API](docs/bot-api.md); `src/main.rs`, `src/client/mod.rs`, `src/client/received.rs`; `tests/client_contract.rs`, `tests/client_runner.rs`, `tests/transport.rs` | `cargo test --locked --test client_contract` |
|
|
20
|
+
| In-process C ABI | [C ABI](docs/c-api.md); `ffi/src/lib.rs`, `ffi/include/slither_sim.h`, `examples/ffi_bot.py`; `ffi/tests/abi.rs` | `cargo test --locked -p slither-sim-ffi` |
|
|
21
|
+
| Python package | [Python package](docs/python.md); `python/src/lib.rs`, `python/slither_sim.pyi`, `python/examples/`; `python/tests/test_session.py` | `uv run --locked --only-group tools python -m maturin build --locked -m python/Cargo.toml`, then `python python/tests/run.py target/wheels` |
|
|
22
|
+
| Wire decoder and local host | [Server guide](docs/raw-server.md); `src/client/protocol.rs`, `src/client/server.rs`; `tests/client_protocol.rs`, `tests/client_server.rs` | `cargo test --locked --test client_protocol` |
|
|
23
|
+
| Capture, audit and recorded replay | [Research workflow](docs/research-workflow.md); `tools/fidelity/evidence.py`, `tools/fidelity/prepare-fidelity-replay.py` and adjacent tests; `examples/fidelity_replay.rs` | Matching Python/Node test; `cargo test --locked --example fidelity_replay` for Rust replay |
|
|
24
|
+
| Core library / WASM consumer | [Configuration](docs/configuration.md), `examples/basic.rs`; `src/lib.rs`, `src/observation/mod.rs`; `tests/core_consumer.rs` | `cargo test --locked --no-default-features --test core_consumer`; explicit `wasm` group for target changes |
|
|
25
|
+
| Simulator or client performance | [Performance](docs/performance.md), [workloads](docs/performance-workloads.md); `examples/perf_baseline.rs`, `tools/perf_compare.py`, `tools/perf_build.py`; `tools/test_perf_*.py` | `cargo test --locked --example perf_baseline`, or the matching Python test; measure when claiming a speed change |
|
|
26
|
+
| Documentation | Relevant guide and its linked source/examples | `python -B -m unittest discover -s tools -p test_documentation.py`; no research dependencies |
|
|
27
|
+
|
|
28
|
+
## Setup and checks
|
|
29
|
+
|
|
30
|
+
Run focused tests first, then the relevant group from the repository root.
|
|
31
|
+
Rust needs Rust 1.99+ and platform build tools; the check runner uses
|
|
32
|
+
standard-library Python 3.11+. Documentation-only changes need accuracy/link
|
|
33
|
+
review and the documentation test above, without a Rust build.
|
|
34
|
+
|
|
35
|
+
| Group | Command | Coverage / prerequisites |
|
|
36
|
+
| --- | --- | --- |
|
|
37
|
+
| Rust | `python tools/check.py rust` | `lint` (formatting; Clippy on default, core-only and single-feature builds) then `test` (default/core-only/bot-only/networking/C ABI tests, doctests and a Python crate build); no uv or Node |
|
|
38
|
+
| Tools | `uv run --locked --only-group tools python tools/check.py tools` | Python/Node tests, local bot/C ABI smoke tests and Python package tests; Python 3.12, uv, Node 22+ (24 recommended) and Rust |
|
|
39
|
+
| Package | `python tools/check.py package` | Local crate verification; no registry publication |
|
|
40
|
+
| WASM | `python tools/check.py wasm` | Core-only and bot-only target checks; install `wasm32-unknown-unknown` first |
|
|
41
|
+
|
|
42
|
+
Before the tools group, run `uv sync --locked --only-group tools`. `all` runs
|
|
43
|
+
`rust`, `tools` and `package`; WASM is explicit. Append `--list` to inspect commands
|
|
44
|
+
without running them. Commands report their time; CI adds a job-summary timing
|
|
45
|
+
table. Tests use doubles or loopback, never outside game servers.
|
|
46
|
+
PR CI runs the same runner automatically: `lint`,
|
|
47
|
+
WASM and package once on Linux, `test` on Linux, Windows, macOS and Rust 1.99,
|
|
48
|
+
and `tools` on Linux, Windows and macOS. The weekly
|
|
49
|
+
[extended checks](https://github.com/NikitaMGrimm/slither-sim/blob/main/.github/workflows/extended.yml) add release-profile tests,
|
|
50
|
+
Linux ARM tests and a RustSec audit; they block nothing and can be dispatched.
|
|
51
|
+
|
|
52
|
+
The tools group's fidelity suite includes transport measurement regressions
|
|
53
|
+
(`tools/fidelity/test_transport_parity.py`). Run them alone with
|
|
54
|
+
`uv run --locked --only-group tools python -B -m unittest discover -s tools/fidelity -p test_transport_parity.py`.
|
|
55
|
+
The [local transport check](docs/research-workflow.md#transport-parity) is an
|
|
56
|
+
explicit measurement, separate from unit tests. Record current-host gate failures
|
|
57
|
+
as baselines; do not loosen official tolerances.
|
|
58
|
+
|
|
59
|
+
## Evidence proportional to the change
|
|
60
|
+
|
|
61
|
+
- Explain the problem and resulting behavior with a reproducer, relevant tests
|
|
62
|
+
and, when useful, a short before/after example such as a request and response.
|
|
63
|
+
- **Documentation:** review accuracy and links against current sources.
|
|
64
|
+
- **Tool/API fixes:** minimal reproducer and regression using existing evidence
|
|
65
|
+
or clearly labelled synthetic inputs; no fresh capture required.
|
|
66
|
+
- **Behavior-preserving optimizations:** demonstrate output parity on relevant
|
|
67
|
+
cases; provide matched before/after measurements only when claiming performance.
|
|
68
|
+
- **Mechanics corrections:** cite supporting evidence and add a focused regression
|
|
69
|
+
fixture. Collect more only if existing evidence cannot support the correction.
|
|
70
|
+
- **New empirical or fitted claims:** follow the [research workflow](docs/research-workflow.md)
|
|
71
|
+
with the complete relevant study, failed/inconclusive attempts, selection rules,
|
|
72
|
+
uncertainty and applicable held-out validation. Explain inapplicable methods;
|
|
73
|
+
do not add ceremonial requirements.
|
|
74
|
+
|
|
75
|
+
The [evidence comparison workflow](docs/research-workflow.md#compare-contributed-evidence)
|
|
76
|
+
screens contributed bundles for declared reporting differences; its statistical
|
|
77
|
+
report supports review without approving physics changes or replacing fixtures.
|
|
78
|
+
|
|
79
|
+
Keep bounded, selected [regression fixtures](https://github.com/NikitaMGrimm/slither-sim/blob/main/tests/fixtures/README.md#selecting-and-updating-cases)
|
|
80
|
+
in Git; keep full recordings, credentials and generated outputs outside it.
|
|
81
|
+
Use Conventional Commits and LF; avoid unrelated formatting. Maintainers review
|
|
82
|
+
ownership, callers, contracts and evidence independently of contributor tests;
|
|
83
|
+
passing tests alone is not acceptance. Collection or publication needs separate
|
|
84
|
+
authorization.
|
|
85
|
+
|
|
86
|
+
Preserve third-party license notices. For external data, note its source and any
|
|
87
|
+
sharing restrictions in `REPORT.md`.
|
|
88
|
+
|
|
89
|
+
A maintainer reviews the current revision and evidence before merging. Required
|
|
90
|
+
CI must pass with latest main; new commits need relevant checks and renewed review.
|
|
91
|
+
Auto-merge can then finish an approved PR. Independent agent review is useful
|
|
92
|
+
evidence, but agents cannot approve their GitHub account's own PR. The owner-authorized
|
|
93
|
+
[release automation](https://github.com/NikitaMGrimm/slither-sim/blob/main/docs/maintainers/releasing.md) can merge compatible patch release PRs
|
|
94
|
+
containing only version/changelog metadata after required CI. Other release
|
|
95
|
+
bumps require maintainer review and merge; publication then runs automatically.
|
|
96
|
+
|
|
97
|
+
For geometry or motion changes, optional before/after plots, diagrams or clips
|
|
98
|
+
can help. Attach or link PR-only media; do not commit it.
|
|
99
|
+
|
|
100
|
+
## Rationale and evidence
|
|
101
|
+
|
|
102
|
+
Keep non-obvious reasons, units, invariants and model limits beside the owning
|
|
103
|
+
code. Link formulas/defaults to their declarations instead of repeating them in
|
|
104
|
+
an agent guide. Brief comments should label rules as measured,
|
|
105
|
+
protocol/client-derived or provisional and link canonical notes/regressions when useful.
|
|
106
|
+
|
|
107
|
+
Keep current instructions in `docs/`. Put dated studies and selected results in
|
|
108
|
+
`research/<topic>/YYYY-MM-DD-<question>/REPORT.md`; follow the
|
|
109
|
+
[research index](https://github.com/NikitaMGrimm/slither-sim/blob/main/research/README.md) for placement and access labels.
|
|
110
|
+
Evidence notes/fixtures own methods, source/archive hashes, selected windows,
|
|
111
|
+
failed cases and uncertainty. Tests consume selected fixtures; synthetic cases
|
|
112
|
+
establish their stated contract. Change a rule's owner, linked evidence and
|
|
113
|
+
focused regression together. Preserve historical plans and contradictory results;
|
|
114
|
+
do not regenerate expectations to agree with new code.
|
|
115
|
+
|
|
116
|
+
## AI assistance
|
|
117
|
+
|
|
118
|
+
Review and verify AI work. End the PR description with a short footer naming
|
|
119
|
+
actual models, harnesses and roles, including material delegated work.
|
|
120
|
+
Use display names; report review and checks accurately. Example:
|
|
121
|
+
|
|
122
|
+
> [!NOTE]
|
|
123
|
+
> 🤖 **Agent assistance: GPT 6.1 Sol via Codex** — implementation; supporting work (verification).
|
|
124
|
+
|
|
125
|
+
Group credits by harness in one closing note. Neither transcripts nor a reviewer
|
|
126
|
+
quota are required.
|
|
127
|
+
|
|
128
|
+
## Interfaces and packaging
|
|
129
|
+
|
|
130
|
+
Interfaces are experimental. Incompatible bot changes require a new
|
|
131
|
+
[contract identifier](docs/client-api.md#interface-versions), updated examples
|
|
132
|
+
and the JSON contract fixture. Keep units, field meanings and lifecycle behavior
|
|
133
|
+
consistent; readers ignore additional response fields. Physics changes can alter
|
|
134
|
+
trajectories without changing the API.
|
|
135
|
+
|
|
136
|
+
The root `Cargo.toml`'s `[workspace.package]` owns the simulator version, inherited
|
|
137
|
+
by the C ABI crate and Python package; `pyproject.toml` owns the tools version.
|
|
138
|
+
Within `0.x`, incompatible Rust API changes bump the minor version. Group
|
|
139
|
+
unreleased changes in the changelog; no permanent freeze or multi-version support
|
|
140
|
+
is promised.
|
|
141
|
+
|
|
142
|
+
Write one user-facing changelog entry per change, with a link to its PR when
|
|
143
|
+
useful. Avoid repeating generated commit titles in a second prose list.
|
|
144
|
+
|
|
145
|
+
The `package` check builds the local crate. It ships the library, binary,
|
|
146
|
+
user guides and examples, the release guide and the fixtures its unit tests read;
|
|
147
|
+
integration tests, other fixtures, evidence tools, schemas and other maintainer
|
|
148
|
+
files require the Git checkout.
|
|
149
|
+
[Historical provenance](docs/provenance.md) records imported components and adaptations;
|
|
150
|
+
routine edits do not refresh import hashes. Per-study source pins remain required.
|
|
151
|
+
Do not publish releases, change repository visibility,
|
|
152
|
+
collaborators or licensing without the owner's authorization.
|