The weight vector was built before substitution_pass and
single_equation_pass, which can fix variables and reduce the free
parameter count. This caused a shape mismatch in newton_solve when
the Jacobian had fewer columns than the weight vector had entries:
ValueError: operands could not be broadcast together with shapes
(55,27) (1,28)
Move build_weight_vector() after both pre-passes so its length
matches the actual free parameters used by the Jacobian.