Skip to content

Add per-session context-window donuts#125

Merged
0101 merged 8 commits into
mainfrom
monitor-contexts
Jul 20, 2026
Merged

Add per-session context-window donuts#125
0101 merged 8 commits into
mainfrom
monitor-contexts

Conversation

@0101

@0101 0101 commented Jul 20, 2026

Copy link
Copy Markdown
Owner

Problem

Agents can quietly fill their context window, and nothing on the dashboard surfaced it. Operators had no at-a-glance signal for which sessions are approaching their limit and should be wrapped up or resumed fresh.

Changes

Adds a context-window donut per live session across the dashboard, wired end-to-end from the SDK through to the UI.

Wire pipeline (SDK → UI)

  • src/Extension/reporting/extension.mjs — subscribe to session.usage_info and forward a new status-preserving usage_info wire kind (currentTokens, tokenLimit). A non-positive/non-finite limit is dropped; a negative current is clamped.
  • src/Server/SessionActivity.fs / SessionActivityService.fsSessionEvent.UsageInfo folds into SessionStatus.ContextUsage (a pure gauge; never changes status); DTO parse + kindText round-trip. In-memory only (ephemeral upstream, not persisted).

Per-session model (absorbs the tm-multi-dot branch)

  • src/Shared/Types.fsContextUsage with fraction / remainingFraction; new SessionDot { Status; ContextUsage option }; WorktreeStatus.Sessions replaces the per-worktree ContextUsage.
  • src/Server/CodingToolStatus.fsCodingToolResult.SessionStatuses built in fromPushSessions from the open, freshness-adjusted sessions (each keeps its own usage), ordered Working -> Waiting -> Idle then most-recently-seen.

Rendering

  • Each live session renders a donut whose arc = fraction of context remaining (a healthy low-usage session is a nearly full ring; one near its limit thins to a sliver), falling back to a plain status dot when a session has not reported usage.
  • Shown on worktree cards, the Overview band Agents row (donuts clustered per agent), and the drill-down chips. Collapsed repo headers keep per-session plain dots (too dense for arcs).

Why per-session (not per-worktree)

An earlier single per-worktree donut sourced usage from the collapsed "footer" session, so it blinked back to a solid circle whenever a newer session became the winner before reporting usage (the common case under CLI session churn). Keeping usage on each SessionDot removes the collapse and the blink.

Tests

  • New SessionStatuses coverage in CodingToolPushSourceTests (per-session ordering, each session keeps its own usage, stale/closed sessions excluded, empty for NoSession/retained fallback).
  • Updated OverviewDataTests, fixtures, and the mocked E2E JSON in ArchiveTests for the new Sessions field.
  • dotnet test src/Tests/Tests.fsproj --filter "Category=Fast" -> 1275 passed, 0 failed.

