fix: attribute parallel Devin subagents to their spawn calls - #1728
Merged
Merged
Conversation
Devin emits subagent_started lifecycle updates in spawn order, but the mapper paired each one with the most recent pending run_subagent call. With parallel subagents every agent row attached to the wrong parent, which broke nested attribution and left child activity projected against an unrelated call. Consume the oldest unresolved run_subagent instead. Also adds narrative coverage pinning that in-flight subagent children never leak into top-level active-tool rows while still rendering nested under their agent.
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.
What
Devin ACP emits
subagent_startedlifecycle updates in spawn order, keyed by short agent IDs. The event mapper paired each update with the most recent pendingrun_subagentcall, so parallel subagents all attached to the newest spawn call. Child tool markers then nested under the wrong parent, corrupting the narrative hierarchy.The mapper now consumes the oldest unresolved
run_subagentcall persubagent_startedupdate (FIFO), matching the observed wire order. A dead splice insubagentCompletedEventswas removed; the shifted call can never still be pending at completion time.Regression coverage added at both layers:
run_subagentcalls must attributesubagent_startedupdates tocall-athencall-bin spawn order.active-toolrows, and must still render nested under their agent.Why
The reported defect: when the Devin provider triggered subagents, every narrative element appeared "currently active" — unresolved child calls surfaced as top-level
Reading files...rows that never settled. The parenting fix for the underlying symptom landed in #1724; this PR fixes the remaining parallel-attribution defect found while replaying real captureddevin acptraffic.UI Changes
Before (user capture): every narrative row stuck in an active state.
After (Electron, ACP fixture
run_subagentsequence): nestedSurvey fixture filessubagent rows all reachfinished, the final responseACP fixture turn complete.renders normally, and a reload shows the identical persisted order with nothing stuck active.Config Changes
None.
Review Notes
Verified end-to-end in the owned Electron app: enabled Devin pointed at the
acp-narrativefixture CLI, sent a subagent prompt in a fresh fixture-repo thread, confirmed nested completion and reloaded persistence. PersistedtoolCallRecordrows showfx-agent-1parented tofx-agentand children parented tofx-agent-1, allcompleted.Known low-probability gaps (pre-existing, documented in review): a nested
run_subagentinside a subagent shares the same FIFO and could misattribute if itssubagent_startedinterleaves with a pending top-level one; arun_subagentwhosesubagent_startednever arrives leaves a stale FIFO head. Real captured traffic shows neither pattern.Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.