Okay scratch all of that.
I extended AuditEventListener to figure out what exactly is going on in the audit event lifecycle, and I noticed that PostUpdate events were in fact being fired. The problem was Grails allows for a combination merge and flush in one method call. I needed to reverse that practice, call merge with the flush flag specifically set to false, and then call save(...) once at the end of the workflow. Only then will the changes and the audit be serialized together.
With that solved, Envers is great!