@gotgenes/pi-subagents 18.0.0 → 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 +14 -0
- package/README.md +22 -31
- 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/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/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 -45
- package/docs/retro/0442-dissolve-agents-conversation-viewer.md +0 -108
- 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/src/observation/notification-state.ts +0 -27
- package/vitest.config.ts +0 -14
|
@@ -1,304 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
issue: 277
|
|
3
|
-
issue_title: "Encapsulate AgentSession behind SubagentSession; retire the remaining agent.session reach-throughs"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Encapsulate AgentSession behind SubagentSession
|
|
7
|
-
|
|
8
|
-
## Problem Statement
|
|
9
|
-
|
|
10
|
-
Callers outside the `lifecycle/` domain reach through `Agent.session` (which returns the raw SDK `AgentSession` via `this.subagentSession?.session`) and operate on the session object directly.
|
|
11
|
-
This violates Law of Demeter and Tell-Don't-Ask — the missing abstractions are intent-revealing methods on `Agent` and `SubagentSession` that delegate internally.
|
|
12
|
-
|
|
13
|
-
Issue #265 introduced `SubagentSession` and routed the run/resume/dispose path through it.
|
|
14
|
-
The remaining consumer-facing reach-throughs were deferred to this issue.
|
|
15
|
-
|
|
16
|
-
## Goals
|
|
17
|
-
|
|
18
|
-
- Add intent-revealing methods to `Agent` and `SubagentSession` that replace every raw `AgentSession` access outside `lifecycle/`.
|
|
19
|
-
- Collapse the duplicated steer buffer-or-deliver logic into a single `Agent.steer()` method.
|
|
20
|
-
- Narrow the `onSessionCreated` observer callback to stop delivering the raw `AgentSession` to spawners.
|
|
21
|
-
- Remove the `Agent.session` getter.
|
|
22
|
-
- After this change, no production module outside `lifecycle/` references the raw `AgentSession`.
|
|
23
|
-
|
|
24
|
-
## Non-Goals
|
|
25
|
-
|
|
26
|
-
- The `Agent` → `Subagent` class rename — independent of this issue, can land in either order.
|
|
27
|
-
- Changing the public `SubagentsService` API surface in `service/service.ts` — it already uses `SubagentRecord` (no live session objects).
|
|
28
|
-
- Refactoring the conversation viewer's rich-rendering internals — only its session reference changes.
|
|
29
|
-
- Architecture doc updates for the file-layout listing — `SubagentSession` and `Agent` files are not being added, moved, or removed.
|
|
30
|
-
|
|
31
|
-
## Background
|
|
32
|
-
|
|
33
|
-
### Affected reach-through sites
|
|
34
|
-
|
|
35
|
-
Every site reaches the raw `AgentSession` exposed by the `Agent.session` getter.
|
|
36
|
-
|
|
37
|
-
| Reach-through | Production files | Current pattern |
|
|
38
|
-
| -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
|
|
39
|
-
| Steer buffer-or-deliver (duplicated) | `service/service-adapter.ts:93`, `tools/steer-tool.ts:43` | `record.session` → `session.steer()` or `record.queueSteer()` |
|
|
40
|
-
| Context-percent stats | `tools/get-result-tool.ts:56`, `tools/steer-tool.ts:57`, `observation/notification.ts:49`, `ui/conversation-viewer.ts:145` | `getSessionContextPercent(record.session)` |
|
|
41
|
-
| Conversation viewing | `tools/get-result-tool.ts:83-84`, `ui/agent-menu.ts:255`, `ui/conversation-viewer.ts:63,223` | `getAgentConversation(record.session)` / `session.messages` |
|
|
42
|
-
| Session-readiness guard | `tools/agent-tool.ts:111`, `lifecycle/agent-manager.ts:205` | `!record.session` / `!agent?.session` |
|
|
43
|
-
| Observer callback delivers raw session | `tools/background-spawner.ts:56`, `tools/foreground-runner.ts:111` | `onSessionCreated(_agent, session)` → `tracker.setSession(session)` + `subscribeUIObserver(session, tracker)` |
|
|
44
|
-
| Activity-tracker session stats | `ui/widget-renderer.ts:106` | `activity?.session` → `getSessionContextPercent(activity.session)` (via `AgentActivityTracker.session`) |
|
|
45
|
-
|
|
46
|
-
### Existing delegate methods
|
|
47
|
-
|
|
48
|
-
`SubagentSession` already has `steer(message)`, `runTurnLoop()`, `resumeTurnLoop()`, and `dispose()`.
|
|
49
|
-
The `session` getter is marked "retired by #277" in its JSDoc.
|
|
50
|
-
|
|
51
|
-
`subscribeAgentObserver` in `observation/record-observer.ts` already accepts `SubscribableSession` (not `AgentSession`), so it can accept `SubagentSession` directly once `SubagentSession` implements the `subscribe()` delegate.
|
|
52
|
-
|
|
53
|
-
### Public API surface
|
|
54
|
-
|
|
55
|
-
The public API (`SubagentsService` + `SubagentRecord` in `service/service.ts`) does not expose `Agent` or `AgentSession`.
|
|
56
|
-
Removing `Agent.session` is not a breaking change for cross-extension consumers.
|
|
57
|
-
|
|
58
|
-
## Design Overview
|
|
59
|
-
|
|
60
|
-
### New delegate methods on `SubagentSession`
|
|
61
|
-
|
|
62
|
-
```typescript
|
|
63
|
-
// Delegates to getAgentConversation(this._session)
|
|
64
|
-
getConversation(): string
|
|
65
|
-
|
|
66
|
-
// Delegates to getSessionContextPercent(this._session)
|
|
67
|
-
getContextPercent(): number | null
|
|
68
|
-
|
|
69
|
-
// Delegates to this._session.subscribe(fn) — satisfies SubscribableSession
|
|
70
|
-
subscribe(fn: (event: AgentSessionEvent) => void): () => void
|
|
71
|
-
|
|
72
|
-
// Delegates to this._session.getSessionStats() — satisfies SessionLike
|
|
73
|
-
getSessionStats(): SessionStatsLike
|
|
74
|
-
|
|
75
|
-
// Delegates to this._session.messages
|
|
76
|
-
get messages(): readonly unknown[]
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
With `subscribe()` and `getSessionStats()`, `SubagentSession` structurally satisfies both `SubscribableSession` and `SessionLike`.
|
|
80
|
-
This lets spawners pass a `SubagentSession` directly to `subscribeUIObserver()` and `tracker.setSession()` without exposing the raw `AgentSession`.
|
|
81
|
-
|
|
82
|
-
### New intent-revealing methods on `Agent`
|
|
83
|
-
|
|
84
|
-
```typescript
|
|
85
|
-
// Buffer-or-deliver: returns true if delivered, false if buffered
|
|
86
|
-
async steer(message: string): Promise<boolean>
|
|
87
|
-
|
|
88
|
-
// Returns true when a SubagentSession is available
|
|
89
|
-
isSessionReady(): boolean
|
|
90
|
-
|
|
91
|
-
// Delegates to SubagentSession.getConversation(), returns undefined if no session
|
|
92
|
-
getConversation(): string | undefined
|
|
93
|
-
|
|
94
|
-
// Delegates to SubagentSession.getContextPercent(), returns null if no session
|
|
95
|
-
getContextPercent(): number | null
|
|
96
|
-
|
|
97
|
-
// Delegates to SubagentSession.subscribe() for conversation-viewer live updates
|
|
98
|
-
subscribeToUpdates(fn: (event: AgentSessionEvent) => void): (() => void) | undefined
|
|
99
|
-
|
|
100
|
-
// Delegates to SubagentSession.messages for conversation-viewer rendering
|
|
101
|
-
get messages(): readonly unknown[]
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
The `steer()` method replaces the duplicated buffer-or-deliver logic:
|
|
105
|
-
|
|
106
|
-
```typescript
|
|
107
|
-
async steer(message: string): Promise<boolean> {
|
|
108
|
-
if (!this.subagentSession) {
|
|
109
|
-
this.queueSteer(message);
|
|
110
|
-
return false;
|
|
111
|
-
}
|
|
112
|
-
await this.subagentSession.steer(message);
|
|
113
|
-
return true;
|
|
114
|
-
}
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
### Observer callback narrowing
|
|
118
|
-
|
|
119
|
-
`AgentLifecycleObserver.onSessionCreated` changes from `(agent: Agent, session: AgentSession)` to `(agent: Agent)`.
|
|
120
|
-
Spawners access `agent.subagentSession!` (already public) which satisfies `SubscribableSession & SessionLike`:
|
|
121
|
-
|
|
122
|
-
```typescript
|
|
123
|
-
// tools/background-spawner.ts — after
|
|
124
|
-
onSessionCreated: (agent) => {
|
|
125
|
-
const sub = agent.subagentSession!;
|
|
126
|
-
bgState.setSession(sub); // SubagentSession satisfies SessionLike
|
|
127
|
-
subscribeUIObserver(sub, bgState); // SubagentSession satisfies SubscribableSession
|
|
128
|
-
},
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
### Internal lifecycle wiring
|
|
132
|
-
|
|
133
|
-
`Agent.run()` already passes the session to `subscribeAgentObserver()`, which accepts `SubscribableSession`.
|
|
134
|
-
After the change, it passes `this.subagentSession` directly instead of `this.subagentSession.session`:
|
|
135
|
-
|
|
136
|
-
```typescript
|
|
137
|
-
// lifecycle/agent.ts — Agent.run(), after
|
|
138
|
-
this.attachObserver(subscribeAgentObserver(this.subagentSession, this, { ... }));
|
|
139
|
-
this.observer?.onSessionCreated?.(this);
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
### Removals
|
|
143
|
-
|
|
144
|
-
- `Agent.session` getter — removed entirely.
|
|
145
|
-
- `SubagentSession.session` getter — marked `@internal`, kept for lifecycle-internal uses (the `getLastAssistantText()` private helper reads `this._session.messages`).
|
|
146
|
-
- `Agent.queueSteer()` — becomes private (called only from `Agent.steer()` and `Agent.flushPendingSteers()`).
|
|
147
|
-
- `Agent.flushPendingSteers()` — becomes private (called only from `Agent.run()`).
|
|
148
|
-
|
|
149
|
-
## Module-Level Changes
|
|
150
|
-
|
|
151
|
-
### `src/lifecycle/subagent-session.ts`
|
|
152
|
-
|
|
153
|
-
- Add `getConversation()`, `getContextPercent()`, `subscribe()`, `getSessionStats()`, `messages` getter.
|
|
154
|
-
- Import `getAgentConversation` from `#src/session/conversation` and `getSessionContextPercent`, `SessionStatsLike` from `#src/lifecycle/usage`.
|
|
155
|
-
- Mark the `session` getter with `@internal` JSDoc.
|
|
156
|
-
|
|
157
|
-
### `src/lifecycle/agent.ts`
|
|
158
|
-
|
|
159
|
-
- Add `steer()`, `isSessionReady()`, `getConversation()`, `getContextPercent()`, `subscribeToUpdates()`, `messages` getter.
|
|
160
|
-
- Remove the `session` getter.
|
|
161
|
-
- Make `queueSteer()` and `flushPendingSteers()` private.
|
|
162
|
-
- In `run()`: pass `this.subagentSession` (not `this.subagentSession.session`) to `subscribeAgentObserver()` and fire `onSessionCreated(this)` without the session param.
|
|
163
|
-
- In `resume()`: pass `subagentSession` (not `subagentSession.session`) to `subscribeAgentObserver()`.
|
|
164
|
-
- Remove the `AgentSession` import.
|
|
165
|
-
- Update `AgentLifecycleObserver.onSessionCreated` to `(agent: Agent)` — no session param.
|
|
166
|
-
|
|
167
|
-
### `src/service/service-adapter.ts`
|
|
168
|
-
|
|
169
|
-
- Replace the 6-line steer reach-through with `await record.steer(message)`.
|
|
170
|
-
- Remove the `!session` guard — `Agent.steer()` owns it.
|
|
171
|
-
|
|
172
|
-
### `src/tools/steer-tool.ts`
|
|
173
|
-
|
|
174
|
-
- Replace the buffer-or-deliver dance with `const delivered = await record.steer(message)`.
|
|
175
|
-
- Use `record.getContextPercent()` instead of `getSessionContextPercent(session)`.
|
|
176
|
-
- Remove the `getSessionContextPercent` import.
|
|
177
|
-
|
|
178
|
-
### `src/tools/get-result-tool.ts`
|
|
179
|
-
|
|
180
|
-
- Use `record.getContextPercent()` instead of `getSessionContextPercent(record.session)`.
|
|
181
|
-
- Use `record.getConversation()` instead of `getAgentConversation(record.session)`.
|
|
182
|
-
- Remove the `getSessionContextPercent` and `getAgentConversation` imports.
|
|
183
|
-
|
|
184
|
-
### `src/tools/agent-tool.ts`
|
|
185
|
-
|
|
186
|
-
- Use `existing.isSessionReady()` instead of `!existing.session`.
|
|
187
|
-
|
|
188
|
-
### `src/lifecycle/agent-manager.ts`
|
|
189
|
-
|
|
190
|
-
- Use `agent.isSessionReady()` instead of `agent?.session`.
|
|
191
|
-
- Update the `onSessionCreated` relay to `(agent) => options.observer!.onSessionCreated!(agent)` — no session param.
|
|
192
|
-
|
|
193
|
-
### `src/observation/notification.ts`
|
|
194
|
-
|
|
195
|
-
- Use `record.getContextPercent()` instead of `getSessionContextPercent(record.session)`.
|
|
196
|
-
- Remove the `getSessionContextPercent` import.
|
|
197
|
-
|
|
198
|
-
### `src/ui/conversation-viewer.ts`
|
|
199
|
-
|
|
200
|
-
- Remove `session: AgentSession` from `ConversationViewerOptions`.
|
|
201
|
-
- Remove the `private session: AgentSession` field.
|
|
202
|
-
- Use `this.record.subscribeToUpdates(() => ...)` instead of `session.subscribe(...)`.
|
|
203
|
-
- Use `this.record.messages` instead of `this.session.messages`.
|
|
204
|
-
- Use `this.record.getContextPercent()` instead of `getSessionContextPercent(this.record.session)`.
|
|
205
|
-
- Remove the `AgentSession` and `getSessionContextPercent` imports.
|
|
206
|
-
|
|
207
|
-
### `src/ui/agent-menu.ts`
|
|
208
|
-
|
|
209
|
-
- Use `record.isSessionReady()` instead of `record.session` check.
|
|
210
|
-
- Remove the `session` variable and stop passing it to `ConversationViewer`.
|
|
211
|
-
|
|
212
|
-
### `src/tools/background-spawner.ts`
|
|
213
|
-
|
|
214
|
-
- Update `onSessionCreated` callback: `(agent) => { const sub = agent.subagentSession!; ... }`.
|
|
215
|
-
- Pass `sub` instead of `session` to `bgState.setSession()` and `subscribeUIObserver()`.
|
|
216
|
-
|
|
217
|
-
### `src/tools/foreground-runner.ts`
|
|
218
|
-
|
|
219
|
-
- Same pattern as `background-spawner.ts`.
|
|
220
|
-
|
|
221
|
-
### `test/helpers/mock-session.ts`
|
|
222
|
-
|
|
223
|
-
- Update `createSubagentSessionStub` to include the new delegate methods (`getConversation`, `getContextPercent`, `subscribe`, `getSessionStats`, `messages`).
|
|
224
|
-
- The stub's `subscribe` can delegate to the underlying mock session's `subscribe`.
|
|
225
|
-
|
|
226
|
-
### Test files requiring updates
|
|
227
|
-
|
|
228
|
-
- `test/lifecycle/subagent-session.test.ts` — add tests for new delegate methods.
|
|
229
|
-
- `test/lifecycle/agent.test.ts` — add tests for `steer()`, `isSessionReady()`, `getConversation()`, `getContextPercent()`; update `queueSteer` and `flushPendingSteers` tests (now private, tested through `steer()`); update `session` getter tests to `isSessionReady()`.
|
|
230
|
-
- `test/service/service-adapter.test.ts` — update steer tests (no more session reach-through).
|
|
231
|
-
- `test/tools/steer-tool.test.ts` — update to use `Agent.steer()` semantics.
|
|
232
|
-
- `test/tools/get-result-tool.test.ts` — update context-percent and conversation assertions.
|
|
233
|
-
- `test/tools/agent-tool.test.ts` — update resume guard to use `isSessionReady()`.
|
|
234
|
-
- `test/tools/background-spawner.test.ts` — update `onSessionCreated` callback assertions.
|
|
235
|
-
- `test/tools/foreground-runner.test.ts` — update `onSessionCreated` callback assertions.
|
|
236
|
-
- `test/observation/notification.test.ts` — update context-percent assertions.
|
|
237
|
-
- `test/conversation-viewer.test.ts` — remove `session` from viewer options, update to use `record` methods.
|
|
238
|
-
- `test/ui/agent-menu.test.ts` — update session guard assertions.
|
|
239
|
-
- `test/lifecycle/agent-manager.test.ts` — update resume guard + observer relay tests.
|
|
240
|
-
|
|
241
|
-
## Test Impact Analysis
|
|
242
|
-
|
|
243
|
-
1. **New unit tests enabled:** Direct testing of `SubagentSession.getConversation()`, `getContextPercent()`, `subscribe()`, `getSessionStats()`, `messages` — these were previously only testable by reaching through the raw session.
|
|
244
|
-
Direct testing of `Agent.steer()` buffer-or-deliver logic — previously scattered across consumer tests.
|
|
245
|
-
2. **Existing tests that become simpler:** `steer-tool.test.ts` and `service-adapter.test.ts` no longer need to set up the session-present/session-absent dance — they test through `Agent.steer()`.
|
|
246
|
-
`get-result-tool.test.ts` no longer needs mock sessions for context-percent assertions.
|
|
247
|
-
3. **Existing tests that stay as-is:** `SubagentSession.runTurnLoop()` and `resumeTurnLoop()` tests — they exercise turn driving, which is unrelated.
|
|
248
|
-
`Agent.run()` integration tests — they verify the full lifecycle including observer wiring.
|
|
249
|
-
|
|
250
|
-
## TDD Order
|
|
251
|
-
|
|
252
|
-
1. Add delegate methods to `SubagentSession` (`getConversation`, `getContextPercent`, `subscribe`, `getSessionStats`, `messages`).
|
|
253
|
-
Update `createSubagentSessionStub` test helper to include the new methods.
|
|
254
|
-
Test: unit tests for each delegate method in `subagent-session.test.ts`.
|
|
255
|
-
Commit: `feat: add delegate methods to SubagentSession for session encapsulation (#277)`.
|
|
256
|
-
|
|
257
|
-
2. Add intent-revealing methods to `Agent` (`steer`, `isSessionReady`, `getConversation`, `getContextPercent`, `subscribeToUpdates`, `messages`).
|
|
258
|
-
Test: unit tests for each method in `agent.test.ts`.
|
|
259
|
-
Commit: `feat: add session-encapsulation methods to Agent (#277)`.
|
|
260
|
-
|
|
261
|
-
3. Migrate steer callers: replace the buffer-or-deliver reach-through in `service-adapter.ts` and `steer-tool.ts` with `record.steer()`.
|
|
262
|
-
Replace `getSessionContextPercent(session)` in `steer-tool.ts` with `record.getContextPercent()`.
|
|
263
|
-
Make `queueSteer()` and `flushPendingSteers()` private on `Agent`.
|
|
264
|
-
Update tests in `service-adapter.test.ts`, `steer-tool.test.ts`, `agent.test.ts` (the `queueSteer`/`flushPendingSteers` tests become tests for `Agent.steer()`; existing tests from step 2 may cover this).
|
|
265
|
-
Commit: `refactor: use Agent.steer for buffer-or-deliver (#277)`.
|
|
266
|
-
|
|
267
|
-
4. Migrate context-percent, conversation, and readiness callers: `get-result-tool.ts`, `agent-tool.ts`, `agent-manager.ts`, `notification.ts`.
|
|
268
|
-
Update corresponding test files.
|
|
269
|
-
Commit: `refactor: replace session reach-throughs in tools and observation (#277)`.
|
|
270
|
-
|
|
271
|
-
5. Refactor conversation viewer and agent-menu: remove `session: AgentSession` from `ConversationViewerOptions`, use `record` methods for subscribe/messages/contextPercent.
|
|
272
|
-
Update `conversation-viewer.test.ts` and `agent-menu.test.ts`.
|
|
273
|
-
Commit: `refactor: remove raw session from conversation viewer (#277)`.
|
|
274
|
-
|
|
275
|
-
6. Narrow `onSessionCreated` callback: change `AgentLifecycleObserver.onSessionCreated` to `(agent: Agent)` — no session param.
|
|
276
|
-
Update `Agent.run()` and `Agent.resume()` to pass `SubagentSession` (not raw session) to `subscribeAgentObserver`.
|
|
277
|
-
Update spawners (`background-spawner.ts`, `foreground-runner.ts`) and `agent-manager.ts` relay.
|
|
278
|
-
Update corresponding test files.
|
|
279
|
-
Commit: `refactor: narrow onSessionCreated to hide raw AgentSession (#277)`.
|
|
280
|
-
|
|
281
|
-
7. Remove `Agent.session` getter.
|
|
282
|
-
Mark `SubagentSession.session` getter as `@internal`.
|
|
283
|
-
Remove `AgentSession` import from `agent.ts`.
|
|
284
|
-
Update any remaining tests that reference `Agent.session` (use `agent.isSessionReady()` or `agent.subagentSession`).
|
|
285
|
-
Verify with `pnpm run check` and `pnpm -r run test`.
|
|
286
|
-
Commit: `refactor: remove Agent.session getter (#277)`.
|
|
287
|
-
|
|
288
|
-
8. Update the architecture doc's "Session encapsulation debt" section to reflect completion.
|
|
289
|
-
Commit: `docs: mark session encapsulation debt resolved (#277)`.
|
|
290
|
-
|
|
291
|
-
## Risks and Mitigations
|
|
292
|
-
|
|
293
|
-
| Risk | Mitigation |
|
|
294
|
-
| --------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
295
|
-
| `SubagentSession` might not structurally satisfy `SubscribableSession` or `SessionLike` | Verify with `pnpm run check` after step 1 — the delegate methods must match the expected signatures exactly. |
|
|
296
|
-
| Making `queueSteer`/`flushPendingSteers` private breaks tests | Step 3 explicitly migrates those tests to exercise `Agent.steer()` instead. |
|
|
297
|
-
| The conversation viewer's `messages` accessor returns `readonly unknown[]` which loses typing | The viewer already casts messages to `{ role: string; [key: string]: unknown }` — the cast is unchanged, and the viewer's rendering is unaffected. |
|
|
298
|
-
| Narrowing `onSessionCreated` could break the `agent-manager.ts` relay's non-null assertion | The relay checks `options.observer?.onSessionCreated` before wiring — the narrowed signature is structurally compatible; the only change is dropping the second parameter. |
|
|
299
|
-
| Large number of test files to update | Steps 3–6 group migrations by concern (steer, stats/conversation/readiness, viewer, observer) so each commit is self-contained and reviewable. |
|
|
300
|
-
|
|
301
|
-
## Open Questions
|
|
302
|
-
|
|
303
|
-
- None — the issue's proposed methods are unambiguous and the acceptance criteria are clear.
|
|
304
|
-
The only design addition beyond the issue is narrowing `onSessionCreated` and adding `messages`/`subscribeToUpdates` for the conversation viewer, both of which are required to satisfy the "no production module outside lifecycle/ references AgentSession" acceptance criterion.
|
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
issue: 280
|
|
3
|
-
issue_title: "Rename the internal Agent class to Subagent"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Rename the internal `Agent` class to `Subagent`
|
|
7
|
-
|
|
8
|
-
## Problem Statement
|
|
9
|
-
|
|
10
|
-
The internal lifecycle class `Agent` (`src/lifecycle/agent.ts`) models a single spawned subagent, but the bare name `Agent` collides with two unrelated concepts in the same code: the parent Pi agent that invokes our tooling, and the SDK's `AgentSession` that each subagent wraps.
|
|
11
|
-
The public API already standardized on the `Subagent*` family (`SubagentsService`, `SubagentRecord`, `SubagentStatus`, `SubagentType`, and — after [#265] — `SubagentSession` / `createSubagentSession`).
|
|
12
|
-
The internal lifecycle layer is the lone holdout still using bare `Agent*`.
|
|
13
|
-
Renaming the subagent-instance cluster closes that inconsistency and removes the parent/child/SDK ambiguity.
|
|
14
|
-
|
|
15
|
-
## Goals
|
|
16
|
-
|
|
17
|
-
- Rename the subagent-instance cluster in `src/lifecycle/` to the `Subagent*` family: `Agent` → `Subagent`, `AgentManager` → `SubagentManager`, `AgentInit` → `SubagentInit`, `AgentLifecycleObserver` → `SubagentLifecycleObserver`, `AgentManagerObserver` → `SubagentManagerObserver`, `AgentManagerOptions` → `SubagentManagerOptions`, `AgentObserverOptions` → `SubagentObserverOptions`, `AgentManagerLike` → `SubagentManagerLike`.
|
|
18
|
-
- Consolidate the duplicate `AgentStatus` union into the existing public `SubagentStatus`, deleting the duplicate and re-pointing `WorkspaceDisposeOutcome.status`.
|
|
19
|
-
- Rename the lifecycle module files to match their primary export: `agent.ts` → `subagent.ts`, `agent-manager.ts` → `subagent-manager.ts`, plus the matching test files and the `make-agent.ts` test helper.
|
|
20
|
-
- Extend the rename to adjacent identifiers in the same cluster for full consistency: the `subscribeAgentObserver` function → `subscribeSubagentObserver`, the `SubagentManagerObserver` methods `onAgent*` → `onSubagent*`, and the `createTestAgent` helper → `createTestSubagent`.
|
|
21
|
-
- Update residual bare `Agent` / `AgentManager` references in lifecycle comments, JSDoc, and error strings — the acceptance grep matches these, not just symbols.
|
|
22
|
-
- Update `docs/architecture/architecture.md` to the new names.
|
|
23
|
-
- This is internal-only and non-breaking — the exported surface is unchanged apart from `WorkspaceDisposeOutcome.status` reading `SubagentStatus` (an identical union), so commits use `refactor:`, never `feat!:`.
|
|
24
|
-
|
|
25
|
-
## Non-Goals
|
|
26
|
-
|
|
27
|
-
- The agent-type/config axis stays untouched: `AgentConfig`, `AgentType`, `AgentTypeRegistry`, `AgentConfigLookup`, `AgentInvocation`, `AgentPromptConfig`, `AgentCategories`.
|
|
28
|
-
- The UI/tool surface stays untouched: `AgentTool` (+ `AgentTool*` variants), `AgentSpawnConfig`, `AgentWidget`, `AgentsMenuHandler`, `AgentActivityTracker`, `AgentDetails`, `AgentCreationWizard`, `AgentConfigEditor`, `AgentFileOps`.
|
|
29
|
-
- SDK types stay untouched: `AgentSession`, `AgentSessionEvent`.
|
|
30
|
-
- Internal field/method names that do not contain the bare `Agent` word — `listAgents`, `getRecord`, the `agents` map, and `record:` parameters — are left as-is; they are not bare-`Agent` symbols and the acceptance grep does not flag them.
|
|
31
|
-
- No behavior changes: this is a pure rename plus a structurally no-op type consolidation.
|
|
32
|
-
|
|
33
|
-
## Background
|
|
34
|
-
|
|
35
|
-
Relevant modules (Lifecycle domain unless noted):
|
|
36
|
-
|
|
37
|
-
- `src/lifecycle/agent.ts` — defines `Agent`, `AgentInit`, `AgentLifecycleObserver`, and the duplicate `AgentStatus` union; owns the full execution lifecycle (`run`, `resume`, `abort`, `steer`, status transitions, workspace disposal).
|
|
38
|
-
Contains bare-`Agent` JSDoc and two error strings (`"Agent not configured for execution …"`, `"Agent not configured for resume …"`).
|
|
39
|
-
- `src/lifecycle/agent-manager.ts` — defines `AgentManager`, `AgentManagerObserver` (methods `onAgentStarted` / `onAgentCompleted` / `onAgentCompacted` / `onAgentCreated`), `AgentManagerOptions`, and `AgentSpawnConfig` (out of scope).
|
|
40
|
-
- `src/lifecycle/workspace.ts` — `WorkspaceDisposeOutcome.status` is typed as the internal `AgentStatus`, imported from `#src/lifecycle/agent`.
|
|
41
|
-
- `src/observation/record-observer.ts` — defines `AgentObserverOptions` and the `subscribeAgentObserver` function.
|
|
42
|
-
- `src/service/service.ts` — defines the public `SubagentStatus` union (verbatim duplicate of `AgentStatus`) and re-exports `LifetimeUsage`, `Workspace`, and the four workspace collaborator types from the lifecycle layer.
|
|
43
|
-
- `src/service/service-adapter.ts` — defines the `AgentManagerLike` test seam.
|
|
44
|
-
- `src/types.ts` — barrel that re-exports `Agent` from `#src/lifecycle/agent`; most consumers import `Agent` via this barrel.
|
|
45
|
-
- `test/helpers/make-agent.ts` — exports `createTestAgent`, imported by ~16 test files.
|
|
46
|
-
|
|
47
|
-
Blast radius is mechanical but wide (~360 occurrences, dominated by the `Agent` class via the `types.ts` barrel).
|
|
48
|
-
`typescript` + `tsserver` are available, so each rename is a scope-aware language-service pass verified by `pnpm run check`; the occurrence count does not drive scope.
|
|
49
|
-
|
|
50
|
-
Constraints from AGENTS.md and skills that apply:
|
|
51
|
-
|
|
52
|
-
- Within a package, import siblings via `#src/` / `#test/` aliases (eslint enforces this) — the file moves must preserve alias imports, not introduce relative paths.
|
|
53
|
-
- After a barrel rename, verify at least one consumer still imports the renamed symbol from the barrel — many consumers import `Subagent` from `#src/types`, so this holds.
|
|
54
|
-
- The public `dist/public.d.ts` bundle is rolled from `src/service/service.ts`; run `pnpm run verify:public-types` after touching the public surface or the status consolidation.
|
|
55
|
-
- Load the `mermaid` skill before editing the architecture doc's class/sequence diagrams.
|
|
56
|
-
|
|
57
|
-
## Design Overview
|
|
58
|
-
|
|
59
|
-
### Status consolidation and the layering constraint
|
|
60
|
-
|
|
61
|
-
`AgentStatus` (in `agent.ts`) and `SubagentStatus` (in `service.ts`) are identical seven-member unions (`queued | running | completed | steered | aborted | stopped | error`).
|
|
62
|
-
The issue asks `WorkspaceDisposeOutcome.status` to point at the public `SubagentStatus`.
|
|
63
|
-
|
|
64
|
-
A naive fix — importing `SubagentStatus` from `service.ts` into `workspace.ts` — would create a circular dependency: `service.ts` already imports the workspace collaborator types (`WorkspaceDisposeOutcome`, …) from `workspace.ts`, so `workspace.ts → service.ts` reverses an existing arrow.
|
|
65
|
-
The correct single home is the lifecycle layer, mirroring how `service.ts` already re-exports `LifetimeUsage` from `#src/lifecycle/usage` and the workspace types from `#src/lifecycle/workspace`:
|
|
66
|
-
|
|
67
|
-
- Keep the union defined in the lifecycle layer (in the renamed `subagent.ts`), renamed `AgentStatus` → `SubagentStatus`.
|
|
68
|
-
- `service.ts` deletes its local definition and adds `export type { SubagentStatus } from "#src/lifecycle/subagent";` alongside its existing re-exports.
|
|
69
|
-
- `workspace.ts` imports `SubagentStatus` from `#src/lifecycle/subagent` (it already imports `AgentStatus` from the same module today — only the symbol name and, after the file move, the path change).
|
|
70
|
-
|
|
71
|
-
The `subagent ↔ workspace` relationship is type-only and already exists (`subagent.ts` imports `Workspace` / `WorkspaceProvider` from `workspace.ts`; `workspace.ts` imports the status union from `subagent.ts`), so no new runtime cycle is introduced — type-only imports are erased.
|
|
72
|
-
|
|
73
|
-
`rollup-plugin-dts` inlines `#src/*` types, so `dist/public.d.ts` still emits the same `SubagentStatus` union literal — structurally a no-op for consumers, confirmed by `verify:public-types`.
|
|
74
|
-
|
|
75
|
-
```typescript
|
|
76
|
-
// src/lifecycle/subagent.ts (renamed from agent.ts)
|
|
77
|
-
export type SubagentStatus =
|
|
78
|
-
| "queued" | "running" | "completed" | "steered"
|
|
79
|
-
| "aborted" | "stopped" | "error";
|
|
80
|
-
|
|
81
|
-
// src/service/service.ts — delete local def, re-export instead
|
|
82
|
-
export type { SubagentStatus } from "#src/lifecycle/subagent";
|
|
83
|
-
|
|
84
|
-
// src/lifecycle/workspace.ts
|
|
85
|
-
import type { SubagentStatus } from "#src/lifecycle/subagent";
|
|
86
|
-
export interface WorkspaceDisposeOutcome {
|
|
87
|
-
status: SubagentStatus;
|
|
88
|
-
description: string;
|
|
89
|
-
}
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
### Rename mechanics
|
|
93
|
-
|
|
94
|
-
Each symbol rename is an atomic, scope-aware language-service operation (the API behind LSP "Rename Symbol"); after each, `pnpm run check` verifies the tree compiles.
|
|
95
|
-
Because a rename updates every reference in one pass and leaves the build green, each logical rename is its own commit with the repository in a valid state — no lift-and-shift staging is required (a rename is not a type replacement; old and new names never coexist).
|
|
96
|
-
|
|
97
|
-
Symbol renames do not touch comments, JSDoc, or string literals.
|
|
98
|
-
There are 26 bare `Agent` and 4 bare `AgentManager` word-occurrences in `src/lifecycle/` comments/strings (e.g. the two `"Agent not configured …"` error messages and cross-file JSDoc in `turn-limits.ts`, `create-subagent-session.ts`, `subagent-session.ts`).
|
|
99
|
-
The acceptance criterion greps `src/lifecycle/` for bare `Agent` / `AgentManager`, so each rename step must also sweep residual comment/string occurrences.
|
|
100
|
-
Compound names (`AgentSession`, `AgentInvocation`, `AgentTypeRegistry`) are not bare-word matches and stay.
|
|
101
|
-
|
|
102
|
-
### Full-consistency adjacent identifiers
|
|
103
|
-
|
|
104
|
-
Per the scope decision, the rename extends to the rest of the cluster's naming so no `Agent`-as-subagent identifier survives:
|
|
105
|
-
|
|
106
|
-
- `src/observation/record-observer.ts`: `subscribeAgentObserver` → `subscribeSubagentObserver`, `AgentObserverOptions` → `SubagentObserverOptions`.
|
|
107
|
-
- `src/lifecycle/subagent-manager.ts`: `SubagentManagerObserver` methods `onAgentStarted` / `onAgentCompleted` / `onAgentCompacted` / `onAgentCreated` → `onSubagentStarted` / `onSubagentCompleted` / `onSubagentCompacted` / `onSubagentCreated` (8 + 11 + 6 + 14 call sites across `src/` and `test/`, all updated by the language-service rename).
|
|
108
|
-
- `test/helpers/make-agent.ts`: `createTestAgent` → `createTestSubagent`, file → `make-subagent.ts` (~16 importers, including `make-deps.ts` and `ui-stubs.ts`).
|
|
109
|
-
|
|
110
|
-
## Module-Level Changes
|
|
111
|
-
|
|
112
|
-
Renamed files (git move, preserving `#src/` / `#test/` alias imports):
|
|
113
|
-
|
|
114
|
-
- `src/lifecycle/agent.ts` → `src/lifecycle/subagent.ts`
|
|
115
|
-
- `src/lifecycle/agent-manager.ts` → `src/lifecycle/subagent-manager.ts`
|
|
116
|
-
- `test/lifecycle/agent.test.ts` → `test/lifecycle/subagent.test.ts`
|
|
117
|
-
- `test/lifecycle/agent-manager.test.ts` → `test/lifecycle/subagent-manager.test.ts`
|
|
118
|
-
- `test/helpers/make-agent.ts` → `test/helpers/make-subagent.ts`
|
|
119
|
-
- `test/helpers/make-agent.test.ts` → `test/helpers/make-subagent.test.ts`
|
|
120
|
-
|
|
121
|
-
Changed (symbols, members, imports, comments/strings):
|
|
122
|
-
|
|
123
|
-
- `src/lifecycle/subagent.ts` — `Agent` → `Subagent`, `AgentInit` → `SubagentInit`, `AgentLifecycleObserver` → `SubagentLifecycleObserver`, `AgentStatus` → `SubagentStatus` (kept here as the single home); update JSDoc and the two error strings.
|
|
124
|
-
- `src/lifecycle/subagent-manager.ts` — `AgentManager` → `SubagentManager`, `AgentManagerObserver` → `SubagentManagerObserver` (+ `onAgent*` methods → `onSubagent*`), `AgentManagerOptions` → `SubagentManagerOptions`; `AgentSpawnConfig` unchanged; update header comment.
|
|
125
|
-
- `src/lifecycle/workspace.ts` — import `SubagentStatus` from `#src/lifecycle/subagent`; `WorkspaceDisposeOutcome.status` retyped.
|
|
126
|
-
- `src/service/service.ts` — delete local `SubagentStatus` definition; add `export type { SubagentStatus } from "#src/lifecycle/subagent";`.
|
|
127
|
-
- `src/service/service-adapter.ts` — `AgentManagerLike` → `SubagentManagerLike`; update header comment referencing `AgentManager`.
|
|
128
|
-
- `src/observation/record-observer.ts` — `subscribeAgentObserver` → `subscribeSubagentObserver`, `AgentObserverOptions` → `SubagentObserverOptions`; update header comment.
|
|
129
|
-
- `src/types.ts` — barrel re-export `export { Agent } from "#src/lifecycle/agent";` → `export { Subagent } from "#src/lifecycle/subagent";`.
|
|
130
|
-
- All consumers of the renamed symbols across `src/` and `test/` (tools, UI, runtime, `index.ts`, session, observation, and their tests) — updated transitively by each language-service rename.
|
|
131
|
-
Out-of-scope `Agent*` symbols in these files are untouched.
|
|
132
|
-
- `test/helpers/make-subagent.ts`, `make-deps.ts`, `ui-stubs.ts`, and ~16 test importers — `createTestAgent` → `createTestSubagent` and updated import paths.
|
|
133
|
-
- `docs/architecture/architecture.md` — file-listing entries (`agent.ts`, `agent-manager.ts`), class/sequence Mermaid diagrams, the type-complexity table row (`AgentInit` → `SubagentInit`, module `agent` → `subagent`), and current-state prose naming the renamed cluster.
|
|
134
|
-
Out-of-scope `Agent*` names (`AgentTool`, `AgentSession`, `AgentTypeRegistry`, …) and historical phase narrative stay as written.
|
|
135
|
-
|
|
136
|
-
No exports are removed from the public surface; the barrel rename swaps one name for another with many live consumers.
|
|
137
|
-
Also swept for the `package-pi-subagents` SKILL.md, which documents internals (`AgentManager`, `Agent`, `make-agent`): update its dependency-flow sketch and module table to the new names.
|
|
138
|
-
|
|
139
|
-
## Test Impact Analysis
|
|
140
|
-
|
|
141
|
-
This is a pure rename plus a no-op type consolidation, so the extraction-style test questions resolve simply:
|
|
142
|
-
|
|
143
|
-
1. New tests enabled: none — no new seams or behavior are introduced.
|
|
144
|
-
2. Tests made redundant: none — no test is duplicated or subsumed.
|
|
145
|
-
3. Tests that must stay as-is (renamed/retargeted only): all of them.
|
|
146
|
-
`test/lifecycle/subagent.test.ts`, `subagent-manager.test.ts`, `record-observer.test.ts`, `service-adapter.test.ts`, and every `createTestSubagent` consumer continue to exercise the same behavior under the new names.
|
|
147
|
-
The status consolidation leaves `WorkspaceDisposeOutcome` behavior identical, so workspace/service tests are unchanged beyond the symbol name.
|
|
148
|
-
|
|
149
|
-
## TDD Order
|
|
150
|
-
|
|
151
|
-
This is a refactor with no red phase; each step is a green checkpoint verified by `pnpm run check` && `pnpm -r run test` (and `verify:public-types` where the public surface is touched) before committing.
|
|
152
|
-
Steps are independent renames ordered smallest-blast-first where practical; any order keeps the tree green.
|
|
153
|
-
|
|
154
|
-
1. Consolidate the status union.
|
|
155
|
-
In `agent.ts` rename `AgentStatus` → `SubagentStatus` and keep the definition there; delete the duplicate in `service.ts` and re-export from the lifecycle module; retype `workspace.ts`.
|
|
156
|
-
Run `pnpm run check`, tests, and `pnpm run verify:public-types` to confirm the bundle is unchanged.
|
|
157
|
-
Commit: `refactor: consolidate AgentStatus into public SubagentStatus (#280)`.
|
|
158
|
-
2. Rename the `Agent` class cluster.
|
|
159
|
-
`Agent` → `Subagent`, `AgentInit` → `SubagentInit`, `AgentLifecycleObserver` → `SubagentLifecycleObserver`; git-move `agent.ts` → `subagent.ts` and `test/lifecycle/agent.test.ts` → `subagent.test.ts`; update the `types.ts` barrel re-export and the `workspace.ts` / `service.ts` import paths to `#src/lifecycle/subagent`; sweep residual bare-`Agent` JSDoc and the two error strings in `subagent.ts`.
|
|
160
|
-
Commit: `refactor: rename Agent class to Subagent (#280)`.
|
|
161
|
-
3. Rename the manager cluster.
|
|
162
|
-
`AgentManager` → `SubagentManager`, `AgentManagerObserver` → `SubagentManagerObserver` (+ `onAgent*` methods → `onSubagent*`), `AgentManagerOptions` → `SubagentManagerOptions`; git-move `agent-manager.ts` → `subagent-manager.ts` and its test file; sweep residual bare-`AgentManager` comments.
|
|
163
|
-
`AgentSpawnConfig` left untouched.
|
|
164
|
-
Commit: `refactor: rename AgentManager cluster to SubagentManager (#280)`.
|
|
165
|
-
4. Rename the observation seam.
|
|
166
|
-
`subscribeAgentObserver` → `subscribeSubagentObserver`, `AgentObserverOptions` → `SubagentObserverOptions` in `record-observer.ts`; update its test and header comment.
|
|
167
|
-
Commit: `refactor: rename subscribeAgentObserver to subscribeSubagentObserver (#280)`.
|
|
168
|
-
5. Rename the adapter seam.
|
|
169
|
-
`AgentManagerLike` → `SubagentManagerLike` in `service-adapter.ts`; update its test and header comment.
|
|
170
|
-
Commit: `refactor: rename AgentManagerLike to SubagentManagerLike (#280)`.
|
|
171
|
-
6. Rename the test helper.
|
|
172
|
-
`createTestAgent` → `createTestSubagent`; git-move `make-agent.ts` → `make-subagent.ts` and `make-agent.test.ts` → `make-subagent.test.ts`; update all importers and `#test/helpers/make-agent` paths.
|
|
173
|
-
Commit: `test: rename createTestAgent to createTestSubagent (#280)`.
|
|
174
|
-
7. Update docs.
|
|
175
|
-
Architecture doc current-state references (file listing, Mermaid diagrams, complexity table, prose) and the `package-pi-subagents` SKILL.md internals; load the `mermaid` skill before editing diagrams.
|
|
176
|
-
Final verification: `pnpm run check`, `pnpm run lint`, `pnpm -r run test`, `pnpm fallow dead-code`, `pnpm run verify:public-types`, and `grep -rnE '\bAgent(Manager|Init)?\b' src/lifecycle/` returns no bare in-scope matches.
|
|
177
|
-
Commit: `docs: update architecture and skill docs for Subagent rename (#280)`.
|
|
178
|
-
|
|
179
|
-
## Risks and Mitigations
|
|
180
|
-
|
|
181
|
-
- Risk: a symbol rename misses string literals or comments, leaving bare `Agent` that the acceptance grep flags.
|
|
182
|
-
Mitigation: each rename step explicitly sweeps comments/strings; the final grep gate in step 7 is the backstop.
|
|
183
|
-
- Risk: pointing `workspace.ts` at the public `SubagentStatus` introduces a `lifecycle → service` cycle.
|
|
184
|
-
Mitigation: keep the union's home in the lifecycle layer (`subagent.ts`) and re-export from `service.ts`, mirroring the existing `LifetimeUsage` / workspace re-export pattern — no new arrow.
|
|
185
|
-
- Risk: the public type bundle changes shape.
|
|
186
|
-
Mitigation: `verify:public-types` after step 1 and step 7; the union is identical, so the bundle differs only in provenance, not content.
|
|
187
|
-
- Risk: a file move accidentally rewrites `#src/` alias imports to relative paths.
|
|
188
|
-
Mitigation: use `git mv` and rely on the language service for import updates; eslint's no-relative-sibling rule catches regressions during `pnpm run lint`.
|
|
189
|
-
- Risk: over-reach into out-of-scope `Agent*` names.
|
|
190
|
-
Mitigation: the rename is symbol-scoped (not text find-replace); the Non-Goals list enumerates the protected names, and the acceptance grep targets only bare `Agent` / `AgentManager` / `AgentInit` / `Agent*Observer`.
|
|
191
|
-
|
|
192
|
-
## Open Questions
|
|
193
|
-
|
|
194
|
-
- Whether to later lowercase incidental prose uses of "Agent" (meaning subagent) in the architecture doc's event tables and history sections — deferred; this plan updates symbol/file names and current-state references, leaving historical narrative as written.
|
|
195
|
-
- Whether `listAgents` / `getRecord` / the `agents` map deserve a follow-up naming pass — deferred; they are not bare-`Agent` symbols and fall outside the approved scope.
|
|
196
|
-
|
|
197
|
-
[#265]: https://github.com/gotgenes/pi-packages/issues/265
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
issue: 360
|
|
3
|
-
issue_title: "fix(pi-subagents): custom agents default to replace mode instead of append"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Custom agents default to append prompt mode
|
|
7
|
-
|
|
8
|
-
## Problem Statement
|
|
9
|
-
|
|
10
|
-
Custom agents loaded from `.pi/agents/*.md` (and the global agents directory) default to `replace` prompt mode when no `prompt_mode` frontmatter key is present, while built-in agents default to `append`.
|
|
11
|
-
This asymmetry surprises users: a custom agent with no explicit `prompt_mode` silently drops the parent system prompt (AGENTS.md, skills, project conventions) and instead shows the bare replace-mode header. @jeffutter reported this in [#180 (comment)](https://github.com/gotgenes/pi-packages/issues/180#issuecomment-4644369646) — their `researcher` agent rendered `"You are a pi coding agent sub-agent."` instead of inheriting the parent prompt.
|
|
12
|
-
|
|
13
|
-
The root cause is the ternary in `src/config/custom-agents.ts` line 65:
|
|
14
|
-
|
|
15
|
-
```typescript
|
|
16
|
-
promptMode: fm.prompt_mode === "append" ? "append" : "replace",
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
Any value other than the literal `"append"` — including `undefined` (key omitted) — falls through to `replace`.
|
|
20
|
-
|
|
21
|
-
## Goals
|
|
22
|
-
|
|
23
|
-
- Custom agents without an explicit `prompt_mode` frontmatter key default to `append`, matching the built-in default in `agent-types.ts`.
|
|
24
|
-
- Only `prompt_mode: replace` (explicit opt-in) selects replace mode.
|
|
25
|
-
- Update tests and user-facing documentation to reflect the new default.
|
|
26
|
-
|
|
27
|
-
This is a **breaking change**: any existing `.pi/agents/*.md` that omits `prompt_mode` flips from `replace` to `append` on upgrade, so those agents begin inheriting the parent system prompt (AGENTS.md / CLAUDE.md / skills) where they previously did not.
|
|
28
|
-
The behavior change is triggered purely by upgrading, with no config edit — it warrants a `fix!:` commit and a `BREAKING CHANGE:` footer so release-please cuts a major version.
|
|
29
|
-
Users who relied on the old implicit-`replace` behavior must add `prompt_mode: replace` explicitly to restore it.
|
|
30
|
-
|
|
31
|
-
## Non-Goals
|
|
32
|
-
|
|
33
|
-
- No change to built-in agents (`default-agents.ts`): `Explore` and `Plan` keep their explicit `promptMode: "replace"`, `general-purpose` keeps `append`.
|
|
34
|
-
- No change to the prompt-assembly logic in `src/session/prompts.ts` — only the default a custom agent resolves to changes.
|
|
35
|
-
- No change to other frontmatter field defaults or parsers.
|
|
36
|
-
|
|
37
|
-
## Background
|
|
38
|
-
|
|
39
|
-
- `src/config/custom-agents.ts` — `loadFromDir` parses each `.md` file's frontmatter into an `AgentConfig`.
|
|
40
|
-
Line 65 is the only place a custom agent's `promptMode` is decided.
|
|
41
|
-
- `src/config/agent-types.ts:118` — the built-in absolute-fallback config uses `promptMode: "append"`.
|
|
42
|
-
- `src/session/prompts.ts:36` — `buildAgentPrompt` branches on `config.promptMode === "append"`; append mode threads the parent system prompt (AGENTS.md / CLAUDE.md) into the child, replace mode does not.
|
|
43
|
-
- The field-parser convention documented at the top of the parser section of `custom-agents.ts` is "omitted → default, none/empty → nothing, value → exact".
|
|
44
|
-
Today `prompt_mode` violates the spirit of "omitted → default" by mapping omitted to `replace` rather than the system default `append`.
|
|
45
|
-
This fix aligns it.
|
|
46
|
-
|
|
47
|
-
Constraint from AGENTS.md: this is the `pi-subagents` package — Biome handles formatting, the upstream vitest suite is a regression canary, and all tests must pass before publishing.
|
|
48
|
-
|
|
49
|
-
## Design Overview
|
|
50
|
-
|
|
51
|
-
Flip the ternary so `replace` requires an explicit opt-in and everything else (including omitted) defaults to `append`:
|
|
52
|
-
|
|
53
|
-
```typescript
|
|
54
|
-
promptMode: fm.prompt_mode === "replace" ? "replace" : "append",
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
Decision table for the resolved `promptMode`:
|
|
58
|
-
|
|
59
|
-
| `prompt_mode` frontmatter value | Before | After |
|
|
60
|
-
| ------------------------------- | ------- | ------- |
|
|
61
|
-
| omitted / `undefined` | replace | append |
|
|
62
|
-
| `replace` | replace | replace |
|
|
63
|
-
| `append` | append | append |
|
|
64
|
-
| unknown (e.g. `merge`) | replace | append |
|
|
65
|
-
|
|
66
|
-
Unknown values now resolve to `append` rather than `replace`.
|
|
67
|
-
This is the safer fallback: an append-mode agent inherits the parent prompt (a superset), so a typo degrades to "inherits everything" rather than "silently drops project context".
|
|
68
|
-
|
|
69
|
-
No type shape changes — `promptMode` remains `"replace" | "append"` (`src/types.ts`).
|
|
70
|
-
|
|
71
|
-
## Module-Level Changes
|
|
72
|
-
|
|
73
|
-
- `src/config/custom-agents.ts` (line 65) — flip the ternary to `fm.prompt_mode === "replace" ? "replace" : "append"`.
|
|
74
|
-
- `src/ui/agent-creation-wizard.ts` (line 106) — update the inline frontmatter doc comment: `Default: replace` → `Default: append` for `prompt_mode`.
|
|
75
|
-
The surrounding guidelines (lines 117–118) already describe both modes correctly and need no change.
|
|
76
|
-
- `README.md` (line 187) — change the `prompt_mode` default column from `` `replace` `` to `` `append` ``.
|
|
77
|
-
Keep the cell's behavioral description of `replace`/`append` unchanged.
|
|
78
|
-
- `test/config/custom-agents.test.ts` — update the two tests that assert the old default (see TDD Order).
|
|
79
|
-
|
|
80
|
-
No architecture-doc references to the default value were found (`docs/architecture/` describes module layout, not field defaults). `CHANGELOG.md` is owned by release-please and is not edited.
|
|
81
|
-
|
|
82
|
-
## Test Impact Analysis
|
|
83
|
-
|
|
84
|
-
This is a behavior fix, not an extraction, so no new test layers are enabled and no tests become redundant.
|
|
85
|
-
Existing tests in `test/config/custom-agents.test.ts` directly exercise the changed line and must be updated to assert the new default:
|
|
86
|
-
|
|
87
|
-
1. `"uses sensible defaults when frontmatter is empty"` — empty frontmatter currently asserts `promptMode` is `"replace"`; must become `"append"`.
|
|
88
|
-
2. `"defaults unknown prompt_mode to replace"` — feeds `prompt_mode: merge` and asserts `"replace"`; must be renamed to `"defaults unknown prompt_mode to append"` and assert `"append"`.
|
|
89
|
-
3. `"loads a basic agent with all frontmatter fields"` (explicit `prompt_mode: replace`) and `"handles prompt_mode: append"` — both pass an explicit value and stay as-is; they pin the explicit-opt-in behavior.
|
|
90
|
-
4. `"uses sensible defaults when no frontmatter at all"` (the `bare` agent) does not currently assert `promptMode` — add an assertion that it resolves to `"append"` to lock the no-frontmatter path.
|
|
91
|
-
|
|
92
|
-
## TDD Order
|
|
93
|
-
|
|
94
|
-
1. Red → Green: update default-mode tests in `test/config/custom-agents.test.ts`.
|
|
95
|
-
- Change the empty-frontmatter test to expect `promptMode` `"append"`.
|
|
96
|
-
- Rename the unknown-mode test to `"defaults unknown prompt_mode to append"` and expect `"append"`.
|
|
97
|
-
- Add a `promptMode` assertion (`"append"`) to the no-frontmatter (`bare`) test.
|
|
98
|
-
- These fail against the current line 65, then pass after the source fix.
|
|
99
|
-
- Apply the one-line fix in `src/config/custom-agents.ts` in the same cycle (the test file and source are coupled — the type checker and assertions move together).
|
|
100
|
-
- Commit (breaking — include the footer):
|
|
101
|
-
|
|
102
|
-
```text
|
|
103
|
-
fix(pi-subagents)!: default custom agents to append prompt mode (#360)
|
|
104
|
-
|
|
105
|
-
BREAKING CHANGE: Custom agents in .pi/agents/*.md that omit the
|
|
106
|
-
prompt_mode frontmatter key now default to append instead of replace,
|
|
107
|
-
so they inherit the parent system prompt (AGENTS.md / CLAUDE.md /
|
|
108
|
-
skills). Add `prompt_mode: replace` explicitly to restore the previous
|
|
109
|
-
standalone-prompt behavior.
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
2. Docs: update user-facing default documentation.
|
|
113
|
-
- `src/ui/agent-creation-wizard.ts` — `prompt_mode` `Default: replace` → `Default: append`.
|
|
114
|
-
- `README.md` — `prompt_mode` default cell → `` `append` ``.
|
|
115
|
-
- Commit: `docs(pi-subagents): note custom agents default to append prompt mode (#360)`.
|
|
116
|
-
|
|
117
|
-
(Optional: steps 1 and 2 may be combined into a single `fix!:` commit since the doc updates are part of the same behavioral correction; keeping them split keeps the source/test change isolated from prose.
|
|
118
|
-
If combined, the `BREAKING CHANGE:` footer lives on the single commit.)
|
|
119
|
-
|
|
120
|
-
## Risks and Mitigations
|
|
121
|
-
|
|
122
|
-
- Risk: existing users rely on the old implicit-`replace` behavior for custom agents that omit `prompt_mode`.
|
|
123
|
-
Mitigation: append mode is a superset (it inherits the parent prompt plus the agent body); the worst case is an agent that now sees more context than before, not less.
|
|
124
|
-
Users who genuinely want a standalone prompt can add `prompt_mode: replace` explicitly.
|
|
125
|
-
The issue frames the old behavior as a bug, and the maintainer authored it.
|
|
126
|
-
- Risk: the upstream vitest regression canary asserts the old default somewhere.
|
|
127
|
-
Mitigation: `grep` confirms the only default-asserting tests are in `test/config/custom-agents.test.ts`; run `pnpm --filter @gotgenes/pi-subagents run test` to confirm the full suite stays green.
|
|
128
|
-
|
|
129
|
-
## Open Questions
|
|
130
|
-
|
|
131
|
-
None.
|
|
132
|
-
The issue's proposed fix is unambiguous and the change surface is fully enumerated above.
|