@melihmucuk/pi-crew 1.0.0

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 (52) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +199 -0
  3. package/agents/code-reviewer.md +145 -0
  4. package/agents/planner.md +142 -0
  5. package/agents/quality-reviewer.md +164 -0
  6. package/agents/scout.md +58 -0
  7. package/agents/worker.md +81 -0
  8. package/dist/agent-discovery.d.ts +34 -0
  9. package/dist/agent-discovery.js +527 -0
  10. package/dist/bootstrap-session.d.ts +11 -0
  11. package/dist/bootstrap-session.js +63 -0
  12. package/dist/crew-manager.d.ts +43 -0
  13. package/dist/crew-manager.js +235 -0
  14. package/dist/index.d.ts +2 -0
  15. package/dist/index.js +27 -0
  16. package/dist/integration/register-command.d.ts +3 -0
  17. package/dist/integration/register-command.js +51 -0
  18. package/dist/integration/register-renderers.d.ts +2 -0
  19. package/dist/integration/register-renderers.js +50 -0
  20. package/dist/integration/register-tools.d.ts +3 -0
  21. package/dist/integration/register-tools.js +25 -0
  22. package/dist/integration/tool-presentation.d.ts +30 -0
  23. package/dist/integration/tool-presentation.js +29 -0
  24. package/dist/integration/tools/crew-abort.d.ts +2 -0
  25. package/dist/integration/tools/crew-abort.js +79 -0
  26. package/dist/integration/tools/crew-done.d.ts +2 -0
  27. package/dist/integration/tools/crew-done.js +28 -0
  28. package/dist/integration/tools/crew-list.d.ts +2 -0
  29. package/dist/integration/tools/crew-list.js +72 -0
  30. package/dist/integration/tools/crew-respond.d.ts +2 -0
  31. package/dist/integration/tools/crew-respond.js +30 -0
  32. package/dist/integration/tools/crew-spawn.d.ts +2 -0
  33. package/dist/integration/tools/crew-spawn.js +42 -0
  34. package/dist/integration/tools/tool-deps.d.ts +8 -0
  35. package/dist/integration/tools/tool-deps.js +1 -0
  36. package/dist/integration.d.ts +3 -0
  37. package/dist/integration.js +8 -0
  38. package/dist/runtime/delivery-coordinator.d.ts +17 -0
  39. package/dist/runtime/delivery-coordinator.js +60 -0
  40. package/dist/runtime/subagent-registry.d.ts +13 -0
  41. package/dist/runtime/subagent-registry.js +55 -0
  42. package/dist/runtime/subagent-state.d.ts +34 -0
  43. package/dist/runtime/subagent-state.js +34 -0
  44. package/dist/status-widget.d.ts +3 -0
  45. package/dist/status-widget.js +84 -0
  46. package/dist/subagent-messages.d.ts +30 -0
  47. package/dist/subagent-messages.js +58 -0
  48. package/dist/tool-registry.d.ts +76 -0
  49. package/dist/tool-registry.js +17 -0
  50. package/docs/architecture.md +883 -0
  51. package/package.json +52 -0
  52. package/prompts/pi-crew:review.md +168 -0
