fix: count busy descendants in the agents-view subagents indicator - #1986
Merged
Merged
Conversation
The "N subagents running" indicator only tallied direct children whose row classified as running, so a busy grandchild under an idle intermediate child left every ancestor reading "N subagents" with a zero count. The tally is now a bottom-up pass over the built rows - the live per-descendant truth - replacing the direct-child increment. Indicator only, per policy: a session is Running when it works itself; idle ancestors of busy subtrees stay in Idle. Within Idle they now rank above plain idle rows, and a collapsed group's summary row renders its running count in the success color instead of dimmed so the busy subtree is discoverable without expanding. Diagnosis credit: Vincent Bailly (VincentBailly#9) traced the stale hasRunningRlmChildren snapshot and the row-walk mechanism; this adopts his walk for the indicator while rejecting the section promotion. RES-1253
The descendant tally read row sections after propagateHeartbeatStateToAncestors had promoted idle ancestors to running, so a heartbeat-active grandchild counted its promoted parent too. The tally now runs before the promotion pass and counts intrinsically busy rows only; once that propagation pass is deleted (#1967) the ordering is a no-op. RES-1253
The recursive tally threw RangeError on a deep child chain just by opening the agents view. The nesting loop assigns every row at most one parent, so the tree is a forest: a reverse breadth-first pass over one work list computes the same bottom-up counts iteratively, with the pre-promotion ordering kept. RES-1253
…dren Second half of the RES-1253 policy, user-approved: Running means the session you enter is doing work now. Delegated child work no longer classifies a session as running - the busy-descendant badge, count, and idle ranking from the first half carry the delegation signal. hasRunningRlmChildren loses its section-classification role in both owners: classifySessionRosterStatus composes busy from the session's own activity/isSessionActive, and isActiveSessionBusy (the worker's activity axis) no longer holds a settled parent at "working" for its children. The "subagents running" status label dies with the section it had to agree with. The field itself stays on the wire, and isSessionSummaryBusy keeps it on purpose for its residency and shutdown-safety consumers (worker eviction snapshots, empty-draft eviction, busy client-owned session counts, daemon stop confirmation). RES-1253
isActiveSessionBusy served two meanings after the classification change: the display activity axis (session's own work only, correct) and worker recovery plus draft-discard (where a running RLM child is live work that dies with the worker). The recovery journal recorded busy:false for a settled parent with a running child, so a worker death skipped its interruption record and notice. The shared predicate is deleted and each meaning gets one named owner: activeActivityForSession reads the session's own isSessionActive directly, and hasLiveSessionWork (own turn or running RLM child) backs recordWorkerRecoveryState and isDiscardableDraft. No caller can grab the wrong meaning blind. RES-1253
sethkarten
self-requested a review
September 3, 2026 15:20
sethkarten
previously approved these changes
Sep 3, 2026
Since Running means the session's own work, an idle parent of a running crew was branching into the delete path: killSubagent chose stop-vs- delete from the display section and stopAgentForDeletion treated activity==='working' as the only live work. Destructive actions are safety consumers of the display/safety split: one row-level hasLiveWork (own section running, busy descendants, or the wire running-children flag) now drives the stop-first branch, the deletion flow, and the confirmation verb. Also trimmed the tally comment to current behavior. RES-1253
Stopping a subagent row whose own run already settled reported 'Subagent already finished' while a nested descendant kept running: cancelRlmChildRun only cancelled the targeted run itself, and a fully released child (run removed, session retained) was never matched by id at all. Cancellation now descends where the tree lives: a settled target stops every running or queued run in its retained session's subtree (cancelRunningRlmDescendants, mirroring hasRunningRlmChildren's walk), and the returned flag stays truthful so the UI says stopped only when something stopped. RES-1253
Comment pass: multi-line narration cut to one-line invariant guards (destructive live-work gate, residency-vs-section busy split, worker- death live work) and code-readable notes deleted. Test pass: the direct- child indicator pin folded into the grandchild pin (the general case), which now also carries the idle-label and wire-flag assertions.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 5b536e7. Configure here.
Cancelling a live child run aborts it, and abort cascades into the child's ACTIVE runs - but running work retained under a settled descendant of that child was the end of the line: neither the cascade nor the cancel walk visited it. cancelRlmChildRun now descends into the target's session after cancelling it, and cancelRunningRlmDescendants descends at every node instead of treating running runs as leaves, so cancellation is exhaustive over the subtree regardless of each node's run state. The returned flag stays truthful. RES-1253
sethkarten
self-requested a review
September 3, 2026 20:57
sethkarten
approved these changes
Sep 3, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

