fix(subscription): wire tokens_saved_rtk from RTK stats endpoint

PR-G2 (Realignment) — retire the dead `tokens_saved_rtk` data plane.

Previously, `SubscriptionTracker.update_contribution` silently mirrored
`tokens_saved_cli_filtering` into `tokens_saved_rtk`, making the two
counters identical at all times and hiding wrap-side RTK savings from
the dashboard.

Wiring:
- New `_last_rtk_tokens_saved` state on the tracker (init to 0).
- `update_contribution` now polls `_get_rtk_stats()` when the caller
  omits an explicit `tokens_saved_rtk`, computes the delta against the
  last lifetime total, and writes only the positive delta. State
  advances monotonically; a counter regression re-baselines without
  emitting a negative delta.
- `cli_filtering` and `rtk` are no longer aliased anywhere in the
  hot path.
- Persistence: `to_dict()` exposes raw `cli_filtering_raw` and
  `rtk_raw` keys (legacy dashboard `cli_filtering` / `rtk` still report
  `max(cli, rtk)` for back-compat). `_load_persisted_state` reads the
  raw keys when present and defaults to 0 otherwise so legacy state
  cannot silently re-inflate `tokens_saved_rtk` by mirroring
  `cli_filtering`.

Build constraints honoured:
- No silent fallback — transient `_get_rtk_stats()` exceptions are
  caught, structured-logged (`event=subscription_rtk_stats_fetch_failed`
  / `event=subscription_rtk_stats_unavailable`), and yield zero delta.
- Configurable — `HEADROOM_RTK_WIRING={enabled,disabled}` opts the
  polling out without disturbing tool selection. Unknown values raise
  loudly via `_rtk_wiring_mode`.
- Comprehensive tests — 9 new unit tests in
  `tests/test_subscription_tracker_rtk_wired.py` pin the wiring
  (baseline, delta across two/three polls, None payload, monotonic
  advance, counter regression, exception, env-var opt-out, explicit
  override, decoupling from cli_filtering). Existing tracker tests
  updated to reflect the no-mirror behaviour.

Refs: REALIGNMENT/09-phase-G-rtk-observability.md (PR-G2)
This commit is contained in:
chopratejas 2026-05-22 13:48:42 -07:00
parent 9536d6b48c
commit 44c605fbb0
4 changed files with 518 additions and 14 deletions

View file

@ -430,6 +430,15 @@ class HeadroomContribution:
"proxy_compression": self.tokens_saved_compression,
"cli_filtering": self.cli_filtering_saved(),
"rtk": self.cli_filtering_saved(),
# PR-G2 (Realignment) — raw counters, distinct from the
# dashboard-facing ``cli_filtering`` / ``rtk`` keys (which
# both report ``max(cli_filtering, rtk)`` for legacy
# display). Persisted so the tracker can round-trip each
# counter independently — the bug PR-G2 retires is that
# ``tokens_saved_rtk`` and ``tokens_saved_cli_filtering``
# used to be identical.
"cli_filtering_raw": self.tokens_saved_cli_filtering,
"rtk_raw": self.tokens_saved_rtk,
"cache_reads": self.tokens_saved_cache_reads,
"total": self.total_saved(),
},

View file