@@ -0,0 +1,883 @@
1
+ # pi-crew Architecture
2
+
3
+ This document explains the technical architecture of `@melihmucuk/pi-crew` for both human users and coding agents.
4
+
5
+ It describes runtime behavior, integration points, ownership rules, delivery semantics, and implementation boundaries. It intentionally avoids code snippets. Source files are referenced instead, because exact code can change while the behavioral contract should remain stable.
6
+
7
+ All paths in this document are relative to the repository root.
8
+
9
+ ## 1. What the project is
10
+
11
+ `pi-crew` is a non-blocking subagent orchestration extension for pi.
12
+
13
+ Its job is to let one pi session delegate work to one or more isolated subagent sessions without blocking the caller session. Each spawned subagent runs independently, and its result is delivered back to the session that spawned it as a `crew-result` custom message. When the owner session is already streaming, that message is delivered as steering content.
14
+
15
+ At a high level, the system adds:
16
+
17
+ - tool-based orchestration for spawning, listing, aborting, responding to, and closing subagents
18
+ - a slash-command emergency abort path
19
+ - TUI renderers for subagent custom messages
20
+ - a live status widget for active subagents owned by the current session
21
+ - bundled subagent definitions and a bundled review prompt template
22
+
23
+ Primary entry points:
24
+
25
+ - `package.json`
26
+ - `extension/index.ts`
27
+ - `README.md`
28
+
29
+ ## 2. Architectural goals
30
+
31
+ The extension is built around a few explicit goals:
32
+
33
+ 1. **Keep the caller session interactive**
34
+ The main session must not block while background work is happening.
35
+
36
+ 2. **Preserve session isolation**
37
+ Each subagent gets its own pi SDK session, context window, and resolved tool/skill set.
38
+
39
+ 3. **Route results to the owning session**
40
+ Results are not sent to whichever session happens to be active. They are sent to the session that created the subagent.
41
+
42
+ 4. **Make multi-agent work understandable in the TUI**
43
+ Users need visible state, clear completion messages, and an emergency stop path.
44
+
45
+ 5. **Stay behavior-first**
46
+ Agent definitions, tool restrictions, and delivery semantics are designed as explicit contracts, not incidental implementation details.
47
+
48
+ Project-level guardrails that define these contracts live in:
49
+
50
+ - `AGENTS.md`
51
+
52
+ ## 3. Package layout and extension surface
53
+
54
+ ### 3.1 Package registration in pi
55
+
56
+ `pi-crew` is packaged as a pi extension package.
57
+
58
+ Registration metadata lives in:
59
+
60
+ - `package.json`
61
+
62
+ Important package-level behaviors:
63
+
64
+ - `pi.extensions` points pi to the built extension entry at `./dist/index.js`
65
+ - `pi.prompts` exposes the bundled prompt template directory at `./prompts`
66
+ - `agents/` is shipped as package data and auto-discovered as the lowest-priority source during agent discovery
67
+
68
+ ### 3.2 Repository structure
69
+
70
+ Main implementation areas:
71
+
72
+ - `extension/` - runtime extension logic
73
+ - `extension/runtime/` - in-memory state and delivery coordination
74
+ - `extension/integration/` - pi tool, command, and renderer registration
75
+ - `agents/` - bundled subagent definitions
76
+ - `prompts/` - bundled prompt templates
77
+
78
+ ## 4. Core runtime components
79
+
80
+ ### 4.1 Extension bootstrap
81
+
82
+ File:
83
+
84
+ - `extension/index.ts`
85
+
86
+ Responsibilities:
87
+
88
+ - instantiate one `CrewManager` for the extension runtime
89
+ - observe pi session lifecycle events
90
+ - activate delivery routing when the active pi session changes
91
+ - abort owned abortable subagents when an owner session shuts down
92
+ - register tools, command, and message renderers
93
+ - refresh the status widget when state changes
94
+
95
+ Session lifecycle events used by the extension:
96
+
97
+ - `session_start`
98
+ - `session_switch`
99
+ - `session_fork`
100
+ - `session_shutdown`
101
+
102
+ This is the bridge between pi core events and `pi-crew` runtime behavior.
103
+
104
+ ### 4.2 Crew manager
105
+
106
+ File:
107
+
108
+ - `extension/crew-manager.ts`
109
+
110
+ `CrewManager` is the main orchestration service.
111
+
112
+ It owns the extension’s operational workflow:
113
+
114
+ - create subagent state records
115
+ - bootstrap isolated subagent sessions
116
+ - send prompts into subagent sessions
117
+ - interpret prompt outcomes
118
+ - transition subagents between `running`, `waiting`, `done`, `error`, and `aborted`
119
+ - deliver results back to the owner session
120
+ - enforce ownership checks for `respond`, `done`, and owned abort paths
121
+ - dispose finished subagents
122
+
123
+ In practice, `CrewManager` is the coordination layer above the registry and delivery subsystems.
124
+
125
+ ### 4.3 Subagent registry
126
+
127
+ Files:
128
+
129
+ - `extension/runtime/subagent-registry.ts`
130
+ - `extension/runtime/subagent-state.ts`
131
+
132
+ Responsibilities:
133
+
134
+ - store live in-memory subagent state in a `Map`
135
+ - generate unique runtime IDs such as `<name>-<hex>`
136
+ - filter subagents by owner session
137
+ - provide summaries for the TUI widget and abort command
138
+ - count other still-running subagents for ordered delivery notes
139
+
140
+ Important architectural property:
141
+
142
+ - the registry is **in-memory only**
143
+ - active subagents are therefore runtime-scoped, not globally persistent across process restarts
144
+
145
+ However, per project rules, subagent session files themselves are intentionally not cleaned up, so post-hoc inspection through pi session history remains possible.
146
+
147
+ ### 4.4 Delivery coordinator
148
+
149
+ File:
150
+
151
+ - `extension/runtime/delivery-coordinator.ts`
152
+
153
+ This component solves one of the most important architecture problems in the extension: **how to deliver background results to the correct session at the correct time**.
154
+
155
+ Responsibilities:
156
+
157
+ - track which pi session is currently active
158
+ - know whether the active owner session is idle or already streaming
159
+ - queue results for inactive owner sessions
160
+ - flush queued results when the owner session becomes active again
161
+ - preserve ordering between the main result message and the optional “remaining subagents” note
162
+
163
+ This separation keeps delivery logic independent from spawning logic.
164
+
165
+ ## 5. Integration with pi
166
+
167
+ ### 5.1 Registered tools
168
+
169
+ Files:
170
+
171
+ - `extension/integration/register-tools.ts`
172
+ - `extension/integration/tools/crew-list.ts`
173
+ - `extension/integration/tools/crew-spawn.ts`
174
+ - `extension/integration/tools/crew-abort.ts`
175
+ - `extension/integration/tools/crew-respond.ts`
176
+ - `extension/integration/tools/crew-done.ts`
177
+
178
+ The extension registers five tools:
179
+
180
+ - `crew_list`
181
+ - `crew_spawn`
182
+ - `crew_abort`
183
+ - `crew_respond`
184
+ - `crew_done`
185
+
186
+ These are the primary public API for LLM-driven orchestration.
187
+
188
+ Behavioral contracts:
189
+
190
+ - `crew_list` shows discovered subagent definitions and active subagents owned by the current session
191
+ - `crew_spawn` starts a non-blocking subagent owned by the current session
192
+ - `crew_abort` can abort one, many, or all active subagents owned by the current session
193
+ - `crew_respond` continues a waiting interactive subagent without blocking the caller session
194
+ - `crew_done` closes a waiting interactive subagent without emitting a duplicate completion message
195
+
196
+ ### 5.2 Registered command
197
+
198
+ File:
199
+
200
+ - `extension/integration/register-command.ts`
201
+
202
+ The extension also registers the `/pi-crew:abort` command.
203
+
204
+ This command differs from `crew_abort` in one important way:
205
+
206
+ - it is intentionally unrestricted across sessions
207
+
208
+ It exists as an emergency escape hatch. This is a deliberate operational tool, not an ownership-safe automation surface.
209
+
210
+ ### 5.3 Custom message renderers
211
+
212
+ Files:
213
+
214
+ - `extension/integration/register-renderers.ts`
215
+ - `extension/subagent-messages.ts`
216
+
217
+ The extension defines two custom message types:
218
+
219
+ - `crew-result`
220
+ - `crew-remaining`
221
+
222
+ These render in the TUI with custom formatting so asynchronous subagent output is readable and visually distinct from normal assistant text.
223
+
224
+ ### 5.4 Status widget
225
+
226
+ File:
227
+
228
+ - `extension/status-widget.ts`
229
+
230
+ When the current session owns active subagents, a live widget shows:
231
+
232
+ - subagent ID
233
+ - the latest assistant-reported model name, or `…` before the first assistant turn ends
234
+ - turn count
235
+ - the latest `assistant.usage.totalTokens` value, displayed as `ctx`
236
+ - running vs waiting state
237
+
238
+ This widget is session-scoped. It only shows subagents owned by the currently active session.
239
+
240
+ ## 6. Subagent definition model
241
+
242
+ ### 6.1 Discovery sources and priority
243
+
244
+ File:
245
+
246
+ - `extension/agent-discovery.ts`
247
+
248
+ Subagent definitions are discovered from three directories in priority order:
249
+
250
+ 1. **Project**: `<cwd>/.pi/agents/*.md`
251
+ 2. **User global**: `~/.pi/agent/agents/*.md`
252
+ 3. **Bundled**: `agents/` in the package
253
+
254
+ When the same subagent name exists in multiple sources, the higher-priority source wins silently. Duplicate names within the same directory produce a warning.
255
+
256
+ If a directory does not exist, it is skipped without warnings.
257
+
258
+ ### 6.2 Definition format
259
+
260
+ Each subagent is a Markdown file with YAML frontmatter plus a Markdown body.
261
+
262
+ Frontmatter fields currently recognized by the runtime:
263
+
264
+ - `name`
265
+ - `description`
266
+ - `model`
267
+ - `thinking`
268
+ - `tools`
269
+ - `skills`
270
+ - `compaction`
271
+ - `interactive`
272
+
273
+ The Markdown body becomes appended system prompt content for the spawned subagent session.
274
+
275
+ ### 6.3 JSON override sources and precedence
276
+
277
+ File:
278
+
279
+ - `extension/agent-discovery.ts`
280
+
281
+ After `.md` discovery, the runtime loads optional per-agent override config from two JSON files:
282
+
283
+ - global: `~/.pi/agent/pi-crew.json`
284
+ - project: `<cwd>/.pi/pi-crew.json`
285
+
286
+ Only these fields are overridable:
287
+
288
+ - `model`
289
+ - `thinking`
290
+ - `tools`
291
+ - `skills`
292
+ - `compaction`
293
+ - `interactive`
294
+
295
+ `name` and `description` are never overridable.
296
+
297
+ Merge behavior:
298
+
299
+ - global config is loaded first
300
+ - project config is loaded second
301
+ - project overrides global for the same subagent and field
302
+ - if both files define the same subagent, unspecified fields from global remain unless project overrides them
303
+
304
+ ### 6.4 Validation and fallback behavior
305
+
306
+ Key behaviors implemented in discovery and bootstrap:
307
+
308
+ - missing or empty `name` or `description` makes the definition invalid and it is ignored
309
+ - names cannot contain whitespace
310
+ - later duplicate names are skipped once an earlier valid definition with the same name has been loaded
311
+ - `model` must use `provider/model-id` format to be considered valid
312
+ - invalid model format is ignored for model resolution with a warning
313
+ - invalid `thinking` values are ignored with a warning
314
+ - invalid `tools` or `skills` field formats produce a warning and are treated as empty lists in frontmatter
315
+ - unknown tools are filtered out with a warning
316
+ - unknown skills are not part of discovery validation; when `skills` is present, bootstrap filters against the loaded skill set, omits unknown names, and writes a `console.warn`
317
+ - non-boolean `compaction` or `interactive` values in frontmatter are ignored without a warning
318
+
319
+ Override-specific validation behavior:
320
+
321
+ - override entry value must be a JSON object
322
+ - unknown override fields produce warnings
323
+ - non-overridable fields (`name`, `description`) produce warnings
324
+ - invalid field types in overrides produce warnings and are ignored
325
+ - invalid `model`/`thinking` values in overrides produce warnings and are ignored
326
+ - invalid `tools`/`skills` formats in overrides produce warnings and are ignored
327
+ - unknown tool names in override `tools` produce warnings; valid names in the same list are still applied
328
+ - override entries for undiscovered subagent names produce warnings and are ignored
329
+
330
+ Important semantic distinction:
331
+
332
+ - omitted `tools` means “use the full supported tool allowlist”
333
+ - omitted `skills` means “do not install a `skillsOverride`, so all skills from the base resource loader remain available”
334
+ - explicit empty `tools` or `skills` means “grant none”
335
+
336
+ That distinction matters for both end users and coding agents authoring subagent definitions.
337
+
338
+ ### 6.5 Supported tool set for spawned subagents
339
+
340
+ File:
341
+
342
+ - `extension/tool-registry.ts`
343
+
344
+ The current built-in tool allowlist for spawned subagents is:
345
+
346
+ - `read`
347
+ - `bash`
348
+ - `edit`
349
+ - `write`
350
+ - `grep`
351
+ - `find`
352
+ - `ls`
353
+
354
+ Important limitation:
355
+
356
+ - tool restriction here is a pi tool-resolution choice, not an OS sandbox boundary
357
+ - for example, a “read-only” subagent remains read-only because of instruction and selected tool capabilities, not because of a kernel-level confinement model
358
+
359
+ ## 7. Session bootstrapping and isolation
360
+
361
+ ### 7.1 How a subagent session is created
362
+
363
+ File:
364
+
365
+ - `extension/bootstrap-session.ts`
366
+
367
+ When `crew_spawn` is executed, the runtime does not clone the current conversation directly. It creates a new agent session with explicit configuration.
368
+
369
+ Bootstrapping responsibilities:
370
+
371
+ - resolve the target model
372
+ - resolve the selected tool set
373
+ - construct a `DefaultResourceLoader`
374
+ - optionally filter skills
375
+ - append the subagent system prompt body
376
+ - create an in-memory settings manager for compaction settings
377
+ - create a new `SessionManager`
378
+ - call `sessionManager.newSession({ parentSession: parentSessionFile })` before creating the agent session
379
+ - create the actual `AgentSession`
380
+
381
+ ### 7.2 Parent-child session linkage
382
+
383
+ A critical implementation rule is that the subagent session must be created through `SessionManager.newSession({ parentSession })`.
384
+
385
+ The current caller session file is passed when one exists. This is the supported way to preserve parent-child linkage for resumable sessions. Project rules explicitly forbid creating subagent sessions through the wrong session factory because it breaks lifecycle expectations.
386
+
387
+ Architectural rationale is documented in:
388
+
389
+ - `AGENTS.md`
390
+
391
+ ### 7.3 Preventing recursive orchestration
392
+
393
+ One of the most important safety guards in the system is this:
394
+
395
+ - spawned subagent sessions must not load the `pi-crew` extension again
396
+
397
+ This is enforced by filtering the extension out through `extensionsOverride` inside the resource loader.
398
+
399
+ Why it matters:
400
+
401
+ - if a subagent can access `crew_spawn`, it can create more subagents
402
+ - that creates recursive or runaway orchestration loops
403
+ - preventing that at session bootstrap time is far safer than relying on prompt instructions alone
404
+
405
+ ### 7.4 Model resolution
406
+
407
+ The runtime resolves models in two stages:
408
+
409
+ 1. if the subagent definition does not specify a valid parsed model, the caller session model is reused
410
+ 2. if a model is specified but not found in the active pi model registry, the runtime falls back to the caller session model and writes a `console.warn`
411
+
412
+ This keeps execution resilient to local model availability differences.
413
+
414
+ ### 7.5 Compaction behavior
415
+
416
+ Each subagent session gets its own in-memory settings manager.
417
+
418
+ Behavior:
419
+
420
+ - `compaction` defaults to `true` if omitted
421
+ - a definition can explicitly disable it
422
+
423
+ This setting is applied per spawned session and does not reuse the caller session's compaction setting.
424
+
425
+ ## 8. Spawn lifecycle
426
+
427
+ ### 8.1 High-level flow
428
+
429
+ Relevant files:
430
+
431
+ - `extension/integration/tools/crew-spawn.ts`
432
+ - `extension/crew-manager.ts`
433
+ - `extension/bootstrap-session.ts`
434
+
435
+ Behavior sequence:
436
+
437
+ 1. The `crew_spawn` tool handler calls `discoverAgents()` to load the current subagent definitions.
438
+ 2. The requested subagent name is resolved against that discovery result.
439
+ 3. The current session ID becomes the subagent owner ID.
440
+ 4. `CrewManager.spawn()` creates a registry entry with status `running` and returns a runtime subagent ID immediately.
441
+ 5. `CrewManager` starts asynchronous session bootstrap in the background.
442
+ 6. Once bootstrapped, the new subagent session receives the task string as its prompt.
443
+ 7. Completion or failure is delivered later as a `crew-result` custom message. If the owner session is already streaming, that message is delivered with `deliverAs: "steer"`.
444
+
445
+ This immediate-return plus background-execution split is the key non-blocking contract of the extension.
446
+
447
+ ### 8.2 Runtime metrics during execution
448
+
449
+ `CrewManager` subscribes to subagent `turn_end` events.
450
+
451
+ Tracked metrics include:
452
+
453
+ - turn count, incremented on each `turn_end`
454
+ - the latest `assistant.usage.totalTokens` value seen on a `turn_end`
455
+ - the latest assistant-reported model name
456
+
457
+ These metrics power the status widget and active subagent summaries.
458
+
459
+ ### 8.3 Prompt outcome interpretation
460
+
461
+ After a prompt cycle completes, the runtime inspects the last assistant message in the subagent session.
462
+
463
+ Outcome mapping:
464
+
465
+ - assistant stop reason `error` -> subagent status `error`
466
+ - assistant stop reason `aborted` -> subagent status `aborted`
467
+ - normal completion with `interactive: true` -> subagent status `waiting`
468
+ - normal completion with non-interactive definition -> subagent status `done`
469
+
470
+ This means interactive subagents and non-interactive subagents share the same prompt execution flow up to the final state transition.
471
+
472
+ ## 9. Delivery model and message ordering
473
+
474
+ ### 9.1 Owner-based routing
475
+
476
+ The most important delivery rule is:
477
+
478
+ - results belong to the session that spawned the subagent
479
+
480
+ They do not belong to:
481
+
482
+ - the currently visible session
483
+ - the most recent session
484
+ - the session that called a command later
485
+
486
+ Ownership identity is based on the current session ID, not the session file path. This matters because unsaved or in-memory sessions may not have stable file paths.
487
+
488
+ ### 9.2 Immediate vs deferred delivery
489
+
490
+ Relevant files:
491
+
492
+ - `extension/runtime/delivery-coordinator.ts`
493
+ - `extension/index.ts`
494
+
495
+ Delivery branches:
496
+
497
+ - if the owner session is currently active, the result is sent immediately
498
+ - if the owner session is not active, the result is queued in memory until that session becomes active again
499
+
500
+ Queued results are flushed when the extension sees that owner session through:
501
+
502
+ - `session_start`
503
+ - `session_switch`
504
+ - `session_fork`
505
+
506
+ ### 9.3 Idle vs streaming session behavior
507
+
508
+ pi requires different delivery semantics depending on whether the target session is idle or already processing output.
509
+
510
+ Behavioral rule for a `crew-result` when no separate remaining-note ordering is needed:
511
+
512
+ - idle owner session -> send with `triggerTurn: true`
513
+ - streaming owner session -> send as steering content with `deliverAs: "steer"` and `triggerTurn: true`
514
+
515
+ When an idle owner also needs a `crew-remaining` note, section 9.5 describes the deliberate `triggerTurn: false` / `true` split used to preserve message order.
516
+
517
+ Why this distinction exists:
518
+
519
+ - sending `deliverAs: "steer"` to an idle session can leave the message unprocessed because there is no active turn loop
520
+ - when the owner session is already streaming, the extension injects the result into that active turn as steering content instead of using the idle-session delivery path
521
+
522
+ This is one of the most subtle but important integration details in the extension.
523
+
524
+ ### 9.4 Deferred flush timing
525
+
526
+ Pending message flush after session activation is intentionally deferred to the next macrotask.
527
+
528
+ Reason:
529
+
530
+ - pi-core can emit `session_switch` before reconnecting the agent listener during resume flows
531
+ - synchronous message delivery at that moment can lose custom message persistence
532
+
533
+ This is why queued results are flushed asynchronously instead of synchronously during session activation.
534
+
535
+ ### 9.5 Result and remaining-note ordering
536
+
537
+ Files:
538
+
539
+ - `extension/subagent-messages.ts`
540
+ - `extension/runtime/delivery-coordinator.ts`
541
+
542
+ When a result is delivered and other subagents from the same owner are still in `running` state, the extension may send two messages:
543
+
544
+ 1. the `crew-result`
545
+ 2. a separate `crew-remaining` note
546
+
547
+ They are intentionally separate messages.
548
+
549
+ Why:
550
+
551
+ - the result message should stay focused on one subagent outcome
552
+ - the remaining count is transient orchestration state, not part of that result payload
553
+
554
+ Ordering guarantee:
555
+
556
+ - the result must appear before the remaining-note message
557
+
558
+ When the owner is idle and other subagents are still running, the extension sends the `crew-result` with `triggerTurn: false`, then sends the remaining note with `triggerTurn: true` so the next turn processes both in order.
559
+
560
+ When the owner is already streaming, the extension sends the `crew-result` first with `deliverAs: "steer"` and `triggerTurn: true`, then sends the `crew-remaining` note after it with `deliverAs: "steer"` and `triggerTurn: false`.
561
+
562
+ The remaining count is computed at send time from the current registry state, not stored in the `crew-result` payload.
563
+
564
+ ## 10. Interactive subagents
565
+
566
+ ### 10.1 Waiting state
567
+
568
+ Interactive subagents are defined with `interactive: true` in frontmatter.
569
+
570
+ After a successful prompt cycle, they transition to `waiting` instead of `done`.
571
+
572
+ Meaning of `waiting`:
573
+
574
+ - the session remains alive
575
+ - the subagent can receive follow-up messages
576
+ - the status widget shows a waiting icon rather than a spinner
577
+
578
+ ### 10.2 `crew_respond`
579
+
580
+ Relevant files:
581
+
582
+ - `extension/integration/tools/crew-respond.ts`
583
+ - `extension/crew-manager.ts`
584
+
585
+ Behavior:
586
+
587
+ - validate that the subagent exists
588
+ - validate that it belongs to the caller session
589
+ - validate that it is in `waiting` state
590
+ - mark it `running`
591
+ - asynchronously send the follow-up prompt
592
+ - return immediately to the caller
593
+
594
+ This is deliberately fire-and-forget. The response comes later as another `crew-result` message.
595
+
596
+ ### 10.3 `crew_done`
597
+
598
+ Relevant files:
599
+
600
+ - `extension/integration/tools/crew-done.ts`
601
+ - `extension/crew-manager.ts`
602
+
603
+ Behavior:
604
+
605
+ - validate existence, ownership, and `waiting` state
606
+ - dispose the session
607
+ - remove the subagent from the registry
608
+ - do **not** send another `crew-result` message
609
+
610
+ That last point is essential. The latest subagent response was already delivered when it entered `waiting`. Sending another completion custom message on `crew_done` would duplicate signal and create an unnecessary turn.
611
+
612
+ ## 11. Abort semantics
613
+
614
+ ### 11.1 Supported abort paths
615
+
616
+ There are three conceptually different abort sources:
617
+
618
+ 1. tool-triggered aborts through `crew_abort`
619
+ 2. unrestricted manual aborts through `/pi-crew:abort`
620
+ 3. cleanup aborts when an owner session shuts down
621
+
622
+ Each path should report the real reason.
623
+
624
+ ### 11.2 Owned abort behavior
625
+
626
+ Relevant files:
627
+
628
+ - `extension/integration/tools/crew-abort.ts`
629
+ - `extension/crew-manager.ts`
630
+
631
+ `crew_abort` supports exactly one mode per call:
632
+
633
+ - `subagent_id`
634
+ - `subagent_ids`
635
+ - `all: true`
636
+
637
+ It only operates on subagents owned by the current session.
638
+
639
+ The result separates:
640
+
641
+ - actually aborted IDs
642
+ - missing or already finished IDs
643
+ - IDs that belong to another session
644
+
645
+ ### 11.3 Unrestricted command abort
646
+
647
+ Relevant file:
648
+
649
+ - `extension/integration/register-command.ts`
650
+
651
+ `/pi-crew:abort` can target any active abortable subagent, regardless of owner. This is not a bug. It is an explicit operational decision.
652
+
653
+ ### 11.4 Session shutdown cleanup
654
+
655
+ Relevant file:
656
+
657
+ - `extension/index.ts`
658
+
659
+ On `session_shutdown`, the extension:
660
+
661
+ - aborts all abortable subagents currently owned by that session
662
+ - clears pending queued messages for that owner
663
+
664
+ This avoids memory leaks and prevents stale queued results from surviving after their owner session is gone.
665
+
666
+ ## 12. Ownership and isolation rules
667
+
668
+ These are core architecture invariants, not optional conventions.
669
+
670
+ ### 12.1 Owner identity
671
+
672
+ Owner identity uses the pi session ID.
673
+
674
+ Why:
675
+
676
+ - session file paths may be undefined for in-memory sessions
677
+ - file-path-based ownership can collapse multiple live sessions into the same logical owner
678
+
679
+ ### 12.2 Session-scoped visibility
680
+
681
+ The following surfaces are ownership-restricted:
682
+
683
+ - `crew_list` active subagent section
684
+ - `crew_abort`
685
+ - `crew_respond`
686
+ - `crew_done`
687
+ - status widget
688
+ - owner cleanup on session shutdown
689
+
690
+ This prevents cross-session interference in normal tool-driven workflows.
691
+
692
+ ### 12.3 What is intentionally not isolated
693
+
694
+ The emergency command `/pi-crew:abort` is intentionally cross-session.
695
+
696
+ This is the only major exception to normal ownership isolation.
697
+
698
+ ## 13. User-facing message model
699
+
700
+ Relevant file:
701
+
702
+ - `extension/subagent-messages.ts`
703
+
704
+ Subagent outcome messaging is normalized into one common format.
705
+
706
+ Every `crew-result` payload includes:
707
+
708
+ - runtime subagent ID
709
+ - logical subagent name
710
+ - final status
711
+ - an optional body derived from the subagent result or error
712
+
713
+ In current completion and error paths, the runtime usually populates that body with assistant text, an error message, or `"(no output)"`.
714
+
715
+ `crew-remaining` is simpler. It carries display text only and does not attach structured `details`.
716
+
717
+ The `SubagentStatus` union currently includes:
718
+
719
+ - `running`
720
+ - `waiting`
721
+ - `done`
722
+ - `error`
723
+ - `aborted`
724
+
725
+ Current `crew-result` deliveries use `waiting`, `done`, `error`, or `aborted`. `running` is a live registry/widget state, not a completion message state.
726
+
727
+ ## 14. Bundled subagents and prompt template
728
+
729
+ ### 14.1 Bundled subagents
730
+
731
+ Files:
732
+
733
+ - `agents/scout.md`
734
+ - `agents/planner.md`
735
+ - `agents/worker.md`
736
+ - `agents/code-reviewer.md`
737
+ - `agents/quality-reviewer.md`
738
+
739
+ These are opinionated subagent definitions for common workflows.
740
+
741
+ They demonstrate how the extension is intended to be used:
742
+
743
+ - `scout` for quick investigation
744
+ - `planner` for interactive planning
745
+ - `worker` for implementation
746
+ - `code-reviewer` for correctness review
747
+ - `quality-reviewer` for maintainability review
748
+
749
+ Architecturally, these files are not special-cased by the runtime. They are auto-discovered as the lowest-priority source (priority 3) and go through the same discovery and bootstrap pipeline as project-level or user-level definitions. Users can override any bundled subagent by placing a same-named `.md` file in `<cwd>/.pi/agents/` or `~/.pi/agent/agents/`.
750
+
751
+ ### 14.2 Bundled review orchestration prompt
752
+
753
+ File:
754
+
755
+ - `prompts/pi-crew:review.md`
756
+
757
+ This prompt template is a good example of how `pi-crew` is meant to be consumed by higher-level orchestration prompts.
758
+
759
+ It does not bypass the extension. Instead, it tells the orchestrating agent to gather review scope with normal repo inspection tools, then use the public `crew_*` tool surface to:
760
+
761
+ - verify required subagents exist
762
+ - spawn reviewers in parallel
763
+ - wait for both result messages
764
+ - merge results into a final report
765
+
766
+ This separation is important:
767
+
768
+ - the extension provides orchestration primitives
769
+ - prompts provide workflow policy
770
+
771
+ ## 15. Failure handling and diagnostics
772
+
773
+ ### 15.1 Discovery warnings
774
+
775
+ Relevant files:
776
+
777
+ - `extension/agent-discovery.ts`
778
+ - `extension/integration/register-tools.ts`
779
+
780
+ Invalid or partially invalid subagent definition files do not crash the extension.
781
+
782
+ Instead:
783
+
784
+ - discovery accumulates warnings
785
+ - `crew_list` includes those warnings in its text output
786
+ - `crew_list` and `crew_spawn` both trigger one-time UI notifications when a UI is available
787
+
788
+ This section covers discovery-time warnings only. Unknown skill names are warned later during bootstrap via `console.warn` in `extension/bootstrap-session.ts`.
789
+
790
+ This keeps misconfigured subagents visible without breaking healthy ones.
791
+
792
+ ### 15.2 Bootstrap failures
793
+
794
+ Bootstrap failures are settled as subagent `error` results.
795
+
796
+ In practice, this covers exceptions thrown while preparing the resource loader or creating the subagent session.
797
+
798
+ The important behavior is that a failed spawn still resolves into a clear terminal subagent result rather than silently disappearing.
799
+
800
+ ### 15.3 Prompt execution failures
801
+
802
+ Prompt-cycle failures are also normalized into terminal `error` or `aborted` outcomes and delivered through the same result channel.
803
+
804
+ This gives downstream orchestrators a single message model to watch, regardless of where the failure occurred.
805
+
806
+ ## 16. What persists and what does not
807
+
808
+ ### Persists
809
+
810
+ - extension package installation metadata
811
+ - bundled prompt template availability
812
+ - copied subagent definition files in `~/.pi/agent/agents/`
813
+ - pi session history files created for subagents
814
+
815
+ ### Does not persist across process restarts
816
+
817
+ - in-memory active subagent registry
818
+ - in-memory pending delivery queue
819
+ - live status widget state
820
+
821
+ This distinction matters when designing higher-level workflows. `pi-crew` preserves session artifacts for inspection, but its live orchestration state is runtime-memory-based.
822
+
823
+ ## 17. Behavioral invariants for future maintainers
824
+
825
+ These are the behaviors future changes must preserve:
826
+
827
+ 1. A spawned subagent must not block the caller session.
828
+ 2. Results must route to the owning session, not merely the currently active one.
829
+ 3. Ownership must be based on session ID.
830
+ 4. Subagent sessions must not load `pi-crew` again.
831
+ 5. Interactive subagents must remain alive after responding until explicitly closed.
832
+ 6. `crew_respond` must return immediately and deliver its result asynchronously later.
833
+ 7. `crew_done` must clean up only and must not emit a duplicate result message.
834
+ 8. When the owner session is inactive, result delivery must be queued and later flushed.
835
+ 9. Result messages must appear before any “remaining subagents” note.
836
+ 10. Session shutdown must abort owned abortable subagents and clear pending queued messages for that owner.
837
+ 11. Tool ownership restrictions must remain strict, except for the emergency abort command.
838
+
839
+ These rules are the extension’s real architecture. File names may move, but these contracts should not.
840
+
841
+ ## 18. Reading guide for coding agents
842
+
843
+ If you need to understand or change behavior, start in this order:
844
+
845
+ 1. `README.md`
846
+ Public product surface and user contract.
847
+
848
+ 2. `AGENTS.md`
849
+ Non-obvious architecture guardrails that must not regress.
850
+
851
+ 3. `extension/index.ts`
852
+ Extension bootstrap and session event wiring.
853
+
854
+ 4. `extension/crew-manager.ts`
855
+ Main orchestration and state transitions.
856
+
857
+ 5. `extension/runtime/delivery-coordinator.ts`
858
+ Owner routing, queueing, and turn-trigger behavior.
859
+
860
+ 6. `extension/bootstrap-session.ts`
861
+ Session construction, model/tool/skill resolution, and extension filtering.
862
+
863
+ 7. `extension/agent-discovery.ts`
864
+ Subagent definition semantics and validation rules.
865
+
866
+ 8. `extension/integration/`
867
+ pi-facing tools, command, and renderers.
868
+
869
+ 9. `agents/` and `prompts/`
870
+ Real workflow examples built on top of the runtime.
871
+
872
+ ## 19. Verification
873
+
874
+ For implementation changes that affect runtime behavior, the project-level verification commands are:
875
+
876
+ - `npm run typecheck`
877
+ - `npm run build`
878
+
879
+ Source:
880
+
881
+ - `AGENTS.md`
882
+
883
+ For documentation-only changes, these commands are usually unnecessary unless the change is coupled with code edits.