diff --git a/CHANGELOG.md b/CHANGELOG.md index 72f2d2e..58d1193 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,15 @@ new version heading in the same commit. ## [Unreleased] +## [0.193.2] — 2026-07-14 +### Fixed +- **Sidebar "All" session badge now counts only genuinely live runs.** It was keyed off `isLive`, which + is deliberately broad — an interactive session that reported `done` but keeps an attachable pane reads + live so its dot stays green and reattachable. That inflated the badge with finished sessions whose tmux + panes were never reaped (some days old), so the count could read ~10 when only a handful were actually + running. The badge now mirrors the server's canonical `aliveSessionCount`: a session with stored status + `running` and a live (or unpollable) pane. Per-session dots/reattach affordances are unchanged. + ## [0.193.1] — 2026-07-14 ### Fixed - **Chat replies no longer stall on "thinking…" forever.** The v1 Chat surface delivered a follow-up by diff --git a/package-lock.json b/package-lock.json index 5b2c272..e94ab71 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "agent-os", - "version": "0.193.1", + "version": "0.193.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "agent-os", - "version": "0.193.1", + "version": "0.193.2", "license": "MIT", "bin": { "agent-os": "bin/agent-os" diff --git a/package.json b/package.json index 03446ff..0eb9479 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "agent-os", - "version": "0.193.1", + "version": "0.193.2", "description": "A generic, governed operating system for running autonomous agents safely across brands. Ships with a local web console.", "license": "MIT", "type": "commonjs", diff --git a/web/src/App.tsx b/web/src/App.tsx index f34fc80..e08bc80 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -997,7 +997,13 @@ function Console({ me }: { me: Member }) { const pendingApprovals = messages.filter(isActionRequired).length // Sessions where Claude is blocked waiting on the human — drives the per-session bell everywhere. const waiting = new Set(messages.filter((m) => m.type === 'notification' && m.status === 'open').map((m) => m.sessionId)) - const runningSessions = sessions.filter(isLive).length + // The sidebar "All" badge counts genuinely LIVE runs — a session actively RUNNING with a live pane — + // mirroring the server's canonical aliveSessionCount. `isLive` is deliberately broader (an interactive + // session that reported `done` but keeps an attachable pane reads live so its dot stays green + + // reattachable), which would inflate this badge with finished sessions whose panes were never reaped. + // A running row with a confirmed-dead pane (alive === false) is mid-reap → excluded; alive undefined + // (poll failed / launcher backend) falls back to the stored 'running' status. + const runningSessions = sessions.filter((s) => s.status === 'running' && s.alive !== false).length // The sidebar is a switcher over the sessions *I'm accountable for* — ones I started directly // (spawnedBy is my member id) OR ones a trigger spawned that run AS me (runAs): a Task I own that // auto-dispatched, a chat message I sent. Those have a `task:`/`automation:` provenance, so keying