@parallel-cli/parallel 0.4.5 → 0.4.7

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
@@ -2,6 +2,59 @@
2
2
 
3
3
  All notable changes to Parallel are documented here.
4
4
 
5
+ ## 0.4.7 - 2026-06-24
6
+
7
+ ### 0.4.7 Added
8
+
9
+ - Added file revision safety for shared-tree co-editing so stale `write_file` retries and `edit_file` calls must re-read and merge concurrent work before mutating.
10
+ - Added immediate agent-to-agent note nudging with duplicate-note suppression, active-agent checks, and rate-limit safeguards.
11
+ - Added visible coordination signals in the Hub, `/board`, `/diff`, and timelines for claims, work-map warnings, notes, approvals, and questions.
12
+ - Added `/review [agent|all] [prompt]`, a lightweight ask-mode reviewer that returns `APPROVE`, `REVISE`, or `BLOCK` with risks, tests to run, and files to inspect.
13
+ - Added Cursor-style per-agent progress steps through `update_steps`, visible in the Hub and attached terminals.
14
+ - Added batched read-only inspection tools (`read_many`, `inspect_project`) plus lightweight performance counters for model turns, tool calls, shell commands, and context usage.
15
+
16
+ ### 0.4.7 Changed
17
+
18
+ - Reworked `/board` into a coordination surface with Work map warnings first, agent/path/time metadata, and suggestions to inspect `/focus` or `/diff`.
19
+ - Prioritized incoming notes and work-map context in agent live context so coordination updates are handled before ordinary activity.
20
+ - Updated product messaging around shared awareness: agents work like a live team on one working tree, not isolated background jobs.
21
+ - Reworked agent rows to keep the Hub compact with cropped summaries, cream bullet recaps capped at four lines, mode badges, and visible `full /focus aN` plus `term /attach aN` shortcuts.
22
+ - Reworked dedicated agent terminals with a launch header, hidden raw launch noise in normal mode, append-only final results, and a small live status region so native scrollback remains usable.
23
+ - Tuned agent prompts by mode so `/ask`, `/task`, `/plan`, and `/review` use clearer contracts, early progress steps, batched inspection, and less redundant shell micro-commanding.
24
+
25
+ ### 0.4.7 Fixed
26
+
27
+ - Fixed the previous collision retry weakness where a stale writer could receive an adaptation diff and then overwrite without a real re-read.
28
+ - Fixed `edit_file` allowing targeted edits on a stale file as long as `old_string` still existed.
29
+ - Fixed timeline narration being hardcoded in French by routing narration through i18n.
30
+ - Fixed `claim_files` appearing as generic file activity instead of coordination activity.
31
+ - Fixed completed attached terminals repainting large dynamic result panels that could trap mouse-wheel scroll at the top.
32
+
33
+ ## 0.4.6 - 2026-06-24
34
+
35
+ ### 0.4.6 Added
36
+
37
+ - Added an interactive npm update prompt on startup with daily cache, CI/headless/attach skips, `PARALLEL_SKIP_UPDATE_CHECK=1`, and `--no-update`.
38
+ - Added a Codex-like empty hub with a quieter framed header, cream-toned accents, and a full-width prompt block with distinct background.
39
+ - Added a complete paginated slash palette driven by one deterministic rendered order.
40
+ - Added selectable `/help` command navigation with visible highlight and Enter-to-run behavior.
41
+ - Added localized prompt placeholder copy and an i18n audit to keep all used UI keys translated.
42
+
43
+ ### 0.4.6 Changed
44
+
45
+ - Reduced default Hub noise by removing persistent startup toasts, duplicate task hints, and always-on command footer lines.
46
+ - Replaced blue/cyan UI accents with a softer cream theme across hub, palettes, wizard/settings lists, markdown summaries, and attached agent terminals.
47
+ - Made the prompt block start at three rows, grow when input wraps, and show the blinking cursor on the first placeholder character while empty.
48
+ - Reused the same minimal prompt treatment in dedicated agent terminals and toned down their footer.
49
+ - Simplified agent rows so secondary telemetry only appears when there is a useful latest signal or result.
50
+ - Moved command palette priority to shared command helpers so autocomplete, help, and rendering stay aligned.
51
+
52
+ ### 0.4.6 Fixed
53
+
54
+ - Fixed slash palette Up/Down navigation jumping to visually unrelated commands.
55
+ - Fixed `/help` being scrollable but not actually selectable.
56
+ - Fixed Wizard and Settings selection lists wrapping around unexpectedly by clamping navigation at list boundaries.
57
+
5
58
  ## 0.4.5 - 2026-06-23
6
59
 
7
60
  ### 0.4.5 Added
package/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # Parallel
2
2
 
3
- Real-time multi-agent coding from one terminal control room.
3
+ Real-time coding agents that work like a live team, not isolated background jobs.
4
4
 
5
- Parallel lets you run several AI coding agents on the same repository at the same time. Each agent has its own task, mode, live activity timeline, model, and shared session context. The TUI stays keyboard-first so you can launch work, inspect progress, answer approvals, steer agents, and review changes without leaving the terminal.
5
+ Parallel lets several AI coding agents co-edit the same repository at the same time with shared awareness injected before every model action. Each agent has its own task, mode, live activity timeline, model, and visible coordination context. The TUI stays keyboard-first so you can launch work, inspect progress, answer approvals, steer agents, review risks, and reconcile changes without leaving the terminal.
6
6
 
7
- > One hub. Many agents. Shared context. Human in control.
7
+ > One working tree. Many agents. Shared awareness. Human in control.
8
8
 
9
9
  [![npm version](https://img.shields.io/npm/v/@parallel-cli/parallel?color=blue)](https://www.npmjs.com/package/@parallel-cli/parallel)
10
10
  ![node version](https://img.shields.io/node/v/@parallel-cli/parallel)
@@ -13,19 +13,24 @@ Parallel lets you run several AI coding agents on the same repository at the sam
13
13
 
14
14
  ## Highlights
15
15
 
16
- - Run multiple agents in parallel on one project.
17
- - Choose explicit modes: `/ask`, `/task`, and `/plan`.
16
+ - Run multiple agents as a live team on one shared working tree.
17
+ - Choose explicit modes: `/ask`, `/task`, `/plan`, and `/review`.
18
18
  - Type plain text to launch a task agent immediately.
19
19
  - Use context-aware input in the hub, focus view, and attached agent terminals.
20
20
  - Steer one agent with `@a1 ...` or broadcast with `@all ...`.
21
21
  - Open dedicated agent terminals with native scrollback.
22
- - See a richer live hub with latest agent signals, mode badges, context usage, and responsive timelines.
22
+ - Use a cleaner Codex-like hub with a framed header, focused prompt bar, and quieter empty state.
23
23
  - Review agents, notes, file activity, diffs, cost, skills, specialists, and saved sessions from the TUI.
24
+ - Use `/review [agent|all]` to spawn a lightweight ask-mode reviewer with verdict, risks, tests, and files to inspect.
25
+ - Avoid lost work with file revision safety: stale `write_file` and `edit_file` calls must re-read and merge before retrying.
26
+ - Nudge agents immediately when another agent posts a targeted note, with dedupe and rate-limit safeguards.
27
+ - See overlapping claims and repeated co-edit conflicts in the Hub, `/board`, `/diff`, and agent timelines.
24
28
  - Track shell-created file mutations in the same live diff feed as agent edits.
25
29
  - Configure OpenAI-compatible providers through a guided wizard and settings panel.
26
30
  - Use 29 provider presets across Western, Chinese, Gateway, Inference, and Local categories.
27
31
  - Support local no-key endpoints such as Ollama and vLLM/SGLang.
28
32
  - Keep shell execution controlled with `ask`, `auto-safe`, or `yolo` approvals.
33
+ - Get prompted for npm updates at startup, with an explicit skip path.
29
34
  - Save and restore project sessions.
30
35
  - Run headless multi-agent jobs for CI or scripts.
31
36
 
@@ -85,6 +90,7 @@ Use explicit modes when intent matters:
85
90
  /ask Reviewer: should we split the CLI parser?
86
91
  /plan Migration: propose the safest rollout for the config change
87
92
  /task Builder: implement the approved plan
93
+ /review all before we commit
88
94
  ```
89
95
 
90
96
  Steer a running agent:
@@ -101,11 +107,36 @@ Broadcast to every agent:
101
107
 
102
108
  `@all` steers active agents in real time. Finished, stopped, or errored agents are not relaunched by a broadcast.
103
109
 
110
+ ## Best Use Case: Coupled Work
111
+
112
+ Parallel is strongest when the work is too coupled for isolated fan-out and too large for one agent.
113
+
114
+ Example live-team flow:
115
+
116
+ ```text
117
+ /task API: define the new billing quote contract in src/api/quotes.ts
118
+ /task Client: build the UI client against the quote contract
119
+ /task Tests: write integration coverage for quote creation and validation
120
+ ```
121
+
122
+ The API agent can claim `src/api`, post a note with the proposed signature, and update the contract. The client agent sees that note and the diff before its next model action, re-reads the file, and adapts without inventing a second interface. The tests agent watches both sides, adds coverage, and can ask for clarification before the three agents collide.
123
+
124
+ Before committing:
125
+
126
+ ```text
127
+ /review all verify the API contract, client usage, and tests agree
128
+ ```
129
+
130
+ The reviewer is ask-only: it does not edit, does not gate the session globally, and returns a structured verdict with risks and validation steps.
131
+
104
132
  ## Agent Modes
105
133
 
106
134
  - `/ask`: questions, reviews, audits, and tradeoffs. The agent answers and advises; mutating tools and shell commands are blocked.
107
- - `/task`: implementation work. The agent can execute, edit, validate, and summarize.
135
+ - `/task`: implementation work. The agent can execute, edit, validate, and summarize. It may also conclude that no file change is needed when the task is a verification.
108
136
  - `/plan`: risky or unclear work. The agent inspects first, presents a plan, then edits only after explicit approval. A timeout does not approve the plan.
137
+ - `/review`: lightweight reviewer around `/ask`. It inspects the current shared-tree work and returns `APPROVE`, `REVISE`, or `BLOCK` with risks, tests to run, and files to inspect.
138
+
139
+ Task and plan agents maintain a small Cursor-style checklist with one active step at a time. The runtime also encourages batched inspection through `read_many` and `inspect_project` so agents avoid slow chains of tiny read-only shell commands.
109
140
 
110
141
  Aliases:
111
142
 
@@ -117,7 +148,9 @@ Plain text is equivalent to `/task`.
117
148
 
118
149
  ## Control Room
119
150
 
120
- The main TUI is the Parallel hub. It is designed to answer:
151
+ The main TUI is the Parallel hub. The default view stays intentionally quiet: a Codex-like framed header, cream-toned accents, a focused prompt block, compact cropped agent rows, and detailed status moved into explicit views.
152
+
153
+ It is designed to answer:
121
154
 
122
155
  - what needs your input
123
156
  - which agents are working
@@ -125,11 +158,16 @@ The main TUI is the Parallel hub. It is designed to answer:
125
158
  - what changed in the project
126
159
  - what model, provider, shell mode, and cost are active
127
160
 
161
+ Agent rows stay compact even when summaries are long. Use the row shortcuts to expand the right level of detail:
162
+
163
+ - `full /focus a1`: open the full in-Hub transcript and result for one agent.
164
+ - `term /attach a1`: reopen that agent's dedicated terminal.
165
+
128
166
  Input has three explicit contexts:
129
167
 
130
168
  - Hub: plain text launches a new `/task` agent. Slash suggestions show hub commands and agent arguments autocomplete for `/focus`, `/send`, `/attach`, `/pause`, `/resume`, `/stop`, `/restore`, and `/commit`.
131
169
  - Focus: after `/focus a1`, plain text talks to the focused agent instead of spawning a new one. `/raw` affects this view only.
132
- - Attach: in `parallel attach a1`, plain text steers the attached agent. `/task`, `/ask`, and `/plan` spawn new agents from that terminal, while `@all ...`, `@a2 ...`, and `/send ...` route instructions through the main session.
170
+ - Attach: in `parallel attach a1`, the same minimal prompt UI steers the attached agent. `/task`, `/ask`, and `/plan` spawn new agents from that terminal, while `@all ...`, `@a2 ...`, and `/send ...` route instructions through the main session.
133
171
 
134
172
  Use `Name: task` when naming an agent:
135
173
 
@@ -143,6 +181,8 @@ Common hub commands:
143
181
  - `/agents`: agent overview.
144
182
  - `/focus a1`: inspect and steer one agent.
145
183
  - `/raw`: toggle raw detail in focus view.
184
+ - `/attach a1`: open or reopen an agent's dedicated terminal.
185
+ - `/review all`: ask-mode reviewer with verdict, risks, tests, and files to inspect.
146
186
  - `/board`: shared blackboard, claims, notes, and file activity.
147
187
  - `/diff`: live diff history.
148
188
  - `/cost`: token and cost breakdown.
@@ -157,9 +197,11 @@ Commands are typed in the control room input. When a long view is open, use Esca
157
197
  Keyboard behavior:
158
198
 
159
199
  - `/` opens slash command suggestions.
160
- - Up/Down selects suggestions when a suggestion menu is open.
200
+ - Up/Down selects suggestions in the same order they appear.
161
201
  - Enter accepts the selected suggestion.
162
202
  - Tab or Right accepts the best completion.
203
+ - `/help` is keyboard navigable: Up/Down moves the visible selection, PgUp/PgDn pages, and Enter runs the selected command.
204
+ - Wizard, settings, slash suggestions, and help views use clamped keyboard selection so the highlight does not jump, disappear, or wrap unexpectedly.
163
205
  - PgUp/PgDn scrolls the hub or focus view even while the input is active. Up/Down scrolls long views and navigates suggestions/history.
164
206
  - Escape returns to the agents view or clears the input.
165
207
 
@@ -175,8 +217,10 @@ parallel attach a1 --root .
175
217
 
176
218
  Attached terminals show:
177
219
 
220
+ - a launch header with agent, mode, model, and task
178
221
  - the selected agent's live timeline
179
222
  - native terminal scrollback
223
+ - append-only final results after `done`, `error`, or `stopped`
180
224
  - model, elapsed time, context, and cost
181
225
  - other agents' current state
182
226
  - approval and question prompts for that agent
@@ -192,6 +236,7 @@ plain text sends a message to this agent
192
236
  /task Tests: write parser regression tests
193
237
  /ask Reviewer: is this result safe to merge?
194
238
  /plan Migration: prepare a migration plan
239
+ /review all before commit
195
240
  /raw
196
241
  /quit
197
242
  ```
@@ -239,6 +284,19 @@ Environment variables:
239
284
  - `PARALLEL_BASE_URL`: override the default provider base URL.
240
285
  - `PARALLEL_MODEL`: override the session model.
241
286
  - `PARALLEL_NO_ALT_SCREEN=1`: disable the alternate terminal screen.
287
+ - `PARALLEL_SKIP_UPDATE_CHECK=1`: disable npm update checks.
288
+
289
+ ## Updates
290
+
291
+ On interactive startup, Parallel checks npm at most once per day for a newer `@parallel-cli/parallel` version. The check is skipped in `attach`, `--headless`, `--first-run`, CI, non-TTY sessions, or when `PARALLEL_SKIP_UPDATE_CHECK=1` is set.
292
+
293
+ When an update is available, Parallel asks before running:
294
+
295
+ ```bash
296
+ npm install -g @parallel-cli/parallel
297
+ ```
298
+
299
+ If the update succeeds, restart Parallel to run the new version. Use `parallel --no-update` for a one-off launch without checking.
242
300
 
243
301
  ## Commands
244
302
 
@@ -247,6 +305,7 @@ Environment variables:
247
305
  - `/ask [Name:] <question> [--model=m]`: launch an ask-only agent.
248
306
  - `/task [Name:] <task> [--model=m] [#skill]`: launch a task agent. Plain text does the same.
249
307
  - `/plan [Name:] <task> [--model=m]`: launch a plan-first agent. It cannot mutate files or run risky shell commands until you manually approve the plan.
308
+ - `/review [agent|all] [prompt]`: launch a lightweight ask-mode reviewer for one agent or the whole shared tree.
250
309
  - `/issue <n>`: spawn a task from a GitHub issue. Requires the `gh` CLI, a GitHub repository, and `gh auth login`.
251
310
  - `/specialist <name> <task>`: spawn with a specialist persona.
252
311
  - `/specialist new <name> [global]`: create a specialist template.
@@ -275,7 +334,7 @@ Environment variables:
275
334
  ### Views And Sessions
276
335
 
277
336
  - `/agents`: agent overview.
278
- - `/board`: shared blackboard, file activity, claims, and notes.
337
+ - `/board`: shared blackboard, work-map warnings, claims, file activity, and notes.
279
338
  - `/notes`: full notes history.
280
339
  - `/diff`: live diff history.
281
340
  - `/cost`: token and cost breakdown.
@@ -357,15 +416,21 @@ When an agent writes a file:
357
416
 
358
417
  1. Parallel checks whether the file changed since that agent last read it.
359
418
  2. If the file is unchanged, the write proceeds.
360
- 3. If another agent changed it, the write is rejected once.
361
- 4. The agent receives the other change as context, re-reads the file, merges both intentions, and retries.
419
+ 3. If another agent or shell command changed it, the write is rejected with an adaptation diff.
420
+ 4. The stale baseline is not silently synchronized. The agent must call `read_file`, merge both intentions on top of the current revision, and retry.
362
421
 
363
- This keeps agents moving without allowing silent overwrites.
422
+ The same stale-read guard applies to `edit_file`, even when `old_string` still exists. This keeps agents moving without allowing silent overwrites.
364
423
 
365
424
  Commands run through `run_command` are also snapshotted before and after execution. If a shell command edits, creates, or deletes tracked project files, Parallel records those mutations in `/diff`, `/board`, and `/commit` ownership just like tool-based edits.
366
425
 
367
426
  The work map is advisory, not a lock. Agents can declare claims with `claim_files`; Parallel detects overlapping claims and repeated conflicts, then shows non-blocking warnings in `/board` and injects them into agent context so agents can coordinate before collisions become expensive.
368
427
 
428
+ ## Shared-Tree Vs Isolated Agents
429
+
430
+ Use Parallel's shared-tree mode when agents need to negotiate live contracts: API and client, schema and tests, parser and docs, or any change where one agent's edit should affect another agent's next step.
431
+
432
+ Use isolated agents or separate worktrees for embarrassingly parallel work: unrelated files, independent chores, or experiments you only want to merge after review. Parallel's identity is the shared-tree team workflow; isolation is a future complement, not the default.
433
+
369
434
  ## Headless Mode
370
435
 
371
436
  For CI and scripts, run without the TUI:
@@ -19,12 +19,14 @@ AGENT MODE: ${mode}
19
19
  ${mode === 'ask'
20
20
  ? `ASK MODE:
21
21
  - You are advisory only. Do not modify files.
22
- - You may inspect with list_files/read_file/search and safe read-only commands when useful.
22
+ - Prefer search/read_file/read_many/inspect_project over shell. Use safe read-only commands only when internal tools are insufficient.
23
+ - Keep the investigation short and targeted. Do not run heavy validation loops unless the user explicitly asks.
23
24
  - Do not run mutating commands, write files, edit files, claim files, or commit.
24
25
  - Finish with task_complete using this user-facing structure in ${userLang}: "Réponse courte", "Recommandation", "Pourquoi", "Prochaines étapes".`
25
26
  : mode === 'plan'
26
27
  ? `PLAN MODE:
27
28
  - Explore first with read-only tools.
29
+ - Batch independent reads/searches with read_many or inspect_project. Keep exploration broad enough to be correct but bounded.
28
30
  - Before modifying any file or running mutating commands, call ask_user with a concrete implementation plan.
29
31
  - The plan must include steps, files you expect to touch, risks, and validation.
30
32
  - Use options ["Approve", "Revise"], recommended "Revise" so timeout never approves changes.
@@ -32,7 +34,8 @@ ${mode === 'ask'
32
34
  - Finish with task_complete using this user-facing structure in ${userLang}: "Plan appliqué", "Ce que j’ai modifié", "Validation", "Risques restants".`
33
35
  : `TASK MODE:
34
36
  - Execute the user's objective end-to-end.
35
- - Explore, edit, validate, and summarize.
37
+ - Use this loop: create visible steps, batch inspect, act, batch validate, summarize.
38
+ - If the task is a verification/audit and the correct outcome is no file changes, that is valid task work. Say explicitly in task_complete that no modification was necessary and why.
36
39
  - Ask the user only when blocked or when a risky product decision cannot be inferred.
37
40
  - Finish with task_complete using this user-facing structure in ${userLang}: "Ce que j’ai fait", "Ce que j’ai vérifié", "Résultat", "Détails techniques".`}
38
41
  ${skillsList
@@ -59,13 +62,16 @@ PARALLEL'S PHILOSOPHY — REAL-TIME CO-EDITING, NEVER ANY BLOCKING:
59
62
  8. MAKE THE SHARED AWARENESS VISIBLE: when another agent's work influenced a decision of yours (you reused their function, adapted to their diff, avoided their work area), SAY IT explicitly — in a post_note to them ("I saw you changed X, so I did Y") and in your task_complete summary (name the agent and what you built on). The user must be able to SEE that you worked as a team, not as isolated bots.
60
63
 
61
64
  WORK METHOD:
62
- - Explore first (list_files, read_file, search) before modifying.
65
+ - For non-trivial work, call update_steps early with 3-6 concrete steps. Keep exactly one step active and mark steps done as you complete them.
66
+ - Explore first before modifying. Decide all independent reads/searches you need, then batch them with read_many or inspect_project instead of calling tools one by one.
67
+ - Use run_command for builds/tests/validation and genuinely useful shell scripts. Do NOT spend many turns running grep/head/tail/wc/awk cascades; batch independent shell checks into one labelled command or use inspect_project.
63
68
  - Declare your work area with claim_files when you start (and when it changes): it prevents collisions without ever locking anything.
64
69
  - If you discover a durable, non-obvious fact about the project (convention, decision, pitfall), save it with remember(fact) for future agents.
65
70
  - wait_for_agent exists for hard dependencies only — prefer progressing on another part of your task over waiting.
66
71
  - Prefer edit_file (targeted changes) over write_file (full rewrite): targeted edits coexist better in parallel.
67
72
  - Make minimal changes; do not rewrite what already works.
68
73
  - Verify your work when relevant (run_command for tests/build), then finish with task_complete.
74
+ - Performance discipline: minimize model turns. If multiple tool calls are independent, make them in the same assistant turn. If several shell checks are independent, run one labelled command.
69
75
  - The task_complete summary is user-facing. Make it structured and specific in ${userLang}, not just "done":
70
76
  1. What I did — concrete outcome in 1-2 sentences.
71
77
  2. Files changed or inspected — mention paths when relevant.
@@ -76,6 +82,29 @@ WORK METHOD:
76
82
  LANGUAGE: write notes addressed to "user" and your task_complete summary in ${userLang}. Notes to other agents and code stay in English.`;
77
83
  /** Assumed context window (tokens) when the provider does not advertise one. */
78
84
  const CONTEXT_WINDOW = 128_000;
85
+ const EMPTY_PERF = {
86
+ modelTurns: 0,
87
+ toolCalls: 0,
88
+ shellCommands: 0,
89
+ shellMs: 0,
90
+ readOnlyShellCommands: 0,
91
+ };
92
+ function noChangeTaskLine() {
93
+ switch (getLang()) {
94
+ case 'fr':
95
+ return 'Mode task: vérification sans changement de fichier nécessaire.';
96
+ case 'es':
97
+ return 'Modo task: verificación sin cambios de archivos necesarios.';
98
+ case 'zh':
99
+ return 'Task 模式:已完成验证,无需修改文件。';
100
+ case 'en':
101
+ default:
102
+ return 'Task mode: verification completed with no file changes needed.';
103
+ }
104
+ }
105
+ function isReadOnlyShell(command) {
106
+ return /\b(grep|rg|head|tail|wc|awk|sed|cat|ls|find)\b/.test(command) && !/[>|;]/.test(command);
107
+ }
79
108
  export class Agent {
80
109
  opts;
81
110
  id;
@@ -90,6 +119,7 @@ export class Agent {
90
119
  stopped = false;
91
120
  lastNoteId = 0;
92
121
  lastChangeId = 0;
122
+ readOnlyShellStreak = 0;
93
123
  constructor(opts) {
94
124
  this.opts = opts;
95
125
  this.id = opts.id;
@@ -114,6 +144,8 @@ export class Agent {
114
144
  cost: opts.price ? 0 : null,
115
145
  startedAt: Date.now(),
116
146
  specialist: opts.specialist?.name,
147
+ progressSteps: [],
148
+ perf: { ...EMPTY_PERF },
117
149
  };
118
150
  this.board.registerAgent(info);
119
151
  // Skip notes/changes that existed before this agent was born
@@ -165,9 +197,13 @@ export class Agent {
165
197
  * A note addressed to this agent just arrived: interrupt the current model
166
198
  * call so the next turn (which injects unread notes) starts immediately.
167
199
  */
168
- nudge() {
200
+ nudge(reason = 'reading team update') {
201
+ if (this.finished || this.stopped || this.paused)
202
+ return false;
169
203
  this.steered = true;
204
+ this.board.setAgentState(this.id, 'listening', reason);
170
205
  this.llmAbort?.abort();
206
+ return true;
171
207
  }
172
208
  /**
173
209
  * Append a message to the in-memory history AND to the conversation file
@@ -189,6 +225,18 @@ export class Agent {
189
225
  await new Promise((r) => setTimeout(r, 300));
190
226
  }
191
227
  }
228
+ updatePerf(delta) {
229
+ const current = this.board.agents.get(this.id)?.perf ?? EMPTY_PERF;
230
+ this.board.updateAgent(this.id, {
231
+ perf: {
232
+ modelTurns: current.modelTurns + (delta.modelTurns ?? 0),
233
+ toolCalls: current.toolCalls + (delta.toolCalls ?? 0),
234
+ shellCommands: current.shellCommands + (delta.shellCommands ?? 0),
235
+ shellMs: current.shellMs + (delta.shellMs ?? 0),
236
+ readOnlyShellCommands: current.readOnlyShellCommands + (delta.readOnlyShellCommands ?? 0),
237
+ },
238
+ });
239
+ }
192
240
  /**
193
241
  * Build the live context injected before EVERY model call:
194
242
  * other agents' status + their fresh diffs + unread notes.
@@ -197,6 +245,15 @@ export class Agent {
197
245
  liveContext() {
198
246
  let hasNews = false;
199
247
  const parts = ['[REAL TIME]', this.board.snapshotFor(this.id)];
248
+ const notes = this.board.notesFor(this.name, this.lastNoteId);
249
+ if (notes.length > 0) {
250
+ this.lastNoteId = notes[notes.length - 1].id;
251
+ hasNews = true;
252
+ parts.push('\n[PRIORITY NOTES RECEIVED — take them into account now]');
253
+ for (const n of notes) {
254
+ parts.push(` • from ${n.from}: ${n.content}`);
255
+ }
256
+ }
200
257
  const changes = this.board.changesSince(this.id, this.lastChangeId);
201
258
  if (changes.length > 0) {
202
259
  this.lastChangeId = changes[changes.length - 1].id;
@@ -219,15 +276,6 @@ export class Agent {
219
276
  }
220
277
  parts.push('Analyze these diffs: if any of them touches your work area, re-read the affected file and adapt. NEVER undo these changes.');
221
278
  }
222
- const notes = this.board.notesFor(this.name, this.lastNoteId);
223
- if (notes.length > 0) {
224
- this.lastNoteId = notes[notes.length - 1].id;
225
- hasNews = true;
226
- parts.push('\n[NOTES RECEIVED — take them into account now]');
227
- for (const n of notes) {
228
- parts.push(` • from ${n.from}: ${n.content}`);
229
- }
230
- }
231
279
  parts.push('\nContinue your task taking the above into account. Use tools, or task_complete if finished.');
232
280
  return { text: parts.join('\n'), hasNews };
233
281
  }
@@ -322,6 +370,7 @@ export class Agent {
322
370
  this.llmAbort = null;
323
371
  }
324
372
  this.steered = false;
373
+ this.updatePerf({ modelTurns: 1 });
325
374
  const a = this.board.agents.get(this.id);
326
375
  if (a) {
327
376
  // Real-time financial view: accrue the cost of this round immediately.
@@ -378,11 +427,40 @@ export class Agent {
378
427
  this.board.log(this.id, 'tool', label);
379
428
  }
380
429
  this.board.updateAgent(this.id, { currentAction: label.slice(0, 80) });
430
+ const shellStartedAt = tc.function.name === 'run_command' ? Date.now() : 0;
381
431
  const result = await this.executor.execute(tc.function.name, args);
432
+ const shellMs = shellStartedAt ? Date.now() - shellStartedAt : 0;
433
+ const readOnlyShell = tc.function.name === 'run_command' && isReadOnlyShell(String(args.command ?? ''));
434
+ this.updatePerf({
435
+ toolCalls: 1,
436
+ shellCommands: tc.function.name === 'run_command' ? 1 : 0,
437
+ shellMs,
438
+ readOnlyShellCommands: readOnlyShell ? 1 : 0,
439
+ });
440
+ if (readOnlyShell) {
441
+ this.readOnlyShellStreak++;
442
+ if (this.readOnlyShellStreak >= 3) {
443
+ this.record({
444
+ role: 'user',
445
+ content: '[PERFORMANCE CORRECTION] You are using several read-only shell micro-commands. Batch the next inspection with read_many/inspect_project or a single labelled shell command, then continue.',
446
+ });
447
+ this.readOnlyShellStreak = 0;
448
+ }
449
+ }
450
+ else if (tc.function.name !== 'update_status' && tc.function.name !== 'update_steps') {
451
+ this.readOnlyShellStreak = 0;
452
+ }
382
453
  if (result === '__TASK_COMPLETE__') {
383
454
  completed = true;
384
455
  const summary = String(args.summary ?? 'Task complete.');
385
- this.board.updateAgent(this.id, { lastResult: summary });
456
+ const changedByThisAgent = this.board.changes.filter((c) => c.agentId === this.id).length;
457
+ const noChangePrefix = this.opts.mode === 'task' && changedByThisAgent === 0
458
+ ? `${noChangeTaskLine()}\n\n`
459
+ : '';
460
+ this.board.updateAgent(this.id, {
461
+ lastResult: `${noChangePrefix}${summary}`,
462
+ progressSteps: (this.board.agents.get(this.id)?.progressSteps ?? []).map((s) => ({ ...s, status: 'done' })),
463
+ });
386
464
  // ONE short headline note (the full summary lives in lastResult and
387
465
  // is rendered as the agent's recap) — no duplicated walls of text.
388
466
  const headline = summary.split('\n').find((l) => l.trim())?.trim() ?? 'Task complete.';
@@ -419,6 +497,8 @@ export class Agent {
419
497
  switch (name) {
420
498
  case 'read_file':
421
499
  return `📖 read ${args.path}`;
500
+ case 'read_many':
501
+ return `📚 read ${Array.isArray(args.paths) ? args.paths.slice(0, 3).join(', ') : 'files'}`;
422
502
  case 'write_file':
423
503
  return `✏ write ${args.path}`;
424
504
  case 'edit_file':
@@ -427,12 +507,16 @@ export class Agent {
427
507
  return `📁 ls ${args.path ?? '.'}`;
428
508
  case 'search':
429
509
  return `🔍 search /${args.pattern}/`;
510
+ case 'inspect_project':
511
+ return `🔎 inspect project`;
430
512
  case 'run_command':
431
513
  return `$ ${args.command}`;
432
514
  case 'post_note':
433
515
  return `✉ note → ${args.to}`;
434
516
  case 'update_status':
435
517
  return `📢 ${args.status}`;
518
+ case 'update_steps':
519
+ return `☑ update steps`;
436
520
  case 'ask_user':
437
521
  return `❓ ${String(args.question ?? '').slice(0, 60)}`;
438
522
  case 'load_skill':