I really wonder why is it so common for people to default to JSON even when designing complex cryptographic protocols like this. I was skimming the spec for the script interpreter, which is something you'd expect would be focused on compactness, but it seems like it's designed entirely around JSON semantics and concepts, which means any implementation necessarily carries along this complexity. This isn't to say that JSON is bad, but to put it at the absolute core of the data model seems problematic. This problem happened with Matrix when they started having to layer JSON around base64-encoded-encrypted-JSON and generally the looseness of the format infecting the entire data model of the protocol.
Like the SPMessage format here too, uses JSON.stringify to indicate structure encoding, which necessarily implies that any implementation of the protocol is bringing along needing to handle JSON semantics. JSON does not seem to be well-suited here as it doesn't composing cleanly in the way a data structure defined in terms of bytes would.