@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,180 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
issue: 232
|
|
3
|
-
issue_title: "Agent.resume() with internal observer lifecycle (Phase 15, Step 6)"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Agent.resume() with internal observer lifecycle
|
|
7
|
-
|
|
8
|
-
## Problem Statement
|
|
9
|
-
|
|
10
|
-
After #229 (`Agent.run()` absorbs `startAgent`), the agent owns its entire run lifecycle but `AgentManager.resume()` still duplicates the observer subscribe/use/release pattern that `run()` handles internally.
|
|
11
|
-
The manager manually calls `subscribeAgentObserver`, wraps `runner.resume()` in a try/catch/finally, marks completion/error, and unsubscribes — the same acquire → use → release resource shape `Agent.run()` already encapsulates.
|
|
12
|
-
This is the last "manager reaches into Agent" duplication in the Phase 15 roadmap (priority 8, smell A: redundant pattern).
|
|
13
|
-
|
|
14
|
-
## Goals
|
|
15
|
-
|
|
16
|
-
- Add `Agent.resume(prompt, signal?)` that owns its observer subscription lifecycle, mirroring `run()`'s internal wiring.
|
|
17
|
-
- Reduce `AgentManager.resume()` to a guard-plus-delegation method (no `subscribeAgentObserver`, no try/finally).
|
|
18
|
-
- Preserve the existing public contract of `AgentManager.resume()` exactly: same signature, same `Agent | undefined` return, same behavior when the record or session is missing.
|
|
19
|
-
- Keep the change non-breaking (`feat:`, not `feat!:`).
|
|
20
|
-
|
|
21
|
-
## Non-Goals
|
|
22
|
-
|
|
23
|
-
- No change to `runner.resume()` / `resumeAgent()` in `agent-runner.ts`.
|
|
24
|
-
- No change to the abort semantics of resume — the parent `signal` continues to flow straight through to `runner.resume({ signal })` (resume does not route through the agent's `abortController`, matching today's behavior).
|
|
25
|
-
- No queue interaction on resume — resume is not subject to the concurrency queue, so `onStarted`/`onRunFinished` are not fired (unchanged from today).
|
|
26
|
-
- No full rewrite of the stale `AgentManager`/`Agent` class diagram in `architecture.md` — that diagram already diverged in #229 (missing `run()`, stale `setupWorktree`/`completeRun`/`setOnRunFinished` signatures); a comprehensive diagram refresh is out of scope here.
|
|
27
|
-
|
|
28
|
-
## Background
|
|
29
|
-
|
|
30
|
-
Relevant modules (all under `packages/pi-subagents/src/`):
|
|
31
|
-
|
|
32
|
-
- `lifecycle/agent.ts` — the `Agent` class.
|
|
33
|
-
Already owns the per-run listener state (`_unsub`, `_detachFn`), the `attachObserver(unsub)` / `releaseListeners()` pair, `resetForResume(startedAt)` (which calls `releaseListeners()`), and `markCompleted` / `markError`.
|
|
34
|
-
Holds `_runner` and `observer` (an `AgentLifecycleObserver`) from construction (#229).
|
|
35
|
-
`Agent.run()` is the template to follow: it wires the observer via `attachObserver(subscribeAgentObserver(session, this, { onCompact: (r, info) => this.observer?.onCompacted?.(r, info) }))`.
|
|
36
|
-
- `lifecycle/agent-manager.ts` — `AgentManager.resume()` currently does the manual subscribe/try-finally dance and imports `subscribeAgentObserver` solely for that.
|
|
37
|
-
- `observation/record-observer.ts` — `subscribeAgentObserver(session, record, options)` returns an unsubscribe function; observes `tool_execution_end`, `message_end`, `compaction_end`.
|
|
38
|
-
- `lifecycle/agent-runner.ts` — `AgentRunner.resume(session, prompt, options?)` returns `Promise<string>` (the response text).
|
|
39
|
-
|
|
40
|
-
Constraint from AGENTS.md / `package-pi-subagents` skill: pi-subagents is a narrow core; this is a pure internal refactor (Tell-Don't-Ask, "state owns its mutations") with no policy or API-surface change.
|
|
41
|
-
|
|
42
|
-
### Observer routing equivalence
|
|
43
|
-
|
|
44
|
-
The manager's old resume wired compaction to the `AgentManagerObserver`:
|
|
45
|
-
|
|
46
|
-
```typescript
|
|
47
|
-
subscribeAgentObserver(session, record, {
|
|
48
|
-
onCompact: (r, info) => this.observer?.onAgentCompacted(r, info),
|
|
49
|
-
});
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
`Agent.resume()` instead routes through the per-agent `AgentLifecycleObserver` (`this.observer?.onCompacted?.`), exactly as `run()` does.
|
|
53
|
-
That lifecycle observer is built by `AgentManager.buildObserver()`, whose `onCompacted` forwards to `this.observer?.onAgentCompacted(agent, info)`.
|
|
54
|
-
Net routing is identical — compaction events still reach the manager-level `AgentManagerObserver.onAgentCompacted`.
|
|
55
|
-
|
|
56
|
-
## Design Overview
|
|
57
|
-
|
|
58
|
-
### `Agent.resume()`
|
|
59
|
-
|
|
60
|
-
```typescript
|
|
61
|
-
async resume(prompt: string, signal?: AbortSignal): Promise<void> {
|
|
62
|
-
if (!this._runner) {
|
|
63
|
-
throw new Error("Agent not configured for execution — missing runner");
|
|
64
|
-
}
|
|
65
|
-
const session = this.session;
|
|
66
|
-
if (!session) {
|
|
67
|
-
throw new Error("Agent not configured for resume — missing session");
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
this.resetForResume(Date.now()); // sets running, clears result/error, releases stale listeners
|
|
71
|
-
this.attachObserver(subscribeAgentObserver(session, this, {
|
|
72
|
-
onCompact: (r, info) => this.observer?.onCompacted?.(r, info),
|
|
73
|
-
}));
|
|
74
|
-
|
|
75
|
-
try {
|
|
76
|
-
const responseText = await this._runner.resume(session, prompt, { signal });
|
|
77
|
-
this.markCompleted(responseText);
|
|
78
|
-
} catch (err) {
|
|
79
|
-
this.markError(err);
|
|
80
|
-
} finally {
|
|
81
|
-
this.releaseListeners();
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
Decision model:
|
|
87
|
-
|
|
88
|
-
- `resetForResume()` already calls `releaseListeners()`, so any leftover handle from a prior run/resume is cleared before the new subscription is attached.
|
|
89
|
-
- The new subscription handle is stored via `attachObserver()` (reusing the `_unsub` slot shared with `run()`), and released in `finally` via `releaseListeners()`.
|
|
90
|
-
- Errors are captured (`markError`) rather than rethrown — `resume()` resolves like `run()`.
|
|
91
|
-
- The two guards (missing runner, missing session) mirror `run()`'s guard style.
|
|
92
|
-
They are defensive: the manager guards `agent?.session` before delegating, so the session guard is unreachable in normal flow but protects the invariant for direct `Agent.resume()` callers/tests.
|
|
93
|
-
|
|
94
|
-
### `AgentManager.resume()` (delegation)
|
|
95
|
-
|
|
96
|
-
```typescript
|
|
97
|
-
async resume(id: string, prompt: string, signal?: AbortSignal): Promise<Agent | undefined> {
|
|
98
|
-
const agent = this.agents.get(id);
|
|
99
|
-
if (!agent?.session) return undefined;
|
|
100
|
-
await agent.resume(prompt, signal);
|
|
101
|
-
return agent;
|
|
102
|
-
}
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
Edge cases preserved:
|
|
106
|
-
|
|
107
|
-
- Missing record → `undefined` (no throw).
|
|
108
|
-
- Record present but no session → `undefined` (no throw).
|
|
109
|
-
- Session present → delegate, return the agent.
|
|
110
|
-
|
|
111
|
-
After this change `agent-manager.ts` no longer references `subscribeAgentObserver` — that import must be removed.
|
|
112
|
-
`this.runner` is still used by `spawn()` (passed to the `Agent` constructor), so the `runner` field stays.
|
|
113
|
-
|
|
114
|
-
## Module-Level Changes
|
|
115
|
-
|
|
116
|
-
- `src/lifecycle/agent.ts`
|
|
117
|
-
- Add the public async method `resume(prompt: string, signal?: AbortSignal): Promise<void>` (placed near `run()` per the stepdown rule).
|
|
118
|
-
- No new imports — `subscribeAgentObserver` is already imported for `run()`.
|
|
119
|
-
- `src/lifecycle/agent-manager.ts`
|
|
120
|
-
- Replace the body of `resume()` with the guard-plus-delegation form above.
|
|
121
|
-
- Remove the now-unused `import { subscribeAgentObserver } from "#src/observation/record-observer";`.
|
|
122
|
-
- No other methods change.
|
|
123
|
-
- `src/lifecycle/agent-runner.ts` — unchanged.
|
|
124
|
-
- `src/observation/record-observer.ts` — unchanged.
|
|
125
|
-
- `docs/architecture/architecture.md` — light doc touch:
|
|
126
|
-
- In the class diagram, update `AgentManager.resume(id, snapshot, exec)` → `resume(id, prompt, signal)` and add `Agent.resume(prompt, signal)` (and, while there, `Agent.run()`, which #229 omitted).
|
|
127
|
-
- Mark Step 6 in the Phase 15 roadmap table/section as complete (`✅`).
|
|
128
|
-
- Note: the class diagram has pre-existing staleness from #229; this touch only corrects the resume-related entries, not the whole diagram.
|
|
129
|
-
|
|
130
|
-
Symbol-removal check: the only removed symbol is the `subscribeAgentObserver` import in `agent-manager.ts`.
|
|
131
|
-
`grep` confirms `subscribeAgentObserver` is still imported and used in `agent.ts` and defined in `record-observer.ts`, so the export stays live.
|
|
132
|
-
|
|
133
|
-
No file in Module-Level Changes is claimed unchanged in Non-Goals (the Non-Goals list `agent-runner.ts` and `record-observer.ts`, which are genuinely untouched).
|
|
134
|
-
|
|
135
|
-
## Test Impact Analysis
|
|
136
|
-
|
|
137
|
-
This is an extraction/relocation of behavior from the manager into the agent.
|
|
138
|
-
|
|
139
|
-
1. New unit tests enabled — `Agent.resume()` can now be tested directly on `Agent` (file `test/lifecycle/agent.test.ts`), which was previously impossible because resume logic lived only in the manager.
|
|
140
|
-
New direct coverage:
|
|
141
|
-
- `resume()` transitions to `completed` and sets `result` from the runner's response text.
|
|
142
|
-
- `resume()` transitions to `error` (and does not throw) when `runner.resume()` rejects.
|
|
143
|
-
- `resume()` subscribes the record-observer to the session (usage/compaction events accumulate on the agent) and releases the subscription in `finally` (handle cleared after completion and after error).
|
|
144
|
-
- `resume()` throws on missing runner / missing session (guard symmetry with `run()`).
|
|
145
|
-
- Compaction during resume forwards through `this.observer?.onCompacted?.`.
|
|
146
|
-
|
|
147
|
-
2. Existing tests that become redundant — none should be deleted.
|
|
148
|
-
The two manager-level resume tests in `test/lifecycle/agent-manager.test.ts` (`resume() also accumulates usage and increments compactions on the same record` and `calls injected runner.resume when resuming an agent`) now exercise the delegation + observer-forwarding integration rather than the inlined logic.
|
|
149
|
-
They stay as integration coverage of `AgentManager.resume()` → `Agent.resume()` and the `onCompacted` → `onAgentCompacted` routing.
|
|
150
|
-
`test/helpers/make-deps.test.ts` (calls `manager.resume(...)`) stays.
|
|
151
|
-
|
|
152
|
-
3. Existing tests that must stay as-is — the manager-level resume tests above genuinely exercise the manager's guard + delegation seam and the observer routing through `buildObserver`, which the agent-level tests do not cover.
|
|
153
|
-
|
|
154
|
-
## TDD Order
|
|
155
|
-
|
|
156
|
-
1. `test/lifecycle/agent.test.ts` — add `Agent.resume()` happy-path + error + guard tests, then implement `Agent.resume()` in `agent.ts`.
|
|
157
|
-
Covers: completed/result on success, error (no throw) on rejection, observer subscribe + `releaseListeners()` in `finally`, compaction forwarding via `onCompacted`, and the missing-runner / missing-session guards.
|
|
158
|
-
At this point both the new `Agent.resume()` and the old `AgentManager.resume()` body coexist (lift-and-shift: introduce the new method alongside the old logic).
|
|
159
|
-
Commit: `feat: add Agent.resume() with internal observer lifecycle`
|
|
160
|
-
2. `test/lifecycle/agent-manager.test.ts` — keep the existing resume tests green, then collapse `AgentManager.resume()` to the guard-plus-delegation form and remove the unused `subscribeAgentObserver` import in the same commit.
|
|
161
|
-
Removing the import and rewriting the body must land together — the type checker flags the unused import immediately, and the existing manager-level resume tests verify the delegation still satisfies the same contract.
|
|
162
|
-
Commit: `refactor: delegate AgentManager.resume() to Agent.resume()`
|
|
163
|
-
3. `docs/architecture/architecture.md` — update the class diagram resume entries (and add `Agent.run()`/`Agent.resume()`), mark Step 6 complete.
|
|
164
|
-
Commit: `docs: mark Phase 15 Step 6 (Agent.resume) complete`
|
|
165
|
-
|
|
166
|
-
## Risks and Mitigations
|
|
167
|
-
|
|
168
|
-
- Risk: observer routing diverges (compaction events stop reaching `onAgentCompacted`).
|
|
169
|
-
Mitigation: the existing manager-level test `resume() also accumulates usage and increments compactions on the same record` asserts `compactionCount` after resume; it stays green only if routing is preserved.
|
|
170
|
-
- Risk: listener leak if `releaseListeners()` is missed on the error path.
|
|
171
|
-
Mitigation: `releaseListeners()` is in `finally`; a dedicated agent-level test asserts the unsub handle is released after both success and error.
|
|
172
|
-
- Risk: behavior change in abort handling if resume is rerouted through `abortController`.
|
|
173
|
-
Mitigation: explicitly keep `signal` flowing straight to `runner.resume({ signal })` (Non-Goal), identical to today.
|
|
174
|
-
- Risk: removing the `subscribeAgentObserver` import while another caller still needs it.
|
|
175
|
-
Mitigation: `grep` confirms `agent.ts` is the only other importer and `record-observer.ts` still exports it.
|
|
176
|
-
|
|
177
|
-
## Open Questions
|
|
178
|
-
|
|
179
|
-
- Whether to later refresh the full `AgentManager`/`Agent` class diagram in `architecture.md` (stale since #229).
|
|
180
|
-
Deferred — out of scope for this issue; a focused follow-up can resync the whole diagram.
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
issue: 237
|
|
3
|
-
issue_title: "Remove disallowed_tools from pi-subagents (Phase 14, Step 1)"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Remove `disallowed_tools` from pi-subagents
|
|
7
|
-
|
|
8
|
-
## Problem Statement
|
|
9
|
-
|
|
10
|
-
The `disallowed_tools` frontmatter field and its runtime counterpart `disallowedSet` duplicate what pi-permission-system already provides via the `permission:` frontmatter with richer semantics (allow/ask/deny vs. binary hide).
|
|
11
|
-
Removing it establishes a single source of truth for tool access control in pi-permission-system and simplifies `filterActiveTools`, `ToolFilterConfig`, and `AgentConfig`.
|
|
12
|
-
|
|
13
|
-
## Goals
|
|
14
|
-
|
|
15
|
-
- Remove the `disallowedTools` field from `AgentConfig` and all code that reads, parses, or serializes it.
|
|
16
|
-
- Remove the `disallowedSet` field from `ToolFilterConfig` and the construction logic in `assembleSessionConfig`.
|
|
17
|
-
- Remove the `disallowedSet` branch from `filterActiveTools` in `agent-runner.ts`.
|
|
18
|
-
- Remove `disallowed_tools` from the agent config editor UI and the agent creation wizard.
|
|
19
|
-
- Update README.md to remove all `disallowed_tools` references and add a migration note.
|
|
20
|
-
- Update tests to remove `disallowedTools`/`disallowedSet` assertions and fixture data.
|
|
21
|
-
- This is a **breaking change** — users with `disallowed_tools` in agent frontmatter must migrate to `permission:` frontmatter.
|
|
22
|
-
|
|
23
|
-
## Non-Goals
|
|
24
|
-
|
|
25
|
-
- Removing `extensions` filtering (Step 2, #238).
|
|
26
|
-
- Collapsing `filterActiveTools` to a recursion guard (Step 3, #239).
|
|
27
|
-
- Changing any pi-permission-system code — this issue is purely pi-subagents.
|
|
28
|
-
- Adding deprecation warnings or runtime migration helpers — the architecture doc calls for clean removal.
|
|
29
|
-
|
|
30
|
-
## Background
|
|
31
|
-
|
|
32
|
-
### Phase 14 context
|
|
33
|
-
|
|
34
|
-
This is Phase 14, Step 1 of the architecture roadmap in `docs/architecture/architecture.md`.
|
|
35
|
-
Steps 1 and 2 (#237, #238) are independent; Step 3 (#239) depends on both.
|
|
36
|
-
|
|
37
|
-
### Files involved
|
|
38
|
-
|
|
39
|
-
| File | Role |
|
|
40
|
-
| --------------------------------- | -------------------------------------------------------------------------- |
|
|
41
|
-
| `src/types.ts` | `AgentConfig.disallowedTools` field definition |
|
|
42
|
-
| `src/config/custom-agents.ts` | Parses `disallowed_tools` from YAML frontmatter |
|
|
43
|
-
| `src/session/session-config.ts` | `ToolFilterConfig.disallowedSet` + construction in `assembleSessionConfig` |
|
|
44
|
-
| `src/lifecycle/agent-runner.ts` | `filterActiveTools` denylist branch + guard conditions at two call sites |
|
|
45
|
-
| `src/ui/agent-config-editor.ts` | Serializes `disallowedTools` to `disallowed_tools` frontmatter |
|
|
46
|
-
| `src/ui/agent-creation-wizard.ts` | Template text showing `disallowed_tools` as an available field |
|
|
47
|
-
| `README.md` | Feature list, frontmatter table, memory detection note, patch notes |
|
|
48
|
-
|
|
49
|
-
### `filterActiveTools` after this change
|
|
50
|
-
|
|
51
|
-
With `disallowedSet` removed, the function simplifies:
|
|
52
|
-
|
|
53
|
-
```typescript
|
|
54
|
-
function filterActiveTools(
|
|
55
|
-
activeTools: string[],
|
|
56
|
-
config: ToolFilterConfig,
|
|
57
|
-
): string[] {
|
|
58
|
-
const { toolNames, extensions } = config;
|
|
59
|
-
if (extensions === false) {
|
|
60
|
-
return activeTools;
|
|
61
|
-
}
|
|
62
|
-
const builtinToolNameSet = new Set(toolNames);
|
|
63
|
-
return activeTools.filter((t) => {
|
|
64
|
-
if (EXCLUDED_TOOL_NAMES.includes(t)) return false;
|
|
65
|
-
if (builtinToolNameSet.has(t)) return true;
|
|
66
|
-
if (Array.isArray(extensions)) {
|
|
67
|
-
return extensions.some((ext) => t.startsWith(ext) || t.includes(ext));
|
|
68
|
-
}
|
|
69
|
-
return true;
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
The `extensions === false` branch becomes a trivial passthrough — no filtering at all.
|
|
75
|
-
The guard condition at both call sites simplifies from `cfg.toolFilter.extensions !== false || cfg.toolFilter.disallowedSet` to `cfg.toolFilter.extensions !== false`.
|
|
76
|
-
|
|
77
|
-
## Design Overview
|
|
78
|
-
|
|
79
|
-
This is a pure removal — no new types, no new modules, no new behavior.
|
|
80
|
-
Every change deletes or simplifies existing code.
|
|
81
|
-
|
|
82
|
-
### Migration path
|
|
83
|
-
|
|
84
|
-
Users currently using `disallowed_tools` in agent frontmatter migrate to pi-permission-system's `permission:` frontmatter:
|
|
85
|
-
|
|
86
|
-
```yaml
|
|
87
|
-
# Before
|
|
88
|
-
disallowed_tools: bash
|
|
89
|
-
|
|
90
|
-
# After
|
|
91
|
-
permission:
|
|
92
|
-
bash: deny
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
## Module-Level Changes
|
|
96
|
-
|
|
97
|
-
1. **`src/types.ts`** — Remove the `disallowedTools` field and its JSDoc comment from `AgentConfig`.
|
|
98
|
-
2. **`src/config/custom-agents.ts`** — Remove the `disallowedTools: csvListOptional(fm.disallowed_tools)` line from the agent config construction.
|
|
99
|
-
3. **`src/session/session-config.ts`** — Remove `disallowedSet` from the `ToolFilterConfig` interface.
|
|
100
|
-
Remove the `disallowedSet` construction block and its comment in `assembleSessionConfig`.
|
|
101
|
-
Remove `disallowedSet` from the `toolFilter` object literal.
|
|
102
|
-
4. **`src/lifecycle/agent-runner.ts`** — Remove the `disallowedSet` destructure and denylist branches from `filterActiveTools`.
|
|
103
|
-
Simplify the `extensions === false` branch to `return activeTools`.
|
|
104
|
-
Simplify both guard conditions from `cfg.toolFilter.extensions !== false || cfg.toolFilter.disallowedSet` to `cfg.toolFilter.extensions !== false`.
|
|
105
|
-
Update comments that mention `disallowedTools denylist`.
|
|
106
|
-
5. **`src/ui/agent-config-editor.ts`** — Remove the two lines that serialize `disallowedTools` to `disallowed_tools` frontmatter.
|
|
107
|
-
6. **`src/ui/agent-creation-wizard.ts`** — Remove the `disallowed_tools:` line from the template text.
|
|
108
|
-
7. **`README.md`** — Remove the "Tool denylist" feature bullet, the `disallowed_tools` row from the frontmatter table, the memory write-capability paragraph (memory was removed in #185; this reference is already stale), the `disallowed_tools` example in the memory section, and the `disallowedTools` mention in the Patch 2 notes.
|
|
109
|
-
Add a migration note under a "Migration" heading or in the breaking changes section.
|
|
110
|
-
|
|
111
|
-
### Test files
|
|
112
|
-
|
|
113
|
-
8. **`test/config/custom-agents.test.ts`** — Remove the two `disallowed_tools` tests ("parses disallowed_tools as csv list" and "disallowed_tools defaults to undefined when omitted").
|
|
114
|
-
9. **`test/session/session-config.test.ts`** — Remove the `disallowedSet` assertion from the default config test and remove the entire "builds disallowedSet from agentConfig.disallowedTools" test.
|
|
115
|
-
10. **`test/lifecycle/agent-runner-extension-tools.test.ts`** — Remove `disallowedTools` from both mock agent config objects.
|
|
116
|
-
Remove the three `disallowedTools`-specific tests ("post-bind re-filter respects disallowedTools denylist", "extensions: false still applies disallowedTools", "extensions: false with no disallowedTools skips the filter").
|
|
117
|
-
Update the file-level JSDoc comment.
|
|
118
|
-
11. **`test/ui/agent-config-editor.test.ts`** — Remove `disallowedTools` from the test fixture and remove the `disallowed_tools` assertion.
|
|
119
|
-
|
|
120
|
-
### Architecture docs
|
|
121
|
-
|
|
122
|
-
12. **`docs/architecture/architecture.md`** — Mark Step 1 as complete (update the step heading or add a completion note).
|
|
123
|
-
|
|
124
|
-
## Test Impact Analysis
|
|
125
|
-
|
|
126
|
-
1. **Tests removed** — 7 tests that directly assert `disallowedTools`/`disallowedSet` behavior become meaningless and are deleted:
|
|
127
|
-
- `custom-agents.test.ts`: 2 tests (csv parsing, undefined default)
|
|
128
|
-
- `session-config.test.ts`: 1 test (`disallowedSet` construction) + 1 assertion in default config test
|
|
129
|
-
- `agent-runner-extension-tools.test.ts`: 3 tests (denylist for extension tools, denylist for built-in tools with `extensions: false`, filter skip with `extensions: false` + no denylist)
|
|
130
|
-
- `agent-config-editor.test.ts`: 1 assertion in the serialization test
|
|
131
|
-
|
|
132
|
-
2. **Tests updated** — Several tests have `disallowedTools` in their mock fixtures but don't test it directly; those fixtures lose the field:
|
|
133
|
-
- `agent-runner-extension-tools.test.ts`: both mock config objects drop `disallowedTools`
|
|
134
|
-
|
|
135
|
-
3. **Tests unchanged** — The remaining `agent-runner-extension-tools.test.ts` tests (`extensions: true`, `extensions: string[]` allowlist, `extensions: false` passthrough) remain valid — they test extension filtering, not the denylist.
|
|
136
|
-
|
|
137
|
-
## TDD Order
|
|
138
|
-
|
|
139
|
-
1. **Remove `disallowedTools` from `AgentConfig`** — Delete the field and JSDoc from `types.ts`.
|
|
140
|
-
Remove `disallowedTools` parsing from `custom-agents.ts`.
|
|
141
|
-
Remove the two `disallowed_tools` tests from `custom-agents.test.ts`.
|
|
142
|
-
Run `pnpm run check` to surface all downstream type errors.
|
|
143
|
-
Commit: `feat!: remove disallowedTools from AgentConfig`
|
|
144
|
-
|
|
145
|
-
2. **Remove `disallowedSet` from `ToolFilterConfig` and `assembleSessionConfig`** — Delete the field from `ToolFilterConfig`, the construction block in `assembleSessionConfig`, and the `disallowedSet` key from the return literal.
|
|
146
|
-
Remove the `disallowedSet`-specific test and assertion from `session-config.test.ts`.
|
|
147
|
-
Run `pnpm run check`.
|
|
148
|
-
Commit: `refactor: remove disallowedSet from ToolFilterConfig`
|
|
149
|
-
|
|
150
|
-
3. **Simplify `filterActiveTools` and guard conditions** — Remove the `disallowedSet` destructure and denylist branches from `filterActiveTools`.
|
|
151
|
-
Simplify the `extensions === false` branch to `return activeTools`.
|
|
152
|
-
Simplify both guard conditions to `cfg.toolFilter.extensions !== false`.
|
|
153
|
-
Update comments.
|
|
154
|
-
Remove the three `disallowedTools`-specific tests and update mock fixtures in `agent-runner-extension-tools.test.ts`.
|
|
155
|
-
Run tests: `pnpm vitest run`.
|
|
156
|
-
Commit: `refactor: remove disallowedSet branch from filterActiveTools`
|
|
157
|
-
|
|
158
|
-
4. **Remove `disallowed_tools` from UI** — Remove serialization from `agent-config-editor.ts` and the template line from `agent-creation-wizard.ts`.
|
|
159
|
-
Remove `disallowedTools` from the test fixture and assertion in `agent-config-editor.test.ts`.
|
|
160
|
-
Run tests: `pnpm vitest run`.
|
|
161
|
-
Commit: `refactor: remove disallowed_tools from config editor and creation wizard`
|
|
162
|
-
|
|
163
|
-
5. **Update README.md** — Remove all `disallowed_tools` references (feature bullet, frontmatter table row, stale memory paragraph, example, patch notes mention).
|
|
164
|
-
Add a migration note directing users to `permission:` frontmatter.
|
|
165
|
-
Commit: `docs: remove disallowed_tools from README and add migration note`
|
|
166
|
-
|
|
167
|
-
6. **Mark Phase 14 Step 1 complete in architecture doc** — Update `docs/architecture/architecture.md` to reflect completion.
|
|
168
|
-
Commit: `docs: mark Phase 14 Step 1 complete in architecture`
|
|
169
|
-
|
|
170
|
-
## Risks and Mitigations
|
|
171
|
-
|
|
172
|
-
| Risk | Mitigation |
|
|
173
|
-
| ---------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
174
|
-
| Users with existing `disallowed_tools` frontmatter silently lose tool restrictions | Breaking change is intentional and documented; `feat!:` commit triggers a major version bump via release-please; README migration note directs to `permission:` frontmatter |
|
|
175
|
-
| `filterActiveTools` behavior regresses for non-denylist paths | Steps 1–3 each run `pnpm run check` or `pnpm vitest run`; existing extension-filtering tests remain unchanged |
|
|
176
|
-
| Stale references to `disallowed_tools` in docs or plans | Grep sweep in step 5 covers README; architecture doc updated in step 6; historical plan/retro files are left as-is (they document past state) |
|
|
177
|
-
|
|
178
|
-
## Open Questions
|
|
179
|
-
|
|
180
|
-
None — the issue's proposed change is unambiguous and the architecture doc provides detailed step-by-step guidance.
|
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
issue: 238
|
|
3
|
-
issue_title: "Remove extensions filtering from pi-subagents (Phase 14, Step 2)"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Remove `extensions` filtering from pi-subagents
|
|
7
|
-
|
|
8
|
-
## Problem Statement
|
|
9
|
-
|
|
10
|
-
The `extensions: string[]` allowlist in agent configuration is tool filtering disguised as extension lifecycle control.
|
|
11
|
-
Extensions always initialize via `bindExtensions()` — the allowlist only hides their tools from the active set afterward, which is pi-permission-system's responsibility.
|
|
12
|
-
Simplifying `extensions` from `true | string[] | false` to `boolean` removes this overlap and makes pi-permission-system the sole authority for tool access control.
|
|
13
|
-
|
|
14
|
-
## Goals
|
|
15
|
-
|
|
16
|
-
- Simplify `extensions` from `true | string[] | false` to `boolean` in `AgentConfig`, `ToolFilterConfig`, and all related code.
|
|
17
|
-
- Remove the `Array.isArray(extensions)` branch from `filterActiveTools` in `agent-runner.ts`.
|
|
18
|
-
- Remove extensions array handling from the agent config editor and creation wizard.
|
|
19
|
-
- Update custom agent frontmatter parsing to coerce array values to `true` (with a deprecation warning).
|
|
20
|
-
- Update tests to remove `extensions: string[]` assertions and fixture data.
|
|
21
|
-
- This is a **breaking change** — users with `extensions: <csv-list>` in agent frontmatter lose per-extension filtering.
|
|
22
|
-
|
|
23
|
-
## Non-Goals
|
|
24
|
-
|
|
25
|
-
- Collapsing `filterActiveTools` to a recursion guard (Step 3, #239).
|
|
26
|
-
- Removing `extensions: false` — it is retained here (used by `isolated`) and dissolved in Phase 16.
|
|
27
|
-
- Changing any pi-permission-system code — this issue is purely pi-subagents.
|
|
28
|
-
- Removing Patch 2 (post-bind re-filter) — it still serves the `EXCLUDED_TOOL_NAMES` recursion guard when `extensions === true`.
|
|
29
|
-
Issue #239 collapses the two-pass dance.
|
|
30
|
-
|
|
31
|
-
## Background
|
|
32
|
-
|
|
33
|
-
### Phase 14 context
|
|
34
|
-
|
|
35
|
-
This is Phase 14, Step 2 of the architecture roadmap in `docs/architecture/architecture.md`.
|
|
36
|
-
Steps 1 (#237, completed) and 2 (#238) are independent; Step 3 (#239) depends on both.
|
|
37
|
-
|
|
38
|
-
### Files involved
|
|
39
|
-
|
|
40
|
-
| File | Role |
|
|
41
|
-
| --------------------------------- | --------------------------------------------------------------------------- |
|
|
42
|
-
| `src/types.ts` | `AgentConfig.extensions` field type |
|
|
43
|
-
| `src/config/custom-agents.ts` | Parses `extensions` from YAML frontmatter via `inheritField()` |
|
|
44
|
-
| `src/session/session-config.ts` | `ToolFilterConfig.extensions` type + passthrough in `assembleSessionConfig` |
|
|
45
|
-
| `src/lifecycle/agent-runner.ts` | `filterActiveTools` array branch + Patch 2 comment |
|
|
46
|
-
| `src/ui/agent-config-editor.ts` | Serializes `extensions` array to frontmatter |
|
|
47
|
-
| `src/ui/agent-creation-wizard.ts` | Template text describing `extensions` field options |
|
|
48
|
-
| `README.md` | Frontmatter table row, Patch 2 notes |
|
|
49
|
-
|
|
50
|
-
### `filterActiveTools` after this change
|
|
51
|
-
|
|
52
|
-
```typescript
|
|
53
|
-
function filterActiveTools(
|
|
54
|
-
activeTools: string[],
|
|
55
|
-
config: ToolFilterConfig,
|
|
56
|
-
): string[] {
|
|
57
|
-
const { toolNames, extensions } = config;
|
|
58
|
-
if (extensions === false) {
|
|
59
|
-
return activeTools;
|
|
60
|
-
}
|
|
61
|
-
const builtinToolNameSet = new Set(toolNames);
|
|
62
|
-
return activeTools.filter((t) => {
|
|
63
|
-
if (EXCLUDED_TOOL_NAMES.includes(t)) return false;
|
|
64
|
-
if (builtinToolNameSet.has(t)) return true;
|
|
65
|
-
return true;
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
The `Array.isArray(extensions)` branch is gone.
|
|
71
|
-
The `builtinToolNameSet.has(t)` check becomes redundant (always returns true for builtins, falls through to `return true` for non-builtins) — but simplifying further is #239's scope.
|
|
72
|
-
|
|
73
|
-
### Custom agent frontmatter migration
|
|
74
|
-
|
|
75
|
-
The `inheritField()` function currently parses CSV values into `string[]`.
|
|
76
|
-
After this change, it must still accept array values gracefully: coerce them to `true` and emit a warning so users know to update their frontmatter.
|
|
77
|
-
|
|
78
|
-
## Design Overview
|
|
79
|
-
|
|
80
|
-
This is primarily a removal — no new types, no new modules.
|
|
81
|
-
The one piece of new behavior is the deprecation warning when `inheritField` encounters an array value for `extensions`.
|
|
82
|
-
|
|
83
|
-
### `inheritField` change
|
|
84
|
-
|
|
85
|
-
Currently `inheritField` is shared between `extensions` and `skills` parsing.
|
|
86
|
-
Since `skills` still supports `string[]`, the function itself cannot change.
|
|
87
|
-
Instead, the call site for `extensions` will post-process: if `inheritField` returns `string[]`, coerce to `true` and log a warning.
|
|
88
|
-
|
|
89
|
-
### Type change scope
|
|
90
|
-
|
|
91
|
-
`AgentConfig.extensions` changes from `true | string[] | false` to `boolean`.
|
|
92
|
-
`ToolFilterConfig.extensions` changes from `boolean | string[]` to `boolean`.
|
|
93
|
-
Both are narrowing changes — existing `true` and `false` values remain valid.
|
|
94
|
-
|
|
95
|
-
## Module-Level Changes
|
|
96
|
-
|
|
97
|
-
1. **`src/types.ts`** — Change `extensions` type from `true | string[] | false` to `boolean`.
|
|
98
|
-
Update JSDoc comment to remove the `string[] = only listed` description.
|
|
99
|
-
2. **`src/config/custom-agents.ts`** — After calling `inheritField(fm.extensions ?? fm.inherit_extensions)`, coerce `string[]` results to `true` and emit a `debugLog` warning.
|
|
100
|
-
The warning informs users that `extensions: <csv-list>` is no longer supported and treated as `extensions: true`.
|
|
101
|
-
3. **`src/session/session-config.ts`** — Change `ToolFilterConfig.extensions` type from `boolean | string[]` to `boolean`.
|
|
102
|
-
Update the JSDoc comment.
|
|
103
|
-
The `assembleSessionConfig` passthrough `const extensions = options.isolated ? false : agentConfig.extensions;` works without changes since the type narrows.
|
|
104
|
-
4. **`src/lifecycle/agent-runner.ts`** — Remove the `Array.isArray(extensions)` branch (lines 47–49) from `filterActiveTools`.
|
|
105
|
-
Update the Patch 2 comment (line 366) that references `extensions: string[]`.
|
|
106
|
-
Update the comment at line 341 ("apply extension allowlist if specified").
|
|
107
|
-
5. **`src/ui/agent-config-editor.ts`** — Remove the `else if (Array.isArray(cfg.extensions))` branch (lines 51–52) from `buildEjectContent`.
|
|
108
|
-
6. **`src/ui/agent-creation-wizard.ts`** — Simplify the `extensions:` line in the template text from `<true (inherit all MCP/extension tools), false (none), or comma-separated names. Default: true>` to `<true (inherit all MCP/extension tools) or false (none). Default: true>`.
|
|
109
|
-
7. **`README.md`** — Simplify the `extensions` row in the frontmatter table to document boolean-only.
|
|
110
|
-
Update Patch 2 notes to remove `extensions: string[]` reference.
|
|
111
|
-
8. **`src/config/default-agents.ts`** — No changes needed; all defaults already use `extensions: true`.
|
|
112
|
-
|
|
113
|
-
### Test files
|
|
114
|
-
|
|
115
|
-
9. **`test/config/custom-agents.test.ts`** — Update the "handles extension allowlist" test: change expectation from `toEqual(["web-search", "mcp-server"])` to `toBe(true)` since CSV values now coerce to `true`.
|
|
116
|
-
Add a test verifying the deprecation warning is emitted.
|
|
117
|
-
10. **`test/session/session-config.test.ts`** — Update the "isolated:true forces extensions to false even for string[] extension list" test: since `AgentConfig.extensions` no longer supports `string[]`, simplify this test to use `extensions: true` and verify `isolated` still forces it to `false`.
|
|
118
|
-
The test name changes to reflect the boolean type.
|
|
119
|
-
11. **`test/lifecycle/agent-runner-extension-tools.test.ts`** — Remove the "post-bind re-filter respects extensions: string[] allowlist" test (line 139).
|
|
120
|
-
Change the `extensions` type annotation in the mutable config mock (line 26) from `boolean | string[]` to `boolean`.
|
|
121
|
-
Update the file-level JSDoc comment to remove `extensions: string[]` references.
|
|
122
|
-
12. **`test/ui/agent-config-editor.test.ts`** — Remove the "emits 'extensions: \<list\>' when extensions is an array" test.
|
|
123
|
-
13. **Test fixtures** — All test helper defaults already use `extensions: false` or `extensions: true`; no fixture changes needed beyond the tests listed above.
|
|
124
|
-
|
|
125
|
-
### Architecture docs
|
|
126
|
-
|
|
127
|
-
14. **`docs/architecture/architecture.md`** — Mark Step 2 as complete.
|
|
128
|
-
|
|
129
|
-
## Test Impact Analysis
|
|
130
|
-
|
|
131
|
-
1. **Tests removed** — 2 tests that directly assert `extensions: string[]` behavior:
|
|
132
|
-
- `agent-runner-extension-tools.test.ts`: "post-bind re-filter respects extensions: string[] allowlist"
|
|
133
|
-
- `agent-config-editor.test.ts`: "emits 'extensions: \<list\>' when extensions is an array"
|
|
134
|
-
|
|
135
|
-
2. **Tests updated** — 3 tests that reference `extensions: string[]` in fixtures or assertions:
|
|
136
|
-
- `custom-agents.test.ts`: "handles extension allowlist" → expectation changes to `true`
|
|
137
|
-
- `session-config.test.ts`: "isolated:true forces extensions to false even for string[] extension list" → uses `true` instead of array
|
|
138
|
-
- `agent-runner-extension-tools.test.ts`: mock config type annotation narrows
|
|
139
|
-
|
|
140
|
-
3. **Tests added** — 1 test:
|
|
141
|
-
- `custom-agents.test.ts`: verifies deprecation warning when array value is provided
|
|
142
|
-
|
|
143
|
-
4. **Tests unchanged** — All other `extensions: true` and `extensions: false` tests remain valid since the boolean cases are preserved.
|
|
144
|
-
|
|
145
|
-
## TDD Order
|
|
146
|
-
|
|
147
|
-
1. **Narrow `extensions` type in `AgentConfig` and `ToolFilterConfig`** — Change `extensions` from `true | string[] | false` to `boolean` in `types.ts`.
|
|
148
|
-
Change `ToolFilterConfig.extensions` from `boolean | string[]` to `boolean` in `session-config.ts`.
|
|
149
|
-
Update JSDoc comments.
|
|
150
|
-
Run `pnpm run check` to surface all downstream type errors.
|
|
151
|
-
Commit: `feat!: narrow extensions type from union to boolean`
|
|
152
|
-
|
|
153
|
-
2. **Remove array branch from `filterActiveTools`** — Remove the `Array.isArray(extensions)` branch.
|
|
154
|
-
Update the Patch 2 comment and the pre-bind filter comment.
|
|
155
|
-
Remove the "post-bind re-filter respects extensions: string[] allowlist" test.
|
|
156
|
-
Narrow the mock config type annotation in `agent-runner-extension-tools.test.ts`.
|
|
157
|
-
Update the file-level JSDoc.
|
|
158
|
-
Run tests: `pnpm vitest run`.
|
|
159
|
-
Commit: `refactor: remove extensions array branch from filterActiveTools`
|
|
160
|
-
|
|
161
|
-
3. **Coerce array values in custom agent frontmatter** — Update the `extensions` assignment in `custom-agents.ts` to coerce `string[]` results from `inheritField` to `true` with a deprecation warning.
|
|
162
|
-
Update the "handles extension allowlist" test expectation from array to `true`.
|
|
163
|
-
Add a test for the deprecation warning.
|
|
164
|
-
Update the "isolated:true forces extensions to false even for string[] extension list" test in `session-config.test.ts` to use `extensions: true`.
|
|
165
|
-
Run tests: `pnpm vitest run`.
|
|
166
|
-
Commit: `refactor: coerce extensions array values to true with deprecation warning`
|
|
167
|
-
|
|
168
|
-
4. **Remove extensions array from UI** — Remove the `Array.isArray(cfg.extensions)` branch from `buildEjectContent`.
|
|
169
|
-
Simplify the `extensions:` line in the creation wizard template.
|
|
170
|
-
Remove the "emits 'extensions: \<list\>'" test from `agent-config-editor.test.ts`.
|
|
171
|
-
Run tests: `pnpm vitest run`.
|
|
172
|
-
Commit: `refactor: remove extensions array from config editor and creation wizard`
|
|
173
|
-
|
|
174
|
-
5. **Update README** — Simplify the `extensions` frontmatter table row to document boolean-only.
|
|
175
|
-
Update Patch 2 notes to remove `extensions: string[]` reference.
|
|
176
|
-
Commit: `docs: simplify extensions field to boolean in README`
|
|
177
|
-
|
|
178
|
-
6. **Mark Phase 14 Step 2 complete** — Update `docs/architecture/architecture.md`.
|
|
179
|
-
Commit: `docs: mark Phase 14 Step 2 complete in architecture`
|
|
180
|
-
|
|
181
|
-
## Risks and Mitigations
|
|
182
|
-
|
|
183
|
-
| Risk | Mitigation |
|
|
184
|
-
| -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
185
|
-
| Users with `extensions: <csv-list>` silently lose per-extension filtering | `feat!:` commit triggers major version bump; frontmatter parser emits deprecation warning and coerces to `true`; README documents the change |
|
|
186
|
-
| `filterActiveTools` behavior regresses for boolean paths | Steps 1–4 each run type checks or tests; `extensions: true` and `extensions: false` tests are unchanged |
|
|
187
|
-
| Type annotation `boolean | string[]` in test mock causes tsc errors after step 1 | Step 2 narrows the annotation in the same commit that removes the array branch |
|
|
188
|
-
|
|
189
|
-
## Open Questions
|
|
190
|
-
|
|
191
|
-
None — the issue's proposed change and the architecture doc's step description are unambiguous.
|