diff --git a/apps/p2/docs/tree.md b/apps/p2/docs/tree.md
index df965bfd2..0a557957d 100644
--- a/apps/p2/docs/tree.md
+++ b/apps/p2/docs/tree.md
@@ -115,7 +115,9 @@ node:
- Web: "Edit" beside the owner's view of a user message (on hover; always shown on touch screens) and "Branch from
here" under an answer, in the main conversation. Under the session in the sidebar, from two branches on, one row per
branch (`Sessions` rows' `branches`: the stored labels, null for the session title, newest first in a stable order,
- the current one marked in place); choosing one switches the session to its end (`SessionTree.select`). The worker
+ the current one marked in place), behind the session row's expand control, which also shows its subagents
+ (collapsed by default, expanded while a subagent is shown); choosing one switches the session to its end
+ (`SessionTree.select`). The worker
reports `p2.main` (`treeSelf`: `main` and the branches with their labels) at start and whenever a commit changes it.
- Search indexes each branch's own entries (after its fork point).
diff --git a/apps/p2/src/web/Drawer.tsx b/apps/p2/src/web/Drawer.tsx
index d2aba978f..af88549b2 100644
--- a/apps/p2/src/web/Drawer.tsx
+++ b/apps/p2/src/web/Drawer.tsx
@@ -71,8 +71,8 @@ function ThemeButton() {
}
/**
- * A session's `/tree` branches (docs/tree.md), from two on, newest first in a stable order: switching only moves the
- * "current" mark. Choosing another branch switches the session to it (`onBranch`, the owner's); the pencil beside a
+ * A session's `/tree` branches (docs/tree.md), newest first in a stable order: switching only moves the "current" mark.
+ * Shown from two branches on, behind the session row's expand control (`hidden` while collapsed). Choosing another branch switches the session to it (`onBranch`, the owner's); the pencil beside a
* row renames it (`onRenameBranch`). A branch without a label (conversation 1's default) shows the session title.
*/
function BranchRows({
@@ -82,6 +82,7 @@ function BranchRows({
onOpen,
onBranch,
onRenameBranch,
+ hidden,
}: {
session: SessionSummary;
conversationId: number;
@@ -89,10 +90,10 @@ function BranchRows({
onOpen: (id: string, conversationId?: number) => void;
onBranch: (id: string, conversationId: number) => void;
onRenameBranch?: (id: string, conversationId: number) => void;
+ hidden: boolean;
}) {
- if (session.branches.length < 2) return null;
return (
-
+
{session.branches.map((branch) => {
const current = branch.conversation === session.main;
const label = branch.label ?? session.title;
@@ -151,11 +152,13 @@ function SessionRow({
archived?: boolean;
children: ReactNode;
}) {
- // A subagent shown expands its session's list.
- const [expanded, setExpanded] = useState(conversationId !== session.main);
+ // One control expands a session's branch rows and its subagents; a subagent shown expands them. Not any conversation
+ // but the main one: right after a `/tree` switch the page shows the new branch before the row names it main.
+ const showsSubagent = session.subagents.some((agent) => agent.conversationId === conversationId);
+ const [expanded, setExpanded] = useState(showsSubagent);
useEffect(() => {
- if (conversationId !== session.main) setExpanded(true);
- }, [conversationId, session.main]);
+ if (showsSubagent) setExpanded(true);
+ }, [showsSubagent]);
// One-shot agents are opened from their script's tool card; archived subagents wait behind their own row.
const listed = (archived ? [] : session.subagents)
.filter((agent) => agent.kind !== "agent")
@@ -164,6 +167,8 @@ function SessionRow({
const stored = listed.filter((agent) => agent.archived);
const [showStored, setShowStored] = useState(false);
const storedOpen = showStored || stored.some((agent) => agent.conversationId === conversationId);
+ const branches = onBranch !== undefined && !archived && session.branches.length >= 2;
+ const nested = [branches && "branches", listed.length > 0 && "subagents"].filter(Boolean).join(" and ");
const row = (agent: (typeof listed)[number]) => (