hermes-agent/tests/run_agent/test_codex_app_server_compaction.py
Teknium 6b81590c55
test: prune low-value tests suite-wide (wave 1) — 46,820 → 28,106 test functions
Systematic prune per AGENTS.md test policy, one pass over every major
test tree (gateway, hermes_cli, tools, agent, run_agent, plugins, cli,
cron, tui_gateway, honcho/openviking, root-level):

- DELETE: source-reading tests (read_text/getsource on prod files),
  change-detector tests (exact catalog counts, model-name snapshots,
  config version literals), mock-echo tests (assert a mock returns what
  it was told), assertion-free/trivial tests, near-duplicate
  parametrizations (boundaries + one representative kept), async/sync
  twin duplicates, cosmetic within-file variations.
- KEEP (mandatory): security/redaction/approval guards, message-role
  alternation invariants, prompt-caching/deterministic-call-id
  invariants, issue-number regression tests (deduped), E2E tests.
- 6 test files deleted outright (script-style/no-assert or fully
  redundant); conftest.py, fakes/, fixtures/ untouched.
- tests/acp/conftest.py added: autouse fixture stubs the live
  models.dev/GitHub/Copilot/Anthropic inventory fetches that ACP server
  tests performed on every session create — test_server.py 147s → 3.4s,
  and the tests are now genuinely hermetic.
- Sleep-based slowness shrunk where safe (codex_ttfb_watchdog,
  compression_concurrent_fork, etc.); no wall-clock assertion tightened.

Verification: full hermetic suite via scripts/run_tests.sh —
2439 files, 31,130 tests passed, 0 failed, 0 flaky retries, 315s wall
(baseline: 583s wall, 13,564s subprocess CPU).
2026-07-29 13:10:23 -07:00

174 lines
4.9 KiB
Python

import time
from types import SimpleNamespace
import pytest
from agent.codex_runtime import _record_codex_app_server_compaction
from agent.conversation_compression import COMPACTION_DONE_STATUS, COMPACTION_STATUS, compress_context
from agent.transports.codex_app_server_session import TurnResult
class FakeCodexSession:
def __init__(self, result):
self.result = result
self.calls = 0
self.closed = False
def compact_thread(self):
self.calls += 1
return self.result
def close(self):
self.closed = True
class SlowCodexSession(FakeCodexSession):
def __init__(self, result, touch_calls):
super().__init__(result)
self.touch_calls = touch_calls
def compact_thread(self):
self.calls += 1
_wait_for_touch(self.touch_calls, "context compression in progress")
return self.result
def _wait_for_touch(touch_calls, desc, timeout=1.0):
deadline = time.monotonic() + timeout
while time.monotonic() < deadline:
if desc in touch_calls:
return
time.sleep(0.01)
pytest.fail(f"timed out waiting for touch {desc!r}; saw {touch_calls!r}")
class DummyAgent:
def __init__(
self,
result,
*,
auto_compaction="native",
):
self.api_mode = "codex_app_server"
self.codex_app_server_auto_compaction = auto_compaction
self.session_id = "hermes-session-1"
self.platform = "cli"
self._cached_system_prompt = "cached prompt"
self._codex_session = FakeCodexSession(result)
self.context_compressor = SimpleNamespace(
compression_count=0,
last_compression_rough_tokens=0,
last_prompt_tokens=123,
last_completion_tokens=45,
awaiting_real_usage_after_compression=False,
)
self.statuses = []
self.status_events = []
self.status_callback = lambda kind, text: self.status_events.append((kind, text))
self.warnings = []
self.events = []
self.built_prompts = []
self.touch_calls = []
self._compression_activity_heartbeat_interval = 0.1
def _touch_activity(self, desc):
self.touch_calls.append(desc)
def _emit_status(self, message):
self.statuses.append(message)
self.status_callback("lifecycle", message)
def _emit_warning(self, message):
self.warnings.append(message)
self.status_callback("warn", message)
def _build_system_prompt(self, system_message):
self.built_prompts.append(system_message)
return "built prompt"
def event_callback(self, name, payload):
self.events.append((name, payload))
def test_codex_app_server_native_auto_mode_leaves_thread_compaction_to_codex():
agent = DummyAgent(
TurnResult(thread_id="thread-1", turn_id="compact-turn-1")
)
messages = [{"role": "user", "content": "hi"}]
returned, prompt = compress_context(
agent,
messages,
"system",
approx_tokens=100000,
task_id="test",
)
assert returned is messages
assert prompt == "cached prompt"
assert agent._codex_session.calls == 0
assert agent.context_compressor.compression_count == 0
assert agent.events == []
def test_codex_app_server_compaction_heartbeat_refreshes_activity_while_waiting():
agent = DummyAgent(
TurnResult(thread_id="thread-1", turn_id="compact-turn-1")
)
agent._codex_session = SlowCodexSession(
agent._codex_session.result,
agent.touch_calls,
)
messages = [{"role": "user", "content": "hi"}]
returned, prompt = compress_context(
agent,
messages,
"system",
approx_tokens=100000,
task_id="test",
force=True,
)
assert returned is messages
assert prompt == "cached prompt"
assert agent._codex_session.calls == 1
assert "context compression started" in agent.touch_calls
assert "context compression in progress" in agent.touch_calls
assert agent.touch_calls[-1] == "context compression completed"
def test_codex_native_boundary_clears_stale_hermes_fallback_streak():
from unittest.mock import patch
from agent.context_compressor import ContextCompressor
with patch(
"agent.context_compressor.get_model_context_length",
return_value=100_000,
):
compressor = ContextCompressor(model="test-model", quiet_mode=True)
compressor._fallback_compression_streak = 1
compressor._last_summary_fallback_used = True
agent = DummyAgent(
TurnResult(thread_id="thread-1", turn_id="normal-turn-1")
)
agent.context_compressor = compressor
turn = TurnResult(
thread_id="thread-1",
turn_id="normal-turn-1",
compacted=True,
)
assert _record_codex_app_server_compaction(agent, turn) is True
assert compressor._fallback_compression_streak == 0
assert compressor._verify_compaction_cleared_threshold is True