Skip to content

feat!: replace ctx duplicates with MinHash structural near-duplicate detection#7

Merged
saldestechnology merged 4 commits into
mainfrom
feat/duplicates-minhash
Jul 9, 2026
Merged

feat!: replace ctx duplicates with MinHash structural near-duplicate detection#7
saldestechnology merged 4 commits into
mainfrom
feat/duplicates-minhash

Conversation

@saldestechnology

Copy link
Copy Markdown
Collaborator

Summary

PR 4 of 7 in the Quality Intelligence Suite. Stacked on #2 (feat/quality-foundation) — will be retargeted to main once #2 merges; review only the top 2 commits until then.

Breaking: replaces the old O(n²) line-based ctx duplicates in place — same command name, entirely new semantics. Old --similarity/--min-lines flags and the line-based detector are deleted (no hidden fallback, no dupes alias). Existing indexes must be rebuilt (ctx index --force, schema v2).

  • Per function/method: normalized token stream from the tree-sitter AST (identifiers → ID, literals → LIT, comments dropped) → k=5 shingles → 128-perm MinHash stored in a new symbol_fingerprints table, populated incrementally during ctx index.
  • Query-time LSH banding (16×8) for candidates, exact Jaccard verification (re-tokenized from stored snippets) — no O(n²).
  • --threshold 0.85 (Jaccard, clamped ≥0.5 with a warning), --min-tokens 50, --against <REF> (diff-scoped), --fail-on-found (exit 1 = findings, for hooks/CI), global --json (includes skipped_languages: ["solidity"] — solang has no tree-sitter grammar).
  • Also refactors serial/parallel indexing through one shared store_file_impl funnel (the parallel path had an inlined copy), and rejects pre-versioning v0 databases instead of silently stamping them (they'd yield silently-empty results).

Test plan

  • End-to-end: renamed-variables + different-literals copy detected at default threshold, unrelated functions not; incremental reindex re-fingerprints only the edited file (verbose-log + byte-identical untouched BLOBs); --fail-on-found exit codes; Solidity → zero rows.
  • Unit: per-language tokenizer normalization, MinHash within ±0.08 of exact Jaccard, LSH pair detection, determinism, snippet ≡ whole-file tokenization, schema v1→v2 enforcement.
  • cargo test (201 green), clippy -D warnings, fmt --check, --no-default-features build — all clean.

🤖 Generated with Claude Code

…l search

Rework ctx duplicates as a MinHash-based near-duplicate detector over
normalized token shingles:

- New src/fingerprint.rs: tree-sitter tokenization (identifiers -> ID,
  literals -> LIT, comments dropped), FNV-1a k=5 shingles, 128-perm
  MinHash (SplitMix64 seeds, LE blobs, deterministic across platforms),
  16x8 LSH banding with exact-Jaccard verification of candidates.
- ctx index now fingerprints function/method symbols incrementally per
  changed file into the new symbol_fingerprints table (cascade-deleted
  with symbols); serial/parallel/watch paths share one store funnel.
- Index schema bumped to v2; v0/v1 databases now fail with the existing
  'run ctx index --force' SchemaVersionMismatch message.
- New CLI: --threshold <0.0-1.0 Jaccard, default 0.85, clamped at 0.5>,
  --min-tokens <N, default 50>, --against <REF>, --fail-on-found
  (exit 1 via Outcome::Findings), global --json envelope with
  SymbolRef pairs, similarity, token counts, skipped_languages.
- Old line-based detector fully removed: find_duplicates,
  normalize_code, calculate_similarity, md5_hash, DuplicateResult, the
  --similarity/--min-lines/--output flags, and the stale shell
  completion entry. Solidity is skipped (solang-parser, no tree-sitter).

BREAKING CHANGE: --threshold is a shingle-set Jaccard similarity, not a
percentage of matching lines; existing indexes must be rebuilt with
ctx index --force.
Update README, docs/, the docs website mirror, the agents guide, and the
JSON output contract for the reworked ctx duplicates: new
--threshold/--min-tokens/--against/--fail-on-found flags, the duplicates
JSON envelope payload, the Solidity skip, and the breaking-change /
reindex notes in the changelog.
@saldestechnology
saldestechnology deleted the branch main July 9, 2026 15:38
@saldestechnology
saldestechnology changed the base branch from feat/quality-foundation to main July 9, 2026 15:41
@saldestechnology
saldestechnology merged commit 23d1dee into main Jul 9, 2026
7 checks passed
@saldestechnology
saldestechnology deleted the feat/duplicates-minhash branch July 9, 2026 17:31
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