SIGN IN SIGN UP

pbz: Chunk 30 — a failed save() says what it left on the device

Post-publish item 8. run() and save() change what the wall is showing on
their first step and finish several steps later, so a failure in between
left the device holding something nobody asked for and said nothing
about it.

Item 8's framing was too narrow. The zero-frame throw it names is one of
four failure points past the moment the wall changes, and not the worst:
nothing in pbz except run/save themselves sends {pause:false}, so a
failure in the pause window leaves a dark wall and no obvious verb.
run() has the identical window and is fixed with it.

The line order is the honesty rule: a maybe- state is assigned before
its send, a bare state after the device's own ack, so a claim can be
checked without reading the prose. Errors are annotated in place rather
than re-wrapped, because Chunk 29's transport errors carry a cause and a
recovery pointer that a new Error would flatten. e.device = {state, id}
rides along for library callers; its absence means nothing was sent.

Live-verified on the spare, and it corrected a message: pause DOES
survive the client disconnecting (fps 0.00 five seconds after close), so
the frozen-wall hazard is real; both printed recoveries work; but a
truncated putSourceCode leaves NO entry rather than a damaged one, so
maybe-saved now says the truer thing.

12 new tests (204 total), typecheck green. Every message asserted for
what it claims and what it must not claim.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PZnUXRsLLnt2A7pR3X4Luj
T
Tarek Rached committed
d042669fbd77842b2835cdb625fd42c4c58da1c5
Parent: 5699f36