@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
|
@@ -1,265 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
issue: 230
|
|
3
|
-
issue_title: "Extract ConcurrencyQueue from AgentManager (Phase 15, Step 5)"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Extract ConcurrencyQueue from AgentManager
|
|
7
|
-
|
|
8
|
-
## Problem Statement
|
|
9
|
-
|
|
10
|
-
`AgentManager` tangles two concerns: agent collection management and scheduling.
|
|
11
|
-
The scheduling concern — `queue[]`, `runningBackground`, `_getMaxConcurrent`, `drainQueue()`, `finalizeBackgroundRun()`, `notifyConcurrencyChanged()` — is 3 fields + 3 methods of cohesive, separable logic.
|
|
12
|
-
`notifyConcurrencyChanged()` is a scheduling method exposed as a public API on the wrong object so that `SettingsManager` can poke the queue after a concurrency limit change.
|
|
13
|
-
This cross-concern leak violates SRP and prevents independent testing of the queue.
|
|
14
|
-
|
|
15
|
-
## Goals
|
|
16
|
-
|
|
17
|
-
- Extract scheduling logic into a `ConcurrencyQueue` class in `src/lifecycle/concurrency-queue.ts`.
|
|
18
|
-
- Delete `notifyConcurrencyChanged()` from `AgentManager` — settings triggers drain on the queue directly via the existing callback wiring.
|
|
19
|
-
- Make scheduling independently testable with fast, focused unit tests.
|
|
20
|
-
- `AgentManager` becomes a pure collection manager (agents Map, lookup, cleanup, iteration) + observer wiring.
|
|
21
|
-
|
|
22
|
-
## Non-Goals
|
|
23
|
-
|
|
24
|
-
- Changing `SettingsManager` internals — `onMaxConcurrentChanged` callback stays; only the wiring target changes (queue.drain instead of manager.notifyConcurrencyChanged).
|
|
25
|
-
- Extracting `Agent.resume()` — tracked in #232.
|
|
26
|
-
- Changing the concurrency semantics (limits, drain order, foreground bypass).
|
|
27
|
-
|
|
28
|
-
## Background
|
|
29
|
-
|
|
30
|
-
### Dependencies
|
|
31
|
-
|
|
32
|
-
Both dependencies are implemented:
|
|
33
|
-
|
|
34
|
-
- Issue #229 (Agent.run()) — ✅ closed.
|
|
35
|
-
Agent owns its full execution lifecycle; `startAgent` and `SpawnArgs` are gone.
|
|
36
|
-
- Issue #231 (runner self-contained) — ✅ closed.
|
|
37
|
-
Agent holds the runner at construction.
|
|
38
|
-
|
|
39
|
-
### Current queue surface in AgentManager
|
|
40
|
-
|
|
41
|
-
| Member | Kind | Purpose |
|
|
42
|
-
| --------------------------------- | ------ | ------------------------------------------------ |
|
|
43
|
-
| `queue: string[]` | field | IDs of background agents waiting to start |
|
|
44
|
-
| `runningBackground: number` | field | Count of currently running background agents |
|
|
45
|
-
| `_getMaxConcurrent: () => number` | field | Injected getter for the concurrency limit |
|
|
46
|
-
| `drainQueue()` | method | Start queued agents up to the limit |
|
|
47
|
-
| `finalizeBackgroundRun()` | method | Decrement counter, notify observer, drain |
|
|
48
|
-
| `notifyConcurrencyChanged()` | method | Public entry point for settings to trigger drain |
|
|
49
|
-
|
|
50
|
-
These 6 members form a cohesive unit — they only reference each other and the agents Map (for status checks during drain).
|
|
51
|
-
|
|
52
|
-
### Callers of queue logic in AgentManager
|
|
53
|
-
|
|
54
|
-
- `spawn()` — checks `runningBackground >= getMaxConcurrent()`, pushes to `queue` or starts.
|
|
55
|
-
- `buildObserver().onStarted` — increments `runningBackground`.
|
|
56
|
-
- `buildObserver().onRunFinished` — calls `finalizeBackgroundRun()`.
|
|
57
|
-
- `abort()` — filters `queue` to remove an aborted ID.
|
|
58
|
-
- `abortAll()` — iterates `queue`, clears it.
|
|
59
|
-
- `waitForAll()` — calls `drainQueue()`.
|
|
60
|
-
- `dispose()` — clears `queue`.
|
|
61
|
-
|
|
62
|
-
### Agent comment to update
|
|
63
|
-
|
|
64
|
-
`agent.ts` line 366 has a comment: "Queue removal stays on AgentManager until #230 extracts ConcurrencyQueue."
|
|
65
|
-
This comment should be updated to remove the forward reference.
|
|
66
|
-
|
|
67
|
-
## Design Overview
|
|
68
|
-
|
|
69
|
-
### ConcurrencyQueue class
|
|
70
|
-
|
|
71
|
-
```typescript
|
|
72
|
-
export class ConcurrencyQueue {
|
|
73
|
-
private queue: string[] = [];
|
|
74
|
-
private running = 0;
|
|
75
|
-
|
|
76
|
-
constructor(
|
|
77
|
-
private readonly getMaxConcurrent: () => number,
|
|
78
|
-
private readonly startAgent: (id: string) => void,
|
|
79
|
-
) {}
|
|
80
|
-
|
|
81
|
-
isFull(): boolean;
|
|
82
|
-
enqueue(id: string): void;
|
|
83
|
-
dequeue(id: string): boolean;
|
|
84
|
-
markStarted(): void;
|
|
85
|
-
markFinished(): void; // running--, drain()
|
|
86
|
-
drain(): void;
|
|
87
|
-
get queuedIds(): readonly string[];
|
|
88
|
-
clear(): void;
|
|
89
|
-
}
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
### Design decision: stored start callback
|
|
93
|
-
|
|
94
|
-
The issue proposes `drain(start: (id: string) => void)` with the callback as a parameter.
|
|
95
|
-
However, the issue also proposes `markFinished()` as no-arg with "running--, drain()" semantics — which contradicts `drain` requiring a callback parameter.
|
|
96
|
-
|
|
97
|
-
Resolution: store the `startAgent` callback at construction.
|
|
98
|
-
This makes `drain()` and `markFinished()` both no-arg, follows Tell-Don't-Ask (the queue is a self-contained unit), and avoids requiring callers to pass the same callback repeatedly.
|
|
99
|
-
|
|
100
|
-
The `startAgent` callback is provided by the wiring layer (`index.ts`) using the established forward-reference-via-closure pattern already used for `onMaxConcurrentChanged`:
|
|
101
|
-
|
|
102
|
-
```typescript
|
|
103
|
-
// index.ts
|
|
104
|
-
const queue = new ConcurrencyQueue(
|
|
105
|
-
() => settings.maxConcurrent,
|
|
106
|
-
(id) => {
|
|
107
|
-
const agent = manager.getRecord(id);
|
|
108
|
-
if (agent?.status !== "queued") return;
|
|
109
|
-
agent.promise = agent.run();
|
|
110
|
-
},
|
|
111
|
-
);
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
### Ordering note
|
|
115
|
-
|
|
116
|
-
`markFinished()` calls `drain()` internally.
|
|
117
|
-
The current `finalizeBackgroundRun()` order is: decrement → observer notification → drain.
|
|
118
|
-
After extraction: `queue.markFinished()` (decrement + drain) → observer notification.
|
|
119
|
-
Drain fires before the observer notification.
|
|
120
|
-
|
|
121
|
-
This reordering is safe: `drain()` only starts promises (no await), and the observer notification (`onAgentCompleted`) processes the completed agent's data without referencing queue state.
|
|
122
|
-
|
|
123
|
-
### AgentManager after extraction
|
|
124
|
-
|
|
125
|
-
```typescript
|
|
126
|
-
export interface AgentManagerOptions {
|
|
127
|
-
runner: AgentRunner;
|
|
128
|
-
worktrees: WorktreeManager;
|
|
129
|
-
queue: ConcurrencyQueue; // was: getMaxConcurrent
|
|
130
|
-
getRunConfig?: () => RunConfig;
|
|
131
|
-
observer?: AgentManagerObserver;
|
|
132
|
-
}
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
`AgentManager` loses `queue`, `runningBackground`, `_getMaxConcurrent`, `drainQueue()`, `finalizeBackgroundRun()`, `notifyConcurrencyChanged()`.
|
|
136
|
-
|
|
137
|
-
### Settings wiring
|
|
138
|
-
|
|
139
|
-
Before:
|
|
140
|
-
|
|
141
|
-
```typescript
|
|
142
|
-
onMaxConcurrentChanged: () => manager.notifyConcurrencyChanged(),
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
After:
|
|
146
|
-
|
|
147
|
-
```typescript
|
|
148
|
-
onMaxConcurrentChanged: () => queue.drain(),
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
`SettingsManager` itself does not change — it still invokes the stored callback.
|
|
152
|
-
The callback wiring in `index.ts` targets the queue directly instead of the manager.
|
|
153
|
-
|
|
154
|
-
### Consumer call site (AgentManager.buildObserver)
|
|
155
|
-
|
|
156
|
-
```typescript
|
|
157
|
-
private buildObserver(options: AgentSpawnConfig): AgentLifecycleObserver {
|
|
158
|
-
return {
|
|
159
|
-
onStarted: (agent) => {
|
|
160
|
-
if (options.isBackground) this.queue.markStarted();
|
|
161
|
-
this.observer?.onAgentStarted(agent);
|
|
162
|
-
},
|
|
163
|
-
onRunFinished: (agent) => {
|
|
164
|
-
if (options.isBackground) {
|
|
165
|
-
this.queue.markFinished();
|
|
166
|
-
try { this.observer?.onAgentCompleted(agent); }
|
|
167
|
-
catch (err) { debugLog("onAgentCompleted observer", err); }
|
|
168
|
-
}
|
|
169
|
-
},
|
|
170
|
-
// onSessionCreated, onCompacted unchanged
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
### Test helper (createManager)
|
|
176
|
-
|
|
177
|
-
```typescript
|
|
178
|
-
function createManager(overrides?: { ...; getMaxConcurrent?: () => number; }) {
|
|
179
|
-
let mgr: AgentManager;
|
|
180
|
-
const queue = new ConcurrencyQueue(
|
|
181
|
-
overrides?.getMaxConcurrent ?? (() => 4),
|
|
182
|
-
(id) => {
|
|
183
|
-
const record = mgr.getRecord(id);
|
|
184
|
-
if (record?.status !== "queued") return;
|
|
185
|
-
record.promise = record.run();
|
|
186
|
-
},
|
|
187
|
-
);
|
|
188
|
-
mgr = new AgentManager({ ..., queue });
|
|
189
|
-
return { manager: mgr, ..., queue };
|
|
190
|
-
}
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
The forward-reference-via-closure is safe because `drain()` is never called during construction.
|
|
194
|
-
The `getMaxConcurrent` parameter name stays in the test helper for readability; it's passed to `ConcurrencyQueue`.
|
|
195
|
-
|
|
196
|
-
## Module-Level Changes
|
|
197
|
-
|
|
198
|
-
| File | Change |
|
|
199
|
-
| ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
200
|
-
| `src/lifecycle/concurrency-queue.ts` | **Add** — new `ConcurrencyQueue` class |
|
|
201
|
-
| `src/lifecycle/agent-manager.ts` | **Change** — remove 3 fields, 3 methods; add `queue: ConcurrencyQueue` to options; update `buildObserver`, `spawn`, `abort`, `abortAll`, `waitForAll`, `dispose` |
|
|
202
|
-
| `src/lifecycle/agent.ts` | **Change** — update comment on `abort()` (remove #230 forward reference) |
|
|
203
|
-
| `src/index.ts` | **Change** — create `ConcurrencyQueue`, pass to manager, wire settings to `queue.drain()` |
|
|
204
|
-
| `test/lifecycle/concurrency-queue.test.ts` | **Add** — unit tests for ConcurrencyQueue |
|
|
205
|
-
| `test/lifecycle/agent-manager.test.ts` | **Change** — update `createManager` helper to construct ConcurrencyQueue; no queue-behavior tests removed (they remain as integration tests) |
|
|
206
|
-
| `docs/architecture/architecture.md` | **Change** — add `concurrency-queue.ts` to layout listing; update agent-manager description |
|
|
207
|
-
|
|
208
|
-
## Test Impact Analysis
|
|
209
|
-
|
|
210
|
-
### New unit tests enabled by extraction
|
|
211
|
-
|
|
212
|
-
1. `isFull()` boundary — returns false when running < max, true when running >= max.
|
|
213
|
-
2. `enqueue()` / `dequeue()` — add/remove from queue, dequeue returns false for missing ID.
|
|
214
|
-
3. `markStarted()` / `markFinished()` — increment/decrement running count.
|
|
215
|
-
4. `drain()` — calls `startAgent` for each queued ID until full; skips when already full; handles empty queue.
|
|
216
|
-
5. `markFinished()` auto-drain — decrement triggers drain of next queued agent.
|
|
217
|
-
6. `clear()` — empties queue without starting agents.
|
|
218
|
-
7. `queuedIds` — snapshot of queue for iteration.
|
|
219
|
-
|
|
220
|
-
These tests were previously impossible because queue logic was interleaved with agent creation, observer notifications, and session management in `AgentManager`.
|
|
221
|
-
|
|
222
|
-
### Existing tests that stay as-is
|
|
223
|
-
|
|
224
|
-
- "queueing and concurrency with injected stubs" — integration tests verifying end-to-end spawn→queue→drain through the full AgentManager stack.
|
|
225
|
-
They still provide value as wiring tests.
|
|
226
|
-
- All observer notification tests — test observer wiring which stays in AgentManager.
|
|
227
|
-
- Bug race condition tests, worktree tests, execution state tests, lifecycle observer forwarding tests — independent of queue.
|
|
228
|
-
|
|
229
|
-
### Existing tests that need updating
|
|
230
|
-
|
|
231
|
-
- `createManager` helper — accepts `getMaxConcurrent` but passes it to `ConcurrencyQueue` constructor instead of `AgentManagerOptions`.
|
|
232
|
-
|
|
233
|
-
## TDD Order
|
|
234
|
-
|
|
235
|
-
1. **Red→Green: ConcurrencyQueue class + tests.**
|
|
236
|
-
New `src/lifecycle/concurrency-queue.ts` with `isFull`, `enqueue`, `dequeue`, `markStarted`, `markFinished`, `drain`, `clear`, `queuedIds`.
|
|
237
|
-
New `test/lifecycle/concurrency-queue.test.ts` covering: full boundary, enqueue/dequeue, start/finish counting, drain ordering, markFinished auto-drain, clear, empty-queue no-op.
|
|
238
|
-
Commit: `feat(pi-subagents): add ConcurrencyQueue class (#230)`
|
|
239
|
-
|
|
240
|
-
2. **Red→Green: Migrate AgentManager to use ConcurrencyQueue.**
|
|
241
|
-
Update `AgentManagerOptions`: replace `getMaxConcurrent` with `queue: ConcurrencyQueue`.
|
|
242
|
-
Update constructor, `buildObserver`, `spawn`, `abort`, `abortAll`, `waitForAll`, `dispose`.
|
|
243
|
-
Delete: `queue` field, `runningBackground` field, `_getMaxConcurrent` field, `notifyConcurrencyChanged()`, `drainQueue()`, `finalizeBackgroundRun()`.
|
|
244
|
-
Update `test/lifecycle/agent-manager.test.ts`: revise `createManager` helper to construct `ConcurrencyQueue` internally.
|
|
245
|
-
Update `src/index.ts`: construct `ConcurrencyQueue`, pass to `AgentManager`, wire `onMaxConcurrentChanged` to `queue.drain()`.
|
|
246
|
-
Update `src/lifecycle/agent.ts`: remove #230 forward-reference comment on `abort()`.
|
|
247
|
-
Run `pnpm run check` after this step.
|
|
248
|
-
Commit: `refactor(pi-subagents): replace inline queue with ConcurrencyQueue (#230)`
|
|
249
|
-
|
|
250
|
-
3. **Docs: Update architecture.**
|
|
251
|
-
Update `docs/architecture/architecture.md`: add `concurrency-queue.ts` to layout listing under `lifecycle/`, update `agent-manager.ts` description from "collection manager + concurrency controller" to "collection manager + observer wiring".
|
|
252
|
-
Commit: `docs(pi-subagents): update architecture for ConcurrencyQueue extraction (#230)`
|
|
253
|
-
|
|
254
|
-
## Risks and Mitigations
|
|
255
|
-
|
|
256
|
-
| Risk | Mitigation |
|
|
257
|
-
| ------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
258
|
-
| Forward-reference-via-closure in test helper and index.ts could break if drain is called during construction | ConcurrencyQueue constructor does not call drain; drain is only called after agents exist. Same pattern already used for `onMaxConcurrentChanged`. |
|
|
259
|
-
| `markFinished()` auto-drain changes ordering (drain before observer notification) | Verified: observer notification only processes the completed agent's data and does not reference queue state. Drain starts promises without awaiting — no observable behavior change. |
|
|
260
|
-
| `markStarted()` called synchronously inside drain loop could miscount | Verified: `Agent.run()` calls `observer.onStarted()` synchronously before the first await, so `markStarted()` fires before control returns to the drain while-loop. The running count is always current. |
|
|
261
|
-
| Integration tests in agent-manager.test.ts break after migration | Tests continue to work because the `createManager` helper constructs the ConcurrencyQueue internally with the same `getMaxConcurrent` semantics. Queue behavior is preserved. |
|
|
262
|
-
|
|
263
|
-
## Open Questions
|
|
264
|
-
|
|
265
|
-
None — the issue's proposed change is unambiguous and both dependencies are implemented.
|
|
@@ -1,245 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
issue: 231
|
|
3
|
-
issue_title: "Push exec/registry relay deps to runner construction (Phase 15, Step 3)"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Push exec/registry relay deps to runner construction
|
|
7
|
-
|
|
8
|
-
## Problem Statement
|
|
9
|
-
|
|
10
|
-
`AgentManager` receives `exec` and `registry` in its constructor but never uses them directly.
|
|
11
|
-
They are stored as fields solely to relay them into `runner.run()` via the `RunContext` parameter.
|
|
12
|
-
This makes `AgentManager` wider than necessary and prevents the runner from being self-contained — a prerequisite for #229 (Agent.run() absorbs startAgent).
|
|
13
|
-
|
|
14
|
-
## Goals
|
|
15
|
-
|
|
16
|
-
- Move `exec` and `registry` from `AgentManager` construction to `ConcreteAgentRunner` construction.
|
|
17
|
-
- Remove `exec` and `registry` from `AgentManagerOptions` (7 → 5 fields).
|
|
18
|
-
- Remove `exec` and `registry` from `RunContext` (4 → 2 fields).
|
|
19
|
-
- Group runner-owned dependencies in a `RunnerDeps` interface: `{ io, exec, registry }`.
|
|
20
|
-
- Replace `runAgent()`'s `io: RunnerIO` parameter with `deps: RunnerDeps`.
|
|
21
|
-
|
|
22
|
-
## Non-Goals
|
|
23
|
-
|
|
24
|
-
- Dissolving `RunContext` entirely — it shrinks to `{ cwd?, parentSession? }`, which is still a coherent per-call grouping.
|
|
25
|
-
Issue #229 will likely dissolve it when `Agent.run()` calls the runner directly.
|
|
26
|
-
- Changing the `AgentRunner` interface's `run()` signature — callers continue to pass `RunOptions` with `context: RunContext`.
|
|
27
|
-
`ConcreteAgentRunner` merges its stored deps before calling `runAgent()`.
|
|
28
|
-
- Touching `resume()` or `resumeAgent()` — they don't use `exec` or `registry`.
|
|
29
|
-
|
|
30
|
-
## Background
|
|
31
|
-
|
|
32
|
-
Issue #169 extracted `RunContext` from `RunOptions` to group the 4 parent-context fields: `exec`, `registry`, `cwd`, `parentSession`.
|
|
33
|
-
The doc comment describes them as "parent environment and identity" fields.
|
|
34
|
-
However, 2 of the 4 fields (`exec`, `registry`) are static — identical across every `run()` call — while the other 2 (`cwd`, `parentSession`) vary per spawn.
|
|
35
|
-
The static pair are relay-only dependencies on `AgentManager`: stored at construction, never read, only forwarded.
|
|
36
|
-
|
|
37
|
-
From the code-design skill, this is a **parameter relay** smell: intermediaries (`AgentManager`) carry fields they never use, only to thread them to the endpoint (`runAgent`).
|
|
38
|
-
The fix: put them on the object the endpoint owns — the runner.
|
|
39
|
-
|
|
40
|
-
### Key references
|
|
41
|
-
|
|
42
|
-
- `src/lifecycle/agent-manager.ts` — stores `exec` and `registry`, relays them at lines 193–194.
|
|
43
|
-
- `src/lifecycle/agent-runner.ts` — `RunContext` interface (line 125), `ConcreteAgentRunner` class (line 189), `runAgent()` free function (line 236).
|
|
44
|
-
- `src/index.ts` — constructs both `ConcreteAgentRunner` and `AgentManager` (lines 148–157).
|
|
45
|
-
- Phase 15 roadmap in `docs/architecture/architecture.md` § Step 3.
|
|
46
|
-
|
|
47
|
-
## Design Overview
|
|
48
|
-
|
|
49
|
-
### RunnerDeps — grouping runner-owned dependencies
|
|
50
|
-
|
|
51
|
-
A new `RunnerDeps` interface groups the three dependencies that the runner owns:
|
|
52
|
-
|
|
53
|
-
```typescript
|
|
54
|
-
export interface RunnerDeps {
|
|
55
|
-
io: RunnerIO;
|
|
56
|
-
exec: ShellExec;
|
|
57
|
-
registry: AgentConfigLookup;
|
|
58
|
-
}
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
`ConcreteAgentRunner` takes `RunnerDeps` at construction:
|
|
62
|
-
|
|
63
|
-
```typescript
|
|
64
|
-
export class ConcreteAgentRunner implements AgentRunner {
|
|
65
|
-
constructor(private readonly deps: RunnerDeps) {}
|
|
66
|
-
|
|
67
|
-
run(snapshot, type, prompt, options) {
|
|
68
|
-
return runAgent(snapshot, type, prompt, options, this.deps);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
`runAgent()` changes its last parameter from `io: RunnerIO` to `deps: RunnerDeps`:
|
|
74
|
-
|
|
75
|
-
```typescript
|
|
76
|
-
export async function runAgent(
|
|
77
|
-
snapshot: ParentSnapshot,
|
|
78
|
-
type: SubagentType,
|
|
79
|
-
prompt: string,
|
|
80
|
-
options: RunOptions,
|
|
81
|
-
deps: RunnerDeps,
|
|
82
|
-
): Promise<RunResult> {
|
|
83
|
-
const effectiveCwd = options.context?.cwd ?? snapshot.cwd;
|
|
84
|
-
const env = await deps.io.detectEnv(deps.exec, effectiveCwd);
|
|
85
|
-
// ...
|
|
86
|
-
const cfg = assembleSessionConfig(type, ..., deps.registry, deps.io.assemblerIO);
|
|
87
|
-
// ...
|
|
88
|
-
}
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
### RunContext shrinks
|
|
92
|
-
|
|
93
|
-
`RunContext` loses `exec` and `registry`:
|
|
94
|
-
|
|
95
|
-
```typescript
|
|
96
|
-
export interface RunContext {
|
|
97
|
-
/** Override working directory (e.g. for worktree isolation). */
|
|
98
|
-
cwd?: string;
|
|
99
|
-
/** Parent session identity (file path + session ID). */
|
|
100
|
-
parentSession?: ParentSessionInfo;
|
|
101
|
-
}
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
The `AgentRunner.run()` interface is unchanged — callers still pass `RunOptions` with `context: RunContext`.
|
|
105
|
-
`ConcreteAgentRunner.run()` reads `exec` and `registry` from its own `deps` instead of from `options.context`.
|
|
106
|
-
|
|
107
|
-
### AgentManager loses 2 fields
|
|
108
|
-
|
|
109
|
-
`AgentManagerOptions` removes `exec` and `registry`.
|
|
110
|
-
`AgentManager` removes the corresponding private fields and the `this.exec` / `this.registry` relay in `startAgent()`.
|
|
111
|
-
The `context` object constructed in `startAgent()` shrinks from 4 fields to 2:
|
|
112
|
-
|
|
113
|
-
```typescript
|
|
114
|
-
context: {
|
|
115
|
-
cwd: record.worktreeState?.path,
|
|
116
|
-
parentSession: options.parentSession,
|
|
117
|
-
},
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
### Wiring in index.ts
|
|
121
|
-
|
|
122
|
-
```typescript
|
|
123
|
-
const runner = new ConcreteAgentRunner({
|
|
124
|
-
io: runnerIO,
|
|
125
|
-
exec: (cmd, args, opts) => pi.exec(cmd, args, opts),
|
|
126
|
-
registry,
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
const manager = new AgentManager({
|
|
130
|
-
runner,
|
|
131
|
-
worktrees: new GitWorktreeManager(process.cwd()),
|
|
132
|
-
observer,
|
|
133
|
-
getMaxConcurrent: () => settings.maxConcurrent,
|
|
134
|
-
getRunConfig: () => settings,
|
|
135
|
-
});
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
## Module-Level Changes
|
|
139
|
-
|
|
140
|
-
### `src/lifecycle/agent-runner.ts`
|
|
141
|
-
|
|
142
|
-
1. Add `RunnerDeps` interface (exported): `{ io: RunnerIO; exec: ShellExec; registry: AgentConfigLookup }`.
|
|
143
|
-
2. Remove `exec` and `registry` from `RunContext`.
|
|
144
|
-
Update doc comment to reflect the 2 remaining per-call fields.
|
|
145
|
-
3. Update `ConcreteAgentRunner` constructor: accept `RunnerDeps` instead of `RunnerIO`.
|
|
146
|
-
4. Update `ConcreteAgentRunner.run()`: pass `this.deps` to `runAgent()`.
|
|
147
|
-
5. Update `runAgent()`: change last parameter from `io: RunnerIO` to `deps: RunnerDeps`.
|
|
148
|
-
Replace `io.` references with `deps.io.`, `options.context.exec` with `deps.exec`, `options.context.registry` with `deps.registry`.
|
|
149
|
-
|
|
150
|
-
### `src/lifecycle/agent-manager.ts`
|
|
151
|
-
|
|
152
|
-
1. Remove `exec: ShellExec` and `registry: AgentTypeRegistry` from `AgentManagerOptions`.
|
|
153
|
-
2. Remove `private readonly exec` and `private readonly registry` fields from `AgentManager`.
|
|
154
|
-
3. Remove assignment of `this.exec` and `this.registry` in the constructor.
|
|
155
|
-
4. Remove `exec: this.exec` and `registry: this.registry` from the `context` object in `startAgent()`.
|
|
156
|
-
5. Remove `ShellExec` and `AgentTypeRegistry` imports (verify no other references first).
|
|
157
|
-
|
|
158
|
-
### `src/index.ts`
|
|
159
|
-
|
|
160
|
-
1. Move `exec` and `registry` from the `AgentManager` constructor call to `ConcreteAgentRunner`:
|
|
161
|
-
`new ConcreteAgentRunner({ io: runnerIO, exec: ..., registry })`.
|
|
162
|
-
2. Remove `exec` and `registry` from the `AgentManager({...})` constructor argument.
|
|
163
|
-
|
|
164
|
-
### `test/lifecycle/agent-runner.test.ts`
|
|
165
|
-
|
|
166
|
-
1. Update all `runAgent(..., io)` calls to `runAgent(..., { io, exec, registry: mockAgentLookup })`.
|
|
167
|
-
2. Remove `exec` and `registry` from `context:` objects in `RunOptions`.
|
|
168
|
-
`context: { exec, registry: mockAgentLookup }` → `context: {}` or `{}`.
|
|
169
|
-
|
|
170
|
-
### `test/lifecycle/agent-runner-extension-tools.test.ts`
|
|
171
|
-
|
|
172
|
-
1. Same pattern as `agent-runner.test.ts`: update `runAgent(..., io)` last param and strip `exec`/`registry` from `context:`.
|
|
173
|
-
|
|
174
|
-
### `test/lifecycle/concrete-agent-runner.test.ts`
|
|
175
|
-
|
|
176
|
-
1. Update `new ConcreteAgentRunner(io)` → `new ConcreteAgentRunner({ io, exec: vi.fn(), registry })`.
|
|
177
|
-
2. Remove `exec` and `registry` from the `context:` in `runner.run()` call options.
|
|
178
|
-
|
|
179
|
-
### `test/lifecycle/agent-manager.test.ts`
|
|
180
|
-
|
|
181
|
-
1. Remove `exec: vi.fn()` and `registry: testRegistry` from `createManager()` factory.
|
|
182
|
-
2. Remove the `testRegistry` construction and `AgentTypeRegistry` import if no other references exist.
|
|
183
|
-
|
|
184
|
-
### `test/helpers/runner-io.ts`
|
|
185
|
-
|
|
186
|
-
1. No structural changes needed — `createRunnerIO()` returns the `RunnerIO` shape, which is unchanged.
|
|
187
|
-
However, add a `createRunnerDeps()` convenience factory that bundles `{ io: createRunnerIO(), exec: vi.fn(), registry: createAgentLookup() }` for runner test files.
|
|
188
|
-
|
|
189
|
-
### `docs/architecture/architecture.md`
|
|
190
|
-
|
|
191
|
-
1. Update the `RunContext` code block in § "RunOptions (12 fields → extract RunContext)" to show only `cwd` and `parentSession`.
|
|
192
|
-
2. Update the field-count description (4 → 2 per-call fields).
|
|
193
|
-
3. Mark Step 3 as complete in the Phase 15 roadmap.
|
|
194
|
-
|
|
195
|
-
## Test Impact Analysis
|
|
196
|
-
|
|
197
|
-
1. No new test surfaces are needed — this is a pure mechanical refactoring (moving constructor parameters).
|
|
198
|
-
The existing runner and manager test suites fully cover the behavior.
|
|
199
|
-
2. No existing tests become redundant — all tests exercise the same interactions, just with deps flowing through a different path.
|
|
200
|
-
3. Existing `agent-manager.test.ts` tests remain as-is in coverage scope.
|
|
201
|
-
They verify `AgentManager` behavior (spawning, queueing, abort, etc.) independent of runner deps.
|
|
202
|
-
4. Existing `agent-runner.test.ts` and `concrete-agent-runner.test.ts` tests remain.
|
|
203
|
-
They verify `runAgent()` and `ConcreteAgentRunner` behavior.
|
|
204
|
-
Call-site patterns change but assertions stay the same.
|
|
205
|
-
|
|
206
|
-
## TDD Order
|
|
207
|
-
|
|
208
|
-
1. **Add `RunnerDeps` interface and update `runAgent()` parameter** — define `RunnerDeps`, change `runAgent()`'s last param from `io` to `deps`, update internal references.
|
|
209
|
-
Update `agent-runner.test.ts` and `agent-runner-extension-tools.test.ts` call sites.
|
|
210
|
-
Commit: `refactor: add RunnerDeps and update runAgent parameter (#231)`
|
|
211
|
-
|
|
212
|
-
2. **Update `ConcreteAgentRunner` to accept `RunnerDeps`** — change constructor from `RunnerIO` to `RunnerDeps`, update `.run()` to pass `this.deps`.
|
|
213
|
-
Update `concrete-agent-runner.test.ts`.
|
|
214
|
-
Add `createRunnerDeps()` helper to `test/helpers/runner-io.ts`.
|
|
215
|
-
Commit: `refactor: ConcreteAgentRunner accepts RunnerDeps (#231)`
|
|
216
|
-
|
|
217
|
-
3. **Remove `exec` and `registry` from `RunContext`** — shrink the interface to 2 fields, update doc comment.
|
|
218
|
-
Strip `exec`/`registry` from `context:` in all runner test call sites.
|
|
219
|
-
Run `pnpm run check` to verify no stale references.
|
|
220
|
-
Commit: `refactor: remove exec and registry from RunContext (#231)`
|
|
221
|
-
|
|
222
|
-
4. **Remove `exec` and `registry` from `AgentManager`** — remove from `AgentManagerOptions`, remove class fields, remove relay in `startAgent()`, clean up imports.
|
|
223
|
-
Update `agent-manager.test.ts` factory.
|
|
224
|
-
Commit: `refactor: remove relay deps from AgentManager (#231)`
|
|
225
|
-
|
|
226
|
-
5. **Update wiring in `index.ts`** — move `exec` and `registry` from `AgentManager` construction to `ConcreteAgentRunner` construction.
|
|
227
|
-
Commit: `refactor: wire exec and registry to ConcreteAgentRunner (#231)`
|
|
228
|
-
|
|
229
|
-
6. **Update architecture docs** — update `RunContext` description and field counts, mark Step 3 complete.
|
|
230
|
-
Commit: `docs: update architecture for runner self-contained (#231)`
|
|
231
|
-
|
|
232
|
-
## Risks and Mitigations
|
|
233
|
-
|
|
234
|
-
1. **Test churn** — ~20 `runAgent()` call sites change their last parameter pattern.
|
|
235
|
-
Mitigation: mechanical find-and-replace; assertions stay identical.
|
|
236
|
-
2. **Step ordering** — Steps 3 and 4 both remove `exec`/`registry` from different types.
|
|
237
|
-
If done in the wrong order, intermediate commits may not type-check.
|
|
238
|
-
Mitigation: Step 1–2 add the new path (`deps`), Step 3 removes from `RunContext` (runner side), Step 4 removes from `AgentManager` (manager side), Step 5 wires them together.
|
|
239
|
-
Each commit is independently valid.
|
|
240
|
-
3. **Import cleanup** — removing `exec`/`registry` from `AgentManager` may leave unused imports (`ShellExec`, `AgentTypeRegistry`).
|
|
241
|
-
Mitigation: grep for other usages before removing; `pnpm run check` catches unused imports.
|
|
242
|
-
|
|
243
|
-
## Open Questions
|
|
244
|
-
|
|
245
|
-
- None — the issue scope is narrow and the design is straightforward.
|