fix(page-cluster): guard cross-block merges against cohesion collapse - #949
Merged
Conversation
Stage B's cross-block merge could chain unrelated units together one merge at a time, each step individually passing its pairwise similarity check while the pooled group's actual common structure eroded toward nothing. A degenerate L2 signature (too coarse to tell templates apart) made this worse by feeding indiscriminate merges into the same chain. - Add a post-merge cohesion guard in front of every Stage B merge path: reject a proposed merge when the pooled group's quorum-core size, compared against each member's own original (pre-merge) core size, drops below a ratio threshold. Track the original core via an anchor map (max-propagated forward) rather than the immediately preceding step, so a long chain of individually-passing merges can't erode the reference itself. - Detect degenerate L2 signatures (too few distinct shapes among enough participants to be discriminating) and skip the L2 merge stage rather than run it on non-discriminating signatures. - Add validateClusterPartition and its building blocks (detectMirrorAxis, normalizePathByMirrorAxis, normalizeHrefByMirrorAxis, computeClusterCohesion, findCrossClusterDuplicates, mergeValidatedClusters) to check a finished partition against itself: cross-cluster duplicates that should have merged (optionally corroborated by a detected URL mirror axis, e.g. a language directory), and clusters whose members don't actually cohere with each other. - Wire an opt-in onPartitionReport callback into resolvePageClusterKeys that, when provided, computes the report and applies its built-in safe-merge policy (byte-identical or mirror-axis-corroborated near-duplicates) to the output clusterKeys. - Add --validation-file to the CLI, new subpath exports for the added modules, and README coverage for the new checks. - Add a synthetic mirrored-template fixture reproducing the L2 signature collapse and the resulting catch-all merge, used by both the merge-cross-block-clusters and resolve-page-cluster-keys tests. Validated against several real crawl archives outside this repo; cluster quality held steady or improved with no crashes, including on a 100k+ page corpus. No page-count or cluster-count details from that validation are recorded here — see PR description for the same constraint.
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
@d-zero/page-cluster's Stage B cross-block merge could chain unrelated units together one merge at a time — each step individually passed its pairwise similarity check while the pooled group's actual common structure eroded toward nothing, producing large catch-all clusters. A degenerate L2 signature (too coarse to tell templates apart under a shared wrapper) made this worse by feeding indiscriminate merges into the same chain.This PR:
Math.max), so a long chain of individually-passing merges can't erode the reference itself.validateClusterPartitionand its building blocks:detectMirrorAxis,normalizePathByMirrorAxis,normalizeHrefByMirrorAxis,computeClusterCohesion,findCrossClusterDuplicates,mergeValidatedClusters) that checks a finished clustering result against itself — cross-cluster duplicates that should have merged (optionally corroborated by a detected URL mirror axis, e.g. a language directory), and clusters whose members don't actually cohere with each other.onPartitionReportcallback intoresolvePageClusterKeysthat, when provided, computes the report and applies its built-in safe-merge policy (byte-identical or mirror-axis-corroborated near-duplicates) to the outputclusterKeys.--validation-fileto the CLI, new subpath exports for the added modules, and README coverage for the new checks.merge-cross-block-clustersandresolve-page-cluster-keystest suites.Validated against several real crawl archives outside this repository; cluster quality held steady or improved across all of them with no crashes, including a 100k+ page corpus. No page-count, cluster-count, or site-identifying detail from that validation is recorded in this repo — all thresholds and behavior claims here are backed by the synthetic fixture only.
Test plan
yarn lint— cleanyarn test— 150 files / 1949 tests passingyarn build— all 29 packages build;page-cluster's new modules present indist//code-review medium— not yet run (requires manual invocation)🤖 Generated with Claude Code