@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,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