@gotgenes/pi-subagents 18.0.1 → 18.0.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 (260) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/docs/architecture/architecture.md +157 -204
  3. package/docs/architecture/history/phase-19-implement-ui-decisions.md +282 -0
  4. package/package.json +5 -6
  5. package/src/lifecycle/subagent.ts +5 -9
  6. package/src/observation/notification.ts +23 -10
  7. package/src/observation/subagent-events-observer.ts +1 -3
  8. package/src/tools/get-result-report.ts +60 -0
  9. package/src/tools/get-result-tool.ts +25 -40
  10. package/src/types.ts +1 -1
  11. package/src/ui/session-navigator.ts +0 -2
  12. package/.prettierignore +0 -5
  13. package/AGENTS.md +0 -7
  14. package/docs/plans/0048-implement-subagents-api.md +0 -304
  15. package/docs/plans/0049-remove-group-join-output-file-rpc.md +0 -180
  16. package/docs/plans/0051-update-adr-0001-hard-fork.md +0 -77
  17. package/docs/plans/0052-remove-scheduled-subagents.md +0 -133
  18. package/docs/plans/0053-extract-model-resolution-from-execute.md +0 -181
  19. package/docs/plans/0054-decompose-index-into-modules.md +0 -302
  20. package/docs/plans/0057-structured-debug-logging.md +0 -154
  21. package/docs/plans/0061-session-format-transcript.md +0 -284
  22. package/docs/plans/0066-replace-as-any-with-sdk-types.md +0 -215
  23. package/docs/plans/0069-create-subagent-runtime.md +0 -345
  24. package/docs/plans/0070-extract-event-handlers.md +0 -306
  25. package/docs/plans/0071-extract-session-config-assembler.md +0 -362
  26. package/docs/plans/0072-inject-agent-manager-collaborators.md +0 -329
  27. package/docs/plans/0076-inject-cwd-into-agent-manager.md +0 -102
  28. package/docs/plans/0077-inject-project-agents-dir.md +0 -115
  29. package/docs/plans/0080-consolidate-agent-config-lookup.md +0 -247
  30. package/docs/plans/0084-extract-git-worktree-manager.md +0 -142
  31. package/docs/plans/0087-evolve-subagent-runtime-methods.md +0 -240
  32. package/docs/plans/0098-extract-agent-record-state-machine.md +0 -435
  33. package/docs/plans/0099-replace-ctx-with-parent-snapshot.md +0 -488
  34. package/docs/plans/0100-replace-callback-threading-with-session-subscription.md +0 -454
  35. package/docs/plans/0102-consolidate-test-record-factory.md +0 -176
  36. package/docs/plans/0108-extract-agent-type-registry.md +0 -322
  37. package/docs/plans/0109-extract-settings-manager.md +0 -276
  38. package/docs/plans/0110-agent-activity-tracker.md +0 -297
  39. package/docs/plans/0111-split-agent-record-lifecycle.md +0 -582
  40. package/docs/plans/0112-replace-agent-manager-callbacks.md +0 -241
  41. package/docs/plans/0113-disambiguate-spawn-options.md +0 -155
  42. package/docs/plans/0114-narrow-agent-tool-menu-deps.md +0 -279
  43. package/docs/plans/0115-decompose-agent-tool.md +0 -337
  44. package/docs/plans/0116-type-housekeeping.md +0 -351
  45. package/docs/plans/0118-settings-manager-apply-methods.md +0 -271
  46. package/docs/plans/0123-remove-vi-fn-cast-smell.md +0 -179
  47. package/docs/plans/0131-consolidate-shared-test-fixtures.md +0 -207
  48. package/docs/plans/0132-inject-io-into-session-config.md +0 -219
  49. package/docs/plans/0133-inject-sdk-boundary-into-agent-runner.md +0 -373
  50. package/docs/plans/0134-reduce-as-any-casts.md +0 -366
  51. package/docs/plans/0135-extract-display-helpers.md +0 -182
  52. package/docs/plans/0136-decompose-agent-menu.md +0 -300
  53. package/docs/plans/0144-consolidate-observation-model.md +0 -263
  54. package/docs/plans/0145-decompose-execute-push-ctx-to-boundary.md +0 -290
  55. package/docs/plans/0146-narrow-ui-context.md +0 -319
  56. package/docs/plans/0147-inject-wrap-text-into-conversation-viewer.md +0 -166
  57. package/docs/plans/0148-split-agent-widget-rendering.md +0 -255
  58. package/docs/plans/0152-add-prompt-snippet.md +0 -91
  59. package/docs/plans/0164-reorganize-into-domain-directories.md +0 -409
  60. package/docs/plans/0165-decompose-resolved-spawn-config.md +0 -157
  61. package/docs/plans/0166-extract-parent-session-info.md +0 -231
  62. package/docs/plans/0167-narrow-runner-io.md +0 -150
  63. package/docs/plans/0168-extract-tool-filter-config.md +0 -173
  64. package/docs/plans/0169-extract-run-context-from-run-options.md +0 -194
  65. package/docs/plans/0170-reduce-build-content-lines-complexity.md +0 -225
  66. package/docs/plans/0171-reduce-render-result-complexity.md +0 -200
  67. package/docs/plans/0172-extract-turn-formatting.md +0 -206
  68. package/docs/plans/0180-reorder-append-prompt-for-kv-cache.md +0 -100
  69. package/docs/plans/0185-remove-persistent-agent-memory.md +0 -161
  70. package/docs/plans/0188-replace-any-casts-with-sdk-types.md +0 -162
  71. package/docs/plans/0192-define-session-context-interface.md +0 -107
  72. package/docs/plans/0193-runtime-owns-context-queries.md +0 -245
  73. package/docs/plans/0194-align-tool-interfaces-for-structural-typing.md +0 -139
  74. package/docs/plans/0195-convert-tool-factories-to-classes.md +0 -264
  75. package/docs/plans/0196-convert-runner-menu-to-classes.md +0 -268
  76. package/docs/plans/0205-decompose-render-widget-lines.md +0 -140
  77. package/docs/plans/0206-decompose-show-agent-detail.md +0 -211
  78. package/docs/plans/0207-decompose-agent-widget-update.md +0 -242
  79. package/docs/plans/0208-extract-shared-test-fixtures.md +0 -298
  80. package/docs/plans/0214-convert-remaining-closure-factories-to-classes.md +0 -261
  81. package/docs/plans/0215-decompose-build-parent-context.md +0 -166
  82. package/docs/plans/0216-decompose-start-agent.md +0 -255
  83. package/docs/plans/0217-extract-overwrite-guard.md +0 -176
  84. package/docs/plans/0218-push-sdk-boundary-in-settings.md +0 -172
  85. package/docs/plans/0219-reduce-test-duplication-top-3-clone-families.md +0 -162
  86. package/docs/plans/0227-evolve-agent-record-into-agent.md +0 -322
  87. package/docs/plans/0228-async-start-agent-dissolve-run-handle.md +0 -288
  88. package/docs/plans/0229-agent-born-complete.md +0 -564
  89. package/docs/plans/0230-extract-concurrency-queue.md +0 -265
  90. package/docs/plans/0231-push-exec-registry-to-runner.md +0 -245
  91. package/docs/plans/0232-agent-resume-internal-observer-lifecycle.md +0 -180
  92. package/docs/plans/0237-remove-disallowed-tools.md +0 -180
  93. package/docs/plans/0238-remove-extensions-filtering.md +0 -191
  94. package/docs/plans/0239-collapse-filter-active-tools.md +0 -217
  95. package/docs/plans/0242-rename-agent-tool-to-subagent.md +0 -165
  96. package/docs/plans/0256-extract-worktree-isolation.md +0 -256
  97. package/docs/plans/0257-extract-child-session-factory.md +0 -285
  98. package/docs/plans/0262-add-workspace-provider-seam.md +0 -264
  99. package/docs/plans/0264-remove-extension-lifecycle-control.md +0 -277
  100. package/docs/plans/0265-born-complete-subagent-session.md +0 -333
  101. package/docs/plans/0270-type-consumable-public-surface.md +0 -204
  102. package/docs/plans/0272-export-workspace-collaborator-types.md +0 -147
  103. package/docs/plans/0277-encapsulate-agent-session.md +0 -304
  104. package/docs/plans/0280-rename-agent-to-subagent.md +0 -197
  105. package/docs/plans/0360-custom-agents-default-append.md +0 -132
  106. package/docs/plans/0373-extract-subagent-state.md +0 -250
  107. package/docs/plans/0374-encapsulate-subagent-start-notification.md +0 -268
  108. package/docs/plans/0375-extract-run-listener-workspace-bracket.md +0 -300
  109. package/docs/plans/0376-extract-manager-observer.md +0 -232
  110. package/docs/plans/0377-split-widget-delegation-from-runtime.md +0 -254
  111. package/docs/plans/0378-consolidate-lifecycle-test-fixtures.md +0 -243
  112. package/docs/plans/0379-consolidate-ui-tools-test-fixtures.md +0 -335
  113. package/docs/plans/0380-extract-layered-settings-loader.md +0 -223
  114. package/docs/plans/0381-replace-concurrency-queue-with-limiter.md +0 -267
  115. package/docs/plans/0400-include-parent-prompt-in-replace-mode.md +0 -199
  116. package/docs/plans/0403-abort-subagents-on-interrupt.md +0 -180
  117. package/docs/plans/0412-unify-session-mock-builders.md +0 -146
  118. package/docs/plans/0420-fold-run-metrics-live-activity-onto-record.md +0 -228
  119. package/docs/plans/0421-migrate-activity-readers-to-record-getters.md +0 -309
  120. package/docs/plans/0422-delete-activity-tracker-ui-observer.md +0 -204
  121. package/docs/plans/0423-widget-self-drive-from-lifecycle.md +0 -264
  122. package/docs/plans/0424-drop-widget-dep-from-subagent-tool.md +0 -166
  123. package/docs/plans/0425-reconcile-subagent-events-contract.md +0 -144
  124. package/docs/plans/0426-consolidate-residual-test-clone-families.md +0 -235
  125. package/docs/plans/0427-reconsider-ui-direction.md +0 -212
  126. package/docs/plans/0441-remove-agent-definition-management-subtree.md +0 -180
  127. package/docs/plans/0442-dissolve-agents-conversation-viewer.md +0 -195
  128. package/docs/plans/0443-consolidate-remaining-test-clone-families.md +0 -268
  129. package/docs/plans/0444-shrink-widget-to-background-agents.md +0 -156
  130. package/docs/plans/0445-native-session-navigation.md +0 -365
  131. package/docs/plans/0446-spike-session-navigation-entry-criteria.md +0 -171
  132. package/docs/plans/0447-extract-subagents-settings-command.md +0 -220
  133. package/docs/plans/0448-block-disabled-agent-spawn.md +0 -207
  134. package/docs/plans/0462-navigation-renderer-tui-components.md +0 -338
  135. package/docs/plans/0463-file-snapshot-source-evicted-agents.md +0 -306
  136. package/docs/plans/0470-refresh-readme-command-surface.md +0 -159
  137. package/docs/retro/0048-implement-subagents-api.md +0 -44
  138. package/docs/retro/0049-remove-group-join-output-file-rpc.md +0 -49
  139. package/docs/retro/0051-update-adr-0001-hard-fork.md +0 -39
  140. package/docs/retro/0053-extract-model-resolution-from-execute.md +0 -40
  141. package/docs/retro/0054-decompose-index-into-modules.md +0 -53
  142. package/docs/retro/0057-structured-debug-logging.md +0 -77
  143. package/docs/retro/0061-session-format-transcript.md +0 -41
  144. package/docs/retro/0066-replace-as-any-with-sdk-types.md +0 -44
  145. package/docs/retro/0069-create-subagent-runtime.md +0 -43
  146. package/docs/retro/0070-extract-event-handlers.md +0 -49
  147. package/docs/retro/0071-extract-session-config-assembler.md +0 -60
  148. package/docs/retro/0072-inject-agent-manager-collaborators.md +0 -46
  149. package/docs/retro/0076-inject-cwd-into-agent-manager.md +0 -35
  150. package/docs/retro/0077-inject-project-agents-dir.md +0 -33
  151. package/docs/retro/0080-consolidate-agent-config-lookup.md +0 -35
  152. package/docs/retro/0084-extract-git-worktree-manager.md +0 -37
  153. package/docs/retro/0087-evolve-subagent-runtime-methods.md +0 -42
  154. package/docs/retro/0098-extract-agent-record-state-machine.md +0 -46
  155. package/docs/retro/0099-replace-ctx-with-parent-snapshot.md +0 -37
  156. package/docs/retro/0100-replace-callback-threading-with-session-subscription.md +0 -36
  157. package/docs/retro/0102-consolidate-test-record-factory.md +0 -30
  158. package/docs/retro/0108-extract-agent-type-registry.md +0 -41
  159. package/docs/retro/0109-extract-settings-manager.md +0 -55
  160. package/docs/retro/0110-agent-activity-tracker.md +0 -44
  161. package/docs/retro/0111-split-agent-record-lifecycle.md +0 -61
  162. package/docs/retro/0112-replace-agent-manager-callbacks.md +0 -35
  163. package/docs/retro/0113-disambiguate-spawn-options.md +0 -29
  164. package/docs/retro/0114-narrow-agent-tool-menu-deps.md +0 -38
  165. package/docs/retro/0115-decompose-agent-tool.md +0 -51
  166. package/docs/retro/0116-type-housekeeping.md +0 -42
  167. package/docs/retro/0118-settings-manager-apply-methods.md +0 -40
  168. package/docs/retro/0123-remove-vi-fn-cast-smell.md +0 -49
  169. package/docs/retro/0131-consolidate-shared-test-fixtures.md +0 -46
  170. package/docs/retro/0132-inject-io-into-session-config.md +0 -33
  171. package/docs/retro/0133-inject-sdk-boundary-into-agent-runner.md +0 -45
  172. package/docs/retro/0134-reduce-as-any-casts.md +0 -56
  173. package/docs/retro/0135-extract-display-helpers.md +0 -38
  174. package/docs/retro/0136-decompose-agent-menu.md +0 -43
  175. package/docs/retro/0144-consolidate-observation-model.md +0 -39
  176. package/docs/retro/0145-decompose-execute-push-ctx-to-boundary.md +0 -56
  177. package/docs/retro/0146-narrow-ui-context.md +0 -70
  178. package/docs/retro/0147-inject-wrap-text-into-conversation-viewer.md +0 -90
  179. package/docs/retro/0148-split-agent-widget-rendering.md +0 -39
  180. package/docs/retro/0152-add-prompt-snippet.md +0 -34
  181. package/docs/retro/0164-reorganize-into-domain-directories.md +0 -82
  182. package/docs/retro/0165-decompose-resolved-spawn-config.md +0 -78
  183. package/docs/retro/0166-extract-parent-session-info.md +0 -66
  184. package/docs/retro/0167-narrow-runner-io.md +0 -63
  185. package/docs/retro/0168-extract-tool-filter-config.md +0 -76
  186. package/docs/retro/0169-extract-run-context-from-run-options.md +0 -68
  187. package/docs/retro/0170-reduce-build-content-lines-complexity.md +0 -72
  188. package/docs/retro/0171-reduce-render-result-complexity.md +0 -77
  189. package/docs/retro/0172-extract-turn-formatting.md +0 -80
  190. package/docs/retro/0180-reorder-append-prompt-for-kv-cache.md +0 -62
  191. package/docs/retro/0185-remove-persistent-agent-memory.md +0 -73
  192. package/docs/retro/0188-replace-any-casts-with-sdk-types.md +0 -69
  193. package/docs/retro/0192-define-session-context-interface.md +0 -59
  194. package/docs/retro/0193-runtime-owns-context-queries.md +0 -75
  195. package/docs/retro/0194-align-tool-interfaces-for-structural-typing.md +0 -62
  196. package/docs/retro/0195-convert-tool-factories-to-classes.md +0 -84
  197. package/docs/retro/0196-convert-runner-menu-to-classes.md +0 -73
  198. package/docs/retro/0205-decompose-render-widget-lines.md +0 -64
  199. package/docs/retro/0206-decompose-show-agent-detail.md +0 -67
  200. package/docs/retro/0207-decompose-agent-widget-update.md +0 -92
  201. package/docs/retro/0208-extract-shared-test-fixtures.md +0 -102
  202. package/docs/retro/0214-convert-remaining-closure-factories-to-classes.md +0 -66
  203. package/docs/retro/0215-decompose-build-parent-context.md +0 -61
  204. package/docs/retro/0216-decompose-start-agent.md +0 -80
  205. package/docs/retro/0217-extract-overwrite-guard.md +0 -63
  206. package/docs/retro/0218-push-sdk-boundary-in-settings.md +0 -72
  207. package/docs/retro/0219-reduce-test-duplication-top-3-clone-families.md +0 -64
  208. package/docs/retro/0227-evolve-agent-record-into-agent.md +0 -80
  209. package/docs/retro/0228-async-start-agent-dissolve-run-handle.md +0 -80
  210. package/docs/retro/0229-agent-born-complete.md +0 -89
  211. package/docs/retro/0230-extract-concurrency-queue.md +0 -38
  212. package/docs/retro/0231-push-exec-registry-to-runner.md +0 -71
  213. package/docs/retro/0232-agent-resume-internal-observer-lifecycle.md +0 -109
  214. package/docs/retro/0237-remove-disallowed-tools.md +0 -78
  215. package/docs/retro/0238-remove-extensions-filtering.md +0 -72
  216. package/docs/retro/0239-collapse-filter-active-tools.md +0 -70
  217. package/docs/retro/0242-rename-agent-tool-to-subagent.md +0 -82
  218. package/docs/retro/0256-extract-worktree-isolation.md +0 -89
  219. package/docs/retro/0257-extract-child-session-factory.md +0 -33
  220. package/docs/retro/0262-add-workspace-provider-seam.md +0 -89
  221. package/docs/retro/0264-remove-extension-lifecycle-control.md +0 -91
  222. package/docs/retro/0265-born-complete-subagent-session.md +0 -97
  223. package/docs/retro/0270-type-consumable-public-surface.md +0 -108
  224. package/docs/retro/0272-export-workspace-collaborator-types.md +0 -38
  225. package/docs/retro/0277-encapsulate-agent-session.md +0 -80
  226. package/docs/retro/0280-rename-agent-to-subagent.md +0 -96
  227. package/docs/retro/0360-custom-agents-default-append.md +0 -81
  228. package/docs/retro/0373-extract-subagent-state.md +0 -94
  229. package/docs/retro/0374-encapsulate-subagent-start-notification.md +0 -171
  230. package/docs/retro/0375-extract-run-listener-workspace-bracket.md +0 -104
  231. package/docs/retro/0376-extract-manager-observer.md +0 -81
  232. package/docs/retro/0377-split-widget-delegation-from-runtime.md +0 -105
  233. package/docs/retro/0378-consolidate-lifecycle-test-fixtures.md +0 -100
  234. package/docs/retro/0379-consolidate-ui-tools-test-fixtures.md +0 -52
  235. package/docs/retro/0380-extract-layered-settings-loader.md +0 -97
  236. package/docs/retro/0381-replace-concurrency-queue-with-limiter.md +0 -95
  237. package/docs/retro/0400-include-parent-prompt-in-replace-mode.md +0 -84
  238. package/docs/retro/0403-abort-subagents-on-interrupt.md +0 -90
  239. package/docs/retro/0412-unify-session-mock-builders.md +0 -80
  240. package/docs/retro/0420-fold-run-metrics-live-activity-onto-record.md +0 -90
  241. package/docs/retro/0421-migrate-activity-readers-to-record-getters.md +0 -105
  242. package/docs/retro/0422-delete-activity-tracker-ui-observer.md +0 -97
  243. package/docs/retro/0423-widget-self-drive-from-lifecycle.md +0 -112
  244. package/docs/retro/0424-drop-widget-dep-from-subagent-tool.md +0 -89
  245. package/docs/retro/0425-reconcile-subagent-events-contract.md +0 -101
  246. package/docs/retro/0426-consolidate-residual-test-clone-families.md +0 -100
  247. package/docs/retro/0427-reconsider-ui-direction.md +0 -102
  248. package/docs/retro/0441-remove-agent-definition-management-subtree.md +0 -97
  249. package/docs/retro/0442-dissolve-agents-conversation-viewer.md +0 -108
  250. package/docs/retro/0443-consolidate-remaining-test-clone-families.md +0 -28
  251. package/docs/retro/0444-shrink-widget-to-background-agents.md +0 -81
  252. package/docs/retro/0445-native-session-navigation.md +0 -122
  253. package/docs/retro/0446-spike-session-navigation-entry-criteria.md +0 -99
  254. package/docs/retro/0447-extract-subagents-settings-command.md +0 -91
  255. package/docs/retro/0448-block-disabled-agent-spawn.md +0 -75
  256. package/docs/retro/0462-navigation-renderer-tui-components.md +0 -105
  257. package/docs/retro/0463-file-snapshot-source-evicted-agents.md +0 -103
  258. package/docs/retro/0470-refresh-readme-command-surface.md +0 -40
  259. package/src/observation/notification-state.ts +0 -27
  260. package/vitest.config.ts +0 -14
