Skip to content

fix(page-cluster): guard cross-block merges against cohesion collapse - #949

Merged
YusukeHirao merged 2 commits into
devfrom
feat/page-cluster-cohesion-guard
Aug 12, 2026
Merged

fix(page-cluster): guard cross-block merges against cohesion collapse#949
YusukeHirao merged 2 commits into
devfrom
feat/page-cluster-cohesion-guard

Conversation

@YusukeHirao

Copy link
Copy Markdown
Member

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:

  • Adds a post-merge cohesion guard in front of every Stage B merge path: a proposed merge is rejected when the pooled group's quorum-core size, compared against each member's own original (pre-merge) core size, drops below a ratio threshold. The original core size is tracked via an anchor map that only ever grows (Math.max), so a long chain of individually-passing merges can't erode the reference itself.
  • Adds L2 signature degeneracy detection: skips the L2 merge stage when too few distinct signature shapes exist among enough participants to be discriminating.
  • Adds a post-hoc partition validation library (validateClusterPartition and 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.
  • Wires 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.
  • Adds --validation-file to the CLI, new subpath exports for the added modules, and README coverage for the new checks.
  • Adds 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 test 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 — clean
  • yarn test — 150 files / 1949 tests passing
  • yarn build — all 29 packages build; page-cluster's new modules present in dist/
  • Regression-checked against multiple real crawl archives (outside this repo) before and after the change
  • /code-review medium — not yet run (requires manual invocation)

🤖 Generated with Claude Code

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.
@YusukeHirao
YusukeHirao requested a review from yusasa16 as a code owner August 12, 2026 15:52
@YusukeHirao
YusukeHirao merged commit cab98ca into dev Aug 12, 2026
6 checks passed
@YusukeHirao
YusukeHirao deleted the feat/page-cluster-cohesion-guard branch August 12, 2026 15:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant