@gotgenes/pi-subagents 18.0.0 → 18.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (257) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +22 -31
  3. package/docs/architecture/architecture.md +157 -204
  4. package/docs/architecture/history/phase-19-implement-ui-decisions.md +282 -0
  5. package/package.json +5 -6
  6. package/src/lifecycle/subagent.ts +5 -9
  7. package/src/observation/notification.ts +23 -10
  8. package/src/observation/subagent-events-observer.ts +1 -3
  9. package/src/tools/get-result-report.ts +60 -0
  10. package/src/tools/get-result-tool.ts +25 -40
  11. package/src/types.ts +1 -1
  12. package/src/ui/session-navigator.ts +0 -2
  13. package/.prettierignore +0 -5
  14. package/AGENTS.md +0 -7
  15. package/docs/plans/0048-implement-subagents-api.md +0 -304
  16. package/docs/plans/0049-remove-group-join-output-file-rpc.md +0 -180
  17. package/docs/plans/0051-update-adr-0001-hard-fork.md +0 -77
  18. package/docs/plans/0052-remove-scheduled-subagents.md +0 -133
  19. package/docs/plans/0053-extract-model-resolution-from-execute.md +0 -181
  20. package/docs/plans/0054-decompose-index-into-modules.md +0 -302
  21. package/docs/plans/0057-structured-debug-logging.md +0 -154
  22. package/docs/plans/0061-session-format-transcript.md +0 -284
  23. package/docs/plans/0066-replace-as-any-with-sdk-types.md +0 -215
  24. package/docs/plans/0069-create-subagent-runtime.md +0 -345
  25. package/docs/plans/0070-extract-event-handlers.md +0 -306
  26. package/docs/plans/0071-extract-session-config-assembler.md +0 -362
  27. package/docs/plans/0072-inject-agent-manager-collaborators.md +0 -329
  28. package/docs/plans/0076-inject-cwd-into-agent-manager.md +0 -102
  29. package/docs/plans/0077-inject-project-agents-dir.md +0 -115
  30. package/docs/plans/0080-consolidate-agent-config-lookup.md +0 -247
  31. package/docs/plans/0084-extract-git-worktree-manager.md +0 -142
  32. package/docs/plans/0087-evolve-subagent-runtime-methods.md +0 -240
  33. package/docs/plans/0098-extract-agent-record-state-machine.md +0 -435
  34. package/docs/plans/0099-replace-ctx-with-parent-snapshot.md +0 -488
  35. package/docs/plans/0100-replace-callback-threading-with-session-subscription.md +0 -454
  36. package/docs/plans/0102-consolidate-test-record-factory.md +0 -176
  37. package/docs/plans/0108-extract-agent-type-registry.md +0 -322
  38. package/docs/plans/0109-extract-settings-manager.md +0 -276
  39. package/docs/plans/0110-agent-activity-tracker.md +0 -297
  40. package/docs/plans/0111-split-agent-record-lifecycle.md +0 -582
  41. package/docs/plans/0112-replace-agent-manager-callbacks.md +0 -241
  42. package/docs/plans/0113-disambiguate-spawn-options.md +0 -155
  43. package/docs/plans/0114-narrow-agent-tool-menu-deps.md +0 -279
  44. package/docs/plans/0115-decompose-agent-tool.md +0 -337
  45. package/docs/plans/0116-type-housekeeping.md +0 -351
  46. package/docs/plans/0118-settings-manager-apply-methods.md +0 -271
  47. package/docs/plans/0123-remove-vi-fn-cast-smell.md +0 -179
  48. package/docs/plans/0131-consolidate-shared-test-fixtures.md +0 -207
  49. package/docs/plans/0132-inject-io-into-session-config.md +0 -219
  50. package/docs/plans/0133-inject-sdk-boundary-into-agent-runner.md +0 -373
  51. package/docs/plans/0134-reduce-as-any-casts.md +0 -366
  52. package/docs/plans/0135-extract-display-helpers.md +0 -182
  53. package/docs/plans/0136-decompose-agent-menu.md +0 -300
  54. package/docs/plans/0144-consolidate-observation-model.md +0 -263
  55. package/docs/plans/0145-decompose-execute-push-ctx-to-boundary.md +0 -290
  56. package/docs/plans/0146-narrow-ui-context.md +0 -319
  57. package/docs/plans/0147-inject-wrap-text-into-conversation-viewer.md +0 -166
  58. package/docs/plans/0148-split-agent-widget-rendering.md +0 -255
  59. package/docs/plans/0152-add-prompt-snippet.md +0 -91
  60. package/docs/plans/0164-reorganize-into-domain-directories.md +0 -409
  61. package/docs/plans/0165-decompose-resolved-spawn-config.md +0 -157
  62. package/docs/plans/0166-extract-parent-session-info.md +0 -231
  63. package/docs/plans/0167-narrow-runner-io.md +0 -150
  64. package/docs/plans/0168-extract-tool-filter-config.md +0 -173
  65. package/docs/plans/0169-extract-run-context-from-run-options.md +0 -194
  66. package/docs/plans/0170-reduce-build-content-lines-complexity.md +0 -225
  67. package/docs/plans/0171-reduce-render-result-complexity.md +0 -200
  68. package/docs/plans/0172-extract-turn-formatting.md +0 -206
  69. package/docs/plans/0180-reorder-append-prompt-for-kv-cache.md +0 -100
  70. package/docs/plans/0185-remove-persistent-agent-memory.md +0 -161
  71. package/docs/plans/0188-replace-any-casts-with-sdk-types.md +0 -162
  72. package/docs/plans/0192-define-session-context-interface.md +0 -107
  73. package/docs/plans/0193-runtime-owns-context-queries.md +0 -245
  74. package/docs/plans/0194-align-tool-interfaces-for-structural-typing.md +0 -139
  75. package/docs/plans/0195-convert-tool-factories-to-classes.md +0 -264
  76. package/docs/plans/0196-convert-runner-menu-to-classes.md +0 -268
  77. package/docs/plans/0205-decompose-render-widget-lines.md +0 -140
  78. package/docs/plans/0206-decompose-show-agent-detail.md +0 -211
  79. package/docs/plans/0207-decompose-agent-widget-update.md +0 -242
  80. package/docs/plans/0208-extract-shared-test-fixtures.md +0 -298
  81. package/docs/plans/0214-convert-remaining-closure-factories-to-classes.md +0 -261
  82. package/docs/plans/0215-decompose-build-parent-context.md +0 -166
  83. package/docs/plans/0216-decompose-start-agent.md +0 -255
  84. package/docs/plans/0217-extract-overwrite-guard.md +0 -176
  85. package/docs/plans/0218-push-sdk-boundary-in-settings.md +0 -172
  86. package/docs/plans/0219-reduce-test-duplication-top-3-clone-families.md +0 -162
  87. package/docs/plans/0227-evolve-agent-record-into-agent.md +0 -322
  88. package/docs/plans/0228-async-start-agent-dissolve-run-handle.md +0 -288
  89. package/docs/plans/0229-agent-born-complete.md +0 -564
  90. package/docs/plans/0230-extract-concurrency-queue.md +0 -265
  91. package/docs/plans/0231-push-exec-registry-to-runner.md +0 -245
  92. package/docs/plans/0232-agent-resume-internal-observer-lifecycle.md +0 -180
  93. package/docs/plans/0237-remove-disallowed-tools.md +0 -180
  94. package/docs/plans/0238-remove-extensions-filtering.md +0 -191
  95. package/docs/plans/0239-collapse-filter-active-tools.md +0 -217
  96. package/docs/plans/0242-rename-agent-tool-to-subagent.md +0 -165
  97. package/docs/plans/0256-extract-worktree-isolation.md +0 -256
  98. package/docs/plans/0257-extract-child-session-factory.md +0 -285
  99. package/docs/plans/0262-add-workspace-provider-seam.md +0 -264
  100. package/docs/plans/0264-remove-extension-lifecycle-control.md +0 -277
  101. package/docs/plans/0265-born-complete-subagent-session.md +0 -333
  102. package/docs/plans/0270-type-consumable-public-surface.md +0 -204
  103. package/docs/plans/0272-export-workspace-collaborator-types.md +0 -147
  104. package/docs/plans/0277-encapsulate-agent-session.md +0 -304
  105. package/docs/plans/0280-rename-agent-to-subagent.md +0 -197
  106. package/docs/plans/0360-custom-agents-default-append.md +0 -132
  107. package/docs/plans/0373-extract-subagent-state.md +0 -250
  108. package/docs/plans/0374-encapsulate-subagent-start-notification.md +0 -268
  109. package/docs/plans/0375-extract-run-listener-workspace-bracket.md +0 -300
  110. package/docs/plans/0376-extract-manager-observer.md +0 -232
  111. package/docs/plans/0377-split-widget-delegation-from-runtime.md +0 -254
  112. package/docs/plans/0378-consolidate-lifecycle-test-fixtures.md +0 -243
  113. package/docs/plans/0379-consolidate-ui-tools-test-fixtures.md +0 -335
  114. package/docs/plans/0380-extract-layered-settings-loader.md +0 -223
  115. package/docs/plans/0381-replace-concurrency-queue-with-limiter.md +0 -267
  116. package/docs/plans/0400-include-parent-prompt-in-replace-mode.md +0 -199
  117. package/docs/plans/0403-abort-subagents-on-interrupt.md +0 -180
  118. package/docs/plans/0412-unify-session-mock-builders.md +0 -146
  119. package/docs/plans/0420-fold-run-metrics-live-activity-onto-record.md +0 -228
  120. package/docs/plans/0421-migrate-activity-readers-to-record-getters.md +0 -309
  121. package/docs/plans/0422-delete-activity-tracker-ui-observer.md +0 -204
  122. package/docs/plans/0423-widget-self-drive-from-lifecycle.md +0 -264
  123. package/docs/plans/0424-drop-widget-dep-from-subagent-tool.md +0 -166
  124. package/docs/plans/0425-reconcile-subagent-events-contract.md +0 -144
  125. package/docs/plans/0426-consolidate-residual-test-clone-families.md +0 -235
  126. package/docs/plans/0427-reconsider-ui-direction.md +0 -212
  127. package/docs/plans/0441-remove-agent-definition-management-subtree.md +0 -180
  128. package/docs/plans/0442-dissolve-agents-conversation-viewer.md +0 -195
  129. package/docs/plans/0444-shrink-widget-to-background-agents.md +0 -156
  130. package/docs/plans/0445-native-session-navigation.md +0 -365
  131. package/docs/plans/0446-spike-session-navigation-entry-criteria.md +0 -171
  132. package/docs/plans/0447-extract-subagents-settings-command.md +0 -220
  133. package/docs/plans/0448-block-disabled-agent-spawn.md +0 -207
  134. package/docs/plans/0462-navigation-renderer-tui-components.md +0 -338
  135. package/docs/plans/0463-file-snapshot-source-evicted-agents.md +0 -306
  136. package/docs/retro/0048-implement-subagents-api.md +0 -44
  137. package/docs/retro/0049-remove-group-join-output-file-rpc.md +0 -49
  138. package/docs/retro/0051-update-adr-0001-hard-fork.md +0 -39
  139. package/docs/retro/0053-extract-model-resolution-from-execute.md +0 -40
  140. package/docs/retro/0054-decompose-index-into-modules.md +0 -53
  141. package/docs/retro/0057-structured-debug-logging.md +0 -77
  142. package/docs/retro/0061-session-format-transcript.md +0 -41
  143. package/docs/retro/0066-replace-as-any-with-sdk-types.md +0 -44
  144. package/docs/retro/0069-create-subagent-runtime.md +0 -43
  145. package/docs/retro/0070-extract-event-handlers.md +0 -49
  146. package/docs/retro/0071-extract-session-config-assembler.md +0 -60
  147. package/docs/retro/0072-inject-agent-manager-collaborators.md +0 -46
  148. package/docs/retro/0076-inject-cwd-into-agent-manager.md +0 -35
  149. package/docs/retro/0077-inject-project-agents-dir.md +0 -33
  150. package/docs/retro/0080-consolidate-agent-config-lookup.md +0 -35
  151. package/docs/retro/0084-extract-git-worktree-manager.md +0 -37
  152. package/docs/retro/0087-evolve-subagent-runtime-methods.md +0 -42
  153. package/docs/retro/0098-extract-agent-record-state-machine.md +0 -46
  154. package/docs/retro/0099-replace-ctx-with-parent-snapshot.md +0 -37
  155. package/docs/retro/0100-replace-callback-threading-with-session-subscription.md +0 -36
  156. package/docs/retro/0102-consolidate-test-record-factory.md +0 -30
  157. package/docs/retro/0108-extract-agent-type-registry.md +0 -41
  158. package/docs/retro/0109-extract-settings-manager.md +0 -55
  159. package/docs/retro/0110-agent-activity-tracker.md +0 -44
  160. package/docs/retro/0111-split-agent-record-lifecycle.md +0 -61
  161. package/docs/retro/0112-replace-agent-manager-callbacks.md +0 -35
  162. package/docs/retro/0113-disambiguate-spawn-options.md +0 -29
  163. package/docs/retro/0114-narrow-agent-tool-menu-deps.md +0 -38
  164. package/docs/retro/0115-decompose-agent-tool.md +0 -51
  165. package/docs/retro/0116-type-housekeeping.md +0 -42
  166. package/docs/retro/0118-settings-manager-apply-methods.md +0 -40
  167. package/docs/retro/0123-remove-vi-fn-cast-smell.md +0 -49
  168. package/docs/retro/0131-consolidate-shared-test-fixtures.md +0 -46
  169. package/docs/retro/0132-inject-io-into-session-config.md +0 -33
  170. package/docs/retro/0133-inject-sdk-boundary-into-agent-runner.md +0 -45
  171. package/docs/retro/0134-reduce-as-any-casts.md +0 -56
  172. package/docs/retro/0135-extract-display-helpers.md +0 -38
  173. package/docs/retro/0136-decompose-agent-menu.md +0 -43
  174. package/docs/retro/0144-consolidate-observation-model.md +0 -39
  175. package/docs/retro/0145-decompose-execute-push-ctx-to-boundary.md +0 -56
  176. package/docs/retro/0146-narrow-ui-context.md +0 -70
  177. package/docs/retro/0147-inject-wrap-text-into-conversation-viewer.md +0 -90
  178. package/docs/retro/0148-split-agent-widget-rendering.md +0 -39
  179. package/docs/retro/0152-add-prompt-snippet.md +0 -34
  180. package/docs/retro/0164-reorganize-into-domain-directories.md +0 -82
  181. package/docs/retro/0165-decompose-resolved-spawn-config.md +0 -78
  182. package/docs/retro/0166-extract-parent-session-info.md +0 -66
  183. package/docs/retro/0167-narrow-runner-io.md +0 -63
  184. package/docs/retro/0168-extract-tool-filter-config.md +0 -76
  185. package/docs/retro/0169-extract-run-context-from-run-options.md +0 -68
  186. package/docs/retro/0170-reduce-build-content-lines-complexity.md +0 -72
  187. package/docs/retro/0171-reduce-render-result-complexity.md +0 -77
  188. package/docs/retro/0172-extract-turn-formatting.md +0 -80
  189. package/docs/retro/0180-reorder-append-prompt-for-kv-cache.md +0 -62
  190. package/docs/retro/0185-remove-persistent-agent-memory.md +0 -73
  191. package/docs/retro/0188-replace-any-casts-with-sdk-types.md +0 -69
  192. package/docs/retro/0192-define-session-context-interface.md +0 -59
  193. package/docs/retro/0193-runtime-owns-context-queries.md +0 -75
  194. package/docs/retro/0194-align-tool-interfaces-for-structural-typing.md +0 -62
  195. package/docs/retro/0195-convert-tool-factories-to-classes.md +0 -84
  196. package/docs/retro/0196-convert-runner-menu-to-classes.md +0 -73
  197. package/docs/retro/0205-decompose-render-widget-lines.md +0 -64
  198. package/docs/retro/0206-decompose-show-agent-detail.md +0 -67
  199. package/docs/retro/0207-decompose-agent-widget-update.md +0 -92
  200. package/docs/retro/0208-extract-shared-test-fixtures.md +0 -102
  201. package/docs/retro/0214-convert-remaining-closure-factories-to-classes.md +0 -66
  202. package/docs/retro/0215-decompose-build-parent-context.md +0 -61
  203. package/docs/retro/0216-decompose-start-agent.md +0 -80
  204. package/docs/retro/0217-extract-overwrite-guard.md +0 -63
  205. package/docs/retro/0218-push-sdk-boundary-in-settings.md +0 -72
  206. package/docs/retro/0219-reduce-test-duplication-top-3-clone-families.md +0 -64
  207. package/docs/retro/0227-evolve-agent-record-into-agent.md +0 -80
  208. package/docs/retro/0228-async-start-agent-dissolve-run-handle.md +0 -80
  209. package/docs/retro/0229-agent-born-complete.md +0 -89
  210. package/docs/retro/0230-extract-concurrency-queue.md +0 -38
  211. package/docs/retro/0231-push-exec-registry-to-runner.md +0 -71
  212. package/docs/retro/0232-agent-resume-internal-observer-lifecycle.md +0 -109
  213. package/docs/retro/0237-remove-disallowed-tools.md +0 -78
  214. package/docs/retro/0238-remove-extensions-filtering.md +0 -72
  215. package/docs/retro/0239-collapse-filter-active-tools.md +0 -70
  216. package/docs/retro/0242-rename-agent-tool-to-subagent.md +0 -82
  217. package/docs/retro/0256-extract-worktree-isolation.md +0 -89
  218. package/docs/retro/0257-extract-child-session-factory.md +0 -33
  219. package/docs/retro/0262-add-workspace-provider-seam.md +0 -89
  220. package/docs/retro/0264-remove-extension-lifecycle-control.md +0 -91
  221. package/docs/retro/0265-born-complete-subagent-session.md +0 -97
  222. package/docs/retro/0270-type-consumable-public-surface.md +0 -108
  223. package/docs/retro/0272-export-workspace-collaborator-types.md +0 -38
  224. package/docs/retro/0277-encapsulate-agent-session.md +0 -80
  225. package/docs/retro/0280-rename-agent-to-subagent.md +0 -96
  226. package/docs/retro/0360-custom-agents-default-append.md +0 -81
  227. package/docs/retro/0373-extract-subagent-state.md +0 -94
  228. package/docs/retro/0374-encapsulate-subagent-start-notification.md +0 -171
  229. package/docs/retro/0375-extract-run-listener-workspace-bracket.md +0 -104
  230. package/docs/retro/0376-extract-manager-observer.md +0 -81
  231. package/docs/retro/0377-split-widget-delegation-from-runtime.md +0 -105
  232. package/docs/retro/0378-consolidate-lifecycle-test-fixtures.md +0 -100
  233. package/docs/retro/0379-consolidate-ui-tools-test-fixtures.md +0 -52
  234. package/docs/retro/0380-extract-layered-settings-loader.md +0 -97
  235. package/docs/retro/0381-replace-concurrency-queue-with-limiter.md +0 -95
  236. package/docs/retro/0400-include-parent-prompt-in-replace-mode.md +0 -84
  237. package/docs/retro/0403-abort-subagents-on-interrupt.md +0 -90
  238. package/docs/retro/0412-unify-session-mock-builders.md +0 -80
  239. package/docs/retro/0420-fold-run-metrics-live-activity-onto-record.md +0 -90
  240. package/docs/retro/0421-migrate-activity-readers-to-record-getters.md +0 -105
  241. package/docs/retro/0422-delete-activity-tracker-ui-observer.md +0 -97
  242. package/docs/retro/0423-widget-self-drive-from-lifecycle.md +0 -112
  243. package/docs/retro/0424-drop-widget-dep-from-subagent-tool.md +0 -89
  244. package/docs/retro/0425-reconcile-subagent-events-contract.md +0 -101
  245. package/docs/retro/0426-consolidate-residual-test-clone-families.md +0 -100
  246. package/docs/retro/0427-reconsider-ui-direction.md +0 -102
  247. package/docs/retro/0441-remove-agent-definition-management-subtree.md +0 -45
  248. package/docs/retro/0442-dissolve-agents-conversation-viewer.md +0 -108
  249. package/docs/retro/0444-shrink-widget-to-background-agents.md +0 -81
  250. package/docs/retro/0445-native-session-navigation.md +0 -122
  251. package/docs/retro/0446-spike-session-navigation-entry-criteria.md +0 -99
  252. package/docs/retro/0447-extract-subagents-settings-command.md +0 -91
  253. package/docs/retro/0448-block-disabled-agent-spawn.md +0 -75
  254. package/docs/retro/0462-navigation-renderer-tui-components.md +0 -105
  255. package/docs/retro/0463-file-snapshot-source-evicted-agents.md +0 -103
  256. package/src/observation/notification-state.ts +0 -27
  257. package/vitest.config.ts +0 -14