@@ -1,304 +0,0 @@
1
- ---
2
- issue: 277
3
- issue_title: "Encapsulate AgentSession behind SubagentSession; retire the remaining agent.session reach-throughs"
4
- ---
5
-
6
- # Encapsulate AgentSession behind SubagentSession
7
-
8
- ## Problem Statement
9
-
10
- Callers outside the `lifecycle/` domain reach through `Agent.session` (which returns the raw SDK `AgentSession` via `this.subagentSession?.session`) and operate on the session object directly.
11
- This violates Law of Demeter and Tell-Don't-Ask — the missing abstractions are intent-revealing methods on `Agent` and `SubagentSession` that delegate internally.
12
-
13
- Issue #265 introduced `SubagentSession` and routed the run/resume/dispose path through it.
14
- The remaining consumer-facing reach-throughs were deferred to this issue.
15
-
16
- ## Goals
17
-
18
- - Add intent-revealing methods to `Agent` and `SubagentSession` that replace every raw `AgentSession` access outside `lifecycle/`.
19
- - Collapse the duplicated steer buffer-or-deliver logic into a single `Agent.steer()` method.
20
- - Narrow the `onSessionCreated` observer callback to stop delivering the raw `AgentSession` to spawners.
21
- - Remove the `Agent.session` getter.
22
- - After this change, no production module outside `lifecycle/` references the raw `AgentSession`.
23
-
24
- ## Non-Goals
25
-
26
- - The `Agent` → `Subagent` class rename — independent of this issue, can land in either order.
27
- - Changing the public `SubagentsService` API surface in `service/service.ts` — it already uses `SubagentRecord` (no live session objects).
28
- - Refactoring the conversation viewer's rich-rendering internals — only its session reference changes.
29
- - Architecture doc updates for the file-layout listing — `SubagentSession` and `Agent` files are not being added, moved, or removed.
30
-
31
- ## Background
32
-
33
- ### Affected reach-through sites
34
-
35
- Every site reaches the raw `AgentSession` exposed by the `Agent.session` getter.
36
-
37
- | Reach-through | Production files | Current pattern |
38
- | -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
39
- | Steer buffer-or-deliver (duplicated) | `service/service-adapter.ts:93`, `tools/steer-tool.ts:43` | `record.session` → `session.steer()` or `record.queueSteer()` |
40
- | Context-percent stats | `tools/get-result-tool.ts:56`, `tools/steer-tool.ts:57`, `observation/notification.ts:49`, `ui/conversation-viewer.ts:145` | `getSessionContextPercent(record.session)` |
41
- | Conversation viewing | `tools/get-result-tool.ts:83-84`, `ui/agent-menu.ts:255`, `ui/conversation-viewer.ts:63,223` | `getAgentConversation(record.session)` / `session.messages` |
42
- | Session-readiness guard | `tools/agent-tool.ts:111`, `lifecycle/agent-manager.ts:205` | `!record.session` / `!agent?.session` |
43
- | Observer callback delivers raw session | `tools/background-spawner.ts:56`, `tools/foreground-runner.ts:111` | `onSessionCreated(_agent, session)` → `tracker.setSession(session)` + `subscribeUIObserver(session, tracker)` |
44
- | Activity-tracker session stats | `ui/widget-renderer.ts:106` | `activity?.session` → `getSessionContextPercent(activity.session)` (via `AgentActivityTracker.session`) |
45
-
46
- ### Existing delegate methods
47
-
48
- `SubagentSession` already has `steer(message)`, `runTurnLoop()`, `resumeTurnLoop()`, and `dispose()`.
49
- The `session` getter is marked "retired by #277" in its JSDoc.
50
-
51
- `subscribeAgentObserver` in `observation/record-observer.ts` already accepts `SubscribableSession` (not `AgentSession`), so it can accept `SubagentSession` directly once `SubagentSession` implements the `subscribe()` delegate.
52
-
53
- ### Public API surface
54
-
55
- The public API (`SubagentsService` + `SubagentRecord` in `service/service.ts`) does not expose `Agent` or `AgentSession`.
56
- Removing `Agent.session` is not a breaking change for cross-extension consumers.
57
-
58
- ## Design Overview
59
-
60
- ### New delegate methods on `SubagentSession`
61
-
62
- ```typescript
63
- // Delegates to getAgentConversation(this._session)
64
- getConversation(): string
65
-
66
- // Delegates to getSessionContextPercent(this._session)
67
- getContextPercent(): number | null
68
-
69
- // Delegates to this._session.subscribe(fn) — satisfies SubscribableSession
70
- subscribe(fn: (event: AgentSessionEvent) => void): () => void
71
-
72
- // Delegates to this._session.getSessionStats() — satisfies SessionLike
73
- getSessionStats(): SessionStatsLike
74
-
75
- // Delegates to this._session.messages
76
- get messages(): readonly unknown[]
77
- ```
78
-
79
- With `subscribe()` and `getSessionStats()`, `SubagentSession` structurally satisfies both `SubscribableSession` and `SessionLike`.
80
- This lets spawners pass a `SubagentSession` directly to `subscribeUIObserver()` and `tracker.setSession()` without exposing the raw `AgentSession`.
81
-
82
- ### New intent-revealing methods on `Agent`
83
-
84
- ```typescript
85
- // Buffer-or-deliver: returns true if delivered, false if buffered
86
- async steer(message: string): Promise<boolean>
87
-
88
- // Returns true when a SubagentSession is available
89
- isSessionReady(): boolean
90
-
91
- // Delegates to SubagentSession.getConversation(), returns undefined if no session
92
- getConversation(): string | undefined
93
-
94
- // Delegates to SubagentSession.getContextPercent(), returns null if no session
95
- getContextPercent(): number | null
96
-
97
- // Delegates to SubagentSession.subscribe() for conversation-viewer live updates
98
- subscribeToUpdates(fn: (event: AgentSessionEvent) => void): (() => void) | undefined
99
-
100
- // Delegates to SubagentSession.messages for conversation-viewer rendering
101
- get messages(): readonly unknown[]
102
- ```
103
-
104
- The `steer()` method replaces the duplicated buffer-or-deliver logic:
105
-
106
- ```typescript
107
- async steer(message: string): Promise<boolean> {
108
- if (!this.subagentSession) {
109
- this.queueSteer(message);
110
- return false;
111
- }
112
- await this.subagentSession.steer(message);
113
- return true;
114
- }
115
- ```
116
-
117
- ### Observer callback narrowing
118
-
119
- `AgentLifecycleObserver.onSessionCreated` changes from `(agent: Agent, session: AgentSession)` to `(agent: Agent)`.
120
- Spawners access `agent.subagentSession!` (already public) which satisfies `SubscribableSession & SessionLike`:
121
-
122
- ```typescript
123
- // tools/background-spawner.ts — after
124
- onSessionCreated: (agent) => {
125
- const sub = agent.subagentSession!;
126
- bgState.setSession(sub); // SubagentSession satisfies SessionLike
127
- subscribeUIObserver(sub, bgState); // SubagentSession satisfies SubscribableSession
128
- },
129
- ```
130
-
131
- ### Internal lifecycle wiring
132
-
133
- `Agent.run()` already passes the session to `subscribeAgentObserver()`, which accepts `SubscribableSession`.
134
- After the change, it passes `this.subagentSession` directly instead of `this.subagentSession.session`:
135
-
136
- ```typescript
137
- // lifecycle/agent.ts — Agent.run(), after
138
- this.attachObserver(subscribeAgentObserver(this.subagentSession, this, { ... }));
139
- this.observer?.onSessionCreated?.(this);
140
- ```
141
-
142
- ### Removals
143
-
144
- - `Agent.session` getter — removed entirely.
145
- - `SubagentSession.session` getter — marked `@internal`, kept for lifecycle-internal uses (the `getLastAssistantText()` private helper reads `this._session.messages`).
146
- - `Agent.queueSteer()` — becomes private (called only from `Agent.steer()` and `Agent.flushPendingSteers()`).
147
- - `Agent.flushPendingSteers()` — becomes private (called only from `Agent.run()`).
148
-
149
- ## Module-Level Changes
150
-
151
- ### `src/lifecycle/subagent-session.ts`
152
-
153
- - Add `getConversation()`, `getContextPercent()`, `subscribe()`, `getSessionStats()`, `messages` getter.
154
- - Import `getAgentConversation` from `#src/session/conversation` and `getSessionContextPercent`, `SessionStatsLike` from `#src/lifecycle/usage`.
155
- - Mark the `session` getter with `@internal` JSDoc.
156
-
157
- ### `src/lifecycle/agent.ts`
158
-
159
- - Add `steer()`, `isSessionReady()`, `getConversation()`, `getContextPercent()`, `subscribeToUpdates()`, `messages` getter.
160
- - Remove the `session` getter.
161
- - Make `queueSteer()` and `flushPendingSteers()` private.
162
- - In `run()`: pass `this.subagentSession` (not `this.subagentSession.session`) to `subscribeAgentObserver()` and fire `onSessionCreated(this)` without the session param.
163
- - In `resume()`: pass `subagentSession` (not `subagentSession.session`) to `subscribeAgentObserver()`.
164
- - Remove the `AgentSession` import.
165
- - Update `AgentLifecycleObserver.onSessionCreated` to `(agent: Agent)` — no session param.
166
-
167
- ### `src/service/service-adapter.ts`
168
-
169
- - Replace the 6-line steer reach-through with `await record.steer(message)`.
170
- - Remove the `!session` guard — `Agent.steer()` owns it.
171
-
172
- ### `src/tools/steer-tool.ts`
173
-
174
- - Replace the buffer-or-deliver dance with `const delivered = await record.steer(message)`.
175
- - Use `record.getContextPercent()` instead of `getSessionContextPercent(session)`.
176
- - Remove the `getSessionContextPercent` import.
177
-
178
- ### `src/tools/get-result-tool.ts`
179
-
180
- - Use `record.getContextPercent()` instead of `getSessionContextPercent(record.session)`.
181
- - Use `record.getConversation()` instead of `getAgentConversation(record.session)`.
182
- - Remove the `getSessionContextPercent` and `getAgentConversation` imports.
183
-
184
- ### `src/tools/agent-tool.ts`
185
-
186
- - Use `existing.isSessionReady()` instead of `!existing.session`.
187
-
188
- ### `src/lifecycle/agent-manager.ts`
189
-
190
- - Use `agent.isSessionReady()` instead of `agent?.session`.
191
- - Update the `onSessionCreated` relay to `(agent) => options.observer!.onSessionCreated!(agent)` — no session param.
192
-
193
- ### `src/observation/notification.ts`
194
-
195
- - Use `record.getContextPercent()` instead of `getSessionContextPercent(record.session)`.
196
- - Remove the `getSessionContextPercent` import.
197
-
198
- ### `src/ui/conversation-viewer.ts`
199
-
200
- - Remove `session: AgentSession` from `ConversationViewerOptions`.
201
- - Remove the `private session: AgentSession` field.
202
- - Use `this.record.subscribeToUpdates(() => ...)` instead of `session.subscribe(...)`.
203
- - Use `this.record.messages` instead of `this.session.messages`.
204
- - Use `this.record.getContextPercent()` instead of `getSessionContextPercent(this.record.session)`.
205
- - Remove the `AgentSession` and `getSessionContextPercent` imports.
206
-
207
- ### `src/ui/agent-menu.ts`
208
-
209
- - Use `record.isSessionReady()` instead of `record.session` check.
210
- - Remove the `session` variable and stop passing it to `ConversationViewer`.
211
-
212
- ### `src/tools/background-spawner.ts`
213
-
214
- - Update `onSessionCreated` callback: `(agent) => { const sub = agent.subagentSession!; ... }`.
215
- - Pass `sub` instead of `session` to `bgState.setSession()` and `subscribeUIObserver()`.
216
-
217
- ### `src/tools/foreground-runner.ts`
218
-
219
- - Same pattern as `background-spawner.ts`.
220
-
221
- ### `test/helpers/mock-session.ts`
222
-
223
- - Update `createSubagentSessionStub` to include the new delegate methods (`getConversation`, `getContextPercent`, `subscribe`, `getSessionStats`, `messages`).
224
- - The stub's `subscribe` can delegate to the underlying mock session's `subscribe`.
225
-
226
- ### Test files requiring updates
227
-
228
- - `test/lifecycle/subagent-session.test.ts` — add tests for new delegate methods.
229
- - `test/lifecycle/agent.test.ts` — add tests for `steer()`, `isSessionReady()`, `getConversation()`, `getContextPercent()`; update `queueSteer` and `flushPendingSteers` tests (now private, tested through `steer()`); update `session` getter tests to `isSessionReady()`.
230
- - `test/service/service-adapter.test.ts` — update steer tests (no more session reach-through).
231
- - `test/tools/steer-tool.test.ts` — update to use `Agent.steer()` semantics.
232
- - `test/tools/get-result-tool.test.ts` — update context-percent and conversation assertions.
233
- - `test/tools/agent-tool.test.ts` — update resume guard to use `isSessionReady()`.
234
- - `test/tools/background-spawner.test.ts` — update `onSessionCreated` callback assertions.
235
- - `test/tools/foreground-runner.test.ts` — update `onSessionCreated` callback assertions.
236
- - `test/observation/notification.test.ts` — update context-percent assertions.
237
- - `test/conversation-viewer.test.ts` — remove `session` from viewer options, update to use `record` methods.
238
- - `test/ui/agent-menu.test.ts` — update session guard assertions.
239
- - `test/lifecycle/agent-manager.test.ts` — update resume guard + observer relay tests.
240
-
241
- ## Test Impact Analysis
242
-
243
- 1. **New unit tests enabled:** Direct testing of `SubagentSession.getConversation()`, `getContextPercent()`, `subscribe()`, `getSessionStats()`, `messages` — these were previously only testable by reaching through the raw session.
244
- Direct testing of `Agent.steer()` buffer-or-deliver logic — previously scattered across consumer tests.
245
- 2. **Existing tests that become simpler:** `steer-tool.test.ts` and `service-adapter.test.ts` no longer need to set up the session-present/session-absent dance — they test through `Agent.steer()`.
246
- `get-result-tool.test.ts` no longer needs mock sessions for context-percent assertions.
247
- 3. **Existing tests that stay as-is:** `SubagentSession.runTurnLoop()` and `resumeTurnLoop()` tests — they exercise turn driving, which is unrelated.
248
- `Agent.run()` integration tests — they verify the full lifecycle including observer wiring.
249
-
250
- ## TDD Order
251
-
252
- 1. Add delegate methods to `SubagentSession` (`getConversation`, `getContextPercent`, `subscribe`, `getSessionStats`, `messages`).
253
- Update `createSubagentSessionStub` test helper to include the new methods.
254
- Test: unit tests for each delegate method in `subagent-session.test.ts`.
255
- Commit: `feat: add delegate methods to SubagentSession for session encapsulation (#277)`.
256
-
257
- 2. Add intent-revealing methods to `Agent` (`steer`, `isSessionReady`, `getConversation`, `getContextPercent`, `subscribeToUpdates`, `messages`).
258
- Test: unit tests for each method in `agent.test.ts`.
259
- Commit: `feat: add session-encapsulation methods to Agent (#277)`.
260
-
261
- 3. Migrate steer callers: replace the buffer-or-deliver reach-through in `service-adapter.ts` and `steer-tool.ts` with `record.steer()`.
262
- Replace `getSessionContextPercent(session)` in `steer-tool.ts` with `record.getContextPercent()`.
263
- Make `queueSteer()` and `flushPendingSteers()` private on `Agent`.
264
- Update tests in `service-adapter.test.ts`, `steer-tool.test.ts`, `agent.test.ts` (the `queueSteer`/`flushPendingSteers` tests become tests for `Agent.steer()`; existing tests from step 2 may cover this).
265
- Commit: `refactor: use Agent.steer for buffer-or-deliver (#277)`.
266
-
267
- 4. Migrate context-percent, conversation, and readiness callers: `get-result-tool.ts`, `agent-tool.ts`, `agent-manager.ts`, `notification.ts`.
268
- Update corresponding test files.
269
- Commit: `refactor: replace session reach-throughs in tools and observation (#277)`.
270
-
271
- 5. Refactor conversation viewer and agent-menu: remove `session: AgentSession` from `ConversationViewerOptions`, use `record` methods for subscribe/messages/contextPercent.
272
- Update `conversation-viewer.test.ts` and `agent-menu.test.ts`.
273
- Commit: `refactor: remove raw session from conversation viewer (#277)`.
274
-
275
- 6. Narrow `onSessionCreated` callback: change `AgentLifecycleObserver.onSessionCreated` to `(agent: Agent)` — no session param.
276
- Update `Agent.run()` and `Agent.resume()` to pass `SubagentSession` (not raw session) to `subscribeAgentObserver`.
277
- Update spawners (`background-spawner.ts`, `foreground-runner.ts`) and `agent-manager.ts` relay.
278
- Update corresponding test files.
279
- Commit: `refactor: narrow onSessionCreated to hide raw AgentSession (#277)`.
280
-
281
- 7. Remove `Agent.session` getter.
282
- Mark `SubagentSession.session` getter as `@internal`.
283
- Remove `AgentSession` import from `agent.ts`.
284
- Update any remaining tests that reference `Agent.session` (use `agent.isSessionReady()` or `agent.subagentSession`).
285
- Verify with `pnpm run check` and `pnpm -r run test`.
286
- Commit: `refactor: remove Agent.session getter (#277)`.
287
-
288
- 8. Update the architecture doc's "Session encapsulation debt" section to reflect completion.
289
- Commit: `docs: mark session encapsulation debt resolved (#277)`.
290
-
291
- ## Risks and Mitigations
292
-
293
- | Risk | Mitigation |
294
- | --------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
295
- | `SubagentSession` might not structurally satisfy `SubscribableSession` or `SessionLike` | Verify with `pnpm run check` after step 1 — the delegate methods must match the expected signatures exactly. |
296
- | Making `queueSteer`/`flushPendingSteers` private breaks tests | Step 3 explicitly migrates those tests to exercise `Agent.steer()` instead. |
297
- | The conversation viewer's `messages` accessor returns `readonly unknown[]` which loses typing | The viewer already casts messages to `{ role: string; [key: string]: unknown }` — the cast is unchanged, and the viewer's rendering is unaffected. |
298
- | Narrowing `onSessionCreated` could break the `agent-manager.ts` relay's non-null assertion | The relay checks `options.observer?.onSessionCreated` before wiring — the narrowed signature is structurally compatible; the only change is dropping the second parameter. |
299
- | Large number of test files to update | Steps 3–6 group migrations by concern (steer, stats/conversation/readiness, viewer, observer) so each commit is self-contained and reviewable. |
300
-
301
- ## Open Questions
302
-
303
- - None — the issue's proposed methods are unambiguous and the acceptance criteria are clear.
304
- The only design addition beyond the issue is narrowing `onSessionCreated` and adding `messages`/`subscribeToUpdates` for the conversation viewer, both of which are required to satisfy the "no production module outside lifecycle/ references AgentSession" acceptance criterion.
@@ -1,197 +0,0 @@
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
@@ -1,132 +0,0 @@
1
- ---
2
- issue: 360
3
- issue_title: "fix(pi-subagents): custom agents default to replace mode instead of append"
4
- ---
5
-
6
- # Custom agents default to append prompt mode
7
-
8
- ## Problem Statement
9
-
10
- Custom agents loaded from `.pi/agents/*.md` (and the global agents directory) default to `replace` prompt mode when no `prompt_mode` frontmatter key is present, while built-in agents default to `append`.
11
- This asymmetry surprises users: a custom agent with no explicit `prompt_mode` silently drops the parent system prompt (AGENTS.md, skills, project conventions) and instead shows the bare replace-mode header. @jeffutter reported this in [#180 (comment)](https://github.com/gotgenes/pi-packages/issues/180#issuecomment-4644369646) — their `researcher` agent rendered `"You are a pi coding agent sub-agent."` instead of inheriting the parent prompt.
12
-
13
- The root cause is the ternary in `src/config/custom-agents.ts` line 65:
14
-
15
- ```typescript
16
- promptMode: fm.prompt_mode === "append" ? "append" : "replace",
17
- ```
18
-
19
- Any value other than the literal `"append"` — including `undefined` (key omitted) — falls through to `replace`.
20
-
21
- ## Goals
22
-
23
- - Custom agents without an explicit `prompt_mode` frontmatter key default to `append`, matching the built-in default in `agent-types.ts`.
24
- - Only `prompt_mode: replace` (explicit opt-in) selects replace mode.
25
- - Update tests and user-facing documentation to reflect the new default.
26
-
27
- This is a **breaking change**: any existing `.pi/agents/*.md` that omits `prompt_mode` flips from `replace` to `append` on upgrade, so those agents begin inheriting the parent system prompt (AGENTS.md / CLAUDE.md / skills) where they previously did not.
28
- The behavior change is triggered purely by upgrading, with no config edit — it warrants a `fix!:` commit and a `BREAKING CHANGE:` footer so release-please cuts a major version.
29
- Users who relied on the old implicit-`replace` behavior must add `prompt_mode: replace` explicitly to restore it.
30
-
31
- ## Non-Goals
32
-
33
- - No change to built-in agents (`default-agents.ts`): `Explore` and `Plan` keep their explicit `promptMode: "replace"`, `general-purpose` keeps `append`.
34
- - No change to the prompt-assembly logic in `src/session/prompts.ts` — only the default a custom agent resolves to changes.
35
- - No change to other frontmatter field defaults or parsers.
36
-
37
- ## Background
38
-
39
- - `src/config/custom-agents.ts` — `loadFromDir` parses each `.md` file's frontmatter into an `AgentConfig`.
40
- Line 65 is the only place a custom agent's `promptMode` is decided.
41
- - `src/config/agent-types.ts:118` — the built-in absolute-fallback config uses `promptMode: "append"`.
42
- - `src/session/prompts.ts:36` — `buildAgentPrompt` branches on `config.promptMode === "append"`; append mode threads the parent system prompt (AGENTS.md / CLAUDE.md) into the child, replace mode does not.
43
- - The field-parser convention documented at the top of the parser section of `custom-agents.ts` is "omitted → default, none/empty → nothing, value → exact".
44
- Today `prompt_mode` violates the spirit of "omitted → default" by mapping omitted to `replace` rather than the system default `append`.
45
- This fix aligns it.
46
-
47
- Constraint from AGENTS.md: this is the `pi-subagents` package — Biome handles formatting, the upstream vitest suite is a regression canary, and all tests must pass before publishing.
48
-
49
- ## Design Overview
50
-
51
- Flip the ternary so `replace` requires an explicit opt-in and everything else (including omitted) defaults to `append`:
52
-
53
- ```typescript
54
- promptMode: fm.prompt_mode === "replace" ? "replace" : "append",
55
- ```
56
-
57
- Decision table for the resolved `promptMode`:
58
-
59
- | `prompt_mode` frontmatter value | Before | After |
60
- | ------------------------------- | ------- | ------- |
61
- | omitted / `undefined` | replace | append |
62
- | `replace` | replace | replace |
63
- | `append` | append | append |
64
- | unknown (e.g. `merge`) | replace | append |
65
-
66
- Unknown values now resolve to `append` rather than `replace`.
67
- This is the safer fallback: an append-mode agent inherits the parent prompt (a superset), so a typo degrades to "inherits everything" rather than "silently drops project context".
68
-
69
- No type shape changes — `promptMode` remains `"replace" | "append"` (`src/types.ts`).
70
-
71
- ## Module-Level Changes
72
-
73
- - `src/config/custom-agents.ts` (line 65) — flip the ternary to `fm.prompt_mode === "replace" ? "replace" : "append"`.
74
- - `src/ui/agent-creation-wizard.ts` (line 106) — update the inline frontmatter doc comment: `Default: replace` → `Default: append` for `prompt_mode`.
75
- The surrounding guidelines (lines 117–118) already describe both modes correctly and need no change.
76
- - `README.md` (line 187) — change the `prompt_mode` default column from `` `replace` `` to `` `append` ``.
77
- Keep the cell's behavioral description of `replace`/`append` unchanged.
78
- - `test/config/custom-agents.test.ts` — update the two tests that assert the old default (see TDD Order).
79
-
80
- No architecture-doc references to the default value were found (`docs/architecture/` describes module layout, not field defaults). `CHANGELOG.md` is owned by release-please and is not edited.
81
-
82
- ## Test Impact Analysis
83
-
84
- This is a behavior fix, not an extraction, so no new test layers are enabled and no tests become redundant.
85
- Existing tests in `test/config/custom-agents.test.ts` directly exercise the changed line and must be updated to assert the new default:
86
-
87
- 1. `"uses sensible defaults when frontmatter is empty"` — empty frontmatter currently asserts `promptMode` is `"replace"`; must become `"append"`.
88
- 2. `"defaults unknown prompt_mode to replace"` — feeds `prompt_mode: merge` and asserts `"replace"`; must be renamed to `"defaults unknown prompt_mode to append"` and assert `"append"`.
89
- 3. `"loads a basic agent with all frontmatter fields"` (explicit `prompt_mode: replace`) and `"handles prompt_mode: append"` — both pass an explicit value and stay as-is; they pin the explicit-opt-in behavior.
90
- 4. `"uses sensible defaults when no frontmatter at all"` (the `bare` agent) does not currently assert `promptMode` — add an assertion that it resolves to `"append"` to lock the no-frontmatter path.
91
-
92
- ## TDD Order
93
-
94
- 1. Red → Green: update default-mode tests in `test/config/custom-agents.test.ts`.
95
- - Change the empty-frontmatter test to expect `promptMode` `"append"`.
96
- - Rename the unknown-mode test to `"defaults unknown prompt_mode to append"` and expect `"append"`.
97
- - Add a `promptMode` assertion (`"append"`) to the no-frontmatter (`bare`) test.
98
- - These fail against the current line 65, then pass after the source fix.
99
- - Apply the one-line fix in `src/config/custom-agents.ts` in the same cycle (the test file and source are coupled — the type checker and assertions move together).
100
- - Commit (breaking — include the footer):
101
-
102
- ```text
103
- fix(pi-subagents)!: default custom agents to append prompt mode (#360)
104
-
105
- BREAKING CHANGE: Custom agents in .pi/agents/*.md that omit the
106
- prompt_mode frontmatter key now default to append instead of replace,
107
- so they inherit the parent system prompt (AGENTS.md / CLAUDE.md /
108
- skills). Add `prompt_mode: replace` explicitly to restore the previous
109
- standalone-prompt behavior.
110
- ```
111
-
112
- 2. Docs: update user-facing default documentation.
113
- - `src/ui/agent-creation-wizard.ts` — `prompt_mode` `Default: replace` → `Default: append`.
114
- - `README.md` — `prompt_mode` default cell → `` `append` ``.
115
- - Commit: `docs(pi-subagents): note custom agents default to append prompt mode (#360)`.
116
-
117
- (Optional: steps 1 and 2 may be combined into a single `fix!:` commit since the doc updates are part of the same behavioral correction; keeping them split keeps the source/test change isolated from prose.
118
- If combined, the `BREAKING CHANGE:` footer lives on the single commit.)
119
-
120
- ## Risks and Mitigations
121
-
122
- - Risk: existing users rely on the old implicit-`replace` behavior for custom agents that omit `prompt_mode`.
123
- Mitigation: append mode is a superset (it inherits the parent prompt plus the agent body); the worst case is an agent that now sees more context than before, not less.
124
- Users who genuinely want a standalone prompt can add `prompt_mode: replace` explicitly.
125
- The issue frames the old behavior as a bug, and the maintainer authored it.
126
- - Risk: the upstream vitest regression canary asserts the old default somewhere.
127
- Mitigation: `grep` confirms the only default-asserting tests are in `test/config/custom-agents.test.ts`; run `pnpm --filter @gotgenes/pi-subagents run test` to confirm the full suite stays green.
128
-
129
- ## Open Questions
130
-
131
- None.
132
- The issue's proposed fix is unambiguous and the change surface is fully enumerated above.