hermes-agent/tests/state/test_compression_lineage_guard.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

164 lines
5.3 KiB
Python

"""Regression tests for stale writes after a compression session split."""
from __future__ import annotations
import pytest
from hermes_state import SessionDB
@pytest.fixture()
def db(tmp_path):
session_db = SessionDB(db_path=tmp_path / "state.db")
try:
yield session_db
finally:
session_db.close()
def _compression_parent(db: SessionDB, session_id: str = "parent") -> None:
db.create_session(session_id, source="webui")
db.append_message(session_id, "user", "before split")
db.end_session(session_id, "compression")
def test_find_live_compression_child_returns_unique_direct_child(db: SessionDB) -> None:
_compression_parent(db)
db.create_session("child", source="webui", parent_session_id="parent")
child = db.find_live_compression_child("parent")
assert child is not None
assert child["id"] == "child"
assert child["parent_session_id"] == "parent"
assert child["ended_at"] is None
def test_find_live_compression_child_fails_closed_when_ambiguous(db: SessionDB) -> None:
_compression_parent(db)
db.create_session("child-a", source="webui", parent_session_id="parent")
db.create_session("child-b", source="webui", parent_session_id="parent")
assert db.find_live_compression_child("parent") is None
def test_find_live_compression_child_ignores_non_continuation_children(
db: SessionDB,
) -> None:
_compression_parent(db)
db.create_session("canonical", source="webui", parent_session_id="parent")
db.create_session(
"branch",
source="webui",
parent_session_id="parent",
model_config={"_branched_from": "parent"},
)
db.create_session(
"delegate",
source="webui",
parent_session_id="parent",
model_config={"_delegate_from": "parent"},
)
db.create_session("tool-child", source="tool", parent_session_id="parent")
child = db.find_live_compression_child("parent")
assert child is not None
assert child["id"] == "canonical"
def test_publish_compression_child_is_atomic_on_handoff_failure(
db: SessionDB, monkeypatch
) -> None:
db.create_session("atomic-parent", source="webui")
db.append_message("atomic-parent", "user", "original")
assert db.try_acquire_compression_lock("atomic-parent", "winner", ttl_seconds=60)
def _boom(*_args, **_kwargs):
raise RuntimeError("handoff insert failed")
monkeypatch.setattr(db, "_insert_message_rows", _boom)
with pytest.raises(RuntimeError, match="handoff insert failed"):
db.publish_compression_child(
parent_session_id="atomic-parent",
child_session_id="atomic-child",
source="webui",
messages=[{"role": "user", "content": "summary"}],
compression_lock_holder="winner",
)
parent = db.get_session("atomic-parent")
assert parent is not None
assert parent["ended_at"] is None
assert db.get_session("atomic-child") is None
def test_publish_compression_child_exposes_complete_child(db: SessionDB) -> None:
db.create_session("atomic-parent", source="webui")
db.append_message("atomic-parent", "user", "original")
assert db.try_acquire_compression_lock("atomic-parent", "winner", ttl_seconds=60)
db.publish_compression_child(
parent_session_id="atomic-parent",
child_session_id="atomic-child",
source="webui",
system_prompt="compressed system",
messages=[{"role": "user", "content": "summary"}],
compression_lock_holder="winner",
)
assert db.get_session("atomic-parent")["end_reason"] == "compression"
child = db.find_live_compression_child("atomic-parent")
assert child is not None
assert child["id"] == "atomic-child"
assert child["system_prompt"] == "compressed system"
assert [m["content"] for m in db.get_messages("atomic-child")] == ["summary"]
def test_publish_compression_child_rejects_lost_or_expired_lease(db: SessionDB) -> None:
db.create_session("lease-parent", source="webui")
db.append_message("lease-parent", "user", "new durable turn")
assert db.try_acquire_compression_lock("lease-parent", "new-winner", ttl_seconds=60)
with pytest.raises(RuntimeError, match="lease lost"):
db.publish_compression_child(
parent_session_id="lease-parent",
child_session_id="stale-child",
source="webui",
messages=[{"role": "user", "content": "stale summary"}],
compression_lock_holder="old-loser",
)
parent = db.get_session("lease-parent")
assert parent is not None
assert parent["ended_at"] is None
assert db.get_session("stale-child") is None
assert [m["content"] for m in db.get_messages("lease-parent")] == [
"new durable turn"
]
def test_compression_lease_blocks_non_owner_but_allows_owner_flush(
db: SessionDB,
) -> None:
db.create_session("leased", source="webui")
assert db.try_acquire_compression_lock("leased", "winner", ttl_seconds=60)
with pytest.raises(RuntimeError, match="being compressed"):
db.append_message("leased", "user", "late stale turn")
db.append_message(
"leased",
"assistant",
"winner flush",
compression_lock_holder="winner",
)
assert [m["content"] for m in db.get_messages("leased")] == ["winner flush"]