Thanks for the input everyone. I'll try to comment on each discussion point:
1) garbled output in large queries
I messed around with a few things, and have not been able to recreate any issues. Can you provide a test case for this? Also, any other interesting things about your terminal, like your $TERM setting, locale, etc. (I'm using xterm with UTF-8, and KDE's Konsole app)
2) %M vs shell call
%M on when connected to the local machine displays the string "[local]" which I didn't like. I wanted a real hostname to show no matter which client/server pair I was using. Zero chance for mistaken commands on the wrong host. Many times we ssh to a remote server, then run psql locally.
Perhaps the more elegant route here, is to change psql's behavior with %M when connected to the local machine? (This would also solve point #3)
3) a forked process for every prompt
While this also isn't very elegant, it seems to work fine. It's not something to worry about these days when the server has 40 cores. ;-) But, I've noticed that different distros store lsof in different locations, so per-environment tweaking might be necessary.
It would be nice if there was a way to do some kind of templating script with the psqlrc file. Something that would dynamically generate the "\set PROMPT" commands on psql startup, rather than calling out to a shell every command. (I'm thinking along the lines of ERB for Ruby, Django for Python, etc.)
But again, I think the more elegant approach is to alter the %M logic.