{{- range where .Site.Menus.main ".Post" "left" -}}
I am pretty sure I would try with post and .Post before landing on Post.
The way I remember is, that the variables of the menu only exist inside of menu templates (“loops”). That means that may be inside of a range you have no menu object “resolved” and thus no .Post variable available that you could test to, resulting in the range returning false for each item. This might be why you found the first two liner template. Inside of the range you have the menu variables available, but not when the range is executed… But that is just an idea, not based on knowledge
I did a quick check on all my templates and always have only a range .Site.Menus.name for all menus.
What is the difference between what is returned by "left" and (safeHTML "left")? I don’t see anything that might be different in what that change gives back? There is no HTML in that string and nothing that would be escaped. Is there anything that is returned additionally like a marker that the string has a certain meaning that is used by the range function?