@gotgenes/pi-subagents 18.0.1 → 18.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (260) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/docs/architecture/architecture.md +157 -204
  3. package/docs/architecture/history/phase-19-implement-ui-decisions.md +282 -0
  4. package/package.json +5 -6
  5. package/src/lifecycle/subagent.ts +5 -9
  6. package/src/observation/notification.ts +23 -10
  7. package/src/observation/subagent-events-observer.ts +1 -3
  8. package/src/tools/get-result-report.ts +60 -0
  9. package/src/tools/get-result-tool.ts +25 -40
  10. package/src/types.ts +1 -1
  11. package/src/ui/session-navigator.ts +0 -2
  12. package/.prettierignore +0 -5
  13. package/AGENTS.md +0 -7
  14. package/docs/plans/0048-implement-subagents-api.md +0 -304
  15. package/docs/plans/0049-remove-group-join-output-file-rpc.md +0 -180
  16. package/docs/plans/0051-update-adr-0001-hard-fork.md +0 -77
  17. package/docs/plans/0052-remove-scheduled-subagents.md +0 -133
  18. package/docs/plans/0053-extract-model-resolution-from-execute.md +0 -181
  19. package/docs/plans/0054-decompose-index-into-modules.md +0 -302
  20. package/docs/plans/0057-structured-debug-logging.md +0 -154
  21. package/docs/plans/0061-session-format-transcript.md +0 -284
  22. package/docs/plans/0066-replace-as-any-with-sdk-types.md +0 -215
  23. package/docs/plans/0069-create-subagent-runtime.md +0 -345
  24. package/docs/plans/0070-extract-event-handlers.md +0 -306
  25. package/docs/plans/0071-extract-session-config-assembler.md +0 -362
  26. package/docs/plans/0072-inject-agent-manager-collaborators.md +0 -329
  27. package/docs/plans/0076-inject-cwd-into-agent-manager.md +0 -102
  28. package/docs/plans/0077-inject-project-agents-dir.md +0 -115
  29. package/docs/plans/0080-consolidate-agent-config-lookup.md +0 -247
  30. package/docs/plans/0084-extract-git-worktree-manager.md +0 -142
  31. package/docs/plans/0087-evolve-subagent-runtime-methods.md +0 -240
  32. package/docs/plans/0098-extract-agent-record-state-machine.md +0 -435
  33. package/docs/plans/0099-replace-ctx-with-parent-snapshot.md +0 -488
  34. package/docs/plans/0100-replace-callback-threading-with-session-subscription.md +0 -454
  35. package/docs/plans/0102-consolidate-test-record-factory.md +0 -176
  36. package/docs/plans/0108-extract-agent-type-registry.md +0 -322
  37. package/docs/plans/0109-extract-settings-manager.md +0 -276
  38. package/docs/plans/0110-agent-activity-tracker.md +0 -297
  39. package/docs/plans/0111-split-agent-record-lifecycle.md +0 -582
  40. package/docs/plans/0112-replace-agent-manager-callbacks.md +0 -241
  41. package/docs/plans/0113-disambiguate-spawn-options.md +0 -155
  42. package/docs/plans/0114-narrow-agent-tool-menu-deps.md +0 -279
  43. package/docs/plans/0115-decompose-agent-tool.md +0 -337
  44. package/docs/plans/0116-type-housekeeping.md +0 -351
  45. package/docs/plans/0118-settings-manager-apply-methods.md +0 -271
  46. package/docs/plans/0123-remove-vi-fn-cast-smell.md +0 -179
  47. package/docs/plans/0131-consolidate-shared-test-fixtures.md +0 -207
  48. package/docs/plans/0132-inject-io-into-session-config.md +0 -219
  49. package/docs/plans/0133-inject-sdk-boundary-into-agent-runner.md +0 -373
  50. package/docs/plans/0134-reduce-as-any-casts.md +0 -366
  51. package/docs/plans/0135-extract-display-helpers.md +0 -182
  52. package/docs/plans/0136-decompose-agent-menu.md +0 -300
  53. package/docs/plans/0144-consolidate-observation-model.md +0 -263
  54. package/docs/plans/0145-decompose-execute-push-ctx-to-boundary.md +0 -290
  55. package/docs/plans/0146-narrow-ui-context.md +0 -319
  56. package/docs/plans/0147-inject-wrap-text-into-conversation-viewer.md +0 -166
  57. package/docs/plans/0148-split-agent-widget-rendering.md +0 -255
  58. package/docs/plans/0152-add-prompt-snippet.md +0 -91
  59. package/docs/plans/0164-reorganize-into-domain-directories.md +0 -409
  60. package/docs/plans/0165-decompose-resolved-spawn-config.md +0 -157
  61. package/docs/plans/0166-extract-parent-session-info.md +0 -231
  62. package/docs/plans/0167-narrow-runner-io.md +0 -150
  63. package/docs/plans/0168-extract-tool-filter-config.md +0 -173
  64. package/docs/plans/0169-extract-run-context-from-run-options.md +0 -194
  65. package/docs/plans/0170-reduce-build-content-lines-complexity.md +0 -225
  66. package/docs/plans/0171-reduce-render-result-complexity.md +0 -200
  67. package/docs/plans/0172-extract-turn-formatting.md +0 -206
  68. package/docs/plans/0180-reorder-append-prompt-for-kv-cache.md +0 -100
  69. package/docs/plans/0185-remove-persistent-agent-memory.md +0 -161
  70. package/docs/plans/0188-replace-any-casts-with-sdk-types.md +0 -162
  71. package/docs/plans/0192-define-session-context-interface.md +0 -107
  72. package/docs/plans/0193-runtime-owns-context-queries.md +0 -245
  73. package/docs/plans/0194-align-tool-interfaces-for-structural-typing.md +0 -139
  74. package/docs/plans/0195-convert-tool-factories-to-classes.md +0 -264
  75. package/docs/plans/0196-convert-runner-menu-to-classes.md +0 -268
  76. package/docs/plans/0205-decompose-render-widget-lines.md +0 -140
  77. package/docs/plans/0206-decompose-show-agent-detail.md +0 -211
  78. package/docs/plans/0207-decompose-agent-widget-update.md +0 -242
  79. package/docs/plans/0208-extract-shared-test-fixtures.md +0 -298
  80. package/docs/plans/0214-convert-remaining-closure-factories-to-classes.md +0 -261
  81. package/docs/plans/0215-decompose-build-parent-context.md +0 -166
  82. package/docs/plans/0216-decompose-start-agent.md +0 -255
  83. package/docs/plans/0217-extract-overwrite-guard.md +0 -176
  84. package/docs/plans/0218-push-sdk-boundary-in-settings.md +0 -172
  85. package/docs/plans/0219-reduce-test-duplication-top-3-clone-families.md +0 -162
  86. package/docs/plans/0227-evolve-agent-record-into-agent.md +0 -322
  87. package/docs/plans/0228-async-start-agent-dissolve-run-handle.md +0 -288
  88. package/docs/plans/0229-agent-born-complete.md +0 -564
  89. package/docs/plans/0230-extract-concurrency-queue.md +0 -265
  90. package/docs/plans/0231-push-exec-registry-to-runner.md +0 -245
  91. package/docs/plans/0232-agent-resume-internal-observer-lifecycle.md +0 -180
  92. package/docs/plans/0237-remove-disallowed-tools.md +0 -180
  93. package/docs/plans/0238-remove-extensions-filtering.md +0 -191
  94. package/docs/plans/0239-collapse-filter-active-tools.md +0 -217
  95. package/docs/plans/0242-rename-agent-tool-to-subagent.md +0 -165
  96. package/docs/plans/0256-extract-worktree-isolation.md +0 -256
  97. package/docs/plans/0257-extract-child-session-factory.md +0 -285
  98. package/docs/plans/0262-add-workspace-provider-seam.md +0 -264
  99. package/docs/plans/0264-remove-extension-lifecycle-control.md +0 -277
  100. package/docs/plans/0265-born-complete-subagent-session.md +0 -333
  101. package/docs/plans/0270-type-consumable-public-surface.md +0 -204
  102. package/docs/plans/0272-export-workspace-collaborator-types.md +0 -147
  103. package/docs/plans/0277-encapsulate-agent-session.md +0 -304
  104. package/docs/plans/0280-rename-agent-to-subagent.md +0 -197
  105. package/docs/plans/0360-custom-agents-default-append.md +0 -132
  106. package/docs/plans/0373-extract-subagent-state.md +0 -250
  107. package/docs/plans/0374-encapsulate-subagent-start-notification.md +0 -268
  108. package/docs/plans/0375-extract-run-listener-workspace-bracket.md +0 -300
  109. package/docs/plans/0376-extract-manager-observer.md +0 -232
  110. package/docs/plans/0377-split-widget-delegation-from-runtime.md +0 -254
  111. package/docs/plans/0378-consolidate-lifecycle-test-fixtures.md +0 -243
  112. package/docs/plans/0379-consolidate-ui-tools-test-fixtures.md +0 -335
  113. package/docs/plans/0380-extract-layered-settings-loader.md +0 -223
  114. package/docs/plans/0381-replace-concurrency-queue-with-limiter.md +0 -267
  115. package/docs/plans/0400-include-parent-prompt-in-replace-mode.md +0 -199
  116. package/docs/plans/0403-abort-subagents-on-interrupt.md +0 -180
  117. package/docs/plans/0412-unify-session-mock-builders.md +0 -146
  118. package/docs/plans/0420-fold-run-metrics-live-activity-onto-record.md +0 -228
  119. package/docs/plans/0421-migrate-activity-readers-to-record-getters.md +0 -309
  120. package/docs/plans/0422-delete-activity-tracker-ui-observer.md +0 -204
  121. package/docs/plans/0423-widget-self-drive-from-lifecycle.md +0 -264
  122. package/docs/plans/0424-drop-widget-dep-from-subagent-tool.md +0 -166
  123. package/docs/plans/0425-reconcile-subagent-events-contract.md +0 -144
  124. package/docs/plans/0426-consolidate-residual-test-clone-families.md +0 -235
  125. package/docs/plans/0427-reconsider-ui-direction.md +0 -212
  126. package/docs/plans/0441-remove-agent-definition-management-subtree.md +0 -180
  127. package/docs/plans/0442-dissolve-agents-conversation-viewer.md +0 -195
  128. package/docs/plans/0443-consolidate-remaining-test-clone-families.md +0 -268
  129. package/docs/plans/0444-shrink-widget-to-background-agents.md +0 -156
  130. package/docs/plans/0445-native-session-navigation.md +0 -365
  131. package/docs/plans/0446-spike-session-navigation-entry-criteria.md +0 -171
  132. package/docs/plans/0447-extract-subagents-settings-command.md +0 -220
  133. package/docs/plans/0448-block-disabled-agent-spawn.md +0 -207
  134. package/docs/plans/0462-navigation-renderer-tui-components.md +0 -338
  135. package/docs/plans/0463-file-snapshot-source-evicted-agents.md +0 -306
  136. package/docs/plans/0470-refresh-readme-command-surface.md +0 -159
  137. package/docs/retro/0048-implement-subagents-api.md +0 -44
  138. package/docs/retro/0049-remove-group-join-output-file-rpc.md +0 -49
  139. package/docs/retro/0051-update-adr-0001-hard-fork.md +0 -39
  140. package/docs/retro/0053-extract-model-resolution-from-execute.md +0 -40
  141. package/docs/retro/0054-decompose-index-into-modules.md +0 -53
  142. package/docs/retro/0057-structured-debug-logging.md +0 -77
  143. package/docs/retro/0061-session-format-transcript.md +0 -41
  144. package/docs/retro/0066-replace-as-any-with-sdk-types.md +0 -44
  145. package/docs/retro/0069-create-subagent-runtime.md +0 -43
  146. package/docs/retro/0070-extract-event-handlers.md +0 -49
  147. package/docs/retro/0071-extract-session-config-assembler.md +0 -60
  148. package/docs/retro/0072-inject-agent-manager-collaborators.md +0 -46
  149. package/docs/retro/0076-inject-cwd-into-agent-manager.md +0 -35
  150. package/docs/retro/0077-inject-project-agents-dir.md +0 -33
  151. package/docs/retro/0080-consolidate-agent-config-lookup.md +0 -35
  152. package/docs/retro/0084-extract-git-worktree-manager.md +0 -37
  153. package/docs/retro/0087-evolve-subagent-runtime-methods.md +0 -42
  154. package/docs/retro/0098-extract-agent-record-state-machine.md +0 -46
  155. package/docs/retro/0099-replace-ctx-with-parent-snapshot.md +0 -37
  156. package/docs/retro/0100-replace-callback-threading-with-session-subscription.md +0 -36
  157. package/docs/retro/0102-consolidate-test-record-factory.md +0 -30
  158. package/docs/retro/0108-extract-agent-type-registry.md +0 -41
  159. package/docs/retro/0109-extract-settings-manager.md +0 -55
  160. package/docs/retro/0110-agent-activity-tracker.md +0 -44
  161. package/docs/retro/0111-split-agent-record-lifecycle.md +0 -61
  162. package/docs/retro/0112-replace-agent-manager-callbacks.md +0 -35
  163. package/docs/retro/0113-disambiguate-spawn-options.md +0 -29
  164. package/docs/retro/0114-narrow-agent-tool-menu-deps.md +0 -38
  165. package/docs/retro/0115-decompose-agent-tool.md +0 -51
  166. package/docs/retro/0116-type-housekeeping.md +0 -42
  167. package/docs/retro/0118-settings-manager-apply-methods.md +0 -40
  168. package/docs/retro/0123-remove-vi-fn-cast-smell.md +0 -49
  169. package/docs/retro/0131-consolidate-shared-test-fixtures.md +0 -46
  170. package/docs/retro/0132-inject-io-into-session-config.md +0 -33
  171. package/docs/retro/0133-inject-sdk-boundary-into-agent-runner.md +0 -45
  172. package/docs/retro/0134-reduce-as-any-casts.md +0 -56
  173. package/docs/retro/0135-extract-display-helpers.md +0 -38
  174. package/docs/retro/0136-decompose-agent-menu.md +0 -43
  175. package/docs/retro/0144-consolidate-observation-model.md +0 -39
  176. package/docs/retro/0145-decompose-execute-push-ctx-to-boundary.md +0 -56
  177. package/docs/retro/0146-narrow-ui-context.md +0 -70
  178. package/docs/retro/0147-inject-wrap-text-into-conversation-viewer.md +0 -90
  179. package/docs/retro/0148-split-agent-widget-rendering.md +0 -39
  180. package/docs/retro/0152-add-prompt-snippet.md +0 -34
  181. package/docs/retro/0164-reorganize-into-domain-directories.md +0 -82
  182. package/docs/retro/0165-decompose-resolved-spawn-config.md +0 -78
  183. package/docs/retro/0166-extract-parent-session-info.md +0 -66
  184. package/docs/retro/0167-narrow-runner-io.md +0 -63
  185. package/docs/retro/0168-extract-tool-filter-config.md +0 -76
  186. package/docs/retro/0169-extract-run-context-from-run-options.md +0 -68
  187. package/docs/retro/0170-reduce-build-content-lines-complexity.md +0 -72
  188. package/docs/retro/0171-reduce-render-result-complexity.md +0 -77
  189. package/docs/retro/0172-extract-turn-formatting.md +0 -80
  190. package/docs/retro/0180-reorder-append-prompt-for-kv-cache.md +0 -62
  191. package/docs/retro/0185-remove-persistent-agent-memory.md +0 -73
  192. package/docs/retro/0188-replace-any-casts-with-sdk-types.md +0 -69
  193. package/docs/retro/0192-define-session-context-interface.md +0 -59
  194. package/docs/retro/0193-runtime-owns-context-queries.md +0 -75
  195. package/docs/retro/0194-align-tool-interfaces-for-structural-typing.md +0 -62
  196. package/docs/retro/0195-convert-tool-factories-to-classes.md +0 -84
  197. package/docs/retro/0196-convert-runner-menu-to-classes.md +0 -73
  198. package/docs/retro/0205-decompose-render-widget-lines.md +0 -64
  199. package/docs/retro/0206-decompose-show-agent-detail.md +0 -67
  200. package/docs/retro/0207-decompose-agent-widget-update.md +0 -92
  201. package/docs/retro/0208-extract-shared-test-fixtures.md +0 -102
  202. package/docs/retro/0214-convert-remaining-closure-factories-to-classes.md +0 -66
  203. package/docs/retro/0215-decompose-build-parent-context.md +0 -61
  204. package/docs/retro/0216-decompose-start-agent.md +0 -80
  205. package/docs/retro/0217-extract-overwrite-guard.md +0 -63
  206. package/docs/retro/0218-push-sdk-boundary-in-settings.md +0 -72
  207. package/docs/retro/0219-reduce-test-duplication-top-3-clone-families.md +0 -64
  208. package/docs/retro/0227-evolve-agent-record-into-agent.md +0 -80
  209. package/docs/retro/0228-async-start-agent-dissolve-run-handle.md +0 -80
  210. package/docs/retro/0229-agent-born-complete.md +0 -89
  211. package/docs/retro/0230-extract-concurrency-queue.md +0 -38
  212. package/docs/retro/0231-push-exec-registry-to-runner.md +0 -71
  213. package/docs/retro/0232-agent-resume-internal-observer-lifecycle.md +0 -109
  214. package/docs/retro/0237-remove-disallowed-tools.md +0 -78
  215. package/docs/retro/0238-remove-extensions-filtering.md +0 -72
  216. package/docs/retro/0239-collapse-filter-active-tools.md +0 -70
  217. package/docs/retro/0242-rename-agent-tool-to-subagent.md +0 -82
  218. package/docs/retro/0256-extract-worktree-isolation.md +0 -89
  219. package/docs/retro/0257-extract-child-session-factory.md +0 -33
  220. package/docs/retro/0262-add-workspace-provider-seam.md +0 -89
  221. package/docs/retro/0264-remove-extension-lifecycle-control.md +0 -91
  222. package/docs/retro/0265-born-complete-subagent-session.md +0 -97
  223. package/docs/retro/0270-type-consumable-public-surface.md +0 -108
  224. package/docs/retro/0272-export-workspace-collaborator-types.md +0 -38
  225. package/docs/retro/0277-encapsulate-agent-session.md +0 -80
  226. package/docs/retro/0280-rename-agent-to-subagent.md +0 -96
  227. package/docs/retro/0360-custom-agents-default-append.md +0 -81
  228. package/docs/retro/0373-extract-subagent-state.md +0 -94
  229. package/docs/retro/0374-encapsulate-subagent-start-notification.md +0 -171
  230. package/docs/retro/0375-extract-run-listener-workspace-bracket.md +0 -104
  231. package/docs/retro/0376-extract-manager-observer.md +0 -81
  232. package/docs/retro/0377-split-widget-delegation-from-runtime.md +0 -105
  233. package/docs/retro/0378-consolidate-lifecycle-test-fixtures.md +0 -100
  234. package/docs/retro/0379-consolidate-ui-tools-test-fixtures.md +0 -52
  235. package/docs/retro/0380-extract-layered-settings-loader.md +0 -97
  236. package/docs/retro/0381-replace-concurrency-queue-with-limiter.md +0 -95
  237. package/docs/retro/0400-include-parent-prompt-in-replace-mode.md +0 -84
  238. package/docs/retro/0403-abort-subagents-on-interrupt.md +0 -90
  239. package/docs/retro/0412-unify-session-mock-builders.md +0 -80
  240. package/docs/retro/0420-fold-run-metrics-live-activity-onto-record.md +0 -90
  241. package/docs/retro/0421-migrate-activity-readers-to-record-getters.md +0 -105
  242. package/docs/retro/0422-delete-activity-tracker-ui-observer.md +0 -97
  243. package/docs/retro/0423-widget-self-drive-from-lifecycle.md +0 -112
  244. package/docs/retro/0424-drop-widget-dep-from-subagent-tool.md +0 -89
  245. package/docs/retro/0425-reconcile-subagent-events-contract.md +0 -101
  246. package/docs/retro/0426-consolidate-residual-test-clone-families.md +0 -100
  247. package/docs/retro/0427-reconsider-ui-direction.md +0 -102
  248. package/docs/retro/0441-remove-agent-definition-management-subtree.md +0 -97
  249. package/docs/retro/0442-dissolve-agents-conversation-viewer.md +0 -108
  250. package/docs/retro/0443-consolidate-remaining-test-clone-families.md +0 -28
  251. package/docs/retro/0444-shrink-widget-to-background-agents.md +0 -81
  252. package/docs/retro/0445-native-session-navigation.md +0 -122
  253. package/docs/retro/0446-spike-session-navigation-entry-criteria.md +0 -99
  254. package/docs/retro/0447-extract-subagents-settings-command.md +0 -91
  255. package/docs/retro/0448-block-disabled-agent-spawn.md +0 -75
  256. package/docs/retro/0462-navigation-renderer-tui-components.md +0 -105
  257. package/docs/retro/0463-file-snapshot-source-evicted-agents.md +0 -103
  258. package/docs/retro/0470-refresh-readme-command-surface.md +0 -40
  259. package/src/observation/notification-state.ts +0 -27
  260. package/vitest.config.ts +0 -14
