@gotgenes/pi-subagents 13.2.1 → 13.2.2

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 (42) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +3 -1
  3. package/dist/public.d.ts +34 -35
  4. package/docs/architecture/architecture.md +50 -49
  5. package/docs/architecture/history/phase-16-invert-dependencies.md +2 -1
  6. package/docs/decisions/0003-publish-bundled-type-declarations.md +3 -1
  7. package/docs/plans/0051-update-adr-0001-hard-fork.md +8 -6
  8. package/docs/plans/0257-extract-child-session-factory.md +3 -1
  9. package/docs/plans/0262-add-workspace-provider-seam.md +41 -39
  10. package/docs/plans/0264-remove-extension-lifecycle-control.md +100 -98
  11. package/docs/plans/0265-born-complete-subagent-session.md +5 -2
  12. package/docs/plans/0270-type-consumable-public-surface.md +3 -1
  13. package/docs/plans/0280-rename-agent-to-subagent.md +197 -0
  14. package/docs/retro/0051-update-adr-0001-hard-fork.md +4 -2
  15. package/docs/retro/0257-extract-child-session-factory.md +3 -1
  16. package/docs/retro/0262-add-workspace-provider-seam.md +3 -1
  17. package/docs/retro/0264-remove-extension-lifecycle-control.md +3 -1
  18. package/docs/retro/0270-type-consumable-public-surface.md +4 -2
  19. package/docs/retro/0280-rename-agent-to-subagent.md +96 -0
  20. package/package.json +1 -1
  21. package/src/index.ts +9 -9
  22. package/src/lifecycle/create-subagent-session.ts +1 -1
  23. package/src/lifecycle/{agent-manager.ts → subagent-manager.ts} +27 -27
  24. package/src/lifecycle/subagent-session.ts +2 -2
  25. package/src/lifecycle/{agent.ts → subagent.ts} +28 -28
  26. package/src/lifecycle/turn-limits.ts +1 -1
  27. package/src/lifecycle/workspace.ts +2 -2
  28. package/src/observation/notification.ts +9 -9
  29. package/src/observation/record-observer.ts +9 -9
  30. package/src/runtime.ts +1 -1
  31. package/src/service/service-adapter.ts +10 -10
  32. package/src/service/service.ts +5 -9
  33. package/src/tools/agent-tool.ts +5 -5
  34. package/src/tools/background-spawner.ts +3 -3
  35. package/src/tools/foreground-runner.ts +5 -5
  36. package/src/tools/get-result-tool.ts +2 -2
  37. package/src/tools/steer-tool.ts +2 -2
  38. package/src/types.ts +1 -1
  39. package/src/ui/agent-creation-wizard.ts +2 -2
  40. package/src/ui/agent-menu.ts +5 -5
  41. package/src/ui/agent-widget.ts +2 -2
  42. package/src/ui/conversation-viewer.ts +3 -3
