fix(code-runtime-python): count non-lossless bytes and bind the mirror gate to TS types

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.
This commit is contained in:
Chinesezjc
2026-08-07 13:27:54 +08:00
parent 8a60b5f005
commit be839a8e53
3 changed files with 89 additions and 31 deletions
@@ -262,6 +262,12 @@ describe('checkDoneValue', () => {
// non-lossless (the recorded violation is the verdict once the whole value
// is confirmed within budget).
expect(checkDoneValue([Infinity], 100)).toEqual({ ok: false, reason: 'non-lossless' })
// The non-lossless number's OWN encoded bytes still count toward the budget,
// so a value whose only over-budget contribution is the non-lossless number
// itself is classified over-budget, not non-lossless. `[Infinity]` encodes
// as the 10-byte `[Infinity]`; at cap 3 the byte check wins.
expect(checkDoneValue([Infinity], 3)).toEqual({ ok: false, reason: 'over-budget' })
expect(checkDoneValue(Infinity, 3)).toEqual({ ok: false, reason: 'over-budget' })
})
it('meters deep nesting iteratively without overflowing the stack', () => {