Muse Code background monitors aren't shown as pending work; the thread looks finished and the monitor can't be stopped#19061

opened18d agobyJjlipworth

Steps to reproduce

  1. In a Muse Code thread, ask the agent to push and watch CI.
  2. Muse calls its monitor tool with a polling loop, then ends its turn. The tool output is:

    Monitor started (work work.v1.monitor.sha256.…, timeout 30m). Events will be delivered automatically. Keep working; do not poll or sleep. With nothing else to do, end the turn: event batches wake the session. Stop it with work_stop.

  3. The agent's final message: "Pipeline #605 is running; I'll report back when it reaches a terminal state."
  4. Look at the thread while the monitor is still running.

Expected behavior

The thread shows background work in progress, with a way to stop it, the same as Muse subagents and workflows (and Claude background commands, Grok monitors). T3 keeps the Muse session alive until the monitor finishes, and the thread isn't treated as done in the sidebar.

Actual behavior

The monitor call shows as a completed tool and the run shows as completed. There is no background-work banner, no stop button, and nothing tells the user the agent is still waiting. T3 also doesn't count the monitor when deciding whether to shut down the idle session.

Cause

  • packages/provider-muse/src/server/adapter.ts:694-741: syncBackground only puts running subagent and workflow items in pendingBackgroundTasks. monitor jobs and tool calls that Muse moves to the background (Item.background: true, @muse-code/sdk msp.d.ts:615) are never tracked.
  • packages/provider-muse/src/server/adapter.ts:2111: hasPendingBackgroundWork only checks observedChildren and a held wake turn. ProviderSessionManager releases sessions that look idle after 30 minutes (apps/server/src/orchestration-v2/ProviderSessionManager.ts:54), so a monitor with a longer or persistent timeout can be killed before it reports back.
  • The adapter never calls the Muse protocol's task/stop or task/stopAll (msp.d.ts:1888-1910), so T3's stop action can't end background work Muse runs itself.

Suggested fix

  • Add live monitor jobs and backgrounded tool calls to pendingBackgroundTasks and hasPendingBackgroundWork. Clear them when Muse's wake turn reports the job finished, or when its timeout passes.
  • When the user stops background work on a Muse thread, call task/stopAll, or task/stop for one job.

Open question: the 1.4.2 SDK types don't name monitor or its work ID. Unless Muse reports work start and finish separately, the adapter may have to read the work ID and timeout from the tool's output. A supported signal from Muse would be better.

Related: #16499 (Grok shell tasks and monitors), #17625 (Claude background command and auto-settle), #18880 (OpenCode background shell and idle release).

Note

Grok responding on behalf of Julius.

This is a confirmed bug on main, the same gap as #18880 (OpenCode) and #17625 (Claude), here for Muse.

What main does (packages/provider-muse/src/server/adapter.ts):

  • publishItem only adds subagent and workflow items to observedChildren. syncBackground and hasPendingBackgroundWork (~2111) read only that set and the held wake turn. So a running monitor, or a tool call Muse backgrounds, never shows up as pending work, and the 30-minute idle release can kill the session.
  • The adapter never calls task/list, task/stop, or task/stopAll.

This isn't upstream. Main pins @muse-code/sdk 1.4.6, which already exposes these signals: Item.background on tool calls, task/list ("one row per running background workload in task/stopAll reach"), and task/stop/task/stopAll. The types don't name monitor, but task/list covers it. No one needs to parse the tool output.

Suggested fix: track toolCall items with background: true (or reconcile against task/list after each turn) in pendingBackgroundTasks and hasPendingBackgroundWork, and wire the thread's stop action to task/stop/task/stopAll.

Workaround for now: ask Muse to poll in the foreground instead of using monitor, or keep the thread active.