Skip to content

Running children: show the full task, recent tool calls, and child output tail in expanded mode #3187

Closed

Description

@marshamonkey25-hue

Problem

While a child run is in progress, the parent chat shows almost none of what the child was actually asked to do or is actually doing. Three separate truncations stack up, and there is no expand path that lifts them:

1. The task text is hard-capped and flattened.

src/tui/render.js:233

const COMPACT_TASK_MAX_CHARS = 96;

compactTaskText() (render.js:236-250) runs the authored task through oneLine() (all newlines and runs of whitespace collapsed to single spaces) and then previewDisplayText(..., 96). So a task prompt that is a real structured brief — objective, context, constraints, files to touch, deliverable, acceptance — becomes a 96-character one-liner with ....

Worse, this is not only the collapsed row. Every running row uses it, including the "expanded" widget detail:

  • render.js:2228 — foreground widget step line: compactTaskText(step.description, step.label)
  • render.js:3046 — single result, running: compactTaskText(r.task)
  • render.js:3327 — workflow/parallel row: compactTaskText(r.task, workflowLabelForResult(d, i))
  • render.js:1108 stepTaskSummary() is the same 96-char summary

So there is no state in which the widget shows the task the child was given. Orchestrators routinely fan out tasks that share a 96-character prefix ("Implement the fix described in the report below... "), which makes two different children render identically. That is the "I can't tell what it's doing" case.

2. Live activity is one line of one tool call.

formatCurrentToolLine() (render.js:743-756) shows only currentTool: <args>, and renderToolArgsPreview() (render.js:737-742) truncates the args to width - 20 unless expanded — with no history, no per-file detail, and no tool sequence. There is no way to see the last N actions, only the current one.

3. The child's own text/thinking stream never reaches the parent.

The parent sees the final result, or output-N.log / FleetView / transcript inspection. Mid-run reasoning and intermediate findings are invisible, so a long child is indistinguishable from a stuck one.

Environment

  • pi-subagents 0.84.0
  • Pi 1.5.0
  • Linux, alacritty, 120x30 terminal

Proposed direction

Keep the current compact default (row budget is a real constraint and should not change), but make the expand key genuinely mean "show me everything about this child".

  1. Task: wrap, do not truncate. In expanded state, render the task with wrapPlainText over r.task / step.description exactly as authored, newlines preserved, no oneLine(), no 96-char cap, no .... The collapsed row keeps compactTaskText (or gets a slightly larger cap, e.g. the available row width, cheap string only).
  2. Recent activity, not just current activity. In expanded state, show the last ~6 tool calls for the child, one line each: tool + primary argument (path / command / grep pattern), each line truncated to width only. Data is already produced for the current-tool line; the producer needs to keep a small bounded ring of recent calls on the status payload — no renderer-side history reconstruction.
  3. Optional child tail. An option (default off) that appends the last ~10 lines of the child's text output to the expanded block, sourced from the tail the producer already reads for run-status (src/runs/background/run-status.js:276) so the renderer still does no I/O.
  4. A knob instead of a constant. Something like tui: { taskPreviewChars, expandedActivityLines, expandedOutputTailLines }, documented in docs/configuration.md, so operators who want a bigger collapsed task cap can have it.

Mandatory performance constraint

This must not make the status, FleetView, watcher, or render loop slower.

  • No per-render file I/O, registry scans, model catalog scans, or prompt summarization.
  • No LLM calls or async work from the renderer.
  • Any new data (recent tool ring, output tail) is added at the producer boundary and bounded in size, like the existing transcript tail.
  • Collapsed mode must stay within the current row-budget system and must not grow.

Acceptance

  • A 400-character, 6-line task authored for a child is fully readable, wrapped at terminal width, in expanded mode — no oneLine(), no ..., no 96-char cap.
  • Collapsed rows are unchanged in row count and byte-cheap (pure string ops only).
  • Expanded mode lists the child's recent tool calls with per-call arguments truncated only by width.
  • Two children with identical 96-character task prefixes are distinguishable in both modes.
  • No new render-path I/O; focused render tests for wide/narrow width, degraded payloads (missing tool history / missing tail), and the expanded wrapping path.

Non-goals

  • Not a new inspector; FleetView stays the deep surface.
  • No change to the default collapsed layout or row budget.
  • No change to workflow/run semantics or to what the child is sent.

Activity

  1. nicobailon commented on Nov 5, 2026

    @nicobailon
    Owner

    Shipped a narrower version in #3196 (779f6ee).

    When one background child is running, the expanded widget now shows its task as written: line breaks, indentation and blank lines kept, wrapped to the terminal width, up to 8 lines plus "…". This also works when finished jobs are still listed next to it. The task is cut to what those 8 lines can show before any wrapping, so a very long brief adds no per-frame cost, and the render path still does no I/O.

    What changed from the proposal, and why:

    • Two or more running children keep the one-line task. The expanded widget has a fixed line budget (16 lines on a 30-row terminal). With two children, the longer task blocks pushed the second child's whole row out of view, and a running child must never be hidden. For several children, the expanded foreground result and FleetView already show each full task.
    • Recent activity and output tail: expanded mode already lists a running child's last 3 tool calls and its recent output lines, so no new history buffer or tail option was added.
    • No new config knobs: the 8-line cap follows from the widget budget, and a setting would be a second way to get what FleetView already shows.

    Thanks @marshamonkey25-hue for the detailed write-up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions