acpmux: an adopted host's running subagents keep their tags

Merged
TE
4d ago
+241-135

Summary

After a daemon restart, the new daemon adopts the running agent host (host_adopted). The hub's subagent tree (SubagentTree) started empty, so it no longer knew which subagents the chat was running. Until each subagent's next progress event, that subagent's lines reached clients without a tag (_meta.acpmux.subagent), so they read as the chat's own. The web pane then showed a helper's grep as the chat's own call. Leo saw this after a finished turn: "why does it say you're still running grep". #30416 (cf818b16) made the pane attribute updates by sessionId. This PR fixes the cause on the hub side, so the hub keeps the list.

  • adopt_held (hub/hosts.rs) now calls seed_subagents_from_log (hub/work_below.rs) before the host's replay reaches the tap. It rebuilds two things from the durable log, the same way the tap followed them live:
    • which subagents the chat started, so tagging continues from the first replayed line
    • which subagents still run, so the summary's subagentsRunning and subagentNames and the work-below state are right
  • A harness start, stop or exit ends the background subagents. A turn start ends the foreground ones. Both match live behaviour, and processes.rs read_processes rebuilds the same way.
  • New SubagentTree::adopt merges the rebuilt tree into the live one. A subagent the live tree already knows keeps its own state.
  • The head predicate for "this line may name a subagent" is now shared with open_work_reads (names_subagents). SubagentTree's background tests move to subagents_background_tests.rs, so the god-file-capped subagents.rs and hosts.rs shrink instead of growing.

Builds on #30439, which added the running-subagent counts that are now rebuilt too.

Test

tests/durable_agents.rs a_subagent_running_across_a_restart_keeps_its_tag_after_adoption. A turn starts subagent child-1 and its tool call. The daemon is killed and restarted, then adopts the host. The test checks that the summary still counts the subagent, then that the child's next line (tool_call_update cg-1) is tagged child-1.

Command: cargo test -p acpmux --test durable_agents a_subagent_running_across_a_restart_keeps_its_tag_after_adoption

  • Base plus test only (78a63f7): see the comment below
  • Head: see the comment below

Observed / Not run

Observed: rustfmt, prepush-gate, and the post-edit god-file check (no growth). The test results are in the comments.
Not run: the full acpmux suite locally (it runs through cmux-ci).

Changelog

Fixed: after an acpmux restart, a running subagent's activity no longer shows as the chat's own.

Agent session: agent session

šŸ¤– Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

Fixes running subagents losing their tags after a daemon restart adopts their host. The adopting daemon's subagent tree started empty, so until each subagent's next progress event its lines reached clients untagged and read as the chat's own activity.

Bug Fixes

  • adopt_held now rebuilds the subagent tree from the durable log before the host's replay reaches the tap, restoring which subagents the chat started and which still run.
  • Added SubagentTree::adopt to merge the rebuilt tree into the live one, keeping live state for subagents the tree already knows.
  • names_subagents is now shared between replay seeding and open_work_reads.
  • Moved SubagentTree's background tests to subagents_background_tests.rs so the file-size-capped subagents.rs and hosts.rs don't grow.