Rebased onto current main (includes #121-#124); clean, no conflicts.

0101 added 4 commits July 20, 2026 09:35
Each agent circle in the Overview band's Agents row now renders as a donut
filled to the agent's context-window occupancy (currentTokens / tokenLimit),
sourced from the SDK session.usage_info event through the push-status pipeline.
An agent that has not reported usage (or after a restart — the value is not
persisted) falls back to the solid circle.

- Shared: ContextUsage type + fraction helper; WorktreeStatus.ContextUsage.
- Reporting extension: subscribe to session.usage_info, forward it as a new
  status-preserving usage_info wire kind (currentTokens, tokenLimit).
- Server: SessionEvent.UsageInfo + status-preserving fold into
  SessionStatus.ContextUsage; wire DTO + parseEvent/kindText; thread through
  CodingToolResult -> WorktreeStatus. In-memory only (not persisted).
- Client: GroupMember carries the per-agent fraction; agentColumn renders a
  .overview-donut with an inline --ctx-fill; index.html conic-gradient donut.
- DemoFixture showcase values; tests for the fold, DTO parse, and aggregation.
Address focused-review findings F1-F4 (doc/spec staleness introduced by the
usage_info addition):
- docs/spec/session-status-push.md:147,156 - wire contract now lists
  currentTokens/tokenLimit and the usage_info -> UsageInfo mapping (7 -> 8).
- src/Server/SessionActivityService.fs - parseEvent/parseReport doc comments
  updated from seven/7 kinds to eight/8.
- src/Tests/SessionActivityServiceTests.fs - module summary updated to eight kinds.
The Agents-row donut now fills its accent arc to the fraction of context still free (ContextUsage.remainingFraction), so a healthy low-usage agent reads as a nearly full ring and one approaching its limit thins to a sliver — instead of a field of tiny slivers for the common low-usage case. fraction (used) stays as the truthful base; the view takes its complement and the CSS var is renamed --ctx-remaining.

Copilot-Session: eeeb328d-1083-4a2f-b9ff-f9362084eca8
Replace the single per-worktree context donut with one donut per live session across worktree cards, the Overview band Agents row, and the drill-down chips; collapsed repo headers show per-session plain dots. This absorbs the tm-multi-dot per-session-dot work (now obsolete) and dissolves the donut-blinks-to-solid bug: usage is kept per session instead of collapsed onto a single footer session that flipped to None whenever the winner changed.

- Shared: SessionDot { Status; ContextUsage option }; WorktreeStatus.Sessions replaces per-worktree ContextUsage.

- Server: CodingToolResult.SessionStatuses built in fromPushSessions from the open, freshness-adjusted sessions (each keeps its own usage), ordered Working->Waiting->Idle then most-recent; WorktreeApi + DemoFixture threaded through.

- Client: CardViews.sessionDots renders per-session donuts (dots on repo headers); OverviewData.GroupMember carries Sessions; OverviewBand clusters per-session donuts in the row and drill-down chips; index.html .ct-donut + --ctx-remaining.

- Tests: per-session SessionStatuses coverage; fixtures + mocked E2E JSON updated for the new field.

Copilot-Session: eeeb328d-1083-4a2f-b9ff-f9362084eca8
Copilot AI review requested due to automatic review settings July 20, 2026 07:40

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds per-session context-window usage indicators from the Copilot SDK through server aggregation to dashboard donuts.

Changes:

  • Adds usage_info ingestion and per-session context models.
  • Renders usage donuts across cards, Overview, and drill-downs.
  • Updates fixtures, tests, and specifications.
Show a summary per file
File Description
src/Extension/reporting/extension.mjs Forwards usage events.
src/Shared/Types.fs Adds usage and session-dot types.
src/Server/SessionActivity.fs Folds usage snapshots.
src/Server/SessionActivityService.fs Parses the new wire event.
src/Server/SessionActivityStore.fs Rehydrates usage as ephemeral.
src/Server/CodingToolStatus.fs Produces ordered session dots.
src/Server/WorktreeApi.fs Exposes sessions to clients.
src/Server/DemoFixture.fs Adds demonstration usage data.
src/Client/OverviewData.fs Carries sessions into Overview groups.
src/Client/OverviewBand.fs Renders Overview donuts.
src/Client/CardViews.fs Renders card and header session dots.
src/Client/index.html Styles dots and donuts.
src/Tests/WorktreeFixtures.fs Updates shared fixture shape.
src/Tests/SessionActivityTests.fs Tests usage folding.
src/Tests/SessionActivityStoreTests.fs Updates stored-status fixtures.
src/Tests/SessionActivityServiceTests.fs Tests wire parsing and validation.
src/Tests/OverviewDataTests.fs Tests session aggregation.
src/Tests/NavigationTests.fs Updates navigation fixtures.
src/Tests/EventProcessingTests.fs Updates event fixtures.
src/Tests/ConfirmModalTests.fs Updates modal fixtures.
src/Tests/CodingToolPushSourceTests.fs Tests per-session ordering and usage.
src/Tests/CanvasAwarenessTests.fs Updates canvas fixtures.
src/Tests/ArchiveTests.fs Updates archive models and JSON.
docs/spec/worktree-monitor.md Documents card donuts.
docs/spec/session-status-push.md Documents the wire contract.
docs/spec/beads-overview-band.md Documents Overview rendering.

Review details

  • Files reviewed: 26/26 changed files
  • Comments generated: 5
  • Review effort level: Medium

Comment on lines +119 to +121
// A pure gauge: record the latest occupancy, never touch Status (or any other field).
| UsageInfo(currentTokens, tokenLimit) ->
{ s with ContextUsage = Some { CurrentTokens = currentTokens; TokenLimit = tokenLimit } }
Comment thread src/Client/CardViews.fs
Comment on lines +35 to +37
prop.className $"ct-dot ct-donut {ctClassName s.Status}"
prop.title (ctTooltip s.Status)
prop.style [ style.custom ("--ctx-remaining", string (ContextUsage.remainingFraction usage)) ] ]
Comment on lines +118 to +119
prop.className [ "overview-circle"; "overview-donut"; accent ]
prop.style [ style.custom ("--ctx-remaining", string (ContextUsage.remainingFraction usage)) ] ]
Comment thread src/Client/OverviewBand.fs Outdated
Comment on lines +213 to +214
prop.className [ "overview-chip-dot"; "overview-donut" ]
prop.style [ style.custom ("--ctx-remaining", string (ContextUsage.remainingFraction usage)) ] ]
Comment on lines +114 to +119
match s.ContextUsage with
| Some usage ->
Html.span
[ prop.key key
prop.className [ "overview-circle"; "overview-donut"; accent ]
prop.style [ style.custom ("--ctx-remaining", string (ContextUsage.remainingFraction usage)) ] ]
0101 added 3 commits July 20, 2026 10:27
… progress-bar drilldown chips

