@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,172 +0,0 @@
1
- ---
2
- issue: 218
3
- issue_title: "Push SDK boundary in settings.ts (Phase 13, Step 5)"
4
- ---
5
-
6
- # Push SDK boundary in settings.ts
7
-
8
- ## Problem Statement
9
-
10
- `settings.ts` imports `getAgentDir` from the Pi SDK (`@earendil-works/pi-coding-agent`) and calls it inside `globalPath()` at invocation time.
11
- This hides a platform dependency inside a module that is otherwise pure configuration logic — violating the project's SDK-boundary rule that pure helpers and domain modules should remain SDK-independent.
12
- The SDK call also forces tests to redirect the env var `PI_CODING_AGENT_DIR` to control `getAgentDir()` output, rather than passing the value directly.
13
-
14
- ## Goals
15
-
16
- - Remove the `getAgentDir` import from `settings.ts` (0 Pi SDK imports).
17
- - Inject `agentDir: string` into `SettingsManager` constructor deps.
18
- - Make `loadSettings` accept `agentDir` as an explicit parameter.
19
- - Eliminate `PI_CODING_AGENT_DIR` env var manipulation from all settings tests.
20
-
21
- ## Non-Goals
22
-
23
- - Removing `process.cwd()` defaults from `loadSettings`/`saveSettings` — that's a separate concern (Node.js API, not Pi SDK).
24
- - Pushing SDK boundaries in other files (`skill-loader.ts`, `custom-agents.ts`, `agent-runner.ts`) — tracked separately in the Phase 13 roadmap.
25
- - Changing the `saveSettings` signature — it only calls `projectPath(cwd)` and has no SDK dependency.
26
-
27
- ## Background
28
-
29
- `settings.ts` exports a `SettingsManager` class and two free functions (`loadSettings`, `saveSettings`).
30
- The only SDK import is `getAgentDir`, used in the private `globalPath()` helper to compute the global settings file path (`~/.pi/agent/subagents.json`).
31
-
32
- The `SettingsManager` constructor already accepts a deps bag `{ emit, cwd, onMaxConcurrentChanged? }`.
33
- Adding `agentDir` to this bag follows the established injection pattern.
34
-
35
- In `index.ts`, `getAgentDir` is already imported for several other call sites (agent runner IO, agent tool, `/agents` menu).
36
- Adding one more usage to the `SettingsManager` construction is zero new imports.
37
-
38
- ### Relevant AGENTS.md constraints
39
-
40
- - **Pi SDK boundaries:** Keep Pi SDK imports out of business-logic modules; accept the value as a parameter or callback.
41
- - **Code-design skill, DIP:** Default to dependency injection for non-trivial dependencies.
42
-
43
- ## Design Overview
44
-
45
- ### Change to `globalPath()`
46
-
47
- Currently:
48
-
49
- ```typescript
50
- function globalPath(): string {
51
- return join(getAgentDir(), "subagents.json");
52
- }
53
- ```
54
-
55
- After:
56
-
57
- ```typescript
58
- function globalPath(agentDir: string): string {
59
- return join(agentDir, "subagents.json");
60
- }
61
- ```
62
-
63
- ### Change to `loadSettings()`
64
-
65
- Currently:
66
-
67
- ```typescript
68
- export function loadSettings(cwd: string = process.cwd()): SubagentsSettings {
69
- return { ...readSettingsFile(globalPath()), ...readSettingsFile(projectPath(cwd)) };
70
- }
71
- ```
72
-
73
- After:
74
-
75
- ```typescript
76
- export function loadSettings(agentDir: string, cwd: string = process.cwd()): SubagentsSettings {
77
- return { ...readSettingsFile(globalPath(agentDir)), ...readSettingsFile(projectPath(cwd)) };
78
- }
79
- ```
80
-
81
- ### Change to `SettingsManager` constructor
82
-
83
- Add `agentDir: string` to the deps bag:
84
-
85
- ```typescript
86
- constructor(deps: { emit: SettingsEmit; cwd: string; agentDir: string; onMaxConcurrentChanged?: () => void }) {
87
- this.emit = deps.emit;
88
- this.cwd = deps.cwd;
89
- this.agentDir = deps.agentDir;
90
- this.onMaxConcurrentChanged = deps.onMaxConcurrentChanged;
91
- }
92
- ```
93
-
94
- `SettingsManager.load()` passes `this.agentDir` to `loadSettings`:
95
-
96
- ```typescript
97
- load(): SubagentsSettings {
98
- const settings = loadSettings(this.agentDir, this.cwd);
99
- // ... rest unchanged
100
- }
101
- ```
102
-
103
- ### Wiring in `index.ts`
104
-
105
- ```typescript
106
- const settings = new SettingsManager({
107
- emit: (event, payload) => pi.events.emit(event, payload),
108
- cwd: process.cwd(),
109
- agentDir: getAgentDir(),
110
- onMaxConcurrentChanged: () => manager.notifyConcurrencyChanged(),
111
- });
112
- ```
113
-
114
- ## Module-Level Changes
115
-
116
- ### `src/settings.ts`
117
-
118
- 1. Remove `import { getAgentDir } from "@earendil-works/pi-coding-agent"`.
119
- 2. Add `agentDir: string` field to the `SettingsManager` constructor deps interface.
120
- 3. Store `this.agentDir = deps.agentDir` as a private readonly field.
121
- 4. Change `globalPath()` signature to `globalPath(agentDir: string)`.
122
- 5. Change `loadSettings` signature to `loadSettings(agentDir: string, cwd?: string)`.
123
- 6. Update `SettingsManager.load()` to call `loadSettings(this.agentDir, this.cwd)`.
124
- 7. Update the header comment to reflect the new injection pattern.
125
-
126
- ### `src/index.ts`
127
-
128
- 1. Add `agentDir: getAgentDir()` to the `SettingsManager` constructor deps object.
129
-
130
- ### `test/settings.test.ts`
131
-
132
- 1. Remove all `PI_CODING_AGENT_DIR` env manipulation (`originalAgentDirEnv`, `beforeEach`/`afterEach` stubs).
133
- 2. Pass `globalDir` directly to `loadSettings(globalDir, projectDir)` in free-function tests.
134
- 3. Add `agentDir: globalDir` (or a dummy string for non-load tests) to all `new SettingsManager(...)` calls.
135
- 4. In `SettingsManager.load()` tests, pass `agentDir: globalDir` to the constructor.
136
- 5. In tests that don't exercise `load()`, use `agentDir: "/nonexistent"` or similar — the value is unused.
137
-
138
- ## Test Impact Analysis
139
-
140
- 1. **New capability:** Free-function tests (`loadSettings`, `saveSettings`) become pure — pass `globalDir` directly instead of manipulating `PI_CODING_AGENT_DIR`.
141
- This is simpler and more reliable.
142
- 2. **Redundant cleanup:** The `originalAgentDirEnv` save/restore pattern in `beforeEach`/`afterEach` can be removed from all `describe` blocks that use it.
143
- 3. **Existing tests stay:** All existing test scenarios remain valid; only their setup mechanics change.
144
-
145
- ## TDD Order
146
-
147
- 1. **Red → Green:** Change `loadSettings` signature to accept `agentDir` parameter; update `globalPath` to accept it.
148
- Update all free-function tests to pass `globalDir` directly instead of env var.
149
- Remove env-var manipulation from the `settings persistence` describe block.
150
- Commit: `feat: inject agentDir into loadSettings to remove SDK dependency`
151
-
152
- 2. **Red → Green:** Add `agentDir` to `SettingsManager` constructor deps; store as private field; thread into `load()`.
153
- Update all `new SettingsManager(...)` call sites in tests.
154
- Remove env-var manipulation from `SettingsManager` describe blocks.
155
- Remove `getAgentDir` import from `settings.ts`.
156
- Commit: `feat: inject agentDir into SettingsManager constructor`
157
-
158
- 3. **Green:** Wire `agentDir: getAgentDir()` into `SettingsManager` construction in `index.ts`.
159
- Run `pnpm run check` to confirm no type errors across the package.
160
- Commit: `feat: wire agentDir from SDK boundary in index.ts (#218)`
161
-
162
- ## Risks and Mitigations
163
-
164
- | Risk | Mitigation |
165
- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
166
- | Breaking the `loadSettings` export signature for hypothetical external callers | The function is only called from `SettingsManager.load()` and tests; no external consumers exist. |
167
- | Test count is high (~35 constructor sites) — mechanical updates could introduce typos | Steps 1 and 2 are focused; run `pnpm vitest run test/settings.test.ts` after each to confirm. |
168
- | Forgetting a test site that still manipulates `PI_CODING_AGENT_DIR` | Grep for `PI_CODING_AGENT_DIR` after step 2 to confirm zero remaining references in `test/settings.test.ts`. |
169
-
170
- ## Open Questions
171
-
172
- None — the issue's proposed change is unambiguous and follows the established injection pattern used in prior Phase 13 steps.
@@ -1,162 +0,0 @@
1
- ---
2
- issue: 219
3
- issue_title: "Reduce test duplication — top 3 clone families (Phase 13, Step 6)"
4
- ---
5
-
6
- # Reduce test duplication — top 3 clone families
7
-
8
- ## Problem statement
9
-
10
- After Phase 12, three test files carry the heaviest remaining clone families in pi-subagents:
11
-
12
- 1. `test/lifecycle/agent-manager.test.ts` (929 lines) — 16 clone groups, ~160 duplicated lines.
13
- Repeated inline runner stubs, worktree stubs, and manager-lifecycle boilerplate.
14
- 2. `test/conversation-viewer.test.ts` (307 lines) — 8 clone groups, ~91 duplicated lines.
15
- Near-identical `ConversationViewer` construction in every test, plus repeated width-loop assertion patterns.
16
- 3. `test/ui/agent-config-editor.test.ts` (471 lines) — 5 clone groups, ~42 duplicated lines.
17
- Repeated `makeEditor()` + `makeMenuUI()` + `fileOps.findAgentFile.mockReturnValue(...)` setup.
18
-
19
- Total target: reduce test duplication by ~200 lines (from ~1,046 combined test-setup lines to < 850).
20
-
21
- ## Goals
22
-
23
- - Extract shared setup and assertion helpers for the three target test files.
24
- - Reduce test duplication by ~200 lines without changing test semantics.
25
- - Follow the existing `test/helpers/` convention (factory + matching `.test.ts` file).
26
-
27
- ## Non-goals
28
-
29
- - No production code changes.
30
- - No new test coverage — this is purely a refactoring of existing test infrastructure.
31
- - Not consolidating clone families in other test files beyond the top 3.
32
- - Not changing any assertion logic or test structure beyond replacing inline stubs with factory calls.
33
-
34
- ## Background
35
-
36
- The project already has several shared test helpers in `test/helpers/`: `make-record.ts`, `mock-session.ts`, `ui-stubs.ts`, `runner-io.ts`, `stub-ctx.ts`, `make-deps.ts`.
37
- Each helper has a companion `.test.ts` file — this convention must be followed.
38
-
39
- Dependencies #214 (closure-to-class conversions) and #216 (startAgent decomposition) are both closed, so the production code these tests cover is stable.
40
-
41
- ## Design overview
42
-
43
- ### File 1: `agent-manager.test.ts` — extract to `test/helpers/manager-stubs.ts`
44
-
45
- Five clone families to extract:
46
-
47
- 1. **Never-resolving runner** — `{ run: vi.fn().mockImplementation(() => new Promise(() => {})), resume: vi.fn() }` appears 5 times.
48
- Extract as `createBlockingRunner(): AgentRunner`.
49
-
50
- 2. **Session-creating runner** — runner that calls `opts.onSessionCreated?.(session)` and resolves.
51
- Appears 5+ times with minor variations (some emit events through the session, some don't).
52
- Extract as `createSessionRunner(session?: MockSession): AgentRunner` that calls `onSessionCreated` and returns a standard result.
53
-
54
- 3. **Worktree stubs with path+branch** — `{ create: vi.fn().mockReturnValue({ path, branch }), cleanup: vi.fn(() => ({ hasChanges: false })), prune: vi.fn() }` appears 4 times identically, plus 1 variant with `create` returning `undefined`.
55
- Extract as `createMockWorktrees(overrides?)`.
56
-
57
- 4. **Standard run result shape** — `{ responseText: "done", session, aborted: false, steered: false }` is repeated in many runner factories.
58
- Extract as `createRunResult(overrides?)`.
59
-
60
- 5. **Gated runner** — uses `Promise.withResolvers` to control when the runner completes.
61
- Appears 2 times.
62
- Keep inline — too tightly coupled to individual test flow-control to generalize cleanly.
63
-
64
- Tests that construct custom runners with unique behavior (event-emitting runners in the `lifetimeUsage` and `compactionCount` tests) keep their inline stubs — those encode test-specific emission sequences that a shared factory would obscure.
65
-
66
- ### File 2: `conversation-viewer.test.ts` — inline factory + assertion helper
67
-
68
- Two clone families to extract:
69
-
70
- 1. **`ConversationViewer` construction** — 15 near-identical constructor calls with the same 8 fields.
71
- Extract as an inline `createTestViewer(overrides?)` factory at the top of the test file.
72
- The factory provides defaults for `tui`, `session`, `record`, `activity`, `theme`, `done`, `registry`, and `wrapText`, and accepts overrides including a convenience `width` and `messages` parameter.
73
-
74
- 2. **Width-loop assertion** — the `for (const w of widths) { create viewer; assertAllLinesFit(viewer.render(w), w) }` pattern repeats in 10 "render width safety" tests.
75
- Extract as an inline `assertRenderFitsWidths(messages, widths?, viewerOverrides?)` helper.
76
-
77
- These helpers stay inline (not in `test/helpers/`) because they depend on file-local helpers (`mockTui`, `mockSession`, `ansiTheme`) and are only used by this one test file.
78
-
79
- ### File 3: `agent-config-editor.test.ts` — inline setup helper
80
-
81
- One clone family to extract:
82
-
83
- 1. **Detail-test setup** — `makeEditor()` + `makeMenuUI([...])` + `fileOps.findAgentFile.mockReturnValue(...)` + optional `fileOps.read.mockReturnValue(...)` appears in ~18 tests.
84
- Extract as an inline `setupDetail(selectResults, options?)` factory that returns `{ fileOps, editor, ui }` with pre-configured mocks.
85
- Options: `filePath`, `fileContent`, `config` (merged into default via `createTestAgentConfig`).
86
-
87
- This stays inline because it's specific to the `showAgentDetail` test suite and depends on file-local `testRegistry` setup.
88
-
89
- ## Module-level changes
90
-
91
- ### New files
92
-
93
- | File | Purpose |
94
- | ------------------------------------ | --------------------------------------------------------------------------------------- |
95
- | `test/helpers/manager-stubs.ts` | `createBlockingRunner`, `createSessionRunner`, `createMockWorktrees`, `createRunResult` |
96
- | `test/helpers/manager-stubs.test.ts` | Smoke tests for the factories |
97
-
98
- ### Modified files
99
-
100
- | File | Change |
101
- | -------------------------------------- | --------------------------------------------------------------------------- |
102
- | `test/lifecycle/agent-manager.test.ts` | Replace inline runner/worktree stubs with `manager-stubs` factories |
103
- | `test/conversation-viewer.test.ts` | Add `createTestViewer` + `assertRenderFitsWidths` inline, migrate all tests |
104
- | `test/ui/agent-config-editor.test.ts` | Add `setupDetail` inline, migrate `showAgentDetail` tests |
105
-
106
- ### Unchanged files
107
-
108
- No production source files are modified.
109
- No other test files are modified.
110
-
111
- ## Test impact analysis
112
-
113
- 1. **New unit tests**: `manager-stubs.test.ts` adds smoke tests verifying factory return shapes (blocking runner never resolves, session runner calls `onSessionCreated`, worktree factory returns the expected interface, run result contains the correct fields).
114
- 2. **Simplified tests**: ~30 tests across the three files replace 3–6 lines of inline stub construction with 1-line factory calls.
115
- 3. **Unchanged tests**: All existing test assertions remain identical — only the setup code changes.
116
- Tests with custom runner behavior (event-emitting, gated, error-throwing) keep their inline stubs.
117
-
118
- ## TDD order
119
-
120
- 1. **Create `test/helpers/manager-stubs.ts` + `manager-stubs.test.ts`** Add `createBlockingRunner`, `createSessionRunner`, `createMockWorktrees`, `createRunResult`.
121
- Add smoke tests verifying each factory's return shape and basic behavior.
122
- Commit: `test: add manager-stubs helper factories (#219)`
123
-
124
- 2. **Migrate `agent-manager.test.ts` to use manager-stubs** Replace 5 inline never-resolving runners with `createBlockingRunner()`.
125
- Replace 4 identical worktree stubs with `createMockWorktrees()` / `createMockWorktrees({ create: ... })`.
126
- Replace inline session-creating runners with `createSessionRunner(session)` where the test only needs `onSessionCreated` wiring.
127
- Replace inline run-result objects with `createRunResult()` where the default shape suffices.
128
- Run `pnpm vitest run test/lifecycle/agent-manager.test.ts` to verify green.
129
- Commit: `test: migrate agent-manager tests to manager-stubs (#219)`
130
-
131
- 3. **Add inline factories to `conversation-viewer.test.ts` and migrate** Add `createTestViewer(overrides?)` inline factory with defaults for all 8 constructor fields.
132
- Add `assertRenderFitsWidths(messages, widths?, overrides?)` inline helper.
133
- Migrate all 10 "render width safety" tests to use `assertRenderFitsWidths`.
134
- Migrate all 5 "safety net" tests to use `createTestViewer`.
135
- Run `pnpm vitest run test/conversation-viewer.test.ts` to verify green.
136
- Commit: `test: reduce conversation-viewer test duplication (#219)`
137
-
138
- 4. **Add inline `setupDetail` to `agent-config-editor.test.ts` and migrate** Add `setupDetail(selectResults, options?)` returning `{ fileOps, editor, ui }`.
139
- Migrate `showAgentDetail` tests to use `setupDetail`.
140
- Run `pnpm vitest run test/ui/agent-config-editor.test.ts` to verify green.
141
- Commit: `test: reduce agent-config-editor test duplication (#219)`
142
-
143
- 5. **Final verification** Run `pnpm vitest run` (full suite) to confirm no regressions.
144
- Run `pnpm run check` to confirm no type errors.
145
- Commit is not needed — this is a verification-only step.
146
-
147
- ## Risks and mitigations
148
-
149
- 1. **Factory defaults diverge from test intent** — If a shared factory's defaults don't match what an individual test expects, assertions silently pass or fail for the wrong reason.
150
- Mitigation: diff all inline stubs against the proposed factory defaults before writing the factory.
151
- Keep tests with unique mock behavior inline rather than force-fitting them into a factory.
152
-
153
- 2. **Over-abstraction obscures test intent** — Extracting too many details into helpers makes tests harder to read.
154
- Mitigation: only extract truly duplicated boilerplate (stub construction); keep test-specific setup and assertions inline.
155
- The gated runner pattern stays inline for this reason.
156
-
157
- 3. **Intermediate broken state** — Partially migrated test files may have import conflicts.
158
- Mitigation: each TDD step fully migrates one file before committing.
159
-
160
- ## Open questions
161
-
162
- None — the issue scope is well-defined and the dependencies are resolved.
@@ -1,322 +0,0 @@
1
- ---
2
- issue: 227
3
- issue_title: "Evolve AgentRecord into Agent with behavior (Phase 15, Step 1)"
4
- ---
5
-
6
- # Evolve AgentRecord into Agent with behavior
7
-
8
- ## Problem Statement
9
-
10
- `AgentRecord` is an anemic domain model — it holds identity, status transitions, and stats but no behavior.
11
- `AgentManager` reaches into records 37 times, performing work that belongs on the agent:
12
-
13
- - **abort**: `AgentManager.abort()` checks `record.status`, calls `record.abortController?.abort()`, calls `record.markStopped()` — this is the agent aborting itself, but the logic lives on the manager.
14
- - **pending steers**: per-agent steer buffers live in a manager-level `Map<string, string[]>`, not on the agent.
15
- - **steer flushing**: `flushPendingSteers(id, session)` iterates the manager map — should be `agent.flushPendingSteers(session)`.
16
- - **worktree setup**: `setupWorktree()` creates a worktree and attaches it to the record — the agent should set up its own worktree.
17
-
18
- ## Goals
19
-
20
- - Move per-agent behavior (`abort`, `queueSteer`/`flushPendingSteers`, `setupWorktree`) from `AgentManager` to the agent.
21
- - `AgentManager` delegates to agents via Tell-Don't-Ask instead of reaching into records.
22
- - Rename `AgentRecord` → `Agent`, `AgentRecordStatus` → `AgentStatus`, `AgentRecordInit` → `AgentInit` across the codebase.
23
- - All changes are internal — the public `SubagentsService` API (`service.ts`) is unaffected.
24
-
25
- ## Non-Goals
26
-
27
- - **`RunHandle` ownership** — moves to `Agent` in #228, not here.
28
- - **Async `startAgent`** — deferred to #228.
29
- - **`onSessionCreated` observer** — deferred to #229.
30
- - **`ConcurrencyQueue` extraction** — deferred to #230.
31
- Queue removal logic stays on `AgentManager.abort()` until then.
32
- - **Relay deps** — deferred to #231.
33
- - **Resume unification** — deferred to #232.
34
-
35
- ## Background
36
-
37
- ### Relevant modules
38
-
39
- | Module | Responsibility | Relationship to this change |
40
- | ------------------------------------------ | ------------------------------------------------------- | ---------------------------------------------------------------------------------- |
41
- | `src/lifecycle/agent-record.ts` (201 LOC) | Status state machine, stats accumulation | Gains behavior methods, renames to `agent.ts` |
42
- | `src/lifecycle/agent-manager.ts` (541 LOC) | Agent collection, spawn, abort, queue, steer buffering | Loses private methods, delegates to agent |
43
- | `src/lifecycle/worktree.ts` | `WorktreeManager` interface and git worktree operations | Agent calls `worktrees.create()` directly |
44
- | `src/lifecycle/worktree-state.ts` | Per-agent worktree lifecycle state | Already attached to agent — `setupWorktree` formalizes this |
45
- | `src/tools/steer-tool.ts` | LLM-facing steer tool | Calls `record.queueSteer()` directly instead of `manager.queueSteer()` |
46
- | `src/service/service-adapter.ts` | Cross-extension API adapter | Calls `record.queueSteer()` directly; `queueSteer` removed from `AgentManagerLike` |
47
- | `src/observation/record-observer.ts` | Session event → agent stats accumulation | Import rename only |
48
- | `src/types.ts` | Internal re-exports | Re-export updates |
49
- | `test/helpers/make-record.ts` | Shared test factory | Renames to `make-agent.ts`, factory → `createTestAgent()` |
50
-
51
- ### Constraints
52
-
53
- - The public export from `package.json` is `"./src/service.ts"` only — `AgentRecord` is internal, so the rename is not breaking for consumers.
54
- - `WorktreeManager` is injected via the manager's constructor — `Agent.setupWorktree()` receives it as a parameter (no new constructor dependency).
55
- - Queue removal in `abort()` stays on `AgentManager` because the queue is manager-owned until #230 extracts `ConcurrencyQueue`.
56
-
57
- ## Design Overview
58
-
59
- ### New methods on Agent
60
-
61
- ```typescript
62
- class Agent {
63
- // Existing: markRunning, markCompleted, markAborted, markSteered, markError, markStopped,
64
- // incrementToolUses, addUsage, incrementCompactions, resetForResume
65
-
66
- // --- New behavior ---
67
-
68
- /** Buffer a steer message for delivery once the session is ready. */
69
- queueSteer(message: string): void;
70
-
71
- /** Flush buffered steers to the session and clear the buffer. */
72
- flushPendingSteers(session: AgentSession): void;
73
-
74
- /** Abort a running agent: fire AbortController, transition to stopped. */
75
- abort(): boolean;
76
-
77
- /** Create a worktree for isolated execution. Throws if impossible. */
78
- setupWorktree(worktrees: WorktreeManager, isolation: IsolationMode | undefined): string | undefined;
79
- }
80
- ```
81
-
82
- ### Steer buffering moves to agent
83
-
84
- Before: `AgentManager` owns `pendingSteers: Map<string, string[]>` and exposes `queueSteer(id, msg)`.
85
- After: each `Agent` owns `private pendingSteers: string[] = []`.
86
- Callers that already hold a record reference (steer tool, service adapter) call `agent.queueSteer(msg)` directly — the manager's `queueSteer` method and the `pendingSteers` map are removed.
87
-
88
- Consumer call-site (steer tool):
89
-
90
- ```typescript
91
- // Before:
92
- this.manager.queueSteer(record.id, params.message);
93
- // After:
94
- record.queueSteer(params.message);
95
- ```
96
-
97
- ### Abort moves to agent
98
-
99
- `Agent.abort()` encapsulates the running-check + controller.abort + markStopped sequence:
100
-
101
- ```typescript
102
- abort(): boolean {
103
- if (this._status !== "running") return false;
104
- this.abortController?.abort();
105
- this.markStopped();
106
- return true;
107
- }
108
- ```
109
-
110
- `AgentManager.abort(id)` retains queue-removal logic (queue is manager-owned until #230) and delegates the running case to `agent.abort()`.
111
- `AgentManager.abortAll()` calls `agent.abort()` for running agents.
112
-
113
- ### Worktree setup moves to agent
114
-
115
- `Agent.setupWorktree(worktrees, isolation)` replaces `AgentManager.setupWorktree(id, record, isolation)`.
116
- The agent creates the worktree, sets `this.worktreeState`, and returns the worktree path.
117
- The error message for impossible worktree creation stays identical.
118
-
119
- ### Rename strategy
120
-
121
- The rename (`AgentRecord` → `Agent`) is the final step — a purely mechanical search-and-replace with no behavior change.
122
- This keeps behavior-adding commits small and reviewable, then consolidates the rename noise into one commit.
123
-
124
- Files affected by the rename:
125
-
126
- | Layer | Files |
127
- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
128
- | Source (lifecycle) | `agent-record.ts` → `agent.ts`, `agent-manager.ts`, `execution-state.ts` |
129
- | Source (observation) | `record-observer.ts`, `notification.ts` |
130
- | Source (tools) | `agent-tool.ts`, `steer-tool.ts`, `get-result-tool.ts`, `background-spawner.ts`, `foreground-runner.ts` |
131
- | Source (UI) | `agent-menu.ts`, `agent-creation-wizard.ts`, `conversation-viewer.ts` |
132
- | Source (service) | `service-adapter.ts` |
133
- | Source (types) | `types.ts` |
134
- | Tests | `agent-record.test.ts` → `agent.test.ts`, `agent-manager.test.ts`, `record-observer.test.ts`, `steer-tool.test.ts`, `get-result-tool.test.ts`, `service-adapter.test.ts` |
135
- | Test helpers | `make-record.ts` → `make-agent.ts` |
136
-
137
- ## Module-Level Changes
138
-
139
- ### `src/lifecycle/agent-record.ts` → `src/lifecycle/agent.ts`
140
-
141
- 1. Add `private pendingSteers: string[] = []` field.
142
- 2. Add `queueSteer(message: string): void` — pushes to `pendingSteers`.
143
- 3. Add `flushPendingSteers(session: AgentSession): void` — iterates buffer, calls `session.steer()`, clears array.
144
- 4. Add `abort(): boolean` — if running, fires controller and marks stopped.
145
- 5. Add `setupWorktree(worktrees: WorktreeManager, isolation: IsolationMode | undefined): string | undefined` — creates worktree, sets `worktreeState`, returns path.
146
- 6. Add import for `WorktreeState`, `WorktreeManager`, `IsolationMode`.
147
- 7. Rename class `AgentRecord` → `Agent`, type `AgentRecordStatus` → `AgentStatus`, interface `AgentRecordInit` → `AgentInit`.
148
-
149
- ### `src/lifecycle/agent-manager.ts`
150
-
151
- 1. Remove `private pendingSteers = new Map<string, string[]>()`.
152
- 2. Remove `queueSteer(id, message)` public method.
153
- 3. Remove `private flushPendingSteers(id, session)` method.
154
- 4. In `startAgent`'s `onSessionCreated` callback: replace `this.flushPendingSteers(id, session)` with `record.flushPendingSteers(session)`.
155
- 5. Remove `private setupWorktree(id, record, isolation)` method.
156
- 6. In `startAgent`: replace `this.setupWorktree(id, record, options.isolation)` with `record.setupWorktree(this.worktrees, options.isolation)`.
157
- 7. Simplify `abort(id)`: delegate running case to `record.abort()`.
158
- 8. Simplify `abortAll()`: call `record.abort()` for running agents.
159
- 9. In `removeRecord`: remove `this.pendingSteers.delete(id)`.
160
- 10. Update imports: `AgentRecord` → `Agent`, `AgentRecordInit` → `AgentInit` (if used).
161
-
162
- ### `src/tools/steer-tool.ts`
163
-
164
- 1. Remove `queueSteer` from `SteerToolManager` interface.
165
- 2. Replace `this.manager.queueSteer(record.id, params.message)` with `record.queueSteer(params.message)`.
166
- 3. Update import: `AgentRecord` → `Agent`.
167
-
168
- ### `src/service/service-adapter.ts`
169
-
170
- 1. Remove `queueSteer` from `AgentManagerLike` interface.
171
- 2. In `steer()`: replace `this.manager.queueSteer(id, message)` with `record.queueSteer(message)` and return `true`.
172
- 3. Update import: `AgentRecord` → `Agent`.
173
-
174
- ### `src/types.ts`
175
-
176
- 1. Update re-export: `AgentRecord` → `Agent`, source path `#src/lifecycle/agent-record` → `#src/lifecycle/agent`.
177
-
178
- ### `src/observation/record-observer.ts`
179
-
180
- 1. Update import and parameter types: `AgentRecord` → `Agent`.
181
-
182
- ### `src/observation/notification.ts`
183
-
184
- 1. Update import and parameter types: `AgentRecord` → `Agent`.
185
-
186
- ### `src/tools/*.ts` (agent-tool, get-result-tool, background-spawner, foreground-runner)
187
-
188
- 1. Update imports and type annotations: `AgentRecord` → `Agent`.
189
-
190
- ### `src/ui/*.ts` (agent-menu, agent-creation-wizard, conversation-viewer)
191
-
192
- 1. Update imports and type annotations: `AgentRecord` → `Agent`.
193
-
194
- ### `test/helpers/make-record.ts` → `test/helpers/make-agent.ts`
195
-
196
- 1. Rename file.
197
- 2. Update imports: `AgentRecord` → `Agent`, `AgentRecordInit` → `AgentInit`.
198
- 3. Rename factory: `createTestRecord` → `createTestAgent`.
199
- 4. Update return type annotation.
200
-
201
- ### `test/lifecycle/agent-record.test.ts` → `test/lifecycle/agent.test.ts`
202
-
203
- 1. Rename file.
204
- 2. Update import: `AgentRecord` → `Agent`.
205
- 3. Update all `describe` block names and `new AgentRecord(...)` calls.
206
- 4. Add new test blocks for `queueSteer`, `flushPendingSteers`, `abort`, `setupWorktree`.
207
-
208
- ### `test/lifecycle/agent-manager.test.ts`
209
-
210
- 1. Remove tests for `AgentManager.queueSteer` (behavior moved to agent).
211
- 2. Update `abort()` tests to verify delegation.
212
- 3. Update imports if `AgentRecord` type is referenced.
213
-
214
- ### `test/tools/steer-tool.test.ts`
215
-
216
- 1. Remove `queueSteer` from mock manager.
217
- 2. Update "session not ready" test to verify `record.queueSteer()` is called.
218
-
219
- ### `test/service/service-adapter.test.ts`
220
-
221
- 1. Remove `queueSteer` from mock managers.
222
- 2. Update steer tests to verify `record.queueSteer()`.
223
-
224
- ### `packages/pi-subagents/docs/architecture/architecture.md`
225
-
226
- 1. Update file listing: `agent-record.ts` → `agent.ts`.
227
- 2. Update `AgentRecordInit` reference in interface width table.
228
-
229
- ## Test Impact Analysis
230
-
231
- ### New unit tests enabled by the extraction
232
-
233
- 1. **`Agent.queueSteer()` / `Agent.flushPendingSteers()`** — isolated tests for steer buffering without needing a full `AgentManager` setup.
234
- Previously the steer buffering was only testable via `AgentManager` integration tests.
235
- 2. **`Agent.abort()`** — isolated tests for the abort state machine (running → stopped, not-running → no-op) without needing manager scaffolding.
236
- 3. **`Agent.setupWorktree()`** — isolated tests for worktree creation and error handling with a mock `WorktreeManager`, without full spawn infrastructure.
237
-
238
- ### Existing tests that become redundant
239
-
240
- 1. `AgentManager — queueSteer` tests — the behavior is now tested directly on `Agent`.
241
- The manager no longer has a `queueSteer` method.
242
- 2. Parts of `AgentManager — abort` tests that verify controller.abort + markStopped — these are now `Agent.abort()` tests.
243
- The manager abort tests should focus on queue-removal logic and delegation.
244
-
245
- ### Existing tests that must stay
246
-
247
- 1. `AgentManager — abort` tests for the "queued" case (queue removal is still manager-owned).
248
- 2. `AgentManager — abortAll` tests (orchestrates both queue clearing and agent abort).
249
- 3. All `AgentManager — spawn/spawnAndWait` tests — the spawn flow still lives on the manager.
250
- 4. `steer-tool` and `service-adapter` tests for the steer path — updated to verify the new call pattern.
251
-
252
- ## TDD Order
253
-
254
- 1. **Red/Green: add `queueSteer()` and `flushPendingSteers()` to `AgentRecord`**
255
- - Add tests in `agent-record.test.ts` for buffering and flushing steers.
256
- - Implement the methods on `AgentRecord`.
257
- - Commit: `feat(pi-subagents): add steer buffering to AgentRecord`
258
-
259
- 2. **Refactor: delegate steer buffering from manager to agent**
260
- - Remove `pendingSteers` map, `queueSteer()`, `flushPendingSteers()` from `AgentManager`.
261
- - In `startAgent`'s `onSessionCreated`: call `record.flushPendingSteers(session)`.
262
- - In `removeRecord`: remove `pendingSteers.delete(id)`.
263
- - Update `steer-tool.ts`: remove `queueSteer` from `SteerToolManager`, call `record.queueSteer()`.
264
- - Update `service-adapter.ts`: remove `queueSteer` from `AgentManagerLike`, call `record.queueSteer()`.
265
- - Remove `AgentManager — queueSteer` tests; update steer-tool and service-adapter tests.
266
- - Run `pnpm run check` to verify no type errors.
267
- - Commit: `refactor(pi-subagents): delegate steer buffering from manager to agent`
268
-
269
- 3. **Red/Green: add `abort()` to `AgentRecord`**
270
- - Add tests in `agent-record.test.ts`: running → aborts and returns true; non-running → returns false; no controller → still marks stopped.
271
- - Implement the method.
272
- - Commit: `feat(pi-subagents): add abort() to AgentRecord`
273
-
274
- 4. **Refactor: delegate abort from manager to agent**
275
- - Simplify `AgentManager.abort()`: queued case stays, running case delegates to `record.abort()`.
276
- - Simplify `AgentManager.abortAll()`: call `record.abort()` for running agents.
277
- - Update manager abort tests to focus on queue removal and delegation.
278
- - Commit: `refactor(pi-subagents): delegate abort from manager to agent`
279
-
280
- 5. **Red/Green: add `setupWorktree()` to `AgentRecord`**
281
- - Add tests in `agent-record.test.ts`: non-worktree returns undefined; worktree created → sets `worktreeState` and returns path; creation fails → throws.
282
- - Implement the method (import `WorktreeState`, `WorktreeManager`, `IsolationMode`).
283
- - Commit: `feat(pi-subagents): add setupWorktree() to AgentRecord`
284
-
285
- 6. **Refactor: delegate worktree setup from manager to agent**
286
- - Remove `private setupWorktree()` from `AgentManager`.
287
- - In `startAgent`: replace `this.setupWorktree(id, record, options.isolation)` with `record.setupWorktree(this.worktrees, options.isolation)`.
288
- - Update any tests that verify worktree setup delegation.
289
- - Commit: `refactor(pi-subagents): delegate worktree setup from manager to agent`
290
-
291
- 7. **Rename `AgentRecord` → `Agent` across codebase**
292
- - Rename `src/lifecycle/agent-record.ts` → `src/lifecycle/agent.ts`.
293
- - Rename class `AgentRecord` → `Agent`, type `AgentRecordStatus` → `AgentStatus`, interface `AgentRecordInit` → `AgentInit`.
294
- - Update all source imports and type references (~20 source files).
295
- - Rename `test/lifecycle/agent-record.test.ts` → `test/lifecycle/agent.test.ts`.
296
- - Rename `test/helpers/make-record.ts` → `test/helpers/make-agent.ts`, factory `createTestRecord` → `createTestAgent`.
297
- - Update all test imports and references (~10 test files).
298
- - Rename `subscribeRecordObserver` → `subscribeAgentObserver` and `RecordObserverOptions` → `AgentObserverOptions` in `record-observer.ts`.
299
- - Run `pnpm run check` and full test suite.
300
- - Commit: `refactor(pi-subagents): rename AgentRecord to Agent`
301
-
302
- 8. **Update architecture docs**
303
- - Update `docs/architecture/architecture.md` file listing: `agent-record.ts` → `agent.ts`.
304
- - Update `AgentRecordInit` → `AgentInit` in the interface width table.
305
- - Update the Phase 15 Step 1 entry to reflect completion.
306
- - Commit: `docs(pi-subagents): update architecture for Agent rename`
307
-
308
- ## Risks and Mitigations
309
-
310
- 1. **Large rename diff in step 7** — The rename touches ~30 files.
311
- Mitigated by making it a purely mechanical change (no behavior change) in a dedicated commit, so reviewers can verify it's a clean rename.
312
- 2. **Queue-removal leaks into agent** — `Agent.abort()` must NOT remove from the manager's queue (that's #230's concern).
313
- Mitigated by scoping `Agent.abort()` to only handle the running case; `AgentManager.abort()` retains queue removal.
314
- 3. **Interface changes cascade** — Removing `queueSteer` from `SteerToolManager` and `AgentManagerLike` requires updating test mocks.
315
- Mitigated by handling interface changes and test updates in the same step (step 2).
316
- 4. **Test factory rename ripple** — `createTestRecord` → `createTestAgent` touches many test files.
317
- Mitigated by including this in the rename step (step 7), which is already a mechanical change.
318
-
319
- ## Open Questions
320
-
321
- None — the issue's proposed change is unambiguous and scoped.
322
- `RunHandle` ownership and other Phase 15 steps are explicitly deferred to their own issues.