One of the least exciting SkyeEngine problems turned out to be one of the most important: deciding what a conversation actually is.
Plain user and assistant text is easy. Real training data also contains hidden reasoning, tool definitions, calls, results and sometimes several assistant turns. One provider returns tool arguments as an object, another stores the same thing as a JSON string. Some sources have stable IDs; others only have a position in a file.
I gave those parts a canonical representation and each assistant turn its own identity. A judge can now point to the exact turn and channel containing a problem, and a repair does not have to hope that array item three still means what it meant before another transformation.
This also made structural failures much easier to catch. Duplicate calls, missing tools, orphaned results and conversations which stop halfway through an exchange are rejected before they quietly become training data.