@gotgenes/pi-subagents 18.0.1 → 18.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (260) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/docs/architecture/architecture.md +157 -204
  3. package/docs/architecture/history/phase-19-implement-ui-decisions.md +282 -0
  4. package/package.json +5 -6
  5. package/src/lifecycle/subagent.ts +5 -9
  6. package/src/observation/notification.ts +23 -10
  7. package/src/observation/subagent-events-observer.ts +1 -3
  8. package/src/tools/get-result-report.ts +60 -0
  9. package/src/tools/get-result-tool.ts +25 -40
  10. package/src/types.ts +1 -1
  11. package/src/ui/session-navigator.ts +0 -2
  12. package/.prettierignore +0 -5
  13. package/AGENTS.md +0 -7
  14. package/docs/plans/0048-implement-subagents-api.md +0 -304
  15. package/docs/plans/0049-remove-group-join-output-file-rpc.md +0 -180
  16. package/docs/plans/0051-update-adr-0001-hard-fork.md +0 -77
  17. package/docs/plans/0052-remove-scheduled-subagents.md +0 -133
  18. package/docs/plans/0053-extract-model-resolution-from-execute.md +0 -181
  19. package/docs/plans/0054-decompose-index-into-modules.md +0 -302
  20. package/docs/plans/0057-structured-debug-logging.md +0 -154
  21. package/docs/plans/0061-session-format-transcript.md +0 -284
  22. package/docs/plans/0066-replace-as-any-with-sdk-types.md +0 -215
  23. package/docs/plans/0069-create-subagent-runtime.md +0 -345
  24. package/docs/plans/0070-extract-event-handlers.md +0 -306
  25. package/docs/plans/0071-extract-session-config-assembler.md +0 -362
  26. package/docs/plans/0072-inject-agent-manager-collaborators.md +0 -329
  27. package/docs/plans/0076-inject-cwd-into-agent-manager.md +0 -102
  28. package/docs/plans/0077-inject-project-agents-dir.md +0 -115
  29. package/docs/plans/0080-consolidate-agent-config-lookup.md +0 -247
  30. package/docs/plans/0084-extract-git-worktree-manager.md +0 -142
  31. package/docs/plans/0087-evolve-subagent-runtime-methods.md +0 -240
  32. package/docs/plans/0098-extract-agent-record-state-machine.md +0 -435
  33. package/docs/plans/0099-replace-ctx-with-parent-snapshot.md +0 -488
  34. package/docs/plans/0100-replace-callback-threading-with-session-subscription.md +0 -454
  35. package/docs/plans/0102-consolidate-test-record-factory.md +0 -176
  36. package/docs/plans/0108-extract-agent-type-registry.md +0 -322
  37. package/docs/plans/0109-extract-settings-manager.md +0 -276
  38. package/docs/plans/0110-agent-activity-tracker.md +0 -297
  39. package/docs/plans/0111-split-agent-record-lifecycle.md +0 -582
  40. package/docs/plans/0112-replace-agent-manager-callbacks.md +0 -241
  41. package/docs/plans/0113-disambiguate-spawn-options.md +0 -155
  42. package/docs/plans/0114-narrow-agent-tool-menu-deps.md +0 -279
  43. package/docs/plans/0115-decompose-agent-tool.md +0 -337
  44. package/docs/plans/0116-type-housekeeping.md +0 -351
  45. package/docs/plans/0118-settings-manager-apply-methods.md +0 -271
  46. package/docs/plans/0123-remove-vi-fn-cast-smell.md +0 -179
  47. package/docs/plans/0131-consolidate-shared-test-fixtures.md +0 -207
  48. package/docs/plans/0132-inject-io-into-session-config.md +0 -219
  49. package/docs/plans/0133-inject-sdk-boundary-into-agent-runner.md +0 -373
  50. package/docs/plans/0134-reduce-as-any-casts.md +0 -366
  51. package/docs/plans/0135-extract-display-helpers.md +0 -182
  52. package/docs/plans/0136-decompose-agent-menu.md +0 -300
  53. package/docs/plans/0144-consolidate-observation-model.md +0 -263
  54. package/docs/plans/0145-decompose-execute-push-ctx-to-boundary.md +0 -290
  55. package/docs/plans/0146-narrow-ui-context.md +0 -319
  56. package/docs/plans/0147-inject-wrap-text-into-conversation-viewer.md +0 -166
  57. package/docs/plans/0148-split-agent-widget-rendering.md +0 -255
  58. package/docs/plans/0152-add-prompt-snippet.md +0 -91
  59. package/docs/plans/0164-reorganize-into-domain-directories.md +0 -409
  60. package/docs/plans/0165-decompose-resolved-spawn-config.md +0 -157
  61. package/docs/plans/0166-extract-parent-session-info.md +0 -231
  62. package/docs/plans/0167-narrow-runner-io.md +0 -150
  63. package/docs/plans/0168-extract-tool-filter-config.md +0 -173
  64. package/docs/plans/0169-extract-run-context-from-run-options.md +0 -194
  65. package/docs/plans/0170-reduce-build-content-lines-complexity.md +0 -225
  66. package/docs/plans/0171-reduce-render-result-complexity.md +0 -200
  67. package/docs/plans/0172-extract-turn-formatting.md +0 -206
  68. package/docs/plans/0180-reorder-append-prompt-for-kv-cache.md +0 -100
  69. package/docs/plans/0185-remove-persistent-agent-memory.md +0 -161
  70. package/docs/plans/0188-replace-any-casts-with-sdk-types.md +0 -162
  71. package/docs/plans/0192-define-session-context-interface.md +0 -107
  72. package/docs/plans/0193-runtime-owns-context-queries.md +0 -245
  73. package/docs/plans/0194-align-tool-interfaces-for-structural-typing.md +0 -139
  74. package/docs/plans/0195-convert-tool-factories-to-classes.md +0 -264
  75. package/docs/plans/0196-convert-runner-menu-to-classes.md +0 -268
  76. package/docs/plans/0205-decompose-render-widget-lines.md +0 -140
  77. package/docs/plans/0206-decompose-show-agent-detail.md +0 -211
  78. package/docs/plans/0207-decompose-agent-widget-update.md +0 -242
  79. package/docs/plans/0208-extract-shared-test-fixtures.md +0 -298
  80. package/docs/plans/0214-convert-remaining-closure-factories-to-classes.md +0 -261
  81. package/docs/plans/0215-decompose-build-parent-context.md +0 -166
  82. package/docs/plans/0216-decompose-start-agent.md +0 -255
  83. package/docs/plans/0217-extract-overwrite-guard.md +0 -176
  84. package/docs/plans/0218-push-sdk-boundary-in-settings.md +0 -172
  85. package/docs/plans/0219-reduce-test-duplication-top-3-clone-families.md +0 -162
  86. package/docs/plans/0227-evolve-agent-record-into-agent.md +0 -322
  87. package/docs/plans/0228-async-start-agent-dissolve-run-handle.md +0 -288
  88. package/docs/plans/0229-agent-born-complete.md +0 -564
  89. package/docs/plans/0230-extract-concurrency-queue.md +0 -265
  90. package/docs/plans/0231-push-exec-registry-to-runner.md +0 -245
  91. package/docs/plans/0232-agent-resume-internal-observer-lifecycle.md +0 -180
  92. package/docs/plans/0237-remove-disallowed-tools.md +0 -180
  93. package/docs/plans/0238-remove-extensions-filtering.md +0 -191
  94. package/docs/plans/0239-collapse-filter-active-tools.md +0 -217
  95. package/docs/plans/0242-rename-agent-tool-to-subagent.md +0 -165
  96. package/docs/plans/0256-extract-worktree-isolation.md +0 -256
  97. package/docs/plans/0257-extract-child-session-factory.md +0 -285
  98. package/docs/plans/0262-add-workspace-provider-seam.md +0 -264
  99. package/docs/plans/0264-remove-extension-lifecycle-control.md +0 -277
  100. package/docs/plans/0265-born-complete-subagent-session.md +0 -333
  101. package/docs/plans/0270-type-consumable-public-surface.md +0 -204
  102. package/docs/plans/0272-export-workspace-collaborator-types.md +0 -147
  103. package/docs/plans/0277-encapsulate-agent-session.md +0 -304
  104. package/docs/plans/0280-rename-agent-to-subagent.md +0 -197
  105. package/docs/plans/0360-custom-agents-default-append.md +0 -132
  106. package/docs/plans/0373-extract-subagent-state.md +0 -250
  107. package/docs/plans/0374-encapsulate-subagent-start-notification.md +0 -268
  108. package/docs/plans/0375-extract-run-listener-workspace-bracket.md +0 -300
  109. package/docs/plans/0376-extract-manager-observer.md +0 -232
  110. package/docs/plans/0377-split-widget-delegation-from-runtime.md +0 -254
  111. package/docs/plans/0378-consolidate-lifecycle-test-fixtures.md +0 -243
  112. package/docs/plans/0379-consolidate-ui-tools-test-fixtures.md +0 -335
  113. package/docs/plans/0380-extract-layered-settings-loader.md +0 -223
  114. package/docs/plans/0381-replace-concurrency-queue-with-limiter.md +0 -267
  115. package/docs/plans/0400-include-parent-prompt-in-replace-mode.md +0 -199
  116. package/docs/plans/0403-abort-subagents-on-interrupt.md +0 -180
  117. package/docs/plans/0412-unify-session-mock-builders.md +0 -146
  118. package/docs/plans/0420-fold-run-metrics-live-activity-onto-record.md +0 -228
  119. package/docs/plans/0421-migrate-activity-readers-to-record-getters.md +0 -309
  120. package/docs/plans/0422-delete-activity-tracker-ui-observer.md +0 -204
  121. package/docs/plans/0423-widget-self-drive-from-lifecycle.md +0 -264
  122. package/docs/plans/0424-drop-widget-dep-from-subagent-tool.md +0 -166
  123. package/docs/plans/0425-reconcile-subagent-events-contract.md +0 -144
  124. package/docs/plans/0426-consolidate-residual-test-clone-families.md +0 -235
  125. package/docs/plans/0427-reconsider-ui-direction.md +0 -212
  126. package/docs/plans/0441-remove-agent-definition-management-subtree.md +0 -180
  127. package/docs/plans/0442-dissolve-agents-conversation-viewer.md +0 -195
  128. package/docs/plans/0443-consolidate-remaining-test-clone-families.md +0 -268
  129. package/docs/plans/0444-shrink-widget-to-background-agents.md +0 -156
  130. package/docs/plans/0445-native-session-navigation.md +0 -365
  131. package/docs/plans/0446-spike-session-navigation-entry-criteria.md +0 -171
  132. package/docs/plans/0447-extract-subagents-settings-command.md +0 -220
  133. package/docs/plans/0448-block-disabled-agent-spawn.md +0 -207
  134. package/docs/plans/0462-navigation-renderer-tui-components.md +0 -338
  135. package/docs/plans/0463-file-snapshot-source-evicted-agents.md +0 -306
  136. package/docs/plans/0470-refresh-readme-command-surface.md +0 -159
  137. package/docs/retro/0048-implement-subagents-api.md +0 -44
  138. package/docs/retro/0049-remove-group-join-output-file-rpc.md +0 -49
  139. package/docs/retro/0051-update-adr-0001-hard-fork.md +0 -39
  140. package/docs/retro/0053-extract-model-resolution-from-execute.md +0 -40
  141. package/docs/retro/0054-decompose-index-into-modules.md +0 -53
  142. package/docs/retro/0057-structured-debug-logging.md +0 -77
  143. package/docs/retro/0061-session-format-transcript.md +0 -41
  144. package/docs/retro/0066-replace-as-any-with-sdk-types.md +0 -44
  145. package/docs/retro/0069-create-subagent-runtime.md +0 -43
  146. package/docs/retro/0070-extract-event-handlers.md +0 -49
  147. package/docs/retro/0071-extract-session-config-assembler.md +0 -60
  148. package/docs/retro/0072-inject-agent-manager-collaborators.md +0 -46
  149. package/docs/retro/0076-inject-cwd-into-agent-manager.md +0 -35
  150. package/docs/retro/0077-inject-project-agents-dir.md +0 -33
  151. package/docs/retro/0080-consolidate-agent-config-lookup.md +0 -35
  152. package/docs/retro/0084-extract-git-worktree-manager.md +0 -37
  153. package/docs/retro/0087-evolve-subagent-runtime-methods.md +0 -42
  154. package/docs/retro/0098-extract-agent-record-state-machine.md +0 -46
  155. package/docs/retro/0099-replace-ctx-with-parent-snapshot.md +0 -37
  156. package/docs/retro/0100-replace-callback-threading-with-session-subscription.md +0 -36
  157. package/docs/retro/0102-consolidate-test-record-factory.md +0 -30
  158. package/docs/retro/0108-extract-agent-type-registry.md +0 -41
  159. package/docs/retro/0109-extract-settings-manager.md +0 -55
  160. package/docs/retro/0110-agent-activity-tracker.md +0 -44
  161. package/docs/retro/0111-split-agent-record-lifecycle.md +0 -61
  162. package/docs/retro/0112-replace-agent-manager-callbacks.md +0 -35
  163. package/docs/retro/0113-disambiguate-spawn-options.md +0 -29
  164. package/docs/retro/0114-narrow-agent-tool-menu-deps.md +0 -38
  165. package/docs/retro/0115-decompose-agent-tool.md +0 -51
  166. package/docs/retro/0116-type-housekeeping.md +0 -42
  167. package/docs/retro/0118-settings-manager-apply-methods.md +0 -40
  168. package/docs/retro/0123-remove-vi-fn-cast-smell.md +0 -49
  169. package/docs/retro/0131-consolidate-shared-test-fixtures.md +0 -46
  170. package/docs/retro/0132-inject-io-into-session-config.md +0 -33
  171. package/docs/retro/0133-inject-sdk-boundary-into-agent-runner.md +0 -45
  172. package/docs/retro/0134-reduce-as-any-casts.md +0 -56
  173. package/docs/retro/0135-extract-display-helpers.md +0 -38
  174. package/docs/retro/0136-decompose-agent-menu.md +0 -43
  175. package/docs/retro/0144-consolidate-observation-model.md +0 -39
  176. package/docs/retro/0145-decompose-execute-push-ctx-to-boundary.md +0 -56
  177. package/docs/retro/0146-narrow-ui-context.md +0 -70
  178. package/docs/retro/0147-inject-wrap-text-into-conversation-viewer.md +0 -90
  179. package/docs/retro/0148-split-agent-widget-rendering.md +0 -39
  180. package/docs/retro/0152-add-prompt-snippet.md +0 -34
  181. package/docs/retro/0164-reorganize-into-domain-directories.md +0 -82
  182. package/docs/retro/0165-decompose-resolved-spawn-config.md +0 -78
  183. package/docs/retro/0166-extract-parent-session-info.md +0 -66
  184. package/docs/retro/0167-narrow-runner-io.md +0 -63
  185. package/docs/retro/0168-extract-tool-filter-config.md +0 -76
  186. package/docs/retro/0169-extract-run-context-from-run-options.md +0 -68
  187. package/docs/retro/0170-reduce-build-content-lines-complexity.md +0 -72
  188. package/docs/retro/0171-reduce-render-result-complexity.md +0 -77
  189. package/docs/retro/0172-extract-turn-formatting.md +0 -80
  190. package/docs/retro/0180-reorder-append-prompt-for-kv-cache.md +0 -62
  191. package/docs/retro/0185-remove-persistent-agent-memory.md +0 -73
  192. package/docs/retro/0188-replace-any-casts-with-sdk-types.md +0 -69
  193. package/docs/retro/0192-define-session-context-interface.md +0 -59
  194. package/docs/retro/0193-runtime-owns-context-queries.md +0 -75
  195. package/docs/retro/0194-align-tool-interfaces-for-structural-typing.md +0 -62
  196. package/docs/retro/0195-convert-tool-factories-to-classes.md +0 -84
  197. package/docs/retro/0196-convert-runner-menu-to-classes.md +0 -73
  198. package/docs/retro/0205-decompose-render-widget-lines.md +0 -64
  199. package/docs/retro/0206-decompose-show-agent-detail.md +0 -67
  200. package/docs/retro/0207-decompose-agent-widget-update.md +0 -92
  201. package/docs/retro/0208-extract-shared-test-fixtures.md +0 -102
  202. package/docs/retro/0214-convert-remaining-closure-factories-to-classes.md +0 -66
  203. package/docs/retro/0215-decompose-build-parent-context.md +0 -61
  204. package/docs/retro/0216-decompose-start-agent.md +0 -80
  205. package/docs/retro/0217-extract-overwrite-guard.md +0 -63
  206. package/docs/retro/0218-push-sdk-boundary-in-settings.md +0 -72
  207. package/docs/retro/0219-reduce-test-duplication-top-3-clone-families.md +0 -64
  208. package/docs/retro/0227-evolve-agent-record-into-agent.md +0 -80
  209. package/docs/retro/0228-async-start-agent-dissolve-run-handle.md +0 -80
  210. package/docs/retro/0229-agent-born-complete.md +0 -89
  211. package/docs/retro/0230-extract-concurrency-queue.md +0 -38
  212. package/docs/retro/0231-push-exec-registry-to-runner.md +0 -71
  213. package/docs/retro/0232-agent-resume-internal-observer-lifecycle.md +0 -109
  214. package/docs/retro/0237-remove-disallowed-tools.md +0 -78
  215. package/docs/retro/0238-remove-extensions-filtering.md +0 -72
  216. package/docs/retro/0239-collapse-filter-active-tools.md +0 -70
  217. package/docs/retro/0242-rename-agent-tool-to-subagent.md +0 -82
  218. package/docs/retro/0256-extract-worktree-isolation.md +0 -89
  219. package/docs/retro/0257-extract-child-session-factory.md +0 -33
  220. package/docs/retro/0262-add-workspace-provider-seam.md +0 -89
  221. package/docs/retro/0264-remove-extension-lifecycle-control.md +0 -91
  222. package/docs/retro/0265-born-complete-subagent-session.md +0 -97
  223. package/docs/retro/0270-type-consumable-public-surface.md +0 -108
  224. package/docs/retro/0272-export-workspace-collaborator-types.md +0 -38
  225. package/docs/retro/0277-encapsulate-agent-session.md +0 -80
  226. package/docs/retro/0280-rename-agent-to-subagent.md +0 -96
  227. package/docs/retro/0360-custom-agents-default-append.md +0 -81
  228. package/docs/retro/0373-extract-subagent-state.md +0 -94
  229. package/docs/retro/0374-encapsulate-subagent-start-notification.md +0 -171
  230. package/docs/retro/0375-extract-run-listener-workspace-bracket.md +0 -104
  231. package/docs/retro/0376-extract-manager-observer.md +0 -81
  232. package/docs/retro/0377-split-widget-delegation-from-runtime.md +0 -105
  233. package/docs/retro/0378-consolidate-lifecycle-test-fixtures.md +0 -100
  234. package/docs/retro/0379-consolidate-ui-tools-test-fixtures.md +0 -52
  235. package/docs/retro/0380-extract-layered-settings-loader.md +0 -97
  236. package/docs/retro/0381-replace-concurrency-queue-with-limiter.md +0 -95
  237. package/docs/retro/0400-include-parent-prompt-in-replace-mode.md +0 -84
  238. package/docs/retro/0403-abort-subagents-on-interrupt.md +0 -90
  239. package/docs/retro/0412-unify-session-mock-builders.md +0 -80
  240. package/docs/retro/0420-fold-run-metrics-live-activity-onto-record.md +0 -90
  241. package/docs/retro/0421-migrate-activity-readers-to-record-getters.md +0 -105
  242. package/docs/retro/0422-delete-activity-tracker-ui-observer.md +0 -97
  243. package/docs/retro/0423-widget-self-drive-from-lifecycle.md +0 -112
  244. package/docs/retro/0424-drop-widget-dep-from-subagent-tool.md +0 -89
  245. package/docs/retro/0425-reconcile-subagent-events-contract.md +0 -101
  246. package/docs/retro/0426-consolidate-residual-test-clone-families.md +0 -100
  247. package/docs/retro/0427-reconsider-ui-direction.md +0 -102
  248. package/docs/retro/0441-remove-agent-definition-management-subtree.md +0 -97
  249. package/docs/retro/0442-dissolve-agents-conversation-viewer.md +0 -108
  250. package/docs/retro/0443-consolidate-remaining-test-clone-families.md +0 -28
  251. package/docs/retro/0444-shrink-widget-to-background-agents.md +0 -81
  252. package/docs/retro/0445-native-session-navigation.md +0 -122
  253. package/docs/retro/0446-spike-session-navigation-entry-criteria.md +0 -99
  254. package/docs/retro/0447-extract-subagents-settings-command.md +0 -91
  255. package/docs/retro/0448-block-disabled-agent-spawn.md +0 -75
  256. package/docs/retro/0462-navigation-renderer-tui-components.md +0 -105
  257. package/docs/retro/0463-file-snapshot-source-evicted-agents.md +0 -103
  258. package/docs/retro/0470-refresh-readme-command-surface.md +0 -40
  259. package/src/observation/notification-state.ts +0 -27
  260. package/vitest.config.ts +0 -14
