diff --git a/src/copilot_usage/parser.py b/src/copilot_usage/parser.py index 43a49b82..f0ed8f87 100644 --- a/src/copilot_usage/parser.py +++ b/src/copilot_usage/parser.py @@ -957,8 +957,12 @@ def _build_completed_summary( active_model_calls=( resume.post_shutdown_turn_starts if resume.session_resumed else 0 ), - active_user_messages=resume.post_shutdown_user_messages, - active_output_tokens=resume.post_shutdown_output_tokens, + active_user_messages=( + resume.post_shutdown_user_messages if resume.session_resumed else 0 + ), + active_output_tokens=( + resume.post_shutdown_output_tokens if resume.session_resumed else 0 + ), shutdown_cycles=shutdown_cycles, events_path=events_path, ) diff --git a/tests/copilot_usage/test_parser.py b/tests/copilot_usage/test_parser.py index c1516253..95a3a91f 100644 --- a/tests/copilot_usage/test_parser.py +++ b/tests/copilot_usage/test_parser.py @@ -6470,6 +6470,34 @@ def test_stale_resume_time_cleared_across_shutdowns(self, tmp_path: Path) -> Non assert fp.last_resume_time is None assert fp.post_shutdown_user_messages == 1 + def test_completed_session_zeroes_active_counters_despite_post_shutdown_values( + self, tmp_path: Path + ) -> None: + """_build_completed_summary must zero active counters when session_resumed=False.""" + from copilot_usage.models import has_active_period_stats + + p = tmp_path / "s" / "events.jsonl" + _write_events(p, _START_EVENT, _USER_MSG, _SHUTDOWN_EVENT) + events = parse_events(p) + fp = _first_pass(events) + + # Manually construct a _ResumeInfo with session_resumed=False but + # non-zero post-shutdown counters — the invariant violation scenario. + resume = _ResumeInfo( + session_resumed=False, + post_shutdown_output_tokens=500, + post_shutdown_turn_starts=3, + post_shutdown_user_messages=2, + last_resume_time=None, + ) + summary = _build_completed_summary(fp, name=None, resume=resume, events=events) + + assert summary.is_active is False + assert summary.active_model_calls == 0 # already guarded + assert summary.active_user_messages == 0 # must be 0 regardless + assert summary.active_output_tokens == 0 # must be 0 regardless + assert not has_active_period_stats(summary) + # --------------------------------------------------------------------------- # ---------------------------------------------------------------------------