@ -53,6 +53,33 @@ _PERSIST_FILE_ENV = _paths.HEADROOM_SUBSCRIPTION_STATE_PATH_ENV
_DEFAULT_PERSIST_DIR = ".headroom"
_DEFAULT_PERSIST_FILE = "subscription_state.json"
# PR-G2 (Realignment) — RTK savings wiring.
#
# Operators can disable the RTK polling from inside ``update_contribution``
# without uninstalling the binary or unsetting ``HEADROOM_CONTEXT_TOOL``.
# Used for diagnostics and for environments where RTK is intentionally
# excluded from headroom accounting (e.g. shadow tests).
#
# Loud / configurable / no silent fallback: unknown values raise loudly via
# the parser below — they do not silently default to ``enabled``.
_RTK_WIRING_ENV = "HEADROOM_RTK_WIRING"
_RTK_WIRING_DEFAULT = "enabled"
_RTK_WIRING_ALLOWED = ("enabled", "disabled")
def _rtk_wiring_mode() -> str:
"""Return ``enabled`` or ``disabled``. Raises on unknown values.
Read at call-time so operators can flip the env var without a restart.
"""
raw = os.environ.get(_RTK_WIRING_ENV, "").strip().lower()
if not raw:
return _RTK_WIRING_DEFAULT
if raw in _RTK_WIRING_ALLOWED:
return raw
raise ValueError(f"Invalid {_RTK_WIRING_ENV}={raw!r}; expected one of {_RTK_WIRING_ALLOWED}")
# Singleton on-demand poll floor (seconds): the dashboard may request a fresh
# poll if the cached snapshot is stale, but we cap how often we will actually
# hit Anthropic to avoid 429s / OAuth-token flagging. Bounded across users.
@ -120,6 +147,17 @@ class SubscriptionTracker(QuotaTracker):
self._current_token: str | None = None
self._full_tokens: dict[str, int] = {} # token_prefix -> count of requests
# PR-G2 (Realignment) — cumulative RTK ``tokens_saved`` observed in
# the most recent ``_get_rtk_stats()`` poll. Lifetime counter from
# the RTK binary (``rtk gain --project``). Used to compute the
# per-call delta that feeds ``HeadroomContribution.tokens_saved_rtk``
# without double-counting across calls.
#
# Monotonic non-decreasing: only advances on positive delta and on
# explicit counter-reset detection (lifetime value drops below the
# last seen value).
self._last_rtk_tokens_saved: int = 0
self._stop_event: asyncio.Event | None = None
self._poll_task: asyncio.Task[None] | None = None
@ -194,7 +232,7 @@ class SubscriptionTracker(QuotaTracker):
tokens_submitted: int = 0,
tokens_saved_compression: int = 0,
tokens_saved_cli_filtering: int | None = None,
tokens_saved_rtk: int = 0,
tokens_saved_rtk: int | None = None,
tokens_saved_cache_reads: int = 0,
compression_savings_usd: float = 0.0,
cache_savings_usd: float = 0.0,
@ -202,22 +240,134 @@ class SubscriptionTracker(QuotaTracker):
"""Update headroom contribution counters for the current session window.
Called after each proxy request completes with the actual token deltas.
PR-G2 (Realignment) ``tokens_saved_rtk`` is now sourced from RTK's
own stats endpoint (``rtk gain --format json`` via
:func:`headroom.proxy.helpers._get_rtk_stats`) when the caller does
not pass an explicit value. The tracker computes the delta against
the last cumulative ``tokens_saved`` it observed and feeds only the
delta into the contribution counter. Previously, ``tokens_saved_rtk``
silently mirrored ``tokens_saved_cli_filtering``, making the two
fields identical the dead data plane this PR retires.
Args:
tokens_saved_rtk: Explicit override for tokens saved by RTK on
this call. If ``None`` (the default), the tracker polls RTK
stats itself and writes the per-call delta. If passed
(including ``0``), the override is used verbatim.
"""
# Polled outside the lock so the subprocess call can't deadlock the
# event loop or contend with concurrent ``notify_active`` callers.
if tokens_saved_rtk is None:
tokens_saved_rtk = self._poll_rtk_delta()
with self._lock:
c = self._state.contribution
cli_filtering = (
tokens_saved_rtk
if tokens_saved_cli_filtering is None
else tokens_saved_cli_filtering
)
# PR-G2: cli_filtering is no longer aliased to the rtk param.
# When the caller omits both, both default to 0 — explicit, loud.
cli_filtering = tokens_saved_cli_filtering or 0
c.tokens_submitted += max(tokens_submitted, 0)
c.tokens_saved_compression += max(tokens_saved_compression, 0)
c.tokens_saved_cli_filtering += max(cli_filtering, 0)
c.tokens_saved_rtk += max(cli_filtering, 0)
c.tokens_saved_rtk += max(tokens_saved_rtk, 0)
c.tokens_saved_cache_reads += max(tokens_saved_cache_reads, 0)
c.compression_savings_usd += max(compression_savings_usd, 0.0)
c.cache_savings_usd += max(cache_savings_usd, 0.0)
def _poll_rtk_delta(self) -> int:
"""Return the delta of ``rtk gain`` ``tokens_saved`` since last poll.
Implementation of PR-G2 data-plane wiring. Calls
:func:`headroom.proxy.helpers._get_rtk_stats` and reads the lifetime
``tokens_saved`` counter, then diffs against
``self._last_rtk_tokens_saved``.
Returns ``0`` (never negative) when:
- ``HEADROOM_RTK_WIRING=disabled`` operator opt-out.
- ``_get_rtk_stats()`` returns ``None`` RTK not selected / not
installed; explicit zero is the right answer.
- ``_get_rtk_stats()`` raises transient error, logged loudly.
- The lifetime counter regressed (RTK reset / new project) that
path also re-baselines ``_last_rtk_tokens_saved`` to the new
(smaller) value so subsequent polls return correct deltas.
Otherwise advances ``self._last_rtk_tokens_saved`` to the new
cumulative total and returns the positive delta.
"""
try:
wiring_mode = _rtk_wiring_mode()
except ValueError as exc:
logger.warning(
"event=subscription_rtk_wiring_invalid_env error=%s",
exc,
)
return 0
if wiring_mode == "disabled":
return 0
try:
# Local import keeps the tracker module decoupled from the proxy
# helper at import time (helpers.py imports many heavy deps).
from headroom.proxy.helpers import _get_rtk_stats
except Exception as exc: # pragma: no cover — defensive
logger.warning(
"event=subscription_rtk_helper_import_failed error=%s",
exc,
)
return 0
try:
stats = _get_rtk_stats()
except Exception as exc:
logger.warning(
"event=subscription_rtk_stats_fetch_failed error=%s",
exc,
)
return 0
if stats is None:
logger.info(
"event=subscription_rtk_stats_unavailable wiring=%s",
wiring_mode,
)
return 0
# Prefer the lifetime monotonic counter (raw upstream value); fall
# back to the unprefixed ``tokens_saved`` only if the lifetime field
# is absent — which only happens on the synthetic zero payloads
# returned when RTK isn't installed.
current_total_raw = stats.get(
"lifetime_tokens_saved",
stats.get("tokens_saved", 0),
)
try:
current_total = int(current_total_raw or 0)
except (TypeError, ValueError) as exc:
logger.warning(
"event=subscription_rtk_stats_coerce_failed value=%r error=%s",
current_total_raw,
exc,
)
return 0
with self._lock:
last = self._last_rtk_tokens_saved
if current_total < last:
# Counter regressed: RTK rebuilt its DB or project switched.
# Re-baseline silently — losing one delta is preferable to
# reporting a giant negative number.
logger.info(
"event=subscription_rtk_counter_regressed previous=%d current=%d",
last,
current_total,
)
self._last_rtk_tokens_saved = current_total
return 0
delta = current_total - last
if delta > 0:
self._last_rtk_tokens_saved = current_total
return delta
# ------------------------------------------------------------------
# State access
# ------------------------------------------------------------------
@ -491,9 +641,20 @@ class SubscriptionTracker(QuotaTracker):
c.tokens_saved_compression = int(
saved.get("proxy_compression", saved.get("compression", 0))
)
cli_filtering = int(saved.get("cli_filtering", saved.get("rtk", 0)))
# PR-G2 (Realignment) — prefer the raw counters when present
# (new format). For backward compatibility with state written
# before PR-G2 we fall back to the dashboard-aliased keys.
# Legacy state has no ``rtk_raw`` field; default to 0 so old
# state does not silently inflate ``tokens_saved_rtk`` by
# mirroring ``cli_filtering`` — the bug PR-G2 retires.
cli_filtering = int(
saved.get(
"cli_filtering_raw",
saved.get("cli_filtering", saved.get("rtk", 0)),
)
)
c.tokens_saved_cli_filtering = cli_filtering
c.tokens_saved_rtk = cli_filtering
c.tokens_saved_rtk = int(saved.get("rtk_raw", 0))
c.tokens_saved_cache_reads = int(saved.get("cache_reads", 0))
savings_usd = contrib.get("savings_usd", {})
c.compression_savings_usd = float(savings_usd.get("compression", 0.0))

