Funny how you understand something as soon as you post it.
The compiler takes (127 + 30) and performs signed 8-bit arithmetic, yielding -99. Casting as a signed (int) duly kept the sign: -99. Casting as an unsigned char reinterpreted the value as 157, which was then cast as a signed int: 157.
My error was in assuming that constants were treated as unsigned chars, but they are treated as signed chars.
There’s a compuler option for that. Project>Build Options…>Project. Go to MPLAB C18. check “Treat ‘char’ as unsigned” (under Category General). The command-line flag is ‘-k’