@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.
- package/CHANGELOG.md +7 -0
- package/docs/architecture/architecture.md +157 -204
- package/docs/architecture/history/phase-19-implement-ui-decisions.md +282 -0
- package/package.json +5 -6
- package/src/lifecycle/subagent.ts +5 -9
- package/src/observation/notification.ts +23 -10
- package/src/observation/subagent-events-observer.ts +1 -3
- package/src/tools/get-result-report.ts +60 -0
- package/src/tools/get-result-tool.ts +25 -40
- package/src/types.ts +1 -1
- package/src/ui/session-navigator.ts +0 -2
- package/.prettierignore +0 -5
- package/AGENTS.md +0 -7
- package/docs/plans/0048-implement-subagents-api.md +0 -304
- package/docs/plans/0049-remove-group-join-output-file-rpc.md +0 -180
- package/docs/plans/0051-update-adr-0001-hard-fork.md +0 -77
- package/docs/plans/0052-remove-scheduled-subagents.md +0 -133
- package/docs/plans/0053-extract-model-resolution-from-execute.md +0 -181
- package/docs/plans/0054-decompose-index-into-modules.md +0 -302
- package/docs/plans/0057-structured-debug-logging.md +0 -154
- package/docs/plans/0061-session-format-transcript.md +0 -284
- package/docs/plans/0066-replace-as-any-with-sdk-types.md +0 -215
- package/docs/plans/0069-create-subagent-runtime.md +0 -345
- package/docs/plans/0070-extract-event-handlers.md +0 -306
- package/docs/plans/0071-extract-session-config-assembler.md +0 -362
- package/docs/plans/0072-inject-agent-manager-collaborators.md +0 -329
- package/docs/plans/0076-inject-cwd-into-agent-manager.md +0 -102
- package/docs/plans/0077-inject-project-agents-dir.md +0 -115
- package/docs/plans/0080-consolidate-agent-config-lookup.md +0 -247
- package/docs/plans/0084-extract-git-worktree-manager.md +0 -142
- package/docs/plans/0087-evolve-subagent-runtime-methods.md +0 -240
- package/docs/plans/0098-extract-agent-record-state-machine.md +0 -435
- package/docs/plans/0099-replace-ctx-with-parent-snapshot.md +0 -488
- package/docs/plans/0100-replace-callback-threading-with-session-subscription.md +0 -454
- package/docs/plans/0102-consolidate-test-record-factory.md +0 -176
- package/docs/plans/0108-extract-agent-type-registry.md +0 -322
- package/docs/plans/0109-extract-settings-manager.md +0 -276
- package/docs/plans/0110-agent-activity-tracker.md +0 -297
- package/docs/plans/0111-split-agent-record-lifecycle.md +0 -582
- package/docs/plans/0112-replace-agent-manager-callbacks.md +0 -241
- package/docs/plans/0113-disambiguate-spawn-options.md +0 -155
- package/docs/plans/0114-narrow-agent-tool-menu-deps.md +0 -279
- package/docs/plans/0115-decompose-agent-tool.md +0 -337
- package/docs/plans/0116-type-housekeeping.md +0 -351
- package/docs/plans/0118-settings-manager-apply-methods.md +0 -271
- package/docs/plans/0123-remove-vi-fn-cast-smell.md +0 -179
- package/docs/plans/0131-consolidate-shared-test-fixtures.md +0 -207
- package/docs/plans/0132-inject-io-into-session-config.md +0 -219
- package/docs/plans/0133-inject-sdk-boundary-into-agent-runner.md +0 -373
- package/docs/plans/0134-reduce-as-any-casts.md +0 -366
- package/docs/plans/0135-extract-display-helpers.md +0 -182
- package/docs/plans/0136-decompose-agent-menu.md +0 -300
- package/docs/plans/0144-consolidate-observation-model.md +0 -263
- package/docs/plans/0145-decompose-execute-push-ctx-to-boundary.md +0 -290
- package/docs/plans/0146-narrow-ui-context.md +0 -319
- package/docs/plans/0147-inject-wrap-text-into-conversation-viewer.md +0 -166
- package/docs/plans/0148-split-agent-widget-rendering.md +0 -255
- package/docs/plans/0152-add-prompt-snippet.md +0 -91
- package/docs/plans/0164-reorganize-into-domain-directories.md +0 -409
- package/docs/plans/0165-decompose-resolved-spawn-config.md +0 -157
- package/docs/plans/0166-extract-parent-session-info.md +0 -231
- package/docs/plans/0167-narrow-runner-io.md +0 -150
- package/docs/plans/0168-extract-tool-filter-config.md +0 -173
- package/docs/plans/0169-extract-run-context-from-run-options.md +0 -194
- package/docs/plans/0170-reduce-build-content-lines-complexity.md +0 -225
- package/docs/plans/0171-reduce-render-result-complexity.md +0 -200
- package/docs/plans/0172-extract-turn-formatting.md +0 -206
- package/docs/plans/0180-reorder-append-prompt-for-kv-cache.md +0 -100
- package/docs/plans/0185-remove-persistent-agent-memory.md +0 -161
- package/docs/plans/0188-replace-any-casts-with-sdk-types.md +0 -162
- package/docs/plans/0192-define-session-context-interface.md +0 -107
- package/docs/plans/0193-runtime-owns-context-queries.md +0 -245
- package/docs/plans/0194-align-tool-interfaces-for-structural-typing.md +0 -139
- package/docs/plans/0195-convert-tool-factories-to-classes.md +0 -264
- package/docs/plans/0196-convert-runner-menu-to-classes.md +0 -268
- package/docs/plans/0205-decompose-render-widget-lines.md +0 -140
- package/docs/plans/0206-decompose-show-agent-detail.md +0 -211
- package/docs/plans/0207-decompose-agent-widget-update.md +0 -242
- package/docs/plans/0208-extract-shared-test-fixtures.md +0 -298
- package/docs/plans/0214-convert-remaining-closure-factories-to-classes.md +0 -261
- package/docs/plans/0215-decompose-build-parent-context.md +0 -166
- package/docs/plans/0216-decompose-start-agent.md +0 -255
- package/docs/plans/0217-extract-overwrite-guard.md +0 -176
- package/docs/plans/0218-push-sdk-boundary-in-settings.md +0 -172
- package/docs/plans/0219-reduce-test-duplication-top-3-clone-families.md +0 -162
- package/docs/plans/0227-evolve-agent-record-into-agent.md +0 -322
- package/docs/plans/0228-async-start-agent-dissolve-run-handle.md +0 -288
- package/docs/plans/0229-agent-born-complete.md +0 -564
- package/docs/plans/0230-extract-concurrency-queue.md +0 -265
- package/docs/plans/0231-push-exec-registry-to-runner.md +0 -245
- package/docs/plans/0232-agent-resume-internal-observer-lifecycle.md +0 -180
- package/docs/plans/0237-remove-disallowed-tools.md +0 -180
- package/docs/plans/0238-remove-extensions-filtering.md +0 -191
- package/docs/plans/0239-collapse-filter-active-tools.md +0 -217
- package/docs/plans/0242-rename-agent-tool-to-subagent.md +0 -165
- package/docs/plans/0256-extract-worktree-isolation.md +0 -256
- package/docs/plans/0257-extract-child-session-factory.md +0 -285
- package/docs/plans/0262-add-workspace-provider-seam.md +0 -264
- package/docs/plans/0264-remove-extension-lifecycle-control.md +0 -277
- package/docs/plans/0265-born-complete-subagent-session.md +0 -333
- package/docs/plans/0270-type-consumable-public-surface.md +0 -204
- package/docs/plans/0272-export-workspace-collaborator-types.md +0 -147
- package/docs/plans/0277-encapsulate-agent-session.md +0 -304
- package/docs/plans/0280-rename-agent-to-subagent.md +0 -197
- package/docs/plans/0360-custom-agents-default-append.md +0 -132
- package/docs/plans/0373-extract-subagent-state.md +0 -250
- package/docs/plans/0374-encapsulate-subagent-start-notification.md +0 -268
- package/docs/plans/0375-extract-run-listener-workspace-bracket.md +0 -300
- package/docs/plans/0376-extract-manager-observer.md +0 -232
- package/docs/plans/0377-split-widget-delegation-from-runtime.md +0 -254
- package/docs/plans/0378-consolidate-lifecycle-test-fixtures.md +0 -243
- package/docs/plans/0379-consolidate-ui-tools-test-fixtures.md +0 -335
- package/docs/plans/0380-extract-layered-settings-loader.md +0 -223
- package/docs/plans/0381-replace-concurrency-queue-with-limiter.md +0 -267
- package/docs/plans/0400-include-parent-prompt-in-replace-mode.md +0 -199
- package/docs/plans/0403-abort-subagents-on-interrupt.md +0 -180
- package/docs/plans/0412-unify-session-mock-builders.md +0 -146
- package/docs/plans/0420-fold-run-metrics-live-activity-onto-record.md +0 -228
- package/docs/plans/0421-migrate-activity-readers-to-record-getters.md +0 -309
- package/docs/plans/0422-delete-activity-tracker-ui-observer.md +0 -204
- package/docs/plans/0423-widget-self-drive-from-lifecycle.md +0 -264
- package/docs/plans/0424-drop-widget-dep-from-subagent-tool.md +0 -166
- package/docs/plans/0425-reconcile-subagent-events-contract.md +0 -144
- package/docs/plans/0426-consolidate-residual-test-clone-families.md +0 -235
- package/docs/plans/0427-reconsider-ui-direction.md +0 -212
- package/docs/plans/0441-remove-agent-definition-management-subtree.md +0 -180
- package/docs/plans/0442-dissolve-agents-conversation-viewer.md +0 -195
- package/docs/plans/0443-consolidate-remaining-test-clone-families.md +0 -268
- package/docs/plans/0444-shrink-widget-to-background-agents.md +0 -156
- package/docs/plans/0445-native-session-navigation.md +0 -365
- package/docs/plans/0446-spike-session-navigation-entry-criteria.md +0 -171
- package/docs/plans/0447-extract-subagents-settings-command.md +0 -220
- package/docs/plans/0448-block-disabled-agent-spawn.md +0 -207
- package/docs/plans/0462-navigation-renderer-tui-components.md +0 -338
- package/docs/plans/0463-file-snapshot-source-evicted-agents.md +0 -306
- package/docs/plans/0470-refresh-readme-command-surface.md +0 -159
- package/docs/retro/0048-implement-subagents-api.md +0 -44
- package/docs/retro/0049-remove-group-join-output-file-rpc.md +0 -49
- package/docs/retro/0051-update-adr-0001-hard-fork.md +0 -39
- package/docs/retro/0053-extract-model-resolution-from-execute.md +0 -40
- package/docs/retro/0054-decompose-index-into-modules.md +0 -53
- package/docs/retro/0057-structured-debug-logging.md +0 -77
- package/docs/retro/0061-session-format-transcript.md +0 -41
- package/docs/retro/0066-replace-as-any-with-sdk-types.md +0 -44
- package/docs/retro/0069-create-subagent-runtime.md +0 -43
- package/docs/retro/0070-extract-event-handlers.md +0 -49
- package/docs/retro/0071-extract-session-config-assembler.md +0 -60
- package/docs/retro/0072-inject-agent-manager-collaborators.md +0 -46
- package/docs/retro/0076-inject-cwd-into-agent-manager.md +0 -35
- package/docs/retro/0077-inject-project-agents-dir.md +0 -33
- package/docs/retro/0080-consolidate-agent-config-lookup.md +0 -35
- package/docs/retro/0084-extract-git-worktree-manager.md +0 -37
- package/docs/retro/0087-evolve-subagent-runtime-methods.md +0 -42
- package/docs/retro/0098-extract-agent-record-state-machine.md +0 -46
- package/docs/retro/0099-replace-ctx-with-parent-snapshot.md +0 -37
- package/docs/retro/0100-replace-callback-threading-with-session-subscription.md +0 -36
- package/docs/retro/0102-consolidate-test-record-factory.md +0 -30
- package/docs/retro/0108-extract-agent-type-registry.md +0 -41
- package/docs/retro/0109-extract-settings-manager.md +0 -55
- package/docs/retro/0110-agent-activity-tracker.md +0 -44
- package/docs/retro/0111-split-agent-record-lifecycle.md +0 -61
- package/docs/retro/0112-replace-agent-manager-callbacks.md +0 -35
- package/docs/retro/0113-disambiguate-spawn-options.md +0 -29
- package/docs/retro/0114-narrow-agent-tool-menu-deps.md +0 -38
- package/docs/retro/0115-decompose-agent-tool.md +0 -51
- package/docs/retro/0116-type-housekeeping.md +0 -42
- package/docs/retro/0118-settings-manager-apply-methods.md +0 -40
- package/docs/retro/0123-remove-vi-fn-cast-smell.md +0 -49
- package/docs/retro/0131-consolidate-shared-test-fixtures.md +0 -46
- package/docs/retro/0132-inject-io-into-session-config.md +0 -33
- package/docs/retro/0133-inject-sdk-boundary-into-agent-runner.md +0 -45
- package/docs/retro/0134-reduce-as-any-casts.md +0 -56
- package/docs/retro/0135-extract-display-helpers.md +0 -38
- package/docs/retro/0136-decompose-agent-menu.md +0 -43
- package/docs/retro/0144-consolidate-observation-model.md +0 -39
- package/docs/retro/0145-decompose-execute-push-ctx-to-boundary.md +0 -56
- package/docs/retro/0146-narrow-ui-context.md +0 -70
- package/docs/retro/0147-inject-wrap-text-into-conversation-viewer.md +0 -90
- package/docs/retro/0148-split-agent-widget-rendering.md +0 -39
- package/docs/retro/0152-add-prompt-snippet.md +0 -34
- package/docs/retro/0164-reorganize-into-domain-directories.md +0 -82
- package/docs/retro/0165-decompose-resolved-spawn-config.md +0 -78
- package/docs/retro/0166-extract-parent-session-info.md +0 -66
- package/docs/retro/0167-narrow-runner-io.md +0 -63
- package/docs/retro/0168-extract-tool-filter-config.md +0 -76
- package/docs/retro/0169-extract-run-context-from-run-options.md +0 -68
- package/docs/retro/0170-reduce-build-content-lines-complexity.md +0 -72
- package/docs/retro/0171-reduce-render-result-complexity.md +0 -77
- package/docs/retro/0172-extract-turn-formatting.md +0 -80
- package/docs/retro/0180-reorder-append-prompt-for-kv-cache.md +0 -62
- package/docs/retro/0185-remove-persistent-agent-memory.md +0 -73
- package/docs/retro/0188-replace-any-casts-with-sdk-types.md +0 -69
- package/docs/retro/0192-define-session-context-interface.md +0 -59
- package/docs/retro/0193-runtime-owns-context-queries.md +0 -75
- package/docs/retro/0194-align-tool-interfaces-for-structural-typing.md +0 -62
- package/docs/retro/0195-convert-tool-factories-to-classes.md +0 -84
- package/docs/retro/0196-convert-runner-menu-to-classes.md +0 -73
- package/docs/retro/0205-decompose-render-widget-lines.md +0 -64
- package/docs/retro/0206-decompose-show-agent-detail.md +0 -67
- package/docs/retro/0207-decompose-agent-widget-update.md +0 -92
- package/docs/retro/0208-extract-shared-test-fixtures.md +0 -102
- package/docs/retro/0214-convert-remaining-closure-factories-to-classes.md +0 -66
- package/docs/retro/0215-decompose-build-parent-context.md +0 -61
- package/docs/retro/0216-decompose-start-agent.md +0 -80
- package/docs/retro/0217-extract-overwrite-guard.md +0 -63
- package/docs/retro/0218-push-sdk-boundary-in-settings.md +0 -72
- package/docs/retro/0219-reduce-test-duplication-top-3-clone-families.md +0 -64
- package/docs/retro/0227-evolve-agent-record-into-agent.md +0 -80
- package/docs/retro/0228-async-start-agent-dissolve-run-handle.md +0 -80
- package/docs/retro/0229-agent-born-complete.md +0 -89
- package/docs/retro/0230-extract-concurrency-queue.md +0 -38
- package/docs/retro/0231-push-exec-registry-to-runner.md +0 -71
- package/docs/retro/0232-agent-resume-internal-observer-lifecycle.md +0 -109
- package/docs/retro/0237-remove-disallowed-tools.md +0 -78
- package/docs/retro/0238-remove-extensions-filtering.md +0 -72
- package/docs/retro/0239-collapse-filter-active-tools.md +0 -70
- package/docs/retro/0242-rename-agent-tool-to-subagent.md +0 -82
- package/docs/retro/0256-extract-worktree-isolation.md +0 -89
- package/docs/retro/0257-extract-child-session-factory.md +0 -33
- package/docs/retro/0262-add-workspace-provider-seam.md +0 -89
- package/docs/retro/0264-remove-extension-lifecycle-control.md +0 -91
- package/docs/retro/0265-born-complete-subagent-session.md +0 -97
- package/docs/retro/0270-type-consumable-public-surface.md +0 -108
- package/docs/retro/0272-export-workspace-collaborator-types.md +0 -38
- package/docs/retro/0277-encapsulate-agent-session.md +0 -80
- package/docs/retro/0280-rename-agent-to-subagent.md +0 -96
- package/docs/retro/0360-custom-agents-default-append.md +0 -81
- package/docs/retro/0373-extract-subagent-state.md +0 -94
- package/docs/retro/0374-encapsulate-subagent-start-notification.md +0 -171
- package/docs/retro/0375-extract-run-listener-workspace-bracket.md +0 -104
- package/docs/retro/0376-extract-manager-observer.md +0 -81
- package/docs/retro/0377-split-widget-delegation-from-runtime.md +0 -105
- package/docs/retro/0378-consolidate-lifecycle-test-fixtures.md +0 -100
- package/docs/retro/0379-consolidate-ui-tools-test-fixtures.md +0 -52
- package/docs/retro/0380-extract-layered-settings-loader.md +0 -97
- package/docs/retro/0381-replace-concurrency-queue-with-limiter.md +0 -95
- package/docs/retro/0400-include-parent-prompt-in-replace-mode.md +0 -84
- package/docs/retro/0403-abort-subagents-on-interrupt.md +0 -90
- package/docs/retro/0412-unify-session-mock-builders.md +0 -80
- package/docs/retro/0420-fold-run-metrics-live-activity-onto-record.md +0 -90
- package/docs/retro/0421-migrate-activity-readers-to-record-getters.md +0 -105
- package/docs/retro/0422-delete-activity-tracker-ui-observer.md +0 -97
- package/docs/retro/0423-widget-self-drive-from-lifecycle.md +0 -112
- package/docs/retro/0424-drop-widget-dep-from-subagent-tool.md +0 -89
- package/docs/retro/0425-reconcile-subagent-events-contract.md +0 -101
- package/docs/retro/0426-consolidate-residual-test-clone-families.md +0 -100
- package/docs/retro/0427-reconsider-ui-direction.md +0 -102
- package/docs/retro/0441-remove-agent-definition-management-subtree.md +0 -97
- package/docs/retro/0442-dissolve-agents-conversation-viewer.md +0 -108
- package/docs/retro/0443-consolidate-remaining-test-clone-families.md +0 -28
- package/docs/retro/0444-shrink-widget-to-background-agents.md +0 -81
- package/docs/retro/0445-native-session-navigation.md +0 -122
- package/docs/retro/0446-spike-session-navigation-entry-criteria.md +0 -99
- package/docs/retro/0447-extract-subagents-settings-command.md +0 -91
- package/docs/retro/0448-block-disabled-agent-spawn.md +0 -75
- package/docs/retro/0462-navigation-renderer-tui-components.md +0 -105
- package/docs/retro/0463-file-snapshot-source-evicted-agents.md +0 -103
- package/docs/retro/0470-refresh-readme-command-surface.md +0 -40
- package/src/observation/notification-state.ts +0 -27
- package/vitest.config.ts +0 -14
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [18.0.2](https://github.com/gotgenes/pi-packages/compare/pi-subagents-v18.0.1...pi-subagents-v18.0.2) (2026-07-14)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Documentation
|
|
12
|
+
|
|
13
|
+
* **pi-subagents:** drop NotificationState from architecture and skill after result-delivery extraction ([99dae2c](https://github.com/gotgenes/pi-packages/commit/99dae2cd631ed41b5ef2ea0565660d72eb4e788f))
|
|
14
|
+
|
|
8
15
|
## [18.0.1](https://github.com/gotgenes/pi-packages/compare/pi-subagents-v18.0.0...pi-subagents-v18.0.1) (2026-06-24)
|
|
9
16
|
|
|
10
17
|
|
|
@@ -114,7 +114,7 @@ classDiagram
|
|
|
114
114
|
+toolUses: number
|
|
115
115
|
+lifetimeUsage: LifetimeUsage
|
|
116
116
|
+subagentSession?: SubagentSession
|
|
117
|
-
+
|
|
117
|
+
+toolCallId?: string
|
|
118
118
|
+markRunning() delegates
|
|
119
119
|
+markCompleted() delegates
|
|
120
120
|
+run()
|
|
@@ -318,8 +318,7 @@ src/
|
|
|
318
318
|
│
|
|
319
319
|
├── observation/ progress tracking and notification
|
|
320
320
|
│ ├── record-observer.ts session-event stats observer
|
|
321
|
-
│ ├── notification.ts completion nudges
|
|
322
|
-
│ ├── notification-state.ts per-agent notification tracking
|
|
321
|
+
│ ├── notification.ts completion nudges + per-agent consumed-result tracking
|
|
323
322
|
│ ├── renderer.ts notification TUI component
|
|
324
323
|
│ ├── composite-subagent-observer.ts fans manager notifications out to multiple observers
|
|
325
324
|
│ └── subagent-events-observer.ts manager lifecycle observer (event emission + persistence + notification)
|
|
@@ -335,6 +334,7 @@ src/
|
|
|
335
334
|
│ ├── foreground-runner.ts foreground execution loop
|
|
336
335
|
│ ├── background-spawner.ts background spawn setup
|
|
337
336
|
│ ├── get-result-tool.ts get_subagent_result tool
|
|
337
|
+
│ ├── get-result-report.ts pure get_subagent_result report formatter
|
|
338
338
|
│ ├── steer-tool.ts steer_subagent tool
|
|
339
339
|
│ └── helpers.ts shared tool utilities
|
|
340
340
|
│
|
|
@@ -645,17 +645,17 @@ That method — testability friction as a boundary probe, with its limits — is
|
|
|
645
645
|
|
|
646
646
|
### Health metrics
|
|
647
647
|
|
|
648
|
-
| Metric | Value
|
|
649
|
-
| -------------------------- |
|
|
650
|
-
| Health score | 78/100 (B)
|
|
651
|
-
| Total LOC | 7,
|
|
652
|
-
| Dead code | 0 files, 0 exports
|
|
653
|
-
| Maintainability index |
|
|
654
|
-
| Avg cyclomatic complexity | 1.4
|
|
655
|
-
| P90 cyclomatic complexity | 2
|
|
656
|
-
| Production duplication |
|
|
657
|
-
| Test duplication |
|
|
658
|
-
| Fallow refactoring targets | 0
|
|
648
|
+
| Metric | Value |
|
|
649
|
+
| -------------------------- | --------------------------- |
|
|
650
|
+
| Health score | 78/100 (B), end of Phase 19 |
|
|
651
|
+
| Total LOC | 7,068 (57 files) |
|
|
652
|
+
| Dead code | 0 files, 0 exports |
|
|
653
|
+
| Maintainability index | 91.0 (good) |
|
|
654
|
+
| Avg cyclomatic complexity | 1.4 |
|
|
655
|
+
| P90 cyclomatic complexity | 2 |
|
|
656
|
+
| Production duplication | 0 lines |
|
|
657
|
+
| Test duplication | 9 clone groups, 81 lines |
|
|
658
|
+
| Fallow refactoring targets | 0 |
|
|
659
659
|
|
|
660
660
|
### Dependency bag inventory
|
|
661
661
|
|
|
@@ -674,8 +674,6 @@ Bags with 10+ fields are the highest priority for decomposition.
|
|
|
674
674
|
| `SubagentSessionIO` | split → `EnvironmentIO` (3) + `SessionFactoryIO` (5+1) | create-subagent-session | ✓ done |
|
|
675
675
|
| `CreateSessionOptions` | 9 | create-subagent-session (SDK bridge) | Low (SDK) |
|
|
676
676
|
| `AgentToolDeps` | 8 | agent-tool | ✓ done |
|
|
677
|
-
| `AgentMenuDeps` | 8 | agent-menu | ✓ done |
|
|
678
|
-
| `ConversationViewerOptions` | 8 | conversation-viewer | Low |
|
|
679
677
|
| `SubagentInit` | 5 (id, type, description, invocation, execution, state) | subagent (one production site) | ✓ done |
|
|
680
678
|
| `SubagentExecution` | 12 (4 mandatory: factory, snapshot, prompt, baseCwd) | subagent (mandatory collaborator) | ✓ done |
|
|
681
679
|
|
|
@@ -689,23 +687,22 @@ No functions remain above the critical threshold — all hotspots resolved in Ph
|
|
|
689
687
|
|
|
690
688
|
Files with highest commit frequency × complexity:
|
|
691
689
|
|
|
692
|
-
| Score | File
|
|
693
|
-
| ----- |
|
|
694
|
-
|
|
|
695
|
-
| 9.
|
|
696
|
-
| 8.
|
|
697
|
-
|
|
|
698
|
-
|
|
|
699
|
-
|
|
|
690
|
+
| Score | File | Commits | Trend |
|
|
691
|
+
| ----- | ----------------------------- | ------- | -------------- |
|
|
692
|
+
| 27.1 | `index.ts` | 109 | ▼ cooling |
|
|
693
|
+
| 9.6 | `tools/agent-tool.ts` | 56 | ▼ cooling |
|
|
694
|
+
| 8.8 | `ui/agent-widget.ts` | 22 | ▼ cooling |
|
|
695
|
+
| 7.3 | `tools/foreground-runner.ts` | 22 | ▼ cooling |
|
|
696
|
+
| 6.6 | `service/service-adapter.ts` | 15 | ▲ accelerating |
|
|
697
|
+
| 6.3 | `config/custom-agents.ts` | 13 | ▼ cooling |
|
|
700
698
|
|
|
701
|
-
|
|
702
|
-
`index.ts` remains the sole accelerating hotspot — expected as the wiring entry point for each refactoring phase.
|
|
699
|
+
`index.ts` remains the top churn hotspot but has cooled after the Phase 19 terminal cut removed its four `/agents`-wiring blocks; `service-adapter.ts` is now the sole accelerating file.
|
|
703
700
|
|
|
704
701
|
### Production duplication
|
|
705
702
|
|
|
706
703
|
The prior clone group between `agent-runner.ts` and `message-formatters.ts` was resolved in #172.
|
|
707
704
|
The 20-line clone group between `agent-config-editor.ts` and `agent-creation-wizard.ts` was resolved in #217 — extracted into `ui/agent-file-writer.ts` (`writeAgentFile`).
|
|
708
|
-
|
|
705
|
+
The final 11-line internal clone group within `agent-config-editor.ts` was eliminated in Phase 19 Step 6 ([#441]) when the file itself was deleted; production duplication is 0 lines.
|
|
709
706
|
|
|
710
707
|
### Session encapsulation debt (Law of Demeter) — resolved by [#277] ✔️
|
|
711
708
|
|
|
@@ -905,262 +902,205 @@ Source LOC decreased from 7,751 (62 files) to 7,650 (61 files); tests grew from
|
|
|
905
902
|
All eight steps are closed: [#420], [#421], [#422], [#423], [#424], [#425], [#426], [#427].
|
|
906
903
|
See [phase-18-reconsider-ui.md](history/phase-18-reconsider-ui.md) for the full findings, step outcomes, dependency diagram, and tracks.
|
|
907
904
|
|
|
908
|
-
## Phase 19 (
|
|
905
|
+
## Phase 19 (complete)
|
|
909
906
|
|
|
910
|
-
Phase 19
|
|
907
|
+
Phase 19 implemented the per-component UI decisions recorded in [ADR-0004]: it shrank the widget to background-only agents, replaced the bespoke conversation viewer with native session navigation dual-sourced by liveness (live record or persisted-file snapshot) and rendered through Pi's own per-entry TUI components, extracted subagent settings to a focused `/subagents-settings` command, and dissolved the monolithic `/agents` menu in a two-commit terminal cut (hub first, then the orphaned agent-definition-management subtree).
|
|
908
|
+
Production duplication dropped to 0 lines; test clone groups dropped from 16 to 9 (target: ≤ 10); source shrank from 7,650 LOC (61 files) to 7,068 LOC (57 files).
|
|
909
|
+
All nine steps are closed: [#446], [#447], [#444], [#445], [#462], [#463], [#442], [#441], [#443].
|
|
910
|
+
A follow-on issue, [#470] (README staleness after the terminal cut), was filed and closed independently.
|
|
911
|
+
See [phase-19-implement-ui-decisions.md](history/phase-19-implement-ui-decisions.md) for the full findings, step outcomes, dependency diagram, and tracks.
|
|
911
912
|
|
|
912
|
-
|
|
913
|
-
The end state deletes `agent-menu.ts` — the god-command that bundles four unrelated jobs — and everything reachable only from it.
|
|
914
|
-
Rather than surgically mutate that doomed module (and the #1 churn hotspot `index.ts`) once per option, Phase 19 first stands up the replacement surfaces additively, then removes the now-orphaned subtree in a single terminal cut.
|
|
915
|
-
This keeps every responsibility's old surface live until its replacement exists (ADR-0004's no-interim-regression invariant), turns the three replacement steps into genuinely parallel work (none touch `agent-menu.ts`), and reduces `index.ts` edits from four surgical removals to one deregistration.
|
|
913
|
+
## Phase 20 improvement roadmap
|
|
916
914
|
|
|
917
|
-
|
|
915
|
+
Phase 20 realizes the last un-extracted domain from the [first-principles refinement](#first-principles-refinement-and-the-deeper-target) — **result delivery** — and clears the residual boundary and complexity debt discovery surfaced around it.
|
|
918
916
|
|
|
919
|
-
|
|
920
|
-
- **Phase B — dissolve `/agents` (terminal cut):** delete the orphaned subtree in two deletion commits, one per subtree (Steps 5–6).
|
|
921
|
-
- **Phase C — test health:** consolidate the test clones that survive the cut (Step 7).
|
|
917
|
+
Discovery findings (fallow + entry-point trace + test-constructibility audit, 2026-07-03):
|
|
922
918
|
|
|
923
|
-
|
|
919
|
+
1. `NotificationState` (`toolCallId`, `resultConsumed`) still lives on `Subagent`; `get-result-tool` reaches through `record.notification?.markConsumed()` twice, always paired with `notifications.cancelNudge(id)` — the doc's own "homeless field" (result-delivery domain) plus a scattered two-step reset.
|
|
920
|
+
2. Both `steer-tool` and `service-adapter` pre-check `status !== "running"` before calling `record.steer()` — ask-then-tell, contradicting the target's "tell by id, with outcomes" rule.
|
|
921
|
+
3. Five file-level eslint-disable headers (`agent-tool` disables 6 rules; `spawn-config` and `agent-widget` 4 each; `model-resolver` 2; `index` 1) and `model: unknown`/`Model<any>`/`any` threading through 8 files mark the SDK type boundary as the largest remaining `any` surface.
|
|
922
|
+
4. Three src functions carry HIGH CRAP scores (notification renderer arrow 79.4, `service-adapter.spawn` 71.3, `get-result-tool.execute` 63.6 — resolved by Step 2); `subagents-settings.handle` (13 cyclomatic, 24 cognitive) is three copy-pasted select→input→validate→apply branches; `service-adapter.ts` is the sole accelerating churn file.
|
|
923
|
+
5. `createTestSubagent` is the most complex function in the workspace (19 cyclomatic, 25 cognitive) because `SubagentStateInit` accepts only transition fields, forcing mutation loops to seed metrics — a Category D "shared factory complexity" signal pointing at the production init surface.
|
|
924
|
+
6. Test duplication sits at 9 in-package clone groups (81 lines), at the ≤ 10 target but with two consolidatable clone families.
|
|
924
925
|
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
| Health score | 78/100 (B) | 83/100 (B+) |
|
|
928
|
-
| Source LOC | 7,650 (61 files) | ~6,780 (~55 files) |
|
|
929
|
-
| Production duplication | 11 lines (1 group) | 0 lines |
|
|
930
|
-
| Test clone groups | 16 | ≤ 10 |
|
|
931
|
-
| Top churn hotspot | `index.ts` (103 commits) | `index.ts` (cooling) |
|
|
926
|
+
No finding scores ≥ 20 on the priority scale (Impact × (6 − Risk)); the phase is a should-fix band (10–15) consolidation.
|
|
927
|
+
Directory organization is healthy (seven domain directories, six root files) — no reorg this phase.
|
|
932
928
|
|
|
933
|
-
###
|
|
929
|
+
### Health metrics (Phase 20)
|
|
934
930
|
|
|
935
|
-
|
|
936
|
-
|
|
931
|
+
| Metric | Phase 19 (end) | Phase 20 target |
|
|
932
|
+
| ------------------------------------------------ | ---------------- | ---------------------- |
|
|
933
|
+
| Health score | 78/100 (B) | ≥ 78 (B) |
|
|
934
|
+
| Source LOC | 7,068 (57 files) | ~7,050 (no net growth) |
|
|
935
|
+
| `record.notification?.` reach-throughs | 4 sites | 0 |
|
|
936
|
+
| Steer status pre-checks outside `Subagent.steer` | 2 sites | 0 |
|
|
937
|
+
| src functions with CRAP ≥ 60 | 3 | 0 |
|
|
938
|
+
| File-level eslint-disable headers | 5 | ≤ 2 |
|
|
939
|
+
| `createTestSubagent` cyclomatic | 19 | ≤ 8 |
|
|
940
|
+
| Test clone groups (in-package) | 9 (81 lines) | ≤ 5 (≤ 40 lines) |
|
|
937
941
|
|
|
938
|
-
|
|
942
|
+
### Steps
|
|
939
943
|
|
|
940
|
-
|
|
941
|
-
2. **View-only vs interactive:** `switchSession` (full interactive takeover) or `loadEntriesFromFile` (read-only transcript built from JSONL)?
|
|
942
|
-
3. **Parallel-agent navigation:** Operator gesture to select which of N background agents to view (from the widget, a command, or both).
|
|
943
|
-
4. **Settings command name:** `/subagents-settings`, `/agents-settings`, or another form consistent with sibling packages?
|
|
944
|
+
#### ✅ Step 1 — Extract result delivery from `Subagent` ([#535])
|
|
944
945
|
|
|
945
|
-
|
|
946
|
-
No production source files change; the spike closes when the ADR addendum is merged.
|
|
947
|
-
|
|
948
|
-
Outcome: ADR-0004 updated with all four entry-criteria answers; Step 4 unblocked.
|
|
949
|
-
|
|
950
|
-
`Release: independent`
|
|
951
|
-
|
|
952
|
-
### ✅ Step 2 — Extract settings to a focused `/subagents-settings` command ([#447])
|
|
953
|
-
|
|
954
|
-
Smell: Category E (naming/organization) — settings are buried inside the monolithic `/agents` command per ADR-0004 Decision C. This step is purely additive: it stands up the new surface without touching `agent-menu.ts`.
|
|
946
|
+
Smell: Category C (anemic domain / misplaced state, Law of Demeter, scattered resets) — the result-delivery domain named in the first-principles refinement is still fused into the execution record.
|
|
955
947
|
Target files:
|
|
956
948
|
|
|
957
|
-
-
|
|
958
|
-
- `src/
|
|
959
|
-
-
|
|
949
|
+
- `src/lifecycle/subagent.ts` — drop `_notification` / `notification`; stop constructing `NotificationState` from `parentSession.toolCallId`.
|
|
950
|
+
- `src/observation/notification.ts` — `NotificationManager` owns consumed-state keyed by agent id behind a single tell operation (e.g. `consume(id)`) that also cancels the pending nudge.
|
|
951
|
+
- `src/observation/notification-state.ts` — dissolve into the manager or move wholly into the observation domain.
|
|
952
|
+
- `src/observation/subagent-events-observer.ts`, `src/tools/get-result-tool.ts` — call the new delivery interface instead of reaching through the record.
|
|
960
953
|
|
|
961
|
-
`
|
|
962
|
-
The
|
|
954
|
+
The `toolCallId` needed by `formatTaskNotification` already travels on `execution.parentSession`; expose it without routing through a notification object.
|
|
955
|
+
The pre-await consumption ordering (the "Bug 1" race tests in `test/lifecycle/subagent-manager.test.ts`) is a preserved invariant — consuming before awaiting must still suppress the completion nudge.
|
|
963
956
|
|
|
964
|
-
Outcome:
|
|
957
|
+
Outcome: zero `record.notification?.` reach-throughs in `src/`; `Subagent` carries no notification field; delivery state lives in the observation domain.
|
|
965
958
|
|
|
966
|
-
`
|
|
959
|
+
Landed: `notification-state.ts` deleted; `Subagent.toolCallId` getter added over `execution.parentSession`; `NotificationManager` owns `consumed: Set<string>` behind one `consume(id)` tell that adds to the set and cancels the pending nudge atomically.
|
|
960
|
+
Collapsing the old two-step reset (`markConsumed()` + `cancelNudge()`) into one atomic operation structurally eliminates the historical "Bug 1" race rather than just reordering it — `consume()` now suppresses the nudge regardless of whether it runs before or after the completion promise resolves, as long as it runs within the 200 ms hold window.
|
|
967
961
|
|
|
968
|
-
|
|
962
|
+
`Release: batch "result-delivery"`
|
|
969
963
|
|
|
970
|
-
|
|
964
|
+
#### ✅ Step 2 — Decompose `get-result-tool.execute` ([#536])
|
|
965
|
+
|
|
966
|
+
Smell: Category B (oversized function) — 61 lines, 15 cyclomatic, CRAP 63.6; mixes wait/consume policy, stats formatting, and output assembly.
|
|
971
967
|
Target files:
|
|
972
968
|
|
|
973
|
-
- `src/
|
|
974
|
-
- `
|
|
975
|
-
- `test/ui/agent-widget.test.ts` — add background-only filtering tests; update assertions.
|
|
969
|
+
- `src/tools/get-result-tool.ts` — extract a pure report formatter (status line, stats parts, body selection) alongside the existing `result-renderer.ts` pattern; consume via the Step 1 delivery interface.
|
|
970
|
+
- `test/tools/get-result-tool.test.ts` — unit-test the pure formatter directly.
|
|
976
971
|
|
|
977
|
-
|
|
978
|
-
Filtering at only one site leaves the other rendering foreground agents, so the enabling move is to route both through one accessor and apply the predicate once at the source.
|
|
979
|
-
`Subagent.invocation.runInBackground` is the reliable signal: set by `spawn-config.ts` → `AgentInvocation.runInBackground` → stored on `Subagent.invocation`.
|
|
980
|
-
ADR-0004 Decision A: foreground runs suppress the widget; the inline `onUpdate` stream is authoritative there.
|
|
972
|
+
Outcome: `execute` ≤ 30 lines with cyclomatic < 10; off the fallow high-complexity list.
|
|
981
973
|
|
|
982
|
-
|
|
974
|
+
Landed: `src/tools/get-result-report.ts` added — `AgentReport` value object plus `renderStatsParts` / `renderReportBody` / `formatAgentReport` pure functions, unit-tested directly in `test/tools/get-result-report.test.ts`.
|
|
975
|
+
`GetResultTool.execute` now owns only record lookup and the wait/consume policy (13 lines), delegating report assembly to a private `buildReport` + `formatAgentReport`; output is byte-identical.
|
|
976
|
+
`get-result-tool.execute` is off the HIGH-CRAP list (3 → 2 remaining: `service-adapter.spawn`, the notification renderer arrow).
|
|
983
977
|
|
|
984
|
-
`Release:
|
|
978
|
+
`Release: batch "result-delivery"`
|
|
985
979
|
|
|
986
|
-
|
|
980
|
+
#### Step 3 — `Subagent.steer` returns an outcome ([#537])
|
|
987
981
|
|
|
988
|
-
Smell: Category C (
|
|
989
|
-
This step adds the new surface alongside the existing viewer; it does not touch `agent-menu.ts`.
|
|
982
|
+
Smell: Category C (ask-then-tell) — coordinators pre-check status before telling.
|
|
990
983
|
Target files:
|
|
991
984
|
|
|
992
|
-
-
|
|
993
|
-
-
|
|
994
|
-
|
|
985
|
+
- `src/lifecycle/subagent.ts` — `steer` owns the non-running rejection and returns a discriminated outcome (`delivered` / `buffered` / `rejected` with the observed status).
|
|
986
|
+
- `src/tools/steer-tool.ts`, `src/service/service-adapter.ts` — drop the status pre-checks and switch on the outcome; the adapter maps the outcome to the public `SubagentsService.steer` boolean, so the published contract is unchanged.
|
|
987
|
+
|
|
988
|
+
Outcome: zero steer status pre-checks outside `Subagent.steer`; `steer-tool.execute` cyclomatic drops below 10.
|
|
995
989
|
|
|
996
|
-
|
|
997
|
-
Mechanism (confirmed by the Step 1 spike and revised by [ADR-0004] Addendum 2): a **read-only** (non-interactive) transcript **dual-sourced by liveness**, rendered through Pi's own public entry components (no bespoke renderer).
|
|
990
|
+
`Release: independent`
|
|
998
991
|
|
|
999
|
-
|
|
1000
|
-
- **Evicted / untracked agent** — render from the file snapshot: `parseSessionEntries(readFileSync(record.outputFile, "utf8"))` → drop the `SessionHeader` → `buildSessionContext(...).messages`.
|
|
992
|
+
#### Step 4 — Type the model boundary ([#538])
|
|
1001
993
|
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
`Subagent.outputFile` already exposes the persisted child session JSONL path via `subagentSession?.outputFile` — no new SDK dependency.
|
|
1005
|
-
The new surface stands up while the old `viewAgentConversation`/`ConversationViewer` path still works; the bespoke viewer is removed only by the terminal cut (Step 5).
|
|
994
|
+
Smell: Category C (platform type threading) — `ModelRegistry.find/getAll/getAvailable` return `any`, forcing `any`/`unknown` model threading through `model-resolver`, `spawn-config`, `service-adapter`, and `parent-snapshot`.
|
|
995
|
+
Target files:
|
|
1006
996
|
|
|
1007
|
-
|
|
997
|
+
- `src/session/model-resolver.ts` — type the registry against `Model<any>` from `@earendil-works/pi-ai` (already imported elsewhere); remove the file-level eslint-disable; extract the fuzzy-scoring loop as a named helper if `resolveModel` (17 cyclomatic, 60 lines) still trips the threshold.
|
|
998
|
+
- `src/service/service-adapter.ts` — type the resolved model in `spawn` (16 cyclomatic, CRAP 71.3, sole accelerating churn file) and extract the model-resolution branch.
|
|
999
|
+
- `src/tools/spawn-config.ts` — shrink the 4-rule file-level disable to line-level or remove it.
|
|
1008
1000
|
|
|
1009
|
-
|
|
1010
|
-
It is **live-source only** behind a renderer-agnostic `TranscriptSource` seam, rendered via Pi's `serializeConversation` text.
|
|
1011
|
-
With the `manager.listAgents()`-only candidate set, no listed record is ever session-disposed (dispose-and-delete are atomic), so the file-snapshot branch has no reachable caller and was deferred to keep `fallow dead-code` clean.
|
|
1012
|
-
Step 4 (#445, the slice) is complete and released (`pi-subagents` v17.3.0); the remaining work is now tracked as two follow-up steps behind the same seam: Step 4a ([#462]) upgrades the renderer from `serializeConversation` text to Pi's per-entry TUI components (gates Step 5 for rendering parity); Step 4b ([#463]) broadens the candidate set to evicted agents and adds the file-snapshot source (`parseSessionEntries` → `buildSessionContext`, independent).
|
|
1001
|
+
Outcome: `model-resolver.ts` file-level eslint-disable removed; `service-adapter.spawn` off the HIGH CRAP list; `any` model returns eliminated from the resolver.
|
|
1013
1002
|
|
|
1014
|
-
`Release: independent`
|
|
1003
|
+
`Release: independent`
|
|
1015
1004
|
|
|
1016
|
-
|
|
1005
|
+
#### Step 5 — Narrow `tui`/`theme` render interfaces ([#539])
|
|
1017
1006
|
|
|
1018
|
-
Smell: Category C (
|
|
1019
|
-
|
|
1020
|
-
This step swaps the renderer behind the existing `TranscriptSource` seam (`src/ui/session-navigation.ts` / `session-navigator.ts`) for Pi's per-entry components (`AssistantMessageComponent` / `ToolExecutionComponent` / …); selection and sourcing are untouched.
|
|
1007
|
+
Smell: Category C/D (platform type threading; wide `any` params in render callbacks).
|
|
1008
|
+
Target files:
|
|
1021
1009
|
|
|
1022
|
-
|
|
1010
|
+
- `src/ui/agent-widget.ts` — replace `tui: any` with a lean local interface (`terminal.columns`, `requestRender()`); shrink the 4-rule file-level disable.
|
|
1011
|
+
- `src/tools/agent-tool.ts` — type `renderCall`/`renderResult` params (`theme`, `result`) with lean local interfaces; shrink the 6-rule file-level disable to the genuinely SDK-gapped lines.
|
|
1012
|
+
- `src/tools/foreground-runner.ts` — retire the line-level `details as any` cast if the SDK surface allows.
|
|
1023
1013
|
|
|
1024
|
-
|
|
1014
|
+
Some disables are irreducible SDK export gaps; the goal is line-level precision, not zero.
|
|
1025
1015
|
|
|
1026
|
-
|
|
1027
|
-
The `TranscriptOverlay` caches that `Container` and rebuilds it on source change only (Pi's `rebuildChatFromMessages` path), keeping the lightweight `◍` streaming indicator.
|
|
1028
|
-
Tool calls render with their real `ToolDefinition`, resolved through a dependency-safe `getToolDefinition` read accessor on the record (mirroring `agentMessages`) surfaced on the `TranscriptSource` seam — no inbound call into the core.
|
|
1029
|
-
The pure `session-navigation.ts` sheds `renderTranscriptLines`/`serializeConversation`; rendering now lives in the SDK/TUI `session-navigator.ts`, which threads `cwd` from the command context.
|
|
1030
|
-
`custom`-role messages are skipped (the bespoke viewer never rendered them either).
|
|
1031
|
-
Selection and sourcing are untouched; native navigation now renders at parity, unblocking Step 5 for rendering fidelity.
|
|
1016
|
+
Outcome: file-level eslint-disable headers 5 → ≤ 2; remaining suppressions are line-level with named rules.
|
|
1032
1017
|
|
|
1033
1018
|
`Release: independent`
|
|
1034
1019
|
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
Smell: Category C (coupling) — the #445 slice sources transcripts live from `manager.listAgents()` only; an agent evicted by the 10-minute cleanup sweep has a persisted session JSONL but no live record, so it is unreachable.
|
|
1038
|
-
This step adds the file-snapshot `TranscriptSource` branch (`parseSessionEntries(readFile(outputFile))` → drop the `SessionHeader` → `buildSessionContext(...).messages`) and broadens the candidate set to evicted agents, behind the same seam; the renderer is untouched.
|
|
1020
|
+
#### Step 6 — Table-driven settings handler ([#540])
|
|
1039
1021
|
|
|
1040
|
-
|
|
1041
|
-
|
|
1022
|
+
Smell: Category B (function duplication inside one function) — `subagents-settings.handle` (13 cyclomatic, 24 cognitive, 52 lines) repeats the select→input→parse→validate→apply→notify flow three times.
|
|
1023
|
+
Target files:
|
|
1042
1024
|
|
|
1043
|
-
|
|
1025
|
+
- `src/ui/subagents-settings.ts` — describe each numeric setting as a descriptor (label, prompt, minimum, validation message, apply method) and drive one loop over the table.
|
|
1026
|
+
- `test/ui/subagents-settings.test.ts` — assert per-descriptor behavior.
|
|
1044
1027
|
|
|
1045
|
-
|
|
1046
|
-
The candidate set is broadened via **manager-retained descriptors**, not a directory scan: the persisted child session carries no subagent `type`/`description` (those live only on the in-memory record), so a scan would yield degraded labels and parse every file per open.
|
|
1047
|
-
Instead `SubagentManager.cleanup()` stashes a lightweight `EvictedSubagent` descriptor (label fields + `outputFile`, no messages) before disposing a record with a persisted file, exposed via `listEvicted()` and cleared by `clearCompleted()`/`dispose()`.
|
|
1048
|
-
`NavigationEntry` became a `live | evicted` discriminated union; the handler selects `liveSource` vs `fileSnapshotSource` by kind inside a `try/catch` (an unreadable file notifies and skips), and `index.ts` injects `readFileSync`.
|
|
1049
|
-
Evicted entries carry an `· evicted (snapshot)` label marker.
|
|
1050
|
-
Coverage is in-session evictions (the sweep's only targets); old-session orphan files — the ones a scan would surface with degraded labels — are out of scope.
|
|
1028
|
+
Outcome: `handle` cyclomatic ≤ 6 and cognitive ≤ 10; off the fallow high-complexity list.
|
|
1051
1029
|
|
|
1052
1030
|
`Release: independent`
|
|
1053
1031
|
|
|
1054
|
-
|
|
1032
|
+
#### Step 7 — Decompose the notification renderer ([#541])
|
|
1055
1033
|
|
|
1056
|
-
Smell: Category
|
|
1057
|
-
This is the first of two deletion commits (split by subtree).
|
|
1058
|
-
The hub `agent-menu.ts` is deleted here, not surgically narrowed, and deleting it is what orphans the leaf subtrees — so it must precede the definition-management deletion (Step 6), because `agent-menu.ts` statically imports the wizard, editor, and file-ops, and dynamically imports the viewer.
|
|
1034
|
+
Smell: Category B/D (oversized arrow, untested complexity) — the renderer arrow in `src/observation/renderer.ts` is fallow's top triage concern (17 cyclomatic, CRAP 79.4).
|
|
1059
1035
|
Target files:
|
|
1060
1036
|
|
|
1061
|
-
- `src/
|
|
1062
|
-
-
|
|
1063
|
-
- Delete `src/ui/conversation-viewer.ts` (241 LOC) and `test/conversation-viewer.test.ts` (239 LOC) — its only consumer is `agent-menu.ts`'s dynamic import, gone with the hub.
|
|
1064
|
-
- Delete `src/ui/message-formatters.ts` (195 LOC) and `test/message-formatters.test.ts` (388 LOC, the largest test function by LOC) — its only consumer is `ConversationViewer`.
|
|
1037
|
+
- `src/observation/renderer.ts` — extract pure line-assembly helpers (status→icon/label selection, stats-parts assembly, preview truncation) that are unit-testable without `Text` or a theme; the arrow becomes a thin wrapper.
|
|
1038
|
+
- `test/observation/renderer.test.ts` — test the pure helpers directly.
|
|
1065
1039
|
|
|
1066
|
-
|
|
1067
|
-
Deleting the hub in one move avoids any surgical edit to the doomed file and leaves the definition-management leaves orphaned for Step 6.
|
|
1040
|
+
Soft ordering: land after Step 1 so the notification-domain files settle first.
|
|
1068
1041
|
|
|
1069
|
-
|
|
1070
|
-
Without the prep commit, deleting either subtree first would have left the other half referencing a deleted module.
|
|
1071
|
-
`index.ts` also shed the now-dead `join` (node:path) and `buildParentSnapshot` imports in addition to the two module imports.
|
|
1072
|
-
The `menu-ui.ts` module is transient and is removed with the wizard/editor in Step 6.
|
|
1042
|
+
Outcome: renderer arrow cyclomatic < 10; `renderer.ts` off the top of the fallow triage list.
|
|
1073
1043
|
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
`Release: batch "dissolve-agents"`
|
|
1044
|
+
`Release: independent`
|
|
1077
1045
|
|
|
1078
|
-
|
|
1046
|
+
#### Step 8 — Full-value `SubagentStateInit` ([#542])
|
|
1079
1047
|
|
|
1080
|
-
Smell: Category
|
|
1081
|
-
This is the second deletion commit (split by subtree).
|
|
1048
|
+
Smell: Category D (shared factory complexity → narrow/complete the production init surface) — `createTestSubagent` (19 cyclomatic, 25 cognitive) seeds metrics via mutation loops because `SubagentStateInit` accepts only transition fields.
|
|
1082
1049
|
Target files:
|
|
1083
1050
|
|
|
1084
|
-
-
|
|
1085
|
-
-
|
|
1086
|
-
- Delete `src/ui/agent-file-ops.ts` (59 LOC) and `test/ui/agent-file-ops.test.ts` (112 LOC) — only consumers were wizard + editor.
|
|
1087
|
-
- Delete `src/ui/agent-file-writer.ts` (55 LOC) and `test/ui/agent-file-writer.test.ts` (148 LOC) — only consumers were wizard + editor.
|
|
1088
|
-
- `test/helpers/ui-stubs.ts` — delete `makeFileOps`, `createTestSubagentConfig`, and `spawnAndWait` from `makeMenuManager` if no surviving consumer remains; delete the file outright once all consumers are gone.
|
|
1089
|
-
|
|
1090
|
-
An operator generates a new agent `.md` by asking a Pi session directly (more capable than a fixed wizard) or by writing the file in an editor; viewing and editing definitions is served by opening the `.md` files in an editor or IDE.
|
|
1091
|
-
These files are orphaned by Step 5, so this is a pure `git rm` with no surviving references and no edit to any doomed file.
|
|
1051
|
+
- `src/lifecycle/subagent-state.ts` — extend `SubagentStateInit` to optionally seed the full value (toolUses, lifetimeUsage, compactionCount, turnCount, activeTools, responseText); a value object is legitimately constructible at any point in its value space.
|
|
1052
|
+
- `test/helpers/make-subagent.ts` — collapse the mutation loops into direct init.
|
|
1092
1053
|
|
|
1093
|
-
Outcome:
|
|
1054
|
+
Outcome: `createTestSubagent` cyclomatic ≤ 8; off the fallow complexity list; no production behavior change.
|
|
1094
1055
|
|
|
1095
|
-
|
|
1096
|
-
`test/helpers/ui-stubs.ts` pruned to `makeMenuUI` only (still consumed by `subagents-settings.test.ts`); `makeFileOps`, `makeMenuManager`, and `createTestSubagentConfig` removed with their `ui-stubs.test.ts` describe blocks.
|
|
1097
|
-
Production duplication: 0 lines (confirmed by `fallow dupes`); `fallow dead-code`: clean. 16 test clone groups remain — Step 7 consolidation target.
|
|
1098
|
-
|
|
1099
|
-
`Release: batch "dissolve-agents"`
|
|
1056
|
+
`Release: independent`
|
|
1100
1057
|
|
|
1101
|
-
|
|
1058
|
+
#### Step 9 — Consolidate remaining test clone families ([#543])
|
|
1102
1059
|
|
|
1103
|
-
Smell: Category D (
|
|
1104
|
-
|
|
1105
|
-
Target files:
|
|
1060
|
+
Smell: Category D (test duplication) — two clone families (`spawn-config.test.ts`: 2 groups / 21 lines; `subagent-manager.test.ts`: 2 groups / 15 lines) plus the `session-config.test.ts` pair (16 lines).
|
|
1061
|
+
Target files: the three test files and `test/helpers/` as needed.
|
|
1106
1062
|
|
|
1107
|
-
|
|
1108
|
-
- `test/ui/agent-widget.test.ts` — merge the duplicate `makeWidget` helper defined twice across two `describe` blocks (14-line clone at :225/:284).
|
|
1109
|
-
- `test/session/session-config.test.ts` — extract a shared fixture for the 16-line internal clone (lines 131–146 / 151–166).
|
|
1110
|
-
- `test/lifecycle/concurrency-limiter.test.ts` — extract shared setup for the 10-line clone (lines 21–30 / 148–155).
|
|
1111
|
-
- `test/tools/spawn-config.test.ts` — extract a shared fixture for the 9-line clone (lines 22–30 / 35–43).
|
|
1063
|
+
Runs last — Steps 1–3 and 8 rewrite portions of these suites, so consolidating first would churn twice.
|
|
1112
1064
|
|
|
1113
|
-
Outcome:
|
|
1065
|
+
Outcome: in-package clone groups 9 → ≤ 5; duplicated lines 81 → ≤ 40.
|
|
1114
1066
|
|
|
1115
1067
|
`Release: independent`
|
|
1116
1068
|
|
|
1117
|
-
### Step
|
|
1069
|
+
### Step dependencies
|
|
1118
1070
|
|
|
1119
1071
|
```mermaid
|
|
1120
1072
|
flowchart LR
|
|
1121
|
-
S1["✅ Step 1
|
|
1122
|
-
|
|
1123
|
-
S3["
|
|
1124
|
-
S4["
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
S1 --> S4
|
|
1132
|
-
S4 --> S4a
|
|
1133
|
-
S4 --> S4b
|
|
1134
|
-
S2 --> S5
|
|
1135
|
-
S3 --> S5
|
|
1136
|
-
S4a --> S5
|
|
1137
|
-
S5 --> S6
|
|
1138
|
-
S6 --> S7
|
|
1073
|
+
S1["✅ Step 1 (#535)<br/>Result delivery off Subagent"] --> S2["✅ Step 2 (#536)<br/>Decompose get-result-tool"]
|
|
1074
|
+
S1 -.soft.-> S7["Step 7 (#541)<br/>Decompose notification renderer"]
|
|
1075
|
+
S3["Step 3 (#537)<br/>Steer returns an outcome"]
|
|
1076
|
+
S4["Step 4 (#538)<br/>Type the model boundary"]
|
|
1077
|
+
S5["Step 5 (#539)<br/>Narrow tui/theme interfaces"]
|
|
1078
|
+
S6["Step 6 (#540)<br/>Table-driven settings handler"]
|
|
1079
|
+
S8["Step 8 (#542)<br/>Full-value SubagentStateInit"] --> S9["Step 9 (#543)<br/>Consolidate test clones"]
|
|
1080
|
+
S2 --> S9
|
|
1081
|
+
S3 --> S9
|
|
1139
1082
|
```
|
|
1140
1083
|
|
|
1141
|
-
The terminal cut (Step 5) depends on all three replacements — settings (Step 2), widget (Step 3), and session navigation **at rendering parity** (Step 4a, which completes the #445 slice) — because each of the four `/agents` options must have its responsibility re-homed, and the viewer replacement at parity, before its branch can die.
|
|
1142
|
-
Step 4b (file-snapshot source) is a new capability and gates nothing.
|
|
1143
|
-
The old `S1 → S6 → S7` chain hid the widget dependency; this diagram makes it explicit.
|
|
1144
|
-
|
|
1145
1084
|
### Parallel tracks
|
|
1146
1085
|
|
|
1147
|
-
- **Track A —
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
- **Track
|
|
1152
|
-
|
|
1153
|
-
|
|
1086
|
+
- **Track A — Result delivery:** Steps 1 → 2, then 7 (soft).
|
|
1087
|
+
- **Track B — Tell-don't-ask:** Step 3.
|
|
1088
|
+
- **Track C — SDK boundary:** Steps 4, 5 (independent of each other).
|
|
1089
|
+
- **Track D — UI polish:** Step 6.
|
|
1090
|
+
- **Track E — Test health:** Step 8, then 9 (9 also waits on Tracks A/B test churn).
|
|
1091
|
+
|
|
1092
|
+
Tracks A–D can proceed in parallel; only Step 9 serializes behind the rest.
|
|
1154
1093
|
|
|
1155
1094
|
### Release batches
|
|
1156
1095
|
|
|
1157
|
-
- **Batch "
|
|
1158
|
-
|
|
1159
|
-
|
|
1096
|
+
- **Batch "result-delivery":** Steps 1, 2 (ship together; tail = Step 2).
|
|
1097
|
+
- Independently releasable: Steps 3, 4, 5, 6, 7, 8, 9.
|
|
1098
|
+
|
|
1099
|
+
Every step lands as a `refactor:`/`test:` commit — hidden changelog types that cut no release on their own; the work auto-batches into the next unhidden release.
|
|
1160
1100
|
|
|
1161
1101
|
## Refactoring history
|
|
1162
1102
|
|
|
1163
|
-
Phases 1–5, 7–
|
|
1103
|
+
Phases 1–5, 7–19 are complete.
|
|
1164
1104
|
Phase 6 (UI extraction to a separate package) was deferred to Phase 18; its intent was resolved by [ADR-0004] (Phase 18 Step 8).
|
|
1165
1105
|
Detailed records are preserved in per-phase history files:
|
|
1166
1106
|
|
|
@@ -1184,6 +1124,7 @@ Detailed records are preserved in per-phase history files:
|
|
|
1184
1124
|
| 16 | Invert dependencies (extensions on a minimal core) | Complete | [phase-16-invert-dependencies.md](history/phase-16-invert-dependencies.md) |
|
|
1185
1125
|
| 17 | Core consolidation | Complete | [phase-17-core-consolidation.md](history/phase-17-core-consolidation.md) |
|
|
1186
1126
|
| 18 | Reconsider UI (first principles) | Complete | [phase-18-reconsider-ui.md](history/phase-18-reconsider-ui.md) |
|
|
1127
|
+
| 19 | Implement ADR-0004 UI decisions | Complete | [phase-19-implement-ui-decisions.md](history/phase-19-implement-ui-decisions.md) |
|
|
1187
1128
|
|
|
1188
1129
|
### Structural refactoring issues
|
|
1189
1130
|
|
|
@@ -1208,6 +1149,8 @@ Detailed records are preserved in per-phase history files:
|
|
|
1208
1149
|
| Phase 17 | #381, #373, #374, #375, #376, #377, #378, #379, #380 | ConcurrencyLimiter, SubagentState, run-start encapsulation, run collaborators, events observer, widget decoupling, lifecycle test fixtures, UI/tools test fixtures, settings-loader extraction |
|
|
1209
1150
|
| Phase 17 (follow-on) | #412, #415 | Session-mock builder unification, worktrees settings-helper migration |
|
|
1210
1151
|
| Phase 18 | #420, #421, #422, #423, #424, #425, #426, #427 | Fold metrics onto record, migrate readers, delete activity tier, widget self-drives, drop widget from tool, reconcile event contract, consolidate test clones, UI-direction ADR |
|
|
1152
|
+
| Phase 19 | #446, #447, #444, #445, #462, #463, #442, #441, #443 | ADR-0004 spike, settings command, background widget, native session nav slice, TUI renderer, file-snapshot source, dissolve /agents + viewer, remove definition mgmt, consolidate test clones |
|
|
1153
|
+
| Phase 19 (follow-on) | #470 | README refresh for the removed /agents command surface |
|
|
1211
1154
|
|
|
1212
1155
|
The remaining open issue is #22 (parent-session resolution), a cross-extension track that does not gate the structural work.
|
|
1213
1156
|
|
|
@@ -1280,5 +1223,15 @@ The upstream test suite is run periodically as a regression canary for the sessi
|
|
|
1280
1223
|
[#447]: https://github.com/gotgenes/pi-packages/issues/447
|
|
1281
1224
|
[#462]: https://github.com/gotgenes/pi-packages/issues/462
|
|
1282
1225
|
[#463]: https://github.com/gotgenes/pi-packages/issues/463
|
|
1226
|
+
[#470]: https://github.com/gotgenes/pi-packages/issues/470
|
|
1227
|
+
[#535]: https://github.com/gotgenes/pi-packages/issues/535
|
|
1228
|
+
[#536]: https://github.com/gotgenes/pi-packages/issues/536
|
|
1229
|
+
[#537]: https://github.com/gotgenes/pi-packages/issues/537
|
|
1230
|
+
[#538]: https://github.com/gotgenes/pi-packages/issues/538
|
|
1231
|
+
[#539]: https://github.com/gotgenes/pi-packages/issues/539
|
|
1232
|
+
[#540]: https://github.com/gotgenes/pi-packages/issues/540
|
|
1233
|
+
[#541]: https://github.com/gotgenes/pi-packages/issues/541
|
|
1234
|
+
[#542]: https://github.com/gotgenes/pi-packages/issues/542
|
|
1235
|
+
[#543]: https://github.com/gotgenes/pi-packages/issues/543
|
|
1283
1236
|
[ADR-0002]: ../decisions/0002-extensions-on-a-minimal-core.md
|
|
1284
1237
|
[ADR-0004]: ../decisions/0004-reconsider-ui-direction.md
|