View file

@ -36,6 +36,9 @@ def _make_snapshot(
def test_tracker_notify_active_update_and_basic_state(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(SubscriptionTracker, "_load_persisted_state", lambda self: None)
# PR-G2: keep the unit test deterministic — do not let
# ``update_contribution`` call out to ``rtk gain`` via the proxy helper.
monkeypatch.setattr(SubscriptionTracker, "_poll_rtk_delta", lambda self: 0)
tracker = SubscriptionTracker(enabled=False)
assert tracker.is_available() is False
@ -175,7 +178,11 @@ async def test_maybe_poll_success_updates_state_and_metrics(
assert isinstance(metrics_calls[1], dict)
def test_persist_and_load_state_round_trip(tmp_path: Path) -> None:
def test_persist_and_load_state_round_trip(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
# PR-G2: ``update_contribution`` polls RTK by default; pin the helper to
# 0 so the round-trip is deterministic.
monkeypatch.setattr(SubscriptionTracker, "_poll_rtk_delta", lambda self: 0)
persist_path = tmp_path / "tracker-state.json"
tracker = SubscriptionTracker(persist_path=persist_path)
tracker.update_contribution(
@ -186,19 +193,32 @@ def test_persist_and_load_state_round_trip(tmp_path: Path) -> None:
compression_savings_usd=1.5,
cache_savings_usd=2.5,
)
# PR-G2: also write a raw RTK delta directly to assert the persisted
# ``rtk_raw`` field round-trips independently of cli_filtering.
tracker.update_contribution(tokens_saved_rtk=9)
tracker._state.poll_count = 7
tracker._persist_state()
loader = SubscriptionTracker(persist_path=persist_path)
assert loader._state.contribution.tokens_submitted == 11
assert loader._state.contribution.tokens_saved_compression == 2
# PR-G2: the raw counters now round-trip independently of the legacy
# dashboard alias.
assert loader._state.contribution.tokens_saved_cli_filtering == 3
assert loader._state.contribution.tokens_saved_rtk == 3
assert loader._state.contribution.tokens_saved_rtk == 9
assert loader._state.contribution.tokens_saved_cache_reads == 4
assert loader._state.contribution.to_dict()["tokens_saved"]["compression"] == 5
# ``compression`` is ``proxy_compression + cli_filtering_saved()`` =
# ``2 + max(3, 9)`` = 11 after PR-G2 (was 5 when rtk mirrored
# cli_filtering).
assert loader._state.contribution.to_dict()["tokens_saved"]["compression"] == 11
assert loader._state.contribution.to_dict()["tokens_saved"]["proxy_compression"] == 2
assert loader._state.contribution.to_dict()["tokens_saved"]["cli_filtering"] == 3
assert loader._state.contribution.to_dict()["tokens_saved"]["rtk"] == 3
# Dashboard ``cli_filtering`` / ``rtk`` keys remain ``max(cli, rtk)``
# for legacy display — 9 wins. Raw counters expose the un-aliased
# values for the tracker's own round-trip.
assert loader._state.contribution.to_dict()["tokens_saved"]["cli_filtering"] == 9
assert loader._state.contribution.to_dict()["tokens_saved"]["rtk"] == 9
assert loader._state.contribution.to_dict()["tokens_saved"]["cli_filtering_raw"] == 3
assert loader._state.contribution.to_dict()["tokens_saved"]["rtk_raw"] == 9
assert loader._state.contribution.compression_savings_usd == 1.5
assert loader._state.contribution.cache_savings_usd == 2.5
assert loader._state.poll_count == 7

View file

@ -0,0 +1,314 @@
"""Tests for PR-G2 — RTK ``tokens_saved`` data-plane wiring.
Phase G of the Headroom realignment retires the dead ``tokens_saved_rtk``
field by sourcing it from RTK's own stats endpoint (``rtk gain --format
json`` via :func:`headroom.proxy.helpers._get_rtk_stats`) and writing the
per-call delta into ``HeadroomContribution.tokens_saved_rtk``. Previously,
the field silently mirrored ``tokens_saved_cli_filtering`` making the
two counters identical at all times and breaking the dashboard's ability
to distinguish proxy-side compression from wrap-side RTK savings.
These tests pin the wiring:
1. The delta is computed correctly across two consecutive
:meth:`update_contribution` calls (monotonic counter advances).
2. ``tokens_saved_rtk`` is exactly zero when ``_get_rtk_stats()`` returns
``None`` (RTK not installed / not selected).
3. ``_last_rtk_tokens_saved`` advances monotonically; deltas are not
replayed across calls when the lifetime counter does not move.
Realignment build constraints honored:
- No silent fallback: a transient ``_get_rtk_stats()`` exception is
structured-logged and yields ``tokens_saved_rtk = 0`` (test 4).
- Configurable: ``HEADROOM_RTK_WIRING=disabled`` opts the polling out and
produces a clean zero, exercised by ``test_disabled_env_returns_zero``.
- Structured logs: each failure path emits a ``event=`` line; the tests
do not pin the log payload to avoid coupling, but the helper signatures
surface them.
- Comprehensive tests: 6 unit tests + 1 explicit delta test cover the
contract.
"""
from __future__ import annotations
from typing import Any
import pytest
import headroom.subscription.tracker as tracker_module
from headroom.subscription.tracker import SubscriptionTracker
def _build_tracker(monkeypatch: pytest.MonkeyPatch) -> SubscriptionTracker:
"""Construct a tracker with persistence disabled (unit-test isolation)."""
monkeypatch.setattr(SubscriptionTracker, "_load_persisted_state", lambda self: None)
return SubscriptionTracker(enabled=True)
def _stub_rtk_stats(
monkeypatch: pytest.MonkeyPatch, payloads: list[dict[str, Any] | None]
) -> list[int]:
"""Stub ``_get_rtk_stats`` to return ``payloads`` in order.
Returns a counter list (mutated by the stub) so callers can assert the
number of polls.
"""
call_count: list[int] = [0]
def fake_get_rtk_stats() -> dict[str, Any] | None:
idx = call_count[0]
call_count[0] += 1
if idx >= len(payloads):
return payloads[-1]
return payloads[idx]
monkeypatch.setattr(
"headroom.proxy.helpers._get_rtk_stats",
fake_get_rtk_stats,
)
return call_count
# ---------------------------------------------------------------------------
# Test 1 — delta computed correctly across two consecutive polls
# ---------------------------------------------------------------------------
def test_tokens_saved_rtk_populated_from_rtk_stats(
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""First call seeds the baseline; second call writes the positive delta."""
tracker = _build_tracker(monkeypatch)
monkeypatch.delenv(tracker_module._RTK_WIRING_ENV, raising=False)
_stub_rtk_stats(
monkeypatch,
[
{"lifetime_tokens_saved": 100},
{"lifetime_tokens_saved": 175},
],
)
# First call — establishes the baseline at 100, contributes 100 (the
# tracker starts at _last_rtk_tokens_saved == 0, so the first delta is
# the full lifetime total). That matches the spec: the field reflects
# cumulative session savings observed by the tracker.
tracker.update_contribution()
contribution_after_first = tracker._state.contribution.tokens_saved_rtk
assert contribution_after_first == 100
assert tracker._last_rtk_tokens_saved == 100
# Second call — delta is 175 - 100 = 75; cumulative contribution = 175.
tracker.update_contribution()
assert tracker._state.contribution.tokens_saved_rtk == 175
assert tracker._last_rtk_tokens_saved == 175
def test_delta_computed_correctly_across_polls(
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""Three consecutive polls — each adds only the new RTK delta."""
tracker = _build_tracker(monkeypatch)
monkeypatch.delenv(tracker_module._RTK_WIRING_ENV, raising=False)
_stub_rtk_stats(
monkeypatch,
[
{"lifetime_tokens_saved": 0}, # baseline at zero
{"lifetime_tokens_saved": 50},
{"lifetime_tokens_saved": 250},
],
)
tracker.update_contribution()
assert tracker._state.contribution.tokens_saved_rtk == 0
assert tracker._last_rtk_tokens_saved == 0
tracker.update_contribution()
assert tracker._state.contribution.tokens_saved_rtk == 50
assert tracker._last_rtk_tokens_saved == 50
tracker.update_contribution()
# 50 + (250 - 50) = 250 cumulative; delta on the third call was 200.
assert tracker._state.contribution.tokens_saved_rtk == 250
assert tracker._last_rtk_tokens_saved == 250
# ---------------------------------------------------------------------------
# Test 2 — ``tokens_saved_rtk = 0`` when stats endpoint returns None
# ---------------------------------------------------------------------------
def test_rtk_stats_none_yields_zero_delta(monkeypatch: pytest.MonkeyPatch) -> None:
"""No RTK selected / installed — contribution stays at zero, no throw."""
tracker = _build_tracker(monkeypatch)
monkeypatch.delenv(tracker_module._RTK_WIRING_ENV, raising=False)
_stub_rtk_stats(monkeypatch, [None, None])
tracker.update_contribution()
tracker.update_contribution()
assert tracker._state.contribution.tokens_saved_rtk == 0
assert tracker._last_rtk_tokens_saved == 0
# ---------------------------------------------------------------------------
# Test 3 — monotonic advancement; no replay on flat poll
# ---------------------------------------------------------------------------
def test_last_rtk_advances_monotonically(monkeypatch: pytest.MonkeyPatch) -> None:
"""Two polls returning the same lifetime total contribute exactly once."""
tracker = _build_tracker(monkeypatch)
monkeypatch.delenv(tracker_module._RTK_WIRING_ENV, raising=False)
_stub_rtk_stats(
monkeypatch,
[
{"lifetime_tokens_saved": 42},
{"lifetime_tokens_saved": 42}, # no movement
{"lifetime_tokens_saved": 42}, # still no movement
],
)
tracker.update_contribution()
assert tracker._state.contribution.tokens_saved_rtk == 42
assert tracker._last_rtk_tokens_saved == 42
tracker.update_contribution()
assert tracker._state.contribution.tokens_saved_rtk == 42 # unchanged
assert tracker._last_rtk_tokens_saved == 42
tracker.update_contribution()
assert tracker._state.contribution.tokens_saved_rtk == 42
assert tracker._last_rtk_tokens_saved == 42
def test_counter_regression_rebaselines_without_negative_delta(
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""RTK DB rebuild drops the lifetime total — re-baseline, do not subtract."""
tracker = _build_tracker(monkeypatch)
monkeypatch.delenv(tracker_module._RTK_WIRING_ENV, raising=False)
_stub_rtk_stats(
monkeypatch,
[
{"lifetime_tokens_saved": 500},
{"lifetime_tokens_saved": 100}, # regression!
{"lifetime_tokens_saved": 150},
],
)
tracker.update_contribution()
assert tracker._state.contribution.tokens_saved_rtk == 500
assert tracker._last_rtk_tokens_saved == 500
tracker.update_contribution()
# Regression: contribution stays at 500 (no negative subtraction).
assert tracker._state.contribution.tokens_saved_rtk == 500
# Baseline now points at the new (smaller) lifetime total so subsequent
# polls can compute a meaningful delta.
assert tracker._last_rtk_tokens_saved == 100
tracker.update_contribution()
# 150 - 100 = 50 new delta; contribution = 500 + 50 = 550.
assert tracker._state.contribution.tokens_saved_rtk == 550
assert tracker._last_rtk_tokens_saved == 150
# ---------------------------------------------------------------------------
# Test 4 — transient exception in the stats endpoint
# ---------------------------------------------------------------------------
def test_rtk_stats_exception_zero_delta_no_throw(
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""A raised ``_get_rtk_stats()`` is caught, logged, and yields 0 delta."""
tracker = _build_tracker(monkeypatch)
monkeypatch.delenv(tracker_module._RTK_WIRING_ENV, raising=False)
def boom() -> dict[str, Any] | None:
raise RuntimeError("transient subprocess failure")
monkeypatch.setattr("headroom.proxy.helpers._get_rtk_stats", boom)
# Must not raise.
tracker.update_contribution()
assert tracker._state.contribution.tokens_saved_rtk == 0
assert tracker._last_rtk_tokens_saved == 0
# ---------------------------------------------------------------------------
# Test 5 — explicit env-var opt-out
# ---------------------------------------------------------------------------
def test_disabled_env_returns_zero(monkeypatch: pytest.MonkeyPatch) -> None:
"""``HEADROOM_RTK_WIRING=disabled`` skips the poll entirely."""
tracker = _build_tracker(monkeypatch)
monkeypatch.setenv(tracker_module._RTK_WIRING_ENV, "disabled")
polls = _stub_rtk_stats(
monkeypatch,
[{"lifetime_tokens_saved": 999}],
)
tracker.update_contribution()
# Stats endpoint never called when wiring is disabled.
assert polls[0] == 0
assert tracker._state.contribution.tokens_saved_rtk == 0
assert tracker._last_rtk_tokens_saved == 0
# ---------------------------------------------------------------------------
# Test 6 — explicit override from caller (back-compat for callers that
# already know the RTK delta out-of-band).
# ---------------------------------------------------------------------------
def test_explicit_rtk_override_skips_poll(monkeypatch: pytest.MonkeyPatch) -> None:
"""Caller-supplied ``tokens_saved_rtk`` short-circuits the poll."""
tracker = _build_tracker(monkeypatch)
monkeypatch.delenv(tracker_module._RTK_WIRING_ENV, raising=False)
polls = _stub_rtk_stats(monkeypatch, [{"lifetime_tokens_saved": 999}])
tracker.update_contribution(tokens_saved_rtk=17)
# Stats endpoint not consulted when the caller passes an explicit value.
assert polls[0] == 0
assert tracker._state.contribution.tokens_saved_rtk == 17
assert tracker._last_rtk_tokens_saved == 0
# ---------------------------------------------------------------------------
# Test 7 — cli_filtering decoupled from rtk
# ---------------------------------------------------------------------------
def test_cli_filtering_no_longer_mirrors_rtk(monkeypatch: pytest.MonkeyPatch) -> None:
"""Pre-PR-G2 bug: ``cli_filtering`` and ``rtk`` were always equal.
After PR-G2 they are independent counters fed by separate sources.
"""
tracker = _build_tracker(monkeypatch)
monkeypatch.delenv(tracker_module._RTK_WIRING_ENV, raising=False)
_stub_rtk_stats(monkeypatch, [{"lifetime_tokens_saved": 25}])
tracker.update_contribution(tokens_saved_cli_filtering=8)
assert tracker._state.contribution.tokens_saved_cli_filtering == 8
# rtk comes from the polled delta, not from cli_filtering.
assert tracker._state.contribution.tokens_saved_rtk == 25