The agents view's running-subagents indicator was blind past one level: a collapsed idle parent read "N subagents" with no running count while a grandchild streamed. The row-build tally counted only direct children, and the parent's own
hasRunningRlmChildrensnapshot freezes between its roster flushes, so busy work deeper in the tree was invisible to every ancestor — and the dimmed summary label made even the counted cases easy to miss. This PR fixes the indicator and, in the same stroke, settles the display policy it was violating.Policy: Running means the session you enter. A session is Running when it is itself doing work now; delegated work shows as the badge, the count, and the idle ranking — never as the section.
Indicator:
runningSubagentCountis now a bottom-up tally over the built rows — the view's live per-descendant truth — so a busy descendant at any depth counts on every ancestor, and the "N subagents running" title on a collapsed group is correct at any nesting level. The pass is iterative (each row has at most one parent, so a deep chain cannot overflow the stack). Within the Idle section, rows with busy descendants rank above plain idle rows, so a working subtree surfaces without lying about the parent's own state. A collapsed group's summary title renders in the success color when its count is non-zero, dim otherwise — existing style vocabulary, no new UI machinery.Classification:
hasRunningRlmChildrenloses its section-classification role. The roster classifier composes busy from the session's own activity/isSessionActive, and the worker's activity axis (renamedisActiveSessionBusytohasLiveSessionWork) no longer holds a settled parent at "working" for its children — a parent whose only activity is a delegated crew lists as Idle, at the top of Idle, with the badge. The "subagents running" status label is removed; a delegating idle session shows normal idle labeling.Deliberately unchanged — the safety half:
hasRunningRlmChildrenstays on the wire, andhasLiveSessionWorkkeeps counting it for every consumer where delegated work is live work: the supervisor's worker-eviction snapshot, empty-draft eviction, busy client-owned session counts, and the daemon stop/update confirmations. Killing a worker mid-delegation would kill the crew, so those gates still treat delegated work as busy; only the display axis changed. (The chat children-existence hint and the agent-observe "busy" status also keep the field; they are not section classification.)Net src: +41/−20 across five files.
Credit: diagnosis by Vincent Bailly — VincentBailly#9 traced the stale-snapshot mechanism and proposed the ancestor walk over live rows. This PR adopts that mechanism and deliberately rejects the section-promotion half per the display policy above.
Validation: pins for a busy grandchild counting on every idle ancestor, busy-descendant-first idle ranking, and the legible collapsed badge fail on main; a direct-child pin documents the non-promotion contract; one existing expectation updated intentionally (a root above a streaming child and grandchild now titles "2 subagents running"). agents-view (state/mode/roster/inactive-reply/missing-cwd), agent-roster, daemon-agent-roster, subagent-summary-line, daemon-session-list, interactive-mode-status — 371 tests green in a sanitized env; root
npm run checkgreen.Linear: RES-1253 https://linear.app/primeintellect/issue/RES-1253
Note
Medium Risk
Changes roster classification, agents-view destructive actions, and recursive RLM cancel behavior—user-visible status and stop semantics can shift for delegating parents, while worker recovery still treats delegated work as busy.
Overview
Agents view now treats Running as the session’s own work: parents that only delegate show as Idle, with subtree busy state surfaced via
runningSubagentCount, collapsed “N subagents running” titles (success styling when non-zero), and idle sort that puts rows with busy descendants first. The count is a bottom-up tally over nested rows so work at any depth rolls up to every ancestor; heartbeats stay out of that tally.Stop/delete UX gates on
hasLiveWork(own running section, descendant count, orhasRunningRlmChildren) so an idle-looking parent with a working crew still stops instead of delete.Daemon/roster display stops promoting parents to “working” solely because children run (
activeActivityForSession,classifySessionRosterStatus);hasLiveSessionWork(renamed fromisActiveSessionBusy) still treats delegated children as busy for recovery, draft discard, and similar safety paths.Cancellation extends
cancelRlmChildRunwithcancelRunningRlmDescendantsso stopping a child also cancels running/queued work under settled or retained sessions in the subtree.Reviewed by Cursor Bugbot for commit e071ab8. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Fix agents-view subagents indicator to count busy descendants recursively
buildAgentsViewRowsnow tallies running descendants across the full nested subtree via iterative breadth-first traversal, so collapsed summaries report total busy counts instead of only direct childrenclassifySessionRosterStatus,activeActivityForSession, andgetSessionStatusLabelno longer treat delegated child work as the parent's own running state; a resident parent with only running children is now idle for display while still counted as busy for recovery and draft-discard via the renamedhasLiveSessionWorkhelperclassifySessionRosterStatusremoves therunning-childflag from the accepted summary shape in agent-roster.ts; out-of-tree callers passing that flag will no longer influence display classificationChanges since #1986 opened
isRunningSessionSummaryhelper with newhasLiveWorkpredicate inAgentsViewModeclass [0bd4d19]AgentsViewMode.killSubagentmethod to use descendant activity when determining termination behavior [0bd4d19]AgentsViewModeto reflect live descendant work [0bd4d19]AgentSession.cancelRlmChildRunto cancel running or queued descendants when the targeted child run has already settled, and added a newAgentSession.cancelRunningRlmDescendantsmethod that recursively walks the session subtree to cancel all active descendants [0511890]AgentSession.cancelRlmChildRunandAgentSession.cancelRunningRlmDescendantsmethods in thecoding-agentpackage to always descend into child sessions and cancel running descendants regardless of whether the direct child is successfully cancelled or is currently running or queued [e071ab8]coding-agentpackage to validate that cancellation from a root session propagates to deeper descendants beneath active child sessions [e071ab8]Macroscope summarized 65d5d6e.