Skip to content

feat(delegation): wake the Coordinator when a delegated task finishes - #2278

Merged
chuks-qua merged 21 commits into
mainfrom
feat/issue-2217
Oct 22, 2026
Merged

chuks-qua merged 21 commits into
mainfrom
feat/issue-2217

Conversation

@chuks-qua

@chuks-qua chuks-qua commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

What

Before this change, a Coordinator that delegated a task with delegate_task heard nothing back. The child finished, failed, or waited on the user, and the Coordinator stayed idle until the user prompted it again.

Now the server wakes the Coordinator when a delegated task finishes, fails, is cancelled, or blocks on the user:

  • An idle Coordinator gets a new turn whose prompt holds the task report.
  • A running Coordinator gets the report as a steer, but only when the turn holds the task-tool lease and the provider can steer. Otherwise the report waits until the turn ends.
  • A child blocked on a question or tool approval shows in the Coordinator's composer dock labelled "From ", and the user answers it there. The Subagents panel shows the child as Waiting.
  • The timeline shows each wake-up as a "From " row with the status and a collapsible Prompt.

Each result is delivered once. A durable ledger on delegated_tasks records which result each Coordinator has seen:

on(task state change, turn end, boot)
  nudgeCoordinator (debounced 1 s, single flight, backoff on admission failure)
    candidates = tasks whose current notice key is not covered by notice_delivered
    select whole reports that fit 16,000 chars; leave the rest for the next wake
    claim(notice_claim) with compare-and-set
    steer into a leased, steerable turn | hold until the turn ends | send a new turn
    settle (claim -> notice_delivered) or return the claim on failure

A result the Coordinator already read through task_status, thread_wait, or its own task_cancel counts as delivered, so it is not sent again. A user Stop on the child still reaches the Coordinator. Stopping the Coordinator does not stop the child, and the later result is still delivered.

Verified with server tests for the ledger, wake service, steer delivery, and boot recovery, web tests for the dock, roster, and timeline row, and live Electron runs with Claude.

Closes #2217

Why

Users delegate work so they can step away. Without a wake-up, every delegation needed a manual "check on it" prompt, and a child blocked on an approval sat unseen in another thread.

UI Changes

Child finished. Before, the roster shows Done but the Coordinator stays idle:

Before: Coordinator idle after the child finished

After, the Coordinator wakes with a "From Count files" row and answers with the result:

After: wake-up row

After: wake-up prompt expanded

Child blocked on the user. Before, the Coordinator thread shows no dock entry:

Before: no dock entry while the child waits

After, the child's approval shows in the Coordinator's dock and the roster shows Waiting:

After: approval in the Coordinator dock

After: roster shows Waiting

After approving from the dock, the child finishes and the Coordinator wakes again:

After: approved and finished

Config Changes

None.

Review Notes

  • Migration. 0097_parallel_madelyne_pryor adds nullable notice_delivered and notice_claim columns to delegated_tasks. It backfills notice_delivered for tasks that had already ended, so an upgrade does not wake Coordinators with old results. Older builds never read either column, so it is registered in COMPATIBLE_STEPS.
  • Prompt injection. Reports come from other agents. The wake message opens with a line telling the Coordinator to treat them as data, not user instructions. A needs-input report tells the Coordinator not to answer the question itself.
  • Known gap. The live run did not capture a structured question (Codex request_user_input) in the dock. The Codex child ran in Default mode, where the tool is unavailable. Tests cover the question path, and the tool-approval path was verified live.
  • Known gap. The server-bootstrap.ts hooks that refresh the roster on child approval changes have no direct test. The service method they call is tested, and the live capture shows the roster moving to Waiting and back.
  • Docs: the Coordinator's tool guidance now says it will be woken, so it does not need to poll.

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

…claimed

A message cut at its size limit still settled every claimed task, so a result whose section was truncated away was never delivered. Select whole sections against the budget before claiming and let the existing rerun deliver the rest.
The wake message arrives as a user-role turn but carries text written by delegated agents. Open it with one line saying so.
…inator

Stopping a child from the UI returned through the acknowledging report, so the Coordinator never heard about it. Only the Coordinator's own task_cancel acknowledges.
The wait recomputed each child's notice key after awaiting its audit write, so a result that landed in between was acknowledged without being returned. Capture the keys when the observation is read.
@chuks-qua
chuks-qua merged commit 5256482 into main Oct 22, 2026
23 of 25 checks passed
@chuks-qua
chuks-qua deleted the feat/issue-2217 branch October 22, 2026 12:53
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.

feat: wake the Coordinator thread when a delegated task finishes

1 participant