fix(VIOL-0064): raise on ambiguous agent-name folder match#767
Merged
Conversation
The agent-name resolver walked the project tree and returned the FIRST `<name>/agent_config` directory it happened to reach, silently. In a project where two directories share the same base name (multi-tenant or multi-workflow layouts), an operator passing `-a <name>` could target the wrong workflow — reading and writing the wrong agent_io — with no warning. Root cause: a first-match `return` inside `os.walk`. The fix adds a plural collector that gathers every matching `agent_config` folder and raises `AmbiguousAgentName` listing all candidates when two or more share the base name. Zero-match and single-match behavior is byte-identical (still `(None, None)` and the single path respectively). `AmbiguousAgentName` subclasses `ValidationError` deliberately: the sole caller wraps the resolver in `except ValidationError: raise` but re-wraps any other exception into a generic "Failed to get agent paths" message that would destroy the candidate list. Subclassing `ValidationError` lets the precise ambiguity error — with its full candidate listing — propagate cleanly to every CLI command with no change to the caller. This also aligns the two-or-more-match case with the existing zero-match case, which already surfaces as a `ValidationError`.
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
Summary
The agent-name resolver (
FileHandler.get_agent_paths) walked the project tree and returned the first<name>/agent_configdirectory it happened to reach, silently. In a project where two directories share the same base name (multi-tenant / multi-workflow layouts), an operator running any CLI command with-a <name>could target the wrong workflow — reading and writing the wrongagent_io— with no warning or error.Root cause: a first-match
returninsideos.walk.Fix:
FileHandler.find_all_specific_folders— collects every matching folder instead of returning the first.get_agent_pathsnow raisesAmbiguousAgentNamelisting every candidate (full path + parent workflow directory) when two or moreagent_configdirectories share the base name.(None, None)and the single path, respectively).find_specific_folder(first-match) is left intact for theagent_iolookup and action-folder resolution — theagent_configraise fires first and covers the common case.Why
AmbiguousAgentNamesubclassesValidationError: the sole caller (ProjectPathsFactory.get_agent_paths) re-raisesValidationErrorunchanged but wraps any other exception into a generic"Failed to get agent paths"message that would destroy the candidate list. SubclassingValidationErrorlets the precise error — with its full candidate listing — propagate cleanly to every CLI command viacreate_project_paths, with no caller edit. This also aligns the ≥2-match case with the existing 0-match case, which already surfaces as aValidationError.Verification
DID NOT RAISE(proving the silent first-match bug), while single/zero/subclass baselines passed.tests/unit/utils/test_get_agent_paths_disambiguation.pypass after the fix, at both the util layer and the CLI-facing factory layer (candidate list survives, not re-wrapped).tests/unit/test_errors.py,tests/unit/utils/,tests/cli/test_cli_hardening.py(incl. the single-matchtest_project_root_reaches_file_handler),tests/workflow/test_runner.py,tests/unit/llm_invocation/test_agent_manager.py,tests/config/— all pass.ruff checkclean;ruff format --checkclean.Out of scope (follow-up)
agent_ioambiguity is not guarded — theagent_configraise fires first. Guard it the same way if a case arises. The separateAgentManagerrealtime resolver is a different code path and is untouched.