@@ -0,0 +1,197 @@
1
+ ---
2
+ issue: 280
3
+ issue_title: "Rename the internal Agent class to Subagent"
4
+ ---
5
+
6
+ # Rename the internal `Agent` class to `Subagent`
7
+
8
+ ## Problem Statement
9
+
10
+ The internal lifecycle class `Agent` (`src/lifecycle/agent.ts`) models a single spawned subagent, but the bare name `Agent` collides with two unrelated concepts in the same code: the parent Pi agent that invokes our tooling, and the SDK's `AgentSession` that each subagent wraps.
11
+ The public API already standardized on the `Subagent*` family (`SubagentsService`, `SubagentRecord`, `SubagentStatus`, `SubagentType`, and — after [#265] — `SubagentSession` / `createSubagentSession`).
12
+ The internal lifecycle layer is the lone holdout still using bare `Agent*`.
13
+ Renaming the subagent-instance cluster closes that inconsistency and removes the parent/child/SDK ambiguity.
14
+
15
+ ## Goals
16
+
17
+ - Rename the subagent-instance cluster in `src/lifecycle/` to the `Subagent*` family: `Agent` → `Subagent`, `AgentManager` → `SubagentManager`, `AgentInit` → `SubagentInit`, `AgentLifecycleObserver` → `SubagentLifecycleObserver`, `AgentManagerObserver` → `SubagentManagerObserver`, `AgentManagerOptions` → `SubagentManagerOptions`, `AgentObserverOptions` → `SubagentObserverOptions`, `AgentManagerLike` → `SubagentManagerLike`.
18
+ - Consolidate the duplicate `AgentStatus` union into the existing public `SubagentStatus`, deleting the duplicate and re-pointing `WorkspaceDisposeOutcome.status`.
19
+ - Rename the lifecycle module files to match their primary export: `agent.ts` → `subagent.ts`, `agent-manager.ts` → `subagent-manager.ts`, plus the matching test files and the `make-agent.ts` test helper.
20
+ - Extend the rename to adjacent identifiers in the same cluster for full consistency: the `subscribeAgentObserver` function → `subscribeSubagentObserver`, the `SubagentManagerObserver` methods `onAgent*` → `onSubagent*`, and the `createTestAgent` helper → `createTestSubagent`.
21
+ - Update residual bare `Agent` / `AgentManager` references in lifecycle comments, JSDoc, and error strings — the acceptance grep matches these, not just symbols.
22
+ - Update `docs/architecture/architecture.md` to the new names.
23
+ - This is internal-only and non-breaking — the exported surface is unchanged apart from `WorkspaceDisposeOutcome.status` reading `SubagentStatus` (an identical union), so commits use `refactor:`, never `feat!:`.
24
+
25
+ ## Non-Goals
26
+
27
+ - The agent-type/config axis stays untouched: `AgentConfig`, `AgentType`, `AgentTypeRegistry`, `AgentConfigLookup`, `AgentInvocation`, `AgentPromptConfig`, `AgentCategories`.
28
+ - The UI/tool surface stays untouched: `AgentTool` (+ `AgentTool*` variants), `AgentSpawnConfig`, `AgentWidget`, `AgentsMenuHandler`, `AgentActivityTracker`, `AgentDetails`, `AgentCreationWizard`, `AgentConfigEditor`, `AgentFileOps`.
29
+ - SDK types stay untouched: `AgentSession`, `AgentSessionEvent`.
30
+ - Internal field/method names that do not contain the bare `Agent` word — `listAgents`, `getRecord`, the `agents` map, and `record:` parameters — are left as-is; they are not bare-`Agent` symbols and the acceptance grep does not flag them.
31
+ - No behavior changes: this is a pure rename plus a structurally no-op type consolidation.
32
+
33
+ ## Background
34
+
35
+ Relevant modules (Lifecycle domain unless noted):
36
+
37
+ - `src/lifecycle/agent.ts` — defines `Agent`, `AgentInit`, `AgentLifecycleObserver`, and the duplicate `AgentStatus` union; owns the full execution lifecycle (`run`, `resume`, `abort`, `steer`, status transitions, workspace disposal).
38
+ Contains bare-`Agent` JSDoc and two error strings (`"Agent not configured for execution …"`, `"Agent not configured for resume …"`).
39
+ - `src/lifecycle/agent-manager.ts` — defines `AgentManager`, `AgentManagerObserver` (methods `onAgentStarted` / `onAgentCompleted` / `onAgentCompacted` / `onAgentCreated`), `AgentManagerOptions`, and `AgentSpawnConfig` (out of scope).
40
+ - `src/lifecycle/workspace.ts` — `WorkspaceDisposeOutcome.status` is typed as the internal `AgentStatus`, imported from `#src/lifecycle/agent`.
41
+ - `src/observation/record-observer.ts` — defines `AgentObserverOptions` and the `subscribeAgentObserver` function.
42
+ - `src/service/service.ts` — defines the public `SubagentStatus` union (verbatim duplicate of `AgentStatus`) and re-exports `LifetimeUsage`, `Workspace`, and the four workspace collaborator types from the lifecycle layer.
43
+ - `src/service/service-adapter.ts` — defines the `AgentManagerLike` test seam.
44
+ - `src/types.ts` — barrel that re-exports `Agent` from `#src/lifecycle/agent`; most consumers import `Agent` via this barrel.
45
+ - `test/helpers/make-agent.ts` — exports `createTestAgent`, imported by ~16 test files.
46
+
47
+ Blast radius is mechanical but wide (~360 occurrences, dominated by the `Agent` class via the `types.ts` barrel).
48
+ `typescript` + `tsserver` are available, so each rename is a scope-aware language-service pass verified by `pnpm run check`; the occurrence count does not drive scope.
49
+
50
+ Constraints from AGENTS.md and skills that apply:
51
+
52
+ - Within a package, import siblings via `#src/` / `#test/` aliases (eslint enforces this) — the file moves must preserve alias imports, not introduce relative paths.
53
+ - After a barrel rename, verify at least one consumer still imports the renamed symbol from the barrel — many consumers import `Subagent` from `#src/types`, so this holds.
54
+ - The public `dist/public.d.ts` bundle is rolled from `src/service/service.ts`; run `pnpm run verify:public-types` after touching the public surface or the status consolidation.
55
+ - Load the `mermaid` skill before editing the architecture doc's class/sequence diagrams.
56
+
57
+ ## Design Overview
58
+
59
+ ### Status consolidation and the layering constraint
60
+
61
+ `AgentStatus` (in `agent.ts`) and `SubagentStatus` (in `service.ts`) are identical seven-member unions (`queued | running | completed | steered | aborted | stopped | error`).
62
+ The issue asks `WorkspaceDisposeOutcome.status` to point at the public `SubagentStatus`.
63
+
64
+ A naive fix — importing `SubagentStatus` from `service.ts` into `workspace.ts` — would create a circular dependency: `service.ts` already imports the workspace collaborator types (`WorkspaceDisposeOutcome`, …) from `workspace.ts`, so `workspace.ts → service.ts` reverses an existing arrow.
65
+ The correct single home is the lifecycle layer, mirroring how `service.ts` already re-exports `LifetimeUsage` from `#src/lifecycle/usage` and the workspace types from `#src/lifecycle/workspace`:
66
+
67
+ - Keep the union defined in the lifecycle layer (in the renamed `subagent.ts`), renamed `AgentStatus` → `SubagentStatus`.
68
+ - `service.ts` deletes its local definition and adds `export type { SubagentStatus } from "#src/lifecycle/subagent";` alongside its existing re-exports.
69
+ - `workspace.ts` imports `SubagentStatus` from `#src/lifecycle/subagent` (it already imports `AgentStatus` from the same module today — only the symbol name and, after the file move, the path change).
70
+
71
+ The `subagent ↔ workspace` relationship is type-only and already exists (`subagent.ts` imports `Workspace` / `WorkspaceProvider` from `workspace.ts`; `workspace.ts` imports the status union from `subagent.ts`), so no new runtime cycle is introduced — type-only imports are erased.
72
+
73
+ `rollup-plugin-dts` inlines `#src/*` types, so `dist/public.d.ts` still emits the same `SubagentStatus` union literal — structurally a no-op for consumers, confirmed by `verify:public-types`.
74
+
75
+ ```typescript
76
+ // src/lifecycle/subagent.ts (renamed from agent.ts)
77
+ export type SubagentStatus =
78
+ | "queued" | "running" | "completed" | "steered"
79
+ | "aborted" | "stopped" | "error";
80
+
81
+ // src/service/service.ts — delete local def, re-export instead
82
+ export type { SubagentStatus } from "#src/lifecycle/subagent";
83
+
84
+ // src/lifecycle/workspace.ts
85
+ import type { SubagentStatus } from "#src/lifecycle/subagent";
86
+ export interface WorkspaceDisposeOutcome {
87
+ status: SubagentStatus;
88
+ description: string;
89
+ }
90
+ ```
91
+
92
+ ### Rename mechanics
93
+
94
+ Each symbol rename is an atomic, scope-aware language-service operation (the API behind LSP "Rename Symbol"); after each, `pnpm run check` verifies the tree compiles.
95
+ Because a rename updates every reference in one pass and leaves the build green, each logical rename is its own commit with the repository in a valid state — no lift-and-shift staging is required (a rename is not a type replacement; old and new names never coexist).
96
+
97
+ Symbol renames do not touch comments, JSDoc, or string literals.
98
+ There are 26 bare `Agent` and 4 bare `AgentManager` word-occurrences in `src/lifecycle/` comments/strings (e.g. the two `"Agent not configured …"` error messages and cross-file JSDoc in `turn-limits.ts`, `create-subagent-session.ts`, `subagent-session.ts`).
99
+ The acceptance criterion greps `src/lifecycle/` for bare `Agent` / `AgentManager`, so each rename step must also sweep residual comment/string occurrences.
100
+ Compound names (`AgentSession`, `AgentInvocation`, `AgentTypeRegistry`) are not bare-word matches and stay.
101
+
102
+ ### Full-consistency adjacent identifiers
103
+
104
+ Per the scope decision, the rename extends to the rest of the cluster's naming so no `Agent`-as-subagent identifier survives:
105
+
106
+ - `src/observation/record-observer.ts`: `subscribeAgentObserver` → `subscribeSubagentObserver`, `AgentObserverOptions` → `SubagentObserverOptions`.
107
+ - `src/lifecycle/subagent-manager.ts`: `SubagentManagerObserver` methods `onAgentStarted` / `onAgentCompleted` / `onAgentCompacted` / `onAgentCreated` → `onSubagentStarted` / `onSubagentCompleted` / `onSubagentCompacted` / `onSubagentCreated` (8 + 11 + 6 + 14 call sites across `src/` and `test/`, all updated by the language-service rename).
108
+ - `test/helpers/make-agent.ts`: `createTestAgent` → `createTestSubagent`, file → `make-subagent.ts` (~16 importers, including `make-deps.ts` and `ui-stubs.ts`).
109
+
110
+ ## Module-Level Changes
111
+
112
+ Renamed files (git move, preserving `#src/` / `#test/` alias imports):
113
+
114
+ - `src/lifecycle/agent.ts` → `src/lifecycle/subagent.ts`
115
+ - `src/lifecycle/agent-manager.ts` → `src/lifecycle/subagent-manager.ts`
116
+ - `test/lifecycle/agent.test.ts` → `test/lifecycle/subagent.test.ts`
117
+ - `test/lifecycle/agent-manager.test.ts` → `test/lifecycle/subagent-manager.test.ts`
118
+ - `test/helpers/make-agent.ts` → `test/helpers/make-subagent.ts`
119
+ - `test/helpers/make-agent.test.ts` → `test/helpers/make-subagent.test.ts`
120
+
121
+ Changed (symbols, members, imports, comments/strings):
122
+
123
+ - `src/lifecycle/subagent.ts` — `Agent` → `Subagent`, `AgentInit` → `SubagentInit`, `AgentLifecycleObserver` → `SubagentLifecycleObserver`, `AgentStatus` → `SubagentStatus` (kept here as the single home); update JSDoc and the two error strings.
124
+ - `src/lifecycle/subagent-manager.ts` — `AgentManager` → `SubagentManager`, `AgentManagerObserver` → `SubagentManagerObserver` (+ `onAgent*` methods → `onSubagent*`), `AgentManagerOptions` → `SubagentManagerOptions`; `AgentSpawnConfig` unchanged; update header comment.
125
+ - `src/lifecycle/workspace.ts` — import `SubagentStatus` from `#src/lifecycle/subagent`; `WorkspaceDisposeOutcome.status` retyped.
126
+ - `src/service/service.ts` — delete local `SubagentStatus` definition; add `export type { SubagentStatus } from "#src/lifecycle/subagent";`.
127
+ - `src/service/service-adapter.ts` — `AgentManagerLike` → `SubagentManagerLike`; update header comment referencing `AgentManager`.
128
+ - `src/observation/record-observer.ts` — `subscribeAgentObserver` → `subscribeSubagentObserver`, `AgentObserverOptions` → `SubagentObserverOptions`; update header comment.
129
+ - `src/types.ts` — barrel re-export `export { Agent } from "#src/lifecycle/agent";` → `export { Subagent } from "#src/lifecycle/subagent";`.
130
+ - All consumers of the renamed symbols across `src/` and `test/` (tools, UI, runtime, `index.ts`, session, observation, and their tests) — updated transitively by each language-service rename.
131
+ Out-of-scope `Agent*` symbols in these files are untouched.
132
+ - `test/helpers/make-subagent.ts`, `make-deps.ts`, `ui-stubs.ts`, and ~16 test importers — `createTestAgent` → `createTestSubagent` and updated import paths.
133
+ - `docs/architecture/architecture.md` — file-listing entries (`agent.ts`, `agent-manager.ts`), class/sequence Mermaid diagrams, the type-complexity table row (`AgentInit` → `SubagentInit`, module `agent` → `subagent`), and current-state prose naming the renamed cluster.
134
+ Out-of-scope `Agent*` names (`AgentTool`, `AgentSession`, `AgentTypeRegistry`, …) and historical phase narrative stay as written.
135
+
136
+ No exports are removed from the public surface; the barrel rename swaps one name for another with many live consumers.
137
+ Also swept for the `package-pi-subagents` SKILL.md, which documents internals (`AgentManager`, `Agent`, `make-agent`): update its dependency-flow sketch and module table to the new names.
138
+
139
+ ## Test Impact Analysis
140
+
141
+ This is a pure rename plus a no-op type consolidation, so the extraction-style test questions resolve simply:
142
+
143
+ 1. New tests enabled: none — no new seams or behavior are introduced.
144
+ 2. Tests made redundant: none — no test is duplicated or subsumed.
145
+ 3. Tests that must stay as-is (renamed/retargeted only): all of them.
146
+ `test/lifecycle/subagent.test.ts`, `subagent-manager.test.ts`, `record-observer.test.ts`, `service-adapter.test.ts`, and every `createTestSubagent` consumer continue to exercise the same behavior under the new names.
147
+ The status consolidation leaves `WorkspaceDisposeOutcome` behavior identical, so workspace/service tests are unchanged beyond the symbol name.
148
+
149
+ ## TDD Order
150
+
151
+ This is a refactor with no red phase; each step is a green checkpoint verified by `pnpm run check` && `pnpm -r run test` (and `verify:public-types` where the public surface is touched) before committing.
152
+ Steps are independent renames ordered smallest-blast-first where practical; any order keeps the tree green.
153
+
154
+ 1. Consolidate the status union.
155
+ In `agent.ts` rename `AgentStatus` → `SubagentStatus` and keep the definition there; delete the duplicate in `service.ts` and re-export from the lifecycle module; retype `workspace.ts`.
156
+ Run `pnpm run check`, tests, and `pnpm run verify:public-types` to confirm the bundle is unchanged.
157
+ Commit: `refactor: consolidate AgentStatus into public SubagentStatus (#280)`.
158
+ 2. Rename the `Agent` class cluster.
159
+ `Agent` → `Subagent`, `AgentInit` → `SubagentInit`, `AgentLifecycleObserver` → `SubagentLifecycleObserver`; git-move `agent.ts` → `subagent.ts` and `test/lifecycle/agent.test.ts` → `subagent.test.ts`; update the `types.ts` barrel re-export and the `workspace.ts` / `service.ts` import paths to `#src/lifecycle/subagent`; sweep residual bare-`Agent` JSDoc and the two error strings in `subagent.ts`.
160
+ Commit: `refactor: rename Agent class to Subagent (#280)`.
161
+ 3. Rename the manager cluster.
162
+ `AgentManager` → `SubagentManager`, `AgentManagerObserver` → `SubagentManagerObserver` (+ `onAgent*` methods → `onSubagent*`), `AgentManagerOptions` → `SubagentManagerOptions`; git-move `agent-manager.ts` → `subagent-manager.ts` and its test file; sweep residual bare-`AgentManager` comments.
163
+ `AgentSpawnConfig` left untouched.
164
+ Commit: `refactor: rename AgentManager cluster to SubagentManager (#280)`.
165
+ 4. Rename the observation seam.
166
+ `subscribeAgentObserver` → `subscribeSubagentObserver`, `AgentObserverOptions` → `SubagentObserverOptions` in `record-observer.ts`; update its test and header comment.
167
+ Commit: `refactor: rename subscribeAgentObserver to subscribeSubagentObserver (#280)`.
168
+ 5. Rename the adapter seam.
169
+ `AgentManagerLike` → `SubagentManagerLike` in `service-adapter.ts`; update its test and header comment.
170
+ Commit: `refactor: rename AgentManagerLike to SubagentManagerLike (#280)`.
171
+ 6. Rename the test helper.
172
+ `createTestAgent` → `createTestSubagent`; git-move `make-agent.ts` → `make-subagent.ts` and `make-agent.test.ts` → `make-subagent.test.ts`; update all importers and `#test/helpers/make-agent` paths.
173
+ Commit: `test: rename createTestAgent to createTestSubagent (#280)`.
174
+ 7. Update docs.
175
+ Architecture doc current-state references (file listing, Mermaid diagrams, complexity table, prose) and the `package-pi-subagents` SKILL.md internals; load the `mermaid` skill before editing diagrams.
176
+ Final verification: `pnpm run check`, `pnpm run lint`, `pnpm -r run test`, `pnpm fallow dead-code`, `pnpm run verify:public-types`, and `grep -rnE '\bAgent(Manager|Init)?\b' src/lifecycle/` returns no bare in-scope matches.
177
+ Commit: `docs: update architecture and skill docs for Subagent rename (#280)`.
178
+
179
+ ## Risks and Mitigations
180
+
181
+ - Risk: a symbol rename misses string literals or comments, leaving bare `Agent` that the acceptance grep flags.
182
+ Mitigation: each rename step explicitly sweeps comments/strings; the final grep gate in step 7 is the backstop.
183
+ - Risk: pointing `workspace.ts` at the public `SubagentStatus` introduces a `lifecycle → service` cycle.
184
+ Mitigation: keep the union's home in the lifecycle layer (`subagent.ts`) and re-export from `service.ts`, mirroring the existing `LifetimeUsage` / workspace re-export pattern — no new arrow.
185
+ - Risk: the public type bundle changes shape.
186
+ Mitigation: `verify:public-types` after step 1 and step 7; the union is identical, so the bundle differs only in provenance, not content.
187
+ - Risk: a file move accidentally rewrites `#src/` alias imports to relative paths.
188
+ Mitigation: use `git mv` and rely on the language service for import updates; eslint's no-relative-sibling rule catches regressions during `pnpm run lint`.
189
+ - Risk: over-reach into out-of-scope `Agent*` names.
190
+ Mitigation: the rename is symbol-scoped (not text find-replace); the Non-Goals list enumerates the protected names, and the acceptance grep targets only bare `Agent` / `AgentManager` / `AgentInit` / `Agent*Observer`.
191
+
192
+ ## Open Questions
193
+
194
+ - Whether to later lowercase incidental prose uses of "Agent" (meaning subagent) in the architecture doc's event tables and history sections — deferred; this plan updates symbol/file names and current-state references, leaving historical narrative as written.
195
+ - Whether `listAgents` / `getRecord` / the `agents` map deserve a follow-up naming pass — deferred; they are not bare-`Agent` symbols and fall outside the approved scope.
196
+
197
+ [#265]: https://github.com/gotgenes/pi-packages/issues/265
@@ -3,13 +3,13 @@ issue: 51
3
3
  issue_title: "docs: update ADR 0001 to reflect hard-fork decision"
4
4
  ---
5
5
 
6
- # Retro: #51 — docs: update ADR 0001 to reflect hard-fork decision
6
+ # Retro: #51 — docs: update ADR-0001 to reflect hard-fork decision
7
7
 
8
8
  ## Final Retrospective (2026-05-16)
9
9
 
10
10
  ### Session summary
11
11
 
12
- Updated ADR 0001 (`docs/decisions/0001-deferred-patches.md`) to reflect the hard-fork decision documented in `docs/architecture/architecture.md`.
12
+ Updated [ADR-0001] to reflect the hard-fork decision documented in `docs/architecture/architecture.md`.
13
13
  The change was planned, implemented, shipped, and released as `pi-subagents-v1.0.2` in a single clean pass with no rework.
14
14
 
15
15
  ### Observations
@@ -35,3 +35,5 @@ The change was planned, implemented, shipped, and released as `pi-subagents-v1.0
35
35
  - 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."
36
36
  This framing is now stale given the hard-fork commitment.
37
37
  A separate issue should update the skill to reflect the architecture document's posture.
38
+
39
+ [ADR-0001]: ../decisions/0001-deferred-patches.md
@@ -5,7 +5,7 @@ issue_title: "Extract ChildSessionFactory from runner"
5
5
 
6
6
  # Retro: #257 — Extract ChildSessionFactory from runner
7
7
 
8
- > Superseded — #257 closed `not_planned`; the work was reframed as Phase 16 "invert dependencies" (ADR 0002, issues #261–#265).
8
+ > Superseded — #257 closed `not_planned`; the work was reframed as Phase 16 "invert dependencies" ([ADR-0002], issues #261–#265).
9
9
 
10
10
  ## Stage: Planning (2026-05-29T00:32:12Z)
11
11
 
@@ -29,3 +29,5 @@ The plan is a lift-and-shift: `runAgent()` keeps its `(snapshot, type, prompt, o
29
29
  - `RunResult.sessionFile` shifts from a late `sessionManager.getSessionFile()` to the factory's `outputFile` — same value (stable after `newSession()`); the existing `/sessions/child.jsonl` assertion is the guard.
30
30
  - Did not invoke `ask_user`: the issue's "Proposed change" is prescriptive, and the two deviations are forced/justified rather than open-ended.
31
31
  - IO interfaces (`RunnerIO`, `RunnerDeps`, etc.) intentionally stay in `agent-runner.ts` for this step to minimize churn; their relocation to the factory module is flagged as an Open Question for Step 4 when the runner dissolves.
32
+
33
+ [ADR-0002]: ../decisions/0002-extensions-on-a-minimal-core.md
@@ -9,7 +9,7 @@ issue_title: "Add WorkspaceProvider extension seam"
9
9
 
10
10
  ### Session summary
11
11
 
12
- Produced a numbered implementation plan for the Phase 16, Step 2 `WorkspaceProvider` seam (ADR 0002).
12
+ Produced a numbered implementation plan for the Phase 16, Step 2 `WorkspaceProvider` seam ([ADR-0002]).
13
13
  The plan adds the seam additively — `WorkspaceProvider` / `Workspace` interfaces, `SubagentsService.registerWorkspaceProvider`, run-start consultation, and `dispose` with a verbatim `resultAddendum` — while leaving the existing `isolation: "worktree"` path untouched for #263 to evict.
14
14
  Three TDD steps (two `feat`, one `docs`).
15
15
 
@@ -85,3 +85,5 @@ Across all stages the plan's risk predictions held and TDD verification was incr
85
85
 
86
86
  1. `AGENTS.md` (Pre-completion reviewer subsection) — added a one-line guardrail: agent `model:` frontmatter must use the `provider/id` alias form the Pi CLI/UI accepts, because an ID absent from the model registry silently falls back to the parent session model.
87
87
  2. `packages/pi-subagents/docs/retro/0262-add-workspace-provider-seam.md` — this Final Retrospective stage entry.
88
+
89
+ [ADR-0002]: ../decisions/0002-extensions-on-a-minimal-core.md
@@ -9,7 +9,7 @@ issue_title: "Remove isolated / extensions:false / noSkills from core"
9
9
 
10
10
  ### Session summary
11
11
 
12
- Planned Phase 16, Step 4: removing the extension-lifecycle-control axis (`isolated`, `extensions: false`, `noSkills`) from the pi-subagents core per ADR 0002.
12
+ Planned Phase 16, Step 4: removing the extension-lifecycle-control axis (`isolated`, `extensions: false`, `noSkills`) from the pi-subagents core per [ADR-0002].
13
13
  Confirmed all three prerequisite Phase 16 steps (#261, #262, #263) are closed, so the explicit "deny-at-use" dependency is satisfied.
14
14
  Produced a four-cycle TDD plan (`isolated` → `extensions` → `skills`/`noSkills`/preload → docs) and committed it.
15
15
 
@@ -87,3 +87,5 @@ The run had zero rework and a PASS pre-completion review; test count moved 1016
87
87
  1. Appended this Final Retrospective stage entry to `packages/pi-subagents/docs/retro/0264-remove-extension-lifecycle-control.md`.
88
88
  2. Considered but **declined** (user: "too narrow") a removal-coupling detection rule for `.pi/prompts/plan-issue.md` — the heuristic that a field named for removal may be the mechanism behind a separate surviving feature.
89
89
  No prompt or `AGENTS.md` changes were made this retro.
90
+
91
+ [ADR-0002]: ../decisions/0002-extensions-on-a-minimal-core.md
@@ -34,7 +34,7 @@ The plan adds a `rollup-plugin-dts` build that bundles `src/service/service.ts`
34
34
 
35
35
  ### Session summary
36
36
 
37
- Executed all four build-order steps: added `rollup` + `rollup-plugin-dts` and a `build:types` script that bundles `src/service/service.ts` into a self-contained `dist/public.d.ts`; wired conditional `exports` (`types` + `default`, fixing the stale path) with a `prepack` hook and a `files` allowlist; added a `pnpm pack` → throwaway-consumer → `tsc` verification harness (`scripts/verify-public-types.sh`) plus a CI step; and recorded ADR 0003.
37
+ Executed all four build-order steps: added `rollup` + `rollup-plugin-dts` and a `build:types` script that bundles `src/service/service.ts` into a self-contained `dist/public.d.ts`; wired conditional `exports` (`types` + `default`, fixing the stale path) with a `prepack` hook and a `files` allowlist; added a `pnpm pack` → throwaway-consumer → `tsc` verification harness (`scripts/verify-public-types.sh`) plus a CI step; and recorded [ADR-0003].
38
38
  A fifth commit documented the new build step in the `package-pi-subagents` skill (reviewer WARN).
39
39
  Root `pnpm run check`, root `pnpm run lint`, and `verify:public-types` all pass.
40
40
 
@@ -91,7 +91,7 @@ Two CI failures during the ship stage — a pre-existing `pnpm fallow dead-code`
91
91
  - The "pi-subagents-* extensions should use the released, npm-installed version, no workspace trickery" directive arrived mid-planning, after initial exploration.
92
92
  Surfacing the consumption-model constraint at kickoff would have framed the scope question earlier.
93
93
  Opportunity, not criticism — the same exchange produced the high-value chicken-and-egg catch (the registry version with the fix cannot exist until #270 publishes) that correctly deferred the worktrees flip to #263.
94
- - A brief "there is no ADR 0003" → "My mistake" exchange; no rework.
94
+ - A brief "there is no [ADR-0003]" → "My mistake" exchange; no rework.
95
95
 
96
96
  ### Diagnostic details
97
97
 
@@ -104,3 +104,5 @@ Two CI failures during the ship stage — a pre-existing `pnpm fallow dead-code`
104
104
 
105
105
  1. `.pi/prompts/ship-issue.md` — renamed Step 2 to "Pre-push checks" and added `pnpm fallow dead-code` alongside `pnpm run lint`, with a one-line note that the gate is `main`-only and blocks pushes regardless of who introduced the failure.
106
106
  2. `AGENTS.md` (§ Code Style pnpm rules) — added a rule to run `pnpm install` and commit the updated `pnpm-lock.yaml` in the same commit when a `package.json` dependency changes, since CI installs with `--frozen-lockfile`.
107
+
108
+ [ADR-0003]: ../decisions/0003-publish-bundled-type-declarations.md
@@ -0,0 +1,96 @@
1
+ ---
2
+ issue: 280
3
+ issue_title: "Rename the internal Agent class to Subagent"
4
+ ---
5
+
6
+ # Retro: #280 — Rename the internal `Agent` class to `Subagent`
7
+
8
+ ## Stage: Planning (2026-05-31T00:09:51Z)
9
+
10
+ ### Session summary
11
+
12
+ Produced a numbered implementation plan to rename the subagent-instance cluster in `src/lifecycle/` from the bare `Agent*` family to `Subagent*`, consolidate the duplicate `AgentStatus` union into the public `SubagentStatus`, and update the architecture doc.
13
+ The plan is a 7-step refactor (no behavior change), each step an atomic language-service rename that leaves the tree green.
14
+
15
+ ### Observations
16
+
17
+ - Scope decisions confirmed with the user via `ask_user`: (1) rename the module files too (`agent.ts` → `subagent.ts`, `agent-manager.ts` → `subagent-manager.ts`, plus test/helper files), and (2) full-consistency rename of adjacent identifiers — `subscribeAgentObserver`, the `SubagentManagerObserver` `onAgent*` methods, and the `createTestAgent` helper.
18
+ - Layering catch: pointing `WorkspaceDisposeOutcome.status` directly at `service.ts`'s `SubagentStatus` would create a `lifecycle → service` cycle (`service.ts` already imports the workspace collaborator types).
19
+ Resolution: keep the union's single home in the lifecycle layer (`subagent.ts`) and have `service.ts` re-export it, mirroring the existing `LifetimeUsage` / workspace re-export pattern.
20
+ - Acceptance-grep catch: the issue's `grep src/lifecycle/` for bare `Agent` matches comments and string literals (e.g. the two `"Agent not configured …"` error messages), not just symbols.
21
+ The language-service rename does not touch those, so each step must sweep residual comment/string occurrences; step 7 has a final grep gate.
22
+ - Compound names (`AgentSession`, `AgentInvocation`, `AgentTypeRegistry`, `AgentTool`, `AgentSpawnConfig`) are not bare-word matches and are explicitly out of scope.
23
+ - Non-breaking — `refactor:` commits throughout; `verify:public-types` runs after the status consolidation and the final step since the public bundle (`dist/public.d.ts`) is rolled from `src/service/service.ts`.
24
+ - Also flagged the `package-pi-subagents` SKILL.md for an internals-naming update (it references `AgentManager`, `Agent`, `make-agent`).
25
+
26
+ ## Stage: Implementation — TDD (2026-05-31T00:38:55Z)
27
+
28
+ ### Session summary
29
+
30
+ Completed 6 refactor commits (steps 1–6 from the plan, with step 5 folded into step 3) plus a `test:` commit for the helper rename and a `docs:` commit for the architecture doc update.
31
+ All 973 tests pass across 59 test files with no test count delta.
32
+ Pre-completion reviewer returned PASS with all 5 acceptance criteria verified.
33
+
34
+ ### Observations
35
+
36
+ - Step 5 (`AgentManagerLike` → `SubagentManagerLike`) was automatically folded into step 3 because the bulk-rename Python script replaced all `AgentManager*` compounds at once — no separate commit was needed or appropriate.
37
+ - The acceptance grep (`grep -rnE '\bAgent(Manager|Init)?\b' src/lifecycle/`) also flags bare `Agent` in comments and error strings; each rename step swept those manually since the language-service rename does not touch non-symbol text.
38
+ - `sed` with negative lookaheads failed on macOS for the `notification.ts` file; fell back to a two-pass approach (sed for the import, then `perl -i -0pe` with negative lookahead for the body).
39
+ - `describe("Agent — ...)` test block names used em-dashes (Unicode U+2014); `sed` with `\u2014` escape did not match on macOS — required Python `re.sub` with the literal character.
40
+ - The `SubagentStatus` type definition was kept in `src/lifecycle/subagent.ts` (single home) and re-exported from `src/service/service.ts`, matching the existing `LifetimeUsage` / workspace re-export pattern and avoiding a `lifecycle → service` cycle.
41
+ - Docs: the architecture doc's session-encapsulation table had misaligned Markdown table columns after the rename (cell widths changed); `rumdl fmt` auto-fixed them.
42
+ - Pre-completion reviewer: PASS — all deterministic checks, all 5 acceptance criteria, conventional commits, docs, Mermaid diagrams, and dead-code gate confirmed clean.
43
+
44
+ ## Stage: Final Retrospective (2026-05-31T01:05:57Z)
45
+
46
+ ### Session summary
47
+
48
+ Shipped the full Planning → TDD → Ship lifecycle for the internal `Agent` → `Subagent` rename across `@gotgenes/pi-subagents`: 7 implementation commits (6 `refactor:`/`test:` + 1 `docs:`), 973 tests green throughout, CI passed on `27abb5aa`, and issue #280 closed.
49
+ No release was triggered (all `refactor:`/`test:`/`docs:` commits), so no release-please PR appeared — expected.
50
+
51
+ ### Observations
52
+
53
+ #### What went well
54
+
55
+ - Two planning-stage catches prevented downstream rework: the `lifecycle → service` import cycle (resolved by keeping `SubagentStatus`'s single home in `subagent.ts` and re-exporting from `service.ts`) and the acceptance grep matching bare `Agent` in comments/strings (so each step swept non-symbol text).
56
+ Both were anticipated in the plan and held during execution.
57
+ - Incremental verification carried the rename safely: `pnpm run check` plus the affected test files ran after every step, so the text-based substitution mistakes were caught instantly and never reached a commit.
58
+ The pre-completion reviewer then returned a clean PASS with nothing to fix.
59
+ - The status re-export needed a follow-up `import type { SubagentStatus }` because `export type { … } from` does not create a local binding for `SubagentRecord` to reference — `pnpm run check` flagged it immediately, a one-edit fix.
60
+
61
+ #### What caused friction (agent side)
62
+
63
+ - `wrong-abstraction` — The plan specified each rename as a "scope-aware language-service pass" (`findRenameLocations`), but the execution toolkit has no LSP-rename tool — only `Edit`, `Bash` (`sed`/`perl`/`python`), and `grep`.
64
+ Execution fell back to text substitution, which is exactly why the comment/string sweep was needed and why the regex gymnastics below happened.
65
+ Impact: added friction but no rework — `tsc` + tests caught every gap; no incorrect commit landed.
66
+ - `other` (cross-platform tooling) — Repeated silent failures from BSD `sed` / `perl` one-liners: BSD `sed` lacks `\b` and lookahead; `perl -i ''` is malformed (the `-i ''` form is a `sed`-ism); neither interprets `\uXXXX` escapes, so em-dash `describe("Agent — …")` blocks and `notification.ts` body renames did not match.
67
+ Each failure forced a grep-verify-redo loop, ultimately resolved by switching to Python `re.sub`.
68
+ Impact: roughly 5–8 extra tool calls across the TDD stage; no rework beyond the redo cycles.
69
+
70
+ #### What caused friction (user side)
71
+
72
+ - None.
73
+ The user's two `ask_user` answers at planning time (file renames + full-consistency adjacent identifiers) front-loaded every scope decision, so the TDD and Ship stages ran without a single mid-course correction.
74
+
75
+ ### Diagnostic details
76
+
77
+ - **Model-performance correlation** — One subagent dispatched (`pre-completion-reviewer`) on judgment-heavy review work (acceptance verification, Mermaid validation via `mmdc`, dead-code gate); appropriate match, no mismatch.
78
+ - **Escalation-delay tracking** — The `notification.ts` body rename cycled ~4–5 consecutive `sed`/`perl`/`grep` calls on the same substitution before switching to `perl -i -0pe`; under the 5-call threshold but the closest the session came.
79
+ The general lesson (prefer Python `re.sub`) generalizes the fix.
80
+ - **Unused-tool detection** — No Explore/`colgrep` gap: the codebase was already understood from planning, and an exact symbol rename is not a semantic-search task.
81
+ The only "missing capability" is a language-service rename tool, which is not in the toolkit — a genuine gap, not an unused option.
82
+ - **Feedback-loop gap analysis** — No gap: `pnpm run check` and affected tests ran after each step (incremental); `pnpm run lint`, `pnpm fallow dead-code`, and `verify:public-types` ran as the final batch.
83
+ Verification cadence was correct.
84
+
85
+ ### Changes made
86
+
87
+ 1. Appended this Final Retrospective stage entry to `packages/pi-subagents/docs/retro/0280-rename-agent-to-subagent.md`.
88
+ 2. Strengthened the global `APPEND_SYSTEM.md` "Shell Commands" rule to name the literal absolute-path `cd` form (e.g. `cd /Users/you/project &&`), not just `cd $CWD &&` — the existing rule failed to catch the literal-path form that agents actually emit.
89
+ This file is global (`~/.pi/agent/APPEND_SYSTEM.md`), outside the repo, so it is not committed here.
90
+ 3. Added a monorepo-specific line to `AGENTS.md` § Monorepo Structure: prefer `pnpm --filter @gotgenes/<pkg> run <script>` (or `pnpm -C packages/<pkg> run <script>`) from the root over `cd packages/<pkg> && pnpm run <script>`.
91
+ Prompted by excessive `cd` chaining observed across this session's Ship and Retro stages.
92
+
93
+ ### Follow-ups considered (not applied)
94
+
95
+ 1. Proposed adding a bulk-substitution tooling rule (prefer Python `re.sub` over `sed`/`perl` one-liners, since BSD `sed` lacks `\b`/lookahead and `\uXXXX` is uninterpreted) to the `code-design` skill's Tooling section.
96
+ The user opted to record the observation here only and skip the skill change.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gotgenes/pi-subagents",
3
- "version": "13.2.1",
3
+ "version": "13.2.2",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
package/src/index.ts CHANGED
@@ -23,11 +23,11 @@ import {
23
23
  import { AgentTypeRegistry } from "#src/config/agent-types";
24
24
  import { loadCustomAgents } from "#src/config/custom-agents";
25
25
  import { SessionLifecycleHandler, ToolStartHandler } from "#src/handlers/index";
26
- import { AgentManager, type AgentManagerObserver } from "#src/lifecycle/agent-manager";
27
26
  import { createChildLifecyclePublisher } from "#src/lifecycle/child-lifecycle";
28
27
  import { ConcurrencyQueue } from "#src/lifecycle/concurrency-queue";
29
28
  import { createSubagentSession, type SubagentSessionDeps } from "#src/lifecycle/create-subagent-session";
30
29
  import { buildParentSnapshot } from "#src/lifecycle/parent-snapshot";
30
+ import { SubagentManager, type SubagentManagerObserver } from "#src/lifecycle/subagent-manager";
31
31
  import { buildEventData, type NotificationDetails, NotificationManager } from "#src/observation/notification";
32
32
  import { createNotificationRenderer } from "#src/observation/renderer";
33
33
  import { createSubagentRuntime } from "#src/runtime";
@@ -56,7 +56,7 @@ export default function (pi: ExtensionAPI) {
56
56
  const runtime = createSubagentRuntime();
57
57
 
58
58
  // ---- Notification system ----
59
- // runtime.widget is assigned after AgentManager construction; arrow closures
59
+ // runtime.widget is assigned after SubagentManager construction; arrow closures
60
60
  // capture `runtime` by reference so they always read the current value.
61
61
  const notifications = new NotificationManager(
62
62
  (msg, opts) => pi.sendMessage(msg, opts),
@@ -76,8 +76,8 @@ export default function (pi: ExtensionAPI) {
76
76
  settings.load();
77
77
 
78
78
  // Observer: receives agent lifecycle notifications and dispatches events/notifications.
79
- const observer: AgentManagerObserver = {
80
- onAgentStarted(record) {
79
+ const observer: SubagentManagerObserver = {
80
+ onSubagentStarted(record) {
81
81
  // Emit started event when agent transitions to running (including from queue).
82
82
  pi.events.emit("subagents:started", {
83
83
  id: record.id,
@@ -85,7 +85,7 @@ export default function (pi: ExtensionAPI) {
85
85
  description: record.description,
86
86
  });
87
87
  },
88
- onAgentCompleted(record) {
88
+ onSubagentCompleted(record) {
89
89
  // Emit lifecycle event based on terminal status.
90
90
  const isError = record.status === "error" || record.status === "stopped" || record.status === "aborted";
91
91
  const eventData = buildEventData(record);
@@ -110,7 +110,7 @@ export default function (pi: ExtensionAPI) {
110
110
 
111
111
  notifications.sendCompletion(record);
112
112
  },
113
- onAgentCompacted(record, info) {
113
+ onSubagentCompacted(record, info) {
114
114
  // Emit compacted event when agent's session compacts (preserves count on record).
115
115
  pi.events.emit("subagents:compacted", {
116
116
  id: record.id,
@@ -121,7 +121,7 @@ export default function (pi: ExtensionAPI) {
121
121
  compactionCount: record.compactionCount,
122
122
  });
123
123
  },
124
- onAgentCreated(record) {
124
+ onSubagentCreated(record) {
125
125
  // Emit created event for background agents (before startAgent / queue drain).
126
126
  pi.events.emit("subagents:created", {
127
127
  id: record.id,
@@ -150,7 +150,7 @@ export default function (pi: ExtensionAPI) {
150
150
  lifecycle: createChildLifecyclePublisher((channel, data) => pi.events.emit(channel, data)),
151
151
  };
152
152
 
153
- // ConcurrencyQueue: scheduling extracted from AgentManager.
153
+ // ConcurrencyQueue: scheduling extracted from SubagentManager.
154
154
  // startAgent callback forward-references manager via closure (safe — drain is never called during construction).
155
155
  const queue = new ConcurrencyQueue(
156
156
  () => settings.maxConcurrent,
@@ -161,7 +161,7 @@ export default function (pi: ExtensionAPI) {
161
161
  },
162
162
  );
163
163
 
164
- const manager = new AgentManager({
164
+ const manager = new SubagentManager({
165
165
  createSubagentSession: (params) => createSubagentSession(params, subagentSessionDeps),
166
166
  baseCwd: process.cwd(),
167
167
  observer,
@@ -5,7 +5,7 @@
5
5
  * `runAgent()` did up front: detect the environment, assemble the session config,
6
6
  * create the SDK session, publish `spawning`/`session-created`, bind extensions,
7
7
  * and apply the recursion guard. It returns a fully usable `SubagentSession` —
8
- * `Agent` then only coordinates (turn loop, steer, dispose).
8
+ * `Subagent` then only coordinates (turn loop, steer, dispose).
9
9
  *
10
10
  * The factory takes a resolved `cwd` value, never the WorkspaceProvider: `cwd`
11
11
  * is a value the factory consumes directly (detectEnv, assembleSessionConfig,