Files
EventHubAiRouter/test/unit/test_path_resolve.py
T
aleksey a2d238d92e
CI / build-gateway (push) Failing after 16s
CI / sync-config (push) Failing after 0s
feat(agent): hierarchical executor with path resolve, runtime probe, quiet UI
Make Zed Agent closer to Cursor: deterministic DevOps path index, live Traefik
port probe before blind edits, stop-after-edit, and quieter Russian progress.
2026-08-13 11:41:27 +03:00

155 lines
5.5 KiB
Python

"""Unit tests for deterministic path index + resolve gating."""
from __future__ import annotations
import json
import unittest
from path_resolve import (
apply_deterministic_path_index,
enrich_plan_from_discovery_tools,
match_index_paths,
path_resolve_needed,
)
class TestPathResolve(unittest.TestCase):
def test_index_hits_traefik_not_fake_yml(self) -> None:
plan = {
"user_goal": "fix observer.ift.calentiq.com traefik route",
"subtasks": [
{
"id": "1",
"prompt": "edit traefik for observer",
"paths": [
r"C:\Users\alexc\IdeaProjects\eventHub\EventHubDevOps\ift\traefik\traefik.yml"
],
}
],
}
# sanitize would drop fake; index should still hit via keywords
indexed = match_index_paths(plan)
self.assertTrue(indexed)
self.assertTrue(
indexed[0].lower().replace("/", "\\").endswith(
r"ift\traefik\dynamic_conf.yml"
)
)
fixed, unresolved = apply_deterministic_path_index(plan)
self.assertEqual(unresolved, [])
self.assertFalse(path_resolve_needed(fixed))
self.assertTrue(
fixed["subtasks"][0]["paths"][0]
.lower()
.replace("/", "\\")
.endswith(r"ift\traefik\dynamic_conf.yml")
)
def test_index_compose_core(self) -> None:
plan = {
"user_goal": "bump timeout in docker compose swarm",
"subtasks": [{"id": "1", "prompt": "edit compose", "paths": []}],
}
fixed, unresolved = apply_deterministic_path_index(plan)
self.assertEqual(unresolved, [])
self.assertIn("docker-compose.core.yml", fixed["subtasks"][0]["paths"][0])
def test_miss_triggers_queries(self) -> None:
plan = {
"user_goal": "EventHubDevOps mystery widget xyz",
"subtasks": [{"id": "1", "prompt": "widget", "paths": []}],
}
fixed, unresolved = apply_deterministic_path_index(plan)
self.assertTrue(unresolved)
self.assertTrue(path_resolve_needed(fixed))
def test_enrich_from_find_tool(self) -> None:
plan = {
"path_resolve_queries": ["dynamic_conf.yml"],
"path_resolve": "needed",
"subtasks": [{"id": "1", "prompt": "x", "paths": []}],
}
yml = r"C:\Users\alexc\IdeaProjects\eventHub\EventHubDevOps\ift\traefik\dynamic_conf.yml"
messages = [
{
"role": "assistant",
"tool_calls": [
{
"id": "f1",
"type": "function",
"function": {
"name": "find_path",
"arguments": json.dumps({"query": "dynamic_conf"}),
},
}
],
},
{"role": "tool", "tool_call_id": "f1", "content": yml + "\n"},
]
enriched = enrich_plan_from_discovery_tools(plan, messages)
self.assertEqual(enriched["path_resolve"], "find")
self.assertFalse(path_resolve_needed(enriched))
self.assertEqual(enriched["subtasks"][0]["paths"][0], yml)
def test_enrich_ignores_yaml_etc_artifacts(self) -> None:
plan = {
"path_resolve": "index",
"subtasks": [
{
"id": "1",
"prompt": "traefik",
"paths": [
r"C:\Users\alexc\IdeaProjects\eventHub\EventHubDevOps\ift\traefik\dynamic_conf.yml"
],
"path_source": "index",
}
],
}
# read_file body mentions container paths — must NOT poison plan
yml_body = (
"http:\n routers:\n"
" # volume: /etc/traefik/dynamic_conf.yml\n"
" # also null:/etc/nginx/conf.d/default.conf\n"
)
messages = [
{
"role": "assistant",
"tool_calls": [
{
"id": "r1",
"type": "function",
"function": {
"name": "read_file",
"arguments": json.dumps(
{
"path": r"C:\Users\alexc\IdeaProjects\eventHub\EventHubDevOps\ift\traefik\dynamic_conf.yml"
}
),
},
}
],
},
{"role": "tool", "tool_call_id": "r1", "content": yml_body},
]
enriched = enrich_plan_from_discovery_tools(plan, messages)
self.assertEqual(enriched["path_resolve"], "index")
self.assertIn(
"dynamic_conf.yml",
enriched["subtasks"][0]["paths"][0],
)
self.assertNotIn("nginx", json.dumps(enriched).lower())
# Without index, still ignore read bodies (no find_* call ids)
plan2 = {
"path_resolve_queries": ["x"],
"path_resolve": "needed",
"subtasks": [{"id": "1", "prompt": "x", "paths": []}],
}
enriched2 = enrich_plan_from_discovery_tools(plan2, messages)
self.assertEqual(enriched2.get("path_resolve"), "needed")
self.assertEqual(enriched2["subtasks"][0]["paths"], [])
if __name__ == "__main__":
unittest.main()