diff --git a/CHANGELOG.md b/CHANGELOG.md index 04bcd17f..4a6a9dde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 3.5.36 - 2026-08-09 (Patch) + +Release impact: Patch because this polishes the shipped subagent panel without changing its contracts or lifecycle behavior. + +- Refined the subagent Command Deck with compact lifecycle timing, a clearer progress timeline, and focused browser coverage for active and orphaned states. + ## 3.5.35 - 2026-08-09 (Patch) Release impact: Patch because this adds regression coverage for shipped runtime safety and subagent UI behavior without changing public contracts. diff --git a/apps/web/src/components/SubagentsPanel.browser.tsx b/apps/web/src/components/SubagentsPanel.browser.tsx index 25ab0c71..528474a7 100644 --- a/apps/web/src/components/SubagentsPanel.browser.tsx +++ b/apps/web/src/components/SubagentsPanel.browser.tsx @@ -129,6 +129,15 @@ describe("SubagentsPanel browser presentation", () => { expect.stringContaining("Failed"), ]), ); + expect( + rosterButtons().find((button) => button.textContent?.includes("Repository explorer")) + ?.textContent, + ).toContain("Active ·"); + expect( + rosterButtons().find((button) => button.textContent?.includes("Detached reviewer")) + ?.textContent, + ).not.toContain("Orphaned ·"); + expect(document.querySelectorAll("time")).toHaveLength(2); await page.getByRole("button", { name: /^Detached reviewer/ }).click(); await expect.element(page.getByText("Tracking lost", { exact: true })).toBeVisible(); diff --git a/apps/web/src/components/SubagentsPanel.tsx b/apps/web/src/components/SubagentsPanel.tsx index 8a582a19..9581b789 100644 --- a/apps/web/src/components/SubagentsPanel.tsx +++ b/apps/web/src/components/SubagentsPanel.tsx @@ -2,19 +2,7 @@ import * as Schema from "effect/Schema"; import { memo, useEffect, useMemo, useRef, useState } from "react"; import type { OrchestrationThreadActivity, ScopedThreadRef } from "@neokod/contracts"; import { type TimestampFormat } from "@neokod/contracts/settings"; -import { - CheckIcon, - EyeIcon, - LoaderIcon, - SearchIcon, - SparklesIcon, - SquarePenIcon, - TerminalIcon, - TriangleAlertIcon, - UnplugIcon, - WrenchIcon, - XIcon, -} from "lucide-react"; +import { CheckIcon, LoaderIcon, TriangleAlertIcon, UnplugIcon, XIcon } from "lucide-react"; import { cn } from "~/lib/utils"; import { useLocalStorage } from "~/hooks/useLocalStorage"; import { deriveSubagentCards } from "../session-logic"; @@ -31,7 +19,6 @@ import { type ResolvedSubagentCard, type SubagentIconStatus, } from "./SubagentsPanel.logic"; -import { deriveToolIconKindFromName, type ToolCallIconKind } from "./chat/ToolCallLabel.logic"; import { Badge } from "./ui/badge"; import { ScrollArea } from "./ui/scroll-area"; import { Toggle, ToggleGroup } from "./ui/toggle-group"; @@ -45,16 +32,6 @@ function toPlainPreview(text: string): string { return text.replace(/`+/g, "").trim(); } -function subagentProgressIcon(iconKind: ToolCallIconKind): React.ReactNode { - const className = "mt-0.5 size-3 shrink-0 text-muted-foreground/50"; - if (iconKind === "terminal") return ; - if (iconKind === "search") return ; - if (iconKind === "eye") return ; - if (iconKind === "square-pen") return ; - if (iconKind === "sparkles") return ; - return ; -} - function subagentStatusIcon(status: SubagentIconStatus): React.ReactNode { if (status === "completed") { return ( @@ -247,11 +224,14 @@ const SubagentsPanel = memo(function SubagentsPanel({ ) : null} - - {card.lifecycle.label} - - {timingLabel(card, timestampFormat)} - + + {card.lifecycle.label} + {card.lifecycle.phase === "orphaned" ? null : ( + <> + · + {timingLabel(card, timestampFormat)} + + )}