diff --git a/src/gateway/server.chat.gateway-server-chat.test.ts b/src/gateway/server.chat.gateway-server-chat.test.ts
index 4e569ddf30a8..1a4433724742 100644
--- a/src/gateway/server.chat.gateway-server-chat.test.ts
+++ b/src/gateway/server.chat.gateway-server-chat.test.ts
@@ -2674,10 +2674,10 @@ describe("gateway server chat", () => {
8_000,
);
blockedReply.resolve();
- await waitForAgentRunOk(runId);
const settledEvent = await settledSessionChange.catch(() => {
throw new Error("Gateway did not publish settled run ownership after chat.send cleanup");
});
+ await waitForAgentRunOk(runId);
expectRecordFields(settledEvent.payload, {
activeRunIds: [],
hasActiveRun: false,
diff --git a/ui/src/components/app-sidebar-session-navigation.ts b/ui/src/components/app-sidebar-session-navigation.ts
index 55a106a3f4b7..f0e70b298136 100644
--- a/ui/src/components/app-sidebar-session-navigation.ts
+++ b/ui/src/components/app-sidebar-session-navigation.ts
@@ -231,11 +231,12 @@ export class AppSidebarSessionNavigationElement extends AppSidebarBase {
pending.push(...session.children);
if (
session.childSessionKeys.length > 0 &&
- this.isSessionChildrenExpanded(session) &&
+ (session.visuallyActive || this.isSessionChildrenExpanded(session)) &&
!this.sessionData.loadedChildSessionKeys.has(session.key) &&
!this.sessionData.childSessionErrorsByParent.has(session.key) &&
!this.sessionData.loadingChildSessionKeys.has(session.key)
) {
+ // Selected collapsed rows need child liveness so delegated work does not look finished.
void this.sessionData.loadChildSessions(session.key);
}
}
diff --git a/ui/src/components/session-attention-presentation.ts b/ui/src/components/session-attention-presentation.ts
index 5c0ecd2daa0b..1aa561699464 100644
--- a/ui/src/components/session-attention-presentation.ts
+++ b/ui/src/components/session-attention-presentation.ts
@@ -50,18 +50,22 @@ export function renderSessionRunSpinner(showTitle = true) {
>`;
}
+export function sessionHasRunningWork(session: SidebarRecentSession): boolean {
+ return session.hasActiveRun || session.runningChildCount > 0;
+}
+
export function renderSessionState(session: SidebarRecentSession, showTitle = true) {
- if (session.hasActiveRun) {
- if (session.status === "queued") {
- const label = t("sessionsView.statusQueued");
- return html``;
- }
+ if (session.hasActiveRun && session.status === "queued") {
+ const label = t("sessionsView.statusQueued");
+ return html``;
+ }
+ if (sessionHasRunningWork(session)) {
return renderSessionRunSpinner(showTitle);
}
if (!session.isChild) {
diff --git a/ui/src/components/session-leading-indicator.ts b/ui/src/components/session-leading-indicator.ts
index cb67965dd157..bbae39e9ce89 100644
--- a/ui/src/components/session-leading-indicator.ts
+++ b/ui/src/components/session-leading-indicator.ts
@@ -5,6 +5,7 @@ import { icons } from "./icons.ts";
import {
renderSessionAttentionIcon,
renderSessionState,
+ sessionHasRunningWork,
} from "./session-attention-presentation.ts";
import {
renderSessionGlyph,
@@ -97,12 +98,14 @@ export function describeSessionTrailingState(
session: SidebarRecentSession,
pullRequestState: SessionPullRequestIndicatorState,
) {
+ const runningLabel =
+ session.hasActiveRun && session.status === "queued"
+ ? t("sessionsView.statusQueued")
+ : t("sessionsView.activeRun");
return [
session.forkSource ? t("sessionsView.forkedSession") : "",
pullRequestState === "none" ? "" : pullRequestStateLabel(pullRequestState),
- session.hasActiveRun
- ? t(session.status === "queued" ? "sessionsView.statusQueued" : "sessionsView.activeRun")
- : "",
+ sessionHasRunningWork(session) ? runningLabel : "",
session.unread ? t("sessionsView.unread") : "",
]
.filter(Boolean)
@@ -124,7 +127,7 @@ export function renderSessionLeadingState(
trailingIndicator: TemplateResult | typeof nothing;
renderedOwnerId?: string;
} {
- const running = session.hasActiveRun;
+ const running = sessionHasRunningWork(session);
const trailingIndicator = session.isChild
? nothing
: renderSessionTrailingState(session, pullRequestState);
diff --git a/ui/src/e2e/session-management.sidebar.e2e.test.ts b/ui/src/e2e/session-management.sidebar.e2e.test.ts
index 0b196b37bddf..77059f187535 100644
--- a/ui/src/e2e/session-management.sidebar.e2e.test.ts
+++ b/ui/src/e2e/session-management.sidebar.e2e.test.ts
@@ -166,6 +166,9 @@ suite.define(() => {
const parent = page.locator(`[data-session-key="${parentKey}"]`);
await parent.waitFor({ state: "visible", timeout: 10_000 });
await expect.poll(() => page.locator(".sidebar-recent-session--child").count()).toBe(0);
+ await expect
+ .poll(() => parent.locator(".session-run-spinner").getAttribute("aria-label"))
+ .toBe("Active run");
await captureUiProof(page, "child-sessions-collapsed.png");
await parent.getByRole("button", { name: "Show 4 child sessions for Plan release" }).click();