@a-t-h-i/bot-lobby 0.4.0 → 0.5.1

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.
Files changed (41) hide show
  1. package/README.md +238 -10
  2. package/package.json +5 -2
  3. package/prompts/master.md +12 -0
  4. package/prompts/panel.md +44 -0
  5. package/prompts/planner.md +69 -0
  6. package/prompts/quickfix.md +41 -0
  7. package/src/execution/agent-runner.ts +7 -2
  8. package/src/execution/pi-runner.ts +25 -0
  9. package/src/index.ts +3 -0
  10. package/src/lobby/ask.ts +226 -0
  11. package/src/lobby/feed.ts +253 -0
  12. package/src/lobby/issues.ts +227 -0
  13. package/src/lobby/keys.ts +51 -0
  14. package/src/lobby/layout.ts +363 -0
  15. package/src/lobby/markdown.ts +48 -0
  16. package/src/lobby/planner.ts +581 -0
  17. package/src/lobby/quickfix.ts +227 -0
  18. package/src/lobby/runtime.ts +591 -0
  19. package/src/lobby/tabs/home.ts +242 -0
  20. package/src/lobby/tabs/issues.ts +72 -0
  21. package/src/lobby/tabs/metrics.ts +275 -0
  22. package/src/lobby/tabs/plan.ts +242 -0
  23. package/src/lobby/tabs/quickfix.ts +129 -0
  24. package/src/lobby/tabs/tasks.ts +243 -0
  25. package/src/lobby/view.ts +1610 -0
  26. package/src/pi/activity.ts +120 -0
  27. package/src/pi/commands.ts +19 -57
  28. package/src/pi/events.ts +5 -2
  29. package/src/pi/model-support.ts +34 -0
  30. package/src/pi/run-summary.ts +2 -0
  31. package/src/pi/settings-ui.ts +69 -1
  32. package/src/pi/start-task.ts +63 -0
  33. package/src/pi/tools.ts +2 -2
  34. package/src/pi/ui.ts +116 -55
  35. package/src/schemas/configuration.ts +102 -3
  36. package/src/schemas/findings.ts +6 -0
  37. package/src/schemas/task.ts +1 -0
  38. package/src/state/backlog.ts +106 -0
  39. package/src/state/comments.ts +136 -0
  40. package/src/state/metrics.ts +305 -0
  41. package/src/workflow/workflow.ts +39 -7
package/README.md CHANGED
@@ -67,13 +67,17 @@ recorded in the task.
67
67
  pi install npm:@juicesharp/rpiv-ask-user-question
68
68
  ```
69
69
 
70
- It is optional. Without it `clarify` still works through Pi's built-in
71
- `select`/`input` prompts (or the Master asks in plain text), just with less
72
- structure.
70
+ It is optional for the Master. Without it `clarify` still works through Pi's
71
+ built-in `select`/`input` prompts (or the Master asks in plain text), just with
72
+ less structure. The lobby's planning panel uses the same questionnaire on its
73
+ own — the library ships as a bot-lobby dependency, so the panel's questions
74
+ arrive one at a time with options whether or not you install the tool for the
75
+ Master (see [The lobby](#the-lobby)).
73
76
 
74
77
  ## Usage
75
78
 
76
79
  ```
80
+ /bot-lobby Open the lobby (alt+l): tasks, planning, quick fixes, metrics
77
81
  /bot-lobby <request> Start a task and hand it to the Master
78
82
  /bot-lobby status [taskId] Active task, state, approvals, blockers, legal next states
79
83
  /bot-lobby tasks Task list (plus any unreadable task state)
@@ -89,8 +93,181 @@ structure.
89
93
  /bot-lobby-settings Same as the settings subcommand
90
94
  /bot-lobby minimize|restore Hide or restore bot-lobby for this session (ctrl+shift+m)
91
95
  /bot-lobby claim <taskId> Take ownership of an orphaned task
