The encoder for this exact (id, version), or null. Never a near match.
Every registered id@version, sorted — for diagnostics when a lookup fails.
Add an encoder. Refuses to replace an existing (id, version): two different functions under one name is exactly the condition that makes a recorded request unreconstructable, and it should fail where the collision is introduced rather than where a verdict later comes out wrong.
A lookup from (id, version) to encoder.
A class rather than a module-level mutable map so that derivation can be run against an EXPLICIT set of encoders. A verifier that silently depended on whichever adapters a process happened to have imported would give different verdicts in different hosts, which is the opposite of what a verifier is for.