Skip to content

feat(web): Prism spawns, collapsed child tree and parent breadcrumb (#17) - #18

Merged
lukemaj merged 2 commits into
mainfrom
feat/17-agents-panel
Sep 25, 2026
Merged

lukemaj merged 2 commits into
mainfrom
feat/17-agents-panel

Conversation

@lukemaj

@lukemaj lukemaj commented Sep 25, 2026

Copy link
Copy Markdown

Closes #17.

The Agents panel listed every child thread as a direct spawn, so threads Model Router (Prism) started for a planner looked like the planner's own spawns. It also had no way to see a child's own children, and a child thread's header gave no route back to its parent.

What changed

  • Prism spawns section. Router threads are recognized from the [model-router job <id> <kind> on route <route>; planner thread <id>] tag in their first user message. A thread's shell carries no such metadata, and router titles are regenerated after the first turn, so the tag is the only stable marker. The panel reads each child thread once through the normal thread-detail atom, caches the parsed tag (or "not a router thread") in memory, then drops the subscription. Router threads are grouped by job; the job label shows request id, aggregate status and route (the dispatcher's route). Everything else stays under "Direct spawns". A thread whose tag is not read yet shows under Direct spawns until the read completes.
  • Collapsed tree. A row whose thread has live child threads (by parentThreadId if a shell ever carries it, else the sub.<parent>.<suffix> id) shows a ▸ N chevron, collapsed by default. Clicking it reveals compact one-line rows (status dot, title, model), each with its own chevron for deeper levels. Nothing expands on its own. Rows still open their thread.
  • Header breadcrumb. A child thread's header reads project / parent title / child title. The parent title links to the parent, and a small menu next to it switches to sibling child threads. Threads the user started are unchanged.

Logic lives in fork-owned files: AgentThreadTree.logic.ts (pure functions plus tests), AgentThreadTree.tsx and chat/ThreadParentCrumbs.tsx. Upstream edits: AgentsPanel.tsx (already allowlisted) and one import plus one JSX line in chat/ChatHeader.tsx (added to scripts/fork-upstream-edits.txt and docs/fork.md).

Not in scope: opening harness-internal subagents read-only (deferred per the Issue), and the mobile client, which has no Agents panel for child threads yet.

Proof

Local, in the worktree (Node 26, pnpm 11.10.0, ELECTRON_RUN_AS_NODE unset):

  • pnpm install --frozen-lockfile: pass
  • pnpm exec vp run -r typecheck: pass
  • pnpm exec vp lint: pass (no warnings in touched lines)
  • pnpm exec vp fmt --check: pass
  • vp test run AgentThreadTree.logic.test.ts subagentThreads.test.ts chat/ChatHeader.test.ts: 20 tests pass (tag parsing, section assignment, tree nesting and toggle state, shell status, breadcrumb links)
  • scripts/fork-check.sh: OK

Live, on an isolated dev instance (server 127.0.0.1:3791, T3CODE_HOME=/tmp/agents-panel-t3home seeded with a VACUUM INTO snapshot of real data, headless Chrome with a fresh profile). Two grandchild threads were created under the router dispatcher thread with a normal thread.create command to exercise nesting.

  • Planner thread with job router-80-release-t3: the panel shows Prism spawns with router-80-release-t3 · Failed · luna/max and the dispatcher plus two worker rows; no Direct spawns section, since the planner spawned nothing itself.
  • The dispatcher row shows a collapsed ▸ 2 chevron (aria-expanded=false, 0 child rows). Clicking it shows Dispatcher helper: run proof and Dispatcher helper: review diff (both gpt-5.6-luna · max); clicking again hides them (0 rows).
  • Dispatcher thread header: model-router / Continue Chromeria Handoff Plan / Fix Release Verification False Failures. The sibling menu lists the two worker threads; choosing one opened sub.…f40b7340, and clicking the parent crumb returned to the planner thread.

Screenshots were kept local because they contain private job prompts and paths from real data: /tmp/agents-panel-shots/01-prism-spawns-collapsed.png, 02-child-tree-expanded.png, 03-child-breadcrumb.png, 04-sibling-menu.png.

