I agree a data modelling update would be my first thought; it may be sufficient for the testing you’ve done to date, but DAX can return some unpredictable results from a model with bi-directional relationships and relationship between fact tables.
That being said, if the only issue you have is that you want the (blank) [Sort Order] sorted last, you could simply add a calculated column to the [Budget] table to set blanks to an arbitrarily large number, like.
Sort Order 2 =
ISBLANK( Budget[Sort Table.Sort Order] ),
Budget[Sort Table.Sort Order]
, then sort the [Cost Item] colum by the new [Sort Order 2] column.
I’m sure I’m missing something, as I’d expect you’ve already tried and discarded this, but thought I’d post it anyway.