@@ -1,52 +0,0 @@
1
- ---
2
- issue: 379
3
- issue_title: "Consolidate UI and tools test fixtures"
4
- ---
5
-
6
- # Retro: #379 — Consolidate UI and tools test fixtures
7
-
8
- ## Stage: Planning (2026-06-16T00:00:00Z)
9
-
10
- ### Session summary
11
-
12
- Produced a 9-step lift-and-shift plan for Phase 17 Step 8 — consolidating the non-lifecycle test clone families.
13
- Measured the live baseline (`fallow dupes -r packages/pi-subagents`: 32 clone groups / 512 lines / 2.49%, seven families) and characterized each family by reading all seven test files, classifying each as genuine cross-file duplication (one) versus intra-file (six).
14
-
15
- ### Observations
16
-
17
- - The only genuine cross-file duplication is the `ResolvedSpawnConfig` builder shared by `foreground-runner.test.ts` and `background-spawner.test.ts` (`dup:80ee2004`) — the one promotion to `test/helpers/` (`make-spawn-config.ts`).
18
- Everything else fallow scores same-file, so it stays file-local or moves into a describe-scoped `beforeEach`, per Step 7's ([#378]) discipline.
19
- - The plan's central constraint is Step 7's hard-won lesson: never wrap the system-under-test **act** in a helper to chase a duplication metric.
20
- Every extracted helper returns a value (`createResolvedSpawnConfig`, `disabledConfig`, `exploreConfig`, `createManagerStub`, `spawnAndWaitRegistering`) or seeds `beforeEach`; the acts stay inline.
21
- Added an "Invariants at risk" grep check to enforce this at review.
22
- - Scope was genuinely ambiguous and resolved via `ask_user`: the issue body names six files, but fallow reports a seventh non-lifecycle family in `test/service/service-adapter.test.ts` (four near-identical `SubagentManagerLike` stubs).
23
- Operator chose to include service-adapter (seven files total) and to **not** bind a numeric group target — acceptance is "each named family consolidated, resulting fallow numbers reported."
24
- My `ask_user` prompt incorrectly claimed the architecture roadmap's Step 8 `Targets` lists service-adapter; it does not (it lists the six issue-body files).
25
- The plan corrects this and notes service-adapter was added in planning.
26
- - The roadmap's stated Step 8 outcome ("clone groups 44 → ≤ 25; overall duplication ≤ 0.6%") predates Steps 1–7 and does not match the current fallow metric (2.49%); flagged as an Open Question rather than treated as binding.
27
- - Non-Goals call out the two residual lifecycle families (Step 7 left them as the visible act), the 11-line production clone inside `src/ui/agent-config-editor.ts` (test-only issue), and the three overlapping session-mock builders ([#412]).
28
- - `ResolvedSpawnConfig` is deeply nested (`identity`/`execution`/`presentation` with mirrored scalars).
29
- Designed the shared builder to take **flat** options and assemble the nested structure internally — sidesteps the `Partial<T>` deep-merge trap and encapsulates the mirroring (`agentInvocation.runInBackground`, `presentation.detailBase`) the hand-built copies duplicate.
30
-
31
- ## Stage: Implementation — TDD (2026-06-16T13:10:00Z)
32
-
33
- ### Session summary
34
-
35
- Executed all 9 plan steps as green-to-green lift-and-shift refactors (no red phase — the existing assertions were the spec), one commit per step plus the docs commit.
36
- Promoted the shared `createResolvedSpawnConfig` builder to `test/helpers/` (+5 self-tests) and consolidated the six remaining families with file-local value-returning builders / `beforeEach` setup.
37
- Test count 1010 → 1015; test files 63 → 64; clone groups 32 → 24; package test duplication 512 → 355 lines (2.49% → 1.73%).
38
-
39
- ### Observations
40
-
41
- - The `agent-config-editor.test.ts` family did not collapse as the plan loosely estimated ("4 → ideally 2"): it stayed at 4 groups / 28 lines.
42
- The `disabledConfig` helper removed only the small `enabled: false` arrange; the residual clones are the repeated `await editor.showAgentDetail(...)` **act** plus its `setupDetail` arrange and `ui.select.mock.calls` menu assertion — left inline because wrapping the system-under-test is the wrong abstraction (Step 7 lesson).
43
- No `ask_user` was needed: acceptance was "consolidate and measure" (no binding numeric target), and the only way to force the number would violate the plan's stated discipline.
44
- - `service-adapter.test.ts` had four near-identical `SubagentManagerLike` stub factories with diverging defaults (`hasRunning` true vs false, varying `spawn` returns).
45
- Consolidated into one file-local `createManagerStub()` with **unannotated** return (typed `vi.fn<SubagentManagerLike[...]>()` stubs) so callers retain `Mock<...>` methods — per the testing-skill rule that annotating the return with the production interface, or spreading `Partial<Interface>` overrides, erases mock methods.
46
- Dropped the overrides parameter entirely; per-test behavior is configured on the returned object (`mgr.getRecord.mockImplementation(...)`, `mgr.hasRunning.mockReturnValue(true)`).
47
- Used `sed` to swap the `defaultManager()` / `createTestManager()` call sites after deleting the factory definitions.
48
- - `ui-observer` update-counting tests moved from closure `let updateCount` counters to `vi.fn()` onUpdate with `toHaveBeenCalledTimes` — removes the repeated scaffolding without hiding the `session.emit` act.
49
- - Pre-completion reviewer: WARN — sole finding was this missing TDD retro entry (now written); all deterministic checks PASS, cross-step invariant ("don't wrap the act") verified upheld, 6 Mermaid blocks validated, dead-code clean.
50
-
51
- [#378]: https://github.com/gotgenes/pi-packages/issues/378
52
- [#412]: https://github.com/gotgenes/pi-packages/issues/412
@@ -1,97 +0,0 @@
1
- ---
2
- issue: 380
3
- issue_title: "Resolve the cross-package settings-loader duplication"
4
- ---
5
-
6
- # Retro: #380 — Resolve the cross-package settings-loader duplication
7
-
8
- ## Stage: Planning (2026-06-16T00:00:00Z)
9
-
10
- ### Session summary
11
-
12
- Planned the resolution of the 23-line cross-package production clone between `src/settings.ts` and `@gotgenes/pi-subagents-worktrees`'s `src/config.ts`.
13
- Issue #380 posed a binary: extract a shared loader vs. document-and-suppress.
14
- The operator chose extraction, delivered as a dedicated subpath export `@gotgenes/pi-subagents/settings`, sequenced as two stages (this plan lands the helper in pi-subagents; a follow-up migrates worktrees).
15
- The plan is a single-package TDD plan in `packages/pi-subagents/docs/plans/0380-extract-layered-settings-loader.md`.
16
-
17
- ### Observations
18
-
19
- - The issue is the operator's own (author `gotgenes` == gh user), so the "Proposed change" was a hypothesis.
20
- Used `ask_user` twice: first to confirm Option 1 vs Option 2 (operator picked extract, then asked for explicit for/against), then to pin API placement (`./settings` subpath, recommended) and release sequencing (two-stage, follow-up for worktrees).
21
- - Key mechanism finding that shaped the framing: fallow's `code-duplication` suppression is **file-scoped only** (`// fallow-ignore-file code-duplication`) — there is no line-level next-line directive, contrary to the issue's "rationale on the line above" phrasing for Option 2.
22
- This would have mattered had Option 2 been chosen.
23
- - The shared idiom is the read-sanitize-warn-merge mechanism; the per-package `sanitize` (numeric ceilings vs `string[]`) is the genuinely-different part.
24
- A generic `loadLayeredSettings<T>({ sanitize, warnLabel, filename, agentDir, cwd })` is a clean extraction with no discriminator parameter.
25
- - Honest Outcome caveat captured in the plan: because worktrees keeps its copy until the follow-up, `fallow:dupes` may still report a residual (or dissolve below `min-lines: 5`, since the generic helper's tokens diverge).
26
- Definitive elimination is the follow-up's outcome, not a hard gate on this plan.
27
- - Followed the `0270-type-consumable-public-surface.md` plan as the template for the `.d.ts`-bundle + `verify:public-types` machinery; the new subpath extends that rather than introducing a new mechanism.
28
- - `loadSettings`'s `process.cwd()` default is dropped per the code-design "no `process.*` in library functions" rule; the sole caller (`SettingsManager.load`) already passes `this.cwd` (verified by grep).
29
- - The worktrees-migration follow-up issue should be created at ship time and back-referenced from the architecture Step 9 roadmap entry.
30
-
31
- ## Stage: Implementation — TDD (2026-06-16T16:00:00Z)
32
-
33
- ### Session summary
34
-
35
- Completed all 4 TDD steps from the plan: added `src/layered-settings.ts` with 15 unit tests, refactored `settings.ts` to delegate through the helper (removing `readSettingsFile` and `globalPath`), published the `@gotgenes/pi-subagents/settings` subpath export with a rolled `dist/settings.d.ts` and extended `verify:public-types` harness, and recorded the decision in the architecture doc.
36
- Test count grew from 1015 to 1030 (+15).
37
- Pre-completion reviewer returned **PASS**.
38
- Follow-up issue [#415] created for the worktrees migration.
39
-
40
- ### Observations
41
-
42
- - The plan's "Outcome caveat" resolved favourably: `pnpm fallow:dupes --skip-local` no longer reports the `settings.ts` ↔ `config.ts` pair after the extraction.
43
- The parametrised helper's token sequence diverged enough that the contiguous identical run dropped below the reporting threshold — a better outcome than the plan's hedged prediction.
44
- - ESLint's pre-commit hook removed `!` non-null assertions from `spy.mock.calls[0]![0]` in the test file (typed `vi.spyOn` mock calls are non-optional tuples; the assertions were redundant).
45
- Staged the auto-fix into the same commit without issue.
46
- - The `rollup.dts.config.mjs` array-of-configs approach worked without incident: both bundles (`dist/public.d.ts` and `dist/settings.d.ts`) are self-contained and `verify:public-types` confirmed both probes type-check against the packaged tarball.
47
- - The `satisfies LayeredSettingsSource<SubagentsSettings>` annotation at the `loadSettings` call site serves double duty: validates the object literal and keeps `LayeredSettingsSource` referenced for fallow dead-code (fallow confirmed: 0 issues).
48
- - Follow-up issue [#415] created before the TDD stage notes were written (operator requested it during the session); architecture doc updated with the `[#415]` reference and link definition.
49
-
50
- ## Stage: Final Retrospective (2026-06-16T18:00:00Z)
51
-
52
- ### Session summary
53
-
54
- Shipped issue #380 end-to-end across four stages (plan → TDD → ship) in one session: extracted `loadLayeredSettings<T>` into `src/layered-settings.ts`, published it at the `@gotgenes/pi-subagents/settings` subpath, and adopted it internally in `settings.ts`.
55
- Released as `pi-subagents-v16.4.0`; CI passed first try; pre-completion reviewer returned PASS.
56
- Notably clean run — no rework, no failed commits, no rabbit-holes.
57
-
58
- ### Observations
59
-
60
- #### What went well
61
-
62
- - The two-stage `ask_user` planning gate worked as designed: it surfaced the binary (extract vs. suppress) neutrally, the operator engaged deeply (asked for explicit for/against before committing), and the answers drove the plan's Goals rather than the issue body.
63
- This is the intended use of `ask_user` for an operator-authored issue framed as "weigh two options."
64
- - Proactive tool-mechanism research paid off: `web_search` + `fetch_content` on the fallow docs during planning revealed that `code-duplication` suppression is **file-scoped only** (no line-level directive), which would have changed Option 2's shape had it been chosen.
65
- Checking the tool's real surface before planning around it caught a latent wrong assumption.
66
- - The plan's honestly-hedged "Outcome caveat" (clone might persist until the worktrees follow-up) resolved favourably — the parametrised helper diverged below fallow's threshold immediately.
67
- Hedging a quantitative prediction rather than over-promising left no credibility gap when the better outcome landed.
68
- - Incremental verification cadence: `pnpm run check` ran right after the interface-adjacent Step 2, vitest ran per-file in each Red/Green, and `build:types` + `verify:public-types` ran inside Step 3 — not deferred to the end.
69
- No feedback-loop gaps.
70
-
71
- #### What caused friction (agent side)
72
-
73
- - `missing-context` (process gap) — the plan's Open Questions flagged the worktrees follow-up issue as "created at ship time," but the `ship-issue` prompt has no step for creating a deferred follow-up.
74
- During shipping I went straight to close + release; the operator had to prompt ("What about the follow up issue…") to trigger #415's creation.
75
- Impact: one extra user turn, no rework — but the #380 close comment references #415, so the follow-up had to exist before close, making the ordering load-bearing.
76
- - `instruction-violation` (self-identified, no rework) — the new test used `String(spy.mock.calls[0]![0])`, which the `testing` skill explicitly warns against ("Assert mock calls with `expect(fn).toHaveBeenCalledWith(...)`, not `fn.mock.calls[0]![0]`").
77
- ESLint's pre-commit hook auto-stripped the redundant `!`, leaving `spy.mock.calls[0][0]`; tests stayed green.
78
- I mirrored the pre-existing pattern in `settings.test.ts` rather than the skill's recommended `toHaveBeenCalledWith(expect.stringMatching(...))`.
79
- Impact: none (auto-fixed, matches existing file style); the rule already exists in the skill, so this is a salience note, not a gap.
80
-
81
- #### What caused friction (user side)
82
-
83
- - None material.
84
- The operator's one mid-ship intervention (asking about the follow-up issue) was a good catch that compensated for the prompt gap above, not a correction of a mistake.
85
-
86
- ### Diagnostic details
87
-
88
- - **Model-performance correlation** — the single subagent dispatch (`pre-completion-reviewer`) ran on `anthropic/claude-sonnet-4-6`, appropriate for judgment-heavy review; no mismatch.
89
- Parent-session `model_change` entries toggled among `sonnet-4-6`, `deepseek-v4-flash`, and `opus-4-8`, but these are operator model selections, not quality-relevant task assignments.
90
- - **Escalation-delay tracking** — no `rabbit-hole` friction; no error sequence exceeded one or two tool calls before resolution.
91
- - **Unused-tool detection** — nothing missed; `web_search`/`fetch_content` were dispatched proactively during planning for the fallow-mechanism question.
92
- - **Feedback-loop gap analysis** — verification ran incrementally (per-step `check`/vitest, in-step `verify:public-types`), not just at the end.
93
- No gap.
94
-
95
- ### Changes made
96
-
97
- 1. `.pi/prompts/ship-issue.md` — added `## 4c. Create planned follow-up issues` between the stacked-release check (§4b) and the close step (§5): if the plan or retro defers work to a follow-up issue, create it with `gh issue create` before closing so the close comment can reference its number.
@@ -1,95 +0,0 @@
1
- ---
2
- issue: 381
3
- issue_title: "Replace ConcurrencyQueue with a thunk-based ConcurrencyLimiter"
4
- ---
5
-
6
- # Retro: #381 — Replace ConcurrencyQueue with a thunk-based ConcurrencyLimiter
7
-
8
- ## Stage: Planning (2026-06-13T00:00:00Z)
9
-
10
- ### Session summary
11
-
12
- Produced a 3-step TDD plan to replace the ID-registry `ConcurrencyQueue` (with its `startAgent` back-edge and `markStarted`/`markFinished` relays) with a pure `ConcurrencyLimiter` that schedules thunks FIFO against a dynamic limit.
13
- The design follows the architecture doc's Phase 17 Step 1 entry and the issue's revised framing closely; the plan adds concrete code sketches for `schedule`/`recheck`/`clear`, the manager call site, the simplified `waitForAll`, and `index.ts` wiring.
14
-
15
- ### Observations
16
-
17
- - Author is `gotgenes` (matches the gh CLI user), so the well-specified proposal was treated as the working hypothesis; the design is unambiguous (down to the architecture-doc Step 1), so the `ask_user` gate was skipped.
18
- - Classified non-breaking: `ConcurrencyQueue`/`ConcurrencyLimiter` are internal — no public API, config, or observable behavior change.
19
- The FIFO admission gate against `maxConcurrent` is preserved.
20
- - Key design decision beyond the issue sketch: `clear()` must *settle* dropped pending promises (resolve them), not just drop the thunks.
21
- Every `schedule()` promise becomes `record.promise`, and the post-spawn contract is that it always settles — dropping without resolving would strand a promise.
22
- This costs a small `settle` handle per pending entry (a few lines beyond the issue's "~40 lines").
23
- - Verified no production caller awaits a *queued* agent's promise in a blocking way (`get-result-tool.ts` guards on `status === "running"`; `spawnAndWait` is foreground/direct; `waitForAll` filters by status), confirming it is safe to give queued agents a real promise.
24
- - Sequencing decision: the `SubagentManagerOptions.queue` → `limiter` swap breaks both call sites (`index.ts` + the manager test helper) and the old test file imports the deleted source, so step 2 is one atomic commit (migrate consumers + delete queue + delete old test).
25
- - `bypassQueue` is kept as-is — it is in the published `SubagentsService` type bundle, so renaming would be breaking; deferred to Open Questions.
26
- - Doc inventory: grep confirmed current-state references to update are the Mermaid lifecycle node, the layout listing, the "What the core owns" bullet, the Step 7 ([#378]) target filename, and the `package-pi-subagents` SKILL lifecycle-domain table.
27
- `SKILL.md` line 80 (Phase 15 history) keeps `ConcurrencyQueue` as a historical record.
28
-
29
- ## Stage: Implementation — TDD (2026-06-13T22:15:00Z)
30
-
31
- ### Session summary
32
-
33
- Executed all 3 planned TDD cycles: (1) added `ConcurrencyLimiter` + 13 unit tests, (2) migrated `SubagentManager`, `index.ts`, `subagent.ts` docstring, and the manager test helper to the limiter while deleting `concurrency-queue.ts` + its test in the same atomic commit, (3) updated `architecture.md` and the package SKILL.
34
- Test count went 975 → 966 (−22 deleted queue tests, +13 new limiter tests); the full suite, `check`, `lint`, and `pnpm fallow dead-code` are all green.
35
-
36
- ### Observations
37
-
38
- - The plan held up cleanly — no surprises in the manager integration tests.
39
- The `queueing and concurrency` describe block passed unchanged after only the `createManager` helper swap (real `ConcurrencyLimiter` instead of `ConcurrencyQueue` + forward-ref start callback), confirming those tests exercise behavior, not queue internals.
40
- - One deviation: a 4th commit (`90135005`, `refactor:`) fixes a stale `// before startAgent / queue drain` comment at `src/index.ts:125` that the plan's grep inventory missed (it named no removed symbol, just deleted concepts).
41
- The pre-completion reviewer caught it.
42
- Committed separately rather than amending the non-HEAD refactor commit, since AGENTS.md discourages interactive rebase in this environment.
43
- - ESLint `@typescript-eslint/no-floating-promises` fired on every bare `limiter.schedule(...)` in the limiter test (the queue's `enqueue` returned `void`; `schedule` returns a promise).
44
- Resolved by prefixing unawaited calls with `void` — all such tasks either stay pending or resolve, so no unhandled rejection.
45
- - The `clear()`-settles-pending-promises decision (made at planning) proved correct and is covered by a dedicated test ("resolves the promises of dropped pending tasks").
46
- - Pre-completion reviewer: WARN (no FAILs).
47
- Reviewer warnings: the single stale-comment finding at `index.ts:125` — now fixed in commit `90135005`.
48
-
49
- ## Stage: Final Retrospective (2026-06-14T00:30:00Z)
50
-
51
- ### Session summary
52
-
53
- Shipped #381 across planning, TDD, and release: `pi-subagents` `16.0.0` → `16.1.0`, tag `pi-subagents-v16.1.0`.
54
- Four commits landed (one `feat`, two `refactor`, one `docs`) plus two `docs(retro)` notes; CI passed first try, the issue was closed with an implemented-in summary, and the release-please PR was merged.
55
- The plan — written down to code sketches — held up across all three TDD cycles with no design rework.
56
-
57
- ### Observations
58
-
59
- #### What went well
60
-
61
- - The plan's fidelity paid off: the `clear()`-settles-pending-promises decision, the atomic step-2 sequencing (migrate consumers + delete queue + delete old test in one commit), and the `void`-prefix prediction for floating promises were all made at planning time and executed without surprise.
62
- The `queueing and concurrency` manager tests passed unchanged after only the `createManager` helper swap, validating the planning claim that they exercise behavior, not queue internals.
63
- - The pre-completion-reviewer (on `anthropic/claude-sonnet-4-6`, 161s, 21 tool uses) caught a stale comment at `src/index.ts:125` that all four deterministic gates (`check`, `lint`, `test`, `fallow dead-code`) passed over.
64
- This is the backstop working exactly as intended — a judgment-model review surfacing residue that pattern-matchers cannot.
65
- - Verification cadence was incremental, not end-loaded: file-scoped `vitest` + `biome` + `eslint` after step 1, `pnpm run check` immediately after the shared-interface change mid-step-2 (per the plan's own instruction), then lifecycle suite → full suite → full lint, then `rumdl` for the docs step, then the full gates + `fallow` before push.
66
-
67
- #### What caused friction (agent side)
68
-
69
- - `missing-context` (self/reviewer-caught) — the stale comment `// before startAgent / queue drain` at `src/index.ts:125` referenced two deleted concepts but was not cataloged in the plan's Module-Level Changes, despite the planning grep output having surfaced that exact line.
70
- The grep hit was visible but never converted into a plan action or an explicit leave-as-is.
71
- Impact: one small follow-up commit (`90135005`, `refactor:`); no rework, no design impact — the reviewer backstop absorbed it before ship.
72
-
73
- #### What caused friction (user side)
74
-
75
- - None.
76
- The single user touchpoint — the release-timing gate in `/ship-issue` (release now vs. batch the Phase 17 sequence) — was strategic judgment the agent correctly deferred, not mechanical oversight.
77
-
78
- ### Diagnostic details
79
-
80
- - **Model-performance correlation** — one subagent dispatch (`pre-completion-reviewer`) on `anthropic/claude-sonnet-4-6`; appropriate match for judgment-heavy review, and it returned the session's only actionable finding.
81
- - **Escalation-delay tracking** — no rabbit-holes; the lone lint error (`@typescript-eslint/no-floating-promises`, 18 sites) was resolved in a single test-file rewrite, far under the 5-call escalation threshold.
82
- - **Unused-tool detection** — nothing under-tooled; `colgrep`/`grep` were used during planning exploration and the reviewer subagent was dispatched as designed.
83
- - **Feedback-loop gap analysis** — no gap; verification ran after every cycle, with `pnpm run check` correctly invoked right after the shared-interface change rather than at end-of-session.
84
-
85
- #### Process note (no inline change)
86
-
87
- - The release-please PR merge required the documented `UNSTABLE` → `gh pr merge` fallback (step 6.4 of `/ship-issue`) because default-`GITHUB_TOKEN` release PRs never get checks.
88
- This recurs every release; the prompt already handles it, so it is recorded here only as a standing pattern, not a friction point.
89
-
90
- ### Changes made
91
-
92
- 1. Added this Final Retrospective stage entry to `packages/pi-subagents/docs/retro/0381-replace-concurrency-queue-with-limiter.md`.
93
- 2. No prompt or `AGENTS.md` changes — the operator chose retro-file-only, since the single friction (the stale `src/index.ts:125` comment) was a one-off execution slip already caught by the pre-completion-reviewer backstop, and the candidate grep-hit rule was judged not worth the prompt verbosity.
94
-
95
- [#378]: https://github.com/gotgenes/pi-packages/issues/378
@@ -1,84 +0,0 @@
1
- ---
2
- issue: 400
3
- issue_title: "perf(pi-subagents): include parent system prompt in replace mode for KV cache reuse"
4
- ---
5
-
6
- # Retro: #400 — Include parent system prompt in replace mode for KV cache reuse
7
-
8
- ## Stage: Planning (2026-06-14T00:42:49Z)
9
-
10
- ### Session summary
11
-
12
- Produced a numbered plan for including the parent system prompt as a cacheable prefix in `buildAgentPrompt()`'s replace branch, mirroring the [#180] append-mode reorder.
13
- The change is a single-function edit plus test and README updates, planned across three TDD/docs commits.
14
-
15
- ### Observations
16
-
17
- - Three design decisions were confirmed with the operator (issue author = gh user) before planning:
18
- 1. Ship as breaking `perf!:` with a `BREAKING CHANGE:` footer — replace-mode agents inherit the parent prompt on upgrade with no user edit, and the thin two-line header is removed.
19
- 2. Use `genericBase` as the no-parent fallback, consistent with append mode.
20
- 3. Apply uniformly to all replace agents, including built-in `Explore` and `Plan` (one code path, no special-casing).
21
- - The operator raised a cross-extension concern about the `genericBase` fallback interacting with `@gotgenes/pi-anthropic-auth`.
22
- Investigation of that package's `system-prompt-shaping.ts` / `request-shaping.ts` showed no new interaction: the `x-anthropic-billing-header` block is prepended unconditionally for OAuth, and de-fingerprinting keys off `PI_DEFAULT_PROMPT_PREFIX` (absent from `genericBase`, which is already neutral).
23
- Captured this in the plan's Background and Risks.
24
- - `parentSystemPrompt` is a required `string` at the `session-config` layer (sourced from `snapshot.systemPrompt`), so the `genericBase` fallback is effectively a defensive/test-only path in real sessions.
25
- - The thin replace header string (`You are a pi coding agent sub-agent`) appears only in `prompts.ts` and its test — no skill or live doc pins it; README needs three edits (Explore/Plan rows, `prompt_mode` table, Patch 3 `<active_agent>` wording, the last already slightly stale post-#180).
26
- - Notable emergent scope point: `Explore`/`Plan` are built-in replace-mode agents, so this change affects them visibly — surfaced and confirmed rather than assumed.
27
-
28
- ## Stage: Implementation — TDD (2026-06-14T00:54:46Z)
29
-
30
- ### Session summary
31
-
32
- Completed all 3 TDD cycles in `packages/pi-subagents`.
33
- The change is a single-function edit to `src/session/prompts.ts` (hoist `identity`, rewrite replace branch) plus test updates and README/skill-doc corrections.
34
- Test count went from 973 to 975 (+2 net new tests) across 59 test files.
35
-
36
- ### Observations
37
-
38
- - Step 1 (Red): rewrote 2 existing replace-mode tests and added 2 new ones (4 failures confirmed against old code); the old "ignores parent prompt" test premise inverted cleanly into "includes parent prompt as base."
39
- - Step 2 (Green): hoisting `const identity = parentSystemPrompt ?? genericBase;` above the `if` block and replacing the `replaceHeader` template were the only `src/` changes; also updated two positional `<active_agent>` tests in the same commit since they broke the moment the branch changed (`tagIdx === 0` → `toBeGreaterThan(0)`).
40
- - The `BREAKING CHANGE:` footer wording was taken verbatim from the plan and landed in the `perf!:` commit.
41
- - Pre-completion reviewer: WARN — one finding: `.pi/skills/package-pi-subagents/SKILL.md` still said "prepends" for the `<active_agent>` tag; fixed in a follow-up `docs:` commit before shipping.
42
- - No deviations from the plan's Module-Level Changes list; no lockfile changes; fallow dead-code exited zero.
43
-
44
- ## Stage: Final Retrospective (2026-06-14T01:11:10Z)
45
-
46
- ### Session summary
47
-
48
- Shipped #400 across three stages (Planning on `claude-opus-4-8`, TDD + Ship on `claude-sonnet-4-6`) as a single-function edit to `buildAgentPrompt()`'s replace branch plus tests and doc updates, released as `pi-subagents` v16.0.0 (major, breaking `perf!:`).
49
- The run was clean end-to-end: two `ask_user` gates during planning, a 3-cycle TDD pass, one pre-completion WARN resolved before push, and a no-friction release-please merge.
50
-
51
- ### Observations
52
-
53
- #### What went well
54
-
55
- - Cross-extension investigation on demand — when the operator asked mid-`ask_user` how the `genericBase` fallback interacts with `@gotgenes/pi-anthropic-auth`, the agent read that sibling repo's `system-prompt-shaping.ts` and `request-shaping.ts` and proved no new interaction (billing header prepended unconditionally; de-fingerprinting keys off `PI_DEFAULT_PROMPT_PREFIX`, absent from the neutral `genericBase`) before answering.
56
- This converted an open worry into a documented Risk row rather than a deferred unknown.
57
- - Emergent-scope surfacing — planning noticed that built-in `Explore`/`Plan` are replace-mode agents and so are visibly affected, then confirmed uniform application via a second `ask_user` instead of assuming.
58
- - Autoformat discipline — after `pi-autoformat` touched `README.md` mid-edit, the agent re-read the region before the next edit (turns 49–50) rather than matching against stale layout, avoiding a failed `oldText`.
59
-
60
- #### What caused friction (agent side)
61
-
62
- - `missing-context` (planning) — the plan listed the README's Patch 3 `<active_agent>` "prepends" wording as a doc update but missed the identical Patch 3 description in `.pi/skills/package-pi-subagents/SKILL.md`.
63
- Exact-grep during planning keyed on removed strings (`You are a pi coding agent sub-agent`, `prompt_mode`); the stale prose carried none of them, so the skill file's "prepends `<active_agent>`" line was not found.
64
- Impact: the pre-completion reviewer caught it as a WARN, requiring one follow-up `docs:` commit (8e93d2a4) during TDD before push — no rework beyond that, and the safety net worked as designed.
65
-
66
- #### What caused friction (user side)
67
-
68
- - None — the operator's mid-planning OAuth question was a high-value redirect that strengthened the plan, not friction.
69
-
70
- ### Diagnostic details
71
-
72
- - **Model-performance correlation** — judgment-heavy planning ran on `claude-opus-4-8`; mechanical TDD execution and the deterministic ship steps ran on `claude-sonnet-4-6`.
73
- Appropriate assignment in both directions; no mismatch.
74
- - **Unused-tool detection** — the `colgrep` skill was loaded in planning but never used; exploration was all exact-symbol grep, which was correct for known symbols.
75
- The one place it would have helped is the `missing-context` friction: a semantic search like "docs describing how the active_agent tag is added to the system prompt" would likely have surfaced both the README and the SKILL.md descriptions that symbol-grep missed.
76
- - **Feedback-loop gap analysis** — verification ran incrementally throughout (green baseline before cycle 1, per-file `vitest` each cycle, full suite + `check` + `lint` + `fallow` after the last step).
77
- No end-loaded verification.
78
- - **Escalation-delay tracking** — no rabbit-holes; no error sequence exceeded one tool call.
79
-
80
- ### Changes made
81
-
82
- 1. `.pi/prompts/plan-issue.md` — extended the Module-Level Changes grep bullet: when a step reworks a documented mechanism's behavior (rather than removing a symbol), grep `.pi/skills/package-*/SKILL.md` for the mechanism name, since reworded prose carries no removed symbol to match.
83
-
84
- [#180]: https://github.com/gotgenes/pi-packages/issues/180
@@ -1,90 +0,0 @@
1
- ---
2
- issue: 403
3
- issue_title: "Pressing Escape does not stop subagent/background agent"
4
- ---
5
-
6
- # Retro: #403 — Pressing Escape does not stop subagent/background agent
7
-
8
- ## Stage: Planning (2026-06-14T00:00:00Z)
9
-
10
- ### Session summary
11
-
12
- Investigated the third-party bug report that ESC does not stop subagents and traced the abort path through both the package and the pinned Pi SDK peer deps.
13
- Found that foreground subagents already receive the parent abort signal end-to-end, while background subagents are detached with no interrupt wiring — the reproducible bug.
14
- Confirmed direction with the operator via `ask_user` (third-party gate): implement ESC-to-abort for both modes, with a foreground guard test, aborting all running and queued background agents.
15
- Wrote and committed plan `0403-abort-subagents-on-interrupt.md`.
16
-
17
- ### Observations
18
-
19
- - Key SDK fact that de-risks the design: in `pi-agent-core` `agent.js`, each run creates a fresh `AbortController` and `finishRun()` discards it **without** aborting on normal completion.
20
- So the parent signal's `abort` event fires only on a real ESC interrupt — latching `abortAll()` to it will not spuriously kill background agents at turn end.
21
- - Chosen mechanism: a small `InterruptHandler` driven by `pi.on("turn_start", ...)`, re-latching `ctx.signal` each turn so the latch tracks the live per-run signal even across runs and tool-less turns.
22
- `turn_start` was preferred over `tool_execution_start` because a background agent can outlive the run that spawned it; a turn-level latch still holds the current run's signal when the user interrupts a later tool-less turn.
23
- - Reused the existing `manager.abortAll()` rather than adding `abortBackground()`.
24
- Foreground agents are already aborted via their own `wireSignal`, so `abortAll()`'s overlap is redundant-but-harmless (status-guarded `abort()`, idempotent `markStopped`).
25
- The manager does not store `isBackground` on the record, so distinguishing modes would need extra state — deferred as an Open Question.
26
- - Classified as a non-breaking `fix:` (not `fix!:`): no config key, default, or output shape changes; detached-survives-ESC was a limitation, not a contract.
27
- Noted the behavior change explicitly in Goals.
28
- - Foreground path is believed already-correct from the code trace; the plan adds a regression guard in `subagent-session.test.ts` (`forwardAbortSignal` is currently untested for the parent-signal path) and will fix only if the guard fails.
29
-
30
- ## Stage: Implementation — TDD (2026-06-14T18:00:00Z)
31
-
32
- ### Session summary
33
-
34
- Completed all three TDD cycles against a green baseline (967 tests).
35
- Added the foreground-abort guard, implemented `InterruptHandler` + `turn_start` wiring, and updated the architecture doc.
36
- Test count went from 967 to 975 (+8: 6 `InterruptHandler` unit tests, 2 foreground guard tests); `check`, `lint`, `test`, and `fallow dead-code` all pass.
37
-
38
- ### Observations
39
-
40
- - The foreground guard (Step 1) passed on the first run, confirming the planning-stage code trace: the parent signal already reaches the child `session.abort()` via `forwardAbortSignal`.
41
- No code fix was needed, so it landed as `test:` exactly as the plan anticipated.
42
- - `InterruptHandler` came out clean against the `code-design` heuristics — one field read from `ctx`, one method on a one-method `InterruptManager` interface, latch state owned internally, `{ once: true }` listener.
43
- The reviewer's code-design check was PASS with no structural concerns.
44
- - `abortAll()` gained a second narrow-interface consumer (the new handler) on top of the shutdown path; `fallow dead-code` stayed green, so its existing `fallow-ignore-next-line unused-class-member` comment was left untouched.
45
- - Pre-completion reviewer: **WARN**.
46
- - Reviewer warnings: stale source-file counts in `architecture.md`.
47
- Fixed the current-state prose claim (`56` → `58` source files).
48
- Left the fallow health-metrics snapshot rows (line ~650, `7,778 (57 files)`) intact — those are point-in-time analysis tables where the file count was computed alongside LOC and other metrics, so bumping one cell in isolation would desync the snapshot.
49
- Amended the fix into the docs commit (not yet pushed).
50
-
51
- ## Stage: Final Retrospective (2026-06-14T20:00:00Z)
52
-
53
- ### Session summary
54
-
55
- Shipped issue #403 end-to-end across four stages (plan → TDD → ship → live verification): root-caused the bug, implemented the `InterruptHandler` (single `fix:` commit), guarded the already-working foreground path, and released `pi-subagents-v16.1.1`.
56
- The operator then live-tested all three abort paths (background subagent, foreground subagent, main agent) and confirmed a single Escape aborts each immediately.
57
- Near-zero rework: one reviewer WARN (stale doc file count) fixed by amend, no follow-up commits, no failed CI.
58
-
59
- ### Observations
60
-
61
- #### What went well
62
-
63
- 1. The planning-stage SDK trace paid dividends two stages later.
64
- When the operator asked during live testing "is it supposed to take two Escapes or just one?", the answer came straight from the `restoreQueuedMessagesToEditor → agent.abort()` trace captured at planning time — no re-investigation.
65
- The same trace explained the main-agent and foreground-subagent abort paths immediately.
66
- 2. The keystone de-risking finding (`finishRun()` discards the per-run `AbortController` without aborting it, so the `abort` event fires only on a real interrupt) held up in practice — no spurious turn-end aborts were observed in live testing.
67
- 3. The foreground guard test passed on its first run, confirming the planning trace, so the plan's pre-typed `test:` commit type was correct and the whole implementation landed with zero rework.
68
- 4. Verification was incremental throughout TDD: green baseline first, per-step affected-file runs, `pnpm run check` after the interface-touching step, and full `test`/`check`/`lint`/`fallow` at the end.
69
-
70
- #### What caused friction (agent side)
71
-
72
- 1. `missing-context` — when adding the new source file `interrupt.ts`, I updated the `handlers/` directory listing in `architecture.md` but not the prose total-file count at line 277 (which was already stale: `56` vs the pre-change actual of `57`).
73
- Impact: one pre-completion reviewer WARN, fixed by amending the docs commit before push — no rework, no extra commit, no CI cost.
74
-
75
- #### What caused friction (user side)
76
-
77
- 1. None.
78
- The operator's involvement was high-value: the third-party-issue direction gate (planning) and the live three-path abort verification (post-ship) validated behavior that unit tests cannot reach (real ESC keypress through the interactive TUI).
79
-
80
- ### Diagnostic details
81
-
82
- 1. Model-performance correlation — ship stage and the `pre-completion-reviewer` subagent both ran on `claude-sonnet-4-6` (mechanical orchestration and checklist review — appropriate); retro synthesis on `claude-opus-4-8` (judgment — appropriate).
83
- No mismatch.
84
- 2. Escalation-delay tracking — no `rabbit-hole` friction points; the planning SDK dig was productive forward exploration, not repeated calls against one error.
85
- 3. Unused-tool detection — the planning SDK trace navigated minified `node_modules/.pnpm` dist files by hand; `colgrep` (project-code semantic search) and an Explore subagent (project-code understanding) were not suited to reverse-engineering pinned third-party `dist` JS, so no tool was wrongly skipped.
86
- 4. Feedback-loop gap analysis — no gap; verification ran incrementally per TDD step, not only at the end.
87
-
88
- ### Changes made
89
-
90
- 1. Added an "Abort / interrupt signal lifecycle" section to `.pi/skills/pi-extension-lifecycle/SKILL.md` documenting the per-run `AbortController`, the ESC → `agent.abort()` path, the `finishRun()` discard-without-abort behavior, and the `ctx.signal` / `tool.execute(signal)` exposure — so future interrupt-timing work need not re-derive it from the pinned SDK `dist` files.
@@ -1,80 +0,0 @@
1
- ---
2
- issue: 412
3
- issue_title: "Unify the three overlapping session-mock builders in pi-subagents tests"
4
- ---
5
-
6
- # Retro: #412 — Unify the three overlapping session-mock builders in pi-subagents tests
7
-
8
- ## Stage: Planning (2026-06-16T00:00:00Z)
9
-
10
- ### Session summary
11
-
12
- Planned the unification of the three `test/helpers/` session-mock builders.
13
- A structural read showed the three sit on two axes (AgentSession-vs-`SubagentSession`, event-bus-vs-factory), that `createSubagentSessionStub` already composes `createMockSession` (intrinsic delegation, not duplication), and that the only genuine independent redeclaration of the four shared base fields lives in `createFactorySession`.
14
- The operator chose targeted reuse with a working-bus core default; the plan folds `createFactorySession` onto the `createMockSession` core and leaves the other two builders untouched.
15
-
16
- ### Observations
17
-
18
- - The issue is the operator's own and explicitly flags the wrong-abstraction risk (Sandi Metz quote), so the `Decide` gate used `ask_user` to choose between full composable factory (A), targeted reuse (B), and decline-and-document (C).
19
- Operator picked **B** with the **working event bus as the core default**.
20
- - Rejected option A (the issue's literal "Proposed change") because a multi-facet `createSessionMock()` with opt-in `withTurnLoop()`/`withBindFacet()` is the over-parameterized factory the issue itself warns against; the honest target is only `createFactorySession`'s independently-redeclared base.
21
- - De-risked the key feasibility assumption with a throwaway `tsc --noEmit` probe: spreading `...createMockSession()` (which returns `MockSession & Record<string, unknown>`) preserves `Mock<...>` typing on the facet methods because `unknown & Mock<...>` narrows to `Mock<...>`.
22
- - Behavioral delta is the inert→working `subscribe` plus new `emit`/`sessionManager` fields on the factory session; confirmed no factory/lifecycle test emits or asserts on the inert subscribe, and `session.dispose` stays a spy (`create-subagent-session.test.ts:194`).
23
- - Plan is two commits: a `refactor(test):` cycle (one new event-bus self-test + the rewrite) and a `docs:` cycle updating the Phase 17 Step 7 note in `architecture.md` to record the resolution.
24
-
25
- ## Stage: Implementation — TDD (2026-06-16T21:20:00Z)
26
-
27
- ### Session summary
28
-
29
- Executed the plan in two TDD cycles exactly as written: a `refactor(test):` cycle (added the working-event-bus self-test as the red, rewrote `createFactorySession` to spread `...createMockSession()` + the factory facet as the green) and a `docs:` cycle recording the targeted-reuse outcome in the `architecture.md` Phase 17 Step 7 note.
30
- Test count went 1030 → 1031 (the one new `createFactorySession` event-bus self-test); full suite 1031 pass across 65 files.
31
- All deterministic gates green from repo root: `check`, `lint`, `test`, and `pnpm fallow dead-code`.
32
-
33
- ### Observations
34
-
35
- - The plan's feasibility probe held: spreading `...createMockSession()` (typed `MockSession & Record<string, unknown>`) preserved `Mock<...>` typing on the facet methods, so `setActiveToolsByName.mock.calls[0][0]` still type-checks — no annotation gymnastics needed.
36
- - The inert→working `subscribe` change was inert in practice as predicted: no factory or lifecycle test emits, and `create-subagent-session.test.ts:194`'s `session.dispose` spy assertion held (the core supplies `dispose` as a `vi.fn()`).
37
- - Pre-completion reviewer: **WARN** (no FAILs).
38
- Reviewer warnings: (1) the `createMockSession` core docstring I added landed orphaned above `toAgentSession` rather than attached to `createMockSession` — fixed in a follow-up `refactor(test):` commit (`5999dcad`) by moving it directly above the declaration; (2) the TDD retro stage was not yet written when the reviewer ran — this entry resolves it.
39
- - Deviation: one extra cleanup commit beyond the planned two (the docstring-placement fix), landed as `refactor(test):` rather than amended because the `docs:` commit already sat on top of the refactor commit and neither was pushed.
40
-
41
- ## Stage: Final Retrospective (2026-06-17T00:00:00Z)
42
-
43
- ### Session summary
44
-
45
- Shipped issue #412 across three stages (planning, TDD, ship) in one continuous session with a single deviation: one extra `refactor(test):` cleanup commit for an orphaned docstring the pre-completion reviewer flagged.
46
- The whole arc was low-friction — the `ask_user` wrong-abstraction gate in planning, the `tsc --noEmit` feasibility probe, and incremental verification all paid off, and CI/release/close ran clean.
47
- No `pi-subagents` release bumped (a `refactor(test):` change), so only the unrelated `pi-github-tools-v4.1.5` doc release rode along in the release-please PR.
48
-
49
- ### Observations
50
-
51
- #### What went well
52
-
53
- - The planning-stage `ask_user` gate did real work: it surfaced the wrong-abstraction risk the issue itself flagged and let the operator pick targeted reuse (B) over the issue's literal composable-factory proposal (A).
54
- This is the `ask_user` skill behaving exactly as the `Decide` gate intends for an operator-authored issue.
55
- - The `tsc --noEmit` throwaway probe in planning (does spreading `...createMockSession()` preserve `Mock<...>` typing?) de-risked the one feasibility unknown before any commit, so the TDD green step landed on the first try with no annotation gymnastics.
56
- - Verification cadence was incremental, not end-loaded: `pnpm run check` ran right after the TDD green step, the full suite after both steps, then `lint`/`fallow` before push.
57
- No feedback-loop gap.
58
-
59
- #### What caused friction (agent side)
60
-
61
- - `missing-context` — the plan called for a docstring touch-up on `createMockSession`, but the existing `createMockSession` docstring block in `mock-session.ts` was *already orphaned* (sitting above `toAgentSession`, not its own declaration).
62
- I enriched the orphaned block instead of noticing it wasn't attached to the symbol it documents.
63
- Impact: one extra `refactor(test):` commit (`5999dcad`) to move the block; caught by the pre-completion reviewer, so no escaped defect — reviewer-caught, not user-caught.
64
-
65
- #### What caused friction (user side)
66
-
67
- - None.
68
- The operator's only mid-session input was the planning `ask_user` answer (direction B, working-bus core default), which was strategic judgment, not mechanical oversight.
69
-
70
- ### Diagnostic details
71
-
72
- - **Model-performance correlation** — the one subagent dispatch (`pre-completion-reviewer`) ran on `anthropic/claude-sonnet-4-6`, appropriate for judgment-heavy review; it found a genuine issue (the orphaned docstring), so no quality mismatch.
73
- - **Escalation-delay tracking** — no `rabbit-hole` friction; no error sequence exceeded one tool call.
74
- - **Unused-tool detection** — no missing-context gap that an Explore/`colgrep` dispatch would have closed; planning already used `grep`/`colgrep` and a `tsc` probe.
75
- - **Feedback-loop gap analysis** — verification ran incrementally (see "What went well"); no end-loaded check.
76
-
77
- ### Changes made
78
-
79
- 1. Appended this Final Retrospective stage entry to `packages/pi-subagents/docs/retro/0412-unify-session-mock-builders.md`.
80
- No `AGENTS.md` or `.pi/prompts/` changes — the single friction point was a one-off slip the pre-completion reviewer already caught (weak evidence for a new rule).
@@ -1,90 +0,0 @@
1
- ---
2
- issue: 420
3
- issue_title: "pi-subagents: fold subagent run metrics and live activity onto the core record"
4
- ---
5
-
6
- # Retro: #420 — pi-subagents: fold subagent run metrics and live activity onto the core record
7
-
8
- ## Stage: Planning (2026-06-17T00:00:00Z)
9
-
10
- ### Session summary
11
-
12
- Produced a 3-step TDD plan (`docs/plans/0420-fold-run-metrics-live-activity-onto-record.md`) for Phase 18 Step 1: fold `turnCount`, active tools, and response text onto `SubagentState`, have `record-observer` populate them, and expose read-only getters on `Subagent`.
13
- The change is a pure addition / tidy-first — both observers keep running and no consumer reads the new getters until Step 2 ([#421]).
14
- Operator-authored, unambiguous proposal matching the architecture roadmap, so the `ask-user` gate was skipped.
15
-
16
- ### Observations
17
-
18
- - The `maxTurns` getter is the one getter that does **not** delegate to `SubagentState` — it delegates to `this.execution.maxTurns`.
19
- Verified both spawners pass `execution.effectiveMaxTurns` as `options.maxTurns` (threaded into `SubagentExecution.maxTurns` by `SubagentManager.spawn`), so the record getter returns the same value `AgentActivityTracker` was constructed with.
20
- - Semantics must be copied field-for-field from `AgentActivityTracker` so Step 2's reader swap is behavior-preserving: `turnCount` starts at **1** (readers assume the at-least-1 invariant — `notification.ts` uses `?? 0`, `result-renderer.ts` gates on `> 0`); `activeTools` uses `name_seq` keying for concurrent same-name tools; `removeActiveTool` deletes the first match; `responseText` resets at `message_start` and appends each text delta.
21
- - Decided to leave `resetForResume` **unchanged** (the new fields are not reset on resume).
22
- Rationale: the tracker is not reconstructed/reset on resume today, so the surviving `SubagentState` accumulating across a resume preserves parity.
23
- Touching it would violate the pure-addition contract; flagged in Open Questions for Step 2 to revisit against observable reader behavior.
24
- - The tracker's `_session`/`setSession` is deliberately **not** folded — it exists only for UI polling reads and is migrated/removed in Steps 2–3.
25
- - No symbol is removed or renamed, so no `package-pi-subagents` SKILL or architecture-doc prose update is needed; the Phase 18 Step 1 roadmap entry already describes this work.
26
-
27
- [#421]: https://github.com/gotgenes/pi-packages/issues/421
28
-
29
- ## Stage: Implementation — TDD (2026-06-17T13:10:00Z)
30
-
31
- ### Session summary
32
-
33
- Executed all 3 TDD steps from the plan: (1) added `turnCount`/`activeTools`/`responseText` fields plus 5 transition methods to `SubagentState`; (2) extended `record-observer` with 4 new event branches (`tool_execution_start`, `turn_end`, `message_start`, `message_update` text_delta) plus paired `removeActiveTool` on `tool_execution_end`; (3) added 4 read-only getters to `Subagent` (`turnCount`, `activeTools`, `responseText`, `maxTurns`).
34
- Test count: 1031 → 1058 (+27 across 3 test files).
35
- Full suite green; type check and lint clean; zero dead code.
36
-
37
- ### Observations
38
-
39
- - The first pre-completion reviewer run returned **FAIL** due to 3 pre-existing `MD051` broken-fragment links in `docs/architecture/history/phase-17-core-consolidation.md` (fragment `#first-principles-refinement-the-deeper-target` was missing `-and-`; correct anchor is `#first-principles-refinement-and-the-deeper-target`).
40
- Fixed in a separate `docs:` commit; re-run returned **WARN**.
41
- - 3 Biome `useTemplate` infos in `packages/pi-permission-system/` are informational only (marked unsafe fix, `biome check --write` skips them) and do not cause a non-zero lint exit.
42
- - The 3 "vacuously-passing" new observer tests (paired `tool_execution_end` removal, `message_start` reset, non-text_delta ignore) pass before the observer handles the events because the state starts in the default/empty state — they correctly verify absence-of-mutation and fully exercise the code path after the observer is implemented.
43
- - WARN finding: `package-pi-subagents` SKILL.md `Observation` domain row description ("Session-event stats") is now slightly incomplete for `record-observer` (it also accumulates live-activity fields).
44
- Intentionally deferred per the planning-stage decision — no symbol removed, and the description will be updated in Step 2 ([#421]) when the observer's role is fully defined after the reader migration.
45
- - Pre-completion reviewer verdict: **WARN** (one non-blocking finding, deferred per retro).
46
-
47
- ## Stage: Final Retrospective (2026-06-17T17:40:39Z)
48
-
49
- ### Session summary
50
-
51
- Shipped Phase 18 Step 1 across planning, TDD (3 red→green→commit cycles, +27 tests), and release (`pi-subagents` v16.5.0).
52
- The code work was clean and rework-free; all friction was in markdown-lint surfacing late — two separate doc-lint failures (one pre-existing, one introduced) escaped the baseline and post-TDD gates and were caught only by the pre-completion reviewer and the ship-stage lint, each requiring a fix commit.
53
-
54
- ### Observations
55
-
56
- #### What went well
57
-
58
- - The `pre-completion-reviewer` safety net earned its keep: it caught the pre-existing `MD051` broken-fragment links in `phase-17-core-consolidation.md` (introduced earlier by `e4d92535`, unrelated to this issue) before the push, returning FAIL on the first run.
59
- Without it the broken links would have shipped.
60
- - TDD execution was textbook: each of the 3 steps followed red→green→commit with no rework to production code, the `maxTurns`-via-`execution` delegation decision from planning held, and the "vacuously-passing" observer tests (verified in the retro) correctly converted to real assertions once the observer was implemented.
61
-
62
- #### What caused friction (agent side)
63
-
64
- - `instruction-violation` (gate-caught, at ship) — wrote a second `[#421]:` link-reference definition into the retro file when appending the TDD stage entry via `Write` full-content, tripping `MD053` (duplicate definition).
65
- The `markdown-conventions` skill states this rule verbatim ("Link reference definitions are file-scoped … a duplicate trips MD053").
66
- Impact: one fix commit at ship time (`80d4d050`), caught by the root `pnpm run lint` pre-push gate rather than during TDD (no lint runs after stage-notes writing).
67
- - `missing-context` (self-identified during ship investigation) — the TDD green-baseline lint was run package-scoped (`pnpm --filter @gotgenes/pi-subagents run lint`), which **silently passes** on `MD051` cross-file fragment failures.
68
- Verified empirically: package `lint:md` (`rumdl check *.md docs/**/*.md`) returns "No issues" on the broken fragment, while root `rumdl check .` exits 1 on it — the cross-file fragment target (`../architecture.md`) is only resolved on a repo-root tree walk.
69
- Impact: the pre-existing `MD051` failure slipped past the baseline gate (whose job is to catch exactly that) and surfaced mid-TDD via the reviewer, costing a fix commit (`86ed0c81`) and a reviewer FAIL/re-dispatch cycle.
70
-
71
- #### What caused friction (user side)
72
-
73
- - None.
74
- The session ran end-to-end without user correction; the operator-authored, roadmap-aligned issue meant no clarification was needed.
75
-
76
- ### Diagnostic details
77
-
78
- - **Model-performance correlation** — two `pre-completion-reviewer` subagent dispatches ran on the agent's configured reviewer model and performed judgment-heavy review work (acceptance criteria, design review, cross-step invariants); appropriate match.
79
- No high-cost model was spent on mechanical work and no reasoning-weak model on judgment work.
80
- - **Feedback-loop gap analysis** — the lint feedback loop fired at the wrong scope and the wrong time: package-scoped at baseline (missed `MD051`), and absent after retro stage-notes writing (missed `MD053` until ship).
81
- `pnpm run check` and `pnpm run test` were run incrementally per step and caught everything they should; only the markdown-lint loop was misconfigured.
82
- - **Escalation-delay / unused-tool** — no `rabbit-hole` friction; no lens-2 or lens-3 findings.
83
-
84
- ### Changes made
85
-
86
- 1. `.pi/prompts/tdd-plan.md` — "Verify green baseline" step 2 and "After the last TDD step" step 3 now specify `pnpm run lint` runs **from the repo root**, with a one-clause rationale that package-scoped lint silently passes on `MD051` cross-file fragments and cross-package issues (Proposal 1).
87
- 2. Proposal 2 (an `MD053` duplicate-link-definition reminder in the retro-writing prompts) was declined — the rule already exists verbatim in the `markdown-conventions` skill, so a prompt clause would duplicate it.
88
- 3. Follow-up (post-retro): `#420` completed Phase 18 Step 1 but the roadmap Steps section was not marked done until the operator noticed.
89
- Added a roadmap-step-status check so this is caught going forward: a WARN bullet in `pre-completion-reviewer.md` §2c (backstop), and a proactive step in `.pi/prompts/tdd-plan.md` step 7 and `.pi/prompts/build-plan.md` "After the last step" — mark the completed roadmap step done (`✅`/`Landed:`) and update the phase status row.
90
- Also marked Step 1 complete in `architecture.md` (Steps list, dependency diagram node, phase table row → "In progress").