@mnvwvnm was on the right track. The big issue was that I was sorting by links (k.file.link) instead of names (k.file.name). I believe link sorting was using the full path which isn’t what I wanted. Sorting by k.file.name fixed that.
It appears the sort is preserving order for equal items (meaning that if when doing a sort, if two items are equal, then they are left in the same order as they were found). This means that what I need is:
group.rows
.sort(k=>k.file.name, 'asc')
.sort(k => k.rating, 'desc')
.map( ... )
The first sort sorts all of the items alphabetically. The second sort sorts them by ratings with the highest rating first. If there are multiple items with the same rating, then the old name order is preserved so within each rating, the items are sorted by name.