Add subagent result delivery artifacts

This commit is contained in:
2026-08-01 23:28:18 -04:00
parent 99e7626e5e
commit 1a5a3a50ac
19 changed files with 1234 additions and 22 deletions

View File

@@ -1 +1 @@
82
101

View File

@@ -77,10 +77,10 @@
"nodeSizeMultiplier": 2.51132136678201,
"lineSizeMultiplier": 2.03949502595156,
"collapse-forces": false,
"centerStrength": 0.350183823529412,
"centerStrength": 0,
"repelStrength": 20,
"linkStrength": 1,
"linkDistance": 500,
"scale": 0.12993773244100013,
"scale": 0.09465945232691539,
"close": false
}

View File

@@ -150,6 +150,25 @@
},
"active": "7ec442f7ed4ccd8b",
"lastOpenFiles": [
"projects/dotfiles/101-pi-subagent-selectable-monitor-implementation.md",
"projects/dotfiles/089-pi-subagent-result-delivery-design-approval-grill.md",
"projects/dotfiles/100-pi-subagent-read-only-attach-view-implementation.md",
"projects/dotfiles/099-pi-subagent-child-activity-capture-implementation.md",
"projects/dotfiles/098-pi-subagent-compact-expanded-monitor-implementation.md",
"projects/dotfiles/097-pi-subagent-clearable-terminal-work-implementation.md",
"projects/dotfiles/096-pi-subagent-labeled-work-items-implementation.md",
"projects/dotfiles/095-pi-subagent-result-delivery-spec-approval-grill.md",
"projects/dotfiles/094-pi-subagent-result-delivery-spec-task.md",
"projects/dotfiles/093-pi-subagent-read-only-attach-feasibility-research.md",
"projects/dotfiles/092-subagent-ui-other-harness-patterns-research.md",
"projects/dotfiles/091-pi-subagent-result-delivery-slice-approval-grill.md",
"projects/dotfiles/090-pi-subagent-result-delivery-slice-plan-task.md",
"projects/dotfiles/088-pi-subagent-result-delivery-wayfinder-integration-grill.md",
"projects/dotfiles/087-pi-subagent-result-delivery-current-extension-task.md",
"projects/dotfiles/086-pi-subagent-result-delivery-ui-research.md",
"projects/dotfiles/085-pi-subagent-result-delivery-runtime-api-research.md",
"projects/dotfiles/084-pi-subagent-result-delivery-product-semantics-grill.md",
"projects/dotfiles/083-pi-subagent-result-delivery-map.md",
"projects/dotfiles/082-pi-ui-bottom-anchored-editor-research.md",
"projects/skills/081-implement-skill-branch-worktree-policy-grill.md",
"projects/skills/080-implement-skill-ticket-scope-grill.md",
@@ -157,25 +176,6 @@
"projects/skills/078-implement-skill-matt-code-review-research.md",
"projects/skills/077-implement-skill-matt-tdd-research.md",
"projects/skills/076-implement-skill-matt-to-tickets-research.md",
"projects/skills/075-implement-skill-matt-implement-research.md",
"projects/skills/074-implement-workflow-implementation-spec.md",
"projects/dotfiles/073-pi-ui-community-pi-packaging-research.md",
"projects/dotfiles/072-pi-ui-patched-pi-packaging-research.md",
"projects/dotfiles/071-pi-ui-final-deployment-verification-task.md",
"projects/dotfiles/070-pi-ui-flex-spacer-pi-patch-task.md",
"projects/dotfiles/068-pi-ui-compact-status-extension-task.md",
"projects/skills/069-implement-workflow-dependency-orchestration-grill.md",
"projects/dotfiles/068-pi-ui-permanent-implementation-task.md",
"projects/dotfiles/067-pi-ui-flex-spacer-bottom-anchor-prototype.md",
"projects/dotfiles/066-pi-ui-existing-extension-layout-survey-research.md",
"projects/dotfiles/065-pi-ui-bottom-anchored-editor-research.md",
"projects/skills/065-implement-workflow-codebase-design-research.md",
"projects/dotfiles/064-pi-ui-third-party-codex-quota-research.md",
"projects/dotfiles/063-pi-ui-customization-spec-task.md",
"projects/dotfiles/062-pi-ui-quota-status-prototype.md",
"projects/dotfiles/061-pi-ui-compact-status-prototype.md",
"projects/dotfiles/060-pi-ui-codex-quota-research.md",
"projects/dotfiles/059-pi-ui-context-token-data-research.md",
"projects/skills",
"projects/dotfiles/XXT3MvgC",
"projects/dotfiles",

View File

@@ -0,0 +1,56 @@
---
status: open
tags:
- wayfinder/map
---
# Pi subagent result delivery
## Destination
Track implementation of the approved specification for improving Pi subagent result delivery so background subagents can finish while the parent session continues another workflow, including a HITL grill, without losing results or requiring an inelegant blocking wait.
## Notes
This is a focused follow-on to [[002-pi-subagents-map|Pi subagents decision]].
Keep the fix Pi-native and centered on the existing subagent extension's tool/API and Pi-native UI surfaces.
Optimize equally for general subagent usability and Wayfinder worker coordination.
The minimum acceptable improvement covers non-blocking result retrieval, visible completion or failure awareness, a less primitive subagent UI, visible summaries of what each child is working on, and workflow-safe reconciliation for Wayfinder AFK workers while HITL work continues.
Do not redesign Wayfinder maps, tickets, claims, or Frontier semantics.
Do not add Herdr or other external host integrations in this effort.
Do not solve remote or OS sandboxing here.
Treat ordinary-message background injection into the active parent conversation as outside the default path unless a HITL design decision explicitly opts into a controlled form.
## Frontier
- [[101-pi-subagent-selectable-monitor-implementation|Pi subagent selectable monitor]]
## Decisions so far
Pi exposes enough extension, custom tool, RPC, session, and UI primitives to implement non-blocking subagent status, result retrieval, notifications, and widgets, but the subagent extension must own supervision, persistence of terminal results, retention, and any push-style coordination.
The Pi-native UI path should use layered state rather than active-message injection: footer status for compact awareness, a subagent widget for a non-disruptive inbox-like view, custom entries for durable milestones or unread trails, and explicit commands or overlays for inspection.
The deployed subagent extension already has non-blocking spawn, polling-friendly status and result tools, blocking wait, process-local terminal result storage, a small widget, notifications, and durable milestone entries, but it has no unread model, durable result body store, acknowledgment state, richer inbox, or visible per-child work summary.
Other agent harnesses consistently make delegated/background work a visible work object with identity, label or title, lifecycle state, logs or result retrieval, completion/failure visibility, and explicit stop/dismiss or steering actions, while leaving workflow-specific reconciliation outside the generic background-work layer.
The generic subagent layer should provide current-session reliable completion state, terminal result retrieval, completion awareness, and work labels without prescribing workflow-specific reconciliation behavior.
Completion should be visible during HITL without derailing it, compact UI should show aggregate counts by status, expanded UI should show per-child rows with label, state, elapsed time, and activity or result marker, and selecting a child should attach a read-only Pi-like view without a text prompt.
Wayfinder should treat the generic subagent layer as a reliable current-session completion, result, and label source, while Wayfinder itself owns active-map reconciliation: completions during HITL are visible but deferred, then reconciled through normal artifact and Frontier mechanics after HITL completion or explicit pause.
Pi can support a read-only attached child view as a custom Pi-native overlay or temporary editor-area replacement fed by child RPC or session events, but the implementation should not assume an embeddable promptless `InteractiveMode` exists.
The behavior design is approved as the basis for the written specification.
The approved behavior design is captured as a specification in [[094-pi-subagent-result-delivery-spec-task|Pi subagent result delivery specification]].
Subagent work items now have explicit and prompt-derived labels reused across accepted, status, list, result, runner naming, notifications, and widget surfaces.
Terminal subagent work now remains visible and retrievable in the current session until explicitly cleared through `subagent_clear`, `/subagent-clear`, or the supervisor clear API.
The subagent widget now has the approved monitor shape: compact mode aggregates status counts, and expanded mode shows one row per visible child with state, elapsed time, label, and activity/result marker.
Structured current-session child activity is now captured from RPC events and retained for future read-only inspection, while status, list, and widget surfaces expose concise activity summaries without transcript bodies.
The read-only attached child view is implemented as `/subagent-attach <id>`, opening a promptless Pi-native overlay with transcript-style activity rendering, detach, and scroll controls.
The first attached-view implementation missed the intended direct selection interaction from the expanded monitor, so selectable monitor activation is now the remaining implementation slice.
## Not yet specified
None.
## Out of scope
Herdr and other external host integrations are outside this effort because this route is scoped to a Pi-native result-delivery improvement.
Replacing Wayfinder mechanics is outside this effort because Wayfinder is the stress-test workflow, not the target system being redesigned.
Remote, container, VM, micro-VM, or OS-level sandboxing is outside this effort because the problem is local result delivery and awareness, not trust-boundary isolation.
Full autonomous background conversation injection is outside the default path because it can disrupt active HITL workflows.

View File

@@ -0,0 +1,57 @@
---
status: resolved
claimed-by: "019fbff0-e725-79bd-861c-f1928d963392"
claimed-at: "2026-08-01T21:13:36-04:00"
resolved-at: "2026-08-01T21:51:14-04:00"
parent: "[[083-pi-subagent-result-delivery-map|Pi subagent result delivery]]"
blocked-by:
- "[[085-pi-subagent-result-delivery-runtime-api-research|Pi subagent result delivery runtime API research]]"
- "[[086-pi-subagent-result-delivery-ui-research|Pi subagent result delivery UI research]]"
- "[[087-pi-subagent-result-delivery-current-extension-task|Pi subagent result delivery current extension inventory]]"
- "[[092-subagent-ui-other-harness-patterns-research|Subagent UI other harness patterns research]]"
tags:
- ticket/grill
---
# Pi subagent result delivery product semantics
## Question
What product semantics should govern reliable non-blocking subagent result delivery and the improved subagent UI, including inbox versus notification versus event stream, read and unread state, failure visibility, result retention, visible summaries of what each child is working on, and whether any controlled parent-session injection is allowed?
## Working decisions
The improvement is not better polling tools for the human.
It should make subagent completion part of the parent agent's working obligations.
The human should not have to remember to check whether subagents finished.
During HITL work, completion should be visible without derailing the active exchange.
After HITL work resolves, or when the human explicitly pauses it, the parent agent should deal with completed subagent work.
The primary success story is Wayfinder dispatching research workers, continuing a HITL grill, showing completion awareness during the grill, then reconciling the research when the grill pauses or ends.
The design must also handle multiple parallel workers completing at different times without losing track of which results still need reconciliation.
Completion awareness during HITL should combine brief visible notices with persistent compact state, so completions are announced once and then remain visible as deferred work.
Completion notices should identify what finished and whether it succeeded, failed, timed out, or was cancelled, with batching when several workers complete together.
Child work labels should use a hybrid with override: accept an explicit caller-provided label when available, infer from known structure such as a Wayfinder ticket title when possible, and otherwise generate or truncate from the prompt.
The generic subagent tool should not prescribe a workflow protocol for what handling a result means.
It should make completed background work reliably visible and retrievable to the parent, while workflow-specific skills such as Wayfinder decide what to do with the result.
The generic layer should provide reliable completion state, reliable terminal result retrieval, completion awareness, and work labels, without workflow-specific reconciliation rules.
Terminal result persistence across parent session restart, Pi restart, or extension reload is not required for this effort.
Current-session reliability is enough.
Within the current session, completed results should remain visible and retrievable until explicitly cleared.
Improved UI should have a compact aggregate view and an expanded per-subagent work-item view.
The compact view should show counts by agent status rather than one row per child.
The expanded view should show one row per subagent with label, state, elapsed time, and last activity or result marker, with truncation when needed.
Selecting a subagent for inspection should attach a read-only live view of that child to the parent UI, so the human can watch what is happening without sending input to the child.
The attached view should look like a normal Pi session view, but without the text prompt.
The attached child view should be an overlay or temporary replacement, not a split pane.
The attached child view only needs detach plus normal scroll up and down controls.
The attached child view is part of this result-delivery improvement, not a hypothetical first implementation.
Feasibility still needs research before implementation slicing because it may touch Pi TUI internals rather than only the existing extension surface.
## Result
The product semantics are settled for this phase.
The generic subagent layer should provide current-session reliable completion state, terminal result retrieval, completion awareness, and work labels without prescribing workflow-specific reconciliation behavior.
Completion should be visible during HITL work but should not derail it.
Workflow-specific skills decide what to do with completed results once their own safe boundary is reached.
The UI direction is compact aggregate counts by status, expandable per-subagent rows with label, state, elapsed time, and last activity or result marker, plus a read-only Pi-like attached child view without a text prompt.
The attached view should use an overlay or temporary replacement rather than split panes and only needs detach plus normal scroll controls.

View File

@@ -0,0 +1,107 @@
---
status: resolved
claimed-by: "019fbffd-327f-77cb-be80-827c31407567"
claimed-at: "2026-08-01T21:01:15-04:00"
resolved-at: "2026-08-01T21:13:30-04:00"
parent: "[[083-pi-subagent-result-delivery-map|Pi subagent result delivery]]"
blocked-by: []
tags:
- ticket/research
---
# Pi subagent result delivery runtime API research
## Question
What can Pi extensions and custom tools currently observe, persist, expose, and return for asynchronous subagent lifecycle and result delivery, and what constraints does that place on non-blocking retrieval, notifications, or event-style coordination?
## Answer
Pi already exposes enough extension, custom tool, SDK, RPC, session, and UI primitives to implement non-blocking subagent result retrieval inside the current subagent extension.
The strongest path is extension-owned supervision with custom tools for spawn, status, list, wait, result, and cancel, plus extension UI notifications or widgets for awareness, plus session custom entries for durable milestone state.
Pi does not expose a built-in cross-session background job registry or a parent-session event stream for external child sessions, so the subagent extension must own child process supervision, correlation ids, retention, and any durable recovery semantics.
Ordinary message injection into the parent conversation is possible through `pi.sendMessage()` and `pi.sendUserMessage()`, but the documented delivery modes constrain it to steer, follow-up, or next-turn delivery and make passive retrieval a safer default for avoiding HITL workflow disruption.
## Findings
### Extension and tool observation surface
Pi extensions can subscribe to lifecycle, session, agent, message, turn, tool, input, model, provider, and user bash events through `pi.on(...)`.
The extension docs list `agent_settled` as the event that fires when Pi will not continue automatically through retry, compaction retry, or queued continuation, which makes it the right parent-side event for clearing or reconciling status after a parent run fully settles.
Custom tools receive `ExtensionContext`, so they can read session state, current mode, UI availability, cwd, model, thinking level, abort signal, idle state, queued-message state, and context usage, but they do not receive command-only session replacement helpers such as `waitForIdle()`, `newSession()`, `fork()`, or `switchSession()`.
Command handlers receive `ExtensionCommandContext`, which adds `waitForIdle()` and session replacement helpers, but the docs state those helpers are command-only because they can deadlock if called from event handlers.
Custom tool execution returns an `AgentToolResult` whose `content` is sent to the LLM, whose `details` are persisted on the tool result and available for rendering or state reconstruction, and whose optional `usage` contributes to session token and cost totals.
Tool progress can be streamed through the `onUpdate` callback, and Pi emits `tool_execution_start`, `tool_execution_update`, `tool_result`, and `tool_execution_end` around tool execution.
These primitives mean subagent tools can return immediately from spawn with accepted ids, can return a still-running shape from result retrieval, and can expose current status without blocking the parent turn.
### Extension persistence and exposure surface
Pi documents `pi.appendEntry(customType, data?)` as durable extension state that does not participate in LLM context and can be reconstructed on `session_start` by reading `ctx.sessionManager.getEntries()`.
The session format documents `CustomEntry` as an extension state entry with `customType` and `data` that does not participate in LLM context, while interactive mode can render it with an entry renderer.
Pi also documents `pi.sendMessage()` as custom message injection that participates in LLM context, and recommends `pi.appendEntry()` with `pi.registerEntryRenderer()` for durable TUI-only content that should not be sent to the LLM.
The current subagent extension already uses `pi.appendEntry("subagent_milestone", { event, status })` on lifecycle milestones, which is the right built-in persistence primitive for terminal awareness and future recovery.
However, the current supervisor keeps live child records in process memory only, and `session_shutdown` cancels all non-terminal children before discarding the supervisor.
The current `list()` returns active children and recent terminal children subject to a TTL, and `result(id)` requires the id to still be present in memory.
Therefore, durable post-restart result delivery would require intentionally reconstructing status and terminal result records from session custom entries or from a separate extension-owned store.
Pi provides the primitives for this, but the current extension implementation does not yet persist the final result body through `appendEntry()`.
### UI and notification surface
In TUI mode, extensions can call `ctx.ui.notify()`, `setStatus()`, `setWidget()`, `setTitle()`, custom components, custom footer, custom header, custom working indicators, and custom renderers.
The TUI docs show `setWidget()` as a persistent above-or-below-editor surface and `notify()` as a non-blocking user notification.
The RPC docs state that extension UI fire-and-forget methods such as `notify`, `setStatus`, `setWidget`, `setTitle`, and `set_editor_text` are emitted as `extension_ui_request` events and do not expect a response.
The RPC docs also state that some TUI-specific methods degrade in RPC mode, with `custom()` returning `undefined`, several working and footer methods becoming no-ops, and `setWidget()` supporting only string arrays.
Because `ctx.hasUI` is true in TUI and RPC modes, while `ctx.mode === "tui"` is required for terminal-only UI, a subagent result delivery design should use `notify`, `setStatus`, and string-array widgets for mode-portable awareness, and reserve custom TUI components for a TUI-only enhancement.
The current subagent extension already sets a widget with a compact or expanded status summary when status changes.
### Async child lifecycle evidence
Pi SDK `AgentSession` exposes `prompt()`, `steer()`, `followUp()`, `subscribe()`, `abort()`, `waitForIdle()`, and event streaming.
The SDK docs state that `prompt()` resolves after the full accepted run finishes, including retries, while `steer()` and `followUp()` enqueue messages during streaming.
The RPC docs state that the RPC `prompt` command response is emitted after acceptance, queuing, or immediate handling, and that events continue streaming asynchronously after acceptance.
The RPC docs expose `agent_settled`, `message_update`, `tool_execution_*`, `queue_update`, and `get_last_assistant_text` over JSONL, which is enough for the current subprocess runner to observe child progress and final text.
The current subagent runner starts `pi --mode rpc --no-extensions --extension <subagents index> --name "subagent <id>"`, sends a `prompt`, observes JSONL events, treats `agent_settled` as completion, calls `get_last_assistant_text`, and then terminates the child process.
This aligns with the documented RPC protocol, where `agent_settled` means no automatic retry, compaction retry, or queued continuation remains, and `get_last_assistant_text` returns the text content of the last assistant message.
### Coordination and event-style options
Pi exposes a shared extension event bus as `pi.events` for communication between extensions.
The SDK docs also say a shared `eventBus` can be passed to `DefaultResourceLoader` to emit or listen from outside the session factory.
This can support in-process extension-to-extension notifications, but it is not documented as a persisted queue, a cross-process bus, or a child-session supervision registry.
For parent-facing async coordination, the reliable primitives are therefore extension-owned state plus tool polling or waiting, visible UI notifications, and optional in-process events for cooperating extensions in the same runtime.
A controlled push into the parent conversation is possible with `pi.sendMessage()` or `pi.sendUserMessage()`.
`pi.sendMessage()` can use `deliverAs: "steer"`, `"followUp"`, or `"nextTurn"`, with `triggerTurn: true` only applying to steer and follow-up while idle.
`pi.sendUserMessage()` always triggers a turn and requires `deliverAs` while streaming.
These semantics are useful for an explicit opt-in completion injection, but they are too disruptive as a default delivery path when a parent session is in a HITL grill or another active workflow.
## Current constraints for design
- Non-blocking spawn and retrieval are feasible today because custom tools can return immediately and later expose status or result from extension-owned supervision state.
- Notifications are feasible today through `ctx.ui.notify()` and status widgets, and these work in TUI and RPC in degraded but documented forms.
- Durable terminal awareness is feasible through `pi.appendEntry()` custom entries, but durable final result retrieval is not present unless the extension persists terminal result bodies or an external store.
- Event-style coordination is feasible only within the current process through `pi.events`, or through RPC event streams owned by a client, not through a built-in persistent background job bus.
- Parent conversation injection is feasible but should be explicit and controlled because `sendMessage()` and `sendUserMessage()` participate in LLM context or trigger turns.
- Command-only session replacement and `waitForIdle()` are not available to custom tools, so subagent tools should not depend on command-only APIs for result delivery.
- TUI custom components are not portable to RPC mode, so the minimum design should not require them.
## Limitations and evidence gaps
No primary Pi documentation found a built-in async job registry, persistent notification center, or background task inbox for extensions.
No primary Pi documentation found an extension API that observes lifecycle events from a different Pi process or a child RPC session unless the extension or SDK client starts and subscribes to that child itself.
The current subagent extension source persists lifecycle milestones but not terminal result bodies, so post-restart retrieval of completed results is an implementation gap rather than a Pi platform impossibility.
The source inspected was the installed Pi package at version `0.82.1` and the deployed dotfiles subagent extension, so upstream behavior can change after that package version.
## Citations
- Pi extension capabilities, event lifecycle, custom tools, `ExtensionContext`, command-only `ExtensionCommandContext`, `pi.sendMessage()`, `pi.sendUserMessage()`, `pi.appendEntry()`, UI methods, and `pi.events`: `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md`.
- Pi SDK `AgentSession`, runtime replacement, event subscription, prompt queueing, custom tools, extensions, session management, and shared event bus: `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/sdk.md`.
- Pi RPC prompt acceptance, asynchronous event streaming, `agent_settled`, `get_last_assistant_text`, `get_entries`, and extension UI protocol degradation: `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/rpc.md`.
- Pi session custom entries, custom messages, message entries, and `SessionManager` append and read APIs: `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/session-format.md`.
- Pi TUI extension component and widget capabilities: `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/tui.md`.
- Pi exported type definitions for `ExtensionUIContext`, `ExtensionContext`, `ExtensionCommandContext`, `ToolDefinition`, and `ExtensionAPI`: `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/dist/core/extensions/types.d.ts`.
- Pi runtime binding for `sendMessage`, `sendUserMessage`, and `appendEntry`, including the custom entry append and `entry_appended` emission: `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/dist/core/agent-session.js`.
- Current subagent extension tool surface and milestone persistence: `/home/alexion/wrk/dotfiles/modules/agents/pi/extensions/subagents/index.ts`.
- Current subagent supervisor lifecycle, in-memory child records, result access, wait behavior, TTL retention, milestone callbacks, and shutdown cancellation: `/home/alexion/wrk/dotfiles/modules/agents/pi/extensions/subagents/supervisor.ts`.
- Current subagent RPC child runner behavior using `agent_settled` and `get_last_assistant_text`: `/home/alexion/wrk/dotfiles/modules/agents/pi/extensions/subagents/runner.ts`.
- Current subagent data shapes for status, result, wait, child records, and runner callbacks: `/home/alexion/wrk/dotfiles/modules/agents/pi/extensions/subagents/types.ts`.
- Current subagent widget rendering: `/home/alexion/wrk/dotfiles/modules/agents/pi/extensions/subagents/ui.ts`.

View File

@@ -0,0 +1,136 @@
---
status: resolved
claimed-by: "019fbffd-3252-7067-a2e7-8fcab9cc7293"
claimed-at: "2026-08-01T21:01:28-04:00"
parent: "[[083-pi-subagent-result-delivery-map|Pi subagent result delivery]]"
blocked-by: []
resolved-at: "2026-08-01T21:03:56-04:00"
tags:
- ticket/research
---
# Pi subagent result delivery UI research
## Question
What Pi-native UI affordances can show subagent completion, failure, unread results, or a lightweight result inbox without disrupting an active parent workflow such as a one-question-at-a-time grill session?
## Findings
The best Pi-native non-disruptive awareness surface is an extension widget plus footer status.
Pi documents `ctx.ui.setStatus()` as persistent footer or status-bar text, and `ctx.ui.setWidget()` as persistent content above or below the editor.
The TUI source stores extension widgets in separate above-editor and below-editor maps, limits string widgets to `InteractiveMode.MAX_WIDGET_LINES`, renders them into widget containers, and requests a render without replacing editor focus.
Sources: Pi `docs/extensions.md`, Custom UI and Widgets, Status, and Footer sections.
Sources: Pi `docs/tui.md`, Pattern 4 and Pattern 5.
Sources: Pi `dist/core/extensions/types.d.ts`, `ExtensionUIContext.setStatus()` and `setWidget()`.
Sources: Pi `dist/modes/interactive/interactive-mode.js`, `setExtensionStatus()`, `setExtensionWidget()`, `renderWidgets()`, and `renderWidgetContainer()`.
Footer status is good for the smallest completion and unread-result indicator.
The built-in footer renders extension statuses from `footerData.getExtensionStatuses()` on an extra sorted status line, and custom footers can consume the same `getExtensionStatuses()` data.
This supports a compact badge such as `subagents: 2 running · 1 unread · 1 failed` without opening a modal, injecting a message, or disturbing a grill prompt.
Sources: Pi `dist/modes/interactive/components/footer.js`, extension status rendering.
Sources: Pi `docs/tui.md`, Pattern 4 and Pattern 6.
Sources: Pi `examples/extensions/status-line.ts` and `examples/extensions/custom-footer.ts`.
A widget is the best Pi-native lightweight inbox surface.
Pi documents widgets as persistent content above or below the editor, with string-array or component-factory content and explicit clear semantics.
The current dotfiles subagent extension already uses this pattern by rendering a collapsed summary or expanded inspector through `ctx.ui.setWidget("subagents", ...)`, and its supervisor updates that widget through `onChange` whenever child status changes.
That proves the runtime state model can drive a non-blocking inbox-like view today.
Sources: Pi `docs/extensions.md`, `ctx.ui.setWidget()` examples.
Sources: Pi `docs/tui.md`, Pattern 5.
Sources: `modules/agents/pi/extensions/subagents/index.ts`, `updateUi()` and `onChange` wiring.
Sources: `modules/agents/pi/extensions/subagents/ui.ts`, `renderSummary()`, `renderInspector()`, and `widget()`.
Sources: `modules/agents/pi/extensions/subagents/supervisor.ts`, `emitChange()`, terminal state handling, and result availability updates.
A durable unread or milestone trail should use custom entries rather than ordinary messages.
Pi documents `pi.appendEntry()` as session-persistent extension data that does not participate in LLM context, and `pi.registerEntryRenderer()` as the TUI renderer for those entries.
The interactive source listens for `entry_appended`, renders custom entries with `addCustomEntryToChat()`, and inserts them before the current streaming component when one exists.
This is suitable for a compact history of completed, failed, or unread subagent results that is visible in the transcript but does not contaminate the parent model context.
Sources: Pi `docs/extensions.md`, `pi.appendEntry()` and Message and Entry Rendering sections.
Sources: Pi `dist/core/extensions/types.d.ts`, `registerEntryRenderer()` and `appendEntry()` definitions.
Sources: Pi `dist/modes/interactive/interactive-mode.js`, `entry_appended` handling and `addCustomEntryToChat()`.
Sources: Pi `examples/extensions/entry-renderer.ts`.
`ctx.ui.notify()` is Pi-native but should be secondary rather than authoritative.
The extension docs define `notify()` as non-blocking and typed as `info`, `warning`, or `error`.
The interactive implementation maps it to `showStatus()`, `showWarning()`, or `showError()`, and `showStatus()` appends or updates a dim chat status line to avoid log spam from back-to-back status messages.
This can announce `subagent sg-... completed` or `failed`, but it is transient and not enough for unread-result accounting.
Sources: Pi `docs/extensions.md`, Dialogs section.
Sources: Pi `dist/core/extensions/types.d.ts`, `ExtensionUIContext.notify()`.
Sources: Pi `dist/modes/interactive/interactive-mode.js`, `showExtensionNotify()` and `showStatus()`.
Sources: Pi `examples/extensions/notify.ts`.
An overlay or custom component can provide an explicit inbox viewer, but it should be user-invoked.
Pi documents `ctx.ui.custom()` as temporarily replacing the editor unless `{ overlay: true }` is passed, and overlay mode renders a floating component on top of existing content.
The interactive source preserves editor text, restores editor focus after non-overlay custom UI, and in overlay mode calls `ui.showOverlay()` instead of clearing the editor container.
This is appropriate for a `/subagent-inbox` or shortcut that opens an inspect-and-mark-read panel, but automatic popup overlays would still interrupt keyboard flow in a one-question-at-a-time grill.
Sources: Pi `docs/extensions.md`, Custom Components and Overlay Mode sections.
Sources: Pi `docs/tui.md`, Overlays and Overlay Focus sections.
Sources: Pi `dist/modes/interactive/interactive-mode.js`, `showExtensionCustom()`.
Sources: Pi `examples/extensions/overlay-test.ts`.
Custom tool rendering is useful for blocking or in-turn subagent results, but it does not solve background result delivery by itself.
Pi supports `renderCall()` and `renderResult()` for tool rows, partial results via `onUpdate`, and compact or expanded tool output.
The bundled Pi subagent example uses custom renderers to show single, chain, and parallel results with success, failure, running, usage, and expanded details.
That pattern is valuable for `subagent_wait` or old blocking subagent calls, but a spawned background child that completes after the parent turn needs a stateful widget, footer badge, entry renderer, or command because no tool row is actively updating at completion time.
Sources: Pi `docs/extensions.md`, Custom Rendering section.
Sources: Pi `examples/extensions/subagent/index.ts`, `renderCall()`, `renderResult()`, and parallel update handling.
Message injection APIs are available but are not the default workflow-safe route.
Pi documents `pi.sendMessage()` as injecting a custom message that participates in LLM context, with delivery modes `steer`, `followUp`, and `nextTurn`.
It separately says TUI-only durable content should use `pi.appendEntry()` with `pi.registerEntryRenderer()` instead.
For AFK worker result awareness during a grill, ordinary or custom message injection risks changing the active parent context and should be reserved for explicit user-approved reconciliation or selected result import.
Sources: Pi `docs/extensions.md`, `pi.sendMessage()` and `pi.appendEntry()` sections.
Sources: Pi `dist/core/extensions/types.d.ts`, `sendMessage()` and `appendEntry()` definitions.
Mode behavior limits which affordances exist outside interactive TUI.
Pi documents that `ctx.hasUI` is true in TUI and RPC modes, false in print and JSON modes, and that TUI-specific features need `ctx.mode === "tui"`.
It also states that in RPC mode some TUI-specific methods are no-ops or return defaults.
The no-op UI context in the extension runner implements notification, status, widget, footer, custom UI, editor, and autocomplete methods as no-ops when no UI is bound.
Therefore, result delivery should keep the authoritative unread/result state in supervisor/session data and treat TUI surfaces as projections.
Sources: Pi `docs/extensions.md`, ExtensionContext and Mode Behavior sections.
Sources: Pi `dist/core/extensions/runner.js`, `noOpUIContext`.
## Answer
Use a layered Pi-native design.
Keep authoritative result and unread state in the subagent supervisor and persisted custom entries.
Project awareness through a footer status badge and the existing subagent widget.
Add a user-invoked inbox command or shortcut using either an expanded widget state or an overlay custom component.
Use `notify()` only as a best-effort completion toast or chat status line.
Use custom entry rendering for durable milestone cards that do not enter LLM context.
Do not inject ordinary messages into the active parent conversation by default.
## Limitations
No primary Pi source found a built-in unread badge, inbox widget, notification center, or read/unread model for extensions.
Those semantics must be implemented by the subagent extension on top of `setStatus()`, `setWidget()`, `appendEntry()`, commands, and optional overlay UI.
No primary Pi source found a way for a background process completion to update an already-finalized tool row after the parent turn has moved on.
Background completion should therefore update extension-owned state surfaces rather than rely on tool result rendering.
Automatic overlays are technically possible, but the cited Pi sources do not define a non-disruptive policy for showing one during active typing or an ongoing HITL flow.
Treat overlays as explicit inbox viewers unless a later design decision chooses interruption rules.
Terminal-level desktop notifications are possible as an example extension writes OSC 777, OSC 99, or Windows toast sequences, but that is not a Pi-owned notification API beyond extension code writing to stdout or spawning a command.
It should not be the primary Pi-native answer.
## Citations
- `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md`.
- `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/tui.md`.
- `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/dist/core/extensions/types.d.ts`.
- `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/dist/core/extensions/runner.js`.
- `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/dist/modes/interactive/interactive-mode.js`.
- `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/dist/modes/interactive/components/footer.js`.
- `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/examples/extensions/status-line.ts`.
- `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/examples/extensions/widget-placement.ts`.
- `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/examples/extensions/entry-renderer.ts`.
- `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/examples/extensions/message-renderer.ts`.
- `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/examples/extensions/overlay-test.ts`.
- `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/examples/extensions/notify.ts`.
- `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/examples/extensions/custom-footer.ts`.
- `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/examples/extensions/subagent/index.ts`.
- `/home/alexion/wrk/dotfiles/modules/agents/pi/extensions/subagents/index.ts`.
- `/home/alexion/wrk/dotfiles/modules/agents/pi/extensions/subagents/ui.ts`.
- `/home/alexion/wrk/dotfiles/modules/agents/pi/extensions/subagents/supervisor.ts`.

View File

@@ -0,0 +1,89 @@
---
status: resolved
claimed-by: 019fbffd-0114-7f56-bce9-2c4e67bb7d52
claimed-at: 2026-08-01T21:01:01-04:00
parent: "[[083-pi-subagent-result-delivery-map|Pi subagent result delivery]]"
blocked-by: []
tags:
- ticket/task/afk
---
# Pi subagent result delivery current extension inventory
## Question
Inventory the current dotfiles-managed Pi subagent extension's result, status, wait, lifecycle, storage, and UI behavior so the design decisions are grounded in the deployed implementation rather than memory.
## Canonical result
The deployed extension is `modules/agents/pi/extensions/subagents`, copied by `modules/agents/pi/pi.nix` into the Home Manager managed `~/.pi/agent/extensions` tree.
It exposes tools and slash commands for spawn, batch spawn, list, status, result, wait, cancel, clear, diagnostics, and UI toggling.
`subagent_spawn` and `subagent_batch` are non-blocking.
They create in-memory child records, return accepted ids immediately, and start children through a bounded supervisor queue.
The default concurrency is three children.
The default context is independent.
The default tool profile is `read-only`, with built-in profiles for no tools, read-only, read-only plus safe bash, and full tools.
Named agents and config are read from `~/.pi/agent/agents`, trusted project `.pi/agents`, `~/.pi/agent/subagents.json`, and trusted project `.pi/subagents.json`.
The lifecycle states are `queued`, `starting`, `running`, `settling`, `completed`, `failed`, `cancelled`, `timed_out`, and `orphaned`.
The supervisor currently drives queued, starting, running, settling, completed, failed, cancelled, and timed_out.
`orphaned` exists in the type model but is not assigned by the current supervisor path.
Startup timeout defaults to 30 seconds.
Runtime timeout defaults to disabled.
Cancellation and shutdown mark active children cancelled.
Timeout marks children timed_out and attempts to cancel the process.
A child is a separate Pi RPC process launched with `--mode rpc`, `--no-extensions`, and an explicit `--extension` pointing back to the subagents extension.
Forked children receive the parent session file through `--fork`.
Independent children do not.
The child environment strips parent `PI_SESSION_ID`, `PI_SESSION_FILE`, `PI_PROVIDER`, `PI_MODEL`, and `PI_REASONING_LEVEL`.
Completion is detected from the child RPC `agent_settled` event, after which the runner asks the child for `get_last_assistant_text` and stores that text as the result.
`subagent_status` returns the current lifecycle record for one id.
The record includes id, label, agent, ad-hoc flag, context, state, cwd, model, thinking, tools, timestamps, elapsed time, last event, stop reason, result availability, child session, and error.
`subagent_list` returns all active records plus terminal records that have not been explicitly cleared.
Terminal records remain visible and addressable by id while the supervisor lives, until `subagent_clear` or `/subagent-clear` removes them from the visible current-session work set.
`subagent_result` is polling-friendly.
Before completion it returns a result object with `running: true`, `resultAvailable: false`, and no result text.
After successful completion it returns `running: false`, `resultAvailable: true`, and the final assistant text.
Failed terminal states return `running: false`, the terminal state, and the error when one exists.
The result object is not marked read, acknowledged, consumed, or hidden by retrieval.
`subagent_wait` is blocking by design.
It accepts ids, optional timeout, and mode `all` or `any`.
It returns ids, mode, ready flag, result objects for all requested ids, pending statuses, timedOut flag, and elapsed time.
A timeout returns pending data but does not cancel children.
An abort rejects the wait and also does not cancel children.
Unknown ids and empty id sets are errors.
Storage is process-local.
The supervisor and all child records live in module-level memory for the extension process.
Terminal results are retained in the in-memory child map until explicit clear.
On `session_shutdown`, the supervisor cancels active children and is cleared.
There is no durable result store, unread queue, acknowledgment state, or cross-session recovery.
The only durable transcript-adjacent output is `pi.appendEntry("subagent_milestone", { event, status })` for accepted, completed, failed, cancelled, and timed_out milestones.
The UI behavior is a small Pi widget plus notifications.
When UI is available and enabled, the widget is registered as `subagents`.
Collapsed mode shows one summary line with running, queued, and terminal counts.
Expanded mode adds one line per listed status with id, label, context, state, elapsed seconds, model, tool profile, last event, and whether a result is available.
The `subagent-ui` command toggles expanded mode.
Spawn and UI commands notify the user.
List, status, result, wait, batch, diagnostics, cancel, and clear commands display JSON through notifications.
Milestones update the transcript via `appendEntry`, but they do not inject an ordinary assistant message into the active conversation.
There is no visible unread result model or reconciliation workflow beyond polling status, polling result, waiting, clearing terminal work, or using the widget.
## Source files inventoried
- `modules/agents/pi/pi.nix`
- `modules/agents/pi/extensions/subagents/index.ts`
- `modules/agents/pi/extensions/subagents/supervisor.ts`
- `modules/agents/pi/extensions/subagents/runner.ts`
- `modules/agents/pi/extensions/subagents/types.ts`
- `modules/agents/pi/extensions/subagents/status.ts`
- `modules/agents/pi/extensions/subagents/ui.ts`
- `modules/agents/pi/extensions/subagents/config.ts`
- `modules/agents/pi/extensions/subagents/agents.ts`
- `modules/agents/pi/extensions/subagents/supervisor.test.ts`

View File

@@ -0,0 +1,30 @@
---
status: resolved
claimed-by: "019fbff0-e725-79bd-861c-f1928d963392"
claimed-at: "2026-08-01T21:52:36-04:00"
resolved-at: "2026-08-01T21:56:21-04:00"
parent: "[[083-pi-subagent-result-delivery-map|Pi subagent result delivery]]"
blocked-by:
- "[[084-pi-subagent-result-delivery-product-semantics-grill|Pi subagent result delivery product semantics]]"
tags:
- ticket/grill
---
# Pi subagent result delivery Wayfinder integration
## Question
How should Wayfinder coordinate AFK worker completion, result inspection, failure recovery, and artifact reconciliation while the parent session remains free to continue HITL work such as grill?
## Working decisions
When AFK workers complete during an active HITL ticket, Wayfinder should surface completion awareness but should not read result bodies or reconcile artifacts until the HITL ticket resolves or the human explicitly pauses for reconciliation.
After the HITL flow resolves, Wayfinder should resume its normal workflow-specific coordination responsibilities rather than ask the human to choose a generic subagent protocol.
For workers belonging to the active map, that means reconciling returned artifacts, recording honest failure or recovery state, updating map decisions, and advancing the Frontier according to Wayfinder's existing mechanics.
The generic subagent layer only needs to make the completion and result reliably visible and retrievable enough for Wayfinder to do that work.
## Result
Wayfinder integration follows the boundary established by the product semantics.
The subagent layer exposes current-session completion, result, and label state without deciding what reconciliation means.
Wayfinder owns the active-map workflow: completion during HITL is visible but deferred, and after HITL completion or explicit pause Wayfinder reconciles same-map worker results through its normal artifact and Frontier mechanics.

View File

@@ -0,0 +1,23 @@
---
status: resolved
claimed-by: "019fbff0-e725-79bd-861c-f1928d963392"
claimed-at: "2026-08-01T21:58:23-04:00"
resolved-at: "2026-08-01T21:59:17-04:00"
parent: "[[083-pi-subagent-result-delivery-map|Pi subagent result delivery]]"
blocked-by:
- "[[084-pi-subagent-result-delivery-product-semantics-grill|Pi subagent result delivery product semantics]]"
- "[[088-pi-subagent-result-delivery-wayfinder-integration-grill|Pi subagent result delivery Wayfinder integration]]"
tags:
- ticket/grill
---
# Pi subagent result delivery design approval
## Question
Does the human approve the proposed behavior design for non-blocking subagent result delivery as the basis for the written specification?
## Result
Approved.
The behavior design is accepted as the basis for the written specification.

View File

@@ -0,0 +1,232 @@
---
status: resolved
claimed-by: "019fc017-704e-7100-a949-2701c6e6a12f"
claimed-at: "2026-08-01T21:29:56-04:00"
resolved-at: "2026-08-01T21:33:10-04:00"
parent: "[[084-pi-subagent-result-delivery-product-semantics-grill|Pi subagent result delivery product semantics]]"
blocked-by: []
tags:
- ticket/research
---
# Subagent UI other harness patterns research
## Question
What do other agent harnesses and adjacent developer-agent tools make visible for background or parallel agents, tasks, jobs, or delegated work, and what design patterns should inform Pi's improved subagent UI without prescribing workflow-specific result handling?
## Answer
Primary sources point to a consistent product pattern: background or delegated agent work needs a durable visible object with an identity, label or title, lifecycle state, detailed transcript or log, and explicit retrieval or steering actions.
Claude Code is the closest peer for Pi because it documents background subagents, a task list, a fork panel, completion notifications, named-agent status in typeahead, permission prompts that name the child, failure preservation, resumable transcripts, and final summaries returned to the main conversation.
GitHub Copilot cloud agent is the strongest adjacent cloud pattern because it centralizes long-running work in an agents panel and session list, opens a session log and overview with progress, token usage, and session length, lets users steer or stop a session, keeps archived history, and answers later questions from session logs.
Devin's public API shows the same model in API form: sessions have ids, titles, tags, status enums, timestamps, messages, pull-request links, structured output, list filtering by tags, detailed retrieval, tag updates, and termination.
OpenHands SDK shows a composable library pattern: concurrent background conversations, conversation forks with titles and tags, execution status, pause and resume, and non-intrusive `ask_agent()` progress questions.
For Pi, these sources support an inbox-like subagent surface plus compact ambient status and one-shot notifications, rather than default uncontrolled conversation injection.
The generic layer should expose the durable work object and retrieval/acknowledgment mechanics, while workflow-specific code decides what it means to reconcile the result.
## Findings
### Claude Code foreground, background, and task-list patterns
Claude Code documents subagents as specialized assistants that run in their own context window with custom prompts, tool access, and permissions, and that return only a summary to the main conversation for context management.
It distinguishes subagents from independent parallel sessions and points users to background agents when they need to monitor many independent sessions from one place.
It also treats descriptions as routing labels because Claude uses each subagent description to decide when to delegate.
Citation: [Anthropic Claude Code subagents](https://docs.anthropic.com/en/docs/claude-code/sub-agents).
Claude Code lets users invoke subagents by natural language, by `@` mention, or as a session-wide agent.
Its `@` typeahead includes named background subagents that are currently running and shows their status next to the name.
This is direct evidence for exposing child identity and lifecycle state at selection or reference points, not only in a separate status command.
Citation: [Anthropic Claude Code subagents](https://docs.anthropic.com/en/docs/claude-code/sub-agents).
Claude Code explicitly separates foreground and background subagents.
Foreground subagents block the main conversation until completion.
Background subagents run concurrently while the user continues working.
When a background subagent needs tool permission, the prompt appears in the main session and names the subagent that is asking.
As of the documented version, background subagent results reach Claude as a completion notification in a later turn, and Claude waits for that notification before reporting the result.
Citation: [Anthropic Claude Code subagents](https://docs.anthropic.com/en/docs/claude-code/sub-agents).
Claude Code keeps completed background subagents visible in `/tasks`, marked done and sorted below running work, until session cleanup.
Its detail view stays open when a subagent finishes.
Failures and stopped subagents leave the list, while API-error failures are reported as failures rather than as findings, and the failure message can include last output so partial work is not lost.
This supports a Pi rule that terminal status and terminal output should remain retrievable until explicitly cleared or retained by policy.
Citation: [Anthropic Claude Code subagents](https://docs.anthropic.com/en/docs/claude-code/sub-agents).
Claude Code documents parallel-research usage where multiple subagents explore independent areas and Claude synthesizes their findings when results return.
It warns that many detailed results consume main-conversation context, which supports Pi keeping result bodies retrievable out of band and only injecting or summarizing by deliberate action.
Citation: [Anthropic Claude Code subagents](https://docs.anthropic.com/en/docs/claude-code/sub-agents).
Claude Code also documents nested delegation.
A subagent can spawn subagents below it up to a configured depth, and nested subagents are recommended when a delegated task itself splits into parallel subtasks so intermediate output never reaches the main conversation and only the top-level summary returns.
This supports preserving hierarchy or parent-child relationships when Pi eventually displays multi-level delegated work, even if the first implementation stays flat.
Citation: [Anthropic Claude Code subagents](https://docs.anthropic.com/en/docs/claude-code/sub-agents).
Claude Code forked subagents appear in a panel below the prompt input with one row for the main session and one row for each fork.
The panel supports navigation, opening a fork transcript and sending follow-up messages, dismissing a finished fork, stopping a running fork, and returning focus to the prompt.
When a fork finishes, its result arrives as a message in the main conversation.
This is a strong UI pattern for Pi's richer subagent widget: rows, statuses, open transcript/details, stop, dismiss or acknowledge, and explicit result handling.
Citation: [Anthropic Claude Code subagents](https://docs.anthropic.com/en/docs/claude-code/sub-agents).
Claude Code persists subagent transcripts independently from the main conversation.
Main-conversation compaction does not affect subagent transcripts, session persistence lets users resume subagents after restarting the same session, and automatic cleanup removes transcripts after a retention period.
This supports Pi separating compact visible state from potentially large child transcripts or results, and making retention an explicit product concept.
Citation: [Anthropic Claude Code subagents](https://docs.anthropic.com/en/docs/claude-code/sub-agents).
### Claude Code common-workflow and scheduled-task patterns
Claude Code's common workflows recommend delegating research to subagents when codebase exploration would flood the parent context.
The subagent reads files in its own context window and reports a summary.
Citation: [Anthropic Claude Code common workflows](https://docs.anthropic.com/en/docs/claude-code/common-workflows).
Claude Code's common workflows also describe parallel sessions via git worktrees and state that background agents are the way to monitor parallel sessions from one screen instead of separate terminals.
This reinforces the distinction between many visible work objects and one active conversation.
Citation: [Anthropic Claude Code common workflows](https://docs.anthropic.com/en/docs/claude-code/common-workflows).
For scheduled autonomous tasks, the same documentation tells users to be explicit about what success looks like and what to do with results because the task runs autonomously and cannot ask clarifying questions.
Its example asks Claude to review pull requests with a label, leave inline comments, and post a summary in a channel.
This supports Pi keeping the generic subagent layer workflow-neutral while letting the caller's prompt or skill define success and result destination.
Citation: [Anthropic Claude Code common workflows](https://docs.anthropic.com/en/docs/claude-code/common-workflows).
### GitHub Copilot cloud agent session-management patterns
GitHub Copilot cloud agent works independently in the background to complete tasks.
GitHub documents that it can research a repository, create implementation plans, fix bugs, update docs, address technical debt, and optionally open a pull request.
It runs in its own ephemeral development environment powered by GitHub Actions.
Citation: [GitHub Docs, Overview of Copilot cloud agent](https://docs.github.com/en/copilot/concepts/agents/cloud-agent/about-cloud-agent).
GitHub exposes delegated work through an agents panel and other entry points on GitHub.com.
The user can have Copilot research, plan, make code changes on a branch, iterate before creating a pull request, or request that a pull request be created right away.
Third-party integrations are explicitly more constrained, because they only support creating a pull request directly rather than deep research, planning, and iterative pre-PR work.
Citation: [GitHub Docs, Overview of Copilot cloud agent](https://docs.github.com/en/copilot/concepts/agents/cloud-agent/about-cloud-agent).
GitHub's session-management documentation says the agents panel can monitor and manage agent sessions across repositories.
Sessions started by the user or prompted by another user appear in a sessions list.
Clicking a session opens a session log and overview where the user can monitor progress, token usage, and session length.
Citation: [GitHub Docs, Managing agent sessions](https://docs.github.com/en/copilot/how-tos/copilot-on-github/use-copilot-agents/manage-and-track-agents).
GitHub's session logs show Copilot's internal reasoning and tools used to understand the repository, make changes, and validate work.
Commits authored by Copilot include a link to session logs, providing traceability for later code review or audit.
Citation: [GitHub Docs, Managing agent sessions](https://docs.github.com/en/copilot/how-tos/copilot-on-github/use-copilot-agents/manage-and-track-agents).
GitHub lets users steer a running session by opening the session and typing a follow-up prompt below the session log.
It lets users stop a session, which ends the GitHub Actions run and preserves already-pushed commits.
It lets users archive stopped sessions to remove them from the session list, and cloud-agent sessions can be archived but not deleted.
Citation: [GitHub Docs, Managing agent sessions](https://docs.github.com/en/copilot/how-tos/copilot-on-github/use-copilot-agents/manage-and-track-agents).
GitHub distinguishes visibility and retrieval semantics for cloud and local sessions.
Cloud-agent sessions are visible by default to repository collaborators in the repository Agents tab, while local sessions are private by default and can be shared view-only.
Recipients can view prompts, responses, and file changes but cannot steer or modify the shared local session.
Citation: [GitHub Docs, Managing agent sessions](https://docs.github.com/en/copilot/how-tos/copilot-on-github/use-copilot-agents/manage-and-track-agents).
GitHub lets users query past sessions in natural language across synced sessions.
When a session is complete or a Copilot-created pull request is being viewed, the user can ask what changed, what was validated, and why, and Copilot answers from session logs.
This supports a Pi design where the completed result remains a retrievable record rather than only a transient notification.
Citation: [GitHub Docs, Managing agent sessions](https://docs.github.com/en/copilot/how-tos/copilot-on-github/use-copilot-agents/manage-and-track-agents).
### Devin session API patterns
Devin's API models delegated work as sessions.
Creating a session requires a prompt and can include a custom title, tags, snapshot id, playbook id, secrets, ACU limit, idempotency, visibility, and a structured-output schema.
If a custom title is omitted, the API can generate one automatically.
This supports Pi accepting caller-provided labels while falling back to inferred or generated labels.
Citation: [Devin API, Create a new session](https://docs.devin.ai/api-reference/v1/sessions/create-a-new-devin-session.md).
Devin's list-sessions endpoint returns session summaries and supports filtering by tags and user email.
Session summaries include session id, title, status, status enum, timestamps, tags, pull-request info, structured output, snapshot id, playbook id, and requesting user email.
The documented status enum includes `working`, `blocked`, `expired`, `finished`, suspend and resume request states, and `resumed`.
Citation: [Devin API, List sessions](https://docs.devin.ai/api-reference/v1/sessions/list-sessions.md).
Devin's retrieve-session endpoint returns detailed session information including status, output metadata, messages, structured output, pull-request info, tags, title, created time, and updated time.
This supports a Pi separation between list summary data and full result or transcript retrieval.
Citation: [Devin API, Retrieve details about an existing session](https://docs.devin.ai/api-reference/v1/sessions/retrieve-details-about-an-existing-session.md).
Devin's API also exposes tag updates and session termination.
Tag updates are capped at 50 tags.
Termination ends an active session and cannot be resumed.
These endpoints support explicit user-managed organization and lifecycle actions on background work objects.
Citations: [Devin API, Update session tags](https://docs.devin.ai/api-reference/v1/sessions/update-session-tags.md) and [Devin API, Terminate a session](https://docs.devin.ai/api-reference/v1/sessions/terminate-a-session.md).
### OpenHands SDK concurrent conversation and fork patterns
OpenHands SDK documents running multiple agent conversations in parallel with `asyncio.gather()` and running a conversation in a background thread with a callback that receives results in the main run loop.
This is a library-level pattern rather than a finished UI pattern, but it reinforces that background execution should have callback or event delivery rather than requiring a blocking wait.
Citation: [OpenHands SDK, Conversation with Async](https://docs.openhands.dev/sdk/guides/convo-async.md).
OpenHands SDK documents `Conversation.fork()` as a deep copy of a conversation's events, agent configuration, and workspace metadata into a new conversation id.
The fork starts in `idle` status, retains the full event memory of the source, can have a title, tags, metadata, a different agent, and fresh or preserved metrics.
Its examples include CI debugging, A/B testing, and tool changes.
This supports Pi treating side explorations as separately identifiable records that can be compared or resumed without contaminating the source context.
Citation: [OpenHands SDK, Fork a Conversation](https://docs.openhands.dev/sdk/guides/convo-fork.md).
OpenHands SDK documents `ask_agent()` as a non-intrusive way to ask context-aware questions during or after a conversation without interrupting the main execution flow.
Its use cases include progress monitoring.
This supports a Pi detail view or retrieval command that can answer status/progress questions without forcing the background worker's entire result into the active parent exchange.
Citation: [OpenHands SDK, Ask Agent Questions](https://docs.openhands.dev/sdk/guides/convo-ask-agent.md).
OpenHands SDK documents pause and resume by starting a conversation in a background thread, calling `conversation.pause()`, observing execution status after pause, sending another message while paused, and calling `run()` again to resume.
This supports exposing pause or stop state as lifecycle state rather than hiding it in logs.
Citation: [OpenHands SDK, Pause and Resume](https://docs.openhands.dev/sdk/guides/convo-pause-and-resume.md).
## Design patterns for Pi
Pi should model each background subagent as a durable current-session work item with id, label, status, timestamps, prompt summary, terminal summary, and retrieval handle.
This pattern is backed by Claude Code's `/tasks`, fork panel, and transcript ids, GitHub's sessions list and log pages, and Devin's session summary and detail APIs.
Pi should keep compact ambient awareness separate from result bodies.
A footer or widget can show counts and short rows for running, done, failed, cancelled, or unread work, while an explicit detail command or expanded widget retrieves full result text.
This pattern follows Claude Code's done task rows and detail view, GitHub's agents panel plus session-log drilldown, and Devin's summary-list versus detail-retrieve split.
Pi should make completion visible once and then persistent until acknowledged or cleared.
Claude Code documents completion notifications and completed tasks that remain listed.
GitHub documents stopped-session archiving rather than deletion from history.
Devin exposes finished sessions and timestamps through list and detail APIs.
Pi should show failure as a first-class terminal state and preserve partial output when available.
Claude Code documents background API-error failures that mark the subagent failed and include last output.
GitHub stops sessions while preserving already-pushed commits.
Devin exposes `blocked`, `expired`, and `finished` status enums rather than a single done bit.
Pi should support caller-provided labels and generated fallback labels.
Claude Code names forks from the first words of the task and uses named subagents in typeahead.
Devin accepts a custom title and otherwise can generate a title.
GitHub session lists provide human-openable session entries.
Pi should expose actions separately from workflow reconciliation.
Generic actions should include inspect, retrieve result, mark read or acknowledge, dismiss or clear, cancel or stop running work, and maybe open transcript.
Workflow-specific actions such as updating a Wayfinder ticket, synthesizing research, or commenting on a PR should remain outside the generic subagent layer.
Claude Code and GitHub both expose generic session actions, while their examples let the task prompt decide whether to create PRs, post summaries, or synthesize findings.
Pi should avoid default uncontrolled injection into the active parent conversation.
Claude Code does return background subagent results as a later main-conversation message, but it also warns that many detailed results consume main-conversation context.
GitHub and Devin primarily use explicit session/log retrieval surfaces.
For Pi's HITL grill case, the safer synthesis is notice plus inbox plus explicit retrieval, with any parent-session injection reserved for a controlled opt-in behavior.
## Limitations and evidence gaps
Cursor documentation was investigated, but the accessible HTML repeatedly rendered the generic docs shell rather than stable primary page bodies for Cloud Agent pages in this environment.
Cursor was therefore not used for settled claims beyond noting the evidence gap.
OpenAI Codex documentation was investigated, but the accessible pages in this environment did not yield stable primary Markdown or easily extractable page bodies for cloud tasks.
Codex was therefore not used for settled claims.
The research did not inspect live proprietary UIs such as Devin or GitHub Copilot by logging into accounts.
Findings are limited to public first-party documentation and first-party API schemas.
Claude Code behavior is moving quickly and its docs include version-specific notes.
The patterns are useful for product design, but exact version behavior should not be copied into Pi without checking the target version at implementation time.
## Citations
- Anthropic Claude Code subagents, including background subagents, `/tasks`, completion notifications, permission prompts, parallel research, nested subagents, fork panel, transcripts, and retention: <https://docs.anthropic.com/en/docs/claude-code/sub-agents>.
- Anthropic Claude Code common workflows, including delegated research, parallel sessions, background-agent monitoring, and scheduled-task result handling: <https://docs.anthropic.com/en/docs/claude-code/common-workflows>.
- GitHub Docs, Overview of Copilot cloud agent, including background autonomous work, agents panel entry points, branches, pull requests, ephemeral environments, and integrations: <https://docs.github.com/en/copilot/concepts/agents/cloud-agent/about-cloud-agent>.
- GitHub Docs, Managing agent sessions, including agents panel, session list, session log and overview, progress, token usage, session length, steering, stopping, archiving, sharing, querying, and completed-session questions: <https://docs.github.com/en/copilot/how-tos/copilot-on-github/use-copilot-agents/manage-and-track-agents>.
- Devin API, Create a new session, including prompt, title, tags, structured output schema, idempotency, snapshots, playbooks, and generated title fallback: <https://docs.devin.ai/api-reference/v1/sessions/create-a-new-devin-session.md>.
- Devin API, List sessions, including summaries, tag and user filtering, status enum, timestamps, titles, tags, pull request info, and structured output: <https://docs.devin.ai/api-reference/v1/sessions/list-sessions.md>.
- Devin API, Retrieve details about an existing session, including status, messages, metadata, structured output, title, tags, timestamps, and pull request info: <https://docs.devin.ai/api-reference/v1/sessions/retrieve-details-about-an-existing-session.md>.
- Devin API, Update session tags: <https://docs.devin.ai/api-reference/v1/sessions/update-session-tags.md>.
- Devin API, Terminate a session: <https://docs.devin.ai/api-reference/v1/sessions/terminate-a-session.md>.
- OpenHands SDK, Conversation with Async, including concurrent agent tasks and background-thread result callbacks: <https://docs.openhands.dev/sdk/guides/convo-async.md>.
- OpenHands SDK, Fork a Conversation, including copied state, idle status, titles, tags, metadata, alternate agents, and fork REST endpoint: <https://docs.openhands.dev/sdk/guides/convo-fork.md>.
- OpenHands SDK, Ask Agent Questions, including non-intrusive progress questions during and after execution: <https://docs.openhands.dev/sdk/guides/convo-ask-agent.md>.
- OpenHands SDK, Pause and Resume, including execution status, background thread execution, pause, and resume: <https://docs.openhands.dev/sdk/guides/convo-pause-and-resume.md>.

View File

@@ -0,0 +1,121 @@
---
status: resolved
claimed-by: "019fc02c-3d48-71aa-b1b4-0ea51138ad4a"
claimed-at: "2026-08-01T21:52:36-04:00"
resolved-at: "2026-08-01T21:54:08-04:00"
parent: "[[084-pi-subagent-result-delivery-product-semantics-grill|Pi subagent result delivery product semantics]]"
blocked-by: []
tags:
- ticket/research
---
# Pi subagent read-only attach feasibility research
## Question
Can Pi support a read-only attached child session view that looks like a normal Pi session without the text prompt, using an overlay or temporary replacement rather than split panes, and what implementation boundary should the result-delivery effort assume?
## Answer
Pi can support the product shape, but not as a pure current subagent-extension UI tweak.
The implementation boundary should assume a Pi-native child-session viewer component owned by the subagent/result-delivery extension, fed by child RPC or session-entry events, and rendered through `ctx.ui.custom()` as either a focused overlay or a temporary editor-area replacement.
The boundary should not assume Pi can simply attach an existing live `InteractiveMode` instance, hide its prompt, and embed that normal session view inside the parent TUI.
## Findings
Pi's extension TUI surface already supports the two requested placement modes.
`ctx.ui.custom()` can show a custom component in place of the editor when `overlay` is absent, and it can render an overlay when `{ overlay: true }` is passed, with width, max-height, anchor, row, column, margin, focus, hiding, and lifecycle handles exposed through `overlayOptions` and `onHandle`.[^tui-overlays]
The implementation source confirms the non-overlay path clears `editorContainer`, adds the custom component there, focuses it, and restores the editor when closed, while the overlay path calls `this.ui.showOverlay(component, resolveOptions())` without replacing the editor container.[^interactive-custom]
The TUI implementation confirms overlays are composited over the visible viewport and clipped by `maxHeight`, and focused overlays receive input through the normal component `handleInput` path.[^tui-overlay-source]
Pi's public TUI component contract is sufficient for a read-only attached viewer component.
A component renders lines for a width, may handle keyboard input, and invalidates caches on theme changes, so an attach view can implement detach plus scroll keys without accepting text input.[^tui-component]
Pi's own docs explicitly tell extension authors to call `tui.requestRender()` after state changes, which is enough for a live view that updates as child events arrive.[^tui-render]
Pi's overlay lifecycle documentation says overlays are disposed when closed and should be recreated rather than reused, so attach/detach should be treated as opening and closing a viewer instance rather than keeping a permanently mounted component around.[^tui-lifecycle]
Pi already exposes the rendering pieces needed to make the viewer look Pi-like, but not a single exported complete transcript widget.
The main package exports `AssistantMessageComponent`, `UserMessageComponent`, `ToolExecutionComponent`, `CustomMessageComponent`, `DynamicBorder`, `getMarkdownTheme`, and other interactive components from `@earendil-works/pi-coding-agent`, which means extension code can reuse Pi's message and tool rendering styles rather than reimplement every visual primitive.[^component-exports]
The interactive mode's own replay path constructs `UserMessageComponent`, `AssistantMessageComponent`, `ToolExecutionComponent`, and related components from session messages and tool events, showing the composition pattern that a child viewer would need to mirror.[^interactive-replay]
However, `InteractiveMode` keeps `chatContainer`, `editorContainer`, `defaultEditor`, `editor`, `footerContainer`, event subscriptions, and render state as private internals, so there is no public API that exposes a ready-made promptless transcript pane for an extension to mount directly.[^interactive-private]
The current subagent runner is not yet feeding enough structured data to an attach view.
It spawns child Pi as `--mode rpc --no-extensions --extension <subagents/index.ts> --name "subagent <id>"`, communicates over JSONL stdin/stdout, and currently records coarse lifecycle strings such as `agent_started`, arbitrary event types, `agent_settled`, and final `get_last_assistant_text`.[^subagent-runner]
The subagent `SubagentStatus` type has an optional `childSession` field, but the current runner never populates it from RPC `get_state`, and `RunnerEvents.accepted(childSession?: string)` is called without a child session path.[^subagent-types]
Therefore the existing extension can show statuses and final results, but it cannot render a live Pi-like child transcript without extending the runner/supervisor data path to retain child events, retrieve child entries or messages, or learn and load the child's session file.[^subagent-ui]
RPC mode is a viable feed for a child-session viewer.
Pi's RPC docs state that events are streamed as JSON lines while the agent operates, including `agent_start`, `agent_settled`, `turn_start`, `turn_end`, `message_start`, `message_update`, `message_end`, and tool execution lifecycle events.[^rpc-events]
RPC also exposes `get_state`, whose response includes `sessionFile` and `sessionId`, and `get_entries`, which returns append-only session entries with stable ids and a `leafId` cursor.[^rpc-state]
RPC `message_update` includes both the partial assistant message and the assistant streaming delta, so a viewer can support a live transcript rather than waiting only for terminal results.[^rpc-message-update]
The current subagent runner already parses the child stdout stream line by line, so preserving these event payloads and publishing them to an attach viewer is an extension-boundary change rather than a new operating-system or terminal integration.[^subagent-runner]
A second full `InteractiveMode` inside the parent is not the right boundary for this effort.
The SDK documents `InteractiveMode` as a full TUI mode with editor, chat history, built-in commands, session runtime, and an own `run()` loop.[^sdk-interactive]
`InteractiveMode.init()` builds a root `FlexSpacerBottomLayout` containing header, loaded resources, chat, pending messages, status, widgets, editor, and footer, then starts a `TUI` and sets focus to the editor.[^interactive-init]
Embedding that whole mode inside the parent overlay would mean nested terminal/TUI ownership, duplicate editor/footer/runtime management, and prompt input that must then be suppressed.
Primary docs and exports show reusable components and SDK sessions, but they do not provide an attach API that mounts another mode's transcript inside the current TUI.
RPC child mode has an important limitation for extension UI fidelity.
The RPC documentation says `ctx.ui.custom()` returns `undefined` in RPC mode and `setFooter()`, `setHeader()`, `setEditorComponent()`, `setWorkingIndicator()`, and related direct-TUI methods are no-ops.[^rpc-ui-limit]
That means an attached view of a child running in RPC mode can faithfully show normal agent messages, thinking, tool calls, and tool outputs from events, but it cannot display arbitrary child-side custom TUI overlays/components as if the child had its own terminal.
For the subagent result-delivery effort, this limitation is acceptable if the promised attach view is a normal Pi-like transcript without the text prompt, not a full nested interactive Pi process.
## Implementation boundary
Build an attach-view feature inside the subagent/result-delivery extension using Pi's extension UI and reusable rendering components.
Extend the child runner/supervisor to retain a per-child event stream, final session metadata, and enough message/tool state to reconstruct a transcript.
Prefer an RPC-event-fed live model, optionally backfilled from `get_entries` or the child session file once `get_state.sessionFile` is captured.
Render the selected child in a focused `ctx.ui.custom()` overlay for the approved overlay path, with a fallback non-overlay custom component that temporarily replaces the editor area.
Implement read-only controls in that component only: detach and scroll up/down.
Do not implement split panes.
Do not try to embed a nested `InteractiveMode`, duplicate a child terminal, or depend on child-side direct TUI extension UI being visible.
If exact visual parity is required later, the Pi core boundary would be a new exported transcript/viewer abstraction extracted from `InteractiveMode`, not a change to Wayfinder or to the status/result tool API alone.
## Limitations
No primary source documents a supported promptless child-session attach API.
The feasibility conclusion is therefore based on Pi's documented extension UI contract, exported components, RPC event protocol, and current source shape rather than an existing first-class feature.
The research did not run an end-to-end prototype that renders a live child transcript in an overlay.
The source evidence establishes the API boundary and feasibility, but implementation will still need tests for rendering, scroll behavior, event ordering, and terminal resize behavior.
The current child process is launched with `--no-extensions` plus only the subagents extension explicitly loaded.
That is good for avoiding recursive/project extension effects, but it also means the attached child view should not promise to show project/global child extension UI unless that launch policy changes.
## Citations
[^tui-overlays]: `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/tui.md`, "Overlays" and "Overlay Focus".
[^interactive-custom]: `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/dist/modes/interactive/interactive-mode.js`, `showExtensionCustom()`.
[^tui-overlay-source]: `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/node_modules/@earendil-works/pi-tui/dist/tui.js`, `showOverlay()`, `handleInput()`, and `compositeOverlays()`.
[^tui-component]: `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/tui.md`, "Component Interface".
[^tui-render]: `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/tui.md`, "Key Rules".
[^tui-lifecycle]: `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/tui.md`, "Overlay Lifecycle".
[^component-exports]: `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/dist/index.d.ts`, interactive component and theme exports.
[^interactive-replay]: `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/dist/modes/interactive/interactive-mode.js`, `addMessageToChat()` and `renderSessionItems()`.
[^interactive-private]: `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/dist/modes/interactive/interactive-mode.d.ts`, private fields on `InteractiveMode`.
[^subagent-runner]: `/home/alexion/wrk/dotfiles/modules/agents/pi/extensions/subagents/runner.ts`, `SubprocessRpcRunner.start()` and `RpcChildHandle.onLine()`.
[^subagent-types]: `/home/alexion/wrk/dotfiles/modules/agents/pi/extensions/subagents/types.ts`, `SubagentStatus`, `RunnerEvents`, and `ChildRunner`.
[^subagent-ui]: `/home/alexion/wrk/dotfiles/modules/agents/pi/extensions/subagents/ui.ts` and `/home/alexion/wrk/dotfiles/modules/agents/pi/extensions/subagents/index.ts`, current widget and registered tool/command behavior.
[^rpc-events]: `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/rpc.md`, "Events" and "Event Types".
[^rpc-state]: `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/rpc.md`, `get_state` and `get_entries`.
[^rpc-message-update]: `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/rpc.md`, `message_update (Streaming)`.
[^sdk-interactive]: `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/sdk.md`, "Run Modes" and `InteractiveMode`.
[^interactive-init]: `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/dist/modes/interactive/interactive-mode.js`, `init()` layout setup.
[^rpc-ui-limit]: `/nix/store/p2xh13r9f890af4b8jdp60rnld1kbwsl-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/rpc.md`, "Extension UI Protocol" limitations.

View File

@@ -0,0 +1,105 @@
---
status: resolved
claimed-by: "019fbff0-e725-79bd-861c-f1928d963392"
claimed-at: "2026-08-01T22:00:33-04:00"
resolved-at: "2026-08-01T22:00:33-04:00"
parent: "[[089-pi-subagent-result-delivery-design-approval-grill|Pi subagent result delivery design approval]]"
blocked-by:
- "[[089-pi-subagent-result-delivery-design-approval-grill|Pi subagent result delivery design approval]]"
tags:
- ticket/task/afk
---
# Pi subagent result delivery specification
## Question
Write the approved non-blocking subagent result-delivery and UI behavior as a specification, without implementation slicing.
## Result
The approved behavior design is captured below as a specification.
This artifact intentionally does not divide the work into implementation slices.
# Specification: Pi subagent result delivery
## Purpose
Improve Pi subagents so background work remains visible and retrievable while the parent session continues another workflow.
The motivating case is Wayfinder dispatching AFK research workers while the parent continues a HITL grill.
The human should not need to poll, block on `subagent_wait`, or remember that workers might have finished.
## Scope
This specification covers current-session subagent result delivery, completion awareness, work labels, and improved Pi-native subagent UI.
It also covers the boundary between the generic subagent layer and workflow-specific skills such as Wayfinder.
It does not cover cross-restart durability, Herdr integration, remote sandboxing, or redesigning Wayfinder mechanics.
## Generic subagent responsibilities
The generic subagent layer must expose reliable current-session completion state.
It must expose reliable current-session terminal result retrieval.
It must expose completion awareness without requiring blocking waits.
It must expose useful work labels for running and terminal children.
It must not prescribe workflow-specific reconciliation rules.
A completed result remains visible and retrievable for the parent session until it is explicitly cleared.
Terminal result persistence across parent session restart, Pi restart, or extension reload is not required.
## Work labels
Each child should have a human-readable label that explains what it is working on.
The spawn caller may provide an explicit label.
Structured callers may provide or imply a label from their own context, such as a Wayfinder ticket title.
Ad hoc children should fall back to a generated or truncated prompt summary.
## Completion awareness
Completion during HITL work should be visible but non-disruptive.
The UI should announce completion once and keep persistent compact state visible afterward.
Completion notices should identify what finished and whether it completed, failed, timed out, or was cancelled.
Several completions may be batched into one notice.
The generic layer should not inject ordinary messages into the active parent conversation by default.
Result bodies should remain retrievable out of band until a workflow or explicit user action chooses to inspect them.
## Compact UI
The compact UI should show aggregate counts by status rather than one row per child.
The compact view is for ambient awareness while the parent workflow remains primary.
It should be enough to tell that work is running, queued, completed, failed, timed out, cancelled, or otherwise awaiting attention.
## Expanded UI
The expanded UI should show one row per subagent.
Each row should include the child label, lifecycle state, elapsed time, and last activity or result marker.
Rows should truncate cleanly when space is limited.
The expanded view is for quickly understanding what children exist and which ones need attention.
## Attached child view
Selecting a child for inspection should open a read-only attached child view.
The view should look like a normal Pi session view, but without the text prompt.
The view should be an overlay or temporary replacement rather than a split pane.
The view only needs detach and normal scroll up and down controls.
It must not provide a text-input channel to the child.
Pi can support this shape through a custom Pi-native viewer component fed by child RPC or session events.
The design must not assume an embeddable promptless `InteractiveMode` exists.
## Wayfinder boundary
Wayfinder treats the generic subagent layer as a reliable current-session source for child completion, result, and label state.
Wayfinder owns active-map reconciliation.
When AFK workers complete during a HITL ticket, Wayfinder may surface completion awareness but should not read result bodies or reconcile artifacts unless the human explicitly pauses for reconciliation.
After HITL completion or explicit pause, Wayfinder reconciles active-map workers through its normal artifact and Frontier mechanics.
## Acceptance criteria
A parent session can continue a HITL workflow while background subagents run.
The human can see that subagents completed or failed without invoking a blocking wait.
The parent can retrieve terminal results later in the same session.
The compact UI shows aggregate status counts.
The expanded UI shows useful per-child work rows.
A selected child can be inspected through a read-only Pi-like attached view without a prompt.
The generic subagent layer remains workflow-neutral.

View File

@@ -0,0 +1,42 @@
---
status: resolved
parent: "[[094-pi-subagent-result-delivery-spec-task|Pi subagent result delivery specification]]"
blocked-by: []
claimed-by: 019fc03c-54fa-7dac-b6a3-3bf7b8f90b96
claimed-at: 2026-08-01T22:10:19-04:00
resolved-at: 2026-08-01T22:24:09-04:00
tags:
- ticket/implementation
---
# Pi subagent labeled work items
## Question
Implement human-readable subagent work labels throughout spawn, status, result, notifications, and widget surfaces.
## What to build
Subagent spawn and batch spawning should accept or derive a stable human-readable label for each child.
Explicit labels from callers should win.
Structured callers should be able to pass labels without adding workflow-specific semantics to the generic subagent layer.
Ad hoc children should receive a useful prompt-derived fallback label instead of only `ad-hoc <id>`.
The selected label should be stored once on the child record and reused consistently anywhere that child is shown or returned.
## Acceptance criteria
- [x] `subagent_spawn` and `subagent_batch` can carry explicit labels.
- [x] Ad hoc children get a stable prompt-derived fallback label when no explicit label is provided.
- [x] Status, list, result, notifications, and widget rendering use the same label.
- [x] Existing named-agent, config, context, model, thinking, and tool-profile behavior remains compatible.
- [x] Tests cover explicit labels and fallback labels.
## Implementation Notes
Keep labels generic.
Do not encode Wayfinder-specific reconciliation behavior in the subagent layer.
Implemented on branch `subagent-labels` in commit `c5828e0 feat(pi): label subagent work items`.
Verification passed with `nix shell nixpkgs#nodejs_24 nixpkgs#tsx -c tsx --test modules/agents/pi/extensions/subagents/supervisor.test.ts modules/agents/pi/extensions/subagents/runner.test.ts modules/agents/pi/extensions/subagents/config.test.ts`.
Review found no blocking findings after follow-up fixes.
The remaining non-blocking evidence limitation is that `index.ts` tool and command handlers are still covered indirectly through config, supervisor, runner, and notification-format tests rather than a fake Pi extension integration test.

View File

@@ -0,0 +1,45 @@
---
status: resolved
parent: "[[094-pi-subagent-result-delivery-spec-task|Pi subagent result delivery specification]]"
claimed-by: 019fc04b-8b68-74cc-835c-da630d49fb38
claimed-at: 2026-08-01T22:26:56-04:00
resolved-at: 2026-08-01T22:33:51-04:00
blocked-by:
- "[[096-pi-subagent-labeled-work-items-implementation|Pi subagent labeled work items]]"
tags:
- ticket/implementation
---
# Pi subagent clearable terminal work
## Question
Implement current-session terminal subagent visibility so completed, failed, cancelled, and timed-out children stay visible and retrievable until explicitly cleared.
## What to build
Terminal children should remain visible in the current-session subagent work set until the parent or human explicitly clears them.
Terminal result retrieval should keep working until clear.
Completion awareness should be non-blocking and should identify the child label and terminal outcome.
Clearing should remove terminal children from the visible work set without implying workflow-specific reconciliation.
## Acceptance criteria
- [x] Terminal children no longer disappear from the visible current-session list because of a TTL.
- [x] A clear or dismiss command or tool removes terminal children from the visible work set.
- [x] Terminal results remain retrievable until cleared.
- [x] Completion notices include the child label and terminal state.
- [x] Multiple terminal transitions can be noticed without requiring `subagent_wait`.
- [x] Tests cover terminal retention, result retrieval before clear, and removal after clear.
## Implementation Notes
Current-session reliability is sufficient.
Do not add cross-restart result persistence.
Implemented on branch `subagent-labels` in commit `8c85c00 feat(pi): retain terminal subagent work`.
Terminal records now stay in `subagent_list` and the widget until `subagent_clear`, `/subagent-clear`, or `Supervisor.clearTerminal()` removes terminal records.
Result and status retrieval remain available until clear, after which cleared ids are unknown.
Verification passed with `nix shell nixpkgs#nodejs_24 nixpkgs#tsx -c tsx --test modules/agents/pi/extensions/subagents/supervisor.test.ts modules/agents/pi/extensions/subagents/runner.test.ts modules/agents/pi/extensions/subagents/config.test.ts`.
Review found no blocking findings after updating the current-extension inventory artifact.
Accepted non-blocking evidence limitations: the clear tool and command are not covered by an extension-level fake Pi registration test, and multiple terminal notice wiring remains covered through supervisor milestone behavior plus notification formatting rather than a multi-child notification integration test.

View File

@@ -0,0 +1,45 @@
---
status: resolved
parent: "[[094-pi-subagent-result-delivery-spec-task|Pi subagent result delivery specification]]"
claimed-by: 019fc055-36a3-7d64-9d17-5e5ca33a7d11
claimed-at: 2026-08-01T22:37:30-04:00
resolved-at: 2026-08-01T22:41:29-04:00
blocked-by:
- "[[097-pi-subagent-clearable-terminal-work-implementation|Pi subagent clearable terminal work]]"
tags:
- ticket/implementation
---
# Pi subagent compact and expanded monitor
## Question
Implement the approved compact and expanded Pi-native subagent monitor behavior.
## What to build
The existing subagent widget should become the approved monitor.
Compact mode should show aggregate counts by status rather than one row per child.
Expanded mode should show one row per visible child with label, lifecycle state, elapsed time, and last activity or result marker.
The monitor should make running, queued, settling, completed, failed, timed-out, and cancelled work distinguishable without requiring a blocking wait or JSON notification dump.
## Acceptance criteria
- [x] Compact mode shows aggregate counts by meaningful status groups.
- [x] Expanded mode shows one row per child with label, state, elapsed time, and last activity or result marker.
- [x] Rows truncate cleanly to terminal width.
- [x] Failed, timed-out, cancelled, completed-with-result, running, queued, and settling children are visually distinguishable.
- [x] The existing UI toggle still works.
- [x] Tests cover compact and expanded rendering.
## Implementation Notes
Keep compact mode ambient.
Do not make it a transcript or result preview surface.
Implemented on branch `subagent-labels` in commit `aafc68e feat(pi): render subagent monitor views`.
Compact rendering now aggregates visible children into queued, running, settling, completed, failed, timed out, cancelled, and orphaned groups.
Expanded rendering now emits one truncated row per visible child with an icon, state, elapsed time, label, and activity/result/error marker.
Verification passed with `nix shell nixpkgs#nodejs_24 nixpkgs#tsx -c tsx --test modules/agents/pi/extensions/subagents/ui.test.ts modules/agents/pi/extensions/subagents/supervisor.test.ts modules/agents/pi/extensions/subagents/runner.test.ts modules/agents/pi/extensions/subagents/config.test.ts`.
Review found no blocking findings.
The independent test-writer subagent was read-only, so the implementation agent authored the final tests after recording the blocked TDD attempt.

View File

@@ -0,0 +1,42 @@
---
status: resolved
claimed-by: "019fc05b-7c70-7d68-af2b-89e9b6b17950"
claimed-at: "2026-08-01T22:44:20-04:00"
resolved-at: "2026-08-01T22:56:57-04:00"
parent: "[[094-pi-subagent-result-delivery-spec-task|Pi subagent result delivery specification]]"
blocked-by:
- "[[096-pi-subagent-labeled-work-items-implementation|Pi subagent labeled work items]]"
tags:
- ticket/implementation
---
# Pi subagent child activity capture
## Question
Capture structured child RPC or session activity in the subagent runner and supervisor so last-activity summaries and read-only inspection can be driven from current-session state.
## What to build
The child runner and supervisor should retain structured current-session activity events instead of only a coarse last event name.
The captured model should support concise last-activity summaries for status/list/widget output and preserve enough message and tool lifecycle information to render a basic Pi-like child transcript later.
Existing final-result collection through `get_last_assistant_text` should continue to work.
## Acceptance criteria
- [x] Child records retain structured activity events from RPC or session data.
- [x] Activity capture includes enough message and tool lifecycle data to reconstruct a basic Pi-like child transcript.
- [x] Status or list output can expose a concise current activity summary without dumping transcript bodies.
- [x] Final result completion through `get_last_assistant_text` still works.
- [x] Tests cover event capture, ordering where relevant, and state updates.
## Implementation Notes
Use the existing RPC event stream as the first feed.
Do not assume an embeddable promptless `InteractiveMode` exists.
Implemented on branch `subagent-labels` in commit `ede3c05 feat(pi): capture subagent activity events`.
The RPC runner now forwards structured event payloads, the supervisor retains full current-session activity events behind `Supervisor.activity`, and status/list/widget surfaces expose summary-only `currentActivity` and `activityHistory` data.
Verification passed with `nix shell nixpkgs#nodejs_24 nixpkgs#tsx -c tsx --test modules/agents/pi/extensions/subagents/supervisor.test.ts modules/agents/pi/extensions/subagents/runner.test.ts modules/agents/pi/extensions/subagents/ui.test.ts modules/agents/pi/extensions/subagents/config.test.ts` and `nix flake check`.
Review found no blocking findings.
A non-blocking risk note remains that full activity retention is unbounded in process memory for the current session.

View File

@@ -0,0 +1,45 @@
---
status: resolved
claimed-by: "019fc06a-9e21-74fd-b16e-4ce8f24f8c3c"
claimed-at: "2026-08-01T23:00:53-04:00"
resolved-at: "2026-08-01T23:07:04-04:00"
parent: "[[094-pi-subagent-result-delivery-spec-task|Pi subagent result delivery specification]]"
blocked-by:
- "[[099-pi-subagent-child-activity-capture-implementation|Pi subagent child activity capture]]"
tags:
- ticket/implementation
---
# Pi subagent read-only attach view
## Question
Implement a read-only Pi-like attached child view for inspecting a selected subagent without sending input to it.
## What to build
Selecting a child should open a read-only child-session view as a Pi-native overlay or temporary replacement.
The view should look like a normal Pi session view but omit the text prompt and provide no input channel to the child.
It should render captured child conversation and activity in a Pi-like style, support detach, and support normal scroll up and down controls.
It should not introduce split panes.
## Acceptance criteria
- [x] A command or UI action opens an attached view for a known child id.
- [x] The view renders captured child conversation and activity in Pi-like style.
- [x] The view has no text input path to the child.
- [x] Detach returns to the parent session.
- [x] Scroll up and down works.
- [x] No split-pane layout is introduced.
- [x] Tests or documented manual verification cover attach, detach, and scroll behavior.
## Implementation Notes
Use a custom Pi-native viewer component fed by child RPC or session events.
Do not try to embed a nested `InteractiveMode`.
Implemented on branch `subagent-labels` in commit `7bc0d07 feat(pi): add read-only subagent attach view`.
The `/subagent-attach <id>` command opens a Pi-native overlay backed by the current supervisor status and retained child activity, renders a promptless transcript-style view, supports ↑/↓/PgUp/PgDn scrolling, and detaches with Esc or q.
Verification passed with `nix shell nixpkgs#nodejs_24 nixpkgs#tsx -c tsx --test modules/agents/pi/extensions/subagents/supervisor.test.ts modules/agents/pi/extensions/subagents/runner.test.ts modules/agents/pi/extensions/subagents/ui.test.ts modules/agents/pi/extensions/subagents/config.test.ts` and `nix flake check`.
Review found no blocking findings.
Test-driven development was attempted with independent test-writer subagents, but this harness gave them read-only tools, so they could not author the test first.

View File

@@ -0,0 +1,37 @@
---
status: claimed
claimed-by: "019fc07d-ab48-7dba-ae9e-caf6bab66d28"
claimed-at: "2026-08-01T23:21:43-04:00"
parent: "[[100-pi-subagent-read-only-attach-view-implementation|Pi subagent read-only attach view]]"
blocked-by:
- "[[100-pi-subagent-read-only-attach-view-implementation|Pi subagent read-only attach view]]"
tags:
- ticket/implementation
---
# Pi subagent selectable monitor
## Question
Implement selecting a subagent from the expanded monitor and attaching to it without requiring the human to copy an id into `/subagent-attach`.
## What to build
The expanded subagent UI should support a selectable mode for visible subagent rows.
The human should be able to move selection between subagents, see which row is selected, and attach to the selected child with a simple activation key.
The existing `/subagent-attach <id>` command may remain as a fallback, but the primary interaction should be selection from the expanded monitor.
The interaction should not add a text input path to the child and should preserve the read-only attached view behavior that already exists.
## Acceptance criteria
- [ ] Expanded subagent UI has a visible selected row when visible children exist.
- [ ] Keyboard navigation can move the selection between visible subagents.
- [ ] Activating the selected row opens the existing read-only attached child view.
- [ ] Detaching from the attached child view returns to the parent session without losing the monitor state.
- [ ] `/subagent-attach <id>` remains available as a fallback.
- [ ] Tests or documented manual verification cover selection, activation, and detach behavior.
## Implementation Notes
This fixes the gap between the approved design's word "selecting" and the first attach implementation, which only exposed an id-based command.
Prefer a Pi-native custom widget or overlay interaction that works with the existing monitor and attach-view code.