Skip to content

Comments

fix: NaN confidence filter silently rejected all graph_accel traversals#340

Merged
aaronsb merged 3 commits intomainfrom
fix/nan-confidence-filter
Feb 19, 2026
Merged

fix: NaN confidence filter silently rejected all graph_accel traversals#340
aaronsb merged 3 commits intomainfrom
fix/nan-confidence-filter

Conversation

@aaronsb
Copy link
Owner

@aaronsb aaronsb commented Feb 19, 2026

Summary

  • Root cause: graph_facade.py passed float('nan') as the min_confidence parameter to graph_accel SQL functions when no confidence filter was requested. In IEEE 754, NaN >= x is always false, so the Rust confidence filter rejected every edge with a loaded confidence value — silently returning empty results from BFS neighborhood, shortest path, and subgraph extraction.
  • Fix: Pass None (SQL NULL) instead, which maps to Rust's Option::None and bypasses the confidence filter entirely.
  • Impact: All three accelerated traversal functions (graph_accel_neighborhood, graph_accel_path, graph_accel_subgraph) were affected. Without this fix, any graph where edges have confidence properties (the common case for semantic edges from ingestion) returned zero results.

How it was found

Searching "Negentropic Viability Model" in the web workstation returned only 1 concept with 1 adjacent at 4 hops deep. Investigation initially focused on the GUC edge-type filtering from PR #339, but the actual bug predates that PR — it was present from the original graph_accel facade integration. The GUC filtering fix (correctly reducing edge count from 19K to 3.9K) just made the empty results more noticeable since there was less data to mask the issue.

The IEEE 754 NaN trap

# Before (broken): NaN as "no filter" sentinel
conf_param = min_confidence if min_confidence is not None else float('nan')
# → Rust: Some(NaN) → edge.confidence >= NaN → always false

# After (fixed): NULL = no filter
# → Rust: None → skip filter entirely

Test plan

  • MCP concept related returns 83 concepts at depth 2 (was 0)
  • MCP concept related at depth 4 returns extensive results (81K+ chars, was 0)
  • Direct SQL comparison: NULL returns 83 results, NaN returns 0
  • Rust core two-phase loading tests pass (cargo test)
  • Web workstation: search "Negentropic Viability Model" shows rich neighborhood at 4 hops

The facade passed float('nan') as the min_confidence parameter when no
confidence filter was requested. In Rust's IEEE 754 semantics, the
comparison `edge.confidence >= NaN` is always false, so the confidence
filter silently rejected every edge that had a loaded confidence value.

This caused graph_accel_neighborhood, graph_accel_path, and
graph_accel_subgraph to return empty results whenever edges had
confidence properties — which is the common case for semantic edges
created during ingestion.

The fix passes None (SQL NULL) instead, which maps to Rust's
Option::None and bypasses the confidence filter entirely.
Verify that BFS and app_id resolution work correctly when nodes are
added first (load_vertices) and edges added separately (load_edges),
matching the pgrx extension's actual load sequence.
New graph-accel way covers build, deploy, debug, GUC testing, and the
NULL-vs-NaN parameter pitfall. API way gets a GraphFacade section.
Testing way adds Rust test commands.
@aaronsb aaronsb merged commit a53745d into main Feb 19, 2026
3 checks passed
@aaronsb aaronsb deleted the fix/nan-confidence-filter branch February 19, 2026 16:41
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