Stream background-command output into claude native mirrors - #1255
Merged
Conversation
Background Bash tasks projected as native subagent mirrors had no transcript source: selecting one in the TUI/webui session list opened an empty session view. Claude announces each background task's output file in the launch tool_result, so the adapter now: - captures the launching command and the announced output path at launch - tails the output file every watcher tick, projecting the command as an opening user message (ordinal 0) and output as line-bounded tool-role chunks whose ordinal is the 1-based index of the chunk's last line - holds a trailing partial line until its newline arrives, and flushes everything (partial included) when the terminal notification lands - caps per-tick chunks at 256 KiB so fast writers drain across ticks Also fixes a latent reconcile bug: the retained-child snapshot was derived only from subagents-dir files, so any snapshot change would archive still-running background-task mirrors. Live background task ids now count as retained, and a transient read_dir failure no longer emits an authoritative snapshot.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Selecting a claude background-task "native" subagent session in the TUI (and webui) session list opened an empty session view. Task-tool subagent mirrors already stream their transcript (projected from
subagents/agent-*.jsonl), but background Bash tasks were projected with lifecycle state and title only — no transcript source was wired, so their mirrors had zero events. Since long-running background tasks are what actually stays visible/running in the session list, the empty view is what users hit.Fix
Claude Code announces each background task's output file in the launch tool_result ("Output is being written to: …/tasks/<id>.output"). The claude adapter now:
usermessage (ordinal 0)toolmessages whose ordinal is the 1-based index of the chunk's last line — deterministic at line granularity, matching the daemon's ordinal replay-dedupe contractNo daemon or UI changes needed: the existing native-mirror projection persists + broadcasts these events, so the transcript is live in the TUI Chat view and webui.
Latent reconcile bug fixed alongside
The
NativeSubagentSnapshotretained-set was derived only fromsubagents/dir files, so any snapshot change (an agent child appearing/finishing) would archive a still-running background task's mirror. Live background task ids now count as retained, and a transientread_dirfailure no longer emits an authoritative snapshot (which could archive mirrors off bad data). A consequence: the first tick now emits a snapshot even with no children, so stale "running" background mirrors from before a daemon restart get archived on resume — previously they lingered as zombies (the underlying process died with the harness).Spec 0079 updated with the background-command transcript + retained-set rules.
Verification
claude, hand-written native transcript): mirror shows the command message, output streams live, the partial line is held until its newline, and the completion notification flushes it and archives the mirror:Known limitation
On daemon restart + session resume, the root transcript history is skipped, so pre-restart background launches are not re-discovered and their output is not re-tailed — accepted, since the background process itself does not survive the harness restart (its mirror is now correctly archived by the first snapshot instead of lingering as running).
🤖 Generated with Claude Code