@a-t-h-i/bot-lobby 0.6.41 → 0.6.43

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
@@ -4,8 +4,6 @@ A [Pi](https://pi.dev) extension for multi-agent software development. Describe
4
4
  plan with the oracle, and follow the agents in a local browser lobby. Approvals, domain boundaries and QA
5
5
  are enforced before anything is called done.
6
6
 
7
- ![The Lobby: the conversation, the agents' activity and the Thinking orb](.github/screenshots/lobby.png)
8
-
9
7
  ## Install
10
8
 
11
9
  ```bash
@@ -14,64 +12,35 @@ pi install npm:@a-t-h-i/bot-lobby
14
12
 
15
13
  Try it first with `pi -e npm:@a-t-h-i/bot-lobby`, or from a checkout with `pi -e ./src/index.ts`.
16
14
  The questionnaire and web tools are built in, so don't also install extensions with the same tool names.
15
+ Requires **Pi 1.0.x** (1.0.1 or later).
17
16
 
18
17
  ## Use
19
18
 
20
- 1. In Pi, run `/bot-lobby add a login page`. Bot-lobby turns on and the lobby opens in your browser.
21
- A new Pi session starts with bot-lobby off, as plain Pi: `Ctrl+Shift+M` or `/bot-lobby on|off` switches it.
19
+ 1. In Pi, run `/bot-lobby add a login page`. The lobby opens in your browser. `Ctrl+Shift+M` or
20
+ `/bot-lobby on|off` switches bot-lobby on or off; a new Pi session starts with it off.
22
21
  2. Answer the oracle's questions and approve its plan, or agree on one with the panel in **Plan** first.
23
- A plan opens with a short list of steps; the detail of each follows for whoever wants it.
24
- Plans you leave without saving them as a task wait under **Plan → Previous**. You can read, carry on,
25
- archive or delete them there. A plan saved as a task leaves that list.
26
- 3. Follow the agents in **Lobby** and **Tasks**: in a task's steps, the one being worked on reads
27
- `active · 1m 12s`, and each task shows how long its agents have worked on it (idle time left out). Models, effort and time limits are in **Settings**.
28
-
29
- **Issues** lists the repository's open issues (with `lobby.issues` on), and **Plan it** starts a
30
- planning session from one. **Git** lists open pull requests; an agent reviews one on request,
31
- read-only, and nothing is posted to GitHub. Both read GitHub through `gh`.
22
+ 3. Follow the agents in **Lobby** and **Tasks**. Their steps fold into one line in the conversation
23
+ and open in place.
32
24
 
33
25
  Small changes go to **Quick fix**. `--task` forces a full task, `--fast` / `--full` picks the workflow,
34
- and `--branch` / `--worktree` isolates it in git. When an isolated task completes, the oracle asks
35
- you to confirm merging and pushing main, then removes its worktree after verifying the merge.
36
- Declining or failed verification keeps the worktree. Delivery can also be reviewed in **Tasks**,
37
- where you can create a PR instead. The task branch is kept.
38
-
39
- Workers never commit; the oracle does. When a task completes, the oracle writes a short commit
40
- message (a first line of 72 characters or fewer, at most three lines below it). The engine then
41
- commits only the files that task's workers changed. A quick fix commits its own files when it
42
- finishes, under the one-line message its agent gives. Changes that were already there before, another
43
- agent's and anything no agent made are left uncommitted.
44
-
45
- New tasks get a short title summarizing the full request, which also names their branch and
46
- session. Naming uses low reasoning on `classifier.effort.cheapModel` when configured, otherwise
47
- the session model. If naming fails or takes more than eight seconds, the request's first content
48
- words are used. Tasks started from an agreed plan keep that plan's title.
49
-
50
- After every worker step, before QA and at completion, the engine runs the project's own linter
51
- (ESLint, Biome, Oxlint, Ruff, or a command you set) on the files the task touched. Only problems on
52
- changed lines count, and QA judges any lint suppression a worker adds. **Settings → Linting** sets it
53
- to off, advise or block. Visual questions come with mockups that expand and scroll side by side.
54
-
55
- QA is sized to what was built, not to the request. Once the work is in, the classifier
56
- reads the diff and sets the QA risk. A change with nothing that runs (docs, styles, comments) passes
57
- on the engine's checks with no QA agent, and a small one gets a light check. One that touches
58
- security, data, concurrency or orchestration gets a deep, adversarial review. The test budget is a
59
- ceiling, never a quota, and the Tasks tab shows the classifier's read and why. With it off, the engine's rules decide.
60
-
61
- If Pi crashes, is killed or loses its terminal, the lobby page keeps everything on screen and
62
- reconnects when Pi is back. The next Pi started in the project carries on what was running. The
63
- planning session returns as it was, and a round that was cut off runs again. Queued quick fixes
64
- run, and every task's session starts again from its saved file, picking up where it stopped. A
65
- quit on purpose stops this work, and `pi -c` brings back the planning session.
66
-
67
- A task that is paused, or that no running session drives, shows **Resume** (`R`) in **Tasks**.
68
- It carries the task on without moving your window: a paused task is unpaused where it runs, and a
69
- stopped one carries on in a background session, which restarts its own session when its file is found.
70
-
71
- The **Tasks** screen has **List** and **Board** subtabs. Board groups saved plans and new tasks
72
- in **Backlog**, active work in **In progress**, and finished work in **Completed**. Abandoned
73
- work stays labeled in Backlog until archived. Cards open the existing task details and actions;
74
- archiving removes a card immediately, while the List view can still show the archive.
26
+ and `--branch` / `--worktree` isolates it in git. Workers never commit: the oracle commits only the
27
+ files the task changed, after the project's linter and a QA pass sized to the change's risk.
28
+
29
+ ## The lobby
30
+
31
+ - **Lobby**: the conversation with the oracle, each run of agent steps inline, and **Thinking** for
32
+ their reasoning.
33
+ - **Plan**: plan with a panel of agents. **View plan** (`V`) opens the draft in a slide-out, where
34
+ any line takes a comment.
35
+ - **Tasks**: every task across sessions as a list or a board, with its steps, timings and **Resume**.
36
+ - **Issues** and **Git**: plan from an open issue, or have an agent review a pull request read-only.
37
+ Both read GitHub through `gh` and post nothing.
38
+ - **Knowledge**: what each agent has learned about the project, which you can edit, annotate or ask
39
+ about.
40
+
41
+ The rail on the left holds settings, the key list, the theme and sounds. The project switcher
42
+ (`P`) sits in the message box and opens any folder on the machine running bot-lobby. A task running
43
+ in a background session opens its conversation from **Tasks**.
75
44
 
76
45
  | Agent | Does |
77
46
  | --- | --- |
@@ -81,144 +50,16 @@ archiving removes a card immediately, while the List view can still show the arc
81
50
  | QA | The final quality gate, at the depth the change's risk calls for |
82
51
  | RESEARCH | External facts, with sources |
83
52
 
84
- ## Projects
85
-
86
- Click the project name (or press `P`) to switch between running projects or choose **Open folder…**.
87
- The folder browser lists directories on the machine running bot-lobby, not the browser's machine;
88
- you can browse, go to a parent, or enter an absolute path. An existing project is reused; otherwise
89
- a dedicated Pi session starts for the folder's detected project root. It loads this copy of bot-lobby
90
- without other extensions and does not automatically trust project-local resources. Switching projects
91
- reloads the page and discards unsent drafts. Projects opened this way stop when their hosting lobby
92
- stops; opening a folder does not start a task or merge work.
93
-
94
- ## Knowledge
95
-
96
- Each agent keeps what it learns about your project in `.pi/bot-lobby/<Agent>/knowledge/`:
97
- stable facts (`knowledge.md`), its standards (design language, engineering or testing standards),
98
- decisions with their reasons, and a short history of completed tasks. Workers only propose
99
- knowledge and the oracle records it, so nothing gets in unchecked; research stays evidence until
100
- the oracle keeps it. When a file is long, the classifier picks the parts that matter to each step, so prompts
101
- stay short. A task cannot complete while a file is over `knowledge.compactionThreshold` (20,000
102
- characters): the oracle rewrites it shorter, and the version before is kept under `archive/`.
103
-
104
- The **Knowledge** tab shows the files as a tree, from the project to each agent and the model it
105
- runs on. Open a file to edit, add or delete its entries, or leave a note on one ("outdated, we
106
- moved to Redis"). A note travels with its entry into every agent's prompt.
107
-
108
- ![The Knowledge tab: each agent's files, and one open with notes on its entries](.github/screenshots/knowledge.png)
109
-
110
- Ask project questions directly from the **Knowledge** composer. The oracle checks saved knowledge
111
- first, searches the codebase for missing information, and records verified findings in the relevant
112
- agent's knowledge. Answers appear in the side pane; the **Chat / Docs** toggle inside the composer
113
- switches back to the selected document. Questions do not create tasks.
114
-
115
- ## Scripts
116
-
117
- Jobs that come back (seeding data, regenerating fixtures, a set of checks before review) are kept
118
- as scripts in `.pi/bot-lobby/scripts/`, shared by every agent, so a step done once is run the next
119
- time instead of being worked out again, which saves tokens and time. Each is named for what it
120
- does, in snake_case with its language's extension (`seed_public_holidays.py`,
121
- `run_changed_tests.sh`), and its first lines say what it is for and how to run it. The oracle
122
- decides when a step is worth a script and saves it (`action=script`); workers only propose one, and
123
- a replaced script is kept under `archive/`. For each step, the classifier picks the scripts that do part of it
124
- and the agent is told to run them (**Settings → Classifier → Shared scripts**; with it off, scripts
125
- whose names share words with the step are suggested).
126
-
127
- ## Less searching
128
-
129
- Agents spend most of their time finding things, so bot-lobby hands them what it already knows:
130
-
131
- - **Repository map.** Scouts, workers, quick fixes and the planner get the project's layout and the
132
- files that match their step, each with what it says it is for and the names it declares. It is
133
- read from the files themselves, so it needs no model and works with the classifier off
134
- (`workflow.repoMap`).
135
- - **Scout notes.** What a scout found about a file is kept and shown in the map as long as the file is
136
- unchanged, so the next task starts from it. A changed file's note is dropped.
137
- - **Reused scouts.** The same question for the same task on a tree with no changes reuses the earlier
138
- findings instead of running again, for example after a crash and resume (`workflow.reuseScouts`).
139
- - **Line anchors.** Scouts report `path:12-40`, and the oracle copies those anchors into each brief,
140
- so a worker opens the exact place.
141
- - **Tool budget.** A scout is told to wrap up after 60% of `scout.maxToolCalls` (30). Past the limit,
142
- further calls are refused, so it reports with what it has (0 means no limit).
143
-
144
- ## Classifier
145
-
146
- A fast classifier makes the small decisions so the large models don't spend tokens on them: who
147
- sits on the planning panel, a task's size, how hard each step is, which files, knowledge and
148
- scripts it needs, and how much QA a change warrants. It is off until you turn it on in
149
- **Settings → Classifier**, and every decision falls back to plain rules when it is off or fails.
150
-
151
- **Answered by** picks who answers, from the models your pi logins offer:
152
-
153
- - **Jev on a host** (the default): TypeSafe's classifier on OpenCode Zen (free while it lasts),
154
- TypeSafe, OpenRouter or the Vercel AI Gateway.
155
- - **Another classifier model** pi lists for your logins, such as Cloudflare's clef, Liquid's d1,
156
- Upstage's solar-decide or Inception's mercury-decide. These answer the same typed questions natively.
157
- - **Any chat model you are signed in to** (an OpenAI, Anthropic or Google account, an API key,
158
- OpenRouter, …). It answers the same questions as JSON with the least reasoning the model allows.
159
- It is slower and less calibrated than a classifier model, so pick a small, fast one.
160
-
161
- The thresholds in `config.json` are tuned for Jev; raise them if another model decides too eagerly.
162
-
163
53
  ## Keys
164
54
 
165
- The lobby is keyboard-first, and every action button shows its key (`Archive E`, `Delete Del`).
166
- `Alt+1`…`Alt+9` switch tabs, `j` / `k` move through lists, `/` focuses search or the message box,
167
- `p` switches project, `d` flips the theme and `?` lists every key. Alt and Ctrl shortcuts can be
168
- rebound with `lobby.keys`. In Pi, `Alt+G` toggles auto mode and `Ctrl+Shift+M` turns bot-lobby on or off.
169
-
170
- ## Screenshots
171
-
172
- | Planning | Tasks |
173
- | --- | --- |
174
- | ![A planning session: the panel's questions with mockups, and the draft plan](.github/screenshots/plan.png) | ![The task list across sessions, with one task's steps](.github/screenshots/tasks.png) |
175
- | **Thinking** | **Questionnaire** |
176
- | ![The Thinking pop-up: each agent's thoughts, in steps](.github/screenshots/thinking.png) | ![A question with a mockup for each option](.github/screenshots/questionnaire.png) |
177
- | **Issues** | **Git** |
178
- | ![An open issue, ready to plan with the panel](.github/screenshots/issues.png) | ![A pull request with an agent's review](.github/screenshots/git.png) |
55
+ Every action button shows its key. `Alt+1`…`Alt+9` switch tabs, `j` / `k` move through lists, `/`
56
+ focuses search or the message box, `p` switches project, `d` flips the theme and `?` lists every key.
179
57
 
180
58
  ## Configuration
181
59
 
182
60
  Settings live in `~/.pi/bot-lobby/config.json` (`BOT_LOBBY_CONFIG_DIR` moves them), and
183
- `/bot-lobby config` shows what is in effect. Colour themes you import, under a name you choose,
184
- are kept in `themes.json` beside it, so every Pi session and project shows them. Tasks and
61
+ `/bot-lobby config` shows what is in effect. Most are also in the lobby's **Settings**. Tasks and
185
62
  project knowledge stay in `.pi/bot-lobby/` inside your project.
186
63
 
187
-
188
- Requires **Pi 1.0.x** (1.0.1 or later). DEV and DESIGN workers and QA reviewers can use
189
- `delegate_subtasks` for useful, separable work. Delegation is optional. Each parent gets five child
190
- slots total, shared across retries; the classifier selects each child’s model and reasoning effort from its brief, lowering
191
- inference for simple work and raising reasoning for complex work on the configured
192
- model. Children inherit the parent’s role,
193
- permissions, worktree and remaining time. Children report to their parent, which
194
- integrates and verifies the result. Children cannot delegate further. Active
195
- children share `workflow.maxParallelWorkers`; waiting parents do not use those
196
- child slots. Cancelling or finishing a parent stops its children and releases
197
- their file claims. Full reports are saved under `.pi/bot-lobby/delegations/`.
198
-
199
- Every assignment has a 15-minute total allowance (or its shorter configured limit),
200
- including startup, tools, retries, children, compaction and reporting. Per-step
201
- allowances persist across reassignments; only the user can extend them, including
202
- in auto mode. Waiting for user answers pauses clocks.
203
-
204
- In **Tasks**, a step being worked on shows how many agents are on it, for example
205
- **Implement large feature (6 agents working)**. Click the count to see which agent is
206
- doing what, with children under their parent. Queued and finished agents are left out,
207
- and a child finishing does not complete a checklist step.
208
-
209
- The oracle, agents and children compact at settled turn boundaries before context
210
- reaches 64,000 estimated tokens, or earlier at 60% of the model window or Pi's
211
- native reserve threshold. Recent messages and summaries retain unfinished work;
212
- raw session history remains available. A failed summary leaves context intact.
213
- Checkpoints preserve constraints, decisions, changed files, verification, failed
214
- approaches, and next actions. A single large input can exceed the threshold before
215
- the next settled boundary.
216
-
217
- Pi's native MCP, `tool_search` and `codemode` are available. **MCP tools** in each
218
- agent's Settings entry grants exact tool names, one per line, such as
219
- `mcp__github__get_issue`. In `config.json` the same field is `mcpTools: ["mcp__github__get_issue"]`
220
- on `master`, `agents.backend`, `agents.designer`, `agents.qa`, `scout`, `researcher`,
221
- `quickFix` and `planner`. Grants default to empty and children inherit them.
222
- Read-only roles also require the server's `readOnlyHint: true`; hidden tools and
223
- ungranted calls are blocked, including calls nested inside codemode. Configure
224
- server connections through Pi's native MCP settings.
64
+ The [guide](docs/guide.md) covers the rest: delivery and commits, crash recovery, knowledge and
65
+ shared scripts, the classifier, delegation, time limits, compaction and MCP tools.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a-t-h-i/bot-lobby",
3
- "version": "0.6.41",
3
+ "version": "0.6.43",
4
4
  "description": "Structured multi-agent software engineering orchestrator for Pi",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
package/src/lobby/feed.ts CHANGED
@@ -46,6 +46,8 @@ export const MAX_ACTIVITY = 400;
46
46
  export const MAX_THOUGHTS = 40;
47
47
  /** Messages the conversation keeps in memory; earlier ones are loaded from the session when scrolled to. */
48
48
  export const MAX_CHAT = 100;
49
+ /** Queued messages remembered for their delivery; older ones are let go. */
50
+ const MAX_QUEUED = 20;
49
51
  /** Longest thought kept; a streaming thought keeps its newest text. */
50
52
  export const MAX_THOUGHT_TEXT = 4000;
51
53
  /** The streaming reply kept: several panes' worth; past it, whole blocks are dropped from its start. */
@@ -201,6 +203,25 @@ export class LobbyFeed {
201
203
  this.touch();
202
204
  }
203
205
 
206
+ /** What the user sent while the oracle was busy: shown at once, so its delivery later is not shown again. */
207
+ private queued: string[] = [];
208
+
209
+ /** Show a message the oracle will only read once its current turn lets it in (a steer). */
210
+ sayQueued(text: string, at = Date.now()): void {
211
+ const body = text.trim();
212
+ if (!body) return;
213
+ this.queued = [...this.queued, body].slice(-MAX_QUEUED);
214
+ this.say("you", body, at);
215
+ }
216
+
217
+ /** Whether `text` is a queued message already on show; it is forgotten once delivered. */
218
+ takeQueued(text: string): boolean {
219
+ const index = this.queued.indexOf(text.trim());
220
+ if (index < 0) return false;
221
+ this.queued.splice(index, 1);
222
+ return true;
223
+ }
224
+
204
225
  say(role: ChatRole, text: string, at = Date.now()): void {
205
226
  const body = text.trim();
206
227
  if (!body) return;
@@ -408,7 +429,11 @@ export function narrateEvent(feed: LobbyFeed, event: AgentEventLike, describe: (
408
429
  }
409
430
  }
410
431
  if (message.role !== "user" && message.role !== "assistant") return;
411
- for (const line of chatText(message.role, textOf(message.content))) feed.say(line.role, line.text);
432
+ for (const line of chatText(message.role, textOf(message.content))) {
433
+ // A steer was shown when it was sent; its delivery is the same message.
434
+ if (line.role === "you" && feed.takeQueued(line.text)) continue;
435
+ feed.say(line.role, line.text);
436
+ }
412
437
  return;
413
438
  }
414
439
  case "agent_end":
package/src/lobby/keys.ts CHANGED
@@ -9,8 +9,8 @@ export const LOBBY_ACTIONS = {
9
9
  help: { key: "alt+h", help: "show or hide this list" },
10
10
  settings: { key: "alt+s", help: "settings: each agent's model and effort" },
11
11
  savePlan: { key: "ctrl+s", help: "save the plan from the Plan tab" },
12
- sessions: { key: "alt+o", help: "browse and message your sessions" },
13
- activity: { key: "alt+a", help: "show or hide Activity on the Lobby" },
12
+ sidebar: { key: "alt+b", help: "open the sidebar on a phone" },
13
+ activity: { key: "alt+a", help: "open or fold every step in the Lobby conversation" },
14
14
  thinking: { key: "alt+t", help: "show or hide Thinking on the Lobby" },
15
15
  nextTab: { key: "alt+]", help: "next tab" },
16
16
  prevTab: { key: "alt+[", help: "previous tab" },
@@ -151,6 +151,8 @@ function toOracle(state: Runtime, text: string): string | undefined {
151
151
  return "reading your request — a quick fix or a task, the oracle takes it from here";
152
152
  }
153
153
  state.pi.sendUserMessage(text, busy ? { deliverAs: "steer" } : undefined);
154
+ // A steer reaches the oracle only when its turn lets it in; the conversation shows it now.
155
+ if (busy) lobbyFeed.sayQueued(text);
154
156
  return undefined;
155
157
  }
156
158