The sign test makes no assumption about the shape of the data: under the null, each non-zero paired difference is equally likely to be positive or negative.
Implement sign_test(before, after) returning (n_pos, n_neg, p_value): drop zero differences, then compute the exact two-sided binomial p-value min(1, 2 * P(X <= min(n_pos, n_neg))) with X ~ Binomial(n, 0.5). With no non-zero differences, the p-value is 1.0.