Skip to content

fix(graph): correct Cypher NOT precedence - #948

Merged
ruvnet merged 1 commit into
mainfrom
fix/cypher-not-precedence-939
Aug 30, 2026
Merged

ruvnet merged 1 commit into
mainfrom
fix/cypher-not-precedence-939

Conversation

@ruvnet

@ruvnet ruvnet commented Aug 30, 2026

Copy link
Copy Markdown
Owner

Outcome

Cypher NOT now binds looser than comparison and tighter than AND. Queries such as NOT n.age = 30 produce NOT (n.age = 30) instead of (NOT n.age) = 30.

Invariants

  1. Comparison expressions remain inside NOT.

  2. NOT expressions remain inside AND.

  3. Arithmetic unary minus retains its existing precedence.

Validation

cargo test -p ruvector-graph passed 352 tests with 13 existing ignored tests.

cargo clippy -p ruvector-graph --all-targets -- -D warnings passed.

RuFlo diff risk reported low risk with score 0 of 100.

Risk

The intentional behavior change affects AST shape for unparenthesized NOT expressions. Exact AST regression tests lock the Cypher precedence contract.

Fixes #939

@ruvnet
ruvnet merged commit c2df540 into main Aug 30, 2026
55 of 56 checks passed

ruvnet commented Aug 31, 2026

Copy link
Copy Markdown
Owner Author

Post-merge Dream review for exact head df644e2a4050901fe8b75db9d2c512255b854f78.

The parser change matches the current Neo4j Cypher boolean precedence: comparisons bind before NOT, which binds before AND. Focused validation reports 352 graph tests passing with 13 existing ignores, clippy passes, and exact-head graph-native, regression, supply-chain, fmt/clippy, and WASM-dedup workflows are green.

Portfolio verdict: INCONCLUSIVE rather than ACCEPT because required Workspace CI run 33321172176 cancelled its core-and-rest shard. The narrow AST semantics are supported; repository-wide promotion remains blocked until that shard completes on the exact candidate or merge head.

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.

cypher parser: NOT binds tighter than comparison — NOT n.age = 30 parses as (NOT n.age) = 30

1 participant