This just dawned on me. There are two normalized message formats, and only historical reasons why. We waste a bunch of developer overhead converting back and forth.
DonationInterface\DonationQueue::buildTransactionMessage creates the legacy ActiveMQ pipeline using a snowflake format where fields are given non-normalized keys. For example, the normalized first_name field is called fname in the queue messages.
The new queue code, on the other hand, passes normalized messages.
One approach would be to make wmf_civicrm able to import either the old queue format or regular normalized messages. Then, rewrite DonationQueue to emit normalized messages.