96
+ /bot-lobby lobby | help Open the lobby, or show this list
92
97
  ```
93
98
 
99
+ ## The lobby
100
+
101
+ The lobby is bot-lobby's full-screen home: a tabbed view over every task in the
102
+ project, your planning, quick fixes and model performance, with one prompt at
103
+ the bottom whose target follows the tab. It opens by itself when
104
+ this session starts (or resumes) a task — the small zen widget returns whenever
105
+ you hide it — and `alt+l` or `/bot-lobby` opens and hides it at any time, with
106
+ or without a task.
107
+
108
+ ```
109
+ ◆ bot-lobby │ 1 Lobby 2 Tasks 2 3 Plan 2? 4 Quick fix ⠋ 5 Metrics ⠋ TASK-add-login implementing Alt+H keys
110
+ (the zen scene: the oracle, DEV · DESIGN · RESEARCH · QA, the plan checklist)
111
+ ╭ Conversation · TASK-add-login ─────────────── Alt+C ╮ ╭ Activity ──────────────────────────────── Alt+A ╮
112
+ │ you ▸ add a login page with email + password │ │ 12:04 MASTER ✓ scouting designer, backend │
113
+ │ oracle ▸ Proposal │ │ 12:06 DEV ⠋ reading auth.ts… │
114
+ │ • LoginForm component │ │ 12:06 DESIGN ⠋ editing LoginForm.tsx… │
115
+ │ • POST /api/login with rate limiting │ │ 12:06 QUICK FIX ✓ done: rename getUser │
116
+ ╰──────────────────────────────────────────────────────╯ ╰─────────────────────────────────────────────────╯
117
+ ╭ Thinking ────────────────────────────────────────────────────────────────────────────────── DEV · 12s ago ╮
118
+ │ The auth module already exposes a session helper; reuse it rather than adding a new one. │
119
+ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯
120
+ ── message the oracle ───────────────────────────────────────────────────────────────────────────────────────
121
+ _
122
+ TYPE enter send shift+enter newline esc browse tab next tab alt+h keys alt+l hide
123
+ ```
124
+
125
+ - **1 Lobby** — the task's zen scene, then the conversation with the oracle
126
+ (its text only: no tool rows, no thinking), an activity log that narrates
127
+ every tool call in plain words (`reading index.html…`, `searching for
128
+ "router" in src`, `running npm test`, `delegating to backend: Step 2 …`) from
129
+ the Master and every subagent, and a single **Thinking** pane — the one place
130
+ thoughts show up: the oracle's live thought as it streams, and each finished
131
+ thought from a subagent, quick fix or the planner (pi's own transcript,
132
+ behind the lobby, still carries the oracle's thinking blocks; `ctrl+t`
133
+ collapses them there). The oracle's replies render as Markdown. Every pane
134
+ can be hidden and brought back — `alt+z` the scene, `alt+c` the
135
+ conversation, `alt+a` the activity log, `alt+k` thinking — and the rest take
136
+ its room; the choice is remembered (`lobby.panels`). Each pane scrolls on
137
+ its own (see **Scrolling** below), and a pane scrolled back stays on what
138
+ you are reading while new lines arrive. The prompt talks to the
139
+ oracle (while it works, enter steers the running turn; `esc` stops it); with
140
+ no task, it starts one.
141
+ - **2 Tasks** — every task in the project: this session's, the ones other pi
142
+ sessions are driving, pending plans saved from the planner, and recently
143
+ finished ones. The detail pane shows the request, the approved plan with its
144
+ step checklist, your comments on it, amendments, what the task waits on and
145
+ its recent runs. `c` comments on the selected task's plan (see below), `s`
146
+ starts a pending plan as a task in this session, `d` twice discards one.
147
+ - **3 Plan** — task planning mode with a planning panel. Describe what you
148
+ want and every seat grills you from its own domain, on the model and
149
+ thinking level its settings name: **DEV** (APIs, data, errors, security,
150
+ performance), **DESIGN** (flows, states, copy, visual language,
151
+ accessibility), **QA** (acceptance criteria, test strategy, edge cases,
152
+ definition of done) and **RESEARCH** (libraries, versions, docs and prior
153
+ art, with the web tools when `pi-web-access` is installed). The **oracle**
154
+ chairs on the Planner model: it reads the seats' questions and notes, folds
155
+ every answer into the draft plan (with a *Decisions by domain* section) and
156
+ asks only what no single seat owns. Each round the seats run in parallel,
157
+ read-only, then the oracle. Every question comes with two to four options,
158
+ the seat's recommendation first, and the oracle puts them to you **one at a
159
+ time** through the ask-user-question questionnaire: a tab per question
160
+ labelled with the seat that asked it (`QA`, `DEV`…), its options with what
161
+ each means, and a row to type your own answer or add a note (four questions
162
+ per questionnaire; more follow in the next one). It opens by itself when a
163
+ round ends while the Plan tab is showing (`lobby.autoAsk`), and otherwise
164
+ when you press `enter` on the empty prompt or `a` while browsing; `esc` puts
165
+ it away with your answers so far kept, and `enter` resumes. Your answers go
166
+ back attributed (`3. [QA] Which browsers must pass? → evergreen only`), and
167
+ every seat reads every answer the next round — so the agents that later
168
+ build the task start aligned. You can still type a free reply instead.
169
+ Without the library the same questions come through pi's own select and
170
+ input dialogs. A roster shows what each seat is doing and whether it is
171
+ READY; the plan is READY only when every seat and the oracle agree. The
172
+ draft plan renders as Markdown (headings, lists, code, tables) beside the
173
+ conversation, followed by what each seat said the plan must respect.
174
+ **Comment on any line of the draft**: click it, or press `enter` to move to
175
+ the draft, pick a line with `↑↓` and press `c`, then type the comment. The
176
+ line is marked `◆` with your comment beneath it, and the comment goes to the
177
+ panel with your answers — or starts a round by itself when no question is
178
+ open. While browsing, `1`–`4` seat or unseat DEV, DESIGN, QA and RESEARCH
179
+ for the next round, `s` saves the plan to the pending tasks list, `n` starts
180
+ over, `r` retries a round that failed or lost a seat, `x` stops one, and `m`
181
+ opens the oracle's (Planner) settings.
182
+ - **4 Quick fix** — a direct prompt, the way you would ask pi, that skips the
183
+ whole workflow: one coding agent (full tools) makes the change right away
184
+ while any task keeps running. Quick fixes run one at a time in the order you
185
+ send them; each shows its steps and final report, and `x` cancels one. A
186
+ request that turns out to be large is reported back instead of attempted.
187
+ `m` opens the quick fix agent's settings — model, thinking level, time
188
+ limit and instructions — right there (the same entry as in
189
+ `/bot-lobby settings`); the tab shows what it runs on.
190
+ - **5 Metrics** — model performance across every Master turn, subagent run,
191
+ quick fix, planning seat and oracle planning turn, as a dashboard: tiles for
192
+ runs (with a sparkline of recent run times), success rate, average and p90
193
+ run time, cost and tasks; average run time per model and thinking level as
194
+ bars; success rate per model as meters marked `✓` (≥90%), `!` (≥70%) or `✗`;
195
+ where the time goes as one bar split by agent, with a legend, and how long a
196
+ task takes from request to done by the oracle's model; then the full table —
197
+ runs, success, mean/median/p90 time, turns, tools, tokens, output tokens per
198
+ second and cost (columns drop from the right on narrow terminals). `g`
199
+ splits the table by agent, `s` cycles the sort (runs, average time, success,
200
+ cost).
201
+
202
+ The **Issues** tab (GitHub issues through the `gh` CLI, planned into tasks
203
+ through the Plan tab) is switched off for now; `"lobby": { "issues": true }`
204
+ brings it back as tab 5.
205
+
206
+ **Keys.** Like a modal editor, the lobby has a typing mode (keys go to the
207
+ prompt) and a browsing mode (`esc`; arrows move through lists, single keys run
208
+ the tab's commands, and on Lobby, Plan and Quick fix any other key resumes
209
+ typing). These work in both modes:
210
+
211
+ | Key | Does |
212
+ | --- | --- |
213
+ | `alt+l` | hide the lobby (back to pi) |
214
+ | `alt+h` (or `?` while browsing) | show every key, and the current tab's |
215
+ | `alt+s` | bot-lobby settings: every agent's model, thinking and time limit, and the lobby's switches |
216
+ | `ctrl+f` (or `/` while browsing) | search the current tab |
217
+ | `tab` / `shift+tab`, `alt+1`…`alt+5` | switch tabs |
218
+ | `alt+z` / `alt+c` / `alt+a` / `alt+k` | show or hide the zen scene / conversation / activity log / thinking |
219
+ | `pageup` / `pagedown` | scroll the focused pane a page |
220
+ | `ctrl+c` | clear the prompt, or hide the lobby when it is empty |
221
+
222
+ Every shortcut can be rebound under `lobby.keys` in the config, by action name:
223
+ `hide`, `help`, `settings`, `search`, `nextTab`, `prevTab`, `toggleScene`,
224
+ `toggleConversation`, `toggleActivity`, `toggleThinking`, `scrollUp`,
225
+ `scrollDown` — e.g. `"keys": { "toggleThinking": "alt+t" }`. Pick keys that
226
+ never type a character (`alt+…`, `ctrl+…`, `f1`…).
227
+
228
+ **Scrolling.** Every pane scrolls on its own and shows a scrollbar in its
229
+ right border when it holds more than fits. While browsing, `←`/`→` move
230
+ between the tab's panes (the conversation, activity log and thinking on
231
+ Lobby; the conversation and draft on Plan; the list and detail on Tasks and
232
+ Quick fix) and the focused one lights up; `↑`/`↓` scroll it a line (or move
233
+ a list's selection, or the draft's cursor), `pageup`/`pagedown` a page, and
234
+ `home`/`end` jump to its oldest line or back to its newest. The conversation,
235
+ activity log and thinking are newest-last: scrolled back, a pane shows `↓N`
236
+ for the lines below it and holds still while new ones arrive; `end` follows
237
+ the newest again. Details stop at their last line. The Thinking pane keeps
238
+ every recent thought, so earlier ones are a scroll away.
239
+
240
+ **Search.** `ctrl+f` opens a search bar above the prompt; as you type, the tab
241
+ narrows to what matches and every match is highlighted: the conversation,
242
+ activity log and thoughts on Lobby; tasks and plans (by id, title, request,
243
+ proposal or plan) on Tasks; the conversation on Plan (the draft stays whole,
244
+ highlighted); jobs on Quick fix; runs (by agent, model, thinking level, kind or
245
+ task) on Metrics. `enter` keeps the search while you browse the results,
246
+ `esc` clears it, and each tab keeps its own.
247
+
248
+ **Mouse.** Clicking a tab opens it, clicking a pane gives it the keys,
249
+ clicking a draft plan line comments on it, clicking the prompt starts typing,
250
+ and the wheel scrolls whichever pane is under the pointer. In pi's regular
251
+ screen the lobby turns mouse reporting on only while it is showing (hold
252
+ `shift` to select text with the mouse); in full-screen pi, pi reports the
253
+ mouse itself. `"lobby": { "mouse": false }` turns clicks off.
254
+
255
+ Anything that needs pi itself —
256
+ built-in slash commands, `/model`, the tool-row toggle — works with the lobby
257
+ hidden; bot-lobby's own `/bot-lobby …` commands also work from the Lobby
258
+ prompt. When the Master asks you something (an approval, a clarifying
259
+ question), the lobby steps aside for the dialog and comes back once you answer.
260
+
261
+ **Plan comments.** A comment on a task's plan is saved beside the task
262
+ (`comments.jsonl`) from any session, and the session that owns the task passes
263
+ new comments to its oracle — right away when you comment in that session,
264
+ within a few seconds from another one, held while the task is paused or the
265
+ session is minimized. The oracle treats a comment like an amendment and calls
266
+ `orchestrate action=plan` with the full revised plan, which replaces the
267
+ approved plan while implementing or reviewing, keeps finished steps done and
268
+ marks the comments addressed (`○` waiting, `◐` sent to the oracle, `✓` plan
269
+ amended). Before a plan exists, a comment asks for a revised proposal instead.
270
+
94
271
  ## Sessions and ownership
95
272
 
96
273
  A task is owned by the pi session that started it (`ctx.sessionManager` id,
@@ -116,7 +293,8 @@ every in-flight subagent process.
116
293
 
117
294
  While the owning session has a task active, its transcript switches to a zen view: `orchestrate` rows
118
295
  and the built-in spinner are hidden, and a widget above the editor animates the
119
- task. At 72 columns and wider it draws a large scene: a header box with the task
296
+ task (the same scene heads the lobby's first tab; the widget shows while the
297
+ lobby is hidden). At 72 columns and wider it draws a large scene: a header box with the task
120
298
  title and state in its top border, a progress bar, and a metadata row with
121
299
  elapsed time, quiet-mode hint and task id; an oracle tower with a twinkling
122
300
  aura (drifting z's while dormant), a radiant orb crown, two window eyes, a
@@ -214,7 +392,7 @@ One tool, every workflow step. It is the Master's only way to move a task.
214
392
  | `scout` | created…synthesizing | Run domain reconnaissance in parallel; repeat later to target-verify a claim |
215
393
  | `research` | any active | Summon the read-only Researcher (domain + instruction) for cited internet evidence; persists the report for audit |
216
394
  | `propose` | created…awaiting_approval | Record the proposal, request approval, handle approve/amend/decline |
217
- | `plan` | planning | Record the internal plan (all §12 areas required) |
395
+ | `plan` | planning, implementing, reviewing | Record the internal plan (all §12 areas required); later, replace it with an amended plan (addresses lobby comments) |
218
396
  | `implement` | planning, implementing, reviewing | Delegate a step to a domain Worker, or several domains at once with `assignments` (parallel, sharing files through the file desk) |
219
397
  | `qa` | implementing, reviewing | Run the QA gate — the only review — over the whole feature |
220
398
  | `knowledge` | any active | Record Master-approved knowledge or a decision |
@@ -339,6 +517,9 @@ top-level `/bot-lobby-settings`) and persist globally to
339
517
  },
340
518
  "scout": { "model": "anthropic/claude-haiku-4-5-20251001", "timeoutMs": 480000 },
341
519
  "researcher": { "model": "anthropic/claude-sonnet-5", "thinking": "low", "instructions": "", "timeoutMs": 600000 },
520
+ "quickFix": { "model": "anthropic/claude-sonnet-5", "thinking": "low", "instructions": "", "timeoutMs": 600000 },
521
+ "planner": { "model": "anthropic/claude-sonnet-5", "thinking": "high", "instructions": "", "timeoutMs": 300000 },
522
+ "lobby": { "autoOpen": true, "planningPanel": ["backend", "designer", "qa", "researcher"], "autoAsk": true, "issues": false, "mouse": true },
342
523
  "workflow": {
343
524
  "maxReviewIterations": 2,
344
525
  "maxParallelScouts": 3,
@@ -373,6 +554,38 @@ visible; only the master keeps `inherit`, since it is the session itself.
373
554
  Each subagent entry has a `timeoutMs` (default 15 min; scouts 8, researcher 10),
374
555
  falling back to `workflow.agentTimeoutMs`.
375
556
 
557
+ The lobby's two agents have entries of their own: `quickFix` (the direct-change
558
+ agent, `low` thinking and 10 minutes by default) and `planner` (the oracle
559
+ chairing the planning panel, `high` thinking; its time limit bounds one round
560
+ for every seat, 5 minutes by default). Both appear in `/bot-lobby settings`,
561
+ take custom instructions, and run on the session's model until you pin one.
562
+ Planning seats reuse their domain's entry — DEV the Backend's, DESIGN the
563
+ Designer's, QA the QA's, RESEARCH the Researcher's model, thinking and
564
+ instructions — so a seat plans on the model that will later build its part.
565
+ The `lobby` entry shapes the lobby itself; `/bot-lobby settings` → **Lobby**
566
+ flips its switches, and key rebinding lives in the file:
567
+
568
+ ```json
569
+ "lobby": {
570
+ "autoOpen": true,
571
+ "planningPanel": ["backend", "designer", "qa", "researcher"],
572
+ "autoAsk": true,
573
+ "issues": false,
574
+ "mouse": true,
575
+ "panels": { "scene": true, "conversation": true, "activity": true, "thinking": true },
576
+ "keys": { "toggleThinking": "alt+t" }
577
+ }
578
+ ```
579
+
580
+ `planningPanel` names the seats a new planning session starts with (every
581
+ seat by default; `[]` lets the oracle plan alone); `autoOpen` opens the lobby
582
+ by itself when this session starts or resumes a task; `autoAsk` puts the
583
+ panel's questions to you as soon as a round ends while the Plan tab is
584
+ showing (otherwise `enter` on the empty prompt does); `issues` shows the
585
+ GitHub Issues tab (off for now); `mouse` turns clicks and the wheel on;
586
+ `panels` is which Lobby panes show (the pane keys update it); `keys` rebinds
587
+ shortcuts by action name.
588
+
376
589
  `thinking` must be one of `off`, `minimal`, `low`, `medium`, `high`, `xhigh`,
377
590
  `max`; a legacy `inherit` or unknown value falls back to `medium`. The thinking
378
591
  picker lists only the levels the selected model supports. Switching to a model
@@ -416,8 +629,11 @@ and the output contract — and an empty layer is dropped.
416
629
  ├── Backend/knowledge/ knowledge.md, engineering-standards.md, decisions.md, completed-tasks.md
417
630
  ├── QA/knowledge/ knowledge.md, testing-standards.md, decisions.md, completed-tasks.md
418
631
  ├── archive/<Agent>/ previous knowledge versions (outside all retrieval paths)
632
+ ├── backlog/PLAN-<slug>.json pending tasks saved from the planner (optionally linked to an issue)
633
+ ├── metrics.jsonl one line per finished run of any agent, for the Metrics tab
419
634
  └── tasks/TASK-<stamp>/
420
635
  ├── state.json the task record (kept after completion)
636
+ ├── comments.jsonl your lobby comments on the plan and their delivery (append-only)
421
637
  ├── proposal.md scratchpads: deleted on completion
422
638
  ├── plan.md
423
639
  ├── designer.md backend.md qa.md
@@ -465,10 +681,22 @@ src/
465
681
  ├── desk/ File desk for parallel workers: checkout table, socket, worker extension
466
682
  ├── knowledge/ Paths, store (single write path), selector, compactor
467
683
  ├── prompts/ Layer loader + compiler
468
- ├── state/ Project root, config, task persistence, state mutation
684
+ ├── lobby/
685
+ │ ├── runtime.ts Mounts the full-screen lobby on pi's TUI, dialogs hand-off, comment delivery, Master metrics
686
+ │ ├── view.ts The tabbed view: tab bar, per-tab prompt, typing/browsing modes, search, help, mouse
687
+ │ ├── keys.ts The shortcut table and its config overrides
688
+ │ ├── ask.ts The panel's questions through the ask-user-question questionnaire (or pi's dialogs)
689
+ │ ├── markdown.ts Markdown through pi's renderer, cached per theme and width
690
+ │ ├── tabs/ Pure renderers: home, tasks, plan, quickfix, issues, metrics
691
+ │ ├── feed.ts Activity log, thinking pane and conversation store
692
+ │ ├── quickfix.ts Direct-change jobs, one at a time
693
+ │ ├── planner.ts The planning panel: seats and the oracle per round, reply parsing, saving a plan
694
+ │ ├── issues.ts GitHub issues through the gh CLI
695
+ │ └── layout.ts Boxes, exact-width columns, wrapping, highlights, bars, meters and sparklines
696
+ ├── state/ Project root, config, task persistence, state mutation, comments, backlog, metrics
469
697
  ├── schemas/ Task, agent, findings, configuration types
470
698
  └── pi/ Commands, lifecycle, orchestrate tool, status widget
471
- prompts/ global, master, designer, backend, qa, scout, worker, reviewer, researcher
699
+ prompts/ global, master, designer, backend, qa, scout, worker, reviewer, researcher, quickfix, planner, panel
472
700
  ```
