@gotgenes/pi-subagents 6.8.2 → 6.8.3

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,15 @@ 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
+ ## [6.8.3](https://github.com/gotgenes/pi-packages/compare/pi-subagents-v6.8.2...pi-subagents-v6.8.3) (2026-05-22)
9
+
10
+
11
+ ### Documentation
12
+
13
+ * mark Step D1 complete in architecture.md ([#113](https://github.com/gotgenes/pi-packages/issues/113)) ([b42de23](https://github.com/gotgenes/pi-packages/commit/b42de238710931348336d6e7fd81bb000a0ab584))
14
+ * plan disambiguate SpawnOptions (public vs internal) ([#113](https://github.com/gotgenes/pi-packages/issues/113)) ([2f3cebc](https://github.com/gotgenes/pi-packages/commit/2f3cebc6623e0ba20c73145d8e7c6b9ffae6f875))
15
+ * **retro:** add retro notes for issue [#112](https://github.com/gotgenes/pi-packages/issues/112) ([2a59ed4](https://github.com/gotgenes/pi-packages/commit/2a59ed4e4f5462cdbf8df96e4b675a9c5ec6eb9d))
16
+
8
17
  ## [6.8.2](https://github.com/gotgenes/pi-packages/compare/pi-subagents-v6.8.1...pi-subagents-v6.8.2) (2026-05-22)
9
18
 
10
19
 
@@ -385,7 +385,7 @@ Each step is sequenced so it makes the next step easier.
385
385
  | ~~Settings relay~~ | ~~`AgentMenuDeps` (13 fields)~~ | **Fixed #109**: `SettingsManager` class; 6 callback fields collapsed to `settings: SettingsManager`; `AgentMenuDeps` now 8 fields |
386
386
  | ~~Post-construction mutation~~ | ~~`AgentRecord` non-transition state~~ | **Fixed #111**: `ExecutionState`, `WorktreeState`, `NotificationState` collaborators; `pendingSteers` moved to `AgentManager`; stats encapsulated behind mutation methods |
387
387
  | ~~Fire-and-forget callbacks~~ | ~~`AgentManagerOptions`~~ | **Fixed #112**: `AgentManagerObserver` interface; `observer` replaces 3 callbacks; `index.ts` constructs one observer object instead of 3 closure lambdas |
388
- | Duplicate `SpawnOptions` | `service.ts` + `agent-manager.ts` | Two incompatible shapes (JSON-friendly vs runtime types) with the same name |
388
+ | ~~Duplicate `SpawnOptions`~~ | ~~`service.ts` + `agent-manager.ts`~~ | **Fixed #113**: internal type renamed to `AgentSpawnConfig`; public `SpawnOptions` in `service.ts` unchanged |
389
389
  | Type dumping ground | `types.ts` | `NotificationDetails` used only by notification/renderer; ~~`DEFAULT_AGENT_NAMES` moved to `AgentTypeRegistry` (#108)~~; `AgentConfig` (21 fields) consumers use 2–4 each |
390
390
  | Wide dependency bags | `AgentToolDeps` (7), `AgentMenuDeps` (8) | Settings narrowed (#109); registry narrowed (#108); more narrowing planned in D steps |
391
391
 
@@ -456,10 +456,11 @@ The record doesn't accumulate half-baked state — it receives fully constructed
456
456
 
457
457
  With the registry class, settings manager, and observer in place, the dependency bags shrink naturally.
458
458
 
459
- #### D1. Disambiguate `SpawnOptions` (#113)
459
+ #### D1. Disambiguate `SpawnOptions` (#113)
460
460
 
461
- Rename the internal `SpawnOptions` in `agent-manager.ts` to `AgentSpawnConfig` (or similar) to distinguish it from the JSON-friendly public `SpawnOptions` in `service.ts`.
462
- The two types serve different consumers and should not share a name.
461
+ **Done.**
462
+ Internal `SpawnOptions` in `agent-manager.ts` renamed to `AgentSpawnConfig`.
463
+ Public `SpawnOptions` in `service.ts` is unchanged.
463
464
 
464
465
  #### D2. Narrow `AgentToolDeps` and `AgentMenuDeps` (#114)
465
466
 
@@ -0,0 +1,155 @@
1
+ ---
2
+ issue: 113
3
+ issue_title: "refactor(pi-subagents): disambiguate SpawnOptions (public vs internal)"
4
+ ---
5
+
6
+ # Disambiguate SpawnOptions (public vs internal)
7
+
8
+ ## Problem Statement
9
+
10
+ `SpawnOptions` is defined in two places with the same name but incompatible shapes:
11
+
12
+ - `service.ts` (public API): 8 fields, JSON-friendly (`model` is `string`, `thinkingLevel` is `string`, uses `foreground` not `isBackground`).
13
+ - `agent-manager.ts` (internal): 13 fields, runtime types (`model` is `Model<any>`, `thinkingLevel` is `ThinkingLevel`, includes `signal`, `onSessionCreated`, `invocation`).
14
+
15
+ The name collision makes it ambiguous which type a reader is working with when they see `SpawnOptions` in a signature.
16
+ `service-adapter.ts` manually converts between the two shapes.
17
+
18
+ ## Goals
19
+
20
+ - Rename the internal `SpawnOptions` in `agent-manager.ts` to `AgentSpawnConfig`.
21
+ - Keep the public `SpawnOptions` in `service.ts` unchanged — it's the published API.
22
+ - Update all internal consumers (`agent-tool.ts`, `agent-menu.ts`, `agent-manager.ts`) to use the new name.
23
+ - Update the `SpawnArgs` internal interface in `agent-manager.ts` to reference `AgentSpawnConfig`.
24
+ - Non-breaking refactor — the public API surface is unchanged.
25
+
26
+ ## Non-Goals
27
+
28
+ - Splitting `AgentSpawnConfig` into agent-configuration fields vs execution/lifecycle fields — the issue mentions this as a "consider" item; defer to a follow-up if the type grows further.
29
+ - Narrowing `AgentToolDeps` or `AgentMenuDeps` — tracked in #114.
30
+ - Removing `onSessionCreated` — it's a legitimate per-spawn callback used by `agent-tool.ts` for UI streaming, structurally different from the lifecycle observer (#112).
31
+
32
+ ## Background
33
+
34
+ ### Current consumers of internal `SpawnOptions`
35
+
36
+ | File | How it references `SpawnOptions` |
37
+ | --------------------- | ------------------------------------------------------------------------------------------- |
38
+ | `agent-manager.ts` | Defines the type; uses it in `spawn()`, `spawnAndWait()`, and `SpawnArgs` |
39
+ | `tools/agent-tool.ts` | Imports and uses in `AgentToolManager.spawn` and `AgentToolManager.spawnAndWait` signatures |
40
+ | `ui/agent-menu.ts` | Imports and uses in `AgentMenuManager.spawnAndWait` signature |
41
+
42
+ ### Public `SpawnOptions` in `service.ts`
43
+
44
+ Defined alongside `SubagentsService`.
45
+ Used by `service-adapter.ts` at the conversion boundary.
46
+ Published via `package.json` exports — **not touched by this change**.
47
+
48
+ ### Dependency: issue #112 (observer refactor)
49
+
50
+ Issue #112 is closed.
51
+ The observer eliminated `onStart`/`onComplete`/`onCompact` from `AgentManagerOptions`.
52
+ `onSessionCreated` remains on the internal `SpawnOptions` (now `AgentSpawnConfig`) — it's per-spawn, not per-manager.
53
+
54
+ ### Architecture reference
55
+
56
+ Phase 7, Step D1 in `docs/architecture/architecture.md`.
57
+
58
+ ## Design Overview
59
+
60
+ This is a pure rename — no structural or behavioral changes.
61
+ The internal `SpawnOptions` becomes `AgentSpawnConfig`.
62
+ Every `import type { SpawnOptions }` from `"../agent-manager.js"` or `"./agent-manager.js"` becomes `import type { AgentSpawnConfig }`.
63
+
64
+ The name `AgentSpawnConfig` was chosen because:
65
+
66
+ 1. It disambiguates from the public `SpawnOptions`.
67
+ 2. It follows the established naming convention in this package (`AgentRecord`, `AgentInvocation`, `AgentTypeRegistry`).
68
+ 3. "Config" conveys that this is a configuration bag assembled by the caller and consumed by the manager — not a service-level options type.
69
+
70
+ ### Type shape (unchanged)
71
+
72
+ ```typescript
73
+ export interface AgentSpawnConfig {
74
+ description: string;
75
+ model?: Model<any>;
76
+ maxTurns?: number;
77
+ isolated?: boolean;
78
+ inheritContext?: boolean;
79
+ thinkingLevel?: ThinkingLevel;
80
+ isBackground?: boolean;
81
+ bypassQueue?: boolean;
82
+ isolation?: IsolationMode;
83
+ invocation?: AgentInvocation;
84
+ signal?: AbortSignal;
85
+ onSessionCreated?: (session: AgentSession) => void;
86
+ parentSessionFile?: string;
87
+ parentSessionId?: string;
88
+ }
89
+ ```
90
+
91
+ ## Module-Level Changes
92
+
93
+ ### `src/agent-manager.ts`
94
+
95
+ - Rename `export interface SpawnOptions` → `export interface AgentSpawnConfig`.
96
+ - Update `SpawnArgs.options` type from `SpawnOptions` to `AgentSpawnConfig`.
97
+ - Update `spawn()` parameter type from `SpawnOptions` to `AgentSpawnConfig`.
98
+ - Update `spawnAndWait()` parameter type from `Omit<SpawnOptions, "isBackground">` to `Omit<AgentSpawnConfig, "isBackground">`.
99
+
100
+ ### `src/tools/agent-tool.ts`
101
+
102
+ - Change import from `SpawnOptions` to `AgentSpawnConfig`.
103
+ - Update `AgentToolManager.spawn` and `AgentToolManager.spawnAndWait` signatures.
104
+
105
+ ### `src/ui/agent-menu.ts`
106
+
107
+ - Change import from `SpawnOptions` to `AgentSpawnConfig`.
108
+ - Update `AgentMenuManager.spawnAndWait` signature.
109
+
110
+ ### `src/service.ts`
111
+
112
+ - No changes — the public `SpawnOptions` stays as-is.
113
+
114
+ ### `src/service-adapter.ts`
115
+
116
+ - No changes — it already uses `unknown` for the spawn options parameter in `AgentManagerLike`.
117
+
118
+ ### `test/agent-manager.test.ts`
119
+
120
+ - No import changes needed — the test file does not import `SpawnOptions`.
121
+ - One test description string mentions "SpawnOptions" → update to "AgentSpawnConfig" for accuracy.
122
+
123
+ ## Test Impact Analysis
124
+
125
+ 1. No new tests are enabled by this rename — it's a 1:1 name substitution.
126
+ 2. No existing tests become redundant.
127
+ 3. All existing tests stay as-is — they construct raw object literals that structurally satisfy the type regardless of its name.
128
+
129
+ ## TDD Order
130
+
131
+ ### Step 1: Rename `SpawnOptions` to `AgentSpawnConfig` and update all consumers
132
+
133
+ 1. Rename the interface in `agent-manager.ts`.
134
+ 2. Update `SpawnArgs`, `spawn()`, and `spawnAndWait()` in `agent-manager.ts`.
135
+ 3. Update the import and signatures in `tools/agent-tool.ts`.
136
+ 4. Update the import and signature in `ui/agent-menu.ts`.
137
+ 5. Update the test description string in `test/agent-manager.test.ts`.
138
+ 6. Run `pnpm run check` to verify types.
139
+ 7. Run `pnpm vitest run` to verify all tests pass.
140
+
141
+ - Commit: `refactor: rename internal SpawnOptions to AgentSpawnConfig (#113)`
142
+
143
+ This is a single-step refactor because the rename is mechanical and all consumers must be updated atomically for the type checker to stay green.
144
+
145
+ ## Risks and Mitigations
146
+
147
+ | Risk | Mitigation |
148
+ | -------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
149
+ | Missed consumer still references old name | `pnpm run check` will catch any unresolved `SpawnOptions` import from `agent-manager.ts` since the export no longer exists |
150
+ | Test descriptions become misleading | Grep for "SpawnOptions" in test files and update any description strings that reference the old name |
151
+ | Confusion with `service.ts` `SpawnOptions` during review | The plan is scoped to internal-only changes; `service.ts` is explicitly listed as "no changes" |
152
+
153
+ ## Open Questions
154
+
155
+ - None — the rename is unambiguous and aligns with both the issue proposal and the architecture doc.
@@ -0,0 +1,35 @@
1
+ ---
2
+ issue: 112
3
+ issue_title: "refactor(pi-subagents): replace AgentManager callbacks with observer interface"
4
+ ---
5
+
6
+ # Retro: #112 — replace AgentManager callbacks with observer interface
7
+
8
+ ## Final Retrospective (2026-05-21T21:00:00-04:00)
9
+
10
+ ### Session summary
11
+
12
+ Replaced three fire-and-forget callback fields (`onStart`, `onComplete`, `onCompact`) on `AgentManagerOptions` with a single `AgentManagerObserver` interface.
13
+ The refactoring touched `agent-manager.ts`, `index.ts`, and `agent-manager.test.ts` with zero test-count delta (652/652).
14
+ Released as `pi-subagents-v6.8.2`.
15
+
16
+ ### Observations
17
+
18
+ #### What went well
19
+
20
+ - The issue description was thorough and unambiguous — no `ask_user` needed during planning, and the design mapped directly to implementation.
21
+ - Self-identified the testing skill's single-call-site rule during execution: the plan split Steps 2 and 3 into separate commits, but `AgentManagerOptions` has one call site in `index.ts`, so both had to land together.
22
+ Merged them without rework.
23
+ - Pre-existing lint issue (unused `ExecutionState` import in `agent-manager.ts`) caught and fixed proactively during the lint step.
24
+
25
+ #### What caused friction (agent side)
26
+
27
+ - `instruction-violation` (self-identified) — The plan wrote TDD Steps 2 and 3 as separate commits, but the testing skill says "when a TDD step changes an interface that has a single call site, the step must include updating that call site."
28
+ The planning phase loaded the testing skill but didn't apply this specific rule when structuring the TDD order.
29
+ Impact: added friction but no rework — caught during execution when `pnpm run check` surfaced the expected type error in `index.ts` after Step 2.
30
+ - `other` (tool interaction) — One `Edit` tool `oldText` match failure in `agent-manager.ts` because the selected block included a blank line that didn't exist between `subscribeRecordObserver` and `options.onSessionCreated`.
31
+ Impact: one extra read + edit cycle (~30 seconds).
32
+
33
+ #### What caused friction (user side)
34
+
35
+ - Nothing — the session ran without user corrections or redirections.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gotgenes/pi-subagents",
3
- "version": "6.8.2",
3
+ "version": "6.8.3",
4
4
  "exports": {
5
5
  ".": "./src/service.ts"
6
6
  },
@@ -47,10 +47,10 @@ interface SpawnArgs {
47
47
  snapshot: ParentSnapshot;
48
48
  type: SubagentType;
49
49
  prompt: string;
50
- options: SpawnOptions;
50
+ options: AgentSpawnConfig;
51
51
  }
52
52
 
53
- export interface SpawnOptions {
53
+ export interface AgentSpawnConfig {
54
54
  description: string;
55
55
  model?: Model<any>;
56
56
  maxTurns?: number;
@@ -138,7 +138,7 @@ export class AgentManager {
138
138
  ctx: ExtensionContext,
139
139
  type: SubagentType,
140
140
  prompt: string,
141
- options: SpawnOptions,
141
+ options: AgentSpawnConfig,
142
142
  ): string {
143
143
  const id = randomUUID().slice(0, 17);
144
144
  const abortController = new AbortController();
@@ -321,7 +321,7 @@ export class AgentManager {
321
321
  ctx: ExtensionContext,
322
322
  type: SubagentType,
323
323
  prompt: string,
324
- options: Omit<SpawnOptions, "isBackground">,
324
+ options: Omit<AgentSpawnConfig, "isBackground">,
325
325
  ): Promise<AgentRecord> {
326
326
  const id = this.spawn(ctx, type, prompt, { ...options, isBackground: false });
327
327
  const record = this.agents.get(id)!;
@@ -1,7 +1,7 @@
1
1
  import type { AgentToolResult, ExtensionContext } from "@earendil-works/pi-coding-agent";
2
2
  import { Text } from "@earendil-works/pi-tui";
3
3
  import { Type } from "@sinclair/typebox";
4
- import type { SpawnOptions } from "../agent-manager.js";
4
+ import type { AgentSpawnConfig } from "../agent-manager.js";
5
5
  import { normalizeMaxTurns } from "../agent-runner.js";
6
6
  import { AgentTypeRegistry } from "../agent-types.js";
7
7
  import { resolveAgentInvocationConfig } from "../invocation-config.js";
@@ -75,8 +75,8 @@ export function buildDetails(
75
75
 
76
76
  /** Narrow manager interface — only the methods the Agent tool calls. */
77
77
  export interface AgentToolManager {
78
- spawn: (ctx: ExtensionContext, type: string, prompt: string, opts: SpawnOptions) => string;
79
- spawnAndWait: (ctx: ExtensionContext, type: string, prompt: string, opts: Omit<SpawnOptions, "isBackground">) => Promise<AgentRecord>;
78
+ spawn: (ctx: ExtensionContext, type: string, prompt: string, opts: AgentSpawnConfig) => string;
79
+ spawnAndWait: (ctx: ExtensionContext, type: string, prompt: string, opts: Omit<AgentSpawnConfig, "isBackground">) => Promise<AgentRecord>;
80
80
  resume: (id: string, prompt: string, signal: AbortSignal) => Promise<AgentRecord | undefined>;
81
81
  getRecord: (id: string) => AgentRecord | undefined;
82
82
  getMaxConcurrent: () => number;
@@ -2,7 +2,7 @@ import { existsSync, mkdirSync, readFileSync, unlinkSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
 
4
4
  import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
5
- import type { SpawnOptions } from "../agent-manager.js";
5
+ import type { AgentSpawnConfig } from "../agent-manager.js";
6
6
  import {
7
7
  AgentTypeRegistry,
8
8
  BUILTIN_TOOL_NAMES,
@@ -19,7 +19,7 @@ export interface AgentMenuManager {
19
19
  listAgents: () => AgentRecord[];
20
20
  getRecord: (id: string) => AgentRecord | undefined;
21
21
  /** Used by generate wizard to spawn an agent that writes the .md file. */
22
- spawnAndWait: (ctx: ExtensionContext, type: string, prompt: string, opts: Omit<SpawnOptions, "isBackground">) => Promise<AgentRecord>;
22
+ spawnAndWait: (ctx: ExtensionContext, type: string, prompt: string, opts: Omit<AgentSpawnConfig, "isBackground">) => Promise<AgentRecord>;
23
23
  }
24
24
 
25
25
  /** Narrow settings interface required by the agent menu. */