@solidrt/cli 0.0.53 → 0.0.55

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/AGENTS.md CHANGED
@@ -11,7 +11,9 @@ bundled `flux` runtime, not on Bun. Invoke via `bunx srt <command>`.
11
11
  The dev loop against a running app is pause_watch -> edit -> reload ->
12
12
  resume_watch -> get_logs -> get_snapshot, with mute_user_input while you
13
13
  measure or test and unmute_user_input after; agents/debugging.md has the
14
- why of each hold. `reload` surfaces build errors but not type errors:
14
+ why of each hold. Several clients may be attached at once: `reload` reaches
15
+ all of them, while call_debug / send_input / get_snapshot are per client
16
+ (debugging.md). `reload` surfaces build errors but not type errors:
15
17
  `bunx srt check` is for those.
16
18
 
17
19
  agents/ carries the depth this one leaves out; read the one that matches
@@ -156,20 +156,28 @@ when exactly one client is connected.
156
156
  window root.
157
157
  - `/texture?id=<textureId>` - same shape and options as `/snapshot`, at the
158
158
  texture's native size (a scene or shader target behind a `<texture>` leaf).
159
- - `/gpu?label=<text>` - the GPU resource inventory; `label` keeps only the
160
- resources created with exactly that label (ids change on reload, labels
161
- do not).
159
+ - `/gpu?label=<text>&draw=<id>` - the GPU resource inventory; `label` keeps
160
+ only the resources created with exactly that label (ids change on reload,
161
+ labels do not). Each texture carries its `format` and declared `sampler`
162
+ (`filter`/`wrap`/`mipmap`/`anisotropy`), the creation-time state a soft
163
+ or aliased map is usually missing. A draw target's entries report uniforms wider than a vec4
164
+ (matrices) as their length, `"[16]"`; `draw` names the one entry (ids are
165
+ per target, so pair it with `label`) reported in full.
162
166
  - `/buffer?id=<bufferId>&offset=<n>&length=<n>&as=<f32|u16|u8>` - vertex
163
167
  buffer contents (default f32; reads cap at 64 KiB).
164
168
  - `/stats?window=<ms>` - the performance statistics. POST
165
169
  `/stats?active=true|false` switches the on-screen stats overlay instead
166
170
  (the `set_stats_overlay` tool): one client with `&client=<id>`, every
167
171
  client (and the setting new clients join with) without; `/clients`
168
- reports each client's `stats`. `frames` counts the frames actually
169
- rebuilt in the window, `fps` the refresh rate presented at: when motion
170
- looks wrong and `fps` looks fine, `frames` is the number to read - a
171
- picture that only changes 26 times a second shows 26 there, and the
172
- stutter is the app's update cadence, not the engine's.
172
+ reports each client's `stats`. `frames` counts the frames that changed
173
+ the picture: tree rebuilds, plus GPU content changes presented without
174
+ one (a layer write, a shader param, an upload - a sprite or shader app
175
+ rebuilds nothing, every frame of it is one of these).
176
+ `fps` is the refresh rate presented at: when motion looks wrong and `fps`
177
+ looks fine, `frames` is the number to read - a picture that only changes
178
+ 26 times a second shows 26 there, and the stutter is the app's update
179
+ cadence, not the engine's. `frames: 0` means the picture did not change
180
+ at all in the window.
173
181
  - `/debug` - the app's registered debug commands; POST
174
182
  `/debug?name=<cmd>` with a JSON body as its args to call one.
175
183
  - POST `/input` with `{ "events": [...] }` - synthetic input through the
@@ -263,6 +271,21 @@ The loop is the same as over MCP: `/reload`, then `/logs?since=`, then
263
271
  Math.min(dt, cap) lets it through, and one bad frame can corrupt anything
264
272
  integrated from dt (positions fly off, accumulators go so negative they
265
273
  never recover). Math.max(0, Math.min(dt, cap)) costs nothing.
274
+ - A fixed-timestep simulation on that clamped dt still drifts: no panel
275
+ presents at exactly its nominal rate (a "60 Hz" panel measured 60.3) and
276
+ the paced tick tracks the real cadence, so a 16.667 ms step against a
277
+ 16.59 ms average dt comes up one step short every few seconds - one frame
278
+ runs no step (freeze), the next runs two (jump), and frame jitter
279
+ scatters which frame it lands on, so it reads as random stutter. The
280
+ runtime hands every callback the refresh rate,
281
+ `onFrame((tick, frame, rate) => ...)` (SDL's nominal Hz): when the step is
282
+ within a few percent of `1000 / rate`, run whole steps per frame
283
+ (`Math.round(dt / STEP_MS)`, clamped to [0, cap]) so the world rides the
284
+ refresh; only accumulate (`acc += dt; while (acc >= STEP_MS) ...`) when
285
+ the display is genuinely off-rate (50, 120, 144 Hz), or interpolate the
286
+ render by `acc / STEP_MS` if the game does not snap to whole pixels. It
287
+ is invisible in a five-second look and survives every renderer
288
+ optimisation; measure it with a steps-per-frame histogram, not by eye.
266
289
  - A registered onFrame is a standing request, not demand-gated: it re-requests
267
290
  the next frame every time it runs, so the runtime keeps calling it - and
268
291
  presents - every frame at the refresh rate until you deregister it (fps