Repository navigation
fix(query): order the per-term guaranteed seeds by match strength (#4357) - #4358
devkancheti4-design wants to merge 1 commit into
Conversation
…aphify-Labs#4357) _pick_seeds appended the per-term guaranteed seeds (Graphify-Labs#1445) in sorted(best_seed_by_term), alphabetical term order, and the renderer prints seeds first, so a weak match on an early-alphabet term led a specific term's exact match. _score_query now returns term_order: the per-term winners by their existing key (-singleton score, which carries the term's IDF weight, then -degree, label length, node id), the term breaking ties. _query_graph_text passes it to _pick_seeds. The same seeds are picked and the order is deterministic; without term_order the sorted order is kept. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks for the pull request, @devkancheti4-design. A maintainer will review it soon. Want to talk it through while it is in review? Come join us on our Discord server. For longer-form discussion there is also GitHub Discussions. A couple of things that speed up review: make sure the test suite passes on Python 3.10 and 3.13, and that the change keeps extraction deterministic. |
There was a problem hiding this comment.
Graphify reviewed this change.
No issues found by static checks — no coupling regressions or blocking issues in the code graph. That is not the same as safe to merge: see what was not checked.
Not checked: tests were not run; formal verification proved 0 of 3 changed function(s) (2 sampled, not proven, 1 not verified).
Formal verification. PR-changed functions: 2/3 verified (0 proven, 2 may-equivalent, 0 distinguished) · 1 not verified (1 vacuous).
Not verified on this run: \_score\_query (vacuous: never exercised).
Graphify review — findings
Orders the per-term guaranteed seeds in _pick_seeds by the strength of each term's best match (IDF-weighted score, then degree, label length, term) instead of alphabetically. A rare term's exact match now prints ahead of a common term's substring hit in the query output. _score_query returns this as term_order; terms missing from it, or callers that don't pass it, fall back to the old sorted order, and the set of seeds picked is unchanged.
No blocking issues surfaced. 2 lower-confidence candidates did not survive cross-model review.
Analysis details — impact, health, verification
Impact & health
Graphify review
Impact — 610 functions depend on the 158 functions this change touches.
Health — this change adds coupling hotspots:
- worse:
_query_graph_text()— 32 callers, 10 callees - worse:
_score_query()— 17 callers, 7 callees
Verification — 610 functions in the blast radius were not formally verified this run (proofs are advisory here).
Gate & verification
graphify gate
PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.
Advisory (not blocking):
- verification_scope: 410 function(s) in the blast radius were not formally verified this run
Test selection
Test selection
14 of 377 test file(s) selected (4%) via static blast radius.
tests/test_benchmark.py— impacttests/test_benchmark_raw_graph.py— impacttests/test_explain_same_file_tie.py— impacttests/test_file_label_disambiguation.py— impacttests/test_mcp_graph_view_cache.py— impacttests/test_path_cli.py— impacttests/test_query_induced_edges.py— impacttests/test_query_mcp_direction.py— impacttests/test_query_names_its_graph.py— impacttests/test_query_seed_order.py— impact, changed-testtests/test_serve.py— impacttests/test_serve_http.py— impacttests/test_terraform.py— impacttests/test_truncation_full_answer.py— impact
Selection is safe under the controlled-regression assumption; always-run tests + a periodic full run are the backstops. Advisory — it never changes the check verdict.
Formal verification
No difference found (not proven): No behavior difference found in \_pick\_seeds (not a proof).
The verifier ran both versions of \_pick\_seeds on many inputs and saw identical behavior every time. Strong evidence the change is safe, but evidence, not a proof.
Guarantee: Empirical: differential testing (both versions run on many generated inputs). A divergence on an untested input remains possible, so this is 'no counterexample found', not 'proven equivalent'.
Note: An input the sampler did not try could still differ.
No difference found (not proven): No behavior difference found in \_query\_graph\_text (not a proof).
The verifier ran both versions of \_query\_graph\_text on many inputs and saw identical behavior every time. Strong evidence the change is safe, but evidence, not a proof.
Guarantee: Empirical: differential testing (both versions run on many generated inputs). A divergence on an untested input remains possible, so this is 'no counterexample found', not 'proven equivalent'.
Note: An input the sampler did not try could still differ.
Could not verify: Could not verify \_score\_query.
The verifier did not have enough to check \_score\_query, so it is saying so rather than guessing. No false assurance is the whole point.
Guarantee: No guarantee either way, this is an honest abstention, not a pass.
Note: Reason: no capturable inputs from the test suite; property tier: not verifiable: all 47 sampled inputs raised on both versions — the function never executed, so 'no divergence' would be vacuous (mostly TypeError — names the real obstacle, not a sampling gap)
· 2 more finding(s) on lines outside this diff (see the check run).
|
Shipped in v0.9.87, just released to PyPI as |
|
Thank you @safishamsi, both for shipping it in 0.9.87 and for keeping the authorship on the cherry-pick. |
What does this PR do?
Closes #4357.
_pick_seedsguarantees one seed per query term (#1445), but it appended those seeds insorted(best_seed_by_term),which is alphabetical term order.
_subgraph_to_textprints seeds first, so on a multi-term query a weak match on anearly-alphabet term was printed ahead of a specific term's exact match.
_score_queryalready ranks each term's winner with the key(-singleton score, -degree, label length, node id),and the singleton score carries the term's IDF weight. This PR:
_QueryScores.term_order(the term itself breaks remaining ties);_query_graph_textpass it to_pick_seeds.What stays the same:
term_order, as withexplain,pathand direct callers,_pick_seedskeeps the sorted order.Terms missing from
term_orderfollow it in sorted order.Measured on AST-only graphs with graphify's own functions (graphify 0.9.86, v8 a5ba60d):
Per question, hit@5 moved +10/-0, +4/-3 and +1/-0. The
script and data reproduce
these numbers.
Type of change
Verification & Invariants
The invariants:
term_orderkeep the legacy order.No persisted or generated state is touched.
How was this tested?
What the new tests cover:
_pick_seedsfollowsterm_order;_pick_seedskeeps the sorted order without it;term_orderfollow it in sorted order;_score_queryorders terms by match strength;alpha bravo charlie apple zebraprinted the common term's seed (apple) before the rareexact match (
charlie) on v8, and printscharliefirst with this change.Graphify-specific checklist
uv run python -m tools.skillgen --bless) when changing their source fragments. (n/a, no fragments changed)🤖 Generated with Claude Code