test(audit): fix critical test suite deadlocks and write exhaustive architectural report

- Fix 'Triple Bingo' history synchronization explosion during streaming

- Implement stateless event buffering in ApiHookClient to prevent dropped events

- Ensure 'tool_execution' events emit consistently across all LLM providers

- Add hard timeouts to all background thread wait() conditions

- Add thorough teardown cleanup to conftest.py's reset_ai_client fixture

- Write highly detailed report_gemini.md exposing asyncio lifecycle flaws
This commit is contained in:
2026-03-05 01:42:47 -05:00
parent bfdbd43785
commit 35480a26dc
15 changed files with 715 additions and 481 deletions

View File

@@ -9,6 +9,7 @@ class ApiHookClient:
self.base_url = base_url
self.max_retries = max_retries
self.retry_delay = retry_delay
self._event_buffer: list[dict[str, Any]] = []
def wait_for_server(self, timeout: float = 3) -> bool:
"""
@@ -209,21 +210,31 @@ class ApiHookClient:
return {"tag": tag, "shown": False, "error": str(e)}
def get_events(self) -> list[Any]:
"""Fetches and clears the event queue from the server."""
"""Fetches new events and adds them to the internal buffer."""
try:
res = self._make_request('GET', '/api/events')
return res.get("events", []) if res else []
new_events = res.get("events", []) if res else []
if new_events:
self._event_buffer.extend(new_events)
return list(self._event_buffer)
except Exception:
return []
return list(self._event_buffer)
def clear_events(self) -> None:
"""Clears the internal event buffer and the server queue."""
self._make_request('GET', '/api/events')
self._event_buffer.clear()
def wait_for_event(self, event_type: str, timeout: float = 5) -> dict[str, Any] | None:
"""Polls for a specific event type."""
"""Polls for a specific event type in the internal buffer."""
start = time.time()
while time.time() - start < timeout:
events = self.get_events()
for ev in events:
# Refresh buffer
self.get_events()
# Search in buffer
for i, ev in enumerate(self._event_buffer):
if isinstance(ev, dict) and ev.get("type") == event_type:
return ev
return self._event_buffer.pop(i)
time.sleep(0.1) # Fast poll
return None