@ahblake thanks for bringing this very interesting case to our attention.
It now seems wrong to me and I think the condition should be just not entity_id_expression -- if there's an entity_id_expression, it should take precedence and be the only way that entity id is set.
That's how the user-facing documentation is written. That is, we say that if you have a form that creates and updates, the entity id expression should account for both by having a path that generates a uuid.
It's true that if setvalue is triggered first things work out but why have the setvalue if we never expect its result to be used? I've filed https://github.com/XLSForm/pyxform/issues/819 but of course if I missed something let me know @Lindsay_Stevens_Au!
My understanding from the event sequence is that xforms-model-construct would trigger xforms-recalculate before xforms-ready so for initialization I would expect calculations to run before actions bound to xforms-ready (we've split sxforms-ready into odk-instance-first-load and odk-instance-load). In that sense Web Forms does seem more strictly correct. In general I would not expect the same node's value to be set by both an action and a calculation, though so for now addressing the issue above should be sufficient.