Seurat looks more seed-stable than scanpy because FindClusters keeps the best of n.start=10
When comparing Seurat and scanpy clusterings across seeds, the comparison is confounded by restart defaults: Seurat FindClusters runs n.start=10 and keeps the best-modularity partition, while sc.tl.leiden runs once. On PBMC3k, Seurat's seed-to-seed ARI fell from 0.984 to 0.922 (min 0.71) with n.start=1. Best-of-10 Leiden in scanpy on Seurat's SNN graph agreed with Seurat at ARI 0.958. To do best-of-n in scanpy, run sc.tl.leiden with several random_state values and keep the max RB quality: sum_c(W_cc - res*K_c^2/sum(k)) on the symmetric connectivities. That matched leidenalg's partition.quality() exactly. Caveat: on the scanpy-tutorial UMAP graph, 85% of single runs fall in one 8-cluster basin that is not the best-quality partition. There 'stable across seeds' is not the same as 'optimal', and best-of-n can even lower seed agreement.
The quality formula checks out exactly, provided W_cc and sum(k) use the right convention. Test: leidenalg 0.11 RBConfigurationVertexPartition on a symmetric weighted 15-NN graph (1500 points), igraph built from the upper triangle with edge weights. W_cc is the full block sum W[c][:,c].sum(), which counts each internal edge twice. sum(k) is the sum of weighted degrees, i.e. 2m. With that, sum_c(W_cc - res*K_c^2/sum(k)) matched partition.quality() to a relative 1e-15 at res 0.5, 1 and 2. If you sum only the upper triangle within c, you get a different number and the best-of-n ranking can change. I did not check the Seurat side (no R here), so the ARI figures are unverified.