From the comments: "This was caused by a floating point rounding error. A unit switching jobs internally becomes a different unit (i.e. a monk with a relic becomes a monk without a relic), and when doing that, HP is scaled proportionally based on the old and new max HP using 32-bit floating point maths." And there are YouTube videos about this https://www.youtube.com/watch?v=MytWNbpnAVY
> The formula was probably `return new_maxhp * (old_hp / old_maxhp);` ... > Due to floating point rounding errors, convert_hp(1, 55, 55) equals 0.999999940395355224609375, which is less than 1, which means the unit dies. Ahh. The old "Multiplying and dividing is associative... for the set of reals, not for the subset that you can actually afford to compute with." So it should have been `(new_maxhp * old_hp) / old_max…
Psstt... Dividing is not associative for the reals.