As often happens in online forums, I discover a solution after I've posted a request for help. The problem is in texMate.py.
/Applications/TextMate.app/Contents/SharedSupport/Bundles/ LaTeX.tmbundle/Support/bin/texMate.py
It tries to be smart and pick the right TeX engine based on presence of a select few packages in the contents of the file. Only if this fails does it use the user's preference. Not only that, if it passes the test for 'latex' it does not even try to check for xelatex.
For example, if I include the packages pstricks and fontspec, texMate.py will see pstricks and immediately choose to use latex, which subsequently dies when fontspec (a xelatex package) is encountered. Take out pstricks, and it will use xelatex.
This heuristic looks pretty broken to me. The preference setting should always take precedence. If we want to keep this dubious auto-detection code, we should add 'auto-detect' to the list of engines in preferences and only do the auto-detection if this is the selected preference.
Thoughts?