Repository navigation
Description
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:1108stepTaskSummary()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".
- Task: wrap, do not truncate. In expanded state, render the task with
wrapPlainTextoverr.task/step.descriptionexactly as authored, newlines preserved, nooneLine(), no 96-char cap, no.... The collapsed row keepscompactTaskText(or gets a slightly larger cap, e.g. the available row width, cheap string only). - 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. - 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. - A knob instead of a constant. Something like
tui: { taskPreviewChars, expandedActivityLines, expandedOutputTailLines }, documented indocs/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
fix(tui): show the full task in multi-job cards, count materialized w…
feat(tui): show a running child's full task in the expanded widget (#…
nicobailon commentedon Nov 5, 2026
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:
Thanks @marshamonkey25-hue for the detailed write-up.