473
701
 
474
702
  Prompts are composed, never duplicated: `global + domain + role + task context +
@@ -518,7 +746,7 @@ compaction, bounded review loops, dependency/architecture approval, retries,
518
746
  cancellation, corrupted-state detection, and the commands/status UI.
519
747
 
520
748
  Deliberately deferred (matching the build plan): worktree-based isolation for
521
- parallel Workers (they share one working tree through the file desk), a large
522
- dashboard, cost/token analytics beyond per-run usage, and
749
+ parallel Workers (they share one working tree through the file desk) and
523
750
  cross-platform runtime abstractions. The internal module boundaries keep those
524
- extractable.
751
+ extractable. The lobby (see above) has since added the full-screen dashboard
752
+ and per-model performance analytics.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a-t-h-i/bot-lobby",
3
- "version": "0.4.0",
3
+ "version": "0.5.1",
4
4
  "description": "Structured multi-agent software engineering orchestrator for Pi",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -38,11 +38,14 @@
38
38
  "typebox": "*"
39
39
  },
40
40
  "devDependencies": {
41
- "@earendil-works/pi-coding-agent": "0.87.0",
42
41
  "@earendil-works/pi-ai": "0.87.0",
42
+ "@earendil-works/pi-coding-agent": "0.87.0",
43
43
  "@earendil-works/pi-tui": "0.87.0",
44
44
  "@types/node": "^22.10.0",
45
45
  "typebox": "1.3.27",
46
46
  "typescript": "^5.7.0"
47
+ },
48
+ "dependencies": {
49
+ "@juicesharp/rpiv-ask-user-question": "^2.11.0"
47
50
  }
48
51
  }
package/prompts/master.md CHANGED
@@ -77,6 +77,18 @@ asked. If the user
77
77
  amends the request, reassess affected assumptions — never silently reinterpret
78
78
  an amendment.
79
79
 
80
+ ## Lobby comments
81
+
82
+ The user can comment on the approved plan (or the proposal) from the lobby, in
83
+ this session or another one. Each comment reaches you as a message naming the
84
+ task; open ones are also listed under `Open plan comments` in your task
85
+ context. Treat a comment like an amendment: reassess what it affects, then call
86
+ `orchestrate action=plan` with the full revised plan (it replaces the current
87
+ one while implementing or reviewing, keeps finished steps done, and marks the
88
+ comments addressed) before delegating more work. Before a plan exists, revise
89
+ the proposal and call `action=propose` again. If a comment needs no change,
90
+ say why in one line.
91
+
80
92
  ## Delegation
81
93
 
82
94
  Assign work to the correct domain; never ask one domain to do another's. A
@@ -0,0 +1,44 @@
1
+ # Planning Panel Member
2
+
3
+ You sit on the planning panel for a task that has not started yet. The panel
4
+ is the oracle plus one member per domain — DEV, DESIGN, QA and RESEARCH — and
5
+ the user answers everyone's questions in one conversation, so every agent that
6
+ later works on the task starts from the same decisions.
7
+
8
+ You never write code or change files. You may read the repository (and, for
9
+ RESEARCH, the web) to ask sharper questions and to state facts.
10
+
11
+ ## Each round
12
+
13
+ You receive the conversation so far, including every panel member's earlier
14
+ questions and the user's answers, and the oracle's current draft plan.
15
+
16
+ - Ask only what your seat owns (below), and only what would change how the
17
+ task is built or verified. Never repeat a question that has been answered,
18
+ or one another member already asked this round.
19
+ - Ask at most two questions, the most important first. Make each specific and
20
+ answerable, and give it two to four options the user can pick from, your
21
+ recommendation first with `(Recommended)` after its label. The user can
22
+ always type their own answer instead, so do not add an "Other" option.
23
+ - If an answer from the user is vague or conflicts with what you see in the
24
+ repository, say so and ask again.
25
+ - Report what the plan must respect from your seat under Notes: facts from
26
+ files you read (name them), constraints, risks, what "done" means for you.
27
+ - When nothing in your seat is open any more, set the status to READY and ask
28
+ nothing.
29
+
30
+ ## Output format
31
+
32
+ ## Status
33
+ OPEN or READY
34
+
35
+ ## Questions
36
+ 1. The question, ending with a question mark?
37
+ - Short label (Recommended) — what choosing it means
38
+ - Another label — what choosing it means
39
+
40
+ (Two to four options per question, labels of one to five words. Omit
41
+ Questions when READY.)
42
+
43
+ ## Notes
44
+ - …
@@ -0,0 +1,69 @@
1
+ # Task Planner
2
+
3
+ You are the oracle chairing a planning panel: you help the user turn an idea
4
+ (or a GitHub issue) into a task plan that the team of agents can execute
5
+ without guessing. The panel's domain members — DEV, DESIGN, QA and RESEARCH —
6
+ ask the user their own questions each round; you own the plan and the
7
+ questions no single domain owns. You are relentless: together you grill the
8
+ user until every decision that changes the implementation is made. You never
9
+ write code and never change files; you may read the repository to ask
10
+ informed questions and to ground the plan in what exists.
11
+
12
+ ## Each turn
13
+
14
+ You receive the conversation so far (every member's questions and the user's
15
+ answers) and, under `## Panel this round`, each member's status, questions
16
+ and notes. Read the repository when it helps, then reply in the output format
17
+ below.
18
+
19
+ - Fold every member's notes and every answer into the draft plan, so each
20
+ domain's decisions are written down where all agents will read them. When
21
+ members disagree, say so and ask the user to decide.
22
+ - Ask at most three questions of your own, the most important first, and
23
+ only cross-cutting ones the members did not ask: scope and non-goals,
24
+ priorities, trade-offs between domains, sequencing, rollout and rollback.
25
+ Never repeat a member's question. Each one must be specific and answerable.
26
+ - Give every question two to four options the user can pick from, your
27
+ recommendation first with `(Recommended)` after its label. The user answers
28
+ the panel's questions one at a time and can always type their own answer,
29
+ so never add an "Other" option.
30
+ - Challenge answers that are vague, contradictory or risky, and ask again.
31
+ Do not accept "whatever you think" for a decision with real trade-offs:
32
+ propose one and ask the user to confirm it.
33
+ - Ground every claim about the codebase in files you read; name them.
34
+ - Keep a draft plan updated every turn so the user sees it converge.
35
+
36
+ Declare the plan READY only when every panel member is READY and nothing
37
+ that would change the implementation is still open. Until then the status is
38
+ GRILLING.
39
+
40
+ ## Output format
41
+
42
+ ## Status
43
+ GRILLING or READY
44
+
45
+ ## Title
46
+ Three to six words naming the task.
47
+
48
+ ## Questions
49
+ 1. The most important open question?
50
+ - Short label (Recommended) — what choosing it means
51
+ - Another label — what choosing it means
52
+ 2. …
53
+
54
+ (Two to four options per question, labels of one to five words. Omit the
55
+ Questions section when READY.)
56
+
57
+ ## Plan
58
+ The current draft, in Markdown:
59
+
60
+ ### Objective
61
+ ### Scope and non-goals
62
+ ### Acceptance criteria
63
+ ### Affected areas
64
+ (files, modules and domains: designer, backend, qa)
65
+ ### Decisions by domain
66
+ (what the user decided for DEV, DESIGN, QA and RESEARCH, one bullet each)
67
+ ### Steps
68
+ 1. …
69
+ ### Risks and open points
@@ -0,0 +1,41 @@
1
+ # Quick Fix Agent
2
+
3
+ You make one small, direct code change the user asked for from the bot-lobby
4
+ lobby. There is no scouting, proposal, plan or review round: the user wants
5
+ the change now, the way they would ask pi directly.
6
+
7
+ ## How to work
8
+
9
+ - Read only what you need to make the change safely; follow the file's
10
+ existing conventions.
11
+ - Make the smallest correct change that does exactly what was asked. Do not
12
+ refactor, rename or tidy anything else.
13
+ - If the request is ambiguous, pick the most reasonable reading and say which
14
+ one you chose in your report; do not stop to ask.
15
+ - If the change turns out to be large (many files, a new dependency, an
16
+ architecture change), make no edits and report what it would take, so the
17
+ user can plan it as a task instead.
18
+ - Run a quick targeted check when one exists (the nearest test file, a
19
+ typecheck of the touched package) with a bash `timeout`; never start dev
20
+ servers, watchers or background processes.
21
+ - Change files with `edit`/`write`, never through shell redirection or
22
+ `sed -i`.
23
+
24
+ ## Other agents
25
+
26
+ A bot-lobby task may be running at the same time in this working tree. Touch
27
+ only the files the request needs, re-read a file right before editing it, and
28
+ never revert, reformat or "fix" changes you did not make.
29
+
30
+ ## Report
31
+
32
+ End with a short report in this shape:
33
+
34
+ ## Done
35
+ One or two sentences on what changed.
36
+
37
+ ## Files
38
+ - path — what changed
39
+
40
+ ## Checked
41
+ What you ran and the result, or "not checked" with the reason.
@@ -2,7 +2,7 @@ import type { Domain, Role } from "../schemas/agent.ts";
2
2
  import type { AgentRun } from "../schemas/findings.ts";
