Private
Public Access
0
0

test(ai_client): TDD red phase - no top-level SDK imports allowed

Phase 3 Task T3.1 of startup_speedup_20260606 track. 9 tests assert:

  - import src.ai_client does NOT trigger google.genai / anthropic /
    openai / requests / google.genai.types imports (the main thread
    must not load these on import; they're warmed on _io_pool)
  - _require_warmed(name) helper exists and is callable
  - _require_warmed returns the cached module if already in sys.modules
  - _require_warmed falls back to importlib for tests/dev where
    warmup didn't run
  - The static audit script does not see src/ai_client.py as a
    contributor of heavy-import violations

All 9 tests are currently FAILING (RED). They will turn GREEN when
T3.2 (the actual refactor of src/ai_client.py to remove top-level
imports and add _require_warmed) lands.

The implementation is held pending MCP client fix (per user instruction).
This commit is contained in:
2026-06-06 15:11:13 -04:00
parent b17cbbdeca
commit 16780ec6d4
@@ -0,0 +1,166 @@
"""Tests that src/ai_client.py has NO top-level heavy SDK imports.
Per spec.md:2.2 Layer 1, the main thread's import chain must not include
heavy modules. Heavy SDKs (google.genai, anthropic, openai, requests) are
warmed on AppController's _io_pool and accessed via _require_warmed().
These tests run in a fresh subprocess to ensure no warmup state leaks
from the test runner. We assert:
- The four heavy SDKs are NOT imported as a side effect of
`import src.ai_client`
- The _require_warmed helper exists
- Calling _require_warmed with an un-warmed module works (fallback
import via importlib)
"""
import subprocess
import sys
import textwrap
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
def _run_in_subprocess(snippet: str) -> subprocess.CompletedProcess:
script = textwrap.dedent(snippet)
return subprocess.run(
[sys.executable, "-c", script],
capture_output=True,
text=True,
cwd=str(ROOT),
timeout=30,
)
def test_ai_client_does_not_import_google_genai_at_module_level() -> None:
res = _run_in_subprocess("""
import sys
import src.ai_client
print('google.genai' in sys.modules)
print('google' in sys.modules)
""")
assert res.returncode == 0, f"stderr: {res.stderr}"
lines = res.stdout.strip().splitlines()
assert lines == ["False", "False"], f"ai_client triggered google.genai import: {res.stdout}"
def test_ai_client_does_not_import_anthropic_at_module_level() -> None:
res = _run_in_subprocess("""
import sys
import src.ai_client
print('anthropic' in sys.modules)
""")
assert res.returncode == 0, f"stderr: {res.stderr}"
assert res.stdout.strip() == "False"
def test_ai_client_does_not_import_openai_at_module_level() -> None:
res = _run_in_subprocess("""
import sys
import src.ai_client
print('openai' in sys.modules)
""")
assert res.returncode == 0, f"stderr: {res.stderr}"
assert res.stdout.strip() == "False"
def test_ai_client_does_not_import_requests_at_module_level() -> None:
res = _run_in_subprocess("""
import sys
import src.ai_client
print('requests' in sys.modules)
""")
assert res.returncode == 0, f"stderr: {res.stderr}"
assert res.stdout.strip() == "False"
def test_ai_client_does_not_import_google_genai_types_at_module_level() -> None:
res = _run_in_subprocess("""
import sys
import src.ai_client
print('google.genai.types' in sys.modules)
""")
assert res.returncode == 0, f"stderr: {res.stderr}"
assert res.stdout.strip() == "False"
def test_ai_client_exposes_require_warmed_helper() -> None:
res = _run_in_subprocess("""
import src.ai_client
print(hasattr(src.ai_client, '_require_warmed'))
print(callable(src.ai_client._require_warmed))
""")
assert res.returncode == 0, f"stderr: {res.stderr}"
assert res.stdout.strip() == "True\nTrue"
def test_require_warmed_returns_module_when_already_loaded() -> None:
res = _run_in_subprocess("""
import sys
import importlib
import src.ai_client
# Pre-load the module (simulating warmup)
importlib.import_module('json')
mod = src.ai_client._require_warmed('json')
print(mod is sys.modules['json'])
""")
assert res.returncode == 0, f"stderr: {res.stderr}"
assert res.stdout.strip() == "True"
def test_require_warmed_falls_back_to_import_if_not_warmed() -> None:
res = _run_in_subprocess("""
import sys
import src.ai_client
# Pick a stdlib module that ai_client doesn't trigger
assert 'collections' in sys.modules # stdlib
# Pick a module that's definitely NOT imported yet
target = 'collections.abc'
importlib_mod = __import__('importlib')
if target in sys.modules:
del sys.modules[target]
mod = src.ai_client._require_warmed(target)
print(mod is not None)
print(target in sys.modules)
""")
assert res.returncode == 0, f"stderr: {res.stderr}"
lines = res.stdout.strip().splitlines()
assert lines[0] == "True"
assert lines[1] == "True"
def test_audit_main_thread_imports_sees_no_new_violation_from_ai_client() -> None:
"""Run the static audit and check that src/ai_client.py contributes no
new heavy imports (any remaining violations are pre-existing in OTHER
files; Phase 4-5 will address them).
"""
res = _run_in_subprocess("""
import sys
from pathlib import Path
sys.path.insert(0, str(Path.cwd()))
from scripts.audit_main_thread_imports import audit, _walk_import_graph
from pathlib import Path
root = Path('.').resolve()
entry = (root / 'sloppy.py').resolve()
graph = _walk_import_graph(entry, root)
ai_client_path = root / 'src' / 'ai_client.py'
if ai_client_path in graph:
import ast
tree = ast.parse(ai_client_path.read_text(encoding='utf-8'))
heavy = ['anthropic', 'google.genai', 'openai', 'requests', 'google.genai.types']
for node in tree.body:
if isinstance(node, ast.Import):
for alias in node.names:
for h in heavy:
if alias.name == h or alias.name.startswith(h + '.'):
print('VIOLATION:', alias.name)
elif isinstance(node, ast.ImportFrom):
if node.module:
for h in heavy:
if node.module == h or node.module.startswith(h + '.'):
print('VIOLATION:', node.module)
print('OK')
""")
assert res.returncode == 0, f"stderr: {res.stderr}"
assert "OK" in res.stdout
assert "VIOLATION" not in res.stdout