feat(web): one delegation: delegate is a resumable task in both roots, the coder choosing to wait and the planner always in the background (one runtime 5b/n)

Merged
DA
6d ago
+510-103

One-agent-runtime migration, PR 5b (docs/proposals/one-agent-runtime.md §8, Decision 3, option A as Dean picked it). Builds on 5a (#2387, merged), whose worker rows read the worker's own session.

What

One delegation mechanism for both roots: delegate, defined as an eve resumable task (serve, the shape eve gives every agent call).

Coding agent (coder/tools/delegate.ts):

  • Input is {task, model?, effort?, background?}.
  • The call answers with eve's receipt at once, and the worker's {model, effort, result} reaches the agent as a <task_result>.
  • Foreground by default: unless the agent sets background, the tool's words and the coder prompt have it call task_wait right after delegating. Setting background: true keeps it working while the worker runs.
  • A developer's steer no longer kills a running worker: a task is never interrupted by a new message, where the old blocking execute aborted on one.
  • A call with the task's id sends the worker more, into the same session, whose child conversation stays the starting call's.
  • The pair is still checked and recorded in a step as the task starts.

Planning model (eve/tools/delegate.ts, PLANNER_DELEGATE_TOOL):

  • Input is {task} only. It always runs in the background, because a foreground wait would hold the spoken turn silent.
  • Its worker is declared hidden (tool: false), as the coder's is, so the model reaches it only through delegate.
  • The prompt now names delegate, and "call delegate again with its taskId" to redirect a worker.

Wiring:

  • Registry: delegate serves [PLANNER, CODER].
  • Planning stored set: registers the planner's delegate. eve's worker, task_wait and task_cancel stay registered for earlier transcripts.
  • Old names keep reading: PLANNER_DELEGATION_TOOLS names both delegate and the legacy worker. The voice's follow of a parked turn (delegatedOf), the steered-worker journal reads (plannerDelegationJournalsOf, shared by the Work store and the voice) and the Work tab projection all read both.
  • Work tab projection: shows a delegate call's {task} as the worker's message, so every desktop reads it unchanged.

Tests

  • tests/voice-live-brain.test.ts, new: a turn parked on a task its delegate started is followed past the plain bound, and the findings that land after it are spoken. It fails without this PR, where the follow ends at the plain bound.
  • tests/plan-work.test.ts, new: the planner's delegate reaches the Work tab as a worker, its task carried as the message and its task named off eve's receipt.
  • Offline evals (test:agent, real eve runtime, local Postgres):
    • The coder delegates, waits with task_wait, and answers with the worker's result from the task result. The call's output is eve's receipt.
    • The planner delegates in the background and its turn waits for the task's result before it ends.
  • Updated: hosted-brain-host-agent.test.ts (the stored set names the planner's delegate), and the goldens (codingAgentDelegationInputSchema gains optional background, re-recorded with LUKE_UPDATE_FIXTURES=1).
  • Suites: the web suite (157 files) passes; eve-layout builds both roots. Lint and repository checks pass.

This PR touches no renderer file. 5a already reads a worker row's state from its session, so rows are right once the call settles at the receipt.

🤖 Generated with Claude Code


Open workspace in Conductor


Devin Review