feat(web): record a subagent's wake-up turn as a child completion

Merged
CH
11d ago
+137-8

Stacked on #1820.

Why

When a subagent finishes, eve opens a new turn on the session that delegated, to hand the result back. eve puts no marker on that turn. It runs under the last request's auth, so it inherits that request's turn kind, and it carries no delivery. Today the relay records it as an unasked spoken turn with no user line. The voice service never follows it, and the record says the developer spoke.

What changes

  • The relay's state notes when the session has delegated, from Luke's own call to a subagent tool (actions.requested). eve's subagent.called event doesn't reach the hook, as the end-to-end eval showed.
  • In a session that has delegated, a turn with no delivery is recorded as a child completion. The relay reuses the existing TURN_ORIGIN.CHILD_COMPLETION and BRAIN_TURN_TRIGGER.CHILD_COMPLETION. eve's notification, with the child's result, becomes the turn's line, authored by the brain (OBSERVATION_SOURCE.CHILD_COMPLETION, already handled by userMetadataOf).
  • RELAY_TURN (bounds.ts) adds that kind beside the two the door admits. A request can't name it: the door still admits only BRAIN_HOST_TURN.

The rule depends on one fact: every ask after a session's opening one carries its own delivery. The opening ask comes before any delegation, so the rule never misreads it.

Tests

  • hosted-brain-host-relay.test.ts: after a delegation, a wake-up turn records as child_completion, with the result as the brain's line. A later turn that carries an ask's delivery stays spoken. Without the change, this test fails.
  • ./scripts/check.sh passes.

This is a web-only change. The voice side, following these turns and speaking them, is the next PR.

šŸ¤– Generated with Claude Code


Open workspace in Conductor