Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/copilot_usage/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
)
Expand Down
28 changes: 28 additions & 0 deletions tests/copilot_usage/test_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)


# ---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
Expand Down
Loading