pi-squire 0.20.1 → 0.20.2

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/CHANGELOG.md CHANGED
@@ -6,6 +6,103 @@ follows [Semantic Versioning](https://semver.org/).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.20.2] - 2026-11-04
10
+
11
+ ### Removed
12
+
13
+ - The `/delegates` panel and its alt+shift+d shortcut are removed. Manage open
14
+ delegates in the compact widget, use `/delegate-open` for switch or peek,
15
+ `/delegate` for new tasks, and `/delegate-resume` for follow-ups. Panel-only
16
+ tests are deleted; remaining navigation, close, and resume tests now drive
17
+ those public entry points. README and older panel descriptions are removed.
18
+
19
+ ### Changed
20
+
21
+ - Running delegate widget rows now show a fixed `working...` secondary line,
22
+ independent of live activity telemetry; finished rows show no secondary line.
23
+ Updated behavior assertions in `test/widget-activity.test.ts`,
24
+ `test/widget-activity-navigation.test.ts`, `test/widget-activity-runtime.test.ts`,
25
+ `test/widget-ancestors.test.ts`, and `test/widget-nesting-final.test.ts` to expect
26
+ the fixed indicator while retaining separate live-reader checks.
27
+ - Trusted Pi sessions in this checkout allow the exact `pnpm lint`,
28
+ `pnpm typecheck`, `pnpm test`, and `pnpm check` commands without a permission
29
+ dialog or auto-mode judge call.
30
+ - Idle compact widgets use one server-wide pane listing per refresh instead of
31
+ inspecting each delegate pane. Sessions publish their pane locator once at
32
+ startup, and activity reads use `kill(pid, 0)` without spawning `ps`.
33
+ Breadcrumbs refresh on Results changes or every 30 seconds, and widget tree
34
+ reads no longer wait for the writer lock. Enter and peek still verify the
35
+ owner and the current pane at action time, including after window renames,
36
+ moves, joins, or breaks.
37
+ Deliberate test changes:
38
+ - `test/widget-activity-runtime.test.ts` replaces "locator ticks keep observing
39
+ without unchanged rewrites, publish rename/move/clear and reset per
40
+ session/generation" with "locator publishes once per session generation and
41
+ idle ticks spawn no pane probes". Idle ticks leave the startup snapshot alone.
42
+ - `test/widget-live.test.ts` replaces "pid reuse, unknown probe,
43
+ malformed/oversized/generation-mismatched files fail closed" with "live pid
44
+ ignores legacy start token; unknown probe and
45
+ malformed/oversized/generation-mismatched files fail closed". A live PID's
46
+ obsolete start token no longer removes its snapshot. "startup probe failure
47
+ is unavailable; early stop cancels delayed initialization" becomes "stop
48
+ before flush cancels publication without process initialization" because
49
+ publishers no longer run a process-start probe.
50
+ - `test/widget-ancestor-process.test.ts` replaces "actual processes: root
51
+ without launch/registry publishes, leaf switches directly, current pane
52
+ names/moves and server mismatches fail closed" with "actual processes:
53
+ startup pane locator follows names/moves at navigation time and server
54
+ mismatches fail closed". Navigation resolves current names and windows from
55
+ the stable pane instead of waiting for another publication.
56
+ - `test/widget-ancestor-real.test.ts` updates "real private tmux:
57
+ attached-client root switch, exact pane/server scope, rename and moved-window
58
+ reattachment" to expect an unchanged startup snapshot after rename or break.
59
+ - `test/widget.test.ts` updates "shutdown while a window read is pending cannot
60
+ resurrect a widget" and "cap zero and terminal-only history stop overview
61
+ tmux reads" to observe pane listings instead of window listings.
62
+ - `test/widget-current.test.ts` updates "current child lookup does zero
63
+ locator/inspect work for unavailable/empty windows and no current candidates"
64
+ and "cap0 and no-candidate Overview refreshes never inspect/locate children
65
+ independently of the publisher" to use the shared pane listing.
66
+ - Child compact widgets replace ancestor rows and the `Delegates` header with one
67
+ breadcrumb ending in `(you)`. Enter on it switches to the direct parent; x
68
+ refuses close, and Left and Right do nothing. Children use the base indent,
69
+ and the two-column selection gutter stays fixed. Root widgets keep their
70
+ `Delegates` header. Names omit their own nonempty agent prefix, and transcript
71
+ ages say `active` instead of `file`. Deliberate frame and navigation expectation
72
+ changes are in `test/widget-ancestors.test.ts`, `test/widget.test.ts`,
73
+ `test/widget-data.test.ts`, `test/widget-navigation.test.ts`,
74
+ `test/widget-activity-navigation.test.ts`, `test/widget-nesting06.test.ts`, and
75
+ `test/widget-nesting-final.test.ts`.
76
+ - The compact widget keeps its two-column selection gutter while unfocused, so
77
+ focusing the list no longer shifts the tree right. `test/widget-ancestors.test.ts`
78
+ and `test/widget.test.ts` now expect the indented unfocused rows; the first and checks that focusing keeps every
79
+ row in its column.
80
+ - `delegation_close` records the close without posting a cancellation message or
81
+ waking the model. UI closes still wake the model. The tool close regression in
82
+ `test/tools.test.ts` now expects silence, and the stopped-root cancellation test
83
+ in `test/subtree-close.test.ts` uses the UI close path to retain its wake check.
84
+ - Browse open delegate descendants in the compact widget with Right to expand
85
+ or enter a branch and Left to collapse or return to its parent. Right does
86
+ nothing on a childless row, Left on any nested row returns to its parent, and
87
+ ancestors ignore both. A collapsed row shows its open-descendant
88
+ count as +N instead of a task-count secondary line. Leaving the list collapses
89
+ all branches. Enter and confirmed x work at every depth. Widget tests now pin
90
+ collapsed counts, tree keyboard behavior, and mixed-depth overflow wording;
91
+ obsolete task-summary tests are removed.
92
+ - Press x in the focused compact widget to close the selected subtree. The widget
93
+ always asks for confirmation, including finished delegates, in plainer words
94
+ ("Close <name> and its delegates? Worktrees and branches stay."); the close
95
+ confirmation tests in `test/navigator-current.test.ts`, `test/widget-navigation.test.ts`
96
+ and `test/widget-nesting-final.test.ts` expect them. Ancestor rows
97
+ refuse close and omit x from their hint. New keyboard tests cover cancellation,
98
+ finished and running closes, and ancestor refusal.
99
+ - Enter in the focused compact delegate widget switches straight to the selected
100
+ delegate's verified tmux window. A dim hint explains how to focus the list;
101
+ focused hints show the selected row's keys. Widget navigation and rendering
102
+ tests now expect direct switching instead of the details panel. Ancestor and
103
+ activity layout tests include the new hint; the nested widget test replaces
104
+ removed branch-detail browsing with a direct switch assertion.
105
+
9
106
  ## [0.20.1] - 2026-11-02
10
107
 
11
108
  ### Changed
@@ -29,8 +126,8 @@ follows [Semantic Versioning](https://semver.org/).
29
126
  test increases from 10,000 to 12,000 characters to cover the fifth tool.
30
127
  Managed forks report their cwd, branch, base and uncopied changes, and their
31
128
  prompt directs them away from the original checkout; non-isolated forks warn
32
- about sharing a folder with a running source. Dashboard details show the
33
- source id, foreign callers get an explicit direct-parent refusal, and the
129
+ about sharing a folder with a running source. Foreign callers get an explicit
130
+ direct-parent refusal, and the
34
131
  fork tool declares its destructive-operation hint.
35
132
 
36
133
  ## [0.19.1] - 2026-11-02
@@ -49,10 +146,10 @@ follows [Semantic Versioning](https://semver.org/).
49
146
  ### Changed
50
147
 
51
148
  - **Breaking:** Pi 1.5.0 or later is now required. Delegate result expand hints use Pi's
52
- configured keybinding, and the inline delegate dashboard and new-delegate
53
- settings form report that Pi is waiting for a choice. The render tests now
149
+ configured keybinding, and the new-delegate settings form reports that Pi is
150
+ waiting for a choice. The render tests now
54
151
  require the configured key in the hint instead of accepting a missing key;
55
- dashboard and form tests pin their blocked-input status. The active-tools
152
+ form tests pin its blocked-input status. The active-tools
56
153
  test fake now preserves retained tools' order, matching Pi 1.5.
57
154
 
58
155
  ## [0.18.4] - 2026-11-02
@@ -157,7 +254,7 @@ follows [Semantic Versioning](https://semver.org/).
157
254
  partial failures return `isError:true` with details rather than discarding
158
255
  successful members in a thrown tmux error. Close requires a readable shared
159
256
  fence before kills. Old single-window wording/schema, direct-close-on-corrupt-
160
- registry, panel/poll/placement text assertions deliberately change; local
257
+ registry, poll and placement text assertions deliberately change; local
161
258
  genuine result publication remains warning-only. Unknown/foreign/obsolete
162
259
  target ids refuse before effects. Canceling unfinished children now requires
163
260
  direct-parent processing rather than silently releasing the task barrier.
@@ -185,44 +282,17 @@ follows [Semantic Versioning](https://semver.org/).
185
282
 
186
283
  ### Changed
187
284
 
188
- - Complete branch-focused widget entry in the same dashboard: initial details
189
- retain their Escape-to-compact-list behavior, while `b` opens only the selected
190
- branch's descendant/resume history and worker details return to that list.
191
- Overall `/delegates` stays scoped to the invoking session's whole subtree.
192
- Root close-all remains explicitly all root subtrees, not only displayed rows.
193
- - Dashboard switch/peek and `/delegate-open` now reuse positively verified
285
+ - `/delegate-open` now reuses positively verified
194
286
  current pane/server/owner locators for reattached latest sessions, without
195
287
  rewriting historical launch/result facts or changing close authority.
196
288
  A lost or replaced current locator never falls back to an old still-open
197
- window; peek captures the exact verified Pi pane. Details distinguish launch
198
- and current windows and reflect native session titles and actual outcomes.
289
+ window; peek captures the exact verified Pi pane.
199
290
  Verified live latest rows remain navigable even before historical disappearance
200
291
  is polled. Closing live navigation rows confirms the separate durable control
201
292
  scope; telemetry never retargets a kill, and reattached windows may remain open.
202
293
  Post-switch ownership loss reports the completed switch honestly.
203
- Add `test/navigator-current.test.ts`, extend `test/dashboard.test.ts` and
204
- `test/widget-nesting-final.test.ts` for deliberate branch-list behavior,
205
- current-window races, title composition and direct-parent resume refusal.
206
- - Compose the shared widget/dashboard actions with context-aware subtree close:
207
- selected close reports aggregate partial errors, and the root retains confirmed
208
- `a` close-all from the same dashboard, including empty/history views. Keep
209
- direct-widget activity/focus and direct-parent resume checks unchanged; no
210
- second panel or row-by-row close authority. Add combined coverage in
211
- `test/widget-nesting-final.test.ts` and root action intent coverage in
212
- `test/dashboard.test.ts`; extend `test/dashboard-actions.test.ts` control stubs.
213
- - Make the direct-delegate widget keyboard-navigable and reuse one dashboard for
214
- widget Enter, `/delegates` and its shortcut. Down at an empty built-in prompt
215
- selects children; stable selection scrolls through the cap. Enter opens details,
216
- and Escape returns to list then prompt. Dashboard list Enter now opens details
217
- before a second Enter switches (a deliberate navigation change); peek, close,
218
- new and authorized resume remain behind existing action/ownership checks.
219
- Custom editors, autocomplete, dialogs and unknown focus pass through unchanged.
220
- The isolated Pi-internals adapter was tested with installed Pi 1.4.0 in both
221
- regular and fullscreen modes; no Pi change or editor/footer replacement.
222
- Protect the empty prompt while a widget-opened dashboard is loading or
223
- re-listing between actions, without intercepting real dashboard/dialog input.
224
- Update `test/navigator.test.ts` for the deliberate two-Enter details/switch
225
- flow and `test/tree-restore.test.ts` to inspect metadata in details.
294
+ Add `test/navigator-current.test.ts` for current-window races and extend
295
+ `test/widget-nesting-final.test.ts` for direct-parent resume refusal.
226
296
  - The interactive direct-delegate overview deliberately replaces only Squire’s
227
297
  running-count entry when its cap is positive, preserving custom footers/editors
228
298
  and the own-delegate badge. Cap zero and non-TUI hosts retain the running count.
@@ -277,7 +347,7 @@ follows [Semantic Versioning](https://semver.org/).
277
347
  Consumers can observe ordinary reopen and runtime replacement without
278
348
  treating launch environment variables as identity authority.
279
349
 
280
- - Explicit ancestor-scoped subtree close and root-only confirmed panel close-all.
350
+ - Explicit ancestor-scoped subtree close.
281
351
  Shared admission/own-entry dispatch fences precede effects, including root
282
352
  reservations. Already-dispatched unknown creates remain charged/fenced and
283
353
  partial; bounded explicit retries never guess no-start. Current verified
@@ -408,12 +478,6 @@ follows [Semantic Versioning](https://semver.org/).
408
478
  retaining root/depth, live-session/obsolete-chain protections and current
409
479
  grants, caps, tool ceiling and trust resolver. Fork/clone copies are history,
410
480
  not authority; inherited launch environment no longer assigns identity.
411
- - Deliberately change the delegates panel to retain hierarchical history and
412
- details rather than only open windows; only verified windows support
413
- navigation. Descendant close stays with the separate explicit-close slice.
414
- Reattachment tests now reopen the same id after shutdown rather than copying
415
- starts into a fresh/live duplicate session. Root outcomes retain processing
416
- durability with a non-displaying recovery wake instead of a repeated final.
417
481
 
418
482
  - Keep durable local result/gone delivery, coordinator wakes and close tracking
419
483
  working when shared fact publication fails; warn and reconcile those saved
@@ -523,7 +587,7 @@ follows [Semantic Versioning](https://semver.org/).
523
587
  each resolving to one model; a `*` pattern makes the file invalid, so the
524
588
  agent is disabled. A body may be empty.
525
589
  - New agent fields: `display_name` (shown on the delegate card, in
526
- `/delegates` and in the window title; it may hold only ASCII letters,
590
+ the compact widget and in the window title; it may hold only ASCII letters,
527
591
  digits, `-` and `_`, and any other value, a space, `#`, `.`, a non-ASCII
528
592
  letter or an empty value among them, makes the file invalid, so the agent is
529
593
  disabled), `enabled: false` (leaves the agent
@@ -575,21 +639,18 @@ follows [Semantic Versioning](https://semver.org/).
575
639
 
576
640
  ### Removed
577
641
 
578
- - The delegate popup: `enter` in `/delegates` and `/delegate-open --popup` no
579
- longer open a tmux popup, and the popup title from 0.13.1 (the close key in
642
+ - `/delegate-open --popup` no longer opens a tmux popup, and the popup title from 0.13.1 (the close key in
580
643
  its title) goes with it. `--popup` is now an unknown-flag usage error. The
581
644
  poll runs again only while a delegation is running. The close hint was hard to
582
645
  see in some themes, and a switch covers the need.
583
646
 
584
647
  ### Changed
585
648
 
586
- - `enter` in the `/delegates` panel, and in its peek, now switches your tmux
587
- client to the delegate's window (the notice says your tmux last-session key returns you); `/delegate-open
588
- <id>` with no flag switches too. The `s` key is gone. With no client attached,
649
+ - `/delegate-open <id>` with no flag switches your tmux client to the delegate's
650
+ window. The switch notice says your tmux last-session key returns you. The `s` key is gone. With no client attached,
589
651
  switch still refuses; peek and close still work. tmux 3.2 stays the minimum,
590
652
  for `new-session -e`.
591
- - Tests changed with it: in `test/navigator.test.ts` the panel hint, `enter`,
592
- peek, no-client, failure, `/delegate-open` parsing, default and completion
653
+ - Tests changed with it: in `test/navigator.test.ts` peek, no-client, failure, `/delegate-open` parsing, default and completion
593
654
  tests now expect a switch, and the popup lifecycle tests are replaced by one
594
655
  test that the poll runs only while a delegation does; `test/tmux.test.ts` no
595
656
  longer tests `popup` and `closePopup`, and `test/popup-parent.ts` and the
@@ -618,14 +679,6 @@ follows [Semantic Versioning](https://semver.org/).
618
679
 
619
680
  ### Added
620
681
 
621
- - `/delegates`, also on `alt+shift+d`, opens a panel of the delegations whose
622
- window is open (newest first): `enter` opens one in a tmux popup, or switches
623
- to it when it is in your own session; `p` peeks at its pane in an overlay (`r` refreshes,
624
- `enter` opens); `s` switches your client to it; `x` closes it, asking only
625
- while it runs; `n` opens the new-delegate form. `/delegate-open <id> [--popup|--switch|--peek]` does one of
626
- these directly. Popup and switch act on the most recently active client of the
627
- parent's session; the parent closes a popup once its delegate's window is gone.
628
- Commands and a shortcut only: the model gets no new tool.
629
682
  - `/delegate` with no arguments opens a new-delegate form: pick an agent, write
630
683
  the task, name it, then a settings screen for model, thinking level (only the
631
684
  levels the model supports, clamped, visibly, when the agent's default or a new model does not support it), auto-exit,
@@ -1121,7 +1174,8 @@ author's dotfiles; the changes below are against that copy.
1121
1174
 
1122
1175
  - The published file list includes `child.ts`, which `index.ts` imports.
1123
1176
 
1124
- [Unreleased]: https://github.com/gvanderclay/pi-squire/compare/v0.20.1...HEAD
1177
+ [Unreleased]: https://github.com/gvanderclay/pi-squire/compare/v0.20.2...HEAD
1178
+ [0.20.2]: https://github.com/gvanderclay/pi-squire/compare/v0.20.1...v0.20.2
1125
1179
  [0.20.1]: https://github.com/gvanderclay/pi-squire/compare/v0.20.0...v0.20.1
1126
1180
  [0.20.0]: https://github.com/gvanderclay/pi-squire/compare/v0.19.1...v0.20.0
1127
1181
  [0.19.1]: https://github.com/gvanderclay/pi-squire/compare/v0.19.0...v0.19.1
package/README.md CHANGED
@@ -327,7 +327,7 @@ Fresh sessions neither adopt nor report earlier trees. Each session sees only
327
327
  its own tree; to collect the delegates of a session you closed, reopen that
328
328
  exact session, which restores its full tree.
329
329
 
330
- Both `delegation_status` and `/delegates` show descendants: a root sees its tree;
330
+ Both `delegation_status` and the compact widget show descendants: a root sees its tree;
331
331
  a coordinator sees only its own subtree, not siblings or unrelated roots.
332
332
  Hierarchy uses stable Pi session ids, not the new delegation id of a resume.
333
333
  Parent/root/depth, launch/result/session paths, workspaces, current verified
@@ -460,20 +460,15 @@ transcript-file age appear when space permits: model is
460
460
  dropped first, then file age, before identity/state are compressed. At very
461
461
  narrow widths the state glyph remains beside the truncated identity.
462
462
  `file … ago` is only a last-active hint from transcript mtime, not live tool
463
- activity. When available, a second line shows factual live activity (below).
464
- Each coordinator row summarizes **all descendant tasks**, at every depth,
465
- including tasks whose windows have exited. Counts are per delegation/launch id,
466
- not per stable session: a failed task and its resumed successor both count, so
467
- a retry cannot erase a known failure. Actual replies supply done/failed/stopped;
468
- saved gone/closed-without-result tasks count as missing. Shared registry
469
- finished/closed/closing flags are not successful replies or proof another
470
- parent processed an outcome. Missing parent facts or tree coverage are labeled
471
- unknown/partial/unavailable, never all done. Summary and activity share one
472
- secondary line; when both do not fit, the task summary wins.
463
+ activity. Each running row has a second line showing `working...`, regardless
464
+ of live telemetry; finished rows have no second line.
465
+ A collapsed delegate with open descendants shows **+N** at the end of its row.
466
+ This counts open stable sessions, not historical attempts or results.
473
467
 
474
468
  Delegates also see their ancestors vertically, root to direct parent, with the
475
469
  direct parent marked `(parent)` (including `root (parent)`). A connected
476
- **Delegates** branch contains only the current session's direct children.
470
+ **Delegates** branch starts with the current session's direct children and
471
+ expands to show their open descendants.
477
472
  There is no current-session row or empty child heading; leaves show ancestors
478
473
  only. Ancestor rows and secondary lines do not consume child-entry slots.
479
474
 
@@ -489,8 +484,8 @@ Configure it in the existing `<agent dir>/squire/settings.json`, alongside
489
484
 
490
485
  - `delegateWidgetPlacement`: `above` (default) or `below` the editor.
491
486
  - `delegateWidgetMaxEntries`: nonnegative safe integer, default **3**. Each
492
- direct child consumes one slot. `+N more direct delegates` counts hidden
493
- eligible direct children, not descendants. **0** hides child rows and restores
487
+ visible delegate consumes one slot, at any expanded depth. `+N more delegates`
488
+ counts eligible rows beyond the viewport. **0** hides child rows and restores
494
489
  Squire's running-count footer while preserving ancestor rows/navigation;
495
490
  zero children never produce an empty heading.
496
491
  - These preferences apply equally to roots and coordinators. Interactive views
@@ -498,8 +493,8 @@ Configure it in the existing `<agent dir>/squire/settings.json`, alongside
498
493
  distinct error and use the defaults without changing task state.
499
494
 
500
495
  Launch/result/close changes refresh promptly; an independent one-second observer
501
- keeps finished-open rows, window eligibility and later native title changes
502
- fresh even when the result poll has stopped. Only visible rows resolve titles and
496
+ keeps finished-open rows, descendant membership, window eligibility, and later
497
+ native title changes fresh even when the result poll has stopped. Only visible rows resolve titles and
503
498
  file metadata and live activity; overflow counts still include every eligible child. Closed/gone-only
504
499
  history without a live reattached session does not keep the observer listing
505
500
  windows. A positively reopened gone coordinator may appear at its current window
@@ -517,9 +512,9 @@ over that mirror: an external picker rename may differ temporarily from the
517
512
  child's own in-memory name. Files are read incrementally, with bounded work per
518
513
  refresh; very large existing transcripts may take several refreshes to catch up.
519
514
 
520
- ### Factual live activity
515
+ ### Live activity telemetry
521
516
 
522
- The secondary line follows actual Pi tool-execution events: `reading…`,
517
+ The internal feed follows actual Pi tool-execution events: `reading…`,
523
518
  `editing…`, `writing…`, `command call…`, or `using <tool name>…`. Parallel
524
519
  and nested calls are tracked by their actual call ids, not by tool name.
525
520
  Active nested calls take precedence over their orchestrator. A tool start is
@@ -528,9 +523,9 @@ call, not proof that a subprocess started or permission was granted. Squire
528
523
  does not inspect commands to guess intent, or display arguments, paths, tool
529
524
  results, thinking or provider payloads.
530
525
 
531
- Otherwise, while an assistant response streams, `response: …` shows a literal
532
- single-line excerpt bounded to 512 UTF-8 bytes. It clears when that message
533
- ends; a quick response may finish between refreshes and never appear. Calls
526
+ Otherwise, while an assistant response streams, the feed holds a literal
527
+ single-line excerpt bounded to 512 UTF-8 bytes. These details are not shown in
528
+ the widget. The excerpt clears when that message ends. Calls
534
529
  clear on matching end, run end/settlement, stop, reload and shutdown. Known
535
530
  task results/close suppress activity even if a delegate's last snapshot remains.
536
531
  A settled or silent coordinator can still own unfinished child tasks: activity
@@ -549,34 +544,36 @@ calls. Publication requires positive Squire ownership at startup; later factual
549
544
  end/settlement observation continues even if task-owner processing fails or its
550
545
  record becomes unreadable, without re-enabling actions. Event publishing works
551
546
  in non-TUI delegates and with the list hidden.
552
- One child-entry slot may occupy two physical lines; there is no empty secondary
553
- line or tool-use counter.
547
+ One running child-entry slot occupies two physical lines; there is no empty
548
+ secondary line or tool-use counter.
554
549
 
555
550
  ### Navigation
556
551
 
557
552
  At an **empty built-in prompt**, press **Down** to select the direct parent in a
558
553
  delegate session, or the first child at root. Up/Down traverse ancestors and
559
- eligible children in display order; only children scroll within the configured cap;
560
- hidden-above/below counts refer to direct children. Selection follows stable
561
- session identity through renames, reordering and resumes. Enter opens that
562
- child's details in the **same dashboard** as /delegates, scoped to that child's
563
- branch (including descendant and resume history, not its siblings). Press **b**
564
- for the branch list to select and inspect its workers. Initial details Escape
565
- returns directly to the compact list; details opened from the branch list return
566
- to that branch list first. Branch-list Escape returns to the compact list, then
567
- Escape again returns to the prompt; Up past the first compact row also leaves
568
- the list. A short hint appears only while the list owns these keys.
569
- Typing or any unrelated key leaves list navigation and passes that key through.
570
- While a widget-opened dashboard is loading or re-listing between actions, keys
571
- are absorbed only if the exact empty built-in prompt still owns focus: Escape
572
- cannot abort a run and action letters cannot leak into that prompt. Once a
573
- real dashboard, dialog, completion menu or unknown component owns input, its
574
- keys pass through normally.
575
- Cap zero never creates invisible selectable children; ancestors remain selectable
576
- and /delegates still works.
554
+ open delegates in display order. Only delegate rows scroll within the configured
555
+ cap. Selection follows stable session identity through renames, reordering and
556
+ resumes. Enter switches directly to the selected delegate's verified tmux window.
557
+ Press **x** to close its recorded subtree. Every close asks for confirmation,
558
+ including finished delegates. Ancestors cannot be closed.
559
+
560
+ Right expands a delegate with children. Right again selects its first child.
561
+ Left collapses an expanded delegate; on a collapsed child with children, Left
562
+ selects its parent. Ancestors and childless rows ignore Left and Right.
563
+ Collapsed delegates show **+N** open descendants at the end of their row.
564
+ Esc, typing, or Up past the first row returns focus to the prompt and collapses
565
+ every branch. Typing passes the key through to the prompt.
566
+
567
+ A dim **↓ to manage delegates** hint appears when the widget is not focused.
568
+ Focused hints show the selected row's valid actions, including expand or
569
+ collapse when applicable. Cap zero never creates invisible selectable
570
+ delegates; ancestors remain selectable.
571
+
572
+ Pending actions absorb keys only while the exact empty built-in prompt still
573
+ owns focus. Dialogs, completion menus, and unknown components keep their keys.
577
574
 
578
575
  Enter on an ancestor switches directly to its verified **current live tmux
579
- window**, not to the dashboard or a historical launch window. Root and leaf
576
+ window**, not to a historical launch window. Root and leaf
580
577
  processes publish their own positive pane/window observation in the same
581
578
  disposable generation snapshot used for activity. The reader checks the elected
582
579
  exact-session owner, process incarnation, tmux server socket/PID/start identity,
@@ -602,54 +599,25 @@ It relies on **Pi TUI internals**, isolated in a small compatibility adapter:
602
599
  the concrete focus getter and exact built-in editor identity. Compatibility was
603
600
  tested with the installed **Pi 1.4.0 bundled CLI**, including regular/fullscreen
604
601
  mode changes. Unknown focus/editor/completion capabilities disable key capture
605
- rather than guessing; /delegates remains available. This is not a generic
602
+ rather than guessing; `/delegate-open` remains available. This is not a generic
606
603
  custom-editor integration or a supported Pi focus hook. JSON/RPC hosts retain
607
604
  the running-count status rather than receiving a terminal widget.
608
605
 
609
606
  ## Reaching delegates
610
607
 
611
- Delegate windows sit out of your way, so reach them from the parent. `/delegates`
612
- (or `alt+shift+d`) opens the same dashboard used by widget Enter, at the overall
613
- view of its descendant hierarchy, including
614
- closed/history rows. Parents precede their children; resume history stays
615
- visible. Each row shows stable launch identity, the available current native Pi
616
- title, agent display label, semantic state/outcome and verified window availability.
617
- Enter opens selected details with identities, paths, result envelope, workspace
618
- and resume information. Historical launch windows are labeled separately from
619
- current verified windows. Lists and details scroll within the available screen.
620
- Widget entry uses the same screen for only its selected branch; `b` exposes that
621
- branch's list without widening its scope. A title change never changes routing.
622
- Metadata is refreshed when opening/reopening the screen after an action; the
623
- compact overview remains the live activity/summary view.
624
- Only a verified live window supports switch/peek; the model has no
625
- tool that moves the terminal. Any ancestor can explicitly close a selected
626
- subtree. The root also has a confirmed close-all action; shared companion names
627
- never grant control over another root.
628
-
629
- | Key | Does |
630
- |---|---|
631
- | `↑` / `↓` | select a delegation in the list; scroll in details |
632
- | `enter` | open selected details; from details, switch your tmux client to its verified window |
633
- | `esc` | details → overall list → prompt; initial widget details → compact list; branch-list details → branch list → compact list |
634
- | `b` | widget entry only: show the selected branch list, preserving its target and history |
635
- | `p` | peek: a snapshot of the window's pane (`capture-pane`) in an overlay; `r` refreshes, `enter` switches, `esc` returns to the list |
636
- | `x` | explicitly close the selected subtree as `delegation_close` does; confirms running work and verified live navigation rows |
637
- | `a` | root only: confirm closing **all root** descendant subtrees, including absent coordinators, even when viewing one branch |
638
- | `r` | resume the selected eligible direct child, collecting a follow-up through the existing resume flow; descendants without authority are refused |
639
- | `n` | new child of the invoking session, not of the selected remote row: the same form `/delegate` opens with no arguments (see [First use](#first-use)) |
608
+ Use the compact widget to switch to a delegate or close its subtree.
609
+ Use `/delegate-open <id> [--switch|--peek]` to reach one delegate by id.
610
+ With no flag or with `--switch`, it switches your tmux client to that delegate's
611
+ verified window. `--peek` opens a pane snapshot in an overlay, where `r`
612
+ refreshes, Enter switches, and Esc returns to the prompt. Ids complete from the
613
+ open delegations. The model has no tool that moves your terminal.
640
614
 
641
615
  Switch acts on the most recently active tmux client attached to the parent's
642
616
  session. With none attached it refuses with a notice; peek and close still
643
- work. No tmux key bindings or options are added.
617
+ work. No tmux key bindings or options are added. To return, use your own tmux
618
+ last-session key, which defaults to `prefix L`. The switch notice reminds you.
644
619
 
645
- To come back, use your own tmux last-session key (tmux's default is `prefix L`,
646
- often rebound); the notice after a switch says so.
647
-
648
- `/delegate-open <id> [--switch|--peek]` does one of these on one delegation
649
- without the panel: with no flag or with `--switch`, it switches; `--peek` opens
650
- the peek overlay. Ids complete from the open delegations.
651
-
652
- Dashboard switch/peek and `/delegate-open` share current-locator verification.
620
+ The compact widget and `/delegate-open` share current-locator verification.
653
621
  For the latest known launch of a stable session, a positively observed current
654
622
  runtime supersedes its old launch window; a later lost/changed locator refuses
655
623
  rather than falling back to an old still-open window. Exact Pi pane liveness
@@ -933,7 +901,7 @@ optional, and the [first-use example](#first-use) is a complete agent file:
933
901
  | Field | Meaning |
934
902
  | --- | --- |
935
903
  | `description` | Shown in the roster and the `delegate` tool's description. Defaults to the name. |
936
- | `display_name` | Shown instead of the name on the delegate card, in `/delegates` and in the window title (`<display_name>-<label>`). The agent is still called by its name. It may hold only ASCII letters, digits, `-` and `_`; any other value (a space, `#`, `.`, a non-ASCII letter, or an empty value) makes the file invalid, so the agent is disabled. |
904
+ | `display_name` | Shown instead of the name on the delegate card, in the compact widget and in the window title (`<display_name>-<label>`). The agent is still called by its name. It may hold only ASCII letters, digits, `-` and `_`; any other value (a space, `#`, `.`, a non-ASCII letter, or an empty value) makes the file invalid, so the agent is disabled. |
937
905
  | `model` | One model: `provider/id` or an alias such as `sonnet`, passed to the child's `--model` unchanged, so Pi resolves it to one model. A `*` pattern makes the file invalid. Absent means the parent session's current model. |
938
906
  | `thinking` | `off`, `minimal`, `low`, `medium`, `high`, `xhigh` or `max`. Absent means the parent session's level; an unknown value is dropped with a warning and the parent's level applies. Pi clamps the level to the model. |
939
907
  | `tools` | The delegate's tools (see below): tool names and `$bundle` entries for exactly those, or only `-name` entries for the parent session's current tools less those. Absent means the parent session's current tools; empty (`tools:` or `tools: []`) means no tools except the `delegateTools` setting. MCP tools follow the selection like any other. |
@@ -1250,12 +1218,11 @@ even when no delegation is recorded. The details gain a `marks` array of
1250
1218
 
1251
1219
  ## Explicit subtree close
1252
1220
 
1253
- `delegation_close` and the `/delegates` close actions enumerate persistent
1221
+ `delegation_close` and the compact widget close action enumerate persistent
1254
1222
  records and close the selected session and all its descendants, including work
1255
1223
  whose coordinator is offline. Any ancestor may close; unrelated trees, siblings
1256
- outside the selected subtree and user windows remain untouched. Only the root
1257
- has the panel's `a` close-all action. Close-all fences new root admissions too;
1258
- neither action kills a companion tmux session wholesale.
1224
+ outside the selected subtree and user windows remain untouched. Neither action
1225
+ kills a companion tmux session wholesale.
1259
1226
 
1260
1227
  Admission is fenced under the shared tree lock **before** window effects.
1261
1228
  Already-reserved pre-dispatch launches cannot dispatch; an already-dispatched
@@ -1969,7 +1936,7 @@ contract.
1969
1936
 
1970
1937
  The automated tests drive the extension through fake Pi lifecycles. The
1971
1938
  reusable `test/mail-harness.ts` runs multiple independent extension instances
1972
- with the real, exactly pinned pi-session-mail 0.6.0 over an isolated shared
1939
+ with the real, exactly pinned pi-session-mail 0.7.1 over an isolated shared
1973
1940
  mail root. Protocol tests cover correlation, asks, stops, fallback, pending
1974
1941
  answers, retries and duplicate delivery after the write/completion crash
1975
1942
  window. These are not real model runs or real process-crash tests. They check
@@ -2009,8 +1976,7 @@ Other extensions may rely on:
2009
1976
  - the `/delegate` and `/delegate-resume` syntax and flags, and their
2010
1977
  no-argument forms: `/delegate` opens the new-delegate form and
2011
1978
  `/delegate-resume` the resume picker;
2012
- - the `/delegates` command and its `alt+shift+d` shortcut, and `/delegate-open <id>` with its
2013
- `--switch` and `--peek` flags;
1979
+ - `/delegate-open <id>` with its `--switch` and `--peek` flags;
2014
1980
  - the `[delegate]` result text and the closed-without-a-result text;
2015
1981
  - the agent file's frontmatter keys and its locations,
2016
1982
  `<agent dir>/agents/<name>.md` and, in a trusted project,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-squire",
3
- "version": "0.20.1",
3
+ "version": "0.20.2",
4
4
  "description": "Starts a delegate Pi session in a background tmux window, sends it the task over message:*, and shows the parent its result",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -55,7 +55,7 @@
55
55
  "@earendil-works/pi-coding-agent": "1.5.0",
56
56
  "@earendil-works/pi-tui": "1.5.0",
57
57
  "@types/node": "26.6.5",
58
- "pi-session-mail": "0.6.0",
58
+ "pi-session-mail": "0.7.1",
59
59
  "typebox": "1.4.3",
60
60
  "typescript": "7.0.2"
61
61
  }
package/src/agents.ts CHANGED
@@ -50,7 +50,7 @@ const DISPLAY_NAME = /^[A-Za-z0-9_-]+$/;
50
50
 
51
51
  export type Agent = {
52
52
  name: string;
53
- /** Shown instead of the name on the delegate card, `/delegates` and the window title; from `display_name`, `[A-Za-z0-9_-]+`. */
53
+ /** Shown instead of the name on the delegate card, compact widget and window title; from `display_name`, `[A-Za-z0-9_-]+`. */
54
54
  displayName?: string;
55
55
  description: string;
56
56
  /** Passed to the child's `--model` unchanged; undefined means the parent's model. */
package/src/index.ts CHANGED
@@ -758,10 +758,11 @@ export default function delegate(
758
758
  pi,
759
759
  results,
760
760
  tmux,
761
- async (ctx, sessionId) => {
761
+ async (ctx, id) => {
762
762
  owner.assert();
763
- await navigator.panel(ctx, sessionId);
763
+ await navigator.openDelegate(ctx, id, "switch");
764
764
  },
765
+ (ctx, id) => navigator.closeDelegate(ctx, id),
765
766
  () => owner.assert(),
766
767
  );
767
768
 
@@ -1449,7 +1450,7 @@ export default function delegate(
1449
1450
  }
1450
1451
  }
1451
1452
 
1452
- /** What the new-delegate form needs, shared by `/delegate` and the panel's `n`. */
1453
+ /** What the no-argument `/delegate` form needs. */
1453
1454
  const newDelegateDeps: NewDelegateDeps = {
1454
1455
  unavailable: () => (tmux.insideTmux() ? undefined : NOT_IN_TMUX),
1455
1456
  roster: rosterFor,
@@ -1703,26 +1704,9 @@ export default function delegate(
1703
1704
  handler: resumeCommand,
1704
1705
  });
1705
1706
 
1706
- const navigator = createNavigator(
1707
- viewResults,
1708
- tmux,
1709
- tracking,
1710
- (ctx: ExtensionContext) => startNewDelegate(ctx, newDelegateDeps),
1711
- {
1712
- assertActive: () => owner.assert(),
1713
- close: (id, ctx) => tracking.close(id, ctx),
1714
- resume: (id, ctx) => resumePicker(ctx, id),
1715
- },
1716
- );
1717
-
1718
- pi.registerCommand("delegates", {
1719
- description: "Open the shared delegate dashboard: details, switch, peek, close, resume",
1720
- handler: async (_args: string, ctx: ExtensionContext) => navigator.panel(ctx),
1721
- });
1722
-
1723
- pi.registerShortcut("alt+shift+d", {
1724
- description: "Open the delegates panel",
1725
- handler: (ctx: ExtensionContext) => navigator.panel(ctx),
1707
+ const navigator = createNavigator(viewResults, tmux, tracking, {
1708
+ assertActive: () => owner.assert(),
1709
+ close: (id, ctx) => tracking.close(id, ctx),
1726
1710
  });
1727
1711
 
1728
1712
  pi.registerCommand("delegate-open", {