@@ -1,107 +0,0 @@
1
- ---
2
- issue: 192
3
- issue_title: "Define SessionContext narrow interface"
4
- ---
5
-
6
- # Define `SessionContext` narrow interface
7
-
8
- ## Problem Statement
9
-
10
- `SubagentRuntime.currentCtx` is typed `{ pi: unknown; ctx: unknown }`.
11
- Every consumer must cast through `as any` to read fields from the SDK context.
12
- This forces context queries (`buildSnapshot`, `getModelInfo`, `getSessionInfo`) to live as closures in `index.ts` with repeated `as any` casts, rather than as typed methods on the state holder.
13
-
14
- The SDK exports `ExtensionContext` — the `unknown` typing is a historical choice, not a constraint.
15
-
16
- ## Goals
17
-
18
- - Define a narrow `SessionContext` interface in `src/types.ts` capturing the 5 fields `SubagentRuntime` actually reads.
19
- - Pure additive — no consumers change in this step.
20
- - Provide the typed foundation for Layer 1 (#193) and subsequent closure-to-class conversion issues.
21
-
22
- ## Non-Goals
23
-
24
- - Changing `SubagentRuntime.currentCtx` type (that's #193).
25
- - Converting closure factories to classes (#195, #196).
26
- - Removing any `as any` casts from `index.ts` (that's #193).
27
-
28
- ## Background
29
-
30
- Phase 11, Layer 0 in `docs/architecture/architecture.md`.
31
- This is the first step in a 5-issue sequence (issues #192–#196) that converts closure factories to classes, eliminating 44 adapter closures in `index.ts`.
32
-
33
- The SDK's `ExtensionContext` interface (in `@earendil-works/pi-coding-agent`) is broad — it exposes `ui`, `abort()`, `shutdown()`, `compact()`, etc.
34
- ISP (Interface Segregation Principle) from `code-design` mandates a narrow interface capturing only what `SubagentRuntime` needs.
35
-
36
- The 5 fields consumed by runtime (traced from `index.ts` lines 214–223 and `lifecycle/parent-snapshot.ts`):
37
-
38
- 1. `cwd` — working directory for agent sessions.
39
- 2. `model` — parent model instance for fallback resolution.
40
- 3. `modelRegistry` — resolving config model strings.
41
- 4. `getSystemPrompt()` — system prompt for append-mode agents.
42
- 5. `sessionManager.getSessionFile()` / `.getSessionId()` / `.getBranch()` — session identification and context inheritance.
43
-
44
- The local `ModelRegistry` interface (in `src/session/model-resolver.ts`) already exists as a narrow ISP interface.
45
- `SessionContext` will reference it rather than redeclaring model-registry methods inline.
46
-
47
- ## Design Overview
48
-
49
- ```typescript
50
- import type { ModelRegistry } from "#src/session/model-resolver";
51
-
52
- /**
53
- * Narrow interface capturing the 5 ExtensionContext fields SubagentRuntime needs.
54
- * Avoids coupling runtime to the full SDK ExtensionContext surface.
55
- */
56
- export interface SessionContext {
57
- readonly cwd: string;
58
- readonly model: unknown;
59
- readonly modelRegistry: ModelRegistry | undefined;
60
- getSystemPrompt(): string;
61
- readonly sessionManager: {
62
- getSessionFile(): string | undefined;
63
- getSessionId(): string;
64
- getBranch(): unknown[];
65
- };
66
- }
67
- ```
68
-
69
- Design decisions:
70
-
71
- 1. `model` stays `unknown` — the runtime only passes it through to `resolveModel`; narrowing it gains nothing and would couple to `@earendil-works/pi-ai`'s `Model<Api>` generic.
72
- 2. `modelRegistry` is `ModelRegistry | undefined` — the SDK type says `ModelRegistry` (non-optional), but `SubagentRuntime.currentCtx` can be undefined, and the architecture doc specifies this signature.
73
- The `| undefined` reflects reality at the cast boundary (pre-bind, the registry may not exist).
74
- 3. `sessionManager` uses an inline structural type rather than importing `ReadonlySessionManager` — we only need 3 of its 13 methods; a separate named type would be over-engineering for a nested structural slice.
75
- 4. `getBranch()` returns `unknown[]` — the runtime passes entries through to `buildParentContext()` which already type-narrows internally.
76
-
77
- ## Module-Level Changes
78
-
79
- | File | Change |
80
- | -------------- | -------------------------------------------------------------------------------------------------------------- |
81
- | `src/types.ts` | Add `SessionContext` interface export. Add `import type { ModelRegistry }` from `#src/session/model-resolver`. |
82
-
83
- No other files change — this is pure additive.
84
-
85
- ## Test Impact Analysis
86
-
87
- 1. No new unit tests are needed — `SessionContext` is a pure type definition with no runtime behavior.
88
- 2. No existing tests become redundant.
89
- 3. A compile-time check (`pnpm run check`) verifies the interface is well-formed and the import resolves.
90
-
91
- ## TDD Order
92
-
93
- 1. **Add `SessionContext` interface to `src/types.ts`** — add the interface with its import.
94
- Verify with `pnpm run check` (type-check passes).
95
- Commit: `feat(pi-subagents): define SessionContext narrow interface (#192)`
96
-
97
- ## Risks and Mitigations
98
-
99
- | Risk | Mitigation |
100
- | ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
101
- | Interface shape doesn't match real `ExtensionContext` at runtime | Traced all 5 fields against SDK `.d.ts` declarations; shapes align exactly. |
102
- | Circular import from `types.ts` → `session/model-resolver.ts` | `model-resolver.ts` does not import from `types.ts`; no cycle. |
103
- | Future SDK changes break the narrow interface | The cast boundary (Layer 1, #193) will be the single enforcement point — structural typing ensures compile-time detection. |
104
-
105
- ## Open Questions
106
-
107
- None — the issue's "Proposed change" section fully specifies the interface shape.
@@ -1,245 +0,0 @@
1
- ---
2
- issue: 193
3
- issue_title: "SubagentRuntime owns context queries"
4
- ---
5
-
6
- # SubagentRuntime owns context queries
7
-
8
- ## Problem Statement
9
-
10
- Three closure queries in `index.ts` reach into `runtime.currentCtx?.ctx` with `as any` casts to extract model, modelRegistry, and sessionManager values.
11
- These closures exist because `SubagentRuntime` stores `unknown` and doesn't provide typed accessors.
12
- The queries belong on the state holder — `SubagentRuntime` owns `currentCtx`, so it should own the queries on that state.
13
-
14
- ## Goals
15
-
16
- - Type `SubagentRuntime.currentCtx` as `SessionContext | undefined` (eliminating the `{ pi: unknown; ctx: unknown }` shape).
17
- - Move the `as SessionContext` cast into `handleSessionStart` — the single SDK boundary.
18
- - Add typed methods on `SubagentRuntime`: `buildSnapshot()`, `getModelInfo()`, `getSessionInfo()`.
19
- - Remove 4 `as any` casts from `index.ts`.
20
- - Remove 3 closure queries from the composition root.
21
- - Update `service-adapter.ts` to delegate to `SubagentRuntime` instead of holding its own `as ExtensionContext` cast.
22
-
23
- ## Non-Goals
24
-
25
- - Converting closure factories to classes (Layer 3, #195/#196).
26
- - Aligning interface names so real objects satisfy tool deps (Layer 2, #194).
27
- - Changing `buildParentContext` in `session/context.ts` (it will continue to accept `ExtensionContext`; `SessionContext` is structurally compatible).
28
-
29
- ## Background
30
-
31
- Issue #192 (closed, shipped as v7.1.0) added the `SessionContext` interface to `src/types.ts`.
32
- This plan builds on that foundation.
33
-
34
- The architecture doc (Phase 11, Layer 1) specifies this exact change: "Change `currentCtx` from `{ pi: unknown; ctx: unknown }` to `SessionContext | undefined`."
35
-
36
- Key modules:
37
-
38
- - `src/runtime.ts` — `SubagentRuntime` class with `currentCtx`, `setSessionContext()`, `clearSessionContext()`
39
- - `src/handlers/lifecycle.ts` — `SessionLifecycleHandler.handleSessionStart()` receives raw SDK `ctx`
40
- - `src/index.ts` — composition root with inline `buildSnapshot`, `getModelInfo`, `getSessionInfo` closures
41
- - `src/service/service-adapter.ts` — `createSubagentsService()` with `getCtx()` and `getModelRegistry()` closures
42
- - `src/lifecycle/parent-snapshot.ts` — `buildParentSnapshot(ctx: ExtensionContext, inheritContext?)` function
43
- - `src/session/context.ts` — `buildParentContext(ctx: ExtensionContext)` function
44
-
45
- AGENTS.md constraint: keep modules focused and composable.
46
- The queries belong on the state owner per Law of Demeter (code-design skill).
47
-
48
- ## Design Overview
49
-
50
- ### Type change
51
-
52
- `SubagentRuntime.currentCtx` becomes `SessionContext | undefined` (previously `{ pi: unknown; ctx: unknown } | undefined`).
53
- The `pi` field is dropped from the stored context — it is only used in `SessionLifecycleHandler` which already stores it as a constructor param.
54
-
55
- ### Cast boundary
56
-
57
- `handleSessionStart` receives `ctx: unknown` from the SDK event.
58
- The single `as SessionContext` cast lives here:
59
-
60
- ```typescript
61
- handleSessionStart(_event: unknown, ctx: unknown): void {
62
- this.runtime.setSessionContext(ctx as SessionContext);
63
- this.manager.clearCompleted();
64
- }
65
- ```
66
-
67
- ### New methods on `SubagentRuntime`
68
-
69
- ```typescript
70
- import type { ParentSnapshot } from "#src/lifecycle/parent-snapshot";
71
- import type { ModelInfo } from "#src/tools/spawn-config";
72
- import type { SessionContext } from "#src/types";
73
-
74
- class SubagentRuntime {
75
- currentCtx: SessionContext | undefined = undefined;
76
-
77
- setSessionContext(ctx: SessionContext): void {
78
- this.currentCtx = ctx;
79
- }
80
-
81
- clearSessionContext(): void {
82
- this.currentCtx = undefined;
83
- }
84
-
85
- buildSnapshot(inheritContext: boolean): ParentSnapshot {
86
- return buildParentSnapshot(this.currentCtx!, inheritContext);
87
- }
88
-
89
- getModelInfo(): ModelInfo {
90
- return {
91
- parentModel: this.currentCtx?.model as ModelInfo["parentModel"],
92
- modelRegistry: this.currentCtx?.modelRegistry,
93
- };
94
- }
95
-
96
- getSessionInfo(): { parentSessionFile: string; parentSessionId: string } {
97
- return {
98
- parentSessionFile: this.currentCtx?.sessionManager?.getSessionFile() ?? "",
99
- parentSessionId: this.currentCtx?.sessionManager?.getSessionId() ?? "",
100
- };
101
- }
102
- }
103
- ```
104
-
105
- ### `buildParentSnapshot` signature change
106
-
107
- Change the parameter type from `ExtensionContext` to `SessionContext`:
108
-
109
- ```typescript
110
- export function buildParentSnapshot(
111
- ctx: SessionContext,
112
- inheritContext?: boolean,
113
- ): ParentSnapshot { ... }
114
- ```
115
-
116
- `ExtensionContext` structurally satisfies `SessionContext` (all 5 fields match), so existing callers (the `/agents` command handler) continue to work without change.
117
-
118
- Similarly, `buildParentContext` changes from `ExtensionContext` to `SessionContext`.
119
- The `sessionManager.getBranch()` returns `unknown[]` in `SessionContext`, which is what `buildParentContext` already treats the entries as (it accesses `.type`, `.message`, `.summary` via runtime checks without type narrowing).
120
-
121
- ### `service-adapter.ts` change
122
-
123
- The adapter currently receives `getCtx: () => { pi: unknown; ctx: unknown } | undefined`.
124
- After this change, it receives the runtime directly and calls `runtime.buildSnapshot()`:
125
-
126
- ```typescript
127
- export function createSubagentsService(
128
- manager: AgentManagerLike,
129
- resolveModel: (input: string, registry: ModelRegistry) => unknown,
130
- runtime: ServiceRuntimeLike,
131
- ): SubagentsService { ... }
132
- ```
133
-
134
- Where `ServiceRuntimeLike` is a narrow interface:
135
-
136
- ```typescript
137
- export interface ServiceRuntimeLike {
138
- readonly currentCtx: SessionContext | undefined;
139
- buildSnapshot(inheritContext: boolean): ParentSnapshot;
140
- getModelInfo(): { modelRegistry: unknown };
141
- }
142
- ```
143
-
144
- ### Impact on `LifecycleRuntime` interface
145
-
146
- The narrow interface in `handlers/lifecycle.ts` changes from:
147
-
148
- ```typescript
149
- interface LifecycleRuntime {
150
- setSessionContext(pi: unknown, ctx: unknown): void;
151
- clearSessionContext(): void;
152
- }
153
- ```
154
-
155
- to:
156
-
157
- ```typescript
158
- interface LifecycleRuntime {
159
- setSessionContext(ctx: SessionContext): void;
160
- clearSessionContext(): void;
161
- }
162
- ```
163
-
164
- ## Module-Level Changes
165
-
166
- 1. `src/runtime.ts` — Change `currentCtx` type, update `setSessionContext()` signature (drop `pi` param), add `buildSnapshot()`, `getModelInfo()`, `getSessionInfo()` methods.
167
- Add imports for `SessionContext`, `ParentSnapshot`, `ModelInfo`, `buildParentSnapshot`.
168
- 2. `src/handlers/lifecycle.ts` — Update `LifecycleRuntime` interface (single `ctx: SessionContext` param).
169
- Cast `ctx as SessionContext` in `handleSessionStart`.
170
- Remove `pi` from `setSessionContext` call.
171
- Import `SessionContext`.
172
- 3. `src/lifecycle/parent-snapshot.ts` — Change `buildParentSnapshot` param from `ExtensionContext` to `SessionContext`.
173
- Update import.
174
- 4. `src/session/context.ts` — Change `buildParentContext` param from `ExtensionContext` to `SessionContext`.
175
- Update import.
176
- 5. `src/service/service-adapter.ts` — Replace `getCtx`/`getModelRegistry` closures with a `ServiceRuntimeLike` interface.
177
- Use `runtime.buildSnapshot()` and `runtime.currentCtx?.modelRegistry`.
178
- Remove `ExtensionContext` import.
179
- 6. `src/index.ts` — Remove inline `buildSnapshot`, `getModelInfo`, `getSessionInfo` closures from `createAgentTool` deps.
180
- Pass `runtime.buildSnapshot.bind(runtime)`, `runtime.getModelInfo.bind(runtime)`, `runtime.getSessionInfo.bind(runtime)`.
181
- Update `createSubagentsService` call to pass `runtime` instead of two closures.
182
- Update `lifecycle.handleSessionStart` call (drop `pi` from `setSessionContext`).
183
- Remove `as any` eslint-disable for the eliminated casts.
184
- 7. `test/runtime.test.ts` — Update session-context method tests (single param).
185
- Add tests for `buildSnapshot()`, `getModelInfo()`, `getSessionInfo()`.
186
- 8. `test/handlers/lifecycle.test.ts` — Update `setSessionContext` mock expectations (single param).
187
- 9. `test/service/service-adapter.test.ts` — Update `createSubagentsService` calls to pass a runtime-like mock instead of two closures.
188
- 10. `test/helpers/stub-ctx.ts` (or equivalent) — Verify the stub ctx satisfies `SessionContext`.
189
-
190
- ## Test Impact Analysis
191
-
192
- 1. **New unit tests enabled:** `SubagentRuntime.buildSnapshot()`, `.getModelInfo()`, `.getSessionInfo()` — previously untestable as anonymous closures.
193
- 2. **Existing tests that simplify:** `service-adapter.test.ts` no longer needs to wire `getCtx`/`getModelRegistry` closures; a simple runtime stub replaces them.
194
- 3. **Tests that stay as-is:** `agent-tool.test.ts` (via `make-deps.ts`) — the tool deps interface still has `buildSnapshot`, `getModelInfo`, `getSessionInfo` fields; only the wiring in `index.ts` changes.
195
- The tool tests use mocks and are unaffected.
196
-
197
- ## TDD Order
198
-
199
- 1. **Red → Green:** Add `buildSnapshot()`, `getModelInfo()`, `getSessionInfo()` method tests to `runtime.test.ts`.
200
- Update `setSessionContext` tests to use single param.
201
- Tests fail because the methods don't exist yet.
202
- Commit: `test: add SubagentRuntime context-query method tests (#193)`
203
-
204
- 2. **Green:** Change `SubagentRuntime.currentCtx` type to `SessionContext | undefined`.
205
- Update `setSessionContext` to single param.
206
- Add three query methods.
207
- Update imports.
208
- Run `pnpm run check` to verify type coherence.
209
- Commit: `feat: SubagentRuntime stores typed SessionContext and owns context queries (#193)`
210
-
211
- 3. **Green:** Change `buildParentSnapshot` and `buildParentContext` to accept `SessionContext` instead of `ExtensionContext`.
212
- Update imports.
213
- Run `pnpm run check`.
214
- Commit: `refactor: narrow buildParentSnapshot param to SessionContext (#193)`
215
-
216
- 4. **Green:** Update `handlers/lifecycle.ts` — change `LifecycleRuntime` interface, cast `ctx as SessionContext` in handler.
217
- Update lifecycle test expectations.
218
- Commit: `refactor: move SessionContext cast to handleSessionStart boundary (#193)`
219
-
220
- 5. **Green:** Update `service-adapter.ts` — introduce `ServiceRuntimeLike`, replace closure params with runtime.
221
- Update service-adapter tests.
222
- Commit: `refactor: service-adapter delegates to SubagentRuntime for context (#193)`
223
-
224
- 6. **Green:** Update `index.ts` — wire `runtime.buildSnapshot.bind(runtime)` etc. into agent tool deps.
225
- Update `createSubagentsService` call.
226
- Remove `as any` casts and corresponding eslint-disable comment.
227
- Clean up unused imports.
228
- Commit: `refactor: index.ts delegates context queries to SubagentRuntime (#193)`
229
-
230
- 7. **Verify:** Run full test suite (`pnpm vitest run`) and type check (`pnpm run check`).
231
- Fix any remaining lint issues.
232
- Commit: `chore: cleanup lint after SubagentRuntime context migration (#193)` (if needed)
233
-
234
- ## Risks and Mitigations
235
-
236
- | Risk | Mitigation |
237
- | ----------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
238
- | `buildParentSnapshot` callers outside this package break when param changes from `ExtensionContext` to `SessionContext` | `ExtensionContext` structurally satisfies `SessionContext` — no source-level changes needed at call sites. The `/agents` command handler passes `ctx` which is still `ExtensionContext` from the SDK. |
239
- | `runtime.currentCtx` is `undefined` when `buildSnapshot()` is called | Same risk exists today — the closure reads `runtime.currentCtx?.ctx` which may be undefined. The `!` assertion documents the invariant: methods are only called during an active session. |
240
- | Dropping `pi` from `currentCtx` breaks something that reads it | Grep confirms `pi` is only stored and never read back from `currentCtx`. `SessionLifecycleHandler` already stores `pi` as its own constructor param. |
241
- | Test fixture `make-deps.ts` still mocks `buildSnapshot`/`getModelInfo`/`getSessionInfo` on `AgentToolDeps` | Correct — the tool interface doesn't change in this issue. The closures in `index.ts` are replaced with bound methods, but the deps shape stays the same. |
242
-
243
- ## Open Questions
244
-
245
- - None — the issue's proposed change and the architecture doc's Layer 1 spec are fully aligned.
@@ -1,139 +0,0 @@
1
- ---
2
- issue: 194
3
- issue_title: "Align tool interfaces for structural typing"
4
- ---
5
-
6
- # Align tool interfaces for structural typing
7
-
8
- ## Problem Statement
9
-
10
- The narrow interfaces that tool factories accept don't structurally match the real objects (`AgentManager`, `SubagentRuntime`, `SettingsManager`).
11
- This forces `index.ts` to build adapter closures bridging the gap — each a one-liner that exists only because names or ownership don't align.
12
- Three specific mismatches prevent structural typing from connecting real objects to tool interfaces directly.
13
-
14
- ## Goals
15
-
16
- - Remove `getMaxConcurrent()` from `AgentToolManager` — it belongs on the settings accessor.
17
- - Rename `SubagentRuntime.updateWidget()` → `update()` so `SubagentRuntime` structurally satisfies `AgentToolWidget`.
18
- - Remove the dead `getToolCallName` re-export from `ui/message-formatters.ts`.
19
- - After these changes, `AgentManager` structurally satisfies `AgentToolManager` and `SubagentRuntime` structurally satisfies `AgentToolWidget` — no adapter closures needed in `index.ts`.
20
-
21
- ## Non-Goals
22
-
23
- - Converting tool factories to classes (that's #195).
24
- - Simplifying `index.ts` wiring (that's #195/#196, after this layer).
25
- - Changing `NotificationManager`'s constructor parameter name (`updateWidget` callback) — it's a positional callback, not a structural interface member.
26
-
27
- ## Background
28
-
29
- This is Phase 11, Layer 2 in `docs/architecture/architecture.md`.
30
- Layer 0 (#192, done) and Layer 1 (#193, done) established the typed `SessionContext` and moved context queries onto `SubagentRuntime`.
31
- Layer 2 (this issue) aligns the remaining structural mismatches.
32
- Layer 3 (#195) depends on this layer.
33
-
34
- Relevant modules:
35
-
36
- - `src/tools/agent-tool.ts` — defines `AgentToolManager` and `AgentToolWidget` interfaces.
37
- - `src/tools/background-spawner.ts` — defines `BackgroundManagerDeps` with `getMaxConcurrent()`.
38
- - `src/runtime.ts` — defines `SubagentRuntime` class with `updateWidget()` delegation method.
39
- - `src/ui/message-formatters.ts` — has the dead `getToolCallName` re-export.
40
- - `src/index.ts` — composition root that builds adapter closures.
41
- - `src/settings.ts` — `SettingsManager` owns `maxConcurrent`.
42
-
43
- ## Design Overview
44
-
45
- ### 1. Move `getMaxConcurrent` off manager interfaces → settings
46
-
47
- The `BackgroundManagerDeps` and `AgentToolManager` interfaces both declare `getMaxConcurrent(): number`.
48
- In reality, the value comes from `SettingsManager.maxConcurrent`.
49
- The fix:
50
-
51
- - Remove `getMaxConcurrent` from `AgentToolManager`.
52
- - Remove `getMaxConcurrent` from `BackgroundManagerDeps`.
53
- - Widen `AgentToolDeps.settings` from `{ readonly defaultMaxTurns: number | undefined }` to also include `readonly maxConcurrent: number`.
54
- - Pass `settings` (or a narrow settings interface) to `spawnBackground` so it can read `maxConcurrent` directly.
55
- - `SettingsManager` already exposes a `get maxConcurrent(): number` property, so it structurally satisfies the widened interface.
56
-
57
- After this, `AgentManager` (which has `spawn`, `spawnAndWait`, `resume`, `getRecord` but NOT `getMaxConcurrent`) structurally satisfies `AgentToolManager`.
58
-
59
- ### 2. Rename `SubagentRuntime.updateWidget()` → `update()`
60
-
61
- The `AgentToolWidget` interface declares `update(): void`.
62
- `SubagentRuntime` has `updateWidget(): void` which delegates to `this.widget?.update()`.
63
- Renaming the delegation method to `update()` makes `SubagentRuntime` structurally satisfy `AgentToolWidget` (it already has `setUICtx`, `ensureTimer`, and `markFinished`).
64
-
65
- Callers of `runtime.updateWidget()`:
66
-
67
- - `src/index.ts` line 70: `() => runtime.updateWidget()` → `() => runtime.update()`
68
- - `src/index.ts` line 199: `update: () => runtime.updateWidget()` → can now pass `runtime` directly (but that's a #195 concern — for now just rename the call).
69
-
70
- The `WidgetLike` interface in `runtime.ts` already uses `update()` — no conflict.
71
-
72
- ### 3. Remove dead re-export
73
-
74
- `src/ui/message-formatters.ts` line 24 exports `getToolCallName` from `#src/session/content-items`.
75
- No consumer imports `getToolCallName` from `message-formatters` — all uses go directly to `content-items.ts`.
76
- Delete the re-export line.
77
-
78
- ### After all three changes
79
-
80
- ```typescript
81
- // AgentToolManager (after removing getMaxConcurrent):
82
- interface AgentToolManager {
83
- spawn(...): string;
84
- spawnAndWait(...): Promise<AgentRecord>;
85
- resume(...): Promise<AgentRecord | undefined>;
86
- getRecord(id: string): AgentRecord | undefined;
87
- }
88
- // AgentManager has all four methods → structural match ✓
89
-
90
- // AgentToolWidget (unchanged):
91
- interface AgentToolWidget {
92
- setUICtx(ctx: unknown): void;
93
- ensureTimer(): void;
94
- update(): void;
95
- markFinished(id: string): void;
96
- }
97
- // SubagentRuntime has all four methods (after rename) → structural match ✓
98
- ```
99
-
100
- ## Module-Level Changes
101
-
102
- | File | Change |
103
- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
104
- | `src/tools/agent-tool.ts` | Remove `getMaxConcurrent` from `AgentToolManager`. Widen `settings` type in `AgentToolDeps` to include `readonly maxConcurrent: number`. |
105
- | `src/tools/background-spawner.ts` | Remove `getMaxConcurrent` from `BackgroundManagerDeps`. Add a `settings: { readonly maxConcurrent: number }` parameter (or add to `BackgroundParams`). Read `settings.maxConcurrent` instead of `manager.getMaxConcurrent()`. |
106
- | `src/runtime.ts` | Rename `updateWidget()` → `update()`. |
107
- | `src/ui/message-formatters.ts` | Remove the `export { getToolCallName } from ...` line. |
108
- | `src/index.ts` | Update `runtime.updateWidget()` → `runtime.update()` at both call sites. Remove `getMaxConcurrent` from the `manager` adapter object passed to `createAgentTool`. Pass `settings` through to `spawnBackground` via the tool deps. |
109
- | `test/tools/background-spawner.test.ts` | Remove `getMaxConcurrent` from mock manager objects. Add `settings` mock with `maxConcurrent`. |
110
- | `test/runtime.test.ts` | Rename `updateWidget` → `update` in test descriptions and call sites. |
111
- | `docs/architecture/architecture.md` | Update Layer 2 status and health metrics (adapter closures count, dead exports count). |
112
-
113
- ## Test Impact Analysis
114
-
115
- 1. No new unit tests are strictly needed — this is interface alignment, not new behavior.
116
- 2. `test/tools/background-spawner.test.ts` needs mock shape updates (remove `getMaxConcurrent` from manager mock, add settings mock).
117
- 3. `test/runtime.test.ts` needs the method name updated from `updateWidget` to `update`.
118
- 4. Existing tests for `agent-tool`, `notification`, and `message-formatters` remain as-is (no behavior change).
119
-
120
- ## TDD Order
121
-
122
- 1. `refactor:` Rename `SubagentRuntime.updateWidget()` → `update()` — update `runtime.ts`, `test/runtime.test.ts`, and both call sites in `index.ts`.
123
- Run `pnpm run check` to verify no type errors remain.
124
- 2. `refactor:` Move `getMaxConcurrent` off manager interfaces — remove from `AgentToolManager` and `BackgroundManagerDeps`, widen `AgentToolDeps.settings`, add settings parameter to `spawnBackground`, update `index.ts` call site and `test/tools/background-spawner.test.ts`.
125
- Run `pnpm run check`.
126
- 3. `refactor:` Remove dead `getToolCallName` re-export from `ui/message-formatters.ts`.
127
- 4. `docs:` Update architecture doc — mark Layer 2 as done, update health metrics (dead exports: 0, adapter closures reduced).
128
-
129
- ## Risks and Mitigations
130
-
131
- | Risk | Mitigation |
132
- | ---------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
133
- | `update()` is a generic name on `SubagentRuntime` — could confuse readers about what's being updated | The method is a documented widget delegation like its siblings (`markFinished`, `ensureTimer`); the JSDoc comment clarifies it delegates to `widget.update()`. |
134
- | `background-spawner` signature change could break other callers | Grep confirms only `agent-tool.ts` calls `spawnBackground` — no other consumers. |
135
- | Renaming method in runtime could miss a call site | Grep and `pnpm run check` after each step catch all references. |
136
-
137
- ## Open Questions
138
-
139
- None — the issue's proposed direction is unambiguous and the architecture doc confirms the design.