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

159 lines
5 KiB
Python

"""Tests for cold-start credits hydration at session open.
The L3 cold-start seed primes agent._credits_state from /api/oauth/account (or a
HERMES_DEV_CREDITS_FIXTURE) so depletion AND the 90% grant warning fire immediately
at session open, not only after the first inference header. These tests assert the
notice policy fires correctly for a seed-shaped CreditsState with the warn90 latch
primed the way conversation_loop does it.
"""
import time
from agent.credits_tracker import CreditsState, evaluate_credits_notices
def _cold_start_notices(state: CreditsState):
"""Mirror the conversation_loop seed: prime seen_below_90 when used_fraction is
computable (the snapshot IS the first observation), then evaluate once."""
latch = {"active": set(), "seen_below_90": False}
if state.used_fraction is not None:
latch["seen_below_90"] = True
show, clear = evaluate_credits_notices(state, latch)
return [n.key for n in show]
def _state(**kw) -> CreditsState:
kw.setdefault("from_header", False)
kw.setdefault("captured_at", time.time())
return CreditsState(**kw)
def test_cold_start_healthy_no_notice():
s = _state(
remaining_micros=30_340_000, subscription_micros=18_000_000,
subscription_limit_micros=20_000_000, subscription_limit_usd="20.00",
denominator_kind="subscription_cap", paid_access=True,
)
assert abs(s.used_fraction - 0.1) < 1e-9
assert _cold_start_notices(s) == []
def test_dev_fixtures_drive_cold_start():
"""Every HERMES_DEV_CREDITS_FIXTURE state produces a valid seed CreditsState."""
import os
from agent.credits_tracker import dev_fixture_credits_state
expected = {
"healthy": [],
"sub_90pct": ["credits.usage"],
"depleted": ["credits.depleted"],
}
for name, want in expected.items():
os.environ["HERMES_DEV_CREDITS"] = "1" # fixtures gate on the dev flag
os.environ["HERMES_DEV_CREDITS_FIXTURE"] = name
try:
fx = dev_fixture_credits_state()
assert fx is not None, name
assert _cold_start_notices(fx) == want, (name, _cold_start_notices(fx))
finally:
os.environ.pop("HERMES_DEV_CREDITS_FIXTURE", None)
os.environ.pop("HERMES_DEV_CREDITS", None)
# ── seed_credits_at_session_start: the shared session-open hydrator ───────────
class _FakeAgent:
"""Minimal agent surface for the seed helper: state slots + an emit that runs
the real policy against the latch (mirroring run_agent._emit_credits_notices,
including the free-model suppression flag)."""
def __init__(self, provider="nous", model=""):
from agent.credits_tracker import evaluate_credits_notices, is_free_tier_model
self.provider = provider
self.model = model
self._credits_state = None
self._credits_session_start_micros = None
self._credits_latch = {"active": set(), "seen_below_90": False, "usage_band": None}
self.emitted: list = []
self._eval = evaluate_credits_notices
self._is_free = is_free_tier_model
def _emit_credits_notices(self):
if self._credits_state is None:
return
show, clear = self._eval(
self._credits_state,
self._credits_latch,
model_is_free=self._is_free(self.model),
)
self.emitted.append(([n.key for n in show], clear))
def _seed(agent, fixture):
import os
from agent.credits_tracker import seed_credits_at_session_start
os.environ["HERMES_DEV_CREDITS"] = "1" # fixtures gate on the dev flag
os.environ["HERMES_DEV_CREDITS_FIXTURE"] = fixture
try:
return seed_credits_at_session_start(agent)
finally:
os.environ.pop("HERMES_DEV_CREDITS_FIXTURE", None)
os.environ.pop("HERMES_DEV_CREDITS", None)
def test_live_crossing_after_seed_still_fires_grant_spent():
"""The gate opens when the session observes the grant NOT yet spent — a healthy
seed followed by a grant-exhausted header is a real in-session crossing and must
still announce grant_spent once."""
a = _FakeAgent()
assert _seed(a, "healthy") is True
a.emitted = []
a._credits_state = _state( # the grant_exhausted shape, as a live header would carry it
remaining_micros=12_340_000, subscription_micros=0,
subscription_limit_micros=20_000_000, subscription_limit_usd="20.00",
purchased_micros=12_340_000, purchased_usd="12.34",
denominator_kind="subscription_cap", paid_access=True,
)
a._emit_credits_notices()
assert a.emitted == [(["credits.grant_spent"], [])]
def test_seed_is_idempotent():
a = _FakeAgent()
_seed(a, "sub_90pct")
a.emitted = []
# second call must no-op (state already populated)
assert _seed(a, "sub_90pct") is False
assert a.emitted == []
def test_seed_skips_non_nous():
from agent.credits_tracker import seed_credits_at_session_start
a = _FakeAgent(provider="openrouter")
assert seed_credits_at_session_start(a) is False
assert a._credits_state is None