community detection stage of the streaming pipeline.
edges are read back from disk (they were already persisted by ApproxKnnBuilder so the FASTA / embedding matrices are never re-materialised) and fed into a NetworkGraph. classic Louvain is then run via Builder.Load() / "Builder.SolveClusters". the resulting per-row family assignment is streamed to disk keyed by row index, keeping only the assignment array (one integer per node) resident instead of any intermediate matrix.
NOTE: the in-memory graph is bounded by the number of nodes (= number of sequences) and the number of edges. for truly massive node counts where the graph itself does not fit in RAM the caller can pre-shard the edge file and run this routine per shard, then merge the communities with the supplied BlockLouvain.MergeCommunities() helper. the default path reuses the proven single-graph Louvain which is already a large improvement over the original all-in-memory pipeline that also held every protein sequence string.