updateSolveStatus() calls solve() when lastResult_.placements is empty,
but solve() calls updateSolveStatus() at the end. When an assembly has
zero constraints (all joints removed), the solver returns zero
placements, causing infinite recursion until stack overflow (segfault).
Add a static re-entrancy guard so the recursive solve() call is skipped
if updateSolveStatus() is already on the call stack.