@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,306 +0,0 @@
1
- ---
2
- issue: 463
3
- issue_title: "pi-subagents: add file-snapshot source to /subagent-sessions for evicted agents"
4
- ---
5
-
6
- # File-snapshot source for evicted agents in `/subagent-sessions`
7
-
8
- ## Release Recommendation
9
-
10
- **Release:** ship independently
11
-
12
- Architecture roadmap Phase 19 Step 4b ([#463]) carries `Release: independent`.
13
- This is a new capability the bespoke viewer never had — it gates nothing and is not a Step 5 prerequisite — so it ships on its own once landed.
14
-
15
- ## Problem Statement
16
-
17
- The [#445] native-session-navigation slice sources transcripts live, from `manager.listAgents()` only.
18
- The manager's cleanup sweep (`SubagentManager.cleanup()`, every 60 s) disposes a completed/stopped/errored record 10 minutes after it finishes — `disposeSession()` frees the heavy in-memory session (its message history included) and the record is deleted from the map.
19
- The lightweight session JSONL persists on disk at `Subagent.outputFile`, but with no live record the agent is unreachable from `/subagent-sessions`.
20
-
21
- This step makes a fully-evicted agent navigable: it adds the file-snapshot `TranscriptSource` branch the #445 seam was designed for, and broadens the picker's candidate set to include evicted agents.
22
-
23
- ## Goals
24
-
25
- - Implement `fileSnapshotSource(outputFile, readFile)` in `src/ui/session-navigation.ts`: `parseSessionEntries(readFile(outputFile))` → drop the `SessionHeader` → `buildSessionContext(...).messages` → a static (no-subscribe, no-streaming) `TranscriptSource`.
26
- - Broaden the `/subagent-sessions` candidate set to include evicted agents, deduped against live records.
27
- - Render an evicted agent's transcript read-only from its persisted file when picked; the renderer (`buildTranscriptComponents`) and overlay (`TranscriptOverlay`) are untouched.
28
- - Inject `readFile` as a parameter so the pure module performs no `fs` calls.
29
-
30
- This change is **not** breaking: it is additive (a new source branch and a broadened candidate set); no existing behavior, output shape, or default changes for a tracked agent.
31
-
32
- ## Non-Goals
33
-
34
- - No directory scan of the tasks directory and no surfacing of prior-process orphan session files (see Design Overview → Candidate-set decision).
35
- - No change to the cleanup sweep's 10-minute eviction policy or to `disposeSession()`.
36
- - No renderer or overlay changes — `session-navigator.ts`'s `buildTranscriptComponents` / `TranscriptOverlay` / `addMessageComponents` are unchanged (Step 4a, [#462], already brought them to parity).
37
- - No `switchSession` / `loadEntriesFromFile` (rejected by the Step 1 spike, [#446]).
38
- - No live re-read or file-watching of the snapshot — a file source is a static snapshot by design.
39
-
40
- ## Background
41
-
42
- Relevant modules:
43
-
44
- - `src/ui/session-navigation.ts` — the pure, unit-testable core: `NavigableSubagent` (narrow record view), `NavigationEntry`, `TranscriptSource`, `listNavigableAgents(agents, registry)`, `liveSource(record)`, `buildLabel(record, registry)`.
45
- It imports SDK *types* only (`ToolDefinition`) and the lifecycle type `SubagentStatus`.
46
- - `src/ui/session-navigator.ts` — the SDK/TUI consumer half: `SessionNavigatorHandler` (picker + source selection) and `TranscriptOverlay` (read-only scrollable renderer).
47
- The handler already calls `liveSource(entry.record)`; the source is the only seam that varies.
48
- - `src/lifecycle/subagent-manager.ts` — `listAgents()` (sorted live records), `cleanup()` (the 10-minute sweep), `clearCompleted()` (new-session wipe, called from `handlers/lifecycle.ts` on `session_start` / `session_before_switch`), `removeRecord()` (`disposeSession()` + `agents.delete`).
49
- - `src/lifecycle/subagent.ts` — `Subagent` exposes `id`, `type`, `description` (readonly), and getters `status`, `startedAt`, `completedAt`, `toolUses`, `outputFile`.
50
- - `src/index.ts` — registers `subagent-sessions`, calling `sessionNavigator.handle({ ui, agents: manager.listAgents(), registry, cwd })`.
51
-
52
- SDK functions (`@earendil-works/pi-coding-agent`): `parseSessionEntries(content): FileEntry[]`, `buildSessionContext(entries: SessionEntry[]): { messages: AgentMessage[]; … }`, and the types `SessionEntry` / `SessionHeader`.
53
- `FileEntry = SessionHeader | SessionEntry`; only the header has `type: "session"`, so `entries.filter((e): e is SessionEntry => e.type !== "session")` is a sound type guard.
54
- `SessionMessage` (the navigator's message type) is `SessionContext["messages"][number]` = `AgentMessage`, so `buildSessionContext(...).messages` matches `TranscriptSource.getMessages()` with no cast.
55
-
56
- Constraints from AGENTS.md / skills that apply:
57
-
58
- - `code-design` SDK-boundary guideline: pure helpers should avoid SDK *runtime* imports.
59
- `fileSnapshotSource` calls the SDK runtime functions `parseSessionEntries` / `buildSessionContext` directly (see Design Overview → SDK-runtime decision); there is no `no-restricted-imports` lint rule, and the module already depends on SDK types.
60
- - `testing`: components used by `session-navigator.ts` need `initTheme(undefined, false)` in `beforeAll` (already present in `session-navigator.test.ts`).
61
- - `fallow dead-code`: a new export with no caller fails the gate.
62
- Producers (`fileSnapshotSource`, `listEvicted`) gain their caller in the integration step within the same push; the pushed tip is dead-code-clean (see Risks).
63
-
64
- ## Design Overview
65
-
66
- ### Candidate-set decision — manager-retained descriptors (not a directory scan)
67
-
68
- The issue proposes enumerating persisted JSONL files in the tasks directory.
69
- The persisted child session carries **no** subagent `type` or `description` — those live only on the in-memory `Subagent` record; the file holds only the conversation plus a header (`id`, `timestamp`, `cwd`, `parentSession`).
70
- A directory scan therefore yields degraded labels (agent type → generic placeholder; curated `description` → a raw first-prompt snippet or filename) and must parse every file on every picker open.
71
-
72
- Decision (confirmed with the operator): the manager retains a lightweight **descriptor** at eviction time instead.
73
- When `cleanup()` disposes a record that has a persisted file, it first copies the record's label fields plus `outputFile` into a separate `evicted` map (no messages — the heavy state is still freed, so memory stays bounded by the number of subagents spawned, not their transcripts).
74
- The picker's candidate set is `live ∪ evicted`, deduped by id, with identical rich labels for both.
75
-
76
- Coverage: this surfaces agents evicted **in the current root session** — which are the cleanup sweep's only targets.
77
- A fresh `SubagentManager` is created per session and `clearCompleted()` runs on `session_start`, so prior-process subagents are never reloaded into the manager; the only files a directory scan would *additionally* surface are old-session orphans, which are exactly the ones with degraded labels.
78
- Picking an evicted agent still reads its file to render (the messages are gone from memory regardless) — so `fileSnapshotSource` is required either way; the descriptor only feeds the *label*.
79
-
80
- ### SDK-runtime decision — call `parseSessionEntries` / `buildSessionContext` directly
81
-
82
- `fileSnapshotSource` imports and calls these SDK runtime functions directly rather than injecting them.
83
- Rationale: they are deterministic parsers of Pi's own session format; the injected `readFile` already provides the unit-test seam (a fake `readFile` returning fixture JSONL fully exercises parse → drop-header → build → messages), so injecting the parsers adds wiring without testability gain.
84
- There is no `no-restricted-imports` rule, and `session-navigation.ts` already imports SDK types.
85
-
86
- ### Data shapes
87
-
88
- `EvictedSubagent` — the descriptor, owned by lifecycle (the manager constructs it), imported as a type by the UI (the UI already imports `SubagentStatus` from lifecycle):
89
-
90
- ```typescript
91
- // src/lifecycle/subagent-manager.ts
92
- export interface EvictedSubagent {
93
- readonly id: string;
94
- readonly type: SubagentType;
95
- readonly description: string;
96
- readonly status: SubagentStatus;
97
- readonly startedAt: number;
98
- readonly completedAt: number | undefined;
99
- readonly toolUses: number;
100
- readonly outputFile: string;
101
- }
102
- ```
103
-
104
- `NavigationEntry` changes from `{ record, label }` to a discriminated union so the handler can pick the source by kind:
105
-
106
- ```typescript
107
- // src/ui/session-navigation.ts
108
- export type NavigationEntry =
109
- | { readonly kind: "live"; readonly label: string; readonly record: NavigableSubagent }
110
- | { readonly kind: "evicted"; readonly label: string; readonly outputFile: string };
111
- ```
112
-
113
- `buildLabel` is narrowed to a per-call interface (ISP) that both a `NavigableSubagent` and an `EvictedSubagent` satisfy, and gains an `evicted` marker:
114
-
115
- ```typescript
116
- interface LabelFields {
117
- readonly type: SubagentType;
118
- readonly description: string;
119
- readonly status: SubagentStatus;
120
- readonly startedAt: number;
121
- readonly completedAt: number | undefined;
122
- readonly toolUses: number;
123
- }
124
-
125
- function buildLabel(fields: LabelFields, registry: AgentConfigLookup, evicted = false): string {
126
- const name = getDisplayName(fields.type, registry);
127
- const duration = formatDuration(fields.startedAt, fields.completedAt);
128
- const marker = evicted ? " · evicted (snapshot)" : "";
129
- return `${name} (${fields.description}) · ${fields.toolUses} tools · ${fields.status} · ${duration}${marker}`;
130
- }
131
- ```
132
-
133
- ### `fileSnapshotSource`
134
-
135
- ```typescript
136
- export function fileSnapshotSource(
137
- outputFile: string,
138
- readFile: (path: string) => string,
139
- ): TranscriptSource {
140
- const entries = parseSessionEntries(readFile(outputFile));
141
- const sessionEntries = entries.filter(
142
- (entry): entry is SessionEntry => entry.type !== "session",
143
- );
144
- const { messages } = buildSessionContext(sessionEntries);
145
- return {
146
- getMessages: () => messages,
147
- subscribe: () => undefined, // static snapshot — no live updates
148
- streaming: () => undefined, // never streaming
149
- getToolDefinition: () => undefined, // no live tool registry off disk
150
- };
151
- }
152
- ```
153
-
154
- ### `listNavigableAgents` (broadened) and the handler call site
155
-
156
- ```typescript
157
- export function listNavigableAgents(
158
- agents: readonly NavigableSubagent[],
159
- evicted: readonly EvictedSubagent[],
160
- registry: AgentConfigLookup,
161
- ): NavigationEntry[] {
162
- const live = agents
163
- .filter((record) => record.isSessionReady())
164
- .map((record): NavigationEntry => ({ kind: "live", record, label: buildLabel(record, registry) }));
165
- const liveIds = new Set(agents.map((record) => record.id));
166
- const evictedEntries = evicted
167
- .filter((d) => !liveIds.has(d.id))
168
- .map((d): NavigationEntry => ({ kind: "evicted", outputFile: d.outputFile, label: buildLabel(d, registry, true) }));
169
- return [...live, ...evictedEntries];
170
- }
171
- ```
172
-
173
- Dedup is keyed by `id` (both shapes carry it) rather than `outputFile`: a record leaves `listAgents()` at the same instant its descriptor is captured, so the sets cannot overlap; the filter is defensive.
174
- Order is live-then-evicted, which is already recency-ordered (evicted agents completed > 10 min ago).
175
-
176
- Handler consumer sketch (Tell-Don't-Ask: the entry tells the handler its kind; the handler asks the right source constructor — no reach-through into the record's internals):
177
-
178
- ```typescript
179
- const entry = entries.find((candidate) => candidate.label === choice);
180
- if (!entry) return;
181
- let source: TranscriptSource;
182
- try {
183
- source = entry.kind === "live" ? liveSource(entry.record) : fileSnapshotSource(entry.outputFile, readFile);
184
- } catch {
185
- ui.notify("Could not read the session transcript file.", "error");
186
- return;
187
- }
188
- // …unchanged: getMarkdownTheme(), ui.custom(new TranscriptOverlay({ source, … }))
189
- ```
190
-
191
- ### Manager retention sketch
192
-
193
- ```typescript
194
- private readonly evicted = new Map<string, EvictedSubagent>();
195
-
196
- private cleanup() {
197
- const cutoff = Date.now() - 10 * 60_000;
198
- for (const [id, record] of this.agents) {
199
- if (record.status === "running" || record.status === "queued") continue;
200
- if ((record.completedAt ?? 0) >= cutoff) continue;
201
- if (record.outputFile) this.evicted.set(id, toEvictedSubagent(record));
202
- this.removeRecord(id, record);
203
- }
204
- }
205
-
206
- listEvicted(): EvictedSubagent[] {
207
- return [...this.evicted.values()].sort((a, b) => b.startedAt - a.startedAt);
208
- }
209
- ```
210
-
211
- `clearCompleted()` and `dispose()` also `this.evicted.clear()` — descriptors belong to the session that evicted them, so a new session starts empty.
212
- `toEvictedSubagent(record)` copies the eight fields; it is a private helper (or a free function in the module) and reads `record.outputFile` only after the `if (record.outputFile)` guard, so the `outputFile` field is always a defined `string`.
213
-
214
- ### Edge cases
215
-
216
- - **`outputFile` undefined at eviction** (headless / never-persisted session) → no descriptor captured; nothing to navigate.
217
- - **File deleted/unreadable after eviction** → `fileSnapshotSource`'s eager read throws; the handler's `try/catch` notifies and returns without opening the overlay.
218
- - **Empty or header-only JSONL** → `buildSessionContext` returns `messages: []`; the overlay renders an empty transcript (no crash).
219
- - **No navigable sessions at all** (no live, no evicted) → existing `ui.notify("No subagent sessions to view.", "info")` path, unchanged.
220
-
221
- ## Module-Level Changes
222
-
223
- - `src/lifecycle/subagent-manager.ts` — add the `EvictedSubagent` interface (exported), the `evicted` map field, descriptor capture in `cleanup()`, `evicted.clear()` in `clearCompleted()` and `dispose()`, the `listEvicted()` method, and the `toEvictedSubagent` helper.
224
- Import `SubagentType` (already in `#src/types`) and `SubagentStatus` (`#src/lifecycle/subagent-state`) for the interface.
225
- - `src/ui/session-navigation.ts` — add `fileSnapshotSource`; import `EvictedSubagent` (type), and the SDK runtime `parseSessionEntries` / `buildSessionContext` plus the `SessionEntry` type; change `NavigationEntry` to the discriminated union; broaden `listNavigableAgents` to `(agents, evicted, registry)`; narrow `buildLabel` to `LabelFields` + `evicted` flag.
226
- - `src/ui/session-navigator.ts` — `SessionNavigatorParams` gains `evicted: readonly EvictedSubagent[]` and `readFile: (path: string) => string`; the handler selects the source by `entry.kind` inside a `try/catch`.
227
- No change to `TranscriptOverlay`, `buildTranscriptComponents`, `addMessageComponents`, or `addUserComponents`.
228
- - `src/index.ts` — add `import { readFileSync } from "node:fs"`; the `subagent-sessions` handler passes `evicted: manager.listEvicted()` and `readFile: (path) => readFileSync(path, "utf8")`.
229
- - `docs/architecture/architecture.md` — mark Step 4b ([#463]) **Landed** with a note recording the descriptor-vs-scan decision and that ADR-0004 Addendum 2's dual-source design is now realized; flip the `S4b` node label in the step-dependency Mermaid diagram to ✅.
230
- - `docs/decisions/0004-reconsider-ui-direction.md` — optional one-line note under Addendum 2 that Step 4b chose manager-retained descriptors over a directory scan (the addendum's "evicted/untracked" wording said file snapshot for *rendering*, which still holds; only the *candidate-set* mechanism is being pinned down).
231
-
232
- No SKILL update: the package SKILL's UI section references no session-navigation internals and the file/domain counts are unchanged (no new module — `fileSnapshotSource` joins the existing `session-navigation.ts`).
233
- The architecture LOC/complexity tables are explicit end-of-phase snapshots, not per-file inventories, so a ~30-LOC addition does not update them.
234
-
235
- ## Test Impact Analysis
236
-
237
- 1. **New unit tests enabled by this change:**
238
- - `fileSnapshotSource` (pure, in `session-navigation.test.ts`): fixture JSONL via a fake `readFile` → assert `getMessages()` equals the parsed messages, the `SessionHeader` is dropped, and `subscribe()` / `streaming()` / `getToolDefinition()` return `undefined`.
239
- - `listNavigableAgents` with evicted descriptors: evicted entries appear with the `· evicted (snapshot)` marker; an evicted descriptor whose id matches a live record is deduped out.
240
- - `SubagentManager.listEvicted()` (in `subagent-manager.test.ts`): after advancing fake timers past the cutoff, a completed agent with an `outputFile` produces a descriptor; one without an `outputFile` does not; `clearCompleted()` empties the set.
241
- - `SessionNavigatorHandler` evicted path (in `session-navigator.test.ts`): picking an evicted label opens an overlay sourced from `readFile`; a throwing `readFile` notifies and skips the overlay.
242
- 2. **Tests that become redundant:** none — the live-source tests still exercise the tracked-agent branch.
243
- 3. **Tests that must stay as-is:** the existing `liveSource`, `listNavigableAgents` (live-only), `TranscriptOverlay`, and live-source handler tests — they pin the tracked-agent behavior this change must not regress.
244
-
245
- ## Invariants at risk
246
-
247
- Step 4 (#445) and Step 4a (#462) established invariants on the navigation surface; this step must preserve them:
248
-
249
- - **Handler is a reactive consumer with no inbound call into the core** (Invariant #423/#445).
250
- Pinned by the existing `session-navigator.test.ts` assertion `expect(record.getToolDefinition).not.toHaveBeenCalled()` in the live-source handler test.
251
- The evicted path reads only `entry.outputFile` (a string) + the injected `readFile`; it makes no inbound call into a record.
252
- - **Read-only, non-interactive overlay** (#445/#446).
253
- The file source returns `subscribe: () => undefined` and `streaming: () => undefined`; the overlay's existing read-only behavior is unchanged.
254
- Pinned by the existing overlay tests.
255
- - **Renderer parity via Pi per-entry components** (#462).
256
- The renderer is untouched; both sources still yield `SessionMessage[]` into the same `buildTranscriptComponents`.
257
- Pinned by the existing `TranscriptOverlay` render tests.
258
-
259
- No new test is needed for these — existing tests already pin them; the integration step keeps them green.
260
-
261
- ## TDD Order
262
-
263
- 1. **`fileSnapshotSource` (pure, additive).**
264
- Surface: `test/ui/session-navigation.test.ts`.
265
- Red: a `describe("fileSnapshotSource")` with a fake `readFile` returning fixture JSONL (a `session` header line + a couple of `message` entries) — assert messages parsed, header dropped, and the three static-source methods return `undefined`.
266
- Green: implement `fileSnapshotSource` and the SDK runtime imports.
267
- Commit: `test(pi-subagents): cover file-snapshot transcript source` then `feat(pi-subagents): add file-snapshot transcript source` (or a single `feat` commit with test + impl).
268
- 2. **Manager evicted-descriptor retention (additive).**
269
- Surface: `test/lifecycle/subagent-manager.test.ts`.
270
- Red: with fake timers, advance past the 10-minute cutoff and assert `listEvicted()` returns a descriptor for a completed agent with an `outputFile`, none for one without, and an empty set after `clearCompleted()`.
271
- Green: add `EvictedSubagent`, the `evicted` map, capture in `cleanup()`, `clear()` in `clearCompleted()`/`dispose()`, `listEvicted()`, and `toEvictedSubagent`.
272
- Run `pnpm run check` after this commit (new exported interface).
273
- Commit: `feat(pi-subagents): retain evicted-agent descriptors in the manager`.
274
- 3. **Integrate: broaden the candidate set and dual-source the handler (breaking the `NavigationEntry` shape).**
275
- This step changes `NavigationEntry` and `listNavigableAgents`'s signature, so the handler, `index.ts` call site, and both UI test files break and are updated together.
276
- Surfaces: `src/ui/session-navigation.ts`, `src/ui/session-navigator.ts`, `src/index.ts`, `test/ui/session-navigation.test.ts`, `test/ui/session-navigator.test.ts`.
277
- Red: update `listNavigableAgents` tests to the union shape and add the evicted-entry (marker + dedup) cases; add the handler evicted-path tests (file source + throwing-`readFile` notify).
278
- Green: change `NavigationEntry` to the union, broaden `listNavigableAgents`, narrow `buildLabel`, add `evicted` + `readFile` to `SessionNavigatorParams`, switch the handler source by kind inside `try/catch`, and wire `manager.listEvicted()` + `readFileSync` in `index.ts`.
279
- Run `pnpm run check` (shared interface change with a single non-test call site).
280
- Commit: `feat(pi-subagents): source evicted-agent transcripts from disk in /subagent-sessions`.
281
- 4. **Docs.**
282
- Update `docs/architecture/architecture.md` Step 4b to Landed (descriptor decision + dual-source realized) and the `S4b` diagram node to ✅; add the optional Addendum 2 note in `docs/decisions/0004-reconsider-ui-direction.md`.
283
- Commit: `docs(pi-subagents): mark Phase 19 Step 4b landed (#463)`.
284
-
285
- ## Risks and Mitigations
286
-
287
- - **Transient dead code between steps 1–2 and 3.**
288
- `fileSnapshotSource` and `listEvicted()` have no caller until step 3.
289
- CI / pre-completion `fallow dead-code` runs on the pushed tip, which is clean once step 3 lands; all steps ship in one push.
290
- Mitigation: do not run `/ship-issue` before step 3 is committed.
291
- - **`buildSessionContext` / `parseSessionEntries` behavior on malformed JSONL.**
292
- Mitigation: the handler `try/catch` covers a throwing read/parse; a TDD fixture exercises a valid header-plus-messages file, and an empty-messages case confirms a graceful empty render.
293
- - **Memory: the `evicted` map grows over a long session.**
294
- Each descriptor is eight scalar fields (no messages), bounded by subagents spawned; the heavy session objects are still disposed.
295
- `clearCompleted()` resets it per session.
296
- - **Divergence from the issue's "enumerate persisted JSONL files" wording.**
297
- Documented and operator-confirmed (descriptors over scan, for rich labels and bounded IO); the architecture/ADR notes record the rationale so the file-scan option is not silently lost.
298
-
299
- ## Open Questions
300
-
301
- None — the candidate-set strategy and the evicted-entry marker were resolved with the operator during planning.
302
-
303
- [#445]: https://github.com/gotgenes/pi-packages/issues/445
304
- [#446]: https://github.com/gotgenes/pi-packages/issues/446
305
- [#462]: https://github.com/gotgenes/pi-packages/issues/462
306
- [#463]: https://github.com/gotgenes/pi-packages/issues/463
@@ -1,44 +0,0 @@
1
- ---
2
- issue: 48
3
- issue_title: "feat: implement and publish SubagentsService at extension init"
4
- ---
5
-
6
- # Retro: #48 — implement and publish SubagentsService at extension init
7
-
8
- ## Final Retrospective (2026-05-17T15:30:00Z)
9
-
10
- ### Session summary
11
-
12
- Planned and implemented a typed `SubagentsService` interface with `Symbol.for()` accessor functions, an adapter wrapping `AgentManager` with model resolution and record serialization, and wired it into the extension init.
13
- Released as `@gotgenes/pi-subagents@4.0.0` (breaking: old untyped global removed).
14
- The plan was revised mid-session to align naming with `pi-permission-system`'s established conventions after the user flagged the discrepancy.
15
-
16
- ### Observations
17
-
18
- #### What went well
19
-
20
- - TDD execution was clean: 8 steps, zero rework, all 33 new tests green on first pass.
21
- - The adapter design was well-scoped — `index.ts` wiring was +16/−12 lines, and the narrow `AgentManagerLike` interface made test mocks trivial.
22
- - The allowlist serialization pattern (`toSubagentRecord`) prevents future leaks of non-serializable fields by default.
23
-
24
- #### What caused friction (agent side)
25
-
26
- - `missing-context` — The initial plan adopted the issue body's naming verbatim (`SubagentsAPI`, `api.ts`, `pi:service:subagents`, `(globalThis as any)`) without checking `pi-permission-system` for the established convention (`SubagentsService`, `service.ts`, `@gotgenes/<pkg>:service`, `Record<symbol, unknown>`).
27
- The user had to explicitly ask "Does this structure follow the pattern set forth by pi-permission-system?"
28
- Impact: full plan rewrite (replaced entire file), issue title update, issue body update — ~15 minutes of rework across 3 user turns.
29
- This was **user-caught**.
30
-
31
- - `missing-context` — Same pattern as the #49 retro: following the issue spec literally without checking the codebase.
32
- The architecture doc also used the stale naming, reinforcing the wrong choice.
33
- Root cause: the "Gather context" step in `/plan-issue` didn't include a cross-package convention check.
34
-
35
- #### What caused friction (user side)
36
-
37
- - The user had to perform mechanical oversight ("Does this follow the pi-permission-system pattern?") that the planner should have caught independently.
38
- If the `/plan-issue` prompt included a step to grep sibling packages for established API patterns, this would have been a design decision surfaced during planning rather than a correction after the fact.
39
-
40
- ### Changes made
41
-
42
- 1. Created `packages/pi-subagents/docs/retro/0048-implement-subagents-api.md` (this file).
43
- 2. Updated `.pi/skills/package-pi-subagents/SKILL.md` — changed `SubagentsAPI` → `SubagentsService` in Implementation Priorities; added `service.ts` and `service-adapter.ts` to module dependency graph and descriptions.
44
- 3. Updated `.pi/prompts/plan-issue.md` — added step 7 to Gather context: check sibling packages for established API patterns before adopting issue body naming.
@@ -1,49 +0,0 @@
1
- ---
2
- issue: 49
3
- issue_title: "feat: remove group-join, output-file, and ad-hoc RPC"
4
- ---
5
-
6
- # Retro: #49 — remove group-join, output-file, and ad-hoc RPC
7
-
8
- ## Final Retrospective (2026-05-17T15:15:00Z)
9
-
10
- ### Session summary
11
-
12
- Planned and implemented the removal of group-join and ad-hoc RPC from `pi-subagents`, releasing v3.0.0.
13
- The original scope included `output-file.ts` removal, but the user intervened to retain it for post-hoc debugging value.
14
- A new issue (#61) was filed to port the output-file format to Pi's official JSONL session schema.
15
-
16
- ### Observations
17
-
18
- #### What went well
19
-
20
- - User intervention produced a materially better outcome — retaining debugging transcripts and identifying a format conformance gap that became #61.
21
- - TDD execution was clean: 6 steps, zero rework, all tests green on first pass after each step.
22
- - The `feat!:` → release-please → v3.0.0 pipeline worked smoothly end-to-end.
23
-
24
- #### What caused friction (agent side)
25
-
26
- - `missing-context` — Included `output-file.ts` removal in the initial plan without questioning its debugging value, despite AGENTS.md's rule "Ask before removing functionality or changing defaults."
27
- The issue body explicitly listed it for removal so I followed the spec literally.
28
- Impact: required plan revision (amend commit), scope-narrowing comment on issue, and filing #61 — roughly 10 minutes of rework, but produced a better design.
29
-
30
- - `missing-context` — When asked whether output-file adheres to Pi's session format, searched the web (`web_search` for "Claude Code session JSONL format") instead of checking the local `~/development/pi/pi` monorepo.
31
- The user had to explicitly say "~/development/pi/pi has the code for Pi's JSONL format."
32
- Impact: one extra round-trip and less authoritative initial answer (Claude Code's format vs Pi's `SessionManager`).
33
- Self-identified after user redirect.
34
-
35
- - `instruction-violation` (self-identified) — Shell-escaped the `gh issue comment` body incorrectly; backtick-wrapped `src/output-file.ts` was interpreted by bash.
36
- Caught immediately via `gh issue view` and fixed with `--edit-last`.
37
- Impact: trivial — one extra command.
38
-
39
- #### What caused friction (user side)
40
-
41
- - The issue body listed output-file for removal without noting its debugging value.
42
- The user's "How confident are we in getting rid of the logging system?"
43
- intervention was the correction.
44
- If the issue had marked output-file removal as "tentative pending debugging value assessment," the plan would have surfaced it as a design decision from the start.
45
- Minor — the discussion was quick and productive.
46
-
47
- ### Changes made
48
-
49
- 1. Created `packages/pi-subagents/docs/retro/0049-remove-group-join-output-file-rpc.md` (this file).
@@ -1,39 +0,0 @@
1
- ---
2
- issue: 51
3
- issue_title: "docs: update ADR 0001 to reflect hard-fork decision"
4
- ---
5
-
6
- # Retro: #51 — docs: update ADR-0001 to reflect hard-fork decision
7
-
8
- ## Final Retrospective (2026-05-16)
9
-
10
- ### Session summary
11
-
12
- Updated [ADR-0001] to reflect the hard-fork decision documented in `docs/architecture/architecture.md`.
13
- The change was planned, implemented, shipped, and released as `pi-subagents-v1.0.2` in a single clean pass with no rework.
14
-
15
- ### Observations
16
-
17
- #### What went well
18
-
19
- - The entire plan→build→ship pipeline completed with zero corrections, zero CI failures, and zero user interventions.
20
- - Parallel context gathering (issue body, `AGENTS.md`, ADR file, architecture doc, two skill files) in one tool call made the planning phase efficient.
21
- - The 4-edit approach (`Edit` with a single call containing four `edits[]` entries) was well-matched to the task — each edit was small, unique, and non-overlapping.
22
-
23
- #### What caused friction (agent side)
24
-
25
- - No friction observed.
26
- The task was unambiguous and the tooling well-suited.
27
-
28
- #### What caused friction (user side)
29
-
30
- - No friction observed.
31
- The session required no user input beyond invoking the three slash commands.
32
-
33
- ### Follow-ups identified
34
-
35
- - The `package-pi-subagents` skill (`.pi/skills/package-pi-subagents/SKILL.md`) still frames the fork as "a friendly fork… carrying a small number of patches" with priorities like "stays as close to upstream as possible."
36
- This framing is now stale given the hard-fork commitment.
37
- A separate issue should update the skill to reflect the architecture document's posture.
38
-
39
- [ADR-0001]: ../decisions/0001-deferred-patches.md
@@ -1,40 +0,0 @@
1
- ---
2
- issue: 53
3
- issue_title: "refactor: extract model resolution from Agent.execute"
4
- ---
5
-
6
- # Retro: #53 — extract model resolution from Agent.execute
7
-
8
- ## Final Retrospective (2026-05-17T21:00:00Z)
9
-
10
- ### Session summary
11
-
12
- Planned and executed the extraction of inline model-resolution logic from `Agent.execute` in `index.ts` into a new `resolveInvocationModel()` function in `model-resolver.ts`.
13
- Released as `pi-subagents-v4.1.0` with +10 new unit tests and no behavior change.
14
- Also fixed a pre-existing `rumdl` glob-quoting bug in `package.json` discovered during the lint step.
15
-
16
- ### Observations
17
-
18
- #### What went well
19
-
20
- - Pre-existing lint bug surfaced and fixed: the `rumdl check '*.md' 'docs/**/*.md'` command in `package.json` used single-quoted globs that prevented shell expansion.
21
- Verified as pre-existing (reproduced on prior commit via `git stash`), cleanly isolated into its own `fix:` commit.
22
- This was a genuine find — the lint had been silently broken.
23
-
24
- #### What caused friction (agent side)
25
-
26
- - `missing-context` — In step 6 (refactoring `index.ts`), replaced the `resolveModel` import with `resolveInvocationModel` without first checking whether `resolveModel` was still used elsewhere in the file.
27
- Two other call sites (`createSubagentsService` at line 386 and `getModelLabel` at line 1043) still needed it.
28
- The plan explicitly listed `getModelLabel` as a non-goal that continues using `resolveModel`, so the information was available.
29
- Caught immediately via `grep` after the edit and fixed in the same commit.
30
- Impact: one extra edit + grep cycle, no rework.
31
-
32
- - `missing-context` — The plan's type definitions specified `model: unknown` for `ModelResolutionResult`, but downstream code in `index.ts` accesses `.id` and `.name` on the model and passes it where `Model<any>` is expected.
33
- The plan's risk section flagged this ("reducing but not eliminating the `any`"), yet the implementation went with `unknown` first, requiring a correction after `pnpm run check` failed with 4 type errors.
34
- Changed to `model: any` to match the existing `resolveModel` return type.
35
- Impact: one extra edit cycle within the same commit, no rework.
36
-
37
- #### What caused friction (user side)
38
-
39
- - None observed.
40
- The issue was well-scoped with clear acceptance criteria, making planning and execution straightforward.
@@ -1,53 +0,0 @@
1
- ---
2
- issue: 54
3
- issue_title: "refactor: decompose src/index.ts into tool + menu modules"
4
- ---
5
-
6
- # Retro: #54 — decompose index.ts into tool + menu modules
7
-
8
- ## Final Retrospective (2026-05-18T02:20:00Z)
9
-
10
- ### Session summary
11
-
12
- Decomposed `src/index.ts` from 1,619 lines to 265 lines across 8 commits.
13
- Extracted 7 new modules (`tools/helpers.ts`, `renderer.ts`, `notification.ts`, `tools/agent-tool.ts`, `tools/get-result-tool.ts`, `tools/steer-tool.ts`, `ui/agent-menu.ts`) with 66 new tests (379 → 445 total).
14
- Released as `pi-subagents-v4.1.1`.
15
- Filed follow-up #66 (replace `as any` casts with proper SDK types) and #67 (flaky `pi-autoformat` acceptance test).
16
-
17
- ### Observations
18
-
19
- #### What went well
20
-
21
- - Leaf-first extraction order worked cleanly — helpers, then renderer, then notification, then tools, then menu.
22
- Each step left the repo green with no cascading breakage.
23
- - The `createNotificationSystem` factory pattern with arrow-closure capture of `widget` (assigned after `AgentManager` construction) preserved the existing deferred-reference semantics without restructuring initialization order.
24
-
25
- #### What caused friction (agent side)
26
-
27
- - `wrong-abstraction` — Applied the code-style skill's "keep Pi SDK imports out of business-logic modules" rule to tool/menu modules, which are SDK consumers, not business logic.
28
- Used `unknown` for `ExtensionContext`, `AgentSession`, `ModelRegistry` in factory dep interfaces, requiring 9 `as any` casts in `index.ts`.
29
- User caught this post-ship.
30
- Impact: filed #66 as a follow-up cleanup; the casts are cosmetic (no runtime effect) but degrade type safety.
31
- Fixed the code-style skill to clarify the boundary. (user-caught)
32
-
33
- - `missing-context` — Four test files (`notification.test.ts`, `get-result-tool.test.ts`, `steer-tool.test.ts`, `agent-tool.test.ts`) omitted `compactionCount: 0` from `AgentRecord` factories.
34
- Caught at the final `pnpm run check` step, not during test writing.
35
- The testing skill already says "grep for ALL test files that construct a compatible mock."
36
- Impact: one extra fix cycle delegated to a subagent, no rework beyond that step. (self-identified)
37
-
38
- - `other` — `Edit` tool failed 3 times matching the UTF-8 middle dot (`·`, U+00B7) in the steer tool's `stateParts.join(" · ")` line.
39
- The third attempt produced a partial match that left the file in a broken state (dangling orphan code after the replacement anchor).
40
- Required `git restore` and a fallback to `python3` line-range replacement.
41
- The same `python3` approach for the menu extraction lost the closing `}` of the default export function.
42
- Impact: ~5 minutes of rework across the two extraction steps, plus one `git restore`.
43
-
44
- #### What caused friction (user side)
45
-
46
- - The `as any` casts could have been caught earlier if the user had flagged the `unknown` types during the planning phase.
47
- However, the plan didn't prescribe exact interface types — that was an implementation decision.
48
- The user's post-ship review ("Why did we have to cast `as any`?
49
- Take a look at `packages/pi-permission-system/` as a model") was an efficient redirect that immediately scoped the investigation.
50
-
51
- ### Changes made
52
-
53
- 1. `.pi/skills/code-style/SKILL.md` — Clarified SDK-boundary guidance: tool definitions, event handlers, and command handlers may import SDK types directly; the restriction targets pure helpers and domain modules.
@@ -1,77 +0,0 @@
1
- ---
2
- issue: 57
3
- issue_title: "feat: structured debug logging for silenced catch blocks"
4
- ---
5
-
6
- # Retro: #57 — structured debug logging for silenced catch blocks
7
-
8
- ## Final Retrospective (2026-05-19T10:30:00Z)
9
-
10
- ### Session summary
11
-
12
- Added `src/debug.ts` with `debugLog` and `isDebug()`, then threaded `debugLog` into ~20 silent `catch` blocks across 9 files.
13
- All 7 TDD cycles went green on the first pass with no rework.
14
- Shipped as `pi-subagents-v5.1.0`, then followed up with a `refactor:` commit converting `DEBUG` (module-level constant) to `isDebug()` (function getter) during the retro.
15
-
16
- ### Observations
17
-
18
- #### What went well
19
-
20
- - The plan's "Non-Goals" section correctly excluded `usage.ts` and `settings.ts` before implementation started, and a post-TDD `grep -rn 'catch\s*{'` confirmed only those two in-scope-excluded files remained.
21
- Closing the loop with a verification query is worth repeating.
22
- - The scope of the change was so well-defined (the issue listed exact file names) that no `ask_user` call was needed during planning.
23
-
24
- #### What caused friction (agent side)
25
-
26
- - `missing-context` — When loading the `ask-user` skill I guessed `.pi/skills/ask-user/SKILL.md` before reading the actual `<location>` tag in `AGENTS.md`, triggering an ENOENT error and a follow-up `find` call.
27
- Impact: 2 extra tool calls, no rework. (self-identified)
28
-
29
- - `other` — The plan's TDD Order step 1 stated *"the test skill documents this pattern"* for `vi.resetModules()` + dynamic import when testing module-level env constants — but the testing skill does not have that entry.
30
- The aspiration was recorded rather than verified.
31
- During the retro, the user's question ("should that be a function getter instead?") led to a better outcome: replace the module-level constant with `isDebug()` so `vi.stubEnv()` alone works, consistent with how every other `process.env` read in this codebase is structured.
32
- Impact: one retro-phase `refactor:` commit; the approach shipped in `v5.1.0` was technically correct but unnecessarily complex to test.
33
-
34
- #### What caused friction (user side)
35
-
36
- - The initial issue proposal chose the module-level-constant pattern (common in Node.js tooling like the `debug` package).
37
- A note in the issue or plan about preferring function-based env reads for testability would have caught this at design time rather than post-ship.
38
- That said, the retro question was efficient — a single targeted redirect resolved it cleanly.
39
-
40
- ### Changes made
41
-
42
- 1. `packages/pi-subagents/src/debug.ts` — replaced `export const DEBUG` with `export function isDebug()`.
43
- 2. `packages/pi-subagents/test/debug.test.ts` — simplified to static import + `vi.stubEnv()` only; removed all `vi.resetModules()` + dynamic `import()` calls.
44
- 3. `.pi/skills/testing/SKILL.md` — added bullet: prefer reading `process.env` inside functions; `vi.stubEnv()` alone is insufficient for module-level constants.
45
-
46
- ## Follow-up Retrospective (2026-05-19T11:15:00Z)
47
-
48
- ### Session summary
49
-
50
- The user asked how many `process.*` reads exist in `pi-subagents`.
51
- Audit found 9 sites: 4 acceptable (wiring layer, detection functions, injectable defaults), 2 genuine injection gaps, and 1 mild case.
52
- Filed #76 (`AgentManager.dispose()` reads `process.cwd()` without a stored `cwd`) and #77 (`createAgentsMenuHandler` hardcodes `process.cwd()` when `AgentMenuDeps` already injects the personal-side equivalent).
53
-
54
- ### Observations
55
-
56
- #### What went well
57
-
58
- - The `isDebug()` refactor naturally led the user to ask a broader design question about `process.*` access patterns, producing two well-scoped follow-up issues without manual triage.
59
- - The audit categorization (genuinely problematic vs. acceptable) was clean — presenting a table with verdicts per site let the user decide scope without re-reading source.
60
-
61
- #### What caused friction (agent side)
62
-
63
- - `premature-convergence` — The original plan accepted the module-level `DEBUG` constant without checking how the rest of the codebase reads `process.env`.
64
- The code-style skill said "keep IO at the edges" but didn't name `process.*` specifically, so the rule wasn't applied.
65
- Impact: one post-ship `refactor:` commit to replace `DEBUG` with `isDebug()`; the pattern was technically correct but inconsistent with codebase conventions. (user-caught)
66
-
67
- #### What caused friction (user side)
68
-
69
- - Nothing notable.
70
- The user's two redirecting questions ("should that be a function?"
71
- and "how many places access `process.*`?") were well-timed interventions that broadened scope productively.
72
-
73
- ### Changes made
74
-
75
- 1. `.pi/skills/code-style/SKILL.md` — added bullet: do not read `process.env`, `process.cwd()`, or `process.platform` inside library/utility functions; accept the value as a parameter.
76
- 2. Filed #76 — inject `cwd` into `AgentManager` constructor.
77
- 3. Filed #77 — add `projectAgentsDir` to `AgentMenuDeps`.