Ok, turns out category table is the way to go. There are already category tables defined for my use case: "Not at eol”(>), "Not at bol”(<) and “line breakable”(|). They are used for filling but are just as appropriate as for wrapping. Now there seems to be two routes: one is to directly use category tables to determine whether to wrap, one is to still use text property to determine whether to wrap, and use category table to apply text property. Which approach is more efficient?
Besides efficiency concerns, using text properties allows use cases described by Ihor, where user can customize on what to wrap and what not to. That seems nice.