@gotgenes/pi-subagents 18.0.1 → 18.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (268) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/docs/architecture/architecture.md +165 -203
  3. package/docs/architecture/history/phase-19-implement-ui-decisions.md +282 -0
  4. package/package.json +6 -7
  5. package/src/config/default-agents.ts +3 -0
  6. package/src/lifecycle/subagent.ts +25 -14
  7. package/src/observation/notification.ts +23 -10
  8. package/src/observation/subagent-events-observer.ts +1 -3
  9. package/src/runtime.ts +2 -1
  10. package/src/service/service-adapter.ts +20 -17
  11. package/src/session/model-resolver.ts +31 -30
  12. package/src/tools/agent-tool.ts +17 -13
  13. package/src/tools/get-result-report.ts +60 -0
  14. package/src/tools/get-result-tool.ts +25 -40
  15. package/src/tools/helpers.ts +21 -5
  16. package/src/tools/spawn-config.ts +5 -5
  17. package/src/tools/steer-tool.ts +37 -27
  18. package/src/types.ts +4 -1
  19. package/src/ui/session-navigator.ts +0 -2
  20. package/.prettierignore +0 -5
  21. package/AGENTS.md +0 -7
  22. package/docs/plans/0048-implement-subagents-api.md +0 -304
  23. package/docs/plans/0049-remove-group-join-output-file-rpc.md +0 -180
  24. package/docs/plans/0051-update-adr-0001-hard-fork.md +0 -77
  25. package/docs/plans/0052-remove-scheduled-subagents.md +0 -133
  26. package/docs/plans/0053-extract-model-resolution-from-execute.md +0 -181
  27. package/docs/plans/0054-decompose-index-into-modules.md +0 -302
  28. package/docs/plans/0057-structured-debug-logging.md +0 -154
  29. package/docs/plans/0061-session-format-transcript.md +0 -284
  30. package/docs/plans/0066-replace-as-any-with-sdk-types.md +0 -215
  31. package/docs/plans/0069-create-subagent-runtime.md +0 -345
  32. package/docs/plans/0070-extract-event-handlers.md +0 -306
  33. package/docs/plans/0071-extract-session-config-assembler.md +0 -362
  34. package/docs/plans/0072-inject-agent-manager-collaborators.md +0 -329
  35. package/docs/plans/0076-inject-cwd-into-agent-manager.md +0 -102
  36. package/docs/plans/0077-inject-project-agents-dir.md +0 -115
  37. package/docs/plans/0080-consolidate-agent-config-lookup.md +0 -247
  38. package/docs/plans/0084-extract-git-worktree-manager.md +0 -142
  39. package/docs/plans/0087-evolve-subagent-runtime-methods.md +0 -240
  40. package/docs/plans/0098-extract-agent-record-state-machine.md +0 -435
  41. package/docs/plans/0099-replace-ctx-with-parent-snapshot.md +0 -488
  42. package/docs/plans/0100-replace-callback-threading-with-session-subscription.md +0 -454
  43. package/docs/plans/0102-consolidate-test-record-factory.md +0 -176
  44. package/docs/plans/0108-extract-agent-type-registry.md +0 -322
  45. package/docs/plans/0109-extract-settings-manager.md +0 -276
  46. package/docs/plans/0110-agent-activity-tracker.md +0 -297
  47. package/docs/plans/0111-split-agent-record-lifecycle.md +0 -582
  48. package/docs/plans/0112-replace-agent-manager-callbacks.md +0 -241
  49. package/docs/plans/0113-disambiguate-spawn-options.md +0 -155
  50. package/docs/plans/0114-narrow-agent-tool-menu-deps.md +0 -279
  51. package/docs/plans/0115-decompose-agent-tool.md +0 -337
  52. package/docs/plans/0116-type-housekeeping.md +0 -351
  53. package/docs/plans/0118-settings-manager-apply-methods.md +0 -271
  54. package/docs/plans/0123-remove-vi-fn-cast-smell.md +0 -179
  55. package/docs/plans/0131-consolidate-shared-test-fixtures.md +0 -207
  56. package/docs/plans/0132-inject-io-into-session-config.md +0 -219
  57. package/docs/plans/0133-inject-sdk-boundary-into-agent-runner.md +0 -373
  58. package/docs/plans/0134-reduce-as-any-casts.md +0 -366
  59. package/docs/plans/0135-extract-display-helpers.md +0 -182
  60. package/docs/plans/0136-decompose-agent-menu.md +0 -300
  61. package/docs/plans/0144-consolidate-observation-model.md +0 -263
  62. package/docs/plans/0145-decompose-execute-push-ctx-to-boundary.md +0 -290
  63. package/docs/plans/0146-narrow-ui-context.md +0 -319
  64. package/docs/plans/0147-inject-wrap-text-into-conversation-viewer.md +0 -166
  65. package/docs/plans/0148-split-agent-widget-rendering.md +0 -255
  66. package/docs/plans/0152-add-prompt-snippet.md +0 -91
  67. package/docs/plans/0164-reorganize-into-domain-directories.md +0 -409
  68. package/docs/plans/0165-decompose-resolved-spawn-config.md +0 -157
  69. package/docs/plans/0166-extract-parent-session-info.md +0 -231
  70. package/docs/plans/0167-narrow-runner-io.md +0 -150
  71. package/docs/plans/0168-extract-tool-filter-config.md +0 -173
  72. package/docs/plans/0169-extract-run-context-from-run-options.md +0 -194
  73. package/docs/plans/0170-reduce-build-content-lines-complexity.md +0 -225
  74. package/docs/plans/0171-reduce-render-result-complexity.md +0 -200
  75. package/docs/plans/0172-extract-turn-formatting.md +0 -206
  76. package/docs/plans/0180-reorder-append-prompt-for-kv-cache.md +0 -100
  77. package/docs/plans/0185-remove-persistent-agent-memory.md +0 -161
  78. package/docs/plans/0188-replace-any-casts-with-sdk-types.md +0 -162
  79. package/docs/plans/0192-define-session-context-interface.md +0 -107
  80. package/docs/plans/0193-runtime-owns-context-queries.md +0 -245
  81. package/docs/plans/0194-align-tool-interfaces-for-structural-typing.md +0 -139
  82. package/docs/plans/0195-convert-tool-factories-to-classes.md +0 -264
  83. package/docs/plans/0196-convert-runner-menu-to-classes.md +0 -268
  84. package/docs/plans/0205-decompose-render-widget-lines.md +0 -140
  85. package/docs/plans/0206-decompose-show-agent-detail.md +0 -211
  86. package/docs/plans/0207-decompose-agent-widget-update.md +0 -242
  87. package/docs/plans/0208-extract-shared-test-fixtures.md +0 -298
  88. package/docs/plans/0214-convert-remaining-closure-factories-to-classes.md +0 -261
  89. package/docs/plans/0215-decompose-build-parent-context.md +0 -166
  90. package/docs/plans/0216-decompose-start-agent.md +0 -255
  91. package/docs/plans/0217-extract-overwrite-guard.md +0 -176
  92. package/docs/plans/0218-push-sdk-boundary-in-settings.md +0 -172
  93. package/docs/plans/0219-reduce-test-duplication-top-3-clone-families.md +0 -162
  94. package/docs/plans/0227-evolve-agent-record-into-agent.md +0 -322
  95. package/docs/plans/0228-async-start-agent-dissolve-run-handle.md +0 -288
  96. package/docs/plans/0229-agent-born-complete.md +0 -564
  97. package/docs/plans/0230-extract-concurrency-queue.md +0 -265
  98. package/docs/plans/0231-push-exec-registry-to-runner.md +0 -245
  99. package/docs/plans/0232-agent-resume-internal-observer-lifecycle.md +0 -180
  100. package/docs/plans/0237-remove-disallowed-tools.md +0 -180
  101. package/docs/plans/0238-remove-extensions-filtering.md +0 -191
  102. package/docs/plans/0239-collapse-filter-active-tools.md +0 -217
  103. package/docs/plans/0242-rename-agent-tool-to-subagent.md +0 -165
  104. package/docs/plans/0256-extract-worktree-isolation.md +0 -256
  105. package/docs/plans/0257-extract-child-session-factory.md +0 -285
  106. package/docs/plans/0262-add-workspace-provider-seam.md +0 -264
  107. package/docs/plans/0264-remove-extension-lifecycle-control.md +0 -277
  108. package/docs/plans/0265-born-complete-subagent-session.md +0 -333
  109. package/docs/plans/0270-type-consumable-public-surface.md +0 -204
  110. package/docs/plans/0272-export-workspace-collaborator-types.md +0 -147
  111. package/docs/plans/0277-encapsulate-agent-session.md +0 -304
  112. package/docs/plans/0280-rename-agent-to-subagent.md +0 -197
  113. package/docs/plans/0360-custom-agents-default-append.md +0 -132
  114. package/docs/plans/0373-extract-subagent-state.md +0 -250
  115. package/docs/plans/0374-encapsulate-subagent-start-notification.md +0 -268
  116. package/docs/plans/0375-extract-run-listener-workspace-bracket.md +0 -300
  117. package/docs/plans/0376-extract-manager-observer.md +0 -232
  118. package/docs/plans/0377-split-widget-delegation-from-runtime.md +0 -254
  119. package/docs/plans/0378-consolidate-lifecycle-test-fixtures.md +0 -243
  120. package/docs/plans/0379-consolidate-ui-tools-test-fixtures.md +0 -335
  121. package/docs/plans/0380-extract-layered-settings-loader.md +0 -223
  122. package/docs/plans/0381-replace-concurrency-queue-with-limiter.md +0 -267
  123. package/docs/plans/0400-include-parent-prompt-in-replace-mode.md +0 -199
  124. package/docs/plans/0403-abort-subagents-on-interrupt.md +0 -180
  125. package/docs/plans/0412-unify-session-mock-builders.md +0 -146
  126. package/docs/plans/0420-fold-run-metrics-live-activity-onto-record.md +0 -228
  127. package/docs/plans/0421-migrate-activity-readers-to-record-getters.md +0 -309
  128. package/docs/plans/0422-delete-activity-tracker-ui-observer.md +0 -204
  129. package/docs/plans/0423-widget-self-drive-from-lifecycle.md +0 -264
  130. package/docs/plans/0424-drop-widget-dep-from-subagent-tool.md +0 -166
  131. package/docs/plans/0425-reconcile-subagent-events-contract.md +0 -144
  132. package/docs/plans/0426-consolidate-residual-test-clone-families.md +0 -235
  133. package/docs/plans/0427-reconsider-ui-direction.md +0 -212
  134. package/docs/plans/0441-remove-agent-definition-management-subtree.md +0 -180
  135. package/docs/plans/0442-dissolve-agents-conversation-viewer.md +0 -195
  136. package/docs/plans/0443-consolidate-remaining-test-clone-families.md +0 -268
  137. package/docs/plans/0444-shrink-widget-to-background-agents.md +0 -156
  138. package/docs/plans/0445-native-session-navigation.md +0 -365
  139. package/docs/plans/0446-spike-session-navigation-entry-criteria.md +0 -171
  140. package/docs/plans/0447-extract-subagents-settings-command.md +0 -220
  141. package/docs/plans/0448-block-disabled-agent-spawn.md +0 -207
  142. package/docs/plans/0462-navigation-renderer-tui-components.md +0 -338
  143. package/docs/plans/0463-file-snapshot-source-evicted-agents.md +0 -306
  144. package/docs/plans/0470-refresh-readme-command-surface.md +0 -159
  145. package/docs/retro/0048-implement-subagents-api.md +0 -44
  146. package/docs/retro/0049-remove-group-join-output-file-rpc.md +0 -49
  147. package/docs/retro/0051-update-adr-0001-hard-fork.md +0 -39
  148. package/docs/retro/0053-extract-model-resolution-from-execute.md +0 -40
  149. package/docs/retro/0054-decompose-index-into-modules.md +0 -53
  150. package/docs/retro/0057-structured-debug-logging.md +0 -77
  151. package/docs/retro/0061-session-format-transcript.md +0 -41
  152. package/docs/retro/0066-replace-as-any-with-sdk-types.md +0 -44
  153. package/docs/retro/0069-create-subagent-runtime.md +0 -43
  154. package/docs/retro/0070-extract-event-handlers.md +0 -49
  155. package/docs/retro/0071-extract-session-config-assembler.md +0 -60
  156. package/docs/retro/0072-inject-agent-manager-collaborators.md +0 -46
  157. package/docs/retro/0076-inject-cwd-into-agent-manager.md +0 -35
  158. package/docs/retro/0077-inject-project-agents-dir.md +0 -33
  159. package/docs/retro/0080-consolidate-agent-config-lookup.md +0 -35
  160. package/docs/retro/0084-extract-git-worktree-manager.md +0 -37
  161. package/docs/retro/0087-evolve-subagent-runtime-methods.md +0 -42
  162. package/docs/retro/0098-extract-agent-record-state-machine.md +0 -46
  163. package/docs/retro/0099-replace-ctx-with-parent-snapshot.md +0 -37
  164. package/docs/retro/0100-replace-callback-threading-with-session-subscription.md +0 -36
  165. package/docs/retro/0102-consolidate-test-record-factory.md +0 -30
  166. package/docs/retro/0108-extract-agent-type-registry.md +0 -41
  167. package/docs/retro/0109-extract-settings-manager.md +0 -55
  168. package/docs/retro/0110-agent-activity-tracker.md +0 -44
  169. package/docs/retro/0111-split-agent-record-lifecycle.md +0 -61
  170. package/docs/retro/0112-replace-agent-manager-callbacks.md +0 -35
  171. package/docs/retro/0113-disambiguate-spawn-options.md +0 -29
  172. package/docs/retro/0114-narrow-agent-tool-menu-deps.md +0 -38
  173. package/docs/retro/0115-decompose-agent-tool.md +0 -51
  174. package/docs/retro/0116-type-housekeeping.md +0 -42
  175. package/docs/retro/0118-settings-manager-apply-methods.md +0 -40
  176. package/docs/retro/0123-remove-vi-fn-cast-smell.md +0 -49
  177. package/docs/retro/0131-consolidate-shared-test-fixtures.md +0 -46
  178. package/docs/retro/0132-inject-io-into-session-config.md +0 -33
  179. package/docs/retro/0133-inject-sdk-boundary-into-agent-runner.md +0 -45
  180. package/docs/retro/0134-reduce-as-any-casts.md +0 -56
  181. package/docs/retro/0135-extract-display-helpers.md +0 -38
  182. package/docs/retro/0136-decompose-agent-menu.md +0 -43
  183. package/docs/retro/0144-consolidate-observation-model.md +0 -39
  184. package/docs/retro/0145-decompose-execute-push-ctx-to-boundary.md +0 -56
  185. package/docs/retro/0146-narrow-ui-context.md +0 -70
  186. package/docs/retro/0147-inject-wrap-text-into-conversation-viewer.md +0 -90
  187. package/docs/retro/0148-split-agent-widget-rendering.md +0 -39
  188. package/docs/retro/0152-add-prompt-snippet.md +0 -34
  189. package/docs/retro/0164-reorganize-into-domain-directories.md +0 -82
  190. package/docs/retro/0165-decompose-resolved-spawn-config.md +0 -78
  191. package/docs/retro/0166-extract-parent-session-info.md +0 -66
  192. package/docs/retro/0167-narrow-runner-io.md +0 -63
  193. package/docs/retro/0168-extract-tool-filter-config.md +0 -76
  194. package/docs/retro/0169-extract-run-context-from-run-options.md +0 -68
  195. package/docs/retro/0170-reduce-build-content-lines-complexity.md +0 -72
  196. package/docs/retro/0171-reduce-render-result-complexity.md +0 -77
  197. package/docs/retro/0172-extract-turn-formatting.md +0 -80
  198. package/docs/retro/0180-reorder-append-prompt-for-kv-cache.md +0 -62
  199. package/docs/retro/0185-remove-persistent-agent-memory.md +0 -73
  200. package/docs/retro/0188-replace-any-casts-with-sdk-types.md +0 -69
  201. package/docs/retro/0192-define-session-context-interface.md +0 -59
  202. package/docs/retro/0193-runtime-owns-context-queries.md +0 -75
  203. package/docs/retro/0194-align-tool-interfaces-for-structural-typing.md +0 -62
  204. package/docs/retro/0195-convert-tool-factories-to-classes.md +0 -84
  205. package/docs/retro/0196-convert-runner-menu-to-classes.md +0 -73
  206. package/docs/retro/0205-decompose-render-widget-lines.md +0 -64
  207. package/docs/retro/0206-decompose-show-agent-detail.md +0 -67
  208. package/docs/retro/0207-decompose-agent-widget-update.md +0 -92
  209. package/docs/retro/0208-extract-shared-test-fixtures.md +0 -102
  210. package/docs/retro/0214-convert-remaining-closure-factories-to-classes.md +0 -66
  211. package/docs/retro/0215-decompose-build-parent-context.md +0 -61
  212. package/docs/retro/0216-decompose-start-agent.md +0 -80
  213. package/docs/retro/0217-extract-overwrite-guard.md +0 -63
  214. package/docs/retro/0218-push-sdk-boundary-in-settings.md +0 -72
  215. package/docs/retro/0219-reduce-test-duplication-top-3-clone-families.md +0 -64
  216. package/docs/retro/0227-evolve-agent-record-into-agent.md +0 -80
  217. package/docs/retro/0228-async-start-agent-dissolve-run-handle.md +0 -80
  218. package/docs/retro/0229-agent-born-complete.md +0 -89
  219. package/docs/retro/0230-extract-concurrency-queue.md +0 -38
  220. package/docs/retro/0231-push-exec-registry-to-runner.md +0 -71
  221. package/docs/retro/0232-agent-resume-internal-observer-lifecycle.md +0 -109
  222. package/docs/retro/0237-remove-disallowed-tools.md +0 -78
  223. package/docs/retro/0238-remove-extensions-filtering.md +0 -72
  224. package/docs/retro/0239-collapse-filter-active-tools.md +0 -70
  225. package/docs/retro/0242-rename-agent-tool-to-subagent.md +0 -82
  226. package/docs/retro/0256-extract-worktree-isolation.md +0 -89
  227. package/docs/retro/0257-extract-child-session-factory.md +0 -33
  228. package/docs/retro/0262-add-workspace-provider-seam.md +0 -89
  229. package/docs/retro/0264-remove-extension-lifecycle-control.md +0 -91
  230. package/docs/retro/0265-born-complete-subagent-session.md +0 -97
  231. package/docs/retro/0270-type-consumable-public-surface.md +0 -108
  232. package/docs/retro/0272-export-workspace-collaborator-types.md +0 -38
  233. package/docs/retro/0277-encapsulate-agent-session.md +0 -80
  234. package/docs/retro/0280-rename-agent-to-subagent.md +0 -96
  235. package/docs/retro/0360-custom-agents-default-append.md +0 -81
  236. package/docs/retro/0373-extract-subagent-state.md +0 -94
  237. package/docs/retro/0374-encapsulate-subagent-start-notification.md +0 -171
  238. package/docs/retro/0375-extract-run-listener-workspace-bracket.md +0 -104
  239. package/docs/retro/0376-extract-manager-observer.md +0 -81
  240. package/docs/retro/0377-split-widget-delegation-from-runtime.md +0 -105
  241. package/docs/retro/0378-consolidate-lifecycle-test-fixtures.md +0 -100
  242. package/docs/retro/0379-consolidate-ui-tools-test-fixtures.md +0 -52
  243. package/docs/retro/0380-extract-layered-settings-loader.md +0 -97
  244. package/docs/retro/0381-replace-concurrency-queue-with-limiter.md +0 -95
  245. package/docs/retro/0400-include-parent-prompt-in-replace-mode.md +0 -84
  246. package/docs/retro/0403-abort-subagents-on-interrupt.md +0 -90
  247. package/docs/retro/0412-unify-session-mock-builders.md +0 -80
  248. package/docs/retro/0420-fold-run-metrics-live-activity-onto-record.md +0 -90
  249. package/docs/retro/0421-migrate-activity-readers-to-record-getters.md +0 -105
  250. package/docs/retro/0422-delete-activity-tracker-ui-observer.md +0 -97
  251. package/docs/retro/0423-widget-self-drive-from-lifecycle.md +0 -112
  252. package/docs/retro/0424-drop-widget-dep-from-subagent-tool.md +0 -89
  253. package/docs/retro/0425-reconcile-subagent-events-contract.md +0 -101
  254. package/docs/retro/0426-consolidate-residual-test-clone-families.md +0 -100
  255. package/docs/retro/0427-reconsider-ui-direction.md +0 -102
  256. package/docs/retro/0441-remove-agent-definition-management-subtree.md +0 -97
  257. package/docs/retro/0442-dissolve-agents-conversation-viewer.md +0 -108
  258. package/docs/retro/0443-consolidate-remaining-test-clone-families.md +0 -28
  259. package/docs/retro/0444-shrink-widget-to-background-agents.md +0 -81
  260. package/docs/retro/0445-native-session-navigation.md +0 -122
  261. package/docs/retro/0446-spike-session-navigation-entry-criteria.md +0 -99
  262. package/docs/retro/0447-extract-subagents-settings-command.md +0 -91
  263. package/docs/retro/0448-block-disabled-agent-spawn.md +0 -75
  264. package/docs/retro/0462-navigation-renderer-tui-components.md +0 -105
  265. package/docs/retro/0463-file-snapshot-source-evicted-agents.md +0 -103
  266. package/docs/retro/0470-refresh-readme-command-surface.md +0 -40
  267. package/src/observation/notification-state.ts +0 -27
  268. package/vitest.config.ts +0 -14
