Skip to content

feat: support negative matching in queries - #28

Merged
luigi-agosti merged 2 commits into
mainfrom
feat/negative-matching
Apr 22, 2026
Merged

feat: support negative matching in queries#28
luigi-agosti merged 2 commits into
mainfrom
feat/negative-matching

Conversation

@Chetnapadhi

Copy link
Copy Markdown
Collaborator

Summary

This PR implements support for negative matching in queries, enabling expressions such as "button not submit", "link without logout", and "input excluding email".

Changes

  • Added query parsing to detect negative tokens with support for multiple triggers and multi-token negatives
  • Integrated negative scoring in the lexical matcher using Jaccard similarity with synonym-aware penalties and hard exclusion thresholds
  • Integrated negative scoring in the embedding matcher using cosine similarity-based penalties
  • Centralized query parsing in the combined matcher to avoid redundant processing
  • Ensured all scores are clamped within the range [0,1]
  • Preserved existing behavior for positive-only queries

Tests

  • Added table-driven tests for query parsing, including edge cases
  • Added integration tests for negative matching across lexical, embedding, and combined matchers
  • Covered cases for synonym-aware exclusion and negative-only queries
  • Ensured no regression in existing positive query behavior

Validation

  • go build ./... passed
  • go test ./... passed
  • go vet ./... passed
  • No changes to public API
  • No new dependencies introduced

Notes

  • Negative matching supports multiple triggers such as "not", "without", "exclude", "except", and "no"
  • Synonym expansion is applied to negative tokens for consistent matching behavior

Fixes #24

Copilot AI review requested due to automatic review settings April 17, 2026 04:31

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds negative matching support to the semantic element finder so queries can exclude/penalize elements using triggers like not, without, excluding, etc.

Changes:

  • Introduces centralized query parsing into positive/negative token sets.
  • Applies negative penalties/exclusions across lexical, embedding, and combined matchers (with score clamping).
  • Adds tests and benchmarks covering negative matching, negative-only queries, and regressions.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
semantic_test.go Adds end-to-end tests for negative matching behavior in the public package surface.
internal/types/types.go Adds ParsedQuery type to represent positive vs negative tokens.
internal/engine/query_parser.go Implements query parsing with negative triggers.
internal/engine/query_parser_test.go Adds table-driven tests for query parsing edge cases.
internal/engine/lexical.go Integrates negative parsing and penalties into lexical matching.
internal/engine/lexical_test.go Adds lexical unit tests for negative penalization, synonyms, and empty queries.
internal/engine/embedding.go Integrates negative parsing and cosine-similarity penalties into embedding matching.
internal/engine/embedding_test.go Adds embedding unit tests for negative penalization, negative-only, and empty queries.
internal/engine/combined.go Centralizes parsing and fuses results with clamped combined scores.
internal/engine/combined_test.go Adds combined-matcher coverage for negative queries, regressions, and clamping.
internal/engine/benchmark_test.go Fixes element ref generation and adds benchmark scenarios for negative queries.
README.md Documents negative query syntax, examples, and expected behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +616 to +620
dSet := tokenSet(descTokens)
for _, nt := range negativeTokens {
if dSet[nt] {
return true
}
Comment thread internal/engine/query_parser.go Outdated

inNegative := false
for _, tok := range tokens {
if negativeTriggers[tok] {
Comment thread semantic_test.go Outdated
Comment on lines +219 to +220
for _, m := range result.Matches {
if m.Ref == "e0" {
@Chetnapadhi
Chetnapadhi force-pushed the feat/negative-matching branch from 1f74041 to f89759e Compare April 17, 2026 05:55

@luigi-agosti luigi-agosti left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Chetnapadhi thanks, I'm going to do a follow up on this to fix a couple of things

@luigi-agosti
luigi-agosti merged commit 2cc7f54 into main Apr 22, 2026
7 checks passed
@Chetnapadhi
Chetnapadhi deleted the feat/negative-matching branch April 22, 2026 11:12
luigi-agosti added a commit that referenced this pull request Apr 24, 2026
feat: support negative matching in queries
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.

Support negative matching in queries

3 participants