@gotgenes/pi-subagents 1.0.2 → 3.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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,50 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [3.0.0](https://github.com/gotgenes/pi-packages/compare/pi-subagents-v2.0.0...pi-subagents-v3.0.0) (2026-05-17)
9
+
10
+
11
+ ### ⚠ BREAKING CHANGES
12
+
13
+ * The JoinMode type and defaultJoinMode setting are removed from the public settings interface.
14
+ * The join-mode setting (smart/async/group) is removed. Background agents always notify individually on completion.
15
+ * The subagents:ready event is no longer emitted. Extensions should use the typed SubagentsAPI ([#48](https://github.com/gotgenes/pi-packages/issues/48)) instead of event-based RPC discovery.
16
+ * The subagents:rpc:ping, subagents:rpc:spawn, and subagents:rpc:stop event channels are no longer registered. Use the typed SubagentsAPI via Symbol.for() instead.
17
+
18
+ ### Features
19
+
20
+ * remove group-join and cross-extension-rpc source ([b7d7f21](https://github.com/gotgenes/pi-packages/commit/b7d7f21af265e2ff95f0534f5c0b51f71b8f1e7f))
21
+ * remove group-join wiring from index.ts ([4e2dc7f](https://github.com/gotgenes/pi-packages/commit/4e2dc7f8a98e441308f229745dfc42d09784d786))
22
+ * remove join-mode types and settings ([1d98793](https://github.com/gotgenes/pi-packages/commit/1d98793eb85aa3d9815274aa443c34bb4434b6f9))
23
+ * remove RPC wiring from index.ts ([3a960af](https://github.com/gotgenes/pi-packages/commit/3a960af8f6bb83219497d6229d12c6859cf3eb71))
24
+
25
+
26
+ ### Documentation
27
+
28
+ * plan removal of group-join, output-file, and ad-hoc RPC ([#49](https://github.com/gotgenes/pi-packages/issues/49)) ([853a97f](https://github.com/gotgenes/pi-packages/commit/853a97f1c47051868b2ffddd7d5509f765a80d07))
29
+ * remove group-join and RPC from README and AGENTS ([9f65f7a](https://github.com/gotgenes/pi-packages/commit/9f65f7a21611af8dead00a5fb34d7d10f3d6ab43))
30
+
31
+ ## [2.0.0](https://github.com/gotgenes/pi-packages/compare/pi-subagents-v1.0.2...pi-subagents-v2.0.0) (2026-05-17)
32
+
33
+
34
+ ### ⚠ BREAKING CHANGES
35
+
36
+ * the `schedule` parameter is removed from the Agent tool. The `subagents:scheduled` and `subagents:scheduler_ready` events are no longer emitted. The `/agents → Settings → Scheduling` toggle is removed.
37
+ * the `schedule` parameter is removed from the Agent tool and the `subagents:scheduled` / `subagents:scheduler_ready` events are no longer emitted. System cron (or launchd) invoking `pi` directly is the recommended replacement for recurring/delayed agent tasks.
38
+
39
+ ### Features
40
+
41
+ * remove scheduled subagents source and tests ([860a03f](https://github.com/gotgenes/pi-packages/commit/860a03f08a6dbd418b437a72c2fd05ea416abacb))
42
+ * remove scheduler wiring, types, and settings ([d5184e8](https://github.com/gotgenes/pi-packages/commit/d5184e88b181e60809b7fecc6a0971a18723bb9d))
43
+
44
+
45
+ ### Documentation
46
+
47
+ * correct Module-Level Changes table in plan [#52](https://github.com/gotgenes/pi-packages/issues/52) (AGENTS.md → SKILL.md) ([93337e2](https://github.com/gotgenes/pi-packages/commit/93337e2a6b0424dc64e0adaf7a5c6ae6913c5991))
48
+ * plan remove in-process scheduled subagents ([#52](https://github.com/gotgenes/pi-packages/issues/52)) ([bc548a4](https://github.com/gotgenes/pi-packages/commit/bc548a4dc6be4c5f810e9e33abcc76bc0d84f0da))
49
+ * remove scheduling from README, architecture doc, and skill ([b2f16f2](https://github.com/gotgenes/pi-packages/commit/b2f16f2a53674a6a2675024dfc038c4243edd299))
50
+ * **retro:** add retro notes for issue [#51](https://github.com/gotgenes/pi-packages/issues/51) ([0f741de](https://github.com/gotgenes/pi-packages/commit/0f741dedbe4a8e26fd1e39098fb153e4511082b9))
51
+
8
52
  ## [1.0.2](https://github.com/gotgenes/pi-packages/compare/pi-subagents-v1.0.1...pi-subagents-v1.0.2) (2026-05-17)
9
53
 
10
54
 
package/README.md CHANGED
@@ -17,7 +17,7 @@ https://github.com/user-attachments/assets/8685261b-9338-4fea-8dfe-1c590d5df543
17
17
  ## Features
18
18
 
19
19
  - **Claude Code look & feel** — same tool names, calling conventions, and UI patterns (`Agent`, `get_subagent_result`, `steer_subagent`) — feels native
20
- - **Parallel background agents** — spawn multiple agents that run concurrently with automatic queuing (configurable concurrency limit, default 4) and smart group join (consolidated notifications)
20
+ - **Parallel background agents** — spawn multiple agents that run concurrently with automatic queuing (configurable concurrency limit, default 4) and individual completion notifications
21
21
  - **Live widget UI** — persistent above-editor widget with animated spinners, live tool activity, token counts, and colored status icons
22
22
  - **Conversation viewer** — select any agent in `/agents` to open a live-scrolling overlay of its full conversation (auto-follows new content, scroll up to pause)
23
23
  - **Custom agent types** — define agents in `.pi/agents/<name>.md` with YAML frontmatter: custom system prompts, model selection, thinking levels, tool restrictions
@@ -31,10 +31,9 @@ https://github.com/user-attachments/assets/8685261b-9338-4fea-8dfe-1c590d5df543
31
31
  - **Git worktree isolation** — run agents in isolated repo copies; changes auto-committed to branches on completion
32
32
  - **Skill preloading** — inject named skills into agent system prompts, discovered from `.pi/skills/`, `.agents/skills/`, and global locations (Pi-standard `<name>/SKILL.md` directory layout supported)
33
33
  - **Tool denylist** — block specific tools via `disallowed_tools` frontmatter
34
- - **Styled completion notifications** — background agent results render as themed, compact notification boxes (icon, stats, result preview) instead of raw XML. Expandable to show full output. Group completions render each agent individually
34
+ - **Styled completion notifications** — background agent results render as themed, compact notification boxes (icon, stats, result preview) instead of raw XML. Expandable to show full output
35
35
  - **Event bus** — lifecycle events (`subagents:created`, `started`, `completed`, `failed`, `steered`, `compacted`) emitted via `pi.events`, enabling other extensions to react to sub-agent activity
36
- - **Cross-extension RPC** — other pi extensions can spawn and stop subagents via the `pi.events` event bus (`subagents:rpc:ping`, `subagents:rpc:spawn`, `subagents:rpc:stop`). Standardized reply envelopes with protocol versioning. Emits `subagents:ready` on load
37
- - **Schedule subagents** — pass `schedule` to the `Agent` tool to fire on cron / interval / one-shot. Session-scoped jobs with PID-locked persistence; results land via the same `subagent-notification` followUp path as manual background completions; manage via `/agents → Scheduled jobs`
36
+
38
37
 
39
38
  ## Install
40
39
 
@@ -63,38 +62,6 @@ Agent({
63
62
 
64
63
  Foreground agents block until complete and return results inline. Background agents return an ID immediately and notify you on completion.
65
64
 
66
- ### Scheduling
67
-
68
- Add a `schedule` field to register the agent to fire later instead of running now:
69
-
70
- ```
71
- Agent({
72
- subagent_type: "Explore",
73
- prompt: "Look at recent commits and summarize what changed since last week",
74
- description: "Weekly commit review",
75
- schedule: "0 0 9 * * 1", // 9am every Monday (6-field cron)
76
- })
77
- ```
78
-
79
- Schedule formats:
80
-
81
- - **Cron** — 6-field (`second minute hour day-of-month month day-of-week`), e.g. `"0 0 9 * * 1"` for 9am every Monday, `"0 */15 * * * *"` for every 15 minutes.
82
- - **Interval** — `"5m"`, `"1h"`, `"30s"`, `"2d"`. Fires repeatedly at that interval.
83
- - **One-shot relative** — `"+10m"`, `"+2h"`, `"+1d"`. Fires once at that future time.
84
- - **One-shot absolute** — full ISO timestamp, e.g. `"2026-12-25T09:00:00.000Z"`.
85
-
86
- When a schedule fires, the spawn runs in background and its completion notification arrives in the conversation through the same `subagent-notification` followUp path as a manually-spawned background agent — your parent agent reasons about the result the same way.
87
-
88
- Schedules are **session-scoped**: they reset on `/new` and restore on `/resume`. List and cancel via `/agents → Scheduled jobs` (creation is the `Agent` tool's job — there is no parallel manual-create wizard). Storage at `<cwd>/.pi/subagent-schedules/<sessionId>.json` with PID-based file locking for cross-instance safety.
89
-
90
- **Disable the feature entirely**: `/agents → Settings → Scheduling → disabled` removes `schedule` from the `Agent` tool spec (no LLM-context cost), hides the menu entry, and stops any active scheduler. The schema-level removal takes effect on the next pi session; the runtime kill is immediate. Re-enable from the same menu.
91
-
92
- Restrictions:
93
- - `schedule` cannot be combined with `inherit_context` (no parent conversation exists at fire time) or `resume` (schedules create fresh agents).
94
- - `run_in_background` is forced to `true`.
95
- - Scheduled fires bypass the `maxConcurrent` queue so a 5-minute interval cannot be deferred behind long-running manual agents.
96
- - **Headless `pi -p` doesn't wait for scheduled subagents.**
97
-
98
65
  ## UI
99
66
 
100
67
  The extension renders a persistent widget above the editor showing all active agents:
@@ -136,7 +103,7 @@ Background agent completion notifications render as styled boxes:
136
103
  transcript: .pi/output/agent-abc123.jsonl
137
104
  ```
138
105
 
139
- Group completions render each agent as a separate block. The LLM receives structured `<task-notification>` XML for parsing, while the user sees the themed visual.
106
+ The LLM receives structured `<task-notification>` XML for parsing, while the user sees the themed visual.
140
107
 
141
108
  ## Default Agent Types
142
109
 
@@ -265,7 +232,7 @@ The `/agents` command opens an interactive menu:
265
232
  Running agents (2) — 1 running, 1 done ← only shown when agents exist
266
233
  Agent types (6) ← unified list: defaults + custom
267
234
  Create new agent ← manual wizard or AI-generated
268
- Settings ← max concurrency, max turns, grace turns, join mode
235
+ Settings ← max concurrency, max turns, grace turns
269
236
  ```
270
237
 
271
238
  - **Agent types** — unified list with source indicators: `•` (project), `◦` (global), `✕` (disabled). Select an agent to manage it:
@@ -276,7 +243,7 @@ Settings ← max concurrency, max turns, grac
276
243
  - **Eject** — writes the embedded default config as a `.md` file to project or personal location, so you can customize it
277
244
  - **Disable/Enable** — toggle agent availability. Disabled agents stay visible in the list (marked `✕`) and can be re-enabled
278
245
  - **Create new agent** — choose project/personal location, then manual wizard (step-by-step prompts for name, tools, model, thinking, system prompt) or AI-generated (describe what the agent should do and a sub-agent writes the `.md` file). Any name is allowed, including default agent names (overrides them)
279
- - **Settings** — configure max concurrency, default max turns, grace turns, and join mode at runtime
246
+ - **Settings** — configure max concurrency, default max turns, and grace turns at runtime
280
247
 
281
248
  ## Graceful Max Turns
282
249
 
@@ -299,29 +266,14 @@ Background agents are subject to a configurable concurrency limit (default: 4).
299
266
 
300
267
  Foreground agents bypass the queue — they block the parent anyway.
301
268
 
302
- ## Join Strategies
303
-
304
- When background agents complete, they notify the main agent. The **join mode** controls how these notifications are delivered. It applies only to background agents.
305
-
306
- | Mode | Behavior |
307
- |------|----------|
308
- | `smart` (default) | 2+ background agents spawned in the same turn are auto-grouped into a single consolidated notification. Solo agents notify individually. |
309
- | `async` | Each agent sends its own notification on completion (original behavior). Best when results need incremental processing. |
310
- | `group` | Force grouping even when spawning a single agent. Useful when you know more agents will follow. |
311
-
312
- **Timeout behavior:** When agents are grouped, a 30-second timeout starts after the first agent completes. If not all agents finish in time, a partial notification is sent with completed results and remaining agents continue with a shorter 15-second re-batch window for stragglers.
313
-
314
- **Configuration:**
315
- - Configure join mode in `/agents` → Settings → Join mode
316
-
317
269
  ## Persistent Settings
318
270
 
319
- Runtime tuning values set via `/agents` → Settings (max concurrency, default max turns, grace turns, default join mode) persist across pi restarts. Two files, merged on load:
271
+ Runtime tuning values set via `/agents` → Settings (max concurrency, default max turns, grace turns) persist across pi restarts. Two files, merged on load:
320
272
 
321
273
  - **Global:** `~/.pi/agent/subagents.json` — your machine-wide defaults. Edit by hand; the `/agents` menu never writes here.
322
274
  - **Project:** `<cwd>/.pi/subagents.json` — per-project overrides. Written by `/agents` → Settings.
323
275
 
324
- **Precedence:** project overrides global on any field present in both. Missing fields fall back to the hardcoded defaults (max concurrency `4`, default max turns unlimited, grace turns `5`, join mode `smart`).
276
+ **Precedence:** project overrides global on any field present in both. Missing fields fall back to the hardcoded defaults (max concurrency `4`, default max turns unlimited, grace turns `5`).
325
277
 
326
278
  **Example — global defaults for a beefy machine:**
327
279
 
@@ -351,80 +303,11 @@ Agent lifecycle events are emitted via `pi.events.emit()` so other extensions ca
351
303
  | `subagents:failed` | Agent errored, stopped, or aborted | same as completed + `error`, `status` |
352
304
  | `subagents:steered` | Steering message sent | `id`, `message` |
353
305
  | `subagents:compacted` | Agent's session successfully compacted | `id`, `type`, `description`, `reason` (`"manual"` / `"threshold"` / `"overflow"`), `tokensBefore`, `compactionCount` |
354
- | `subagents:scheduled` | Schedule lifecycle change | `{ type: "added" \| "removed" \| "updated" \| "fired" \| "error", … }` (job/agentId/error fields per type) |
355
- | `subagents:scheduler_ready` | Scheduler bound to session, enabled jobs armed | `sessionId`, `jobCount` |
356
- | `subagents:ready` | Extension loaded and RPC handlers registered | — |
357
306
  | `subagents:settings_loaded` | Persisted settings applied at extension init | `settings` (merged global + project) |
358
307
  | `subagents:settings_changed` | `/agents` → Settings mutation was applied | `settings`, `persisted` (`boolean` — `false` on write failure) |
359
308
 
360
309
  `tokens.total` = `input + output + cacheWrite`. `cacheRead` is excluded — each turn's `cacheRead` is the cumulative cached prefix re-read on that one API call, so summing per-message would over-count it. Use `contextUsage.percent` (surfaced as `(NN%)` in the widget) for current context size.
361
310
 
362
- ## Cross-Extension RPC
363
-
364
- Other pi extensions can spawn and stop subagents programmatically via the `pi.events` event bus, without importing this package directly.
365
-
366
- All RPC replies use a standardized envelope: `{ success: true, data?: T }` on success, `{ success: false, error: string }` on failure.
367
-
368
- ### Discovery
369
-
370
- Listen for `subagents:ready` to know when RPC handlers are available:
371
-
372
- ```typescript
373
- pi.events.on("subagents:ready", () => {
374
- // RPC handlers are registered — safe to call ping/spawn/stop
375
- });
376
- ```
377
-
378
- ### Ping
379
-
380
- Check if the subagents extension is loaded and get the protocol version:
381
-
382
- ```typescript
383
- const requestId = crypto.randomUUID();
384
- const unsub = pi.events.on(`subagents:rpc:ping:reply:${requestId}`, (reply) => {
385
- unsub();
386
- if (reply.success) console.log("Protocol version:", reply.data.version);
387
- });
388
- pi.events.emit("subagents:rpc:ping", { requestId });
389
- ```
390
-
391
- ### Spawn
392
-
393
- Spawn a subagent and receive its ID:
394
-
395
- ```typescript
396
- const requestId = crypto.randomUUID();
397
- const unsub = pi.events.on(`subagents:rpc:spawn:reply:${requestId}`, (reply) => {
398
- unsub();
399
- if (!reply.success) {
400
- console.error("Spawn failed:", reply.error);
401
- } else {
402
- console.log("Agent ID:", reply.data.id);
403
- }
404
- });
405
- pi.events.emit("subagents:rpc:spawn", {
406
- requestId,
407
- type: "general-purpose",
408
- prompt: "Do something useful",
409
- options: { description: "My task", run_in_background: true },
410
- });
411
- ```
412
-
413
- ### Stop
414
-
415
- Stop a running agent by ID:
416
-
417
- ```typescript
418
- const requestId = crypto.randomUUID();
419
- const unsub = pi.events.on(`subagents:rpc:stop:reply:${requestId}`, (reply) => {
420
- unsub();
421
- if (!reply.success) console.error("Stop failed:", reply.error);
422
- });
423
- pi.events.emit("subagents:rpc:stop", { requestId, agentId: "agent-id-here" });
424
- ```
425
-
426
- Reply channels are scoped per `requestId`, so concurrent requests don't interfere.
427
-
428
311
  ## Persistent Agent Memory
429
312
 
430
313
  Agents can have persistent memory across sessions. Set `memory` in frontmatter to enable:
@@ -512,8 +395,6 @@ src/
512
395
  agent-types.ts # Unified agent registry (defaults + user), tool name resolution
513
396
  agent-runner.ts # Session creation, execution, graceful max_turns, steer/resume
514
397
  agent-manager.ts # Agent lifecycle, concurrency queue, completion notifications
515
- cross-extension-rpc.ts # RPC handlers for cross-extension spawn/ping via pi.events
516
- group-join.ts # Group join manager: batched completion notifications with timeout
517
398
  custom-agents.ts # Load user-defined agents from .pi/agents/*.md
518
399
  memory.ts # Persistent agent memory (resolve, read, build prompt blocks)
519
400
  skill-loader.ts # Preload skills (Pi-standard + Agent Skills spec layouts)
@@ -48,14 +48,11 @@ invocation-config.ts — merge tool params with agent config
48
48
  output-file.ts — JSONL transcript streaming
49
49
  settings.ts — persistent operational settings
50
50
 
51
- schedule.ts — cron/interval/one-shot job dispatch ← removing
52
- schedule-store.ts — file-backed schedule persistence ← removing
53
51
  cross-extension-rpc.ts — RPC over pi.events ← replacing
54
52
  group-join.ts — batch completion notifications
55
53
 
56
54
  ui/agent-widget.ts — above-editor live status widget
57
55
  ui/conversation-viewer.ts — scrollable session overlay
58
- ui/schedule-menu.ts — /agents schedule submenu ← removing
59
56
  ```
60
57
 
61
58
  ### Coupling today
@@ -63,8 +60,7 @@ ui/schedule-menu.ts — /agents schedule submenu ← removing
63
60
  The widget reads agent state by holding a direct reference to
64
61
  `AgentManager` and polling a shared mutable `Map<string, AgentActivity>`
65
62
  every 80 ms. The conversation viewer subscribes directly to `AgentSession`
66
- objects. The scheduler holds a direct `AgentManager` reference and calls
67
- `manager.spawn()`.
63
+ objects.
68
64
 
69
65
  Cross-extension consumers use an ad-hoc RPC layer over `pi.events`
70
66
  (`subagents:rpc:spawn`, `subagents:rpc:stop`, `subagents:rpc:ping`) with
@@ -342,10 +338,10 @@ Add the `SubagentsAPI` interface, serializable types, and `Symbol.for()`
342
338
  accessor functions as public exports of this package. No behavioral
343
339
  changes to the core yet.
344
340
 
345
- ### Phase 2: Remove scheduling
341
+ ### Phase 2: Remove scheduling ✓ (done — issue #52)
346
342
 
347
- Delete `schedule.ts`, `schedule-store.ts`, `ui/schedule-menu.ts`. Remove
348
- the `schedule` parameter from the `Agent` tool schema. Remove scheduler
343
+ Deleted `schedule.ts`, `schedule-store.ts`, `ui/schedule-menu.ts`. Removed
344
+ the `schedule` parameter from the `Agent` tool schema. Removed scheduler
349
345
  setup and lifecycle hooks from `index.ts`.
350
346
 
351
347
  ### Phase 3: Remove group-join, output-file, ad-hoc RPC
@@ -0,0 +1,163 @@
1
+ ---
2
+ issue: 49
3
+ issue_title: "feat: remove group-join, output-file, and ad-hoc RPC"
4
+ ---
5
+
6
+ # Remove group-join and ad-hoc RPC
7
+
8
+ ## Problem Statement
9
+
10
+ Two optional subsystems remain in the core that are either consumer concerns or replaced by the typed `SubagentsAPI` (#48):
11
+
12
+ 1. **Group join** — grouped completion notifications add batching complexity for marginal UX benefit when individual notifications are sufficient.
13
+ 2. **Ad-hoc RPC** — untyped RPC over `pi.events` with per-request reply channels is replaced by the typed `SubagentsAPI` published via `Symbol.for()`.
14
+
15
+ Removing these two subsystems reduces the core's surface area by ~220 source LOC, eliminates the join-mode settings system, and simplifies the completion callback path in `index.ts`.
16
+
17
+ The **output file** subsystem (`src/output-file.ts`) is retained — it provides valuable post-hoc debugging transcripts for subagent sessions.
18
+ A separate issue (#61) tracks porting it to Pi's official JSONL session format.
19
+
20
+ ## Goals
21
+
22
+ - Delete `src/group-join.ts` (141 LOC) and `src/cross-extension-rpc.ts` (80 LOC).
23
+ - Delete `test/cross-extension-rpc.test.ts`.
24
+ - Remove all group-join wiring from `index.ts`: `GroupJoinManager` instantiation, batch tracking (`currentBatchAgents`, `finalizeBatch`, `batchFinalizeTimer`, `batchCounter`), join-mode configuration state, and settings menu entry.
25
+ - Remove all RPC wiring from `index.ts`: `registerRpcHandlers` import, `currentCtx` capture for RPC, `unsubPing/Spawn/Stop` teardown, and the `subagents:ready` broadcast.
26
+ - Remove `JoinMode` type and `joinMode`/`groupId` fields from `types.ts`.
27
+ - Remove `NotificationDetails.others` field (no longer needed without grouping).
28
+ - Remove `defaultJoinMode` from `SubagentsSettings` and `SettingsAppliers` in `settings.ts`.
29
+ - Remove `resolveJoinMode` from `invocation-config.ts`.
30
+ - Simplify the completion callback in `index.ts` to always send an individual notification.
31
+ - Preserve existing lifecycle events (`subagents:started`, `subagents:completed`, `subagents:failed`) — they are already emitted.
32
+ - This is a **breaking change** (`feat!:`) — the join-mode setting is removed and RPC channels are no longer registered.
33
+
34
+ ## Non-Goals
35
+
36
+ - Removing the `Symbol.for("pi-subagents:manager")` global accessor — that belongs to #48 (implement SubagentsAPI), which replaces it with the typed `publishSubagentsAPI()`.
37
+ - Removing `bypassQueue` from `SpawnOptions` — it remains useful for the typed API.
38
+ - Providing migration shims for RPC consumers — none known.
39
+ - Removing or modifying `src/output-file.ts` — retained for debugging value; porting to Pi's JSONL format is tracked in #61.
40
+
41
+ ## Background
42
+
43
+ The architecture doc marks these modules as "removing."
44
+ Issue #52 (remove scheduled subagents) is already implemented and merged.
45
+ Issue #48 (implement SubagentsAPI) depends on RPC removal here since the typed API replaces the untyped RPC.
46
+
47
+ The `index.ts` file is the primary wiring layer affected.
48
+ The completion callback currently routes through `groupJoin.onAgentComplete()` and only falls through to `sendIndividualNudge()` on `'pass'`.
49
+ After this change, the callback always calls `sendIndividualNudge()` directly, which simplifies the control flow from ~90 lines of group/batch logic down to a single function call.
50
+
51
+ The `currentCtx` variable captured in `session_start` exists solely for the RPC spawn handler.
52
+ After RPC removal, session lifecycle hooks simplify: `session_start` only needs `manager.clearCompleted()`.
53
+
54
+ ## Design Overview
55
+
56
+ This is a pure deletion change with minor simplification of the remaining completion path.
57
+
58
+ After removal, the background-agent completion flow becomes:
59
+
60
+ 1. `AgentManager` calls `onComplete(record)`.
61
+ 2. `onComplete` emits `subagents:completed` or `subagents:failed` on `pi.events`.
62
+ 3. `onComplete` persists the record via `pi.appendEntry`.
63
+ 4. If `record.resultConsumed`, clean up widget and return.
64
+ 5. Otherwise, call `sendIndividualNudge(record)` — which schedules the notification with a 200ms debounce window (retained for `get_subagent_result` cancellation).
65
+
66
+ The `NotificationDetails` interface stays (individual notifications still use it) but loses the `others` field.
67
+ The `outputFile` field on `NotificationDetails` stays since output-file is retained.
68
+
69
+ ### Settings changes
70
+
71
+ `SubagentsSettings` loses `defaultJoinMode`.
72
+ The settings menu loses the "Join mode" entry.
73
+ `snapshotSettings()` and `persistToastFor()` patterns are unchanged — they just carry one fewer field.
74
+
75
+ ### Types changes
76
+
77
+ ```typescript
78
+ // Remove from types.ts:
79
+ export type JoinMode = 'async' | 'group' | 'smart';
80
+
81
+ // Remove from AgentRecord:
82
+ groupId?: string;
83
+ joinMode?: JoinMode;
84
+
85
+ // Remove from NotificationDetails:
86
+ others?: NotificationDetails[];
87
+ ```
88
+
89
+ `AgentRecord.outputFile`, `outputCleanup`, and `toolCallId` are retained — they support the output-file subsystem which remains in scope.
90
+
91
+ ## Module-Level Changes
92
+
93
+ ### Delete
94
+
95
+ | File | Lines |
96
+ | ---------------------------------- | ----- |
97
+ | `src/group-join.ts` | 141 |
98
+ | `src/cross-extension-rpc.ts` | 80 |
99
+ | `test/cross-extension-rpc.test.ts` | ~220 |
100
+
101
+ ### Modify
102
+
103
+ | File | Change |
104
+ | ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
105
+ | `src/index.ts` | Remove imports for group-join and RPC modules. Remove `GroupJoinManager` instantiation and the grouped-delivery callback (~30 lines). Remove batch tracking state and `finalizeBatch()` (~40 lines). Remove join-mode state (`defaultJoinMode`, `getDefaultJoinMode`, `setDefaultJoinMode`). Remove RPC registration, `currentCtx` capture, `unsubPing/Spawn/Stop` teardown. Remove `subagents:ready` emit. Remove "Join mode" settings menu entry and `snapshotSettings` join-mode field. Simplify `onComplete` callback to always call `sendIndividualNudge`. Remove the `currentBatchAgents` deferred-notification check. Remove join-mode resolution in background spawn path. |
106
+ | `src/types.ts` | Remove `JoinMode` type. Remove `groupId` and `joinMode` from `AgentRecord`. Remove `others` from `NotificationDetails`. |
107
+ | `src/settings.ts` | Remove `JoinMode` import. Remove `defaultJoinMode` from `SubagentsSettings`. Remove `setDefaultJoinMode` from `SettingsAppliers`. Remove `VALID_JOIN_MODES`. Remove sanitize clause and `applySettings` clause for `defaultJoinMode`. |
108
+ | `src/invocation-config.ts` | Remove `JoinMode` import. Remove `resolveJoinMode` export. |
109
+ | `README.md` | Remove "Cross-extension RPC" section. Remove join-mode documentation. Remove `subagents:ready` from events table. Update settings persistence paragraph to drop join-mode. |
110
+ | `.pi/skills/package-pi-subagents/SKILL.md` | Remove `cross-extension-rpc.ts` and `group-join.ts` from architecture diagram and module tables. Update `index.ts` description. |
111
+
112
+ ## Test Impact Analysis
113
+
114
+ 1. No new unit tests are needed — this is pure deletion.
115
+ 2. `test/cross-extension-rpc.test.ts` becomes entirely redundant and is deleted.
116
+ 3. `test/output-file.test.ts` is retained (output-file stays).
117
+ 4. There is no dedicated `group-join.test.ts` — the group-join logic was only tested indirectly through integration.
118
+ 5. Existing tests for `agent-manager`, `agent-runner`, `settings`, and `invocation-config` must be checked for references to `joinMode`, `groupId`, `defaultJoinMode`, or `resolveJoinMode` — any such references need updating.
119
+ 6. The notification renderer test (if any) may reference `others` on `NotificationDetails` — check and remove.
120
+
121
+ ## TDD Order
122
+
123
+ Since this is a removal (not a feature), the order is deletion-first with validation passes.
124
+
125
+ 1. **Delete source files for both subsystems.**
126
+ Delete `src/group-join.ts`, `src/cross-extension-rpc.ts`.
127
+ Delete `test/cross-extension-rpc.test.ts`.
128
+ Commit: `feat!: remove group-join and cross-extension-rpc source`
129
+
130
+ 2. **Remove RPC wiring from `index.ts`.**
131
+ Remove `registerRpcHandlers` import and call. Remove `currentCtx` state and RPC-related `session_start`/`session_shutdown` logic (keep `manager.clearCompleted()` call). Remove `unsubPing/Spawn/Stop` teardown. Remove `subagents:ready` emit.
132
+ Commit: `feat!: remove RPC wiring from index.ts`
133
+
134
+ 3. **Remove group-join wiring from `index.ts`.**
135
+ Remove `GroupJoinManager` import and instantiation (including the grouped-delivery callback). Remove batch tracking (`currentBatchAgents`, `batchFinalizeTimer`, `batchCounter`, `finalizeBatch`). Remove `defaultJoinMode` state, `getDefaultJoinMode`, `setDefaultJoinMode`. Remove join-mode resolution in background spawn path. Remove "Join mode" settings menu entry. Remove `defaultJoinMode` from `snapshotSettings()`. Simplify the `onComplete` callback: remove `currentBatchAgents` check and `groupJoin.onAgentComplete()` routing — always call `sendIndividualNudge(record)`. Remove `setDefaultJoinMode` from `applyAndEmitLoaded` appliers.
136
+ Commit: `feat!: remove group-join wiring from index.ts`
137
+
138
+ 4. **Clean up types, settings, and invocation-config.**
139
+ Remove `JoinMode` type from `types.ts`. Remove `groupId` and `joinMode` from `AgentRecord`. Remove `others` from `NotificationDetails`. Remove `defaultJoinMode` from `SubagentsSettings` and `SettingsAppliers` in `settings.ts`. Remove `VALID_JOIN_MODES` and sanitize/apply clauses. Remove `resolveJoinMode` and `JoinMode` import from `invocation-config.ts`.
140
+ Commit: `feat!: remove join-mode types and settings`
141
+
142
+ 5. **Verify all tests pass and fix straggling references.**
143
+ Run `pnpm vitest run` and `pnpm run check`. Fix any test fixtures or assertions that reference removed fields (`joinMode`, `groupId`, `defaultJoinMode`, `resolveJoinMode`).
144
+ Commit (if fixes needed): `test: remove references to deleted subsystems from test fixtures`
145
+
146
+ 6. **Update documentation.**
147
+ Update `README.md`: remove "Cross-extension RPC" section, join-mode documentation, `subagents:ready` event row. Update settings persistence paragraph.
148
+ Update `.pi/skills/package-pi-subagents/SKILL.md`: remove `cross-extension-rpc.ts` and `group-join.ts` from architecture diagram and module tables, update `index.ts` description.
149
+ Commit: `docs: remove group-join and RPC from README and AGENTS`
150
+
151
+ ## Risks and Mitigations
152
+
153
+ | Risk | Mitigation |
154
+ | --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
155
+ | Missed references cause compile errors | `grep -rn 'group.join\|GroupJoin\|registerRpcHandlers\|resolveJoinMode\|JoinMode' src/` after each step. `pnpm run check` catches import errors. |
156
+ | Test fixtures reference removed fields | Step 5 explicitly scans for and fixes these. TypeScript `noEmit` check catches type mismatches. |
157
+ | `Symbol.for("pi-subagents:manager")` accidentally removed | Explicitly out of scope — this belongs to #48. The global accessor stays until the typed API replaces it. |
158
+ | Breaking change not communicated | `feat!:` commit prefix triggers a major version bump via release-please. |
159
+ | Settings file with `defaultJoinMode` on disk | `sanitize()` already drops unknown fields silently — once the field is removed from the interface, existing files just have an inert JSON key that is ignored on load. |
160
+
161
+ ## Open Questions
162
+
163
+ None — the issue scope is fully specified and the architecture doc ratified these removals.
@@ -0,0 +1,131 @@
1
+ ---
2
+ issue: 52
3
+ issue_title: "feat: remove in-process scheduled subagents"
4
+ ---
5
+
6
+ # Remove in-process scheduled subagents
7
+
8
+ ## Problem Statement
9
+
10
+ The scheduling subsystem reimplements OS-level cron inside a process that is not designed to be a long-lived daemon.
11
+ System cron (or launchd) invoking `pi` directly is strictly superior: it survives crashes and reboots, is inspectable via `crontab -l`, and adds zero lines of code to this extension.
12
+ The current implementation weighs ~610 source lines plus ~820 test lines, a `croner` dependency, PID-locked file persistence, and scheduler lifecycle wiring scattered across `index.ts`.
13
+
14
+ ## Goals
15
+
16
+ - Delete the three scheduling source files (`schedule.ts`, `schedule-store.ts`, `ui/schedule-menu.ts`).
17
+ - Delete the three scheduling test files (`schedule.test.ts`, `schedule-store.test.ts`, `schedule-e2e.test.ts`).
18
+ - Remove all scheduler wiring from `index.ts` (~200 lines of imports, lifecycle hooks, tool-schema gates, and menu routing).
19
+ - Remove `ScheduledSubagent` and `ScheduleStoreData` interfaces from `types.ts`.
20
+ - Remove `schedulingEnabled` from `SubagentsSettings`, `SettingsAppliers`, and related sanitize/apply logic in `settings.ts`.
21
+ - Remove the `croner` dependency from `package.json`.
22
+ - Update `README.md` (remove "Scheduling" section and events-table rows) and package `AGENTS.md` (remove scheduling modules from architecture diagram and tables).
23
+ - This is a **breaking change** (`feat!:`) — the `schedule` parameter is removed from the `Agent` tool, and the `subagents:scheduled` / `subagents:scheduler_ready` events are no longer emitted.
24
+
25
+ ## Non-Goals
26
+
27
+ - Removing `bypassQueue` from `SpawnOptions` in `agent-manager.ts` — it remains useful for cross-extension RPC callers.
28
+ - Removing other subsystems slated for removal in the architecture doc (output-file, cross-extension-rpc, group-join) — those are separate issues.
29
+ - Providing a migration path or compatibility shim — no known consumers depend on the scheduling events.
30
+
31
+ ## Background
32
+
33
+ The architecture doc (`docs/architecture/architecture.md`) already marks `schedule.ts`, `schedule-store.ts`, and `ui/schedule-menu.ts` as `← removing`.
34
+ This issue executes that plan.
35
+
36
+ The scheduling code touches `index.ts` in several distinct regions:
37
+
38
+ 1. Imports (lines 27–28, 46)
39
+ 2. Scheduler instance creation and `startScheduler()` helper (lines 445–462)
40
+ 3. Lifecycle hooks: `session_start`, `session_before_switch`, `session_shutdown` (lines 470–496)
41
+ 4. The `schedule` tool-schema param shape, conditional inclusion, and guideline string (lines 621–640, 666, 719)
42
+ 5. Schedule execution path in the Agent tool handler (lines 880–918)
43
+ 6. `/agents` menu: "Scheduled jobs" entry and routing (lines 1297–1327)
44
+ 7. `/agents → Settings → Scheduling` toggle (lines 1855–1867)
45
+
46
+ The `settings.ts` module has `schedulingEnabled` woven into `SubagentsSettings`, `SettingsAppliers`, `sanitize()`, and `applySettings()`.
47
+
48
+ `types.ts` carries `ScheduledSubagent` (30 lines) and `ScheduleStoreData` (5 lines) — both are only consumed by the scheduling subsystem.
49
+
50
+ ## Design Overview
51
+
52
+ This is a pure deletion change with no new abstractions.
53
+ The approach is inside-out: delete leaf modules first (no dependents), then remove references from the wiring layer (`index.ts`, `settings.ts`, `types.ts`), then clean up docs.
54
+
55
+ The `bypassQueue` option on `SpawnOptions` stays — its JSDoc comment mentioning "scheduler" should be updated to a generic description since the scheduler is the only current user but the option is architecturally useful for any caller that needs to skip the concurrency queue.
56
+
57
+ ## Module-Level Changes
58
+
59
+ ### Delete
60
+
61
+ | File | Lines |
62
+ | ----------------------------- | ----- |
63
+ | `src/schedule.ts` | 365 |
64
+ | `src/schedule-store.ts` | 143 |
65
+ | `src/ui/schedule-menu.ts` | 104 |
66
+ | `test/schedule.test.ts` | 429 |
67
+ | `test/schedule-store.test.ts` | 154 |
68
+ | `test/schedule-e2e.test.ts` | 237 |
69
+
70
+ ### Modify
71
+
72
+ | File | Change |
73
+ | ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
74
+ | `src/index.ts` | Remove scheduler imports, instance creation, `startScheduler()`, lifecycle hooks, `scheduleParamShape`/`scheduleParam`/`scheduleGuideline`, schedule execution path in Agent handler, "Scheduled jobs" menu entry + routing, "Scheduling" settings toggle. |
75
+ | `src/types.ts` | Remove `ScheduledSubagent` interface and `ScheduleStoreData` interface. |
76
+ | `src/settings.ts` | Remove `schedulingEnabled` from `SubagentsSettings` and `SettingsAppliers`. Remove sanitize clause and `applySettings` clause for `schedulingEnabled`. |
77
+ | `src/agent-manager.ts` | Update `bypassQueue` JSDoc to remove scheduler-specific language. |
78
+ | `package.json` | Remove `"croner": "^10.0.1"` from dependencies. |
79
+ | `README.md` | Remove "Scheduling" feature bullet, "Scheduling" subsection (lines 66–96), and `subagents:scheduled` / `subagents:scheduler_ready` rows from the events table. |
80
+ | `.pi/skills/package-pi-subagents/SKILL.md` | Remove `schedule.ts`, `schedule-store.ts`, `ui/schedule-menu.ts` from the architecture diagram and module tables. Update `index.ts` description to drop scheduler mention. (`packages/pi-subagents/AGENTS.md` is a stub — the architecture content lives in the skill file.) |
81
+
82
+ ## Test Impact Analysis
83
+
84
+ 1. No new unit tests are needed — this is pure deletion.
85
+ 2. All three scheduling test files (`schedule.test.ts`, `schedule-store.test.ts`, `schedule-e2e.test.ts`) become entirely redundant and are deleted.
86
+ 3. Existing tests for `agent-manager`, `agent-runner`, `settings`, and other modules stay as-is. The `settings.test.ts` file (if it exists) may need minor updates to remove `schedulingEnabled` from fixture data.
87
+
88
+ ## TDD Order
89
+
90
+ Since this is a removal (not a feature), the order is deletion-first with a single validation pass.
91
+
92
+ 1. **Delete scheduling source files.**
93
+ Delete `src/schedule.ts`, `src/schedule-store.ts`, `src/ui/schedule-menu.ts`.
94
+ Delete `test/schedule.test.ts`, `test/schedule-store.test.ts`, `test/schedule-e2e.test.ts`.
95
+ Commit: `feat!: remove scheduled subagents source and tests`
96
+
97
+ 2. **Remove scheduler wiring from `index.ts`.**
98
+ Remove imports, scheduler instance, `startScheduler()`, lifecycle hooks, schedule-related tool schema params and guideline, schedule execution path in Agent handler, "Scheduled jobs" menu entry/routing, and "Scheduling" settings toggle.
99
+ Commit: `feat!: remove scheduler wiring from index.ts`
100
+
101
+ 3. **Clean up types and settings.**
102
+ Remove `ScheduledSubagent` and `ScheduleStoreData` from `types.ts`.
103
+ Remove `schedulingEnabled` from `SubagentsSettings`, `SettingsAppliers`, `sanitize()`, and `applySettings()` in `settings.ts`.
104
+ Update `bypassQueue` JSDoc in `agent-manager.ts`.
105
+ Commit: `feat!: remove scheduling types and settings`
106
+
107
+ 4. **Remove `croner` dependency.**
108
+ Remove from `package.json`, run `pnpm install` to update lockfile.
109
+ Commit: `build: remove croner dependency`
110
+
111
+ 5. **Verify all tests pass.**
112
+ Run `pnpm vitest run` in the package. Fix any test fixtures that reference `schedulingEnabled` or scheduling types.
113
+ Commit (if fixes needed): `test: remove scheduling references from test fixtures`
114
+
115
+ 6. **Update documentation.**
116
+ Update `README.md`: remove scheduling feature bullet, "Scheduling" subsection, and event-table rows.
117
+ Update package `AGENTS.md`: remove scheduling modules from architecture diagram and module tables, update `index.ts` description.
118
+ Commit: `docs: remove scheduling from README and AGENTS`
119
+
120
+ ## Risks and Mitigations
121
+
122
+ | Risk | Mitigation |
123
+ | ------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
124
+ | Missed scheduling reference causes compile error | `grep -rn 'schedule\|Schedule\|croner' src/` after each step to catch stragglers. TypeScript `noEmit` check catches import errors. |
125
+ | Test fixtures reference `schedulingEnabled` | Step 5 explicitly scans for and fixes these. |
126
+ | `bypassQueue` removal mistakenly included | Explicitly excluded in Non-Goals; plan preserves the option and only updates its JSDoc. |
127
+ | Breaking change not communicated | `feat!:` commit prefix triggers a major version bump via release-please. |
128
+
129
+ ## Open Questions
130
+
131
+ None — the issue scope is fully specified and the architecture doc already ratified this removal.
@@ -0,0 +1,33 @@
1
+ ---
2
+ issue: 51
3
+ issue_title: "docs: update ADR 0001 to reflect hard-fork decision"
4
+ ---
5
+
6
+ # Retro: #51 — docs: update ADR 0001 to reflect hard-fork decision
7
+
8
+ ## Final Retrospective (2026-05-16)
9
+
10
+ ### Session summary
11
+
12
+ Updated ADR 0001 (`docs/decisions/0001-deferred-patches.md`) to reflect the hard-fork decision documented in `docs/architecture/architecture.md`.
13
+ The change was planned, implemented, shipped, and released as `pi-subagents-v1.0.2` in a single clean pass with no rework.
14
+
15
+ ### Observations
16
+
17
+ #### What went well
18
+
19
+ - The entire plan→build→ship pipeline completed with zero corrections, zero CI failures, and zero user interventions.
20
+ - Parallel context gathering (issue body, `AGENTS.md`, ADR file, architecture doc, two skill files) in one tool call made the planning phase efficient.
21
+ - The 4-edit approach (`Edit` with a single call containing four `edits[]` entries) was well-matched to the task — each edit was small, unique, and non-overlapping.
22
+
23
+ #### What caused friction (agent side)
24
+
25
+ - No friction observed. The task was unambiguous and the tooling well-suited.
26
+
27
+ #### What caused friction (user side)
28
+
29
+ - No friction observed. The session required no user input beyond invoking the three slash commands.
30
+
31
+ ### Follow-ups identified
32
+
33
+ - The `package-pi-subagents` skill (`.pi/skills/package-pi-subagents/SKILL.md`) still frames the fork as "a friendly fork… carrying a small number of patches" with priorities like "stays as close to upstream as possible." This framing is now stale given the hard-fork commitment. A separate issue should update the skill to reflect the architecture document's posture.