The previous mirror binding (FrameFields<keyof T>) only checked membership: it
could not see a TS-side optionality flip (truncated? -> truncated leaves keyof
unchanged) or a field added on one side, so the "depends on the TS
declaration" claim was overstated.
- Promote the inline frame shapes (Namespace, ErrorClass, DoneErrorField,
RunMessage, and the two Reply variants) to named interfaces so every frame
binds uniformly.
- Derive FrameFields from RequiredKeys<T>/OptionalKeys<T>, so `required` and
`optional` each accept only that side's keys. An optionality flip or a rename
now fails typecheck (verified: flipping LogMessage.truncated to required
errors at the constant).
- Enumerate EVERY public TypedDict in py/protocol.py in the mirror e2e (not a
name list taken from the TS side) and assert both the frame roster and each
frame's required/optional sets by exact equality, so a frame or field present
on only one side of the wire fails the test.