pi-extended-teams 2.3.1 → 2.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,296 +1,60 @@
1
1
  # pi-extended-teams
2
2
 
3
- **A control-first subagent system for Pi.**
3
+ pi-extended-teams runs read and write agents inside Pi, with eight configurable tiers and a live view of their work. Agents have separate conversations, can message each other, and return their results to your current session.
4
4
 
5
- pi-extended-teams lets the lead split work into bounded lanes, watch agents live, steer or stop them, and receive their reports. The lead still makes the final call.
5
+ [![pi-extended-teams demo](assets/pi-extended-teams-demo.gif)](assets/pi-extended-teams-demo.gif)
6
6
 
7
- Read agents are the default. Edit agents are opt-in and should own isolated files.
7
+ ## Features
8
8
 
9
- [![Three agents working in parallel inside Pi](https://raw.githubusercontent.com/dantetekanem/pi-extended-teams/main/assets/pi-extended-teams-in-action.png)](https://raw.githubusercontent.com/dantetekanem/pi-extended-teams/main/assets/pi-extended-teams-in-action.png)
9
+ - Run readers and writers in parallel. One agent can trace a failure while another checks tests or works on a separate change. File claims help writers coordinate their edits.
10
10
 
11
- ## Try without installing
11
+ - Choose models by the work they will do. Eight tiers cover collection, review, analysis, critical reasoning, patches, features, system changes, and critical implementation. Each tier has its own model and thinking setting, with the lead's settings as the fallback.
12
12
 
13
- ```bash
14
- pi -e npm:pi-extended-teams
15
- ```
16
-
17
- This runs the published package for the current Pi invocation without adding it to your project configuration.
18
-
19
- ## Install and run
20
-
21
- Install from npm:
22
-
23
- ```bash
24
- pi install npm:pi-extended-teams
25
- ```
26
-
27
- Or install directly from GitHub:
28
-
29
- ```bash
30
- pi install git:github.com/dantetekanem/pi-extended-teams
31
- ```
32
-
33
- For the first run, start with:
34
-
35
- ```text
36
- /pi-extended-teams-onboard
37
- ```
38
-
39
- On a new installation with no pi-extended-teams settings, a startup notice points to this command. It gives the current agent a read-only snapshot of the models, favorite tiers, shared extensions, and package source available in that Pi session. The agent recommends a setup, shows the exact changes it wants to make, and explains how to update the installed package. Nothing changes until you approve it. Run the command again whenever your models or extensions change.
40
-
41
- Then ask for help naturally:
42
-
43
- ```text
44
- Review the current changes with separate agents for correctness, test gaps, and security. Give me the evidence so I can make the final call.
45
- ```
46
-
47
- The current Pi session becomes the agent group automatically. Setup remains optional: an unset tier inherits the current lead-session model and thinking level. Use `/agents-favorite-models` to configure tiers directly and `/agents-extensions` to choose which observable loaded extensions spawned agents receive.
48
-
49
- ## How it works
50
-
51
- - Public read and edit agents run in separate in-process Pi sessions. A write tier grants edit tools; it does not open a terminal pane. The terminal runtime remains available for existing integrations.
52
- - The activity card shows progress, intent tier, elapsed time, tokens, and tool activity.
53
- - You can open an agent's transcript, send it a message, interrupt a stuck tool command, or stop it.
54
- - Completed reports return to the lead automatically and remain recoverable when needed.
55
- - `get_agent_status` gives the lead or an eligible nested parent one read-only snapshot of owned active, queued, stalled, or recently completed read and edit agents. It uses current-run evidence, preserves lifecycle quarantine, and does not perform cleanup.
56
- - Every spawn names an intent tier instead of choosing ad hoc model settings. Configured favorites take priority; unset tiers inherit the current lead model and thinking.
57
- - Edit agents can claim isolated files. Claims coordinate cooperative agents; they are not access control.
58
- - Lazy session context and nested read helpers are available when a bounded task needs them.
59
-
60
- This works well for multi-angle code review, root-cause investigation, parallel verification, repository mapping, and one narrow edit that can stay separate from the lead's work.
61
-
62
- ## Live control
63
-
64
- With the editor empty, press Down to open agent navigation. Use Down/Up to move, `l` to expand large tool logs, `m` to message an agent, `i` to interrupt its currently running tool command, `x` to stop the whole agent, and Escape to return.
65
-
66
- Inside Herdr, press `h` in an ordinary direct agent's preview to move it into a focused sibling Pi pane in the same workspace. Its conversation and team communication continue there. Nested helpers and delegation-enabled or workflow agents are excluded.
67
-
68
- Scroll the transcript with Page Up/Page Down or the mouse wheel, including under Herdr. Press End or scroll back to the bottom to follow new output.
69
-
70
- The lead can invoke the same command-only behavior with `interrupt_teammate({ agent_name: "agent" })`. It keeps the agent's session, task context, and file claims intact so you can send follow-up work. In-process cancellation is cooperative and may report that it is still pending; for tmux-backed agents, success means Pi's Escape key was delivered, not that command settlement was independently confirmed.
71
-
72
- [![Inspecting and messaging a running agent](https://raw.githubusercontent.com/dantetekanem/pi-extended-teams/main/assets/pi-extended-teams-agent-navigation.png)](https://raw.githubusercontent.com/dantetekanem/pi-extended-teams/main/assets/pi-extended-teams-agent-navigation.png)
73
-
74
- Completed reports wake the lead automatically. End the current turn to wait. One `get_agent_status` snapshot is allowed when current status is needed; do not poll with sleeps, loops, or repeated checks. Use `check_teammate` only when `get_agent_status` shows a suspected lifecycle failure or a persisted report needs recovery.
75
-
76
- The lead owns decomposition, integration, and acceptance. Pi packages and spawned agents run with your system permissions, so review project-local instructions and configuration through Pi's normal trust flow.
77
-
78
- ## Task outcomes and full reports
79
-
80
- A final report or clean exit does not mean the task succeeded. Agents can include an explicit outcome with their full report:
81
-
82
- ```text
83
- report_and_exit({
84
- content: "The implementation needs a product decision. Full findings follow…",
85
- summary: "API decision needed",
86
- outcome: "blocked",
87
- questions: ["Should the endpoint require authentication?"]
88
- })
89
- ```
90
-
91
- Optional outcomes are `succeeded`, `blocked`, `failed`, and `cancelled`. Reports can also include `changedPaths`, `artifacts` (`path`, optional `label`), and `findings` (`id`, `text`, `evidence`). Finding IDs must be unique within the report. These are agent-reported claims and references, not independent verification.
92
-
93
- New reports store a versioned `result` with runtime-assigned task, run, and report IDs in `reports.json`; the full Markdown report remains unchanged. Repeating the same run's report preserves the first stored report. Plain reports remain supported, and omitted outcomes stay unspecified.
94
-
95
- Without assigned checks, verification is `not-requested`. Lead acceptance starts as `pending`. Agent-reported claims cannot change either state. Trusted integrations can record an explicit decision through `recordReportAcceptance(teamName, reportId, "accepted" | "rejected", reason?)` in `src/utils/report-events.ts`. Final-report tools cannot assign identities, verification, or acceptance.
96
-
97
- `get_agent_status` shows task outcome separately from lifecycle status. The lead can recover the full persisted result through `check_teammate` after the agent leaves the roster.
98
-
99
- ## Assigned checks
100
-
101
- The lead can attach explicit checks to `spawn_agent`, individual swarm agents, or swarm defaults:
102
-
103
- ```text
104
- spawn_agent({
105
- name: "result-review",
106
- model_slot: "read-review",
107
- prompt: "Review task outcomes without editing files.",
108
- checks: [{
109
- name: "result-contract",
110
- command: "pnpm --config.verify-deps-before-run=false exec vitest run src/results/report-result.test.ts",
111
- timeoutSeconds: 60
112
- }]
113
- })
114
- ```
115
-
116
- Each check needs a unique name, a command, and a finite positive per-command timeout in seconds. Commands run through Pi's native local BashOperations in the agent's cwd, before its final report closes the recipient. Swarm agents inherit defaults; `checks: []` disables that inheritance. Nested helpers cannot assign checks, and report fields or metadata cannot authorize commands. Trusted spawn integrations receive `checks` on the orchestration request and must bind them as the admitted member's `assignedChecks`.
117
-
118
- Verification records the actual exit, full output, and source before and after execution. Fingerprints include Git HEAD/index metadata, tracked working-file bytes, and nonignored untracked files. Optional `inputs` are literal paths relative to the agent's cwd, contained within its repository; omitting them covers the repository. Unsupported source inputs or Pi runtimes fail visibly rather than falling back to another command runner.
119
-
120
- Check records and private full logs live under `~/.pi/teams/<team>/checks/`. Report IDs reference their check IDs. `listTeamReportEvents` and orchestration/status reads recheck current source and expose stale verification without rewriting historical evidence. After roster removal, `check_teammate` retrieves the report, observed check records, and full-log paths. Ordinary lead notifications include verification state, not full logs.
121
-
122
- Duplicate submissions do not rerun commands. An unresolved execution claim is not replayed and prevents clean finalization. In-process interruption and shutdown cancel assigned checks and wait for raw settlement; nonsettling operations remain quarantined without releasing claims. Failed checks do not imply a failed lifecycle, overwrite the reported task outcome, or grant lead acceptance. Automatic repair is disabled unless explicitly authorized.
123
-
124
- These fingerprints are observations, not snapshots or workspace isolation. They do not capture ignored/external inputs, external services, or edits restored between observations. Checks and agents share the host's permissions; this is not a sandbox against other same-user processes.
125
-
126
- ## Optional bounded repair
127
-
128
- Add `repair: { maxAttempts: 1 }` to a spawn with assigned `checks` to allow one additional repair attempt after initial verification. The limit is zero to five; zero disables repair. Swarm defaults are inherited, and an agent can override them with `{ maxAttempts: 0 }`. Only the lead or a trusted integration can authorize repair. Metadata, report parameters, and nested helpers cannot enable it. Trusted integrations bind the request's `repair` as the member's `repairPolicy`.
129
-
130
- A failed check returns its observed exit and full-log reference to the responsible agent. A `report_and_exit` repair receipt has `accepted: false` and a `repairRequest`; the agent remains active, repairs only its assigned scope, and resubmits. Repair does not grant edit permissions: read agents must report a blocker when edits are needed, and edit agents must keep or reacquire claims before changing files. Plaintext reporting uses a separate repair turn after current work settles. An accepted final-report receipt is still separate from lead acceptance.
131
-
132
- The harness reruns failed checks and checks whose scoped inputs changed. It reuses passed evidence only when the current scoped source matches. Runtime submission IDs prevent duplicate reports from consuming another attempt. Reservations and decisions are persisted before check execution or repair feedback; cancellation prevents further automatic attempts. A pending native claim or controller reservation keeps cleanup fenced even after in-process state is lost. A stop may therefore report blocked cleanup rather than claim the agent stopped.
133
-
134
- Repair history lives under `~/.pi/teams/<team>/repairs/`. The report's `repair` includes its controller ID, ledger path, state, and available attempt counts/request IDs. Missing or corrupt records remain pending with an error; unknown counts are omitted. `listTeamReportEvents`, status, and report recovery read authoritative repair/check evidence without rewriting history. `readStoredTeamReportEvent` retrieves an exact historical record without observing source.
135
-
136
- Exhausted, declined, cancelled, or otherwise blocked repair produces an effective blocker while preserving the agent's reported `outcome`. `effectiveTaskOutcome(result)` exposes that distinction to trusted consumers. Passing checks never invent a success claim or grant lead acceptance. Existing reports and spawns without a repair policy retain their behavior.
137
-
138
- ## Optional grouped reports
139
-
140
- The lead can request compact reports for a batch:
141
-
142
- ```text
143
- spawn_swarm_agents({
144
- completion_group: { delivery: "all-settled" },
145
- defaults: { model_slot: "read-review" },
146
- agents: [
147
- { name: "correctness", prompt: "Review correctness without editing." },
148
- { name: "tests", prompt: "Review test coverage without editing." }
149
- ]
150
- })
151
- ```
152
-
153
- Omitting `completion_group` keeps immediate full-report delivery. `delivery: "immediate"` sends compact member indexes; `"all-settled"` waits for the batch, including queued members. Rejected admissions, cancellations and interruptions have explicit states. Blockers, runtime failures and failed/stale verification can request an early wake. An urgent last result does not require a redundant final wake.
154
-
155
- Reported members' indexes include task/run/slot identity, reported and effective outcomes, verification, acceptance, findings/questions, and a full-report ID/path. Unadmitted assignments retain their slot/state/reason without invented run IDs or results. Read the referenced Markdown when more evidence is needed; it survives private transcript deletion. Index verification is a stored snapshot, so recheck current source-bound evidence before accepting work. Group settlement never grants task success or lead acceptance. Nested reports still target their exact parent, and workflow/pi-prompt suppression excludes lead-facing evidence and wakes.
156
-
157
- Journals live under `~/.pi/teams/<team>/completion-groups/`. A sibling `<inbox>.json.durable` marker keeps an opted-in inbox's later writes synchronized even after its last grouped index is removed; never-grouped inboxes retain ordinary atomic writes. The harness binds membership before admission and actual run IDs before launch; agent metadata cannot authorize grouping. Reload preserves explicit terminal states, records lost unadmitted work as interrupted, and leaves uncertain running ownership unresolved. It does not restart work, revive recipients or release claims.
158
-
159
- A durable inbox index and a wake request have separate receipts. Pi's custom-message call does not return an admission acknowledgment. A reserved request remains `pending` until exact session history is `observed`; that observation is not provider success or a power-loss guarantee. Ambiguous requests are not automatically repeated after errors or reload. Use `read_inbox` for a saved index when a warning reports an unconfirmed wake. Grouped correlation requires Pi's custom-message/history APIs; ordinary delivery keeps its existing fallback.
160
-
161
- ### Measured delivery replay
162
-
163
- One September 8, 2026 comparison used Pi 0.85.1 and configured `read-review` model `openai-codex/gpt-5.6-terra`, high thinking. Two fresh SDK sessions synthesized the same ten supplied source-backed reports, first immediate/full, then all-settled/compact. SSE transport, retries and compaction settings were identical; retries and compaction were disabled.
13
+ - Let a writer call in specialists. A `write-feature` or `write-critical` agent can spawn read helpers when explicitly enabled. Helpers report to that writer and cannot delegate further.
164
14
 
165
- | Observation | Immediate/full | All-settled/compact |
166
- | --- | ---: | ---: |
167
- | Wake requests | 10 | 1 |
168
- | Model requests / assistant responses | 11 | 3 |
169
- | Provider input tokens, excluding cache | 17,796 | 5,149 |
170
- | Cache-read tokens | 17,408 | 5,120 |
171
- | Cache-write tokens | 0 | 0 |
172
- | Output tokens | 293 | 237 |
173
- | Full-report retrievals | 0 | 1 |
174
- | Elapsed time | 26.239s | 10.748s |
15
+ - Direct agent-to-agent messaging lets readers send findings straight to writers, without making the lead relay them.
175
16
 
176
- Both syntheses preserved all ten required finding/control pairs, pending acceptance and the exact detail retrieved from full report F9. Each session emitted one `agent_settled` event; wake requests are not equivalent to completed agent runs. These are actual provider usage figures from one controlled replay, not estimates, randomized statistics, new specialist investigations or a general review-speed guarantee. The [measurement record](docs/grouped-report-measurement.json) retains the assignment, complete corpus, tested source identity, method and observations without session histories or credentials.
17
+ - Follow each agent from the editor. The activity card shows progress, tier, model, elapsed time, and context usage. Down opens the transcript, with theme-aware panels, configurable colors, and expandable tool results.
177
18
 
178
- ## Optional specialist continuation
19
+ - Mouse-wheel and Page Up/Page Down scrolling works inside Herdr, too. Press End to follow live output again.
179
20
 
180
- Save a specialist's findings when you expect a later follow-up:
21
+ - Move an agent into its own Herdr pane with `h`. Eligible direct agents resume their saved conversation in a focused sibling pane and keep communicating with the team.
181
22
 
182
- ```text
183
- spawn_agent({
184
- name: "auth-review",
185
- model_slot: "read-review",
186
- prompt: "Review auth and config. Report stable finding IDs, evidence and inspected source references.",
187
- checkpoint: { inputs: ["auth", "config"], retentionDays: 30 }
188
- })
189
- ```
190
-
191
- The checkpoint preserves the original assignment, scoped source observations, author/run/tier, findings, questions, reported `inspectedEvidence`, lead-supplied `decisions`, and independent report references. It keeps the original report plus bounded recent history. Records are limited to 64 KiB and live in `~/.pi/agent/checkpoints/`, outside private transcripts and Pi's resume picker. Omit both `checkpoint` and `continue_from` to keep ordinary spawning unchanged; metadata and nested helpers cannot enable them. Swarm defaults and individual agents also accept `checkpoint`; put `continue_from` on each selected agent.
192
-
193
- Copy the exact checkpoint ID from the saved report into a new assignment:
194
-
195
- ```text
196
- spawn_agent({
197
- name: "auth-followup",
198
- model_slot: "read-review",
199
- continue_from: "checkpoint:<saved hash>",
200
- prompt: "Recheck F1 and F2 after the tenant fix. Revalidate token-policy dependencies, including unchanged callers."
201
- })
202
- ```
203
-
204
- `name` becomes a prefix for a fresh recipient. Continuation creates a new run and SDK session; it does not reopen the old mailbox or transcript, resume a process, transfer claims, or inherit execution permissions or repair budgets. The current prompt, cwd, tier, instructions, checks and repair policy govern. Old findings, verification and acceptance remain historical claims. Edit agents must acquire their own claims normally.
205
-
206
- Continuation inherits the checkpoint's input scope and retention unless you supply a current `checkpoint` override; old lead decisions are not reauthorized. Scope entries are literal paths relative to the current cwd, contained within its repository. At actual launch, including after queue delays, the harness reloads the checkpoint and compares each retained report's dependency scope. Changed, uncertain or changed-during-investigation evidence requires revalidation beyond the diff. An unchanged fingerprint is not proof that a finding still holds, a dependency graph or a snapshot; ignored/external inputs and restored edits remain outside its evidence.
207
-
208
- Full reports are synchronized independently before checkpoint publication and cleanup. Missing known report provenance or uncertain publication prevents destructive cleanup. In-process read and edit admission supports checkpoints; legacy terminal startup/queue requests reject checkpoint and continuation options. Existing legacy report producers can preserve checkpoint-bound reports. Trusted orchestration requests use `continueFrom`; a custom start callback still owns actual admission and execution.
209
-
210
- Retention defaults to 30 days, with an integer range of 1 to 365. Use the lead-only `/agents-checkpoints list` and `/agents-checkpoints delete <checkpoint ID>` commands. Expired records cannot be loaded; one lead startup sweep retires due records and reports corrupt entries without discarding healthy siblings. Missing, incompatible, corrupt, deleted or expired selections fail with an actionable error. Deletion retires that exact root record permanently, preventing future continuation and replay. It does not erase independent report history or context already delivered to a successor.
211
-
212
- ### Measured follow-up
213
-
214
- One September 8, 2026 pair used Pi 0.85.1 and `openai-codex/gpt-5.6-terra`, high thinking, with identical current source, task and tools. A scripted original investigation saved F1/F2/F3, then its real SDK session was disposed and its private transcript removed before either fresh follow-up session. The fixture fixed tenant isolation, left expiration broken and reopened unsigned-token acceptance through a changed configuration dependency. Both follow-ups correctly classified all three controls.
23
+ - Correct an agent while it works. Press `m` to message it, `i` to interrupt its current command while keeping its context, or `x` to stop it.
215
24
 
216
- | Observation | Fresh | Checkpoint |
217
- | --- | ---: | ---: |
218
- | Model / HTTP requests | 3 / 3 | 3 / 3 |
219
- | Provider input tokens, excluding cache | 1,841 | 3,789 |
220
- | Cache-read / cache-write tokens | 0 / 0 | 1,536 / 0 |
221
- | Output tokens | 267 | 233 |
222
- | File reads / unchanged-file rereads | 3 / 1 | 3 / 1 |
223
- | First useful persisted result | 8.682s | 8.344s |
224
- | Elapsed through final response | 10.296s | 10.156s |
25
+ - Keep running agents through same-process `/reload`. Their controls and reports reconnect after the reload; process restarts are not supported.
225
26
 
226
- This fixture showed no read or input-token savings: input including cache was 1,841 versus 5,325 tokens. One fixed fresh-then-checkpoint pair cannot establish a speed improvement. Each session emitted one `agent_settled`; lead acceptance stayed pending. The controlled starter/report submission exercised real SDK and checkpoint APIs, not full production admission-to-teardown or an OS-process restart. The pair predates the replay, missing-report cleanup and native cancellation repairs, so it does not measure those fixes. The [public record](docs/continuation-measurement.json) preserves the fixed corpus, assignments, method, historical source observation, aggregate results and limits; scripted usage remains null.
27
+ - Choose which of your loaded Pi extensions agents can use. Onboarding recommends models and extension settings for approval.
227
28
 
228
- ## Intent tiers
29
+ - Check the work before accepting it. Assign verification commands, record which source they checked, and optionally allow a limited number of repair attempts. Reports distinguish the agent's claimed outcome from check results.
229
30
 
230
- Every spawn names a `model_slot`. Configured favorites take priority; otherwise the tier uses the current lead-session model and thinking level:
31
+ - Keep the findings after agents exit. Reports arrive automatically, can be grouped into a batch summary, and remain recoverable. Save specialist findings for a fresh follow-up; compatible footers can show combined recorded session costs.
231
32
 
232
- | Tier | Use it for |
233
- | --- | --- |
234
- | `read-collect` | Bounded facts, logs, inventories, or test output. |
235
- | `read-review` | Normal review, verification, and test-gap work. |
236
- | `read-analyze` | Root-cause analysis across connected evidence. |
237
- | `read-critical` | Rare high-stakes security, architecture, concurrency, migration, or data reasoning. |
238
- | `write-patch` | A narrow documentation, config, fixture, or bug fix. |
239
- | `write-feature` | A bounded feature with a known design. |
240
- | `write-system` | A cross-cutting integration or refactor inside claimed files. |
241
- | `write-critical` | Rare high-risk security, concurrency, recovery, migration, or data-integrity work. |
33
+ ## Get started
242
34
 
243
- `read-review` is the normal read default. Legacy tier names remain accepted for this minor release, but new prompts should use the canonical names above.
35
+ Try it for one Pi session:
244
36
 
245
- ## Explicit spawning
246
-
247
- Pi can choose when delegation helps, or you can call the tools directly:
248
-
249
- ```text
250
- spawn_swarm_agents({
251
- defaults: { model_slot: "read-review" },
252
- agents: [
253
- { name: "correctness", prompt: "Review the diff for concrete correctness risks. Do not edit." },
254
- { name: "tests", prompt: "Find missing regression coverage with file and line evidence. Do not edit." }
255
- ]
256
- })
37
+ ```bash
38
+ pi -e npm:pi-extended-teams
257
39
  ```
258
40
 
259
- For an edit, choose a write tier and name the files it may claim. Never run overlapping writers against the same paths.
260
-
261
- ### Programmatic event launch
262
-
263
- Another loaded extension can ask the lead session to launch one public agent through the orchestration event. Register the response listener and correlate it by `requestId` before emitting the request:
41
+ Or install it:
264
42
 
265
- ```ts
266
- pi.events.emit("pi-extended-teams:orchestration-request", {
267
- requestId,
268
- type: "spawn_agent",
269
- ctx, // pass the current Pi command context when needed
270
- params: {
271
- name: "implementation",
272
- prompt: "Implement the claimed change and report the evidence.",
273
- cwd,
274
- model_slot: "write-critical",
275
- allow_nested_read_agents: true,
276
- metadata: { operationId },
277
- },
278
- });
43
+ ```bash
44
+ pi install npm:pi-extended-teams
279
45
  ```
280
46
 
281
- The correlated response is `{ requestId, type, ok: true, details, content }` on success or `{ requestId, type, ok: false, error }` on failure. `prompt` is always a direct string; it may tell the child where a packaged prompt file lives, but there is no `prompt_file` API. The configured extension allowlist still determines which tools are available inside the child session. Teammate sessions cannot satisfy these requests.
282
-
283
- ## Configuration
47
+ GitHub installation is also supported: `pi install git:github.com/dantetekanem/pi-extended-teams`.
284
48
 
285
- Global settings live at `~/.pi/agent/pi-extended-teams/settings.json`. Project overrides live at `.pi/pi-extended-teams.json`. Favorite intent tiers are global so `/agents-favorite-models` and spawning use the same choices. Configuring favorites is optional; an unset tier falls back to the current lead-session model and thinking level. `/pi-extended-teams-onboard` inspects both settings layers, recommends a complete model and extension policy, and gives source-specific package update instructions without changing either file on its first pass.
49
+ Run `/pi-extended-teams-onboard` for setup recommendations, then ask for what you need:
286
50
 
287
- Public read and edit spawns respect their role's concurrency limit and overflow setting. Enabled overflow queues accepted work; disabled overflow returns a capacity error. Quarantined requests stay fenced without blocking unrelated eligible work. `stop_teammate` can cancel a queued request before launch. Failed admissions trigger an attempted recipient notification and remain visible in status (up to 20 recent failures). The public queue and recent failure index are session-local, not restart-durable.
51
+ > Use separate agents to investigate the failure and check the test coverage. Bring their findings back together.
288
52
 
289
- Spawned sessions are private by default under `~/.pi/teams/<team>/agent-sessions/` and stay out of Pi's normal `/resume` picker.
53
+ ## Documentation
290
54
 
291
- ## Security and data access
55
+ [Agent reference](docs/reference.md) covers tiers, keyboard controls, Herdr eligibility, configuration, checks, repair, checkpoints, and extension integration. [The teams skill](skills/teams.md) has orchestration and handoff examples. See [the changelog](CHANGELOG.md) for release history.
292
56
 
293
- Read [SECURITY.md](SECURITY.md) for private vulnerability reporting and [docs/access.md](docs/access.md) for the subprocess, filesystem, extension, hook, and network boundaries.
57
+ Agents run with your system permissions. Read-only roles and file claims are coordination contracts, not sandboxes. See [access disclosures](docs/access.md) and [security reporting](SECURITY.md).
294
58
 
295
59
  ## Development
296
60
 
@@ -299,12 +63,8 @@ pnpm typecheck
299
63
  pnpm test:focused
300
64
  ```
301
65
 
302
- ## Credits
303
-
304
- pi-extended-teams is based on [pi-teams](https://github.com/burggraf/pi-teams). This fork focuses on session-connected agents, live control, and a smaller public tool surface.
305
-
306
- The broader coordination lineage includes [claude-code-teams-mcp](https://github.com/cs50victor/claude-code-teams-mcp).
66
+ ## Credits and license
307
67
 
308
- ## License
68
+ Based on [pi-teams](https://github.com/burggraf/pi-teams), with coordination lineage from [claude-code-teams-mcp](https://github.com/cs50victor/claude-code-teams-mcp).
309
69
 
310
- MIT
70
+ [MIT](LICENSE).
@@ -0,0 +1,270 @@
1
+ # Agent reference
2
+
3
+ Setup, controls, and orchestration contracts for [pi-extended-teams](../README.md).
4
+
5
+ ## Intent tiers
6
+
7
+ Every public spawn requires `model_slot`. Configured favorites take priority; unset tiers inherit the current lead model and thinking level. Direct `role`, `model`, and `thinking` spawn fields are not supported.
8
+
9
+ | Tier | Use it for |
10
+ | --- | --- |
11
+ | `read-collect` | Bounded facts, logs, inventories, or test output. |
12
+ | `read-review` | Normal review, verification, and test-gap work. |
13
+ | `read-analyze` | Root-cause analysis across connected evidence. |
14
+ | `read-critical` | Rare high-stakes security, architecture, concurrency, migration, or data reasoning. |
15
+ | `write-patch` | A narrow documentation, config, fixture, or bug fix. |
16
+ | `write-feature` | A bounded feature with a known design. |
17
+ | `write-system` | A cross-cutting integration or refactor inside claimed files. |
18
+ | `write-critical` | Rare high-risk security, concurrency, recovery, migration, or data-integrity work. |
19
+
20
+ `read-review` is the normal read default. Legacy tier names remain accepted for this minor release, but use canonical names in new prompts. Tiers identify the work; they do not guarantee a correct answer.
21
+
22
+ ## Spawning and coordination
23
+
24
+ Public read and edit agents run in separate in-process Pi sessions. A write tier selects edit work; it does not open a terminal pane. The terminal runtime remains available for existing integrations.
25
+
26
+ ```text
27
+ spawn_swarm_agents({
28
+ defaults: { model_slot: "read-review" },
29
+ agents: [
30
+ { name: "correctness", prompt: "Review the diff for concrete correctness risks. Do not edit." },
31
+ { name: "tests", prompt: "Find missing regression coverage with file and line evidence. Do not edit." }
32
+ ]
33
+ })
34
+ ```
35
+
36
+ Read agents are the default for independent questions. Keep cohesive implementation with the lead. Delegate edits only when files and outcomes can stay separate. Use file claims, and never assign overlapping writers.
37
+
38
+ ### Nested read helpers
39
+
40
+ ```text
41
+ spawn_agent({
42
+ name: "recovery-fix",
43
+ model_slot: "write-critical",
44
+ allow_nested_read_agents: true,
45
+ prompt: "In src/recovery.ts and test/recovery.test.ts, prevent cancelled jobs from resuming. Claim both files. Use read helpers to check cancellation paths, then report the fix and focused test results."
46
+ })
47
+ ```
48
+
49
+ Only a depth-0 `write-feature` or `write-critical` agent with explicit opt-in receives nested spawn tools. Helpers use canonical `read-*` tiers, report to that parent, share its team and cwd, and cannot delegate further. `write-patch`, `write-system`, and read agents cannot spawn helpers. Global capacity still applies.
50
+
51
+ ### Messages and context
52
+
53
+ Agents can address another running agent with `send_message({ recipient, content })`. Omitting the recipient addresses `team-lead`; missing or stopped recipients fail. Messaging does not grant orchestration authority. The lead owns scope, integration, and acceptance.
54
+
55
+ Each agent starts with an isolated conversation. Include the goal, file boundaries, decisions, evidence already collected, and the result you need. `session_context: "lazy"` exposes a bounded, filtered snapshot of the lead's active branch for on-demand reading. It does not eagerly copy the conversation or replace a useful assignment. See [the teams skill](../skills/teams.md) for handoff examples.
56
+
57
+ ## Live controls
58
+
59
+ | Key | Action |
60
+ | --- | --- |
61
+ | Down, with the editor empty | Open agent navigation. |
62
+ | Up / Down | Previous / next agent; Up from the first returns to the lead. |
63
+ | Left / Right | Cycle through agents. |
64
+ | Page Up / Page Down or mouse wheel | Scroll the transcript, including under Herdr. |
65
+ | Home / End | Jump to the beginning / return to following new output. |
66
+ | `l` | Expand or collapse large tool logs. |
67
+ | `m` | Write a message to the selected agent. |
68
+ | `i` | Interrupt its running tool command without stopping the agent. |
69
+ | `x` | Stop the whole selected agent. |
70
+ | `h`, inside Herdr | Move an eligible agent into a focused sibling Pi pane. |
71
+ | Escape | Return to the lead; when composing a message, cancel the composer. |
72
+
73
+ Scrolling back to the bottom resumes following output. Navigation follows activity-row order, and agents still finishing cleanup remain accessible. The message composer clears while sending and restores your draft on failure if it remains open.
74
+
75
+ Panels and borders use Pi's theme. The shared `activityColors` palette controls agent names, tier shades, model/thinking colors, progress, and warnings. Context warnings appear at 75% and 90%.
76
+
77
+ ### Herdr handoff
78
+
79
+ Press `h` in an ordinary direct agent's preview to resume its saved conversation in a focused sibling Pi pane in the same workspace. Team communication continues there. This is a handoff, not a second copy.
80
+
81
+ Nested helpers, delegation-enabled agents, and workflow agents are excluded. An active assigned check blocks transfer until it settles. Public spawning itself requires neither Herdr nor a terminal pane.
82
+
83
+ ### Interrupt, stop, and wait
84
+
85
+ `interrupt_teammate({ agent_name: "agent" })` matches `i`: it preserves the session, task context, and claims. In-process cancellation is cooperative and may remain pending. For tmux-backed agents, success confirms Escape delivery, not command settlement. `stop_teammate` cancels the whole agent, including queued work.
86
+
87
+ Reports return automatically. The lead should end its turn to wait rather than poll. `get_agent_status` provides one read-only snapshot of owned active, queued, stalled, or recently completed agents; eligible nested parents can inspect their helpers too. It preserves lifecycle quarantine and does not clean up. Use `check_teammate` for a suspected lifecycle failure or recovery of a persisted report.
88
+
89
+ ### Reload and costs
90
+
91
+ Running and starting agents survive same-process `/reload`, reconnecting controls, reports, and cost accounting. They keep their original implementation until an idle reload. Failed reconnection has a 60-second recovery window before cancellation starts. Quitting or changing sessions still cleans up agents; process-restart recovery is not supported.
92
+
93
+ Compatible footer extensions can display combined recorded cost for the main session and finalized in-process agents without changing Pi's native usage totals. Unfinished or missing usage keeps the total incomplete. Terminal handoffs are excluded.
94
+
95
+ ## Configuration
96
+
97
+ Global settings live at `~/.pi/agent/pi-extended-teams/settings.json`. Project overrides live at `.pi/pi-extended-teams.json`. Favorite tiers are global so the picker and spawning use the same choices.
98
+
99
+ - `/pi-extended-teams-onboard` gives the current agent a read-only inventory of available models, favorite tiers, shared extensions, and package source. It recommends a setup, shows exact proposed changes, and explains updates. Nothing changes until approved. New installations show a startup notice; rerun onboarding when models or extensions change.
100
+ - `/agents-favorite-models` configures tier models and thinking levels. Type to filter full provider/model names from any picker column. Changes save immediately; thinking choices follow the model's capabilities.
101
+ - `/agents-extensions` chooses which observable loaded extensions spawned agents receive.
102
+
103
+ Public spawns respect each role's concurrency limit. Enabled overflow queues accepted work; disabled overflow returns a capacity error. Quarantined requests stay fenced without blocking unrelated eligible work. Failed admissions attempt recipient notification and remain visible in status, up to 20 recent failures. The public queue and failure index are session-local, not restart-durable.
104
+
105
+ Spawned sessions are private by default under `~/.pi/teams/<team>/agent-sessions/`, outside Pi's normal `/resume` picker.
106
+
107
+ ## Task outcomes and full reports
108
+
109
+ A completed agent, a successful task, passed verification, and lead acceptance are separate facts.
110
+
111
+ ```text
112
+ report_and_exit({
113
+ content: "The implementation needs a product decision. Full findings follow…",
114
+ summary: "API decision needed",
115
+ outcome: "blocked",
116
+ questions: ["Should the endpoint require authentication?"]
117
+ })
118
+ ```
119
+
120
+ Optional outcomes are `succeeded`, `blocked`, `failed`, and `cancelled`. Reports also accept `changedPaths`, `artifacts` (`path`, optional `label`), and `findings` (`id`, `text`, `evidence`). Finding IDs must be unique. These are agent claims and references, not independent verification.
121
+
122
+ New reports store a versioned `result` with runtime-assigned task/run/report IDs in `reports.json`, alongside the unchanged full Markdown report. Repeating a run's report preserves the first stored report. Plain reports remain supported; omitted outcomes stay unspecified.
123
+
124
+ Without checks, verification is `not-requested`; lead acceptance starts `pending`. Report tools cannot assign identities, verification, or acceptance. Lead/trusted integrations can record acceptance through `recordReportAcceptance(teamName, reportId, "accepted" | "rejected", reason?)` in `src/utils/report-events.ts`. `get_agent_status` separates task outcome from lifecycle; `check_teammate` can recover the persisted result after roster removal.
125
+
126
+ ## Assigned checks
127
+
128
+ ```text
129
+ spawn_agent({
130
+ name: "result-review",
131
+ model_slot: "read-review",
132
+ prompt: "Review task outcomes without editing files.",
133
+ checks: [{
134
+ name: "result-contract",
135
+ command: "pnpm --config.verify-deps-before-run=false exec vitest run src/results/report-result.test.ts",
136
+ timeoutSeconds: 60
137
+ }]
138
+ })
139
+ ```
140
+
141
+ Checks require unique names, commands, and finite positive per-command timeouts in seconds. They run through Pi's native local BashOperations in the agent cwd before final-report closure. Swarm defaults are inherited; `checks: []` disables inheritance. Nested helpers, report fields, and metadata cannot authorize checks. Trusted integrations bind request `checks` as `assignedChecks`.
142
+
143
+ Records capture exit, full output, and source before/after execution. Fingerprints cover Git HEAD/index metadata, tracked bytes, and nonignored untracked files. Optional `inputs` are literal repository-contained paths relative to cwd; omission covers the repository. Unsupported inputs or runtimes fail visibly without another runner fallback.
144
+
145
+ Private logs live under `~/.pi/teams/<team>/checks/`; reports reference check IDs. Status, orchestration reads, and `listTeamReportEvents` expose stale verification without rewriting history. `check_teammate` retrieves records and log paths after roster removal; ordinary notifications omit full logs.
146
+
147
+ Duplicate submissions do not rerun commands. Unresolved execution claims prevent clean finalization and are not replayed. Interruption/shutdown cancels checks and waits for raw settlement; nonsettling work remains quarantined with claims retained. Failed checks neither change lifecycle/task outcome nor grant acceptance. Fingerprints are observations, not snapshots or workspace isolation: ignored/external inputs, services, and edits restored between observations are outside coverage.
148
+
149
+ ## Optional bounded repair
150
+
151
+ Add `repair: { maxAttempts: 1 }` with checks for one additional repair attempt. The limit is zero to five; zero disables repair, including inherited swarm policy. Only the lead or a trusted integration authorizes it; integrations bind `repair` as `repairPolicy`. Metadata, report parameters, and nested helpers cannot enable it.
152
+
153
+ A failed check returns its exit and full-log reference. An unaccepted `report_and_exit` receipt carries `repairRequest`: the agent stays active, repairs within scope, and resubmits. Read agents must report a blocker if edits are needed; writers keep or reacquire claims. Plaintext reporting uses a separate repair turn after work settles. Receipt acceptance is not lead acceptance.
154
+
155
+ The harness reruns failed checks and checks with changed inputs, reusing passes only for matching scoped source. Submission IDs prevent duplicate attempt consumption. Persisted reservations/decisions precede execution or feedback; cancellation prevents further attempts. Pending native/controller claims fence cleanup even after in-process state loss, so stop may report blocked cleanup.
156
+
157
+ History lives under `~/.pi/teams/<team>/repairs/`. Report `repair` includes controller ID, ledger path, state, available counts/request IDs. Missing/corrupt records remain pending with an error; unknown counts are omitted. Status/report recovery observes authoritative evidence; `readStoredTeamReportEvent` reads history without observing source.
158
+
159
+ Exhausted, declined, cancelled, or blocked repair preserves the reported outcome but adds an effective blocker, exposed through `effectiveTaskOutcome(result)`. Passing checks never invent success or acceptance. Spawns without repair retain ordinary behavior.
160
+
161
+ ## Optional grouped reports
162
+
163
+ ```text
164
+ spawn_swarm_agents({
165
+ completion_group: { delivery: "all-settled" },
166
+ defaults: { model_slot: "read-review" },
167
+ agents: [
168
+ { name: "correctness", prompt: "Review correctness without editing." },
169
+ { name: "tests", prompt: "Review test coverage without editing." }
170
+ ]
171
+ })
172
+ ```
173
+
174
+ Omission keeps immediate full reports. `"immediate"` sends compact member indexes; `"all-settled"` waits for the batch, including queued members. Rejections, cancellations, and interruptions retain explicit states. Blockers, runtime failures, or failed/stale checks can wake early; an urgent last result needs no redundant final wake.
175
+
176
+ Indexes include task/run/slot identity, reported/effective outcomes, verification, acceptance, findings/questions, and full-report references. Unadmitted assignments retain state/reason without invented identities. Full Markdown survives private transcript deletion. Recheck source-bound evidence before acceptance; settlement grants neither success nor acceptance. Nested reports target their exact parent; workflow/pi-prompt suppression excludes lead-facing evidence and wakes.
177
+
178
+ Journals live under `~/.pi/teams/<team>/completion-groups/`. A sibling `<inbox>.json.durable` marker keeps opted-in inbox writes synchronized; never-grouped inboxes use ordinary atomic writes. Membership binds before admission, run IDs before launch; metadata cannot authorize grouping. Reload retains terminal states, marks lost unadmitted work interrupted, and leaves uncertain ownership unresolved without restarting work, reviving recipients, or releasing claims.
179
+
180
+ Inbox persistence and wake requests have separate receipts. Pi's custom-message call has no admission acknowledgment: a reserved request stays `pending` until exact history is `observed`, not provider success or a power-loss guarantee. Ambiguous wakes are not retried automatically. Use `read_inbox` when warned of an unconfirmed wake. Grouped correlation needs Pi's custom-message/history APIs; ordinary delivery retains its fallback.
181
+
182
+ ### Measured delivery replay
183
+
184
+ One September 8, 2026 controlled replay on Pi 0.85.1, `openai-codex/gpt-5.6-terra`, high thinking, compared two fresh SDK sessions synthesizing ten supplied reports. SSE transport/settings matched; retries and compaction were disabled.
185
+
186
+ | Observation | Immediate/full | All-settled/compact |
187
+ | --- | ---: | ---: |
188
+ | Wake requests | 10 | 1 |
189
+ | Model requests / assistant responses | 11 | 3 |
190
+ | Provider input tokens, excluding cache | 17,796 | 5,149 |
191
+ | Cache-read / cache-write tokens | 17,408 / 0 | 5,120 / 0 |
192
+ | Output tokens | 293 | 237 |
193
+ | Full-report retrievals | 0 | 1 |
194
+ | Elapsed time | 26.239s | 10.748s |
195
+
196
+ Both preserved all ten finding/control pairs, pending acceptance, and the exact F9 detail. Each emitted one `agent_settled`; wake count is not completed-run count. These are provider observations from one fixed full-then-compact replay, not randomized statistics, new investigations, or a general speed guarantee. The [measurement record](grouped-report-measurement.json) contains the corpus, assignments, source identity, method, and limits without histories or credentials.
197
+
198
+ ## Optional specialist continuation
199
+
200
+ ```text
201
+ spawn_agent({
202
+ name: "auth-review",
203
+ model_slot: "read-review",
204
+ prompt: "Review auth and config. Report stable finding IDs, evidence and inspected source references.",
205
+ checkpoint: { inputs: ["auth", "config"], retentionDays: 30 }
206
+ })
207
+ ```
208
+
209
+ Checkpoints preserve assignment, scoped source observations, author/run/tier, findings, questions, `inspectedEvidence`, lead-supplied `decisions`, and independent report references. They retain the original report plus bounded recent history, limited to 64 KiB under `~/.pi/agent/checkpoints/`, outside private transcripts and `/resume`. Ordinary spawning is unchanged when omitted. Swarm defaults/agents accept `checkpoint`; `continue_from` belongs on individual agents. Metadata and nested helpers cannot enable either.
210
+
211
+ ```text
212
+ spawn_agent({
213
+ name: "auth-followup",
214
+ model_slot: "read-review",
215
+ continue_from: "checkpoint:<saved hash>",
216
+ prompt: "Recheck F1 and F2 after the tenant fix. Revalidate token-policy dependencies, including unchanged callers."
217
+ })
218
+ ```
219
+
220
+ Use the exact saved ID. The name becomes a prefix for a fresh recipient/run/SDK session. Current cwd, prompt, tier, instructions, permissions, checks, and repair govern. Continuation does not reopen a mailbox/transcript, resume a process, transfer claims, or inherit permissions/budgets. Old evidence is historical; writers acquire claims normally.
221
+
222
+ Scope/retention inherit unless overridden by a current `checkpoint`; old decisions are not reauthorized. Inputs are literal repository-contained paths relative to cwd. Actual launch, including queued launch, reloads the checkpoint and compares retained dependency scopes. Changed/uncertain evidence requires revalidation beyond the diff. Unchanged fingerprints prove neither findings nor dependency graphs; ignored/external inputs and restored edits remain outside coverage.
223
+
224
+ Full reports synchronize independently before publication/cleanup. Missing provenance or uncertain publication blocks destructive cleanup. In-process admission supports continuation; legacy terminal startup/queues reject it, though existing producers can preserve checkpoint-bound reports. Trusted requests use `continueFrom`; custom starters own admission/execution.
225
+
226
+ Retention defaults to 30 days (1 to 365). Lead-only `/agents-checkpoints list` and `/agents-checkpoints delete <checkpoint ID>` manage records. Startup retires expired records and reports corruption without discarding healthy siblings. Missing/incompatible/corrupt/deleted/expired selections fail visibly. Deletion permanently prevents continuation/replay, not independent history or already-delivered context.
227
+
228
+ ### Measured follow-up
229
+
230
+ One September 8, 2026 pair on Pi 0.85.1 and `openai-codex/gpt-5.6-terra`, high thinking, compared fresh then checkpoint follow-ups with identical source/task/tools. The original scripted investigation's SDK session and private transcript were removed first. Both correctly classified fixed tenant isolation, broken expiration, and unsigned-token acceptance reopened through a changed dependency.
231
+
232
+ | Observation | Fresh | Checkpoint |
233
+ | --- | ---: | ---: |
234
+ | Model / HTTP requests | 3 / 3 | 3 / 3 |
235
+ | Provider input tokens, excluding cache | 1,841 | 3,789 |
236
+ | Cache-read / cache-write tokens | 0 / 0 | 1,536 / 0 |
237
+ | Output tokens | 267 | 233 |
238
+ | File reads / unchanged-file rereads | 3 / 1 | 3 / 1 |
239
+ | First useful persisted result | 8.682s | 8.344s |
240
+ | Elapsed through final response | 10.296s | 10.156s |
241
+
242
+ No read or input-token savings appeared: input including cache was 1,841 versus 5,325. One fixed-order pair cannot establish speed improvement. Each emitted one `agent_settled`; acceptance stayed pending. Real SDK/checkpoint APIs were exercised, not production admission-to-teardown or process restart. The pair predates replay, missing-report cleanup, and native cancellation fixes. The [public record](continuation-measurement.json) contains corpus, assignments, historical source, results, and limits; scripted usage remains null.
243
+
244
+ ## Programmatic event launch
245
+
246
+ Another loaded extension can request an agent from the lead session. Register a response listener correlated by `requestId` before emitting:
247
+
248
+ ```ts
249
+ pi.events.emit("pi-extended-teams:orchestration-request", {
250
+ requestId,
251
+ type: "spawn_agent",
252
+ ctx, // pass the current Pi command context when needed
253
+ params: {
254
+ name: "implementation",
255
+ prompt: "Implement the claimed change and report the evidence.",
256
+ cwd,
257
+ model_slot: "write-critical",
258
+ allow_nested_read_agents: true,
259
+ metadata: { operationId },
260
+ },
261
+ });
262
+ ```
263
+
264
+ The correlated response is `{ requestId, type, ok: true, details, content }` or `{ requestId, type, ok: false, error }`. `prompt` is a direct string; it may reference a packaged prompt file, but there is no `prompt_file` API. Normal tier/capacity/lifecycle rules and the extension allowlist apply. This is a lead-session event-bus integration, not external RPC; teammate sessions cannot satisfy requests.
265
+
266
+ ## Security and data access
267
+
268
+ Read-only roles are behavioral instructions, not sandboxes. Current in-process sessions include base edit/write tools; selected extensions can add capabilities too. Agents run with your system permissions. File claims coordinate cooperative writers, not filesystem access control. Review project instructions and configuration through Pi's normal trust flow.
269
+
270
+ Read [SECURITY.md](../SECURITY.md) for private vulnerability reporting and [access.md](access.md) for access disclosures covering subprocesses, files, extensions, hooks, and networking.
@@ -28,7 +28,7 @@ export interface AgentFollowTranscriptOptions {
28
28
 
29
29
  type TranscriptBlock =
30
30
  | { kind: "section"; label: "user" | "thinking" | "assistant"; text: string }
31
- | { kind: "tool"; id?: string; name: string; args: unknown; result?: string; details?: unknown; isError?: boolean };
31
+ | { kind: "tool"; id?: string; name: string; args: unknown; result?: string; readSummary?: string; details?: unknown; isError?: boolean };
32
32
 
33
33
  function stringifyToolArgs(args: unknown): string {
34
34
  if (args === undefined) return "";
@@ -42,6 +42,7 @@ function stringifyToolArgs(args: unknown): string {
42
42
  function compactToolArgs(name: string, args: unknown): string {
43
43
  if (!args || typeof args !== "object") return sanitizeTuiLine(stringifyToolArgs(args));
44
44
  const values = args as Record<string, unknown>;
45
+ if (name === "ls") return compactTranscriptLine(String(values.path ?? "."));
45
46
  const primary = name === "bash"
46
47
  ? values.command
47
48
  : name === "read"
@@ -226,6 +227,14 @@ function renderToolBlock(theme: ExtendedTeamsTheme, block: Extract<TranscriptBlo
226
227
  if (compactBlock) return compactBlock;
227
228
 
228
229
  const header = renderToolHeader(theme, block);
230
+ if (!expandLargeToolResults && (block.name === "read" || block.name === "bash" || block.name === "ls")) {
231
+ const state = block.result === undefined
232
+ ? pendingText(theme, "working")
233
+ : block.isError ? failureText(theme, "✗") : successText(theme, "✓");
234
+ const summary = block.name === "read" && !block.isError && block.readSummary
235
+ ? mutedText(theme, ` · ${block.readSummary}`) : "";
236
+ return [boundTranscriptLine(`${header}${summary}${mutedText(theme, " · ")}${state}`, width)];
237
+ }
229
238
  if (block.result === undefined) {
230
239
  return [header, `${structuralText(theme, "│")} ${pendingText(theme, "waiting for result…")}`, `${structuralText(theme, "╰─")} ${pendingText(theme, "running")}`, ""];
231
240
  }
@@ -290,28 +299,40 @@ export function formatAgentFollowTranscript(messages: any[], options: AgentFollo
290
299
  const name = sanitizeTuiLine(String(message.toolName || "tool"));
291
300
  const matchingTool = (id ? toolsById.get(id) : undefined)
292
301
  ?? blocks.slice().reverse().find((block): block is Extract<TranscriptBlock, { kind: "tool" }> => block.kind === "tool" && block.result === undefined && block.name === name);
302
+ let readSummary: string | undefined;
303
+ if ((matchingTool?.name ?? name) === "read") {
304
+ const text = typeof message.content === "string" ? message.content
305
+ : (Array.isArray(message.content) ? message.content : [])
306
+ .filter((part: any) => part?.type === "text" && typeof part.text === "string")
307
+ .map((part: any) => part.text).join("\n");
308
+ const lineCount = text ? text.replace(/\r\n?/g, "\n").replace(/\n$/, "").split("\n").length : 0;
309
+ readSummary = `${lineCount} line${lineCount === 1 ? "" : "s"} · ${formatResultSize(text)}`;
310
+ }
293
311
  const result = sanitizeTuiText(extractTextParts(message.content));
294
312
  const isError = typeof message.isError === "boolean" ? message.isError : undefined;
295
313
  if (matchingTool) {
296
314
  matchingTool.result = result;
315
+ matchingTool.readSummary = readSummary;
297
316
  matchingTool.details = message.details;
298
317
  matchingTool.isError = isError;
299
318
  } else {
300
- blocks.push({ kind: "tool", id, name, args: undefined, result, details: message.details, isError });
319
+ blocks.push({ kind: "tool", id, name, args: undefined, result, readSummary, details: message.details, isError });
301
320
  }
302
321
  }
303
322
  }
304
323
 
305
- const lines = blocks.flatMap(block => {
324
+ const lines: string[] = [];
325
+ for (const block of blocks) {
306
326
  if (block.kind === "tool") {
307
- return renderToolBlock(theme, block, options.expandLargeToolResults === true, options.width);
327
+ lines.push(...renderToolBlock(theme, block, options.expandLargeToolResults === true, options.width));
328
+ } else if (block.label === "thinking") {
329
+ if (lines.length > 0 && lines[lines.length - 1] !== "") lines.push("");
330
+ lines.push(theme.fg("thinkingText", block.label), block.text.replace(/\*\*/g, ""), "");
331
+ } else {
332
+ const labelToken = block.label === "user" ? "customMessageLabel" : "accent";
333
+ lines.push(theme.fg(labelToken, block.label), block.text, "");
308
334
  }
309
- if (block.label === "thinking") {
310
- return [theme.fg("thinkingText", block.label), block.text.replace(/\*\*/g, ""), ""];
311
- }
312
- const labelToken = block.label === "user" ? "customMessageLabel" : "accent";
313
- return [theme.fg(labelToken, block.label), block.text, ""];
314
- });
335
+ }
315
336
  return lines.length > 0 ? lines : [theme.fg("dim", "Waiting for the agent's first transcript event…")];
316
337
  }
317
338
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-extended-teams",
3
- "version": "2.3.1",
3
+ "version": "2.3.3",
4
4
  "description": "Control-first, session-connected subagents for Pi with live navigation and intent-tier routing",
5
5
  "repository": {
6
6
  "type": "git",
@@ -28,7 +28,7 @@
28
28
  "scripts": {
29
29
  "typecheck": "tsc --noEmit",
30
30
  "test": "vitest run",
31
- "test:focused": "vitest run src/utils/claims.test.ts src/utils/tasks.test.ts src/utils/model-resolution.test.ts src/utils/settings.test.ts src/utils/write-queue.test.ts src/utils/shared-memory.test.ts extensions/index.test.ts extensions/events/register-events.test.ts extensions/internal/session-files.test.ts extensions/team/contracts.test.ts extensions/tools/delegation-guard.test.ts extensions/tools/agent-communication-tools.test.ts extensions/tools/read-helper.test.ts extensions/agents/read-agent.test.ts extensions/agents/write-agent.test.ts extensions/tools/team-tools.read-agent.test.ts extensions/ui/agent-follow-view.test.ts extensions/tools/coordination-tools.test.ts",
31
+ "test:focused": "vitest run --maxWorkers=2 src/utils/claims.test.ts src/utils/tasks.test.ts src/utils/model-resolution.test.ts src/utils/settings.test.ts src/utils/write-queue.test.ts src/utils/shared-memory.test.ts extensions/index.test.ts extensions/events/register-events.test.ts extensions/internal/session-files.test.ts extensions/team/contracts.test.ts extensions/tools/delegation-guard.test.ts extensions/tools/agent-communication-tools.test.ts extensions/tools/read-helper.test.ts extensions/agents/read-agent.test.ts extensions/agents/write-agent.test.ts extensions/tools/team-tools.read-agent.test.ts extensions/ui/agent-follow-view.test.ts extensions/tools/coordination-tools.test.ts",
32
32
  "build": "tsc --noEmit"
33
33
  },
34
34
  "main": "extensions/index.ts",
@@ -52,7 +52,9 @@
52
52
  "README.md",
53
53
  "LICENSE",
54
54
  "SECURITY.md",
55
- "docs/access.md"
55
+ "docs/access.md",
56
+ "docs/reference.md",
57
+ "assets/pi-extended-teams-demo.gif"
56
58
  ],
57
59
  "dependencies": {
58
60
  "uuid": "^11.1.0"