Summary
In a multi-term query, a single generic term that exactly equals a short, unrelated leaf node's label receives the _EXACT_MATCH_BONUS (1000×IDF) and outscores every genuinely relevant node by ~10×. _pick_seeds (gap_ratio 0.2) then drops all other candidates, so the traversal starts from one irrelevant leaf and returns a tiny dead-end subgraph.
Observed on graphifyy 0.8.49.
Repro (real graph, Phoenix/Elixir codebase, ~5,400 nodes)
Query:
graphify query "dashboard home page LiveView content KPI cards alerts today grid"
The graph contains a rich cluster for the dashboard feature (IrisWeb.DashboardLive, kpi_card(), alert_row(), plus design docs whose labels match 3 of the query terms). Expected seeds somewhere in that cluster.
Actual _score_nodes output (top of the ranking):
6037.89 home() <- "home" == bare label -> exact tier
680.74 grid_view() <- "grid" prefix tier
621.57 Home / Today Dashboard (Iris) <- 3 substring hits
616.01 Home Today Mock
_pick_seeds keeps only home() because every other node is below 20% of the top score. home() is a 2-neighbor leaf (a controller action), so BFS depth 2 returns 3 nodes and the answer collapses:
Traversal: BFS depth=2 | Start: ['home()'] | 3 nodes found
The failure generalizes: any generic English word in a concept query that happens to equal (or prefix) a short function name hijacks the seed. Same graph, "dashboard liveview kpi alerts today grid" seeds at grid_view() / gridlines() for the same reason, while "dashboard KPI alerts" (no colliding generic words) seeds correctly.
Why this feels like a scorer bug rather than user error
The exact-match tier is clearly right for identifier queries (graphify query "FooBarService"). But in a 10-term query, an exact hit on one term says much less than substring hits on three terms. The current scoring has no notion of term coverage, so one lucky collision dominates, and the aggressive seed gap then removes all diversity.
Possible directions
- Weight the exact/prefix bonuses by the fraction of query terms the node matches, so a 1-of-10 exact hit can't bury a 3-of-10 multi-term match.
- Or relax
_pick_seeds when the top seed's score comes from a single term of a many-term query — keep at least one seed from the best multi-term-coverage node.
- Or treat very short labels (
home, grid) as low-information exact matches, e.g. dampen the exact bonus by label-token IDF.
Happy to provide more score traces if useful.
Summary
In a multi-term query, a single generic term that exactly equals a short, unrelated leaf node's label receives the
_EXACT_MATCH_BONUS(1000×IDF) and outscores every genuinely relevant node by ~10×._pick_seeds(gap_ratio 0.2) then drops all other candidates, so the traversal starts from one irrelevant leaf and returns a tiny dead-end subgraph.Observed on
graphifyy0.8.49.Repro (real graph, Phoenix/Elixir codebase, ~5,400 nodes)
Query:
The graph contains a rich cluster for the dashboard feature (
IrisWeb.DashboardLive,kpi_card(),alert_row(), plus design docs whose labels match 3 of the query terms). Expected seeds somewhere in that cluster.Actual
_score_nodesoutput (top of the ranking):_pick_seedskeeps onlyhome()because every other node is below 20% of the top score.home()is a 2-neighbor leaf (a controller action), so BFS depth 2 returns 3 nodes and the answer collapses:The failure generalizes: any generic English word in a concept query that happens to equal (or prefix) a short function name hijacks the seed. Same graph,
"dashboard liveview kpi alerts today grid"seeds atgrid_view()/gridlines()for the same reason, while"dashboard KPI alerts"(no colliding generic words) seeds correctly.Why this feels like a scorer bug rather than user error
The exact-match tier is clearly right for identifier queries (
graphify query "FooBarService"). But in a 10-term query, an exact hit on one term says much less than substring hits on three terms. The current scoring has no notion of term coverage, so one lucky collision dominates, and the aggressive seed gap then removes all diversity.Possible directions
_pick_seedswhen the top seed's score comes from a single term of a many-term query — keep at least one seed from the best multi-term-coverage node.home,grid) as low-information exact matches, e.g. dampen the exact bonus by label-token IDF.Happy to provide more score traces if useful.