Built with Claude Code (Claude Opus 5.5).

🤖 Generated with Claude Code

)

The Agents panel now separates threads Model Router (Prism) started for
this thread from the thread's own spawns, grouped by job with status and
route. Router threads are recognized from the [model-router job ...] tag
in their first message, read once per thread and cached. Rows with child
threads show a collapsed chevron with the child count that reveals
compact nested rows. A child thread's header shows the parent title as a
link plus a menu to switch between siblings.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XL labels Sep 25, 2026
@github-actions

github-actions Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire 13.5 KiB 13.5 KiB +2 B (+0.0%) 15.1 KiB ✅
Codex Thread snapshot wire 7.1 KiB 7.1 KiB 0 B (0.0%) 7.3 KiB ✅
Codex Live turn WebSocket wire 6.4 KiB 6.4 KiB +2 B (+0.0%) 7.8 KiB ✅
Codex Live turn WebSocket decoded 56.2 KiB 56.2 KiB 0 B (0.0%) 66.4 KiB ✅
Codex Live turn messages 9 9 0 (0.0%) 21 ✅
Claude Total thread wire 13.5 KiB 13.5 KiB +6 B (+0.0%) 15.1 KiB ✅
Claude Thread snapshot wire 7.1 KiB 7.1 KiB −6 B (−0.1%) 7.3 KiB ✅
Claude Live turn WebSocket wire 6.4 KiB 6.5 KiB +12 B (+0.2%) 7.8 KiB ✅
Claude Live turn WebSocket decoded 57.0 KiB 57.0 KiB 0 B (0.0%) 66.4 KiB ✅
Claude Live turn messages 9 9 0 (0.0%) 21 ✅

Baseline: 43daf00 · PR result: c9f8dbc · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 113.9 KiB
  • Claude decoded thread snapshot: 114.6 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@lukemaj
lukemaj merged commit fc62c05 into main Sep 25, 2026
18 checks passed
@lukemaj
lukemaj deleted the feat/17-agents-panel branch September 25, 2026 17:05
lukemaj added a commit that referenced this pull request Sep 27, 2026
) (#18)

* feat(web): Prism spawns, collapsed child tree and parent breadcrumb (#17)

The Agents panel now separates threads Model Router (Prism) started for
this thread from the thread's own spawns, grouped by job with status and
route. Router threads are recognized from the [model-router job ...] tag
in their first message, read once per thread and cached. Rows with child
threads show a collapsed chevron with the child count that reveals
compact nested rows. A child thread's header shows the parent title as a
link plus a menu to switch between siblings.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(web): keep Agents tree internals unexported for knip (#17)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
lukemaj added a commit that referenced this pull request Sep 27, 2026
) (#18)

* feat(web): Prism spawns, collapsed child tree and parent breadcrumb (#17)

The Agents panel now separates threads Model Router (Prism) started for
this thread from the thread's own spawns, grouped by job with status and
route. Router threads are recognized from the [model-router job ...] tag
in their first message, read once per thread and cached. Rows with child
threads show a collapsed chevron with the child count that reveals
compact nested rows. A child thread's header shows the parent title as a
link plus a menu to switch between siblings.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(web): keep Agents tree internals unexported for knip (#17)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
lukemaj added a commit that referenced this pull request Sep 27, 2026
) (#18)

* feat(web): Prism spawns, collapsed child tree and parent breadcrumb (#17)

The Agents panel now separates threads Model Router (Prism) started for
this thread from the thread's own spawns, grouped by job with status and
route. Router threads are recognized from the [model-router job ...] tag
in their first message, read once per thread and cached. Rows with child
threads show a collapsed chevron with the child count that reveals
compact nested rows. A child thread's header shows the parent title as a
link plus a menu to switch between siblings.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(web): keep Agents tree internals unexported for knip (#17)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Agents panel: Prism spawns section, collapsed child tree, parent breadcrumb

1 participant