@@ -1,309 +0,0 @@
1
- ---
2
- issue: 421
3
- issue_title: "pi-subagents: migrate activity-tracker readers to the record getters"
4
- ---
5
-
6
- # Migrate activity-tracker readers to the record getters
7
-
8
- ## Problem Statement
9
-
10
- Phase 18 Step 1 ([#420]) folded the live-activity fields (`turnCount`, `activeTools`, `responseText`, `maxTurns`) onto the single owned run-state value object and exposed them as read-only getters on `Subagent`, but nothing reads them yet.
11
- Five consumers still reach into a separate UI `AgentActivityTracker` for data the record now exposes directly — a Law-of-Demeter coupling that keeps the activity tier entangled with the core.
12
- This step switches each reader from the tracker to the record getters so that no reader reads activity off `AgentActivityTracker`, unblocking the tracker's deletion in Step 3 ([#422]).
13
-
14
- This is Phase 18 Step 2 of the architecture roadmap (`docs/architecture/architecture.md`).
15
- It is a reader migration: the producer plumbing that still constructs trackers, subscribes `ui-observer`, and populates the runtime activity map (`foreground-runner`, `background-spawner`, `runtime.ts`, `ui-observer.ts`) is left in place and removed in Step 3.
16
- The reader-held map dependencies in `notification`, `agent-widget`, and `agent-menu` — files Step 3 does not touch — are removed here.
17
-
18
- ## Goals
19
-
20
- - Switch `widget-renderer` to read live activity off the `Subagent` records returned by `listAgents()` rather than a parallel `activityMap`, folding the `WidgetActivity` interface into `WidgetAgent`.
21
- - Drop the `activity` constructor param from `ConversationViewer`; read `activeTools` / `responseText` off `this.record`.
22
- - Drop the `AgentActivityReader` dependency from `AgentsMenuHandler`.
23
- - Migrate `runForeground` and `buildDetails` to read streaming state (`turnCount`, `maxTurns`, `activeTools`, `responseText`) off the `Subagent` they already hold.
24
- - Migrate `buildNotificationDetails` to read `turnCount` / `maxTurns` off the record, and drop the `agentActivity` map dependency (and the now-vestigial `cleanupCompleted` method) from `NotificationManager`.
25
- - Project each `Subagent` into a pure-data `WidgetAgent` snapshot inside `AgentWidget` (with a `contextPercent` field), keeping `widget-renderer` a pure function of plain data.
26
-
27
- This change is **not breaking**.
28
- The published service surface (`src/service/service.ts`) exposes `SubagentRecord` / `SubagentStatus`, neither of which changes.
29
- There is one accepted observable behavior change in the widget (below), but no API, config, or default changes on upgrade without a user edit.
30
-
31
- ### Accepted behavior change
32
-
33
- Today the widget shows **no** turn count on finished-agent lines because the activity tracker is deleted on completion (foreground deletes it after `spawnAndWait`; `NotificationManager.sendCompletion` deletes it for background agents).
34
- The record's `turnCount` getter persists, so once `widget-renderer` reads off `listAgents()` records, finished lines will show `⟳N`.
35
- This is **accepted** (confirmed with the operator): the deletion-on-completion behavior was a UI-state artifact, and showing the turn count consistently is the more correct outcome.
36
- Preserving the old behavior would require the widget to track which finished agents were "cleaned up" — reintroducing exactly the coupling this phase removes.
37
-
38
- ## Non-Goals
39
-
40
- - Deleting `AgentActivityTracker` / `ui-observer`, or removing the producer plumbing in `foreground-runner` / `background-spawner` / `runtime.ts` that still constructs trackers, subscribes, and populates the activity map — Step 3 ([#422]).
41
- - Dropping the `widget` and `agentActivity` constructor params from `AgentTool` — Step 5 ([#424]).
42
- - Making the widget self-drive its timer from lifecycle events instead of spawn-tool calls — Step 4 ([#423]).
43
- - Reconciling the public event contract (`SUBAGENT_EVENTS.ACTIVITY`) — Step 6 ([#425]).
44
- - Changing `SubagentState`, `record-observer`, or the getters themselves — landed in Step 1 ([#420]).
45
-
46
- ## Background
47
-
48
- Relevant modules and how they relate:
49
-
50
- - `src/lifecycle/subagent.ts` — exposes the four read-only getters added in Step 1: `turnCount` and `activeTools` and `responseText` delegate to the owned `SubagentState`; `maxTurns` returns `this.execution.maxTurns`.
51
- Also exposes `getContextPercent(): number | null` (delegates to `subagentSession.getContextPercent()`), the live context-window utilization.
52
- - `src/ui/widget-renderer.ts` — pure rendering functions.
53
- `renderFinishedLine` / `renderRunningLines` take a `WidgetAgent` plus a `WidgetActivity | undefined`; `renderWidgetLines` takes an `activityMap: ReadonlyMap<string, WidgetActivity>`.
54
- `renderRunningLines` computes the context percent via `activity?.session ? getSessionContextPercent(activity.session) : null` — a reach into session stats from a module documented as taking no SDK types.
55
- - `src/ui/agent-widget.ts` — `AgentWidget` holds the `agentActivity` map and passes `manager.listAgents()` (Subagents, structurally accepted as `WidgetAgent`) plus the map to `renderWidgetLines`.
56
- - `src/ui/conversation-viewer.ts` — `ConversationViewer` takes an `activity: AgentActivityTracker | undefined`; reads `activity.activeTools` / `activity.responseText` in `buildContentLines` for the running streaming indicator.
57
- - `src/ui/agent-menu.ts` — defines `AgentActivityReader` (`get(id): AgentActivityTracker | undefined`), takes it as a constructor param, and reads `this.agentActivity.get(record.id)` in `viewAgentConversation` to pass to `ConversationViewer`.
58
- - `src/tools/foreground-runner.ts` — constructs `fgState = new AgentActivityTracker(...)`, subscribes `ui-observer`, populates the activity map, and reads `fgState.turnCount` / `fgState.maxTurns` / `fgState.activeTools` / `fgState.responseText` in `streamUpdate`; passes `fgState` to `buildDetails`.
59
- - `src/tools/helpers.ts` — `buildDetails(base, record, activity?, overrides?)` reads `activity?.turnCount` and `activity?.maxTurns`.
60
- Two call sites: `runForeground` (passes `fgState`) and `AgentTool` resume (no activity arg).
61
- - `src/observation/notification.ts` — `buildNotificationDetails(record, resultMaxLen, activity?)` reads `activity?.turnCount` / `activity?.maxTurns`.
62
- `NotificationManager` holds the `agentActivity` map and deletes from it in `sendCompletion` and `cleanupCompleted`.
63
- - `src/observation/subagent-events-observer.ts` — `onSubagentCompleted` calls `notifications.cleanupCompleted(record.id)` when `record.notification?.resultConsumed`, else `notifications.sendCompletion(record)`.
64
- - `src/index.ts` — constructs `NotificationManager`, `AgentWidget`, and `AgentsMenuHandler`, each currently passed `runtime.agentActivity`.
65
-
66
- AGENTS.md / code-design constraints that apply:
67
-
68
- - `widget-renderer.ts` is a pure rendering module ("stateless: they receive data and return formatted strings.
69
- No timers, no SDK types, no side effects").
70
- The migration keeps it pure and **narrows** it: the precomputed `contextPercent` field lets it drop the `SessionLike` / `getSessionContextPercent` imports, removing the session reach-through.
71
- - `AgentWidget` is the adapter between the live manager/records and the pure renderer; the explicit `Subagent` → `WidgetAgent` projection belongs there (DIP, narrow data boundary).
72
- - `getSessionContextPercent` and `SessionLike` stay in `usage.ts` — still used by `subagent-session.ts` and `getSessionTokens`, so removing the widget-renderer import creates no dead code.
73
-
74
- ## Design Overview
75
-
76
- ### `WidgetAgent` absorbs the activity fields (widget-renderer)
77
-
78
- `WidgetActivity` is removed; its fields move onto `WidgetAgent` as plain data, plus a precomputed context percent:
79
-
80
- ```typescript
81
- export interface WidgetAgent {
82
- readonly id: string;
83
- readonly type: SubagentType;
84
- readonly status: string;
85
- readonly description: string;
86
- readonly toolUses: number;
87
- readonly startedAt: number;
88
- readonly completedAt?: number;
89
- readonly error?: string;
90
- readonly lifetimeUsage?: Readonly<LifetimeUsage>;
91
- readonly compactionCount: number;
92
- // Folded-in live activity (was WidgetActivity)
93
- readonly turnCount: number;
94
- readonly maxTurns?: number;
95
- readonly activeTools: ReadonlyMap<string, string>;
96
- readonly responseText: string;
97
- readonly contextPercent: number | null;
98
- }
99
- ```
100
-
101
- `renderFinishedLine(agent, registry, theme)` and `renderRunningLines(agent, registry, spinnerFrame, theme)` drop the `WidgetActivity | undefined` parameter and read `agent.turnCount` / `agent.maxTurns` / `agent.activeTools` / `agent.responseText` directly.
102
- `renderRunningLines` uses `agent.contextPercent` in place of `activity?.session ? getSessionContextPercent(activity.session) : null`.
103
- `renderWidgetLines` and `buildSections` drop the `activityMap` parameter.
104
- Because every `WidgetAgent` now carries activity, the old "no activity provided → omit turn count / show `thinking…`" branch is gone — `describeActivity(emptyMap, "")` already returns the `thinking…` string for an idle running agent, so the running-line text is preserved.
105
-
106
- ### `AgentWidget` projects records into snapshots
107
-
108
- `AgentWidget` drops its `agentActivity` constructor param and field.
109
- `renderWidget` maps each record through a local projection before handing the array to the pure renderer:
110
-
111
- ```typescript
112
- private toWidgetAgent(record: Subagent): WidgetAgent {
113
- return {
114
- id: record.id,
115
- type: record.type,
116
- status: record.status,
117
- description: record.description,
118
- toolUses: record.toolUses,
119
- startedAt: record.startedAt,
120
- completedAt: record.completedAt,
121
- error: record.error,
122
- lifetimeUsage: record.lifetimeUsage,
123
- compactionCount: record.compactionCount,
124
- turnCount: record.turnCount,
125
- maxTurns: record.maxTurns,
126
- activeTools: record.activeTools,
127
- responseText: record.responseText,
128
- contextPercent: record.getContextPercent(),
129
- };
130
- }
131
- ```
132
-
133
- `renderWidget` then calls `renderWidgetLines({ agents: this.manager.listAgents().map(r => this.toWidgetAgent(r)), registry, … })` with no `activityMap`.
134
- `assembleWidgetState` keeps consuming raw records via its `AgentSummary` shape (id / status / completedAt) — unchanged.
135
- This makes the snapshot boundary explicit: the renderer depends only on plain data; `AgentWidget` owns the projection (Tell-Don't-Ask — it asks each record once and hands forward a value).
136
-
137
- ### `ConversationViewer` reads off the record
138
-
139
- The `activity` constructor param and field are removed.
140
- `buildContentLines` reads the streaming indicator inputs off the record it already holds:
141
-
142
- ```typescript
143
- if (this.record.status === "running") {
144
- lines.push(...formatStreamingIndicator(
145
- this.record.activeTools,
146
- this.record.responseText,
147
- width,
148
- th,
149
- ));
150
- }
151
- ```
152
-
153
- The `&& this.activity` guard is dropped — a running record always exposes `activeTools` / `responseText` (empty / `""` when idle), and `describeActivity` renders the idle case as `thinking…`, matching the prior no-tracker fallback.
154
-
155
- ### `AgentsMenuHandler` drops the reader
156
-
157
- The `AgentActivityReader` interface and the `agentActivity` constructor param are removed.
158
- `viewAgentConversation` no longer looks up a tracker; it constructs `ConversationViewer` without an `activity` field.
159
-
160
- ### `buildDetails` / `runForeground` read off the record
161
-
162
- `buildDetails` drops its `activity?: AgentActivityTracker` parameter; the structural `record` param gains `turnCount?: number` and `maxTurns?: number`, and the body reads `record.turnCount` / `record.maxTurns`:
163
-
164
- ```typescript
165
- export function buildDetails(
166
- base: Pick<AgentDetails, "displayName" | "description" | "subagentType" | "modelName" | "tags">,
167
- record: {
168
- toolUses: number; startedAt: number; completedAt?: number; status: string;
169
- error?: string; id?: string; lifetimeUsage: LifetimeUsage;
170
- turnCount?: number; maxTurns?: number;
171
- },
172
- overrides?: Partial<AgentDetails>,
173
- ): AgentDetails { … turnCount: record.turnCount, maxTurns: record.maxTurns … }
174
- ```
175
-
176
- `Subagent` satisfies this structurally (the getters supply `turnCount` / `maxTurns`).
177
- In `runForeground`, `streamUpdate` reads `recordRef?.turnCount ?? 1`, `recordRef?.activeTools ?? new Map()`, `recordRef?.responseText ?? ""`, and `execution.effectiveMaxTurns` for `maxTurns` (the runner already holds this constant; `recordRef` is undefined until `onSessionCreated`).
178
- The final `buildDetails(presentation.detailBase, record, fgState, { tokens })` becomes `buildDetails(presentation.detailBase, record, { tokens })`.
179
- The `fgState` tracker, its `subscribeUIObserver` subscription, and the `agentActivity.set` / `delete` calls remain (producer plumbing removed in Step 3) but are no longer read.
180
-
181
- ### `buildNotificationDetails` / `NotificationManager`
182
-
183
- `buildNotificationDetails(record, resultMaxLen)` drops the `activity?` param and reads `record.turnCount` / `record.maxTurns`.
184
- `NotificationManager` drops the `agentActivity` constructor param and field; `sendCompletion` keeps only the nudge scheduling.
185
- `cleanupCompleted` only ever deleted a map entry, so it becomes vestigial and is **removed** from both `NotificationSystem` and `NotificationManager`.
186
- `SubagentEventsObserver.onSubagentCompleted` updates its `resultConsumed` branch to simply `return` (skip the nudge) instead of calling `cleanupCompleted`.
187
-
188
- ### Consumer call-site check (index.ts)
189
-
190
- ```typescript
191
- const notifications = new NotificationManager((msg, opts) => pi.sendMessage(msg, opts));
192
- const widget = new AgentWidget(manager, registry);
193
- const agentsMenu = new AgentsMenuHandler(manager, registry, settings, new FsAgentFileOps(), …);
194
- ```
195
-
196
- All three constructions drop the `runtime.agentActivity` argument.
197
- `runtime.agentActivity` itself stays (still written by the spawn tools; removed in Step 3).
198
-
199
- ## Module-Level Changes
200
-
201
- - `src/ui/widget-renderer.ts` — remove the `WidgetActivity` interface; fold its fields plus `contextPercent` into `WidgetAgent`; drop the `WidgetActivity | undefined` param from `renderFinishedLine` / `renderRunningLines`; drop `activityMap` from `buildSections` / `renderWidgetLines`; remove the `SessionLike` and `getSessionContextPercent` imports (keep `getLifetimeTotal`).
202
- - `src/ui/agent-widget.ts` — drop the `agentActivity` constructor param and field; add the `toWidgetAgent` projection; map `listAgents()` through it in `renderWidget`; drop the `AgentActivityTracker` import.
203
- - `src/ui/conversation-viewer.ts` — drop the `activity` field and `ConversationViewerOptions.activity`; read `activeTools` / `responseText` off `this.record`; drop the `AgentActivityTracker` import.
204
- - `src/ui/agent-menu.ts` — remove the `AgentActivityReader` interface and the `agentActivity` constructor param; drop the tracker lookup in `viewAgentConversation`; drop the `AgentActivityTracker` import.
205
- - `src/tools/helpers.ts` — `buildDetails` drops the `activity?` param and reads `record.turnCount` / `record.maxTurns` (param type gains the two optional fields); drop the `AgentActivityTracker` import.
206
- - `src/tools/foreground-runner.ts` — `streamUpdate` and the final `buildDetails` call read off `recordRef` / `record`; the `fgState` construction, `subscribeUIObserver`, and map writes stay (Step 3).
207
- - `src/observation/notification.ts` — `buildNotificationDetails` drops the `activity?` param and reads off the record; `NotificationManager` drops the `agentActivity` param/field and the `delete` calls; remove `cleanupCompleted` from `NotificationSystem` and the class; drop the `AgentActivityTracker` import.
208
- - `src/observation/subagent-events-observer.ts` — `onSubagentCompleted` `resultConsumed` branch returns without calling `cleanupCompleted`.
209
- - `src/index.ts` — drop `runtime.agentActivity` from the `NotificationManager`, `AgentWidget`, and `AgentsMenuHandler` constructions.
210
- - `.pi/skills/package-pi-subagents/SKILL.md` — update the module-dependency-flow line `widget ─polls─→ AgentActivityTracker map` to reflect that the widget now polls `listAgents()` records.
211
- - `docs/architecture/architecture.md` — add a `Landed:` line to the Phase 18 Step 2 entry during implementation (the entry text already describes the work).
212
-
213
- Test files (see TDD Order for which step each lands in):
214
-
215
- - `test/helpers/make-subagent.ts` — add `turnCount` / `activeTools` / `responseText` / `maxTurns` shorthands to `createTestSubagent` so reader tests can seed activity on records.
216
- - `test/widget-renderer.test.ts` — remove `WidgetActivity` / `makeActivity`; fold activity defaults into `makeAgent` (`turnCount`, `maxTurns`, `activeTools`, `responseText`, `contextPercent`); drop the `activity` arg from render calls and `activityMap` from `renderWidgetLines` calls; update the former "omit turn count when no activity" cases to assert the turn count now renders; convert the session-stats context test to a `contextPercent` field.
217
- - `test/ui/agent-widget.test.ts` — drop the `agentActivity` arg from `new AgentWidget(...)`; add a projection test asserting `renderWidget` reads activity off records.
218
- - `test/conversation-viewer.test.ts` — drop `activity` from `TestViewerOptions` / `createTestViewer`; seed the running-indicator test's `activeTools` / `responseText` via `createTestSubagent`; drop the `AgentActivityTracker` import.
219
- - `test/ui/agent-menu.test.ts` — drop the `agentActivity` arg from `new AgentsMenuHandler(...)`.
220
- - `test/tools/helpers.test.ts` — drop the `activity` arg from `buildDetails` calls; seed `turnCount` / `maxTurns` via `createTestSubagent`; drop the `AgentActivityTracker` import.
221
- - `test/tools/foreground-runner.test.ts` — adjust any `details.turnCount` assertions to the record's value (turn count `1` default matches the prior tracker default, so most cases are unchanged); the activity-map registration test stays (producer plumbing remains).
222
- - `test/observation/notification.test.ts` — drop `agentActivity` from `makeArgs` and `new NotificationManager(...)`; drop the `activity` arg from `buildNotificationDetails` calls and seed `turnCount` / `maxTurns` via `createTestSubagent`; remove the two map-cleanup assertions and the `cleanupCompleted` test.
223
- - `test/observation/subagent-events-observer.test.ts` — update any assertion that `cleanupCompleted` is called on `resultConsumed` to assert no nudge is sent instead.
224
-
225
- `test/runtime.test.ts` and `test/helpers/make-deps.ts` keep their `AgentActivityTracker` map usage — the runtime map and the `AgentTool` `agentActivity` access survive this step (removed in Steps 3 / 5).
226
- Completed historical plans under `docs/plans/` are point-in-time records and are not edited.
227
-
228
- ## Test Impact Analysis
229
-
230
- 1. **New unit tests enabled.**
231
- `agent-widget.test.ts` can now assert the projection directly — that `renderWidget` surfaces a record's `turnCount` / `activeTools` / `contextPercent` without any external map — because activity lives on the record the manager stub returns.
232
- `widget-renderer.test.ts` tests get simpler: a single `makeAgent` carries everything, removing the two-object (`WidgetAgent` + `WidgetActivity`) arrangement.
233
- 2. **Tests that become redundant / simplified.**
234
- The `widget-renderer` "omits turn count when no activity provided" cases lose their premise (there is no activity-absent path); they convert to asserting the turn count renders.
235
- The `notification` "sendCompletion cleans up activity" and "cleanupCompleted removes activity" cases lose their subject (the map is gone) and are removed.
236
- `ui-observer.test.ts` and `agent-activity-tracker.test.ts` stay — they pin the producer behavior still wired until Step 3.
237
- 3. **Tests that must stay as-is.**
238
- `foreground-runner.test.ts`'s activity-map registration test (the tracker is still constructed and registered), and `runtime.test.ts`'s `agentActivity` map presence test, genuinely exercise the producer plumbing this step does not remove.
239
-
240
- ## Invariants at risk
241
-
242
- - **Step 1 ([#420]) outcome — `Subagent` is the single home for run state; getters available for migration.**
243
- This step is the consumer of that outcome; the getters' parity with the old tracker (turn count starts at `1`, `name_seq` active-tool keying, reset-then-append response text) is what makes the swap behavior-preserving for running agents.
244
- Pinned by the existing `subagent-state.test.ts` / `record-observer.test.ts` cases from Step 1 plus the reader tests migrated here.
245
- - **`widget-renderer` purity — pure functions, plain data, no SDK types** (established when the renderer was split out, plan 0148).
246
- The migration preserves and strengthens it: the `contextPercent` field removes the `getSessionContextPercent(session)` reach-through, so the renderer no longer touches session stats.
247
- Pinned by `widget-renderer.test.ts` constructing plain `WidgetAgent` objects (no class instances).
248
- - **`NotificationManager` construction graph stays a cycle-free DAG with no widget dependency** (index.ts comment).
249
- Dropping the `agentActivity` map narrows its deps further; no new dependency is added.
250
-
251
- No earlier phase step's documented `Outcome:` is regressed — the producer plumbing Step 1's tidy-first overlap left in place is untouched here.
252
-
253
- ## TDD Order
254
-
255
- 1. **Preparatory: seed activity on test records.**
256
- Surface: `test/helpers/make-subagent.ts` (+ a focused assertion in `test/helpers/make-deps.test.ts` or `make-subagent` coverage if one exists).
257
- Add `turnCount` / `activeTools` / `responseText` / `maxTurns` shorthands to `createTestSubagent` (drive `state.incrementTurnCount` / `addActiveTool` / `appendResponseText`; thread `maxTurns` into `makeStubExecution`).
258
- Pure test-helper addition — no production change; makes the reader-migration steps easy ("make the change that makes the change easy").
259
- Commit: `test: seed live-activity on createTestSubagent (#421)`.
260
- 2. **Migrate the widget reader.**
261
- Surface: `test/widget-renderer.test.ts`, `test/ui/agent-widget.test.ts`.
262
- Red→green: update `makeAgent` to carry activity, drop the `activity` arg / `activityMap`, assert finished lines now render the turn count, assert the `AgentWidget` projection.
263
- Implement the `WidgetAgent` fold + `contextPercent`, the render-signature changes, and the `AgentWidget.toWidgetAgent` projection; update the `new AgentWidget(...)` call in `index.ts` and the SKILL.md flow line.
264
- This step lands the accepted behavior change (finished-agent turn count), so the commit is `feat:`, not `refactor:`.
265
- Run `pnpm run check` after this commit — `renderWidgetLines` is the shared signature changed.
266
- Commit: `feat: read widget activity off subagent records (#421)`.
267
- 3. **Migrate the conversation viewer and `/agents` menu.**
268
- Surface: `test/conversation-viewer.test.ts`, `test/ui/agent-menu.test.ts`.
269
- Red→green: drop `activity` from the viewer factory and seed the running-indicator inputs on the record; drop the `agentActivity` arg from the menu handler construction.
270
- Implement: drop `ConversationViewer.activity`; read off `this.record`; remove `AgentActivityReader` and the `viewAgentConversation` lookup; update the `new AgentsMenuHandler(...)` call in `index.ts`.
271
- The viewer constructor signature and the menu constructor signature both change with their sole call sites in the same commit.
272
- Commit: `refactor: read conversation-viewer activity off the record (#421)`.
273
- 4. **Migrate `buildDetails` and the foreground runner.**
274
- Surface: `test/tools/helpers.test.ts`, `test/tools/foreground-runner.test.ts`.
275
- Red→green: drop the `activity` arg from `buildDetails` calls and seed `turnCount` / `maxTurns` on the record; confirm the foreground `details` still report the record's turn count.
276
- Implement: `buildDetails` param/body change (both call sites — `runForeground` and the `AgentTool` resume path — compile in the same commit), and `runForeground`'s `streamUpdate` / final `buildDetails` reads.
277
- Commit: `refactor: build agent details from the record, not the tracker (#421)`.
278
- 5. **Migrate notifications and drop the activity map there.**
279
- Surface: `test/observation/notification.test.ts`, `test/observation/subagent-events-observer.test.ts`.
280
- Red→green: drop `agentActivity` from the notification fixtures and the `activity` arg from `buildNotificationDetails`; remove the map-cleanup and `cleanupCompleted` cases; assert the observer's `resultConsumed` branch sends no nudge.
281
- Implement: `buildNotificationDetails` reads off the record; `NotificationManager` drops the map param/field and `cleanupCompleted`; `NotificationSystem` drops `cleanupCompleted`; `SubagentEventsObserver` returns in the `resultConsumed` branch; update the `new NotificationManager(...)` call in `index.ts`.
282
- Run `pnpm run check` after this commit — `NotificationSystem` is a shared interface and `index.ts` is its construction site.
283
- Commit: `refactor: build notification details from the record (#421)`.
284
-
285
- After Step 5, no reader reads activity off `AgentActivityTracker`; the tracker, `ui-observer`, and the runtime map remain only as inert producer plumbing for Step 3 ([#422]).
286
-
287
- ## Risks and Mitigations
288
-
289
- - **Risk: the running-line idle text changes.**
290
- Once `activeTools` / `responseText` always come off the record, an idle running agent renders via `describeActivity(new Map(), "")` instead of the old no-tracker `thinking…` fallback.
291
- Mitigation: `describeActivity` already returns `thinking…` for an empty map and blank text, so the output is preserved; the migrated `widget-renderer` test pins it.
292
- - **Risk: transient background-tracker map leak between Steps 2 and 3.**
293
- `NotificationManager` no longer deletes finished agents' trackers from the runtime map, and background agents are no longer cleaned up by anyone until the map is removed.
294
- Mitigation: after this step the map is write-only and read by nobody, so the leak is inert and short-lived; Step 3 ([#422]) removes the map entirely.
295
- - **Risk: `streamUpdate` runs before `recordRef` is set (foreground).**
296
- The initial `streamUpdate()` and the first spinner ticks fire before `onSessionCreated` assigns `recordRef`.
297
- Mitigation: read with defaults that match the tracker's initial values (`turnCount ?? 1`, empty `activeTools`, `"" `responseText, `execution.effectiveMaxTurns` for `maxTurns`).
298
- - **Risk: removing `cleanupCompleted` changes the observer's consumed-result path.**
299
- Mitigation: the method only deleted a map entry; the observer's intent (skip the nudge when the result was already consumed) is preserved by an early `return`, pinned by the updated observer test.
300
-
301
- ## Open Questions
302
-
303
- - Whether the `NotificationSystem` interface should be narrowed further (e.g. to a two-method completion notifier) now that `cleanupCompleted` is gone is deferred — it is orthogonal to this step and best judged once Steps 3–5 settle the surrounding wiring.
304
-
305
- [#420]: https://github.com/gotgenes/pi-packages/issues/420
306
- [#422]: https://github.com/gotgenes/pi-packages/issues/422
307
- [#423]: https://github.com/gotgenes/pi-packages/issues/423
308
- [#424]: https://github.com/gotgenes/pi-packages/issues/424
309
- [#425]: https://github.com/gotgenes/pi-packages/issues/425
@@ -1,204 +0,0 @@
1
- ---
2
- issue: 422
3
- issue_title: "pi-subagents: delete AgentActivityTracker and ui-observer, drop the activity map from the core"
4
- ---
5
-
6
- # Delete AgentActivityTracker and ui-observer, drop the activity map from the core
7
-
8
- ## Problem Statement
9
-
10
- The activity tier is the UI's live-streaming bookkeeping, but today it lives inside the core.
11
- A `Map<string, AgentActivityTracker>` sits on the core composition root (`SubagentRuntime`), and the two spawn tools construct trackers, open a second session subscription (`subscribeUIObserver`), and populate or delete the map.
12
- After Phase 18 Step 2 ([#421]) migrated every reader to the record getters, nothing reads the trackers or the map any longer — they are dead bookkeeping the core still maintains.
13
- This is the third step of the Phase 18 spine (activity-tier disentanglement): delete `AgentActivityTracker` and `ui-observer`, and remove the activity map from `SubagentRuntime` and the spawn tools.
14
-
15
- ## Goals
16
-
17
- - Delete `src/ui/agent-activity-tracker.ts` and `src/ui/ui-observer.ts` (~145 LOC).
18
- - Remove `agentActivity` from `SubagentRuntime` (`src/runtime.ts`) and from the `AgentToolRuntime` slice (`src/tools/agent-tool.ts`).
19
- - Stop constructing trackers, calling `subscribeUIObserver` / `setSession`, and populating or deleting the map in `src/tools/foreground-runner.ts` and `src/tools/background-spawner.ts`.
20
- - Remove the now-unused `AgentActivityAccess` interface and the `agentActivity` parameter from both spawner functions.
21
- - Leave each child session with exactly one session subscription (the core's own `record-observer`) and zero UI state on the runtime.
22
- - Keep the existing test suite green at every commit.
23
-
24
- This is **not** a breaking change.
25
- `AgentActivityTracker`, `ui-observer`, and `SubagentRuntime.agentActivity` are internal symbols — none appear in the public service surface (`src/service/service.ts`) or the settings entry (`src/layered-settings.ts`).
26
- Observable behavior is unchanged; commits use `refactor:` / `docs:`.
27
-
28
- ## Non-Goals
29
-
30
- - Changing how the widget starts/stops its timer — the spawn tools still call `widget.ensureTimer` / `update` / `markFinished` after this step; that decoupling is Phase 18 Step 4 ([#423]).
31
- - Dropping the `widget` or activity-map constructor params from the `subagent` tool — that is Phase 18 Step 5 ([#424]).
32
- - Touching `record-observer.ts`, `SubagentState`, or the record getters added in Steps 1–2.
33
- - Reconciling the public event contract (Step 6) or any UI-distribution decision (Step 8).
34
-
35
- ## Background
36
-
37
- Relevant modules and their current relationships:
38
-
39
- - `src/ui/agent-activity-tracker.ts` — `AgentActivityTracker` class (active tools, response text, turn count, session ref).
40
- Constructed per-spawn in both spawner tools; written via transition methods; no longer read after [#421].
41
- - `src/ui/ui-observer.ts` — `subscribeUIObserver(session, tracker, onUpdate?)` opens a second session subscription parallel to `record-observer` and streams events into the tracker.
42
- - `src/runtime.ts` — `SubagentRuntime.agentActivity: Map<string, AgentActivityTracker>`, the UI streaming-state map on the core composition root.
43
- - `src/tools/agent-tool.ts` — declares the `AgentActivityAccess` interface and the `AgentToolRuntime.agentActivity` field; passes `this.runtime.agentActivity` into both spawners.
44
- - `src/tools/foreground-runner.ts` — constructs `fgState`, calls `setSession` + `subscribeUIObserver`, populates and deletes the map; its `streamUpdate` already reads activity off the record (`recordRef`), not the tracker.
45
- - `src/tools/background-spawner.ts` — constructs `bgState`, calls `setSession` + `subscribeUIObserver` inside an `observer.onSessionCreated`, populates the map.
46
-
47
- The architecture doc records this as Phase 18 Step 3 (`docs/architecture/architecture.md`, roadmap and step-dependency diagram), with the explicit outcome "−145 LOC, one session subscription per child, runtime holds zero UI state."
48
-
49
- AGENTS.md constraints that apply:
50
-
51
- - Run `pnpm fallow dead-code` locally before pushing — deleting modules can orphan sibling exports.
52
- - pi-subagents is a narrow core with no UI policy; removing UI bookkeeping from the core moves it in the documented direction (dependency arrows point inward).
53
-
54
- ## Design Overview
55
-
56
- This step is a deletion enabled by Step 2, not a new abstraction.
57
- The two structural wins are removing an output-argument pattern (`agentActivity.set(...)` / `.delete(...)` writes into a received map) and narrowing two function signatures by dropping the `agentActivity` parameter.
58
-
59
- ### Foreground runner
60
-
61
- The `observer.onSessionCreated` callback stays — it is still the only place `recordRef` and `fgId` are bound mid-flight (while `spawnAndWait` is in progress) and where `widget.ensureTimer()` fires.
62
- Only the tracker lines are removed.
63
- The post-change callback:
64
-
65
- ```typescript
66
- observer: {
67
- onSessionCreated: (agent) => {
68
- recordRef = agent;
69
- fgId = agent.id;
70
- widget.ensureTimer();
71
- },
72
- },
73
- ```
74
-
75
- The `fgState` construction, the `unsubUI` variable and its two `unsubUI?.()` cleanup calls, and `agentActivity.set` / `agentActivity.delete` all go.
76
- `streamUpdate` is unchanged — it already reads `recordRef?.turnCount`, `recordRef?.activeTools`, `recordRef?.responseText`.
77
- Re-renders are driven by the existing 80 ms spinner interval, which reads fresh record state populated by the core's `record-observer`.
78
-
79
- ### Background spawner
80
-
81
- `onSessionCreated` in the background spawner did **only** tracker work (`bgState.setSession`, `subscribeUIObserver`), so the entire `observer` block is removed from the spawn opts.
82
- The post-spawn `widget.ensureTimer()` and `widget.update()` calls (outside the observer) stay.
83
- The `bgState` construction and `agentActivity.set(id, bgState)` go.
84
-
85
- ### Agent tool
86
-
87
- `AgentTool` stops passing `this.runtime.agentActivity` to both spawners (Step "remove param").
88
- The `AgentActivityAccess` interface, the `AgentToolRuntime.agentActivity` field, and the `import { AgentActivityTracker }` are removed once no caller references them.
89
-
90
- ### Runtime
91
-
92
- `SubagentRuntime.agentActivity` and its `import type { AgentActivityTracker }` are removed, along with the field's doc comment.
93
- The session-context methods and `createSubagentRuntime` are untouched.
94
-
95
- ## Module-Level Changes
96
-
97
- Source:
98
-
99
- - `src/tools/foreground-runner.ts` — remove `AgentActivityTracker` import, `subscribeUIObserver` import, `AgentActivityAccess` import, the `agentActivity` parameter, `fgState`, `unsubUI` (+ both `unsubUI?.()` calls), `agentActivity.set`, `agentActivity.delete`; trim the doc comment that lists "AgentActivityTracker creation, UI observer subscription".
100
- - `src/tools/background-spawner.ts` — remove `AgentActivityTracker` import, `subscribeUIObserver` import, `AgentActivityAccess` import, the `agentActivity` parameter, `bgState`, the entire `observer` block, `agentActivity.set`; trim the doc comment.
101
- - `src/tools/agent-tool.ts` — remove `AgentActivityAccess` interface, `AgentToolRuntime.agentActivity` field, `import { AgentActivityTracker }`, and the two `this.runtime.agentActivity` arguments to `spawnBackground` / `runForeground`.
102
- - `src/runtime.ts` — remove `agentActivity` field (+ doc comment) and `import type { AgentActivityTracker }`.
103
- - `src/types.ts` — reword the `SubscribableSession` doc comment from "Used by record-observer and ui-observer" to reference `record-observer` only.
104
- - `src/ui/agent-activity-tracker.ts` — **delete**.
105
- - `src/ui/ui-observer.ts` — **delete**.
106
-
107
- Tests:
108
-
109
- - `test/ui/agent-activity-tracker.test.ts` — **delete**.
110
- - `test/ui/ui-observer.test.ts` — **delete**.
111
- - `test/tools/foreground-runner.test.ts` — drop the `runtime.agentActivity` argument from every `runForeground(...)` call; remove the "registers activity tracker in agentActivity on session creation" test (redundant with the ensureTimer/markFinished test).
112
- - `test/tools/background-spawner.test.ts` — drop the `runtime.agentActivity` argument from every `spawnBackground(...)` call; remove the "registers an AgentActivityTracker in agentActivity map" test and the `AgentActivityTracker` import.
113
- - `test/tools/agent-tool.test.ts` — remove the "registers activity in agentActivity map" test.
114
- - `test/runtime.test.ts` — remove the "agentActivity map is independently mutable" and "multiple instances are isolated" tests, the two `agentActivity` assertions in "returns correct defaults", and the `AgentActivityTracker` import.
115
- - `test/helpers/make-deps.ts` — remove the `agentActivity` map construction, the `agentActivity` field on the runtime stub, and the `AgentActivityTracker` import; update the runtime doc comment.
116
- - `test/helpers/make-deps.test.ts` — remove the "agentActivity is an empty Map on the runtime" test, the "runtime.agentActivity satisfies AgentActivityAccess" test, and the `AgentActivityTracker` import.
117
-
118
- Docs:
119
-
120
- - `docs/architecture/architecture.md`:
121
- - File tree (around line 350) — remove the `agent-activity-tracker.ts` and `ui-observer.ts` entries.
122
- - "Observation model" prose (around lines 365–368) — drop the "UI streaming … is handled by `ui/ui-observer.ts`" sentence and the stale "widget reads agent state by polling a shared `Map<string, AgentActivityTracker>`" sentence (the widget reads off records since [#421]).
123
- - System diagram (around line 68) — remove the `ui-observer` node.
124
- - Sequence-diagram note (around line 261) — drop "+ ui-observer" so it reads "agent-observer subscribes to session events".
125
- - Phase 18 roadmap Step 3 entry — mark complete (✅) with a `Landed:` bullet, matching the Steps 1–2 format.
126
- - Phase 18 health-metrics table — the "Activity-tier modules slated for removal" row becomes historical; leave the snapshot but ensure the Step 3 `Landed:` bullet records the realized LOC delta.
127
- - `.pi/skills/package-pi-subagents/SKILL.md`:
128
- - Module-dependency-flow block — remove `←─subscribes─ ui-observer` from the `record-observer ─subscribes─→ AgentSession` line.
129
- - Domain table — UI directory count `12 → 10`; domain header "seven domains (59 files)" → "(57 files)".
130
-
131
- Historical docs under `docs/plans/`, `docs/retro/`, and `docs/architecture/history/` reference these symbols as records of past work and are **not** edited.
132
-
133
- ## Test Impact Analysis
134
-
135
- This is a deletion, not an extraction, so it enables no new lower-level tests.
136
-
137
- 1. New tests enabled: none — the deleted modules' behavior is gone, not relocated.
138
- 2. Tests that become redundant: the tracker/observer unit suites (`agent-activity-tracker.test.ts`, `ui-observer.test.ts`) test deleted code and are removed wholesale; the "registers in agentActivity map" tests across `foreground-runner`, `background-spawner`, `agent-tool`, `runtime`, and `make-deps` test removed state and are deleted.
139
- 3. Tests that must stay: the spawner result-text tests, the `ensureTimer` / `markFinished` / `update` widget-driving tests, the foreground streaming-`onUpdate` test, and the runtime session-context tests — they exercise behavior that survives this step.
140
-
141
- ## Invariants at risk
142
-
143
- This step touches surfaces refactored by Phase 18 Steps 1–2.
144
- The relevant prior `Landed:` invariants and the tests that pin them:
145
-
146
- - "no consumer references `AgentActivityTracker`" (Step 2 outcome) — pinned by the type checker: after this step the symbol is deleted, so any surviving reference fails `pnpm run check`.
147
- The foreground `streamUpdate` reading off `recordRef` (Step 2) must remain — covered by `test/tools/foreground-runner.test.ts` "calls onUpdate with streaming details while running".
148
- - "`Subagent` is the single home for all run state; getters available" (Step 1 outcome) — unchanged here; the getters keep their existing coverage in `test/lifecycle/` and `test/observation/`.
149
- - Foreground re-render after dropping the second subscription — pinned by the streaming-`onUpdate` test (spinner-driven tick), confirming re-renders survive without `subscribeUIObserver`.
150
-
151
- No new test is required; the type checker plus the surviving streaming test cover the at-risk invariants.
152
-
153
- ## TDD Order
154
-
155
- This is primarily code deletion; each step is a `refactor:`/`docs:` commit that keeps `pnpm run check` and the full suite green.
156
- Steps are ordered so no commit leaves a dangling type reference.
157
-
158
- 1. **Remove tracker wiring + the `agentActivity` parameter from the spawners.**
159
- Edit `foreground-runner.ts` and `background-spawner.ts` to drop tracker construction, `subscribeUIObserver`/`setSession`, map writes, and the `agentActivity` parameter; update the two `AgentTool` call sites; update `foreground-runner.test.ts` and `background-spawner.test.ts` (drop the arg, remove the "registers tracker" tests and the `AgentActivityTracker` import in the background test).
160
- The parameter removal cascades to call sites and tests at the type level, so they land together.
161
- Run `pnpm run check` immediately after — shared-signature change.
162
- Commit: `refactor: stop wiring activity trackers in the spawn tools (#422)`.
163
-
164
- 2. **Remove the activity map from the runtime and the agent-tool slice.**
165
- Delete `SubagentRuntime.agentActivity` (`runtime.ts`), the `AgentActivityAccess` interface, the `AgentToolRuntime.agentActivity` field, and the `AgentActivityTracker` import in `agent-tool.ts`; update `make-deps.ts` (drop the map + field), and all tests reading the field (`runtime.test.ts`, `make-deps.test.ts`, `agent-tool.test.ts`).
166
- Removing the field and `AgentActivityAccess` export breaks every reader at the type level, so all consumer + test updates land in this commit.
167
- Run `pnpm run check` immediately after.
168
- Commit: `refactor: drop the activity map from the runtime and agent tool (#422)`.
169
-
170
- 3. **Delete the dead modules and their tests.**
171
- Delete `src/ui/agent-activity-tracker.ts`, `src/ui/ui-observer.ts`, `test/ui/agent-activity-tracker.test.ts`, `test/ui/ui-observer.test.ts`; reword the `SubscribableSession` comment in `types.ts`.
172
- Run `pnpm fallow dead-code` to confirm no sibling export (e.g. `SessionLike`, `SubscribableSession`) was orphaned.
173
- Commit: `refactor: delete AgentActivityTracker and ui-observer (#422)`.
174
-
175
- 4. **Update the architecture doc and package skill.**
176
- Apply the doc edits listed in Module-Level Changes (file tree, observation-model prose, system + sequence diagrams, Phase 18 Step 3 ✅ + `Landed:` bullet, SKILL.md flow diagram and domain counts).
177
- Verify any touched Mermaid renders (load the `mermaid` skill).
178
- Commit: `docs: mark Phase 18 Step 3 complete and remove activity-tier references (#422)`.
179
-
180
- ## Risks and Mitigations
181
-
182
- - **Foreground re-render cadence.**
183
- Dropping `subscribeUIObserver` removes event-driven re-renders; updates now rely solely on the 80 ms spinner poll.
184
- The displayed content is identical within ≤80 ms latency (the poll reads the same record the core observer populates), and the spinner already ran at this cadence — no perceptible regression.
185
- Pinned by the streaming-`onUpdate` test.
186
- - **Stale doc references.**
187
- The architecture doc and SKILL.md describe the activity map as current state.
188
- Mitigation: Step 4 grep-driven sweep; the file tree, prose, and two diagrams are all listed explicitly.
189
- - **Orphaned sibling exports.**
190
- Deleting the modules could orphan `SessionLike` or `SubscribableSession`.
191
- Verified during planning: both remain used (`SessionLike` by `subagent-session.ts`; `SubscribableSession` by `record-observer.ts`, `subagent-session.ts`, `types.ts`).
192
- Mitigation: `pnpm fallow dead-code` in Step 3.
193
- - **Commit ordering.**
194
- Removing the field before the spawners stop passing it would break the build.
195
- Mitigation: Step 1 (stop passing) strictly precedes Step 2 (remove field).
196
-
197
- ## Open Questions
198
-
199
- None blocking.
200
- Whether the widget should self-drive from lifecycle events (so the spawners no longer call `ensureTimer`/`update`/`markFinished`) is deferred to Phase 18 Step 4 ([#423]).
201
-
202
- [#421]: https://github.com/gotgenes/pi-packages/issues/421
203
- [#423]: https://github.com/gotgenes/pi-packages/issues/423
204
- [#424]: https://github.com/gotgenes/pi-packages/issues/424