Skip to content

fix: attribute parallel Devin subagents to their spawn calls - #1728

Merged
chuks-qua merged 1 commit into
mainfrom
fix/devin-parallel-subagent-attribution
Sep 21, 2026
Merged

chuks-qua merged 1 commit into
mainfrom
fix/devin-parallel-subagent-attribution

Conversation

@chuks-qua

@chuks-qua chuks-qua commented Sep 21, 2026

Copy link
Copy Markdown
Contributor

What

Devin ACP emits subagent_started lifecycle updates in spawn order, keyed by short agent IDs. The event mapper paired each update with the most recent pending run_subagent call, 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_subagent call per subagent_started update (FIFO), matching the observed wire order. A dead splice in subagentCompletedEvents was removed; the shifted call can never still be pending at completion time.

Regression coverage added at both layers:

  • Mapper test: two parallel run_subagent calls must attribute subagent_started updates to call-a then call-b in spawn order.
  • Narrative test: in-flight subagent children (Devin child markers never receive their own terminal update) must not leak into top-level active-tool rows, 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 captured devin acp traffic.

UI Changes

Before (user capture): every narrative row stuck in an active state.

After (Electron, ACP fixture run_subagent sequence): nested Survey fixture files subagent rows all reach finished, the final response ACP 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-narrative fixture CLI, sent a subagent prompt in a fresh fixture-repo thread, confirmed nested completion and reloaded persistence. Persisted toolCallRecord rows show fx-agent-1 parented to fx-agent and children parented to fx-agent-1, all completed.

Known low-probability gaps (pre-existing, documented in review): a nested run_subagent inside a subagent shares the same FIFO and could misattribute if its subagent_started interleaves with a pending top-level one; a run_subagent whose subagent_started never arrives leaves a stale FIFO head. Real captured traffic shows neither pattern.

Before: every narrative row stuck active

After: nested subagent rows finish and final response renders

After reload: persisted order identical, nothing stuck active


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

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.
@chuks-qua
chuks-qua merged commit 360b8f3 into main Sep 21, 2026
6 checks passed
@chuks-qua
chuks-qua deleted the fix/devin-parallel-subagent-attribution branch September 21, 2026 16:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant