[Bug]: Claude's per-line Monitor wakes are tagged background_task, so each one wakes a delegated child's parent

Aperta
#36,113 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

@juliusmarminge ci sta già lavorando.

Dal 13/11/2026.

  • #36339 di @juliusmarminge — aperta

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
22/100
Tipo di issue
Bug
Chiarezza
Abbastanza chiara
Stato di attività
Attiva
Stack tecnologico
typescript

Direzione di ricerca

Start in apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts around the terminal task_notification handling (about lines 9344-9367) and backgroundWorkNotification (about 9448-9466), then check ProviderContinuationService.ts lines 247-256 where the default background_task/updated tag is applied. Related gate logic is in Orchestrator.ts near line 752, subagentProjection.ts, and orchestrationV2PendingBackgroundWork.ts. Done means a per-line Monitor event records a monitor/updated report while other updated wakes keep their current tag, with the gate behaving as the issue's table describes.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Before submitting
  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.
Area

apps/server

Steps to reproduce

Derived from a production lifecycle read back from the state DB and the child's Claude session log. I did not rerun it as a clean repro.

  1. A parent delegates an async delegate_task to a Claude child. The child finishes, and the original task is delivered.
  2. The parent sends the child a follow-up with t3_thread_send. The child starts a long command and arms a Monitor on its output that emits one line per event (for example, one line per surviving mutant). It does not call t3_background_wait on the Monitor. It ends the turn.
  3. Each Monitor line wakes the child. The child replies briefly ("Covered. Waiting for the rest.") and ends the turn.
Expected behavior

The follow-up gate drops Monitor progress, as its comment says ("monitor updates only report progress", Orchestrator.ts:752). The parent is not woken for each Monitor line.

Actual behavior

Every Monitor line wake starts a new follow-up delegated task (completionWake: "always"). Each one completes and wakes the parent. In one lifecycle, a dispatcher received 42 such progress-only hand-backs from one worker in about 5 hours. Each one cost the dispatcher a full model turn.

The cause is the tag. A per-line Monitor wake reaches the orchestrator as {source: {kind: "background_task"}, outcome: "updated"}, not as monitor. The gate refuses only monitor, so it lets these through. The Monitor's own end does carry monitor (a terminal task_notification), so on main the gate drops the one wake it should keep (#31843) and keeps the ones it should drop.

Claude event Tag T3 gives it Gate on main Gate after #31856
Per-line Monitor event background_task / updated passes, one follow-up per wake passes
Monitor ends monitor / completed dropped passes

Why the per-line wake has no Monitor tag:

  • The Claude adapter records a wake report only for a terminal task_notification system message (ClaudeAdapterV2.ts:9344-9367). A Monitor line is a queued <task-notification> prompt carrying an <event>, not one of those.
  • With no report, backgroundWorkNotification returns null and the continuation is offered with no notification (ClaudeAdapterV2.ts:9448-9466).
  • ProviderContinuationService then fills in its default background_task / updated (ProviderContinuationService.ts:247-256).

The same tag also feeds delegatedTaskProgress, which excludes runs from an original task's work runs only when their notification is monitor (subagentProjection.ts:273-280), and monitorHoldsWakeCompletion (orchestrationV2PendingBackgroundWork.ts:120). So the mislabel is not limited to follow-ups.

A possible fix: when a buffered Claude wake is a Monitor event, record a {kind: "monitor", outcome: "updated"} wake report, the way a terminal task_notification records one today. The gate, delegatedTaskProgress and monitorHoldsWakeCompletion then work unchanged. Dropping every updated wake at the gate instead would also drop other wakes that arrive with no report and the same default tag, such as a ScheduleWakeup, whose turn can hold a real answer.

This is separate from #21837, which is about a follow-up settling while awaited work is pending. None of the Monitors here were awaited, so a fix for #21837 would not stop these wakes.

Impact

Major degradation or frequent failure

Version or commit

0.1.10-nightly.20261112.4564 (bc647ed53595888efacdd8ca435967d48888a952). The cited code is unchanged on main ed05c0e43b64631f9780ad538fb4db1f0e0cd66d.

Environment

macOS arm64, local server. Claude Opus 5.5 parent and child.

Logs or stack traces
# Child's Claude session log: one queued Monitor line, then the wake
20:59:14.289Z queue-operation enqueue  <task-notification> <task-id>br517lnp6</task-id> <summary>Monitor event: "...: survivors and the end"</summary> <event>ok  Unmutated baseline in 3s build + 3s test</event> ...
# The same wake in the T3 child thread (projection message)
20:59:14.482Z user  notification={"source":{"kind":"background_task"},"outcome":"updated","summary":"Background activity updated"}
20:59:18.046Z assistant  "The baseline passes. Waiting for survivors or the final tally."
# -> a new follow-up task, completed and delivered to the parent at 20:59:18

# Across the lifecycle
Monitor-event notifications enqueued in the child: 76, across 10 Monitors
Follow-ups started by background_task/updated wakes: 42 (20:59:18Z to 01:48:35Z), all delivered to the parent
Monitors awaited with t3_background_wait: 0
Workaround

Tell delegated children to use a background command that ends once, instead of a Monitor that emits a line per event. Awaiting the Monitor does not help after the first result, because follow-ups ignore awaited work (#21837).

Lingua principale
TypeScript
Stelle
24.8k
Fork
6.4k
Merge medio
59m
PR unite (30g)
418

Preparare l'ambiente

Apri in Codespaces

Avvia il container di sviluppo del progetto nel browser, con il tuo account GitHub.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di pingdotgg/t3code

Tutte le issue di pingdotgg/t3code

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.