Present clone findings as clone groups (#5) - #30
Draft
drogers0 wants to merge 4 commits into
Draft
Conversation
Collapse N-way duplicates into first-class clone groups across the JSON and HTML reports instead of scattering the N·(N−1)/2 pairwise findings. - Add `CloneGroup` + `build_groups` (the single grouping source of truth) and a `group_stats` helper in `similarity::clustering`. Groups are derived from findings and re-numbered deterministically (total order over the sorted location-identity vector), so membership/ids are reproducible run-to-run. Without `--cluster` each finding is its own 2-location singleton group; with it, findings sharing a function merge. Detection output is unchanged. - JSON (BREAKING): findings now nest under a top-level `groups` array; the flat `findings` array is removed. Each group carries its unique `locations`, `max_score`/`max_duplicated_lines`, and its pairwise `findings`. - HTML: flat per-finding list by default; under `--cluster` a summary line plus one collapsible section per multi-location group. Fix the sort script to reorder only top-level rows so nested member findings are not reparented. - Stats: add `group_count` + de-duplicated `grouped_function_count`, populated via `group_stats` in the pipeline, sonarqube engine, and `diff` (recomputed after filtering to changed paths so the report stays internally consistent). - Update the benchmark harness to read `groups[].findings[]`, regenerate the golden JSON snapshot and the example reports, and refresh README/CLAUDE.md/ docs. SARIF and the in-memory `ScanResult.findings` model are unchanged, so the detection baseline is not re-frozen.
drogers0
marked this pull request as draft
July 9, 2026 21:25
Make clone grouping the single, unconditional presentation. Findings sharing a function identity merge into one family via union-find; the representative is the most-connected location (identity-min tiebreak). - HTML: GitHub-style family cards — representative code block plus member diffs oriented against the rep (single canonicalization point), injective consumed-aware member assignment, self-clones and leftovers under "Other matches". Single-finding families render as one open pair card; multi-finding families collapse with the first member pre-open. - Remove --cluster / --cluster-min-size flags, the cluster_findings / cluster_min_size config + overrides + validation, and the vestigial Finding.metadata field (JSON and SARIF schema change). - JSON/SARIF flow through the same always-on grouping; SARIF stays one-result-per-finding. - Regenerate golden snapshots (metadata + cluster config removed) and examples; refresh docs and CLAUDE.md. Detection output is unchanged; the frozen baseline is not re-frozen.
…ually Cut the representative/star model from the HTML family card. A multi-finding family now lists its member locations and renders every finding as an equal side-by-side diff card (first pre-open); cross-location and self-clone findings get identical treatment, with self-clones carrying an "internal duplication" label. This removes the arbitrary demotion where an in-family self-clone was buried in a collapsed "Other matches" section while a standalone self-clone rendered as a full card. - Remove the `representative` field from CloneGroup and its most-connected computation in build_groups (locations stay identity-sorted; finding order unchanged). - Delete the rep source block, member-row consumption/orientation logic, and the "Other matches" catch-all from html.rs (render_code_block, render_member_rows, orient_finding, and helpers). - Regenerate the HTML/JSON/SARIF examples; refresh README/CLAUDE/docs. Detection output is unchanged; the frozen baseline is not re-frozen.
Render the multi-finding family card as `<details open>` so a clone group shows its findings without a click; its first finding card is already pre-opened, so the group and its first diff are both visible by default.
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.
Closes #5.
Collapses N-way duplicates into first-class clone groups across the JSON and HTML reports, instead of scattering the N·(N−1)/2 pairwise findings. Detection output (findings, scores, pairs) is unchanged — this is a presentation/derivation change — so the frozen detection baseline is not re-frozen.
What changed
CloneGroup+build_groups(the single grouping source of truth) and agroup_statshelper insimilarity::clustering. Groups are derived from findings and re-numbered deterministically via a total order over the sorted location-identity vector, so membership/ids are reproducible run-to-run. Without--clustereach finding is its own 2-location singleton group; with it, findings sharing a function merge.groupsarray; the flatfindingsarray is removed. Each group carries its uniquelocations,max_score/max_duplicated_lines, and its pairwisefindings. Consume asfor g in groups: for f in g.findings— no clustered-vs-flat branching.--cluster, a summary line (“{group_count} clone groups across {grouped_function_count} functions”) plus one collapsible section per multi-location group. The client-side sort script now reorders only top-level rows, so nested member findings are no longer reparented on first paint.group_count+ de-duplicatedgrouped_function_count, populated viagroup_statsin the pipeline, the sonarqube engine, anddiff(recomputed after filtering to changed paths so the report stays internally consistent).ScanResult.findingsmodel are unchanged.groups[].findings[], regenerated the golden JSON snapshot and all four example reports, and refreshed README / CLAUDE.md / docs.Validation
cargo fmt --check,cargo clippy --all-targets -- -D warnings,cargo test(273 lib + 16 integration + 3 golden), andcargo build --releaseall pass. The detection baseline (benchmark/baseline.json) is untouched.