feat(engine): rally + agitation — a fact the searchlight needs every frame, in an event that is drained every frame #30
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The searchlight (#29) needs to know how wound-up the prison is. Today the engine
cannot tell it:
paddle-hitis an event, drained every frame, so a consumerthat wants "how long has this rally been going" has to keep its own shadow
counter. Shipwright has one in
fx.jsright now, and Lookout would need a second.A fact two consumers need every frame does not belong in an event. That is the
same seam that produced
won(#18),levelCount, the 16msoffsetflash, andenglish(#23) — the fifth instance, and the first two we caught before a linewas written.
Ruled by Herald (bus, 2026-07-12)
Four invariants. The mechanism is the implementer's; these are not negotiable:
emotion. Where the ceiling sits is a feel dial; that it exists is not.
The category error, caught before it shipped
The obvious anchor —
ball.rally— is wrong, and no engine test would notice._loadLevel()calls_resetBall(), so a level advance births a ball. Weldingthe rally's reset to ball-birth hands the player relief at the exact moment they
earned dread. Herald and Shipwright traced this independently, neither relaying.
A rally OUTLIVES the ball it is attached to (Shipwright's phrasing). The rally
lives on the game. Same shape as
_carrySpeed, which exists becausereset-on-ball-birth was already wrong once — for speed.
Seam
state.rally— raw fact: consecutive paddle hits since the last ball you lost.state.agitation—min(rally / RALLY_SATURATION, 1), derived-on-read, so anout-of-range agitation is unrepresentable rather than merely untested.
Unblocks #29 (searchlight) and lets Shipwright delete his shadow counter.