Public: anyone can read this; the crew can change it.
The frame the round publishes: `src/frame.ts`, a world in and 4 KB out #71
Check · Review · Land · Live done — Landed and live in production.
Pushed. Here's the pull description:
shipped production is serving it deploy feb7d92
Sign in to join this conversation.
Pushed. Here's the pull description:
---
src/frame.tsis one pure function — a world plus the round's clock and id in, aFrameout — and the only place the sea's numbers become the wire's. Every stride, scale and cap comes fromsrc/protocol.ts, every sea number fromsrc/world.ts, the roster cap fromsrc/concept.ts; there is no second table of scales here, and no import of a socket, a bus or a database.The three translations it owns, each argued in the module header and tested:
VELOCITY_SCALEholds per second, so a velocity that meant units/s would clamp in ordinary play. Velocities and currents go out multiplied byDT(the protocol's own "1/256 of a unit per tick"), which makes the wire'sFIELD_MAXof 8 mean 160 units/s — the top of the range play lives in. The alternative, mapping the sea's own 600-unit clamp onto 8, is a cap a lane never approaches and would squash every readable current into the bottom quarter of the scale, below the "a twentieth of full scale draws nothing" line the look section sets.THRUST_MAX— becauseTHRUST_MAXis 12.5 units/s² and would saturate the ±4 thatTHRUST_SCALEleaves; a share of full thrust is also the number a door can draw.Clamping: every linear quantity saturates at the range its scale leaves in an int16, by vector magnitude, so a clamped velocity or current still points where it pointed instead of being squared off component by component; angles wrap, because an angle is a circle. It is clamped in the builder and not only in the encoder so a door holding the object in-process sees exactly what a door holding the bytes sees. Worst rounding error after the wire: 0.125 sea units for a position (inside the quarter-unit promise interpolation rests on), 0.039 units/s for a velocity, ~0.63 units/s for a current, π/65536 rad for the gate.
MOTE_STUNNEDis the only flag set — the beached bit is #67's and is named in a comment rather than invented here.Measured, on this branch: a full frame — 24 motes, a field driven to the sea's own cap — is 924 bytes of the 4096 allowed, and builds in 44 µs, about a thousandth of the 50 ms tick. In that extreme braid 21 of 256 wire cells saturate at
FIELD_MAXand the mean cell sits at 1.82 of 8; that is the sea's hottest hour, and saturating there is what the wire is designed to do.Names are not on the binary wire, so they ride the built frame as
names, in roster order (the world's own mote order —addMoteappends,removeMotesplices), truncated atNAME_MAXwith control characters removed; escaping stays each door's job. A door can diff two frames by index and never match by name.Not in here: who is in the roster, admission, spectators, when a frame is sent, and what
clockcounts — #8, #53 and #58 own those; the frame carries the number it is handed. Outsidesrc/frame.tsand its test I touched only a README row and a paragraph insrc/protocol.ts's header pointing at where the units are written down, so the next decoder (#60) does not have to guess them.To look:
src/frame.test.tsis where the argument is — the averaging tests, the clamp-not-wrap tests, and the byte and microsecond counts, which print their real numbers in the assertion message.bun run testis green (132 tests).🤖 Generated with Claude Code
Closes #66