3
3
  import { roleSpec } from "../roles/registry.ts";
4
4
  import { compilePrompt } from "../prompts/compiler.ts";
5
- import { activityDetail, activityWord } from "../pi/activity.ts";
5
+ import { activityDetail, activityWord, describeToolCall } from "../pi/activity.ts";
6
6
  import { shortDuration, truncate } from "../text.ts";
7
7
  import { runPiAgent, spawnPiProcess, type PiStreamEvent, type ProcessRunner } from "./pi-runner.ts";
8
8
 
@@ -114,6 +114,7 @@ function baseRun(request: AgentRequest, runId: string, startedAt: string, attemp
114
114
  output: "",
115
115
  attempts,
116
116
  startedAt,
117
+ ...(request.thinking ? { thinking: request.thinking } : {}),
117
118
  ...(attempts > 1 ? { note: `retry ${attempts - 1} of ${(request.retries ?? 0)}`, noteKind: "warning" as const } : {}),
118
119
  };
119
120
  }
@@ -208,9 +209,13 @@ function createLiveRun(base: AgentRun, request: AgentRequest) {
208
209
  case "tool_execution_start": {
209
210
  const activity = activityWord(event.toolName);
210
211
  const detail = activityDetail(event.toolName, event.args);
211
- emit({ activity, detail, tools: (state.tools ?? 0) + 1 }, changed(activity, detail));
212
+ const step = describeToolCall(event.toolName, event.args);
213
+ emit({ activity, detail, step, tools: (state.tools ?? 0) + 1 }, changed(activity, detail) || step !== state.step);
212
214
  return;
213
215
  }
216
+ case "thought":
217
+ emit({ thought: event.text }, true);
218
+ return;
214
219
  case "thinking":
215
220
  case "writing":
216
221
  emit({ activity: event.type, detail: undefined }, changed(event.type, undefined));
@@ -61,8 +61,13 @@ export type PiStreamEvent =
61
61
  | { type: "compaction" }
62
62
  | { type: "usage"; input: number; output: number; cost: number; model?: string }
63
63
  | { type: "wrap_up" }
64
+ /** One finished thinking block, bounded to `MAX_THOUGHT_CHARS`. */
65
+ | { type: "thought"; text: string }
64
66
  | { type: "heartbeat" };
65
67
 
68
+ /** Longest thought forwarded from a subagent stream. */
69
+ export const MAX_THOUGHT_CHARS = 1500;
70
+
66
71
  export interface ProcessRunOptions {
67
72
  cwd: string;
68
73
  signal?: AbortSignal;
@@ -215,6 +220,11 @@ export function createStreamCollector(
215
220
  phase = next;
216
221
  onEvent?.({ type: next });
217
222
  }
223
+ // One parse per finished thinking block (not per token) forwards the thought itself.
224
+ if (onEvent && line.includes('"thinking_end"')) {
225
+ const thought = finishedThought(line);
226
+ if (thought) onEvent({ type: "thought", text: thought });
227
+ }
218
228
  };
219
229
  const keep = (line: string) => {
220
230
  deltaPhase(line);
@@ -261,6 +271,21 @@ export function createStreamCollector(
261
271
  };
262
272
  }
263
273
 
274
+ /** The text of a `thinking_end` message update, trimmed and bounded; undefined for anything else. */
275
+ export function finishedThought(line: string): string | undefined {
276
+ let event: { assistantMessageEvent?: { type?: string; content?: unknown } };
277
+ try {
278
+ event = JSON.parse(line) as typeof event;
279
+ } catch {
280
+ return undefined;
281
+ }
282
+ const update = event?.assistantMessageEvent;
283
+ if (update?.type !== "thinking_end" || typeof update.content !== "string") return undefined;
284
+ const text = update.content.trim();
285
+ if (!text) return undefined;
286
+ return text.length > MAX_THOUGHT_CHARS ? `${text.slice(0, MAX_THOUGHT_CHARS - 1)}…` : text;
287
+ }
288
+
264
289
  /** Build the `pi` argv for one isolated, headless RPC agent run; the task goes over stdin. */
265
290
  export function buildPiArgs(options: Omit<PiRunOptions, "task"> & { systemPromptFile?: string }): string[] {
266
291
  const args = ["--mode", "rpc", "--no-session", "--no-prompt-templates", "--no-themes"];
package/src/index.ts CHANGED
@@ -6,9 +6,12 @@ import { onTransition } from "./state/task-state.ts";
6
6
  import { ping } from "./pi/notify.ts";
7
7
  import { isSubagentProcess } from "./pi/quiet.ts";
8
8
  import { registerDeskClient } from "./desk/client-extension.ts";
9
+ import { registerLobbyEvents } from "./lobby/runtime.ts";
9
10
 
10
11
  export default function (pi: ExtensionAPI): void {
11
12
  registerLifecycle(pi, CONFIG_DIR_NAME);
13
+ // After the lifecycle, so the lobby opens over a task the widget state already knows.
14
+ registerLobbyEvents(pi, CONFIG_DIR_NAME);
12
15
  onTransition((task) => ping(task.state, task.title));
13
16
  registerCommands(pi, CONFIG_DIR_NAME);
14
17
  registerOrchestrateTool(pi, CONFIG_DIR_NAME);