@@ -1,564 +0,0 @@
1
- ---
2
- issue: 229
3
- issue_title: "Agent born complete: Agent.run() absorbs startAgent (Phase 15, Step 4)"
4
- ---
5
-
6
- # Agent born complete — Agent.run() absorbs startAgent
7
-
8
- ## Problem Statement
9
-
10
- `AgentManager.startAgent()` orchestrates the entire agent execution lifecycle on behalf of the agent.
11
- The manager reaches into Agent 10 times across `spawn()` + `startAgent()`: writing `notification` and `execution` after construction, passing its own deps as method arguments, wiring callbacks through three layers, and calling completion methods with its own state.
12
- Agent cannot run itself — it depends on the manager to push it through every phase.
13
-
14
- The `onSessionCreated` callback threads through `AgentSpawnConfig` → `startAgent` → `RunOptions` → runner, crossing four module boundaries just to deliver a session reference to the tool boundary.
15
-
16
- ## Goals
17
-
18
- - Agent receives `runner`, `worktrees`, and a lifecycle observer at construction — born complete with all dependencies.
19
- - `Agent.run()` encapsulates the full execution lifecycle: worktree setup, runner invocation, session-creation handling, observer wiring, worktree cleanup, and status transitions.
20
- - Delete `AgentManager.startAgent()`, `SpawnArgs`, and `onSessionCreated` from `AgentSpawnConfig`.
21
- - Zero post-construction writes from `AgentManager` to Agent (`notification`, `execution`, `promise` all set internally).
22
- - Move `ParentSessionInfo` and `CompactionInfo` out of `agent-manager.ts` to break the type-import cycle that would arise from `agent.ts` importing from `agent-manager.ts`.
23
- - Worktree failures propagate through the async error surface (uniform with all other run errors).
24
-
25
- ## Non-Goals
26
-
27
- - Extracting `ConcurrencyQueue` from `AgentManager` — deferred to #230.
28
- - Adding `Agent.resume()` — deferred to #232.
29
- - Removing scheduling fields from `AgentManager` (queue, runningBackground, drainQueue) — deferred to #230.
30
- - Changing `agent-runner.ts` internals — the runner's `RunOptions.onSessionCreated` callback stays; Agent is the caller now instead of the manager.
31
- - Restructuring `AgentInit` into nested sub-objects (identity/config/deps) — this plan adds optional fields alongside existing ones to minimize test churn; a follow-up can tighten the interface.
32
-
33
- ## Background
34
-
35
- ### Prerequisites (complete)
36
-
37
- - Issue #227 (Agent with behavior) — moved abort, steer buffering, worktree setup, `completeRun`/`failRun` from manager to Agent. ✅
38
- - Issue #228 (async startAgent) — converted `startAgent` to async/await, eliminated `.then()`/`.catch()`. ✅
39
- - Issue #231 (runner self-contained) — moved `exec` and `registry` to `ConcreteAgentRunner` construction. ✅
40
-
41
- ### Key modules
42
-
43
- | Module | Role | Change |
44
- | ----------------------- | ---------------------------------------- | ----------------------------------------------------- |
45
- | `agent.ts` | Status machine + per-agent behavior | Gains `run()`, lifecycle observer, run-config fields |
46
- | `agent-manager.ts` | Collection + concurrency + orchestration | Loses `startAgent`, `SpawnArgs`; `spawn()` simplified |
47
- | `agent-runner.ts` | Session orchestration | Imports `ParentSessionInfo` from new location |
48
- | `background-spawner.ts` | Tool boundary for background spawn | `onSessionCreated` → `observer` field |
49
- | `foreground-runner.ts` | Tool boundary for foreground spawn | `onSessionCreated` → `observer` field |
50
- | `record-observer.ts` | Session event → Agent stats | Imports `CompactionInfo` from new location |
51
-
52
- ### Constraint: biome/eslint conflict
53
-
54
- Per AGENTS.md, when both linters run on the same file, restructure code to eliminate assertions entirely with explicit `if` guards.
55
-
56
- ## Design Overview
57
-
58
- ### AgentLifecycleObserver interface
59
-
60
- A per-agent observer created by `AgentManager` and passed to `Agent` at construction.
61
- Replaces the scattered callback mechanisms (`onRunFinished`, `onSessionCreated`, `onCompact`).
62
-
63
- ```typescript
64
- /** Per-agent lifecycle observer — created by AgentManager for each spawn. */
65
- interface AgentLifecycleObserver {
66
- /** Fires when the agent transitions to running (inside run(), after markRunning). */
67
- onStarted?(agent: Agent): void;
68
- /** Fires when the runner creates the session — delivers the session to external consumers. */
69
- onSessionCreated?(agent: Agent, session: AgentSession): void;
70
- /** Fires once when the run completes or fails (for concurrency drain). */
71
- onRunFinished?(agent: Agent): void;
72
- /** Fires on compaction events during the run. */
73
- onCompacted?(agent: Agent, info: CompactionInfo): void;
74
- }
75
- ```
76
-
77
- All methods are optional — manager composes only the callbacks needed per agent.
78
-
79
- ### Agent constructor changes
80
-
81
- New optional fields on `AgentInit` (alongside existing identity + status fields):
82
-
83
- ```typescript
84
- interface AgentInit {
85
- // ... existing identity + status fields unchanged ...
86
-
87
- // Shared deps (new — required for run(), optional for tests)
88
- runner?: AgentRunner;
89
- worktrees?: WorktreeManager;
90
- observer?: AgentLifecycleObserver;
91
- getRunConfig?: () => RunConfig;
92
-
93
- // Run config (new — required for run(), optional for tests)
94
- snapshot?: ParentSnapshot;
95
- prompt?: string;
96
- model?: Model<any>;
97
- maxTurns?: number;
98
- isolated?: boolean;
99
- thinkingLevel?: ThinkingLevel;
100
- isolation?: IsolationMode;
101
- parentSession?: ParentSessionInfo;
102
- isBackground?: boolean;
103
- signal?: AbortSignal;
104
- }
105
- ```
106
-
107
- Fields are optional so existing tests that only test status transitions and steer buffering continue to work unchanged.
108
- `Agent.run()` guards on the required fields (`runner`, `snapshot`, `prompt`) and throws if missing.
109
-
110
- Agent creates its own `AbortController` in the constructor (not passed in).
111
- Agent creates its own `NotificationState` from `parentSession?.toolCallId` in the constructor (no external write).
112
-
113
- ### Agent.run() sketch
114
-
115
- ```typescript
116
- async run(): Promise<void> {
117
- if (!this.runner || !this.snapshot) {
118
- throw new Error("Agent not configured for execution — missing runner or snapshot");
119
- }
120
- this.markRunning(Date.now());
121
- this.observer?.onStarted?.(this);
122
- this.wireSignal(this._signal, () => this.abort());
123
-
124
- try {
125
- this.setupWorktree(); // internal, uses this.worktrees + this.isolation
126
- } catch (err) {
127
- this.markError(err);
128
- this.observer?.onRunFinished?.(this);
129
- return;
130
- }
131
-
132
- const runConfig = this._getRunConfig?.();
133
- try {
134
- const result = await this.runner.run(this.snapshot, this.type, this._prompt, {
135
- context: { cwd: this.worktreeState?.path, parentSession: this._parentSession },
136
- model: this._model,
137
- maxTurns: this._maxTurns,
138
- defaultMaxTurns: runConfig?.defaultMaxTurns,
139
- graceTurns: runConfig?.graceTurns,
140
- isolated: this._isolated,
141
- thinkingLevel: this._thinkingLevel,
142
- signal: this.abortController!.signal,
143
- onSessionCreated: (session) => {
144
- const outputFile = session.sessionManager?.getSessionFile?.() ?? undefined;
145
- this.execution = { session, outputFile };
146
- this.flushPendingSteers(session);
147
- this.attachObserver(subscribeAgentObserver(session, this, {
148
- onCompact: (r, info) => this.observer?.onCompacted?.(r, info),
149
- }));
150
- this.observer?.onSessionCreated?.(this, session);
151
- },
152
- });
153
- this.completeRun(result);
154
- } catch (err) {
155
- this.failRun(err);
156
- }
157
- }
158
- ```
159
-
160
- ### AgentManager.spawn() — after
161
-
162
- ```typescript
163
- spawn(snapshot, type, prompt, options): string {
164
- const id = randomUUID().slice(0, 17);
165
-
166
- const compositeObserver = this.buildObserver(options);
167
-
168
- const record = new Agent({
169
- id, type,
170
- description: options.description,
171
- status: options.isBackground ? "queued" : "running",
172
- startedAt: Date.now(),
173
- invocation: options.invocation,
174
- // Run config
175
- snapshot, prompt,
176
- model: options.model,
177
- maxTurns: options.maxTurns,
178
- isolated: options.isolated,
179
- thinkingLevel: options.thinkingLevel,
180
- isolation: options.isolation,
181
- parentSession: options.parentSession,
182
- isBackground: options.isBackground,
183
- signal: options.signal,
184
- // Shared deps
185
- runner: this.runner,
186
- worktrees: this.worktrees,
187
- observer: compositeObserver,
188
- getRunConfig: this.getRunConfig,
189
- });
190
- this.agents.set(id, record);
191
-
192
- if (options.isBackground) this.observer?.onAgentCreated(record);
193
-
194
- if (options.isBackground && !options.bypassQueue
195
- && this.runningBackground >= this._getMaxConcurrent()) {
196
- this.queue.push(id);
197
- return id;
198
- }
199
-
200
- record.promise = record.run();
201
- return id;
202
- }
203
- ```
204
-
205
- ### Observer composition — `buildObserver`
206
-
207
- ```typescript
208
- private buildObserver(options: AgentSpawnConfig): AgentLifecycleObserver {
209
- return {
210
- onStarted: (agent) => {
211
- if (options.isBackground) this.runningBackground++;
212
- this.observer?.onAgentStarted(agent);
213
- },
214
- onSessionCreated: options.observer?.onSessionCreated,
215
- onRunFinished: (agent) => {
216
- if (options.isBackground) this.finalizeBackgroundRun(agent);
217
- },
218
- onCompacted: (agent, info) => {
219
- this.observer?.onAgentCompacted(agent, info);
220
- },
221
- };
222
- }
223
- ```
224
-
225
- ### AgentSpawnConfig changes
226
-
227
- ```typescript
228
- export interface AgentSpawnConfig {
229
- description: string;
230
- model?: Model<any>;
231
- maxTurns?: number;
232
- isolated?: boolean;
233
- inheritContext?: boolean;
234
- thinkingLevel?: ThinkingLevel;
235
- isBackground?: boolean;
236
- bypassQueue?: boolean;
237
- isolation?: IsolationMode;
238
- invocation?: AgentInvocation;
239
- signal?: AbortSignal;
240
- parentSession?: ParentSessionInfo;
241
- /** Per-agent lifecycle observer — replaces onSessionCreated callback. */
242
- observer?: AgentLifecycleObserver;
243
- // DELETED: onSessionCreated
244
- }
245
- ```
246
-
247
- ### Queue simplification
248
-
249
- The queue changes from `{ id: string; args: SpawnArgs }[]` to `string[]` (agent IDs only).
250
- `drainQueue` calls `record.run()` directly:
251
-
252
- ```typescript
253
- private drainQueue() {
254
- while (this.queue.length > 0 && this.runningBackground < this._getMaxConcurrent()) {
255
- const id = this.queue.shift()!;
256
- const record = this.agents.get(id);
257
- if (record?.status !== "queued") continue;
258
- record.promise = record.run();
259
- }
260
- }
261
- ```
262
-
263
- The `setupWorktree` call and error handling in `drainQueue` are subsumed by `Agent.run()`.
264
- Worktree errors propagate through the promise and surface on `record.error` via `Agent.run()`'s internal `catch` → `markError` → `observer.onRunFinished`.
265
-
266
- ### Error surface change
267
-
268
- The synchronous-throw contract for worktree failure in `spawn()` is replaced by a uniform async error surface:
269
-
270
- - `spawn()` never throws (no `setupWorktree` call; Agent.run() handles it internally).
271
- - Background worktree failures surface as `record.error` via `get_subagent_result` and `/agents`.
272
- - Foreground worktree failures surface when `spawnAndWait` awaits the promise and checks `record.status`.
273
- - The try/catch in `background-spawner.ts` around `manager.spawn()` becomes unreachable for worktree errors but is retained for future-proofing.
274
-
275
- ### Type relocation
276
-
277
- `ParentSessionInfo` and `CompactionInfo` move from `agent-manager.ts` to `types.ts` to break the circular type-import that would otherwise arise (`agent-manager.ts` imports `Agent` from `agent.ts`; `agent.ts` would import `ParentSessionInfo` from `agent-manager.ts`).
278
-
279
- ### Tool-layer changes
280
-
281
- `background-spawner.ts` and `foreground-runner.ts` replace `onSessionCreated` callback with `observer` field:
282
-
283
- ```typescript
284
- // Before (background-spawner)
285
- onSessionCreated: (session) => {
286
- bgState.setSession(session);
287
- subscribeUIObserver(session, bgState);
288
- },
289
-
290
- // After
291
- observer: {
292
- onSessionCreated: (_agent, session) => {
293
- bgState.setSession(session);
294
- subscribeUIObserver(session, bgState);
295
- },
296
- },
297
- ```
298
-
299
- The `foreground-runner.ts` `onSessionCreated(session, record)` becomes `observer.onSessionCreated(agent, session)` — the parameters swap order (agent first for observer consistency) and `record` becomes `agent`.
300
-
301
- ### completeRun / failRun signature change
302
-
303
- These methods currently accept `worktrees: WorktreeManager` as a parameter (output-argument pattern inherited from the pre-#227 era).
304
- Agent now owns `worktrees`, so the parameter is removed:
305
-
306
- ```typescript
307
- // Before
308
- completeRun(result: RunResult, worktrees: WorktreeManager): void { ... }
309
- failRun(err: unknown, worktrees: WorktreeManager): void { ... }
310
-
311
- // After
312
- completeRun(result: RunResult): void { ... } // uses this.worktrees internally
313
- failRun(err: unknown): void { ... } // uses this.worktrees internally
314
- ```
315
-
316
- These methods also fire `this.observer?.onRunFinished?.(this)` instead of the old `fireOnRunFinished()` callback.
317
- The `setOnRunFinished`, `_onRunFinished`, and `fireOnRunFinished` private members are deleted.
318
-
319
- ### setupWorktree signature change
320
-
321
- `setupWorktree` currently accepts `(worktrees, isolation)` as parameters.
322
- It becomes a private no-arg method using `this.worktrees` and `this._isolation` internally.
323
-
324
- ## Module-Level Changes
325
-
326
- ### `src/types.ts`
327
-
328
- - Add `ParentSessionInfo` interface (moved from `agent-manager.ts`).
329
- - Add `CompactionInfo` type (moved from `agent-manager.ts`).
330
-
331
- ### `src/lifecycle/agent.ts`
332
-
333
- - Add `AgentLifecycleObserver` interface export.
334
- - Expand `AgentInit` with optional run-config and deps fields: `runner`, `worktrees`, `observer`, `getRunConfig`, `snapshot`, `prompt`, `model`, `maxTurns`, `isolated`, `thinkingLevel`, `isolation`, `parentSession`, `isBackground`, `signal`.
335
- - Remove `abortController` from `AgentInit` — Agent creates its own.
336
- - Remove `promise` from `AgentInit` — set internally by `run()`.
337
- - Store new fields as private readonly properties in the constructor.
338
- - Create `AbortController` in constructor.
339
- - Create `NotificationState` from `parentSession?.toolCallId` in constructor.
340
- - Add `async run(): Promise<void>` method — absorbs the full `startAgent` logic.
341
- - Change `setupWorktree` from public to private, remove parameters (uses own fields).
342
- - Change `completeRun(result, worktrees)` → `completeRun(result)` (uses own fields).
343
- - Change `failRun(err, worktrees)` → `failRun(err)` (uses own fields).
344
- - Delete `setOnRunFinished`, `_onRunFinished`, `fireOnRunFinished` — replaced by observer.
345
- - Import `subscribeAgentObserver` and `RunResult` types.
346
- - Import `ParentSessionInfo`, `CompactionInfo` from `types.ts` (not `agent-manager.ts`).
347
-
348
- ### `src/lifecycle/agent-manager.ts`
349
-
350
- - Remove `ParentSessionInfo` export (moved to `types.ts`; re-export for backward compat).
351
- - Remove `CompactionInfo` export (moved to `types.ts`; re-export for backward compat).
352
- - Delete `startAgent` private method.
353
- - Delete `SpawnArgs` interface.
354
- - Rewrite `spawn()` to create complete Agent with all deps and config, call `record.run()`.
355
- - Remove `record.notification = ...` external write (Agent creates its own).
356
- - Add private `buildObserver(options)` method to compose per-agent lifecycle observer.
357
- - Simplify queue from `{ id: string; args: SpawnArgs }[]` to `string[]`.
358
- - Simplify `drainQueue()` to call `record.run()` (no `setupWorktree`, no `startAgent`, no error catch).
359
- - Remove `onSessionCreated` from `AgentSpawnConfig`, add `observer?: AgentLifecycleObserver`.
360
- - Remove `import { subscribeAgentObserver }` (no longer used here).
361
- - Remove `import { NotificationState }` (no longer used here).
362
-
363
- ### `src/lifecycle/agent-runner.ts`
364
-
365
- - Change import of `ParentSessionInfo` from `#src/lifecycle/agent-manager` to `#src/types`.
366
-
367
- ### `src/observation/record-observer.ts`
368
-
369
- - Change import of `CompactionInfo` from `#src/lifecycle/agent-manager` to `#src/types`.
370
-
371
- ### `src/tools/background-spawner.ts`
372
-
373
- - Change import: remove `AgentSpawnConfig` (if no longer needed) or update as needed.
374
- - Import `ParentSessionInfo` from `#src/types` (if source changes).
375
- - Replace `onSessionCreated` callback with `observer` field in spawn call.
376
- - The `BackgroundManagerDeps.spawn()` signature updates to match new `AgentSpawnConfig`.
377
-
378
- ### `src/tools/foreground-runner.ts`
379
-
380
- - Replace `onSessionCreated` callback with `observer` field.
381
- - Update parameter destructuring: `(session, record)` → `(agent, session)`.
382
- - Import `ParentSessionInfo` from `#src/types`.
383
- - The `ForegroundManagerDeps.spawnAndWait()` signature updates to match new config.
384
-
385
- ### `src/tools/agent-tool.ts`
386
-
387
- - Import `ParentSessionInfo` from `#src/types` instead of `#src/lifecycle/agent-manager`.
388
- - Update `AgentToolManager` interface if `AgentSpawnConfig` shape changed.
389
-
390
- ### `src/service/service-adapter.ts`
391
-
392
- - No significant changes — `AgentManagerLike.spawn()` already accepts `unknown` options.
393
-
394
- ### `test/lifecycle/agent.test.ts`
395
-
396
- - Add test suite for `Agent.run()` covering: full lifecycle, worktree setup, session creation, observer notifications, error handling, abort signal wiring.
397
- - Update existing tests that use `completeRun(result, worktrees)` → `completeRun(result)`.
398
- - Update existing tests that use `failRun(err, worktrees)` → `failRun(err)`.
399
- - Update existing tests that use `setupWorktree(worktrees, isolation)` → remove (now private).
400
- - Remove tests for `setOnRunFinished` / `fireOnRunFinished`.
401
- - Update `AgentInit` usages that pass `abortController` — Agent creates its own.
402
-
403
- ### `test/lifecycle/agent-manager.test.ts`
404
-
405
- - Remove/rewrite `onSessionCreated callback receives record` describe block — callback is deleted.
406
- - Remove/rewrite `toolCallId notification wiring` tests — notification is now Agent-internal.
407
- - Update `execution state` tests — execution is set internally by Agent.run(), not by the manager's `onSessionCreated`.
408
- - Update mock runner stubs: runner mock should still fire `onSessionCreated` (Agent passes it to the runner).
409
- - Update tests that inspect `runner.run()` call args for the `onSessionCreated` field.
410
- - Update queue-related tests to reflect simplified queue (IDs only).
411
-
412
- ### `test/helpers/manager-stubs.ts`
413
-
414
- - Update `createSessionRunner` — it fires `opts.onSessionCreated` which is now called by Agent.run() internally; the mock pattern stays similar but the caller changes.
415
-
416
- ### `test/tools/background-spawner.test.ts`
417
-
418
- - Update spawn call to use `observer` instead of `onSessionCreated`.
419
- - Update assertions that inspect the spawn options for `onSessionCreated`.
420
-
421
- ### `test/tools/foreground-runner.test.ts`
422
-
423
- - Update `onSessionCreated` usage to `observer.onSessionCreated`.
424
- - Update parameter order in callback assertions: `(agent, session)` instead of `(session, record)`.
425
-
426
- ### `test/helpers/make-agent.ts`
427
-
428
- - Remove `abortController` from the factory default (if present) — Agent creates its own.
429
- - No other changes needed — run-config fields are optional.
430
-
431
- ### `packages/pi-subagents/docs/architecture/architecture.md`
432
-
433
- - Update Step 4 status from planned to complete.
434
- - Update the file layout listing for `agent.ts` and `agent-manager.ts` descriptions.
435
- - Mark `SpawnArgs` and `startAgent` as deleted in the listing.
436
-
437
- ## Test Impact Analysis
438
-
439
- 1. **New unit tests enabled by extraction:**
440
- - `Agent.run()` can be tested in isolation with mock runner and worktrees — no need for the full `AgentManager` + queue + concurrency infrastructure.
441
- - Lifecycle observer callbacks can be tested directly on a single Agent instance.
442
- - Worktree error handling in `run()` can be tested without the manager's `spawn()` error-recovery logic.
443
-
444
- 2. **Existing tests that become redundant:**
445
- - `AgentManager — onSessionCreated callback receives record` — the callback mechanism is deleted.
446
- - `AgentManager — toolCallId notification wiring` — Agent now creates its own `NotificationState`; manager-level tests for this become Agent-level tests.
447
- - Some `agent-manager.test.ts` tests that indirectly test execution/observer wiring can be simplified to verify that `agent.run()` is called (delegation test) rather than re-testing the internal lifecycle.
448
-
449
- 3. **Existing tests that stay as-is:**
450
- - Queue/concurrency tests in `agent-manager.test.ts` — these test manager-level scheduling, not run internals.
451
- - `record-observer.test.ts` — observer logic unchanged; only import path changes.
452
- - `agent-runner.test.ts` — runner internals unchanged.
453
- - Status transition tests in `agent.test.ts` — Agent status machine unchanged.
454
- - `background-spawner.test.ts` / `foreground-runner.test.ts` — updated for observer pattern but same behavioral coverage.
455
-
456
- ## TDD Order
457
-
458
- 1. **Move `ParentSessionInfo` and `CompactionInfo` to `types.ts`.**
459
- Add both to `types.ts`.
460
- Re-export from `agent-manager.ts` for backward compat.
461
- Update `agent-runner.ts` and `record-observer.ts` imports to use `types.ts`.
462
- Verify all existing tests pass.
463
- Commit: `refactor: move ParentSessionInfo and CompactionInfo to types.ts (#229)`
464
-
465
- 2. **Add `AgentLifecycleObserver` interface to `agent.ts`.**
466
- Define and export the interface with optional `onStarted`, `onSessionCreated`, `onRunFinished`, `onCompacted` methods.
467
- No behavioral changes — just the type definition.
468
- Commit: `feat: add AgentLifecycleObserver interface (#229)`
469
-
470
- 3. **Expand `AgentInit` with run-config and deps fields; Agent stores them.**
471
- Add optional fields to `AgentInit`: `runner`, `worktrees`, `observer`, `getRunConfig`, `snapshot`, `prompt`, `model`, `maxTurns`, `isolated`, `thinkingLevel`, `isolation`, `parentSession`, `isBackground`, `signal`.
472
- Agent stores them as private properties in the constructor.
473
- Agent creates its own `AbortController` in the constructor.
474
- Agent creates `NotificationState` from `parentSession?.toolCallId` in the constructor.
475
- Remove `abortController` from `AgentInit` (Agent creates its own).
476
- Update `createTestAgent` helper and `agent.test.ts` to remove `abortController` from init; tests that need abort can use `record.abortController` directly.
477
- Write tests: constructor stores deps and run config; constructor creates AbortController; constructor creates NotificationState when toolCallId present; constructor does not create NotificationState when toolCallId absent.
478
- Commit: `feat: expand AgentInit with run-config, deps, and self-created AbortController (#229)`
479
-
480
- 4. **Change `setupWorktree` to private, remove parameters.**
481
- Make `setupWorktree` a private method that uses `this.worktrees` and `this._isolation`.
482
- Update `AgentManager.spawn()` and `drainQueue()` call sites: `record.setupWorktree(this.worktrees, options.isolation)` → remove (will be called by `run()`).
483
- Temporarily call `setupWorktree` from the manager's `spawn` path (keep the old call pattern working until `run()` is added in step 6).
484
- Update `agent.test.ts` tests that called `setupWorktree` directly — convert to testing via `run()` or remove if redundant.
485
- Commit: `refactor: make setupWorktree private, remove parameters (#229)`
486
-
487
- 5. **Change `completeRun`/`failRun` to use own `worktrees`; replace `fireOnRunFinished` with observer.**
488
- Remove `worktrees` parameter from `completeRun` and `failRun`.
489
- Replace `fireOnRunFinished()` with `this.observer?.onRunFinished?.(this)`.
490
- Delete `setOnRunFinished`, `_onRunFinished`, `fireOnRunFinished`.
491
- Update `agent-manager.ts`: stop calling `record.setOnRunFinished(...)`, stop passing `this.worktrees` to `completeRun`/`failRun`.
492
- Update all `agent.test.ts` tests that call `completeRun(result, worktrees)` and `failRun(err, worktrees)`.
493
- Update `agent-manager.test.ts` tests that verify `setOnRunFinished` or concurrency drain — drain now works via the observer's `onRunFinished`.
494
- Write test: `completeRun` calls `observer.onRunFinished`; `failRun` calls `observer.onRunFinished`.
495
- Commit: `refactor: remove worktrees param from completeRun/failRun, replace fireOnRunFinished with observer (#229)`
496
-
497
- 6. **Add `Agent.run()` method — absorbs `startAgent` logic.**
498
- Implement `Agent.run()` following the design sketch above.
499
- Write tests for `Agent.run()`:
500
- - Happy path: run completes, status transitions, observer callbacks fire in order.
501
- - Session creation: execution state set, steers flushed, record-observer attached.
502
- - Worktree setup and cleanup on success.
503
- - Worktree setup failure: markError + observer.onRunFinished.
504
- - Runner error: failRun + observer.onRunFinished.
505
- - Abort signal forwarding.
506
- - RunConfig threading (defaultMaxTurns, graceTurns).
507
- Commit: `feat: add Agent.run() encapsulating full execution lifecycle (#229)`
508
-
509
- 7. **Rewrite `AgentManager.spawn()` to create complete Agent and call `agent.run()`.**
510
- Delete `startAgent`.
511
- Delete `SpawnArgs`.
512
- Add `buildObserver` private method.
513
- Rewrite `spawn()` to construct Agent with all fields, call `record.run()`.
514
- Remove `record.notification = ...` external write.
515
- Remove `subscribeAgentObserver` and `NotificationState` imports.
516
- Simplify queue from `{ id: string; args: SpawnArgs }[]` to `string[]`.
517
- Simplify `drainQueue()` to call `record.run()`.
518
- Replace `onSessionCreated` with `observer` on `AgentSpawnConfig`.
519
- Update `agent-manager.test.ts`:
520
- - Remove `onSessionCreated callback receives record` tests.
521
- - Update notification wiring tests (now Agent-internal).
522
- - Update mock runners if needed.
523
- - Verify queue/concurrency tests still pass.
524
- Commit: `feat!: AgentManager.spawn() creates complete Agent, deletes startAgent (#229)`
525
-
526
- 8. **Update tool-layer consumers: `background-spawner.ts`, `foreground-runner.ts`, `agent-tool.ts`.**
527
- Replace `onSessionCreated` callback with `observer` field in both spawner and runner.
528
- Update `foreground-runner.ts` callback: `(session, record)` → `(agent, session)`.
529
- Update `agent-tool.ts` imports: `ParentSessionInfo` from `#src/types`.
530
- Update narrow manager interfaces (`BackgroundManagerDeps`, `ForegroundManagerDeps`, `AgentToolManager`) to reflect new `AgentSpawnConfig` shape.
531
- Update `background-spawner.test.ts` and `foreground-runner.test.ts`.
532
- Commit: `refactor: update tool layer to use lifecycle observer instead of onSessionCreated (#229)`
533
-
534
- 9. **Remove backward-compat re-exports and update architecture docs.**
535
- Remove `ParentSessionInfo` and `CompactionInfo` re-exports from `agent-manager.ts` (if no external consumer depends on the old location).
536
- Update `docs/architecture/architecture.md`: mark Step 4 complete, update file listings.
537
- Commit: `docs: mark Phase 15 Step 4 complete, update architecture (#229)`
538
-
539
- ## Risks and Mitigations
540
-
541
- 1. **Large test surface.**
542
- `agent.test.ts` (684 lines) and `agent-manager.test.ts` (815 lines) both need significant updates.
543
- Mitigation: Lift-and-shift approach — new fields are optional on `AgentInit`, so most existing tests compile unchanged.
544
- Only tests that touch `completeRun`, `failRun`, `setupWorktree`, `setOnRunFinished`, `abortController`, or `onSessionCreated` need updating.
545
-
546
- 2. **Breaking change for `AgentSpawnConfig` consumers.**
547
- `onSessionCreated` is deleted.
548
- The `service-adapter.ts` and cross-extension consumers that pass `AgentSpawnConfig` may need updates.
549
- Mitigation: `service-adapter.ts` passes `unknown` for options — no compile error.
550
- The `observer` field is optional, so consumers that don't use `onSessionCreated` are unaffected.
551
-
552
- 3. **Async worktree error surface changes tool-layer behavior.**
553
- `background-spawner.ts` catch block around `manager.spawn()` becomes unreachable for worktree errors.
554
- Mitigation: Keep the catch block for other potential errors; the agent's error status surfaces the worktree failure message to users.
555
-
556
- 4. **`AgentInit` grows wide (15+ optional fields).**
557
- Mitigation: Fields are optional with sensible defaults.
558
- Follow-up #230 may restructure Agent's constructor (ConcurrencyQueue changes may motivate nesting).
559
- Tracked as a known smell to revisit.
560
-
561
- ## Open Questions
562
-
563
- 1. Should the backward-compat re-exports of `ParentSessionInfo`/`CompactionInfo` from `agent-manager.ts` stay permanently, or be removed in step 9?
564
- Decision: remove in step 9 if grep confirms no external consumers.