Two gaps from the previous round's fixes:
- checkDoneValue flagged a non-lossless number but skipped counting its encoded
bytes, so a value over budget ONLY through that number classified as
non-lossless instead of over-budget (e.g. [Infinity] at cap 3, whose encoding
is 10 bytes). Count the scalar's bytes even when flagging, so the budget check
wins as the JSDoc promises. Add cap-3 regression cases.
- The mirror e2e compared the Python TypedDict keys against a hand-written
constant, so a field change on the TS side alone would not fail it, and the
reply frames were not probed at all. Introduce WIRE_FRAME_FIELDS in
protocol.ts, bound to each frame interface's key set via `satisfies` (a
renamed/removed field breaks typecheck — verified), and drive the mirror test
from it, now covering ReplyOk/ReplyErr too. The test therefore fails on
one-sided drift from either language.