[travsr-mcp] guard get_execution_path against ambiguous endpoints - #799
Open
ritikpal1122 wants to merge 2 commits into
Open
[travsr-mcp] guard get_execution_path against ambiguous endpoints#799ritikpal1122 wants to merge 2 commits into
ritikpal1122 wants to merge 2 commits into
Conversation
get_execution_path took the first hit from search_nodes_by_name, so an ambiguous name silently became a guess and the tool then reported "no path found" between the pair it happened to pick. That is a wrong answer rather than a missing one: the caller is told two symbols are disconnected when the tool simply looked at the wrong ones. On fastlane/fastlane, Runner.run has four definitions and only match's calls fetch_certificate. Resolution now goes through resolve_reference_targets, the tiered resolver graph and search_symbol already use. get_execution_path was the one tool not going through it, so this removes an inconsistency rather than adding a mechanism. An ambiguous endpoint returns the candidate list and names which side is ambiguous, and the listed exact signatures each resolve uniquely through Tier 1, so they are directly re-runnable. Ambiguity is reported before resolution failure, because "I found several and will not choose" is more actionable than "I found none". SEC P0, and the reason resolve_endpoint filters before it counts: ambiguity is a property of what THIS caller may see. A name with four definitions of which the caller may see one resolves uniquely for them, and they are never told the other three exist. Counting first and filtering after would leak them through the candidate list, which is the existence oracle get_execution_path_denied_matches_not_found exists to prevent. Ambiguous also collapses to None in into_unique, so the non-diagnose path cannot proceed on a guessed endpoint. Three tests, all mutation checked. Reverting to first-match fails both ambiguity tests. Swapping the filter and the count fails the leak test, and notably does NOT fail the pre-existing denied-matches-not-found test, so that ordering was previously unguarded.
`VName::new` takes `impl Into<String>`, so `&format!(..)` borrows a value that already satisfies the bound. Three sites in the new tests, all rejected by `needless_borrows_for_generic_args`. My local check ran `cargo clippy -p travsr-mcp --all-targets` without `-D warnings`, so these surfaced as warnings I did not read rather than as a failure. CI runs `cargo clippy --workspace --all-targets -- -D warnings`; verified against that exact command now, workspace wide.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #779.
The bug
get_execution_pathtook the first hit fromsearch_nodes_by_name:So an ambiguous name became a guess, and the tool then reported "no path found" between the pair it happened to pick. That is a wrong answer, not a missing one: the caller is told two symbols are disconnected when the tool simply looked at the wrong ones. On fastlane/fastlane,
Runner.runhas four definitions and only match's callsfetch_certificate.The fix
Resolution now goes through
resolve_reference_targets, the tiered resolvergraphandsearch_symbolalready use.get_execution_pathwas the one tool not going through it, so this removes an inconsistency rather than adding a mechanism.An ambiguous endpoint returns the candidate list and says which side is ambiguous. The listed exact signatures each resolve uniquely through Tier 1, so they are directly re-runnable:
Ambiguity is checked before resolution failure, because "I found several and will not choose" is more actionable than "I found none".
SEC P0: why the filter runs before the count
This is the part worth reviewing closely. Ambiguity is a property of what this caller may see:
A name with four definitions of which the caller may see one resolves uniquely for them, and they are never told the other three exist. Counting first and filtering after would leak them through the candidate list, which is the existence oracle
get_execution_path_denied_matches_not_foundexists to prevent.Ambiguousalso collapses toNoneininto_unique(), so the non-diagnose path (which returns an empty string for every failure) cannot proceed on a guessed endpoint.Tests, all mutation checked
Three added. Each was verified to fail when the fix is reverted, not just to pass:
ambiguous_endpoint_lists_candidatesFAILED,ambiguous_sink_names_the_sinkFAILEDambiguity_never_leaks_denied_definitionsFAILEDWorth flagging from the second row: swapping the order does not fail the pre-existing
get_execution_path_denied_matches_not_found. That ordering was previously unguarded, so the leak test covers a real gap rather than restating an existing check.Verification
One file changed.
Note
The candidate list uses
" at <path>"rather than the em-dashgraphuses for the same list. This is a diagnostic message, not the<sig> (<kind>) — <path>wire headerpackages/travsr-vscodeparses, so it has no separator to preserve and falls under the no-em-dash rule the CI gate enforces. The gate caught my first attempt.