- Overview band: flatten the per-worktree cluster so every session circle shares one uniform gap regardless of which worktree it belongs to.

- Cards: bump the per-session dots/donuts from 10px to 15px to match the band circles.

- Drill-down: drop the per-session chip donuts; each chip now fills its background as a subtle left-to-right progress bar to its most-loaded session's context usage (used), faint enough to preserve label contrast.

Copilot-Session: eeeb328d-1083-4a2f-b9ff-f9362084eca8
Flatten every worktree's per-session dots into a single row in the collapsed repo header (List.collect) with one uniform gap, instead of per-worktree .ct-dots clusters that spaced within-worktree dots tighter than across-worktree ones.

Copilot-Session: eeeb328d-1083-4a2f-b9ff-f9362084eca8
The Agents band previously grouped each worktree once, under its single collapsed activity/skill. Now grouping is per session: each live session lands in the group its OWN status and running skill classify to, so a worktree whose sessions differ (e.g. one running pr while two sit idle) splits across the matching groups instead of clumping. A group's count is its number of sessions, and a member carries only the subset of its sessions in that group.

- Shared: SessionDot gains Skill (the session's own running skill).

- Server: fromPushSessions threads each session's Skill into SessionStatuses.

- Client: sessionGroupKind classifies a session from its status/skill; aggregate folds per session; band circles render only the group's matching sessions.

- DemoFixture + tests updated; new tests cover split-across-groups, per-session count, and per-group session subsets.

Copilot-Session: eeeb328d-1083-4a2f-b9ff-f9362084eca8
@0101
0101 enabled auto-merge (squash) July 20, 2026 09:25
@0101
0101 disabled auto-merge July 20, 2026 09:34
@0101
0101 enabled auto-merge (squash) July 20, 2026 09:53
UsageInfo no longer shares the status last-write-wins clock: a dedicated apply branch updates ContextUsage on its own ContextUsageAt ordering clock, so a usage report can't block a slightly-earlier status transition nor be discarded by a newer one (both arrival orders covered).

Add per-session Sessions to the overview-band fixture plus E2E assertions for the donut arc (--ctx-remaining), multi-session clustering and the drill-down --ctx-used fill; the per-session aggregate had left the empty-Sessions fixture rendering no Agents section. Bump the ct-dot size assertion to 15px.

Copilot-Session: ec7f3da2-617e-41f5-9c1b-6ca9ddc73c65
@0101
0101 merged commit 2bda6ba into main Jul 20, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants