TransactionOnlyPomModel
The one service a core environment is missing before PSI can be written. Every mutation routes through ChangeUtil.prepareAndRunChangeAction → PomManager.getModel(project).runTransaction(...), and a core project has none: the real PomModelImpl lives in platform/core-impl, which the embedded compiler does not carry, and nothing in the compiler registers one because the compiler only ever reads PSI.
Running the transaction and stopping there is the point, not a shortcut. What the real implementation adds is PSI change event dispatch and a reparse, and neither is wanted: the reparse is a known cost under repeated edits, and analysis learns that a file changed by polling its modification stamp — which the tree surgery bumps by itself — rather than by listening.