Trying to gain more understanding of this issue, and as I see it, the full story wrt linefeed-treatment='preserve' and hyphenate='true' is:
1) for blocks of text containing preserved linefeeds, the TextLayoutManager actually generates multiple Paragraphs (see TextLM.getNextKnuthElements() -> in case of an explicit break, the 'current' sequence is ended, and a new one is added to the returnList)
2) the optimal line-breaks are determined by the LineLayoutManager per Paragraph ( see LineLM.createLineBreaks() )
3) the hyphenation-points are determined for each Paragraph in the same loop ( see LineLM.findOptimalBreakingPoints() )
4) BUT: the integration of hyphenation-points (applyChanges() and getChangedKnuthElements()) operate on the TextLayoutManager instance as a whole.
=> the entire content generated by the TextLM in question is copied as many times as there are paragraphs/preserved linefeeds in the source
Mainly TextLM.getChangedKnuthElements() is a bit problematic in this regard: every time this is called, it generates an element-list based on the complete set of AreaInfos for the LM. In LineLM.findHyphenationPoints(), each of the original paragraphs is replaced by that list.
I already tried to change that method to take into account the position-indices of the first and last element in the parameter oldList. This already gets me somewhat further, but still far from committable...