@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,220 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
issue: 447
|
|
3
|
-
issue_title: "pi-subagents: extract subagent settings to a focused /subagents-settings command"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Extract subagent settings to a focused `/subagents-settings` command
|
|
7
|
-
|
|
8
|
-
## Release Recommendation
|
|
9
|
-
|
|
10
|
-
**Release:** ship independently
|
|
11
|
-
|
|
12
|
-
Phase 19 Step 2 ([#447]) carries `Release: independent` in the architecture roadmap, and the only batch defined there is "dissolve-agents" (Steps 5–6, [#442]/[#441]).
|
|
13
|
-
This step is purely additive — it stands up the new command without touching `agent-menu.ts` — so it ships on its own with no batch coupling.
|
|
14
|
-
|
|
15
|
-
## Problem Statement
|
|
16
|
-
|
|
17
|
-
The `/agents` command bundles four unrelated jobs (running-agent visibility, agent-type browsing, the creation wizard, and operational settings).
|
|
18
|
-
ADR-0004 Decision C splits them.
|
|
19
|
-
Settings has standalone value but does not belong buried inside an agent-management menu — a focused, top-level command is discoverable on its own without navigating a multi-purpose menu.
|
|
20
|
-
|
|
21
|
-
This step is deliberately **additive**: it stands up the new command without touching `agent-menu.ts`.
|
|
22
|
-
The old in-menu Settings option keeps working until Phase 19 Step 5 ([#442]) deletes `agent-menu.ts` wholesale.
|
|
23
|
-
Keeping the work additive avoids surgery on the doomed module and lets this step run in parallel with the rest of the Phase 19 replacement track.
|
|
24
|
-
|
|
25
|
-
## Goals
|
|
26
|
-
|
|
27
|
-
- Add `src/ui/subagents-settings.ts` — a `SubagentsSettingsHandler` lifted verbatim from `AgentsMenuHandler.showSettings`, carrying its own narrow manager interface (the three `apply*` methods and three readonly accessors only) and a narrow UI interface (only `select`, `input`, `notify`).
|
|
28
|
-
- Register the `/subagents-settings` command in `src/index.ts`, passing the existing `settings` (`SettingsManager`) directly.
|
|
29
|
-
- Add `test/ui/subagents-settings.test.ts` covering the extracted handler's behavior.
|
|
30
|
-
|
|
31
|
-
Non-breaking: this is pure addition.
|
|
32
|
-
No existing export, command, or behavior changes.
|
|
33
|
-
|
|
34
|
-
## Non-Goals
|
|
35
|
-
|
|
36
|
-
- Do **not** remove `showSettings` or `AgentMenuSettings` from `agent-menu.ts` — that file is deleted whole in Phase 19 Step 5 ([#442]).
|
|
37
|
-
- Do **not** modify the `/agents` command, its handler, or any wiring in `index.ts` beyond adding the new registration block.
|
|
38
|
-
- Do **not** add a settings re-show loop or any new settings behavior — the lift preserves the single-selection-then-return semantics of `showSettings` (see Design Overview).
|
|
39
|
-
- Defer the background widget ([#444]), native session navigation ([#445]), and the `/agents` dissolution ([#442]/[#441]) to their own Phase 19 steps.
|
|
40
|
-
|
|
41
|
-
## Background
|
|
42
|
-
|
|
43
|
-
Relevant existing modules:
|
|
44
|
-
|
|
45
|
-
- `src/ui/agent-menu.ts` — `AgentsMenuHandler.showSettings(ui)` is the source of the lift.
|
|
46
|
-
It depends solely on `this.settings` (typed `AgentMenuSettings`) and the `ui` parameter (`MenuUI`).
|
|
47
|
-
It calls `ui.select` once, then `ui.input` + one `settings.apply*` + `ui.notify` for the chosen field.
|
|
48
|
-
It does not loop: it shows the settings list once, applies one change (or none), and returns.
|
|
49
|
-
The re-show in the live menu comes from `showAgentsMenu` re-invoking *itself* after `showSettings` returns — not from `showSettings` looping.
|
|
50
|
-
- `AgentMenuSettings` (in `agent-menu.ts`) — the narrow settings shape `showSettings` reads: `readonly maxConcurrent`, `readonly defaultMaxTurns: number | undefined`, `readonly graceTurns`, plus `applyMaxConcurrent`/`applyDefaultMaxTurns`/`applyGraceTurns`, each returning `{ message: string; level: "info" | "warning" }`.
|
|
51
|
-
- `MenuUI` (in `agent-menu.ts`) — the wide menu UI interface; `showSettings` uses only `select`, `input`, and `notify` from it.
|
|
52
|
-
- `src/settings.ts` — `SettingsManager` is the concrete settings object constructed in `index.ts`.
|
|
53
|
-
It already exposes all six members of `AgentMenuSettings` (the three getters and three `apply*` methods), so it structurally satisfies the new narrow manager interface and can be passed directly.
|
|
54
|
-
- `src/index.ts` — constructs `settings = new SettingsManager(...)`, then `new AgentsMenuHandler(manager, registry, settings, ...)` and `registerCommand("agents", ...)`.
|
|
55
|
-
Sibling commands register flat, hyphenated names (`agents`, `colgrep-reindex`, `permission-system`) — no `:` namespace.
|
|
56
|
-
- `docs/decisions/0004-reconsider-ui-direction.md` — the addendum (2026-06-20) confirms the command name **`/subagents-settings`** (Criterion 4) and rejects `/subagents:settings` and `/agents-settings`.
|
|
57
|
-
|
|
58
|
-
AGENTS.md / package constraints:
|
|
59
|
-
|
|
60
|
-
- pi-subagents is a minimal core; the surviving UI is an in-core reactive consumer.
|
|
61
|
-
This extraction adds a command surface only — no policy, no new core dependency.
|
|
62
|
-
- Modules marked `← removing` (the `/agents` subtree) must not gain features — this plan adds nothing to `agent-menu.ts`.
|
|
63
|
-
|
|
64
|
-
## Design Overview
|
|
65
|
-
|
|
66
|
-
`SubagentsSettingsHandler` is a faithful lift of `showSettings` into a standalone, independently-registered command.
|
|
67
|
-
It owns the settings UI interaction and depends on two narrow interfaces it declares itself (ISP — neither carries a field the handler does not use).
|
|
68
|
-
|
|
69
|
-
### Narrow interfaces
|
|
70
|
-
|
|
71
|
-
```typescript
|
|
72
|
-
/** Narrow settings interface required by the subagents-settings command. */
|
|
73
|
-
export interface SubagentsSettingsManager {
|
|
74
|
-
readonly maxConcurrent: number;
|
|
75
|
-
readonly defaultMaxTurns: number | undefined;
|
|
76
|
-
readonly graceTurns: number;
|
|
77
|
-
applyMaxConcurrent(n: number): { message: string; level: "info" | "warning" };
|
|
78
|
-
applyDefaultMaxTurns(n: number): { message: string; level: "info" | "warning" };
|
|
79
|
-
applyGraceTurns(n: number): { message: string; level: "info" | "warning" };
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/** Narrow UI interface — only the ctx.ui methods the settings handler calls. */
|
|
83
|
-
export interface SubagentsSettingsUI {
|
|
84
|
-
select(title: string, options: string[]): Promise<string | undefined>;
|
|
85
|
-
input(title: string, defaultValue?: string): Promise<string | undefined>;
|
|
86
|
-
notify(message: string, level: "info" | "warning" | "error"): void;
|
|
87
|
-
}
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
`SubagentsSettingsManager` is shape-identical to `AgentMenuSettings` but owned by the new module (zero import from `agent-menu.ts`, which is doomed).
|
|
91
|
-
`SubagentsSettingsUI` is narrower than `MenuUI` — it drops `confirm`, `editor`, and `custom`, which `showSettings` never calls.
|
|
92
|
-
|
|
93
|
-
### Handler
|
|
94
|
-
|
|
95
|
-
```typescript
|
|
96
|
-
export class SubagentsSettingsHandler {
|
|
97
|
-
constructor(private readonly settings: SubagentsSettingsManager) {}
|
|
98
|
-
|
|
99
|
-
async handle({ ui }: { ui: SubagentsSettingsUI }): Promise<void> {
|
|
100
|
-
// verbatim lift of showSettings: one select → input → apply* → notify
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
The body is copied character-for-character from `showSettings` (the same three `if` branches, the same `parseInt` / validation / toast wiring), with `this.settings` resolving against the new narrow interface.
|
|
106
|
-
|
|
107
|
-
### Registration call site (index.ts)
|
|
108
|
-
|
|
109
|
-
```typescript
|
|
110
|
-
const subagentsSettings = new SubagentsSettingsHandler(settings);
|
|
111
|
-
pi.registerCommand("subagents-settings", {
|
|
112
|
-
description: "Configure subagent settings (concurrency, turn limits)",
|
|
113
|
-
handler: async (_args, ctx) => {
|
|
114
|
-
await subagentsSettings.handle({ ui: ctx.ui });
|
|
115
|
-
},
|
|
116
|
-
});
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
`settings` (the `SettingsManager` instance) is passed directly — it structurally satisfies `SubagentsSettingsManager`.
|
|
120
|
-
The command handler needs only `ctx.ui` (no `modelRegistry`, no `parentSnapshot`), so its params are narrower than the `/agents` handler's.
|
|
121
|
-
|
|
122
|
-
### Design-review findings
|
|
123
|
-
|
|
124
|
-
| Smell | Location | Evidence | Result |
|
|
125
|
-
| --------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- |
|
|
126
|
-
| Wide interface | `SubagentsSettingsManager` (6 members) | `handle` reads all 3 accessors and calls all 3 apply methods | None — 100% usage |
|
|
127
|
-
| Wide interface | `SubagentsSettingsUI` (3 methods) | `handle` calls `select`, `input`, `notify` | None — 100% usage |
|
|
128
|
-
| LoD violation | `subagents-settings.ts` | `this.settings.applyMaxConcurrent(n)` is a direct call; `ui.notify(toast.message, toast.level)` reads a returned value, not a reach-through | None |
|
|
129
|
-
| Output argument | `subagents-settings.ts` | handler reads accessors + calls apply methods; never writes back into `settings` or `ui` | None |
|
|
130
|
-
|
|
131
|
-
The extraction introduces a genuine new collaborator (a focused command handler owning the settings interaction) with its own narrow contracts — it is not procedure-splitting.
|
|
132
|
-
|
|
133
|
-
### Edge cases (preserved verbatim from `showSettings`)
|
|
134
|
-
|
|
135
|
-
- `select` returns `undefined` (operator cancels) → return early, no change.
|
|
136
|
-
- `input` returns falsy (empty / cancel) → no apply call.
|
|
137
|
-
- `maxConcurrent` / `graceTurns`: reject `n < 1` with `"Must be a positive integer."` warning.
|
|
138
|
-
- `defaultMaxTurns`: accept `n >= 0` (0 = unlimited); reject `n < 0` with `"Must be 0 (unlimited) or a positive integer."` warning.
|
|
139
|
-
- Single selection then return — no settings re-show loop (matches current `showSettings`).
|
|
140
|
-
|
|
141
|
-
## Module-Level Changes
|
|
142
|
-
|
|
143
|
-
- **New** `src/ui/subagents-settings.ts` — `SubagentsSettingsHandler` class, `SubagentsSettingsManager` interface, `SubagentsSettingsUI` interface.
|
|
144
|
-
~80 LOC.
|
|
145
|
-
- **Changed** `src/index.ts` — add the `SubagentsSettingsHandler` import, construct it, and register the `subagents-settings` command.
|
|
146
|
-
No other lines change; the `/agents` block stays intact.
|
|
147
|
-
- **New** `test/ui/subagents-settings.test.ts` — unit tests for the handler.
|
|
148
|
-
- **No change** to `src/ui/agent-menu.ts` (and its `AgentMenuSettings` / `showSettings` / `MenuUI` stay as-is — deleted later in [#442]).
|
|
149
|
-
|
|
150
|
-
Doc / skill grep results (no stale references to update in this step):
|
|
151
|
-
|
|
152
|
-
- `architecture.md` Step 2 already names `src/ui/subagents-settings.ts`, `SubagentsSettingsHandler`, `SubagentsSettingsManager`, and the `/subagents-settings` command with `Outcome: new subagents-settings.ts (~80 LOC) and focused command registered; agent-menu.ts untouched` — the file appears as a *planned* addition, so no doc edit is needed now; its status line flips to ✅ at ship time only if the operator wants it folded in.
|
|
153
|
-
- The package skill (`.pi/skills/package-pi-subagents/SKILL.md`) lists the UI domain by count (`ui/` = 10 modules); adding one file makes it 11, but the table is a coarse summary that is not maintained per-file — leave it for a later Phase 19 doc-sync unless the operator asks otherwise.
|
|
154
|
-
- `settings.ts` comments reference `/agents → Settings` as the writer of project settings; those are still accurate (the in-menu path keeps working), so no edit.
|
|
155
|
-
They become stale only when [#442] deletes `agent-menu.ts`; do not pre-edit them here.
|
|
156
|
-
|
|
157
|
-
## Test Impact Analysis
|
|
158
|
-
|
|
159
|
-
1. **New tests enabled by the extraction.**
|
|
160
|
-
`test/ui/subagents-settings.test.ts` can unit-test the settings flow in isolation against the standalone handler — no `AgentsMenuHandler` construction (registry, fileOps, two agent dirs) required.
|
|
161
|
-
This is strictly more focused than the current `agent-menu.test.ts` "agent menu — settings" describe block, which has to drive the full top menu (`"Settings"` from the main menu) before reaching the settings list.
|
|
162
|
-
2. **Existing tests that become redundant.**
|
|
163
|
-
None are removed in this step.
|
|
164
|
-
The "agent menu — settings" tests in `agent-menu.test.ts` still genuinely exercise the live in-menu path, which keeps working until [#442].
|
|
165
|
-
They are superseded only when `agent-menu.ts` is deleted in Step 5 — removing them now would drop coverage of a still-shipping surface.
|
|
166
|
-
3. **Existing tests that must stay as-is.**
|
|
167
|
-
All of `agent-menu.test.ts` stays unchanged — this step does not touch `agent-menu.ts`.
|
|
168
|
-
|
|
169
|
-
## Invariants at risk
|
|
170
|
-
|
|
171
|
-
This step adds a new module and one registration; it does not touch the Phase 18 spine that prior steps refactored.
|
|
172
|
-
The ADR-0004 / Phase 18 invariants (runtime holds zero UI state [#422]; widget is a reactive consumer with no inbound core calls [#423]; the `subagent` tool depends only on manager/runtime/settings/registry [#424]; declared event channels equal emitted channels [#425]) are untouched and stay pinned by their existing suites.
|
|
173
|
-
The new handler adds no inbound call into the core and emits no events — it reads/applies through the existing `SettingsManager` surface only, so it preserves these invariants by construction.
|
|
174
|
-
|
|
175
|
-
## TDD Order
|
|
176
|
-
|
|
177
|
-
1. **Red→Green: extract `SubagentsSettingsHandler` with its narrow interfaces.**
|
|
178
|
-
Test surface: `test/ui/subagents-settings.test.ts`.
|
|
179
|
-
Write tests against a `makeSettings()`-style manager stub (lift the stub shape from `agent-menu.test.ts`) and a narrow UI stub (lift `makeMenuUI`, or reuse it — it already provides `select`/`input`/`notify`):
|
|
180
|
-
- constructable;
|
|
181
|
-
- cancel at the settings list (`select` → `undefined`) → no apply call;
|
|
182
|
-
- `maxConcurrent`: valid input delegates to `applyMaxConcurrent(n)` and notifies the returned toast; `n < 1` notifies the positive-integer warning and does not apply;
|
|
183
|
-
- `defaultMaxTurns`: `0` delegates `applyDefaultMaxTurns(0)`; a positive value delegates; `n < 0` notifies the warning;
|
|
184
|
-
- `graceTurns`: valid input delegates to `applyGraceTurns(n)`; `n < 1` notifies the warning;
|
|
185
|
-
- empty/cancelled `input` → no apply call.
|
|
186
|
-
Implementation: create `src/ui/subagents-settings.ts` with the class and both interfaces; body lifted verbatim from `showSettings`.
|
|
187
|
-
Commit: `feat: add SubagentsSettingsHandler for focused settings command (#447)`.
|
|
188
|
-
2. **Green: register the `/subagents-settings` command in `index.ts`.**
|
|
189
|
-
Test surface: none new (command registration in `index.ts` is exercised by the package's existing index-level wiring tests if present; otherwise verify by `pnpm run check` and the suite).
|
|
190
|
-
Implementation: import `SubagentsSettingsHandler`, construct it with `settings`, and `registerCommand("subagents-settings", ...)` passing `{ ui: ctx.ui }`.
|
|
191
|
-
Run `pnpm run check` immediately (the registration is the only call site of the new export — it must compile alongside the new module).
|
|
192
|
-
Commit: `feat: register /subagents-settings command (#447)`.
|
|
193
|
-
|
|
194
|
-
Both steps may be folded into one commit if preferred — the export and its single call site are small — but keeping the handler (with its tests) separate from the wiring keeps each commit self-contained and reviewable.
|
|
195
|
-
|
|
196
|
-
## Risks and Mitigations
|
|
197
|
-
|
|
198
|
-
- **Risk: the lift diverges from `showSettings`, causing the standalone command to behave differently from the in-menu option while both ship.**
|
|
199
|
-
Mitigation: copy the body verbatim and assert the same validation/toast behavior in the new test file; the two surfaces share the same `SettingsManager`, so applied values are identical.
|
|
200
|
-
- **Risk: passing `SettingsManager` directly fails structural typing against the new narrow interface.**
|
|
201
|
-
Mitigation: `SettingsManager` already declares all six members with matching signatures (verified in `src/settings.ts`); `pnpm run check` in Step 2 confirms it.
|
|
202
|
-
- **Risk: command-name drift from the ADR.**
|
|
203
|
-
Mitigation: the name `subagents-settings` is fixed by the ADR-0004 addendum (Criterion 4) and the roadmap Step 2; use it exactly.
|
|
204
|
-
- **Risk: an unused-import or dead-export flag if the wiring lands in a separate commit from the handler.**
|
|
205
|
-
Mitigation: Step 2 adds the sole call site immediately; run `pnpm fallow dead-code` before pushing.
|
|
206
|
-
|
|
207
|
-
## Open Questions
|
|
208
|
-
|
|
209
|
-
- Whether to also flip the `architecture.md` Step 2 status line to ✅ in this issue or defer to a Phase 19 doc-sync — decide at ship time (the architecture entry currently lists the file as planned, which is harmless until then).
|
|
210
|
-
- Whether a settings re-show loop (apply one setting → re-show the list) is desirable for the standalone command — deferred; the lift preserves single-selection-then-return to match current behavior, and a loop is a separate UX decision.
|
|
211
|
-
|
|
212
|
-
[#441]: https://github.com/gotgenes/pi-packages/issues/441
|
|
213
|
-
[#442]: https://github.com/gotgenes/pi-packages/issues/442
|
|
214
|
-
[#444]: https://github.com/gotgenes/pi-packages/issues/444
|
|
215
|
-
[#445]: https://github.com/gotgenes/pi-packages/issues/445
|
|
216
|
-
[#447]: https://github.com/gotgenes/pi-packages/issues/447
|
|
217
|
-
[#422]: https://github.com/gotgenes/pi-packages/issues/422
|
|
218
|
-
[#423]: https://github.com/gotgenes/pi-packages/issues/423
|
|
219
|
-
[#424]: https://github.com/gotgenes/pi-packages/issues/424
|
|
220
|
-
[#425]: https://github.com/gotgenes/pi-packages/issues/425
|
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
issue: 448
|
|
3
|
-
issue_title: "`enabled: false` does not prevent explicitly spawning disabled agents"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Honor `enabled: false` in the spawn path and tool-description list
|
|
7
|
-
|
|
8
|
-
## Release Recommendation
|
|
9
|
-
|
|
10
|
-
**Release:** ship independently
|
|
11
|
-
|
|
12
|
-
This is a standalone bug fix.
|
|
13
|
-
It is not referenced by any step in `packages/pi-subagents/docs/architecture/architecture.md`, so it carries no `Release:` batch tag and should ship on its own.
|
|
14
|
-
|
|
15
|
-
## Problem Statement
|
|
16
|
-
|
|
17
|
-
In `@gotgenes/pi-subagents`, setting `enabled: false` on a custom agent override (e.g. `.pi/agents/Plan.md`) hides the agent from `getAvailableTypes()` — so it disappears from the `subagent_type` available-types list — but does **not** prevent it from being spawned when named explicitly via `subagent_type: "Plan"`.
|
|
18
|
-
|
|
19
|
-
This contradicts both the README ("disabled per-project with `enabled: false`") and the inline registry comment in `agent-types.ts` ("Disabled agents are kept but excluded from spawning").
|
|
20
|
-
|
|
21
|
-
The root cause is that the spawn resolution path (`resolveSpawnConfig`) calls `registry.resolveType()`, which delegates to `resolveKey()` and only checks key existence, never `enabled`.
|
|
22
|
-
The registry already has an `isValidType()` method that checks `enabled`, but it is not used in the spawn path.
|
|
23
|
-
|
|
24
|
-
A secondary inconsistency: `buildTypeListText()` (the subagent tool description) lists agents via `getDefaultAgentNames()` / `getUserAgentNames()`, which filter by `isDefault` only, not `enabled`.
|
|
25
|
-
So a disabled agent still appears in the "Default agents" / "Custom agents" sections of the tool description, even though it is correctly excluded from the `subagent_type` parameter's available-types line.
|
|
26
|
-
|
|
27
|
-
## Goals
|
|
28
|
-
|
|
29
|
-
- A disabled agent named explicitly via `subagent_type` is **not** spawned.
|
|
30
|
-
Instead, the spawn returns an explicit error: `Agent type "<Name>" is disabled` (operator-confirmed behavior over the fallback alternative).
|
|
31
|
-
- The error uses the registry's canonical key for the name, so case-insensitive input (`plan` → `Plan`) reports the canonical casing.
|
|
32
|
-
- Disabled agents no longer appear in the "Default agents" / "Custom agents" sections of the subagent tool description, making the tool description consistent with the `subagent_type` available-types line.
|
|
33
|
-
- Genuinely unknown types continue to fall back to `general-purpose` (unchanged).
|
|
34
|
-
- Enabled types continue to resolve and spawn exactly as before (unchanged).
|
|
35
|
-
|
|
36
|
-
This is a **behavior change** but **not a breaking change**: explicit spawning of a disabled agent was buggy, undocumented behavior that contradicted the documented contract.
|
|
37
|
-
The fix makes the code match what the README and registry comment already promise.
|
|
38
|
-
Commit messages use `fix:`.
|
|
39
|
-
|
|
40
|
-
## Non-Goals
|
|
41
|
-
|
|
42
|
-
- No change to the lenient unknown-type fallback (`fellBack` → `general-purpose`).
|
|
43
|
-
Disabled is distinct from unknown: a disabled type is a known agent that the operator deliberately turned off, so an explicit error is more informative than a silent fallback.
|
|
44
|
-
- No change to `resolveAgentConfig()`'s handling of disabled configs.
|
|
45
|
-
The UI (`display.ts`, `agent-menu.ts`, `agent-config-editor.ts`) deliberately resolves disabled configs to display, edit, and re-enable them; that behavior must be preserved.
|
|
46
|
-
- No change to the `/agents` menu, which lists disabled agents (marked `✕`) via `getAllTypes()` — intentional and unaffected.
|
|
47
|
-
- No README rewrite: the README already states that `enabled: false` disables an agent for spawning, so it is now accurate.
|
|
48
|
-
(An optional one-line note documenting the error message is in Open Questions.)
|
|
49
|
-
|
|
50
|
-
## Background
|
|
51
|
-
|
|
52
|
-
Relevant modules:
|
|
53
|
-
|
|
54
|
-
- `src/config/agent-types.ts` — `AgentTypeRegistry`.
|
|
55
|
-
- `resolveType(name)` → `resolveKey(name)`: returns the canonical key for any existing agent, **ignoring `enabled`**.
|
|
56
|
-
- `isValidType(type)`: resolves the key and returns `false` when the config has `enabled === false` (or the key is unknown).
|
|
57
|
-
Already exists, already tested, **not used in the spawn path**.
|
|
58
|
-
- `resolveAgentConfig(type)`: returns the config for an existing key (including disabled) or falls back to `general-purpose`.
|
|
59
|
-
Used by both the spawn path and the UI.
|
|
60
|
-
- `getDefaultAgentNames()` / `getUserAgentNames()`: filter by `isDefault`, not `enabled`.
|
|
61
|
-
Sole consumer is `buildTypeListText` (verified by grep across `src/` and `test/`).
|
|
62
|
-
- `src/tools/spawn-config.ts` — `resolveSpawnConfig(params, registry, modelInfo, settings)`.
|
|
63
|
-
Pure function returning `ResolvedSpawnConfig | SpawnConfigError`.
|
|
64
|
-
Lines 80-83 resolve the type:
|
|
65
|
-
|
|
66
|
-
```typescript
|
|
67
|
-
const rawType = params.subagent_type as SubagentType;
|
|
68
|
-
const resolved = registry.resolveType(rawType);
|
|
69
|
-
const subagentType = resolved ?? "general-purpose";
|
|
70
|
-
const fellBack = resolved === undefined;
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
- `src/tools/helpers.ts` — `buildTypeListText(registry, agentDir)` and the `TypeListRegistry` interface (extends `AgentConfigLookup`, so `resolveAgentConfig` is already available on it).
|
|
74
|
-
- `src/tools/agent-tool.ts` — `AgentTool.execute` already short-circuits on a config error: `if ("error" in config) return textResult(config.error);`.
|
|
75
|
-
So returning `SpawnConfigError` from `resolveSpawnConfig` is sufficient to surface the message to the model with no further wiring.
|
|
76
|
-
|
|
77
|
-
AGENTS.md / package constraints that apply:
|
|
78
|
-
|
|
79
|
-
- Pi-subagents is a minimal core with no policy enforcement.
|
|
80
|
-
This fix is **not** policy — it enforces the agent's own `enabled` flag, which is part of the registry's documented contract, not a cross-cutting tool/skill restriction (those live in `@gotgenes/pi-permission-system`).
|
|
81
|
-
- Biome handles formatting; no Prettier.
|
|
82
|
-
|
|
83
|
-
## Design Overview
|
|
84
|
-
|
|
85
|
-
Two localized, independent changes.
|
|
86
|
-
Neither introduces a new collaborator, widens a dependency bag, or changes layer wiring, so the design-review structural checklist finds nothing to flag.
|
|
87
|
-
|
|
88
|
-
### 1. Spawn-path gate (explicit error for disabled types)
|
|
89
|
-
|
|
90
|
-
In `resolveSpawnConfig`, after resolving the canonical key, gate on `enabled` before falling back.
|
|
91
|
-
The check reuses the registry's existing `isValidType`, which already encodes "exists and enabled":
|
|
92
|
-
|
|
93
|
-
```typescript
|
|
94
|
-
const rawType = params.subagent_type as SubagentType;
|
|
95
|
-
const resolved = registry.resolveType(rawType);
|
|
96
|
-
|
|
97
|
-
// A known-but-disabled type is an explicit error, not a silent fallback.
|
|
98
|
-
if (resolved !== undefined && !registry.isValidType(resolved)) {
|
|
99
|
-
return { error: `Agent type "${resolved}" is disabled` };
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const subagentType = resolved ?? "general-purpose";
|
|
103
|
-
const fellBack = resolved === undefined;
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
Decision model:
|
|
107
|
-
|
|
108
|
-
| `subagent_type` input | `resolveType` | `isValidType(resolved)` | Outcome |
|
|
109
|
-
| ------------------------- | ------------- | ----------------------- | -------------------------------------------------------------- |
|
|
110
|
-
| enabled agent (`Explore`) | `"Explore"` | `true` | resolves, spawns (unchanged) |
|
|
111
|
-
| disabled agent (`Plan`) | `"Plan"` | `false` | error: `Agent type "Plan" is disabled` |
|
|
112
|
-
| unknown (`foo`) | `undefined` | not reached | falls back to `general-purpose`, `fellBack = true` (unchanged) |
|
|
113
|
-
|
|
114
|
-
`isValidType(resolved)` re-runs `resolveKey` on an already-canonical key — a negligible, correct lookup.
|
|
115
|
-
Because the gate runs first, `resolveAgentConfig(subagentType)` downstream is only ever reached for enabled or unknown types, so its disabled-config behavior (kept for the UI) is never exercised on the spawn path.
|
|
116
|
-
|
|
117
|
-
This keeps the gate at the spawn boundary and leaves `resolveType` and `resolveAgentConfig` untouched, preserving every UI consumer that relies on resolving disabled agents.
|
|
118
|
-
|
|
119
|
-
### 2. Tool-description list filter
|
|
120
|
-
|
|
121
|
-
In `buildTypeListText`, filter both name lists by `enabled` before rendering.
|
|
122
|
-
`resolveAgentConfig(name)` returns the disabled config (with `enabled === false`) for a disabled name, so the predicate is straightforward:
|
|
123
|
-
|
|
124
|
-
```typescript
|
|
125
|
-
const isEnabled = (name: string) => registry.resolveAgentConfig(name).enabled !== false;
|
|
126
|
-
const defaultNames = registry.getDefaultAgentNames().filter(isEnabled);
|
|
127
|
-
const userNames = registry.getUserAgentNames().filter(isEnabled);
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
This localizes the fix to the one consumer that needs it, preserves the `getDefaultAgentNames` / `getUserAgentNames` method semantics (they still answer "which names are default / user"), and makes the tool description consistent with the `subagent_type` available-types line (both now exclude disabled agents).
|
|
131
|
-
|
|
132
|
-
`TypeListRegistry` already extends `AgentConfigLookup`, so `resolveAgentConfig` is in scope; no interface change.
|
|
133
|
-
|
|
134
|
-
## Module-Level Changes
|
|
135
|
-
|
|
136
|
-
- `src/tools/spawn-config.ts` — add the disabled-type gate in `resolveSpawnConfig` (3 lines) before the `subagentType` / `fellBack` assignment.
|
|
137
|
-
No signature or return-type change (`SpawnConfigError` already supported).
|
|
138
|
-
- `src/tools/helpers.ts` — add the `isEnabled` predicate and `.filter(isEnabled)` to the two name lists in `buildTypeListText`.
|
|
139
|
-
No signature or interface change.
|
|
140
|
-
- `src/config/agent-types.ts` — no code change.
|
|
141
|
-
The inline comment "Disabled agents are kept but excluded from spawning" becomes accurate without edit; the `resolveType` JSDoc already says "Returns the canonical key or undefined" (unchanged behavior).
|
|
142
|
-
|
|
143
|
-
No architecture-doc, ADR, or SKILL changes:
|
|
144
|
-
|
|
145
|
-
- `grep -rn "448" docs/` and the architecture roadmap show no reference to this issue → no roadmap/health-table update.
|
|
146
|
-
- No file is added, removed, or moved → no layout-listing update.
|
|
147
|
-
- The `package-pi-subagents` SKILL describes domains and phases, not the `resolveType`/`isValidType` mechanics, so the reworded-prose grep (`enabled`, `resolveType`, `spawning`) surfaces nothing that this fix invalidates.
|
|
148
|
-
- README is already consistent (see Non-Goals); no edit.
|
|
149
|
-
|
|
150
|
-
## Test Impact Analysis
|
|
151
|
-
|
|
152
|
-
This is a small behavior fix, not an extraction, so no existing tests become redundant.
|
|
153
|
-
|
|
154
|
-
1. **New tests enabled** — both target surfaces are pure and already directly tested:
|
|
155
|
-
- `resolveSpawnConfig` disabled-type error path (`test/tools/spawn-config.test.ts`).
|
|
156
|
-
- `buildTypeListText` disabled-exclusion path (`test/tools/helpers.test.ts`).
|
|
157
|
-
2. **Redundant tests** — none.
|
|
158
|
-
The existing `agent-types.test.ts` case "returns config for disabled type (no fallback for existing disabled)" stays as-is: it pins `resolveAgentConfig`'s disabled behavior, which the UI depends on and this fix deliberately does not change.
|
|
159
|
-
3. **Tests that must stay** — `agent-types.test.ts` `isValidType` "returns false for disabled agents" and `getAvailableTypes` "excludes disabled agents" already pin the registry primitives the gate reuses; keep them.
|
|
160
|
-
|
|
161
|
-
## Invariants at risk
|
|
162
|
-
|
|
163
|
-
This change touches the spawn-resolution and tool-description surfaces but does not regress any prior phase's documented outcome:
|
|
164
|
-
|
|
165
|
-
- `resolveAgentConfig` disabled-config behavior is pinned by `test/config/agent-types.test.ts` → "returns config for disabled type (no fallback for existing disabled)".
|
|
166
|
-
The plan leaves `resolveAgentConfig` unchanged; this test must stay green.
|
|
167
|
-
- The unknown-type fallback is pinned by `test/tools/spawn-config.test.ts` → "falls back to general-purpose for unknown agent type".
|
|
168
|
-
The gate runs only for `resolved !== undefined`, so the unknown path is untouched; this test must stay green.
|
|
169
|
-
- The UI's disabled-agent listing (`getAllTypes`) is pinned by `test/config/agent-types.test.ts` → `getAllTypes` "includes disabled agents"; unaffected.
|
|
170
|
-
|
|
171
|
-
## TDD Order
|
|
172
|
-
|
|
173
|
-
1. **Red→Green: spawn-path disabled error.**
|
|
174
|
-
Test surface: `test/tools/spawn-config.test.ts`, `resolveSpawnConfig — type resolution` describe block.
|
|
175
|
-
Add two cases: (a) a registry with a disabled `Plan` override returns `{ error: 'Agent type "Plan" is disabled' }` for `subagent_type: "Plan"`; (b) case-insensitive input `subagent_type: "plan"` reports the canonical `"Plan"` in the message.
|
|
176
|
-
Build the registry with `new AgentTypeRegistry(() => new Map([["Plan", makeAgentConfig({ name: "Plan", enabled: false })]]))` (mirror the `agent-types.test.ts` fixture shape).
|
|
177
|
-
Then add the gate to `resolveSpawnConfig`.
|
|
178
|
-
Verify the existing "falls back to general-purpose for unknown agent type" and "resolves a known agent type" cases stay green (unknown/enabled paths unchanged).
|
|
179
|
-
Commit: `fix(pi-subagents): return an error when spawning a disabled agent type (#448)`.
|
|
180
|
-
|
|
181
|
-
2. **Red→Green: tool-description excludes disabled agents.**
|
|
182
|
-
Test surface: `test/tools/helpers.test.ts`, `buildTypeListText` describe block.
|
|
183
|
-
Add a case: a registry whose `defaults`/`users` include a name resolving to `{ enabled: false }` omits that name from the rendered list (assert `.not.toContain`).
|
|
184
|
-
Extend the `makeRegistry` stub's `resolve` to return `enabled` (the stub currently returns only `description`/`model`; add `enabled` so the predicate can read it).
|
|
185
|
-
Then add the `isEnabled` filter to `buildTypeListText`.
|
|
186
|
-
Verify the existing "lists default agents", "adds Custom agents section", and "omits Custom agents section" cases stay green (their stubs resolve to enabled configs by default).
|
|
187
|
-
Commit: `fix(pi-subagents): exclude disabled agents from the subagent tool description (#448)`.
|
|
188
|
-
|
|
189
|
-
3. **Verify: full check + suite.**
|
|
190
|
-
Run `pnpm --filter @gotgenes/pi-subagents run check`, `pnpm --filter @gotgenes/pi-subagents run lint`, `pnpm --filter @gotgenes/pi-subagents run test`, and `pnpm fallow dead-code`.
|
|
191
|
-
No new commit unless a fix is needed.
|
|
192
|
-
|
|
193
|
-
## Risks and Mitigations
|
|
194
|
-
|
|
195
|
-
- **Risk:** changing `resolveType` directly would break UI consumers (`agent-config-editor.ts`, `agent-menu.ts`) that intentionally resolve disabled agents.
|
|
196
|
-
**Mitigation:** the gate lives in `resolveSpawnConfig`, not in `resolveType`; `resolveType` and `resolveAgentConfig` are unchanged.
|
|
197
|
-
- **Risk:** an operator currently relying on the buggy behavior (explicitly spawning a disabled agent) gets an error after upgrade.
|
|
198
|
-
**Mitigation:** this is the documented, intended contract; the error message is explicit and actionable ("…is disabled"), and the operator can re-enable via the `/agents` menu or by removing `enabled: false`.
|
|
199
|
-
- **Risk:** the `buildTypeListText` filter could accidentally hide enabled agents if `resolveAgentConfig` returned a wrong config.
|
|
200
|
-
**Mitigation:** `resolveAgentConfig(name)` for a name already in the registry returns that exact config; the predicate only excludes `enabled === false`.
|
|
201
|
-
Existing `buildTypeListText` tests (which resolve to enabled configs) guard against over-filtering.
|
|
202
|
-
|
|
203
|
-
## Open Questions
|
|
204
|
-
|
|
205
|
-
- Should the README's `## For Extension Authors` or the agent-config table gain a one-line note that an explicit `subagent_type` for a disabled agent now errors?
|
|
206
|
-
Deferred — the README already states `enabled: false` disables the agent; the error message is self-explanatory.
|
|
207
|
-
Revisit only if a user asks why the spawn errored.
|