@gotgenes/pi-subagents 10.0.1 → 10.2.0
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 +41 -0
- package/docs/architecture/architecture.md +78 -159
- package/docs/architecture/history/phase-14-strip-policy.md +49 -0
- package/docs/plans/0227-evolve-agent-record-into-agent.md +322 -0
- package/docs/plans/0228-async-start-agent-dissolve-run-handle.md +288 -0
- package/docs/retro/0227-evolve-agent-record-into-agent.md +80 -0
- package/docs/retro/0228-async-start-agent-dissolve-run-handle.md +42 -0
- package/docs/retro/0239-collapse-filter-active-tools.md +33 -0
- package/package.json +1 -1
- package/src/lifecycle/agent-manager.ts +70 -207
- package/src/lifecycle/{agent-record.ts → agent.ts} +151 -13
- package/src/lifecycle/execution-state.ts +2 -2
- package/src/observation/notification.ts +8 -8
- package/src/observation/record-observer.ts +7 -7
- package/src/service/service-adapter.ts +8 -8
- package/src/tools/agent-tool.ts +4 -4
- package/src/tools/background-spawner.ts +2 -2
- package/src/tools/foreground-runner.ts +4 -4
- package/src/tools/get-result-tool.ts +2 -2
- package/src/tools/steer-tool.ts +4 -5
- package/src/types.ts +1 -1
- package/src/ui/agent-creation-wizard.ts +2 -2
- package/src/ui/agent-menu.ts +5 -5
- package/src/ui/conversation-viewer.ts +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,47 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [10.2.0](https://github.com/gotgenes/pi-packages/compare/pi-subagents-v10.1.0...pi-subagents-v10.2.0) (2026-05-27)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* **pi-subagents:** add run lifecycle methods to Agent ([2a378f1](https://github.com/gotgenes/pi-packages/commit/2a378f1c82e977bdfee25931ab449757e364d589))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Documentation
|
|
17
|
+
|
|
18
|
+
* **pi-subagents:** update architecture for async startAgent ([941eb10](https://github.com/gotgenes/pi-packages/commit/941eb109e71e4c51d5bb37a2a46ffc12f618d949))
|
|
19
|
+
* plan async startAgent and RunHandle dissolution ([#228](https://github.com/gotgenes/pi-packages/issues/228)) ([647adf8](https://github.com/gotgenes/pi-packages/commit/647adf853fec63ea53afd63bc8204c89a6194bbe))
|
|
20
|
+
* **retro:** add planning stage notes for issue [#228](https://github.com/gotgenes/pi-packages/issues/228) ([8dd9f8a](https://github.com/gotgenes/pi-packages/commit/8dd9f8ab7082c08e424b1b4a9557253af2ce584b))
|
|
21
|
+
* **retro:** add retro notes for issue [#227](https://github.com/gotgenes/pi-packages/issues/227) ([78a4d64](https://github.com/gotgenes/pi-packages/commit/78a4d645f524465c64bf0b6ba1bcca37858e8721))
|
|
22
|
+
* **retro:** add TDD stage notes for issue [#228](https://github.com/gotgenes/pi-packages/issues/228) ([ab497c5](https://github.com/gotgenes/pi-packages/commit/ab497c57723666d0635a0a08f9eecc06576da549))
|
|
23
|
+
|
|
24
|
+
## [10.1.0](https://github.com/gotgenes/pi-packages/compare/pi-subagents-v10.0.1...pi-subagents-v10.1.0) (2026-05-27)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
### Features
|
|
28
|
+
|
|
29
|
+
* **pi-subagents:** add abort() to AgentRecord ([bbc9dc7](https://github.com/gotgenes/pi-packages/commit/bbc9dc779d2ff845680f6de34d0ef33c10cdf124))
|
|
30
|
+
* **pi-subagents:** add setupWorktree() to AgentRecord ([1786fdb](https://github.com/gotgenes/pi-packages/commit/1786fdb939d3e858d6453b71a43b9fb3c3346a88))
|
|
31
|
+
* **pi-subagents:** add steer buffering to AgentRecord ([a22d8c7](https://github.com/gotgenes/pi-packages/commit/a22d8c77e8074e1fe9f396305267380d9f3558b3))
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
### Bug Fixes
|
|
35
|
+
|
|
36
|
+
* **pi-subagents:** remove unused AgentInit/AgentStatus re-exports from types.ts ([6789cb7](https://github.com/gotgenes/pi-packages/commit/6789cb72e26eefd54da4ff6ee5dd847c4fa78385))
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
### Documentation
|
|
40
|
+
|
|
41
|
+
* **pi-subagents:** archive Phase 14, advance to Phase 15 ([a8147fb](https://github.com/gotgenes/pi-packages/commit/a8147fb3f6be9af6d73089bbb42b40080e8e04a7))
|
|
42
|
+
* **pi-subagents:** update architecture for Agent rename ([#227](https://github.com/gotgenes/pi-packages/issues/227)) ([f9afc88](https://github.com/gotgenes/pi-packages/commit/f9afc88dcc21213abe453baa032563ff37499ca9))
|
|
43
|
+
* plan evolve AgentRecord into Agent with behavior ([#227](https://github.com/gotgenes/pi-packages/issues/227)) ([d56ff97](https://github.com/gotgenes/pi-packages/commit/d56ff97408063de6467149dc332e35d4078dd137))
|
|
44
|
+
* replace \n with <br/> in Mermaid node labels ([3312a45](https://github.com/gotgenes/pi-packages/commit/3312a4559100cf9ae923f67819653b5a99fceb12))
|
|
45
|
+
* **retro:** add planning stage notes for issue [#227](https://github.com/gotgenes/pi-packages/issues/227) ([ccd9788](https://github.com/gotgenes/pi-packages/commit/ccd9788ac619ae9f0380cb4b0c0b632efb0faf68))
|
|
46
|
+
* **retro:** add retro notes for issue [#239](https://github.com/gotgenes/pi-packages/issues/239) ([58a19a1](https://github.com/gotgenes/pi-packages/commit/58a19a1e65d93c753ef7ba9c24e34d4ebb6f172d))
|
|
47
|
+
* **retro:** add TDD stage notes for issue [#227](https://github.com/gotgenes/pi-packages/issues/227) ([66cf314](https://github.com/gotgenes/pi-packages/commit/66cf314aa4bef736a689d547e75e8bede1757f85))
|
|
48
|
+
|
|
8
49
|
## [10.0.1](https://github.com/gotgenes/pi-packages/compare/pi-subagents-v10.0.0...pi-subagents-v10.0.1) (2026-05-27)
|
|
9
50
|
|
|
10
51
|
|
|
@@ -34,44 +34,44 @@ The extension is organized around six domains, each responsible for one aspect o
|
|
|
34
34
|
flowchart TB
|
|
35
35
|
subgraph config["Config domain"]
|
|
36
36
|
direction TB
|
|
37
|
-
AgentTypeRegistry["AgentTypeRegistry
|
|
38
|
-
DefaultAgents["default-agents
|
|
39
|
-
CustomAgents["custom-agents
|
|
40
|
-
InvocationConfig["invocation-config
|
|
37
|
+
AgentTypeRegistry["AgentTypeRegistry<br/>(registry of agent types)"]
|
|
38
|
+
DefaultAgents["default-agents<br/>(built-in types)"]
|
|
39
|
+
CustomAgents["custom-agents<br/>(user .md files)"]
|
|
40
|
+
InvocationConfig["invocation-config<br/>(per-call merge)"]
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
subgraph session["Session domain"]
|
|
44
44
|
direction TB
|
|
45
|
-
SessionConfig["assembleSessionConfig
|
|
46
|
-
Prompts["prompts
|
|
47
|
-
Context["context
|
|
48
|
-
SafeFs["safe-fs
|
|
49
|
-
SkillLoader["skill-loader
|
|
50
|
-
Env["env
|
|
51
|
-
ModelResolver["model-resolver
|
|
45
|
+
SessionConfig["assembleSessionConfig<br/>(pure assembler)"]
|
|
46
|
+
Prompts["prompts<br/>(system prompt)"]
|
|
47
|
+
Context["context<br/>(parent history)"]
|
|
48
|
+
SafeFs["safe-fs<br/>(symlink/name guards)"]
|
|
49
|
+
SkillLoader["skill-loader<br/>(preload skills)"]
|
|
50
|
+
Env["env<br/>(git/platform)"]
|
|
51
|
+
ModelResolver["model-resolver<br/>(fuzzy match)"]
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
subgraph lifecycle["Lifecycle domain"]
|
|
55
55
|
direction TB
|
|
56
|
-
AgentManager["AgentManager
|
|
57
|
-
AgentRunner["agent-runner
|
|
58
|
-
|
|
59
|
-
ParentSnapshot["ParentSnapshot
|
|
60
|
-
Worktree["worktree
|
|
56
|
+
AgentManager["AgentManager<br/>(spawn, queue, abort)"]
|
|
57
|
+
AgentRunner["agent-runner<br/>(session, turns, results)"]
|
|
58
|
+
Agent["Agent<br/>(status, behavior: abort/steer/worktree/run lifecycle)"]
|
|
59
|
+
ParentSnapshot["ParentSnapshot<br/>(frozen parent state)"]
|
|
60
|
+
Worktree["worktree<br/>(git isolation)"]
|
|
61
61
|
end
|
|
62
62
|
|
|
63
63
|
subgraph observation["Observation domain"]
|
|
64
64
|
direction TB
|
|
65
|
-
RecordObserver["record-observer
|
|
66
|
-
Notification["notification
|
|
67
|
-
UIObserver["ui-observer
|
|
65
|
+
RecordObserver["record-observer<br/>(stats via events)"]
|
|
66
|
+
Notification["notification<br/>(completion nudges)"]
|
|
67
|
+
UIObserver["ui-observer<br/>(streaming state)"]
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
subgraph tools["Tools domain"]
|
|
71
71
|
direction TB
|
|
72
|
-
AgentTool["subagent tool
|
|
73
|
-
ResultRenderer["result-renderer
|
|
74
|
-
SpawnConfig["spawn-config
|
|
72
|
+
AgentTool["subagent tool<br/>(dispatch)"]
|
|
73
|
+
ResultRenderer["result-renderer<br/>(pure rendering)"]
|
|
74
|
+
SpawnConfig["spawn-config<br/>(resolve params)"]
|
|
75
75
|
FgRunner["foreground-runner"]
|
|
76
76
|
BgSpawner["background-spawner"]
|
|
77
77
|
GetResult["get_subagent_result"]
|
|
@@ -80,9 +80,9 @@ flowchart TB
|
|
|
80
80
|
|
|
81
81
|
subgraph ui["UI domain"]
|
|
82
82
|
direction TB
|
|
83
|
-
Widget["agent-widget
|
|
84
|
-
ConvViewer["conversation-viewer
|
|
85
|
-
Menu["agent-menu
|
|
83
|
+
Widget["agent-widget<br/>(live status)"]
|
|
84
|
+
ConvViewer["conversation-viewer<br/>(session overlay)"]
|
|
85
|
+
Menu["agent-menu<br/>(slash command)"]
|
|
86
86
|
end
|
|
87
87
|
|
|
88
88
|
AgentTool --> AgentManager
|
|
@@ -101,11 +101,11 @@ flowchart TB
|
|
|
101
101
|
|
|
102
102
|
```mermaid
|
|
103
103
|
classDiagram
|
|
104
|
-
class
|
|
104
|
+
class Agent {
|
|
105
105
|
+id: string
|
|
106
106
|
+type: SubagentType
|
|
107
107
|
+description: string
|
|
108
|
-
+status:
|
|
108
|
+
+status: AgentStatus
|
|
109
109
|
+result?: string
|
|
110
110
|
+error?: string
|
|
111
111
|
+toolUses: number
|
|
@@ -120,16 +120,25 @@ classDiagram
|
|
|
120
120
|
+markError()
|
|
121
121
|
+markStopped()
|
|
122
122
|
+resetForResume()
|
|
123
|
+
+abort(): boolean
|
|
124
|
+
+queueSteer(message)
|
|
125
|
+
+flushPendingSteers(session)
|
|
126
|
+
+setupWorktree(worktrees, isolation)
|
|
127
|
+
+completeRun(result, worktrees)
|
|
128
|
+
+failRun(err, worktrees)
|
|
129
|
+
+wireSignal(signal, onAbort)
|
|
130
|
+
+attachObserver(unsub)
|
|
131
|
+
+releaseListeners()
|
|
132
|
+
+setOnRunFinished(fn)
|
|
123
133
|
}
|
|
124
134
|
|
|
125
135
|
class AgentManager {
|
|
126
136
|
+spawn(snapshot, type, prompt, config)
|
|
127
137
|
+spawnAndWait(snapshot, type, prompt, config)
|
|
128
138
|
+resume(id, snapshot, exec)
|
|
129
|
-
+getRecord(id):
|
|
130
|
-
+listAgents():
|
|
139
|
+
+getRecord(id): Agent
|
|
140
|
+
+listAgents(): Agent[]
|
|
131
141
|
+abort(id)
|
|
132
|
-
+queueSteer(id, message)
|
|
133
142
|
}
|
|
134
143
|
|
|
135
144
|
class AgentTypeRegistry {
|
|
@@ -157,7 +166,7 @@ classDiagram
|
|
|
157
166
|
+hasRunning(): boolean
|
|
158
167
|
}
|
|
159
168
|
|
|
160
|
-
AgentManager -->
|
|
169
|
+
AgentManager --> Agent : creates/manages
|
|
161
170
|
AgentManager --> ParentSnapshot : receives at spawn
|
|
162
171
|
SubagentsService --> AgentManager : wraps via adapter
|
|
163
172
|
AgentManager --> AgentTypeRegistry : resolves types
|
|
@@ -216,10 +225,10 @@ sequenceDiagram
|
|
|
216
225
|
Asm-->>Runner: SessionConfig
|
|
217
226
|
Runner->>Child: create session + run turn loop
|
|
218
227
|
Child-->>Runner: result text
|
|
219
|
-
Runner-->>Mgr: update
|
|
220
|
-
Note over Mgr:
|
|
228
|
+
Runner-->>Mgr: update Agent
|
|
229
|
+
Note over Mgr: agent-observer subscribes to session events for stats
|
|
221
230
|
Note over Mgr: ui-observer subscribes for streaming state
|
|
222
|
-
Mgr-->>Tool:
|
|
231
|
+
Mgr-->>Tool: Agent
|
|
223
232
|
Tool-->>LLM: formatted result
|
|
224
233
|
```
|
|
225
234
|
|
|
@@ -259,11 +268,10 @@ src/
|
|
|
259
268
|
├── lifecycle/ agent execution and state tracking
|
|
260
269
|
│ ├── agent-manager.ts spawn, queue, abort, resume, concurrency
|
|
261
270
|
│ ├── agent-runner.ts session creation, turn loop, tool filtering
|
|
262
|
-
│ ├── agent
|
|
271
|
+
│ ├── agent.ts status state machine, per-agent behavior (abort, steer, worktree)
|
|
263
272
|
│ ├── parent-snapshot.ts immutable spawn-time parent state
|
|
264
273
|
│ ├── execution-state.ts session/output phase state
|
|
265
274
|
│ ├── permission-bridge.ts optional bridge to pi-permission-system registry
|
|
266
|
-
│ ├── run-handle.ts per-run cleanup lifecycle
|
|
267
275
|
│ ├── worktree.ts git worktree isolation
|
|
268
276
|
│ ├── worktree-state.ts worktree phase state
|
|
269
277
|
│ └── usage.ts token usage tracking
|
|
@@ -504,7 +512,7 @@ Bags with 10+ fields are the highest priority for decomposition.
|
|
|
504
512
|
| `AgentToolDeps` | 8 | agent-tool | ✓ done |
|
|
505
513
|
| `AgentMenuDeps` | 8 | agent-menu | ✓ done |
|
|
506
514
|
| `ConversationViewerOptions` | 8 | conversation-viewer | Low |
|
|
507
|
-
| `
|
|
515
|
+
| `AgentInit` | 8 | agent | Low |
|
|
508
516
|
|
|
509
517
|
### Complexity hotspots
|
|
510
518
|
|
|
@@ -665,103 +673,11 @@ Phase 13 addressed remaining closure factories, the last fallow refactoring targ
|
|
|
665
673
|
All six steps are closed: [#214], [#215], [#216], [#217], [#218], [#219].
|
|
666
674
|
See [phase-13-remaining-smells.md](history/phase-13-remaining-smells.md) for details.
|
|
667
675
|
|
|
668
|
-
##
|
|
676
|
+
## Phase 14 (complete)
|
|
669
677
|
|
|
670
|
-
Phase 14
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
### Findings summary
|
|
675
|
-
|
|
676
|
-
| Finding | Category | Impact | Risk | Priority |
|
|
677
|
-
| ----------------------------------------------------------------------------------------- | ------------- | ------ | ---- | -------- |
|
|
678
|
-
| `disallowed_tools` duplicates pi-permission-system's `permission:` frontmatter | A: Overlap | 4 | 2 | 12 |
|
|
679
|
-
| `extensions: string[]` allowlist is tool filtering disguised as lifecycle control | A: Overlap | 3 | 2 | 9 |
|
|
680
|
-
| `filterActiveTools` ran twice (pre-bind + post-bind) to catch extension-registered tools | B: Complexity | 3 | 1 | ✓ done |
|
|
681
|
-
| `ToolFilterConfig` existed solely to carry filtering state through the runner | C: Accidental | 2 | 1 | ✓ done |
|
|
682
|
-
| `Agent` tool name is PascalCase — misaligns with Pi's lowercase built-in convention | D: Convention | 2 | 1 | 3 |
|
|
683
|
-
|
|
684
|
-
### Step 1: Remove `disallowed_tools` — [#237] ✅ Complete
|
|
685
|
-
|
|
686
|
-
Remove the `disallowedTools` field from `AgentConfig` and all code that processes it.
|
|
687
|
-
|
|
688
|
-
1. Remove `disallowedTools` from the `AgentConfig` interface in `types.ts`.
|
|
689
|
-
2. Remove `disallowed_tools` parsing from custom agent frontmatter in `custom-agents.ts`.
|
|
690
|
-
3. Remove `disallowedSet` from `ToolFilterConfig` in `session-config.ts`.
|
|
691
|
-
4. Remove the `disallowedSet` construction in `assembleSessionConfig`.
|
|
692
|
-
5. Remove the `disallowedSet` branch from `filterActiveTools` in `agent-runner.ts`.
|
|
693
|
-
6. Remove `disallowed_tools` from the agent config editor UI.
|
|
694
|
-
7. Remove `disallowed_tools` from the agent creation wizard.
|
|
695
|
-
8. Update tests.
|
|
696
|
-
|
|
697
|
-
- Target: `types.ts`, `custom-agents.ts`, `session-config.ts`, `agent-runner.ts`, `ui/agent-config-editor.ts`, `ui/agent-creation-wizard.ts`
|
|
698
|
-
- Smell: A (responsibility overlap with pi-permission-system)
|
|
699
|
-
- Outcome: users migrate to `permission:` frontmatter for tool restrictions; single source of truth for access control
|
|
700
|
-
|
|
701
|
-
### Step 2: Remove `extensions` filtering — [#238] ✅ Complete
|
|
702
|
-
|
|
703
|
-
Remove the `extensions: string[]` allowlist and simplify the field to a boolean.
|
|
704
|
-
The `extensions: false` case (used by `isolated`) is retained in this step and removed in Phase 16.
|
|
705
|
-
|
|
706
|
-
1. Change `extensions` type from `true | string[] | false` to `boolean` in `AgentConfig`.
|
|
707
|
-
2. Remove the `extensions` array branch from `filterActiveTools` in `agent-runner.ts`.
|
|
708
|
-
3. Remove `extensions` from the agent config editor and creation wizard.
|
|
709
|
-
4. Update custom agent frontmatter parsing to treat array values as `true` (with a warning).
|
|
710
|
-
5. Update tests.
|
|
711
|
-
|
|
712
|
-
- Target: `types.ts`, `agent-runner.ts`, `session-config.ts`, `ui/agent-config-editor.ts`, `ui/agent-creation-wizard.ts`
|
|
713
|
-
- Smell: A (tool filtering disguised as extension lifecycle control)
|
|
714
|
-
- Outcome: `filterActiveTools` reduces to two concerns: recursion guard and `extensions: false` passthrough
|
|
715
|
-
|
|
716
|
-
### Step 3: Collapse `filterActiveTools` to recursion guard — [#239] ✅ Complete
|
|
717
|
-
|
|
718
|
-
With Steps 1–2 complete, `filterActiveTools` had only two remaining branches: the `EXCLUDED_TOOL_NAMES` recursion guard and the `extensions === false` passthrough.
|
|
719
|
-
Inlined the `extensions === false` passthrough into the callsite and reduced the function to its essential purpose.
|
|
720
|
-
|
|
721
|
-
1. Simplified `filterActiveTools` to filter only `EXCLUDED_TOOL_NAMES`.
|
|
722
|
-
2. Removed `ToolFilterConfig` — the function no longer needs a config bag.
|
|
723
|
-
3. Removed the pre-bind filter call — extension tools aren't in the active set pre-bind, so the guard is a no-op there.
|
|
724
|
-
4. Kept a single post-bind filter call for the recursion guard.
|
|
725
|
-
5. Flattened `SessionConfig` — removed `toolFilter: ToolFilterConfig`; `toolNames` and `extensions` are top-level fields.
|
|
726
|
-
6. Updated tests.
|
|
727
|
-
|
|
728
|
-
- Target: `agent-runner.ts`, `session-config.ts`
|
|
729
|
-
- Smell: B (accidental complexity), C (two-pass filter dance)
|
|
730
|
-
- Outcome: `filterActiveTools` is a one-liner; `SessionConfig` loses one nested type; the pre-bind/post-bind dance is gone
|
|
731
|
-
|
|
732
|
-
### Step 4: Rename `Agent` tool to `subagent` — [#242] ✅ Complete
|
|
733
|
-
|
|
734
|
-
Rename the `Agent` tool to `subagent` to align with Pi's built-in tool naming convention (all lowercase: `read`, `bash`, `write`, `edit`, `find`, `grep`, `ls`).
|
|
735
|
-
The PascalCase name was inherited from tintinweb/pi-subagents (mimicking Claude Code's convention), but Pi uses lowercase for all built-in tools.
|
|
736
|
-
The companion tools are already lowercase snake_case (`get_subagent_result`, `steer_subagent`), and nicobailon/pi-subagents already uses `subagent`.
|
|
737
|
-
|
|
738
|
-
1. Rename tool name from `"Agent"` to `"subagent"` in `agent-tool.ts`.
|
|
739
|
-
2. Update `label` and `promptSnippet` in the tool definition.
|
|
740
|
-
3. Update `EXCLUDED_TOOL_NAMES` in `agent-runner.ts`.
|
|
741
|
-
4. Update the fallback display name in `agent-tool.ts`.
|
|
742
|
-
5. Update architecture docs (tool references, domain diagrams, cross-extension section).
|
|
743
|
-
6. Update pi-permission-system docs that reference the `Agent` tool name.
|
|
744
|
-
7. Update tests.
|
|
745
|
-
|
|
746
|
-
- Target: `tools/agent-tool.ts`, `lifecycle/agent-runner.ts`, `docs/`, `../pi-permission-system/docs/`
|
|
747
|
-
- Smell: D (convention mismatch — PascalCase in a lowercase ecosystem)
|
|
748
|
-
- Outcome: all three tools use consistent lowercase naming; aligns with Pi's built-in convention
|
|
749
|
-
|
|
750
|
-
### Step dependency diagram
|
|
751
|
-
|
|
752
|
-
```mermaid
|
|
753
|
-
flowchart LR
|
|
754
|
-
S1["Step 1\nRemove disallowed_tools"]
|
|
755
|
-
S2["Step 2\nRemove extensions filtering"]
|
|
756
|
-
S3["Step 3\nCollapse filterActiveTools"]
|
|
757
|
-
S4["Step 4\nRename Agent to subagent"]
|
|
758
|
-
|
|
759
|
-
S1 --> S3
|
|
760
|
-
S2 --> S3
|
|
761
|
-
```
|
|
762
|
-
|
|
763
|
-
Steps 1, 2, and 4 are independent and can proceed in parallel.
|
|
764
|
-
Step 3 depends on Steps 1 and 2.
|
|
678
|
+
Phase 14 removed tool and extension policy enforcement from pi-subagents, eliminating overlap with pi-permission-system.
|
|
679
|
+
All four steps are closed: [#237], [#238], [#239], [#242].
|
|
680
|
+
See [phase-14-strip-policy.md](history/phase-14-strip-policy.md) for details.
|
|
765
681
|
|
|
766
682
|
[#237]: https://github.com/gotgenes/pi-packages/issues/237
|
|
767
683
|
[#238]: https://github.com/gotgenes/pi-packages/issues/238
|
|
@@ -773,23 +689,24 @@ Step 3 depends on Steps 1 and 2.
|
|
|
773
689
|
Phase 15 addresses the anemic domain model in the lifecycle layer.
|
|
774
690
|
`AgentRecord` is a data bag — identity, status transitions, and stats — but no behavior.
|
|
775
691
|
`AgentManager` reaches into records 37 times, doing work that belongs on the agent.
|
|
776
|
-
Per-agent state (pending steers, abort logic, run lifecycle)
|
|
692
|
+
Per-agent state (pending steers, abort logic, run lifecycle) was scattered across the manager, `RunHandle`, and a manager-level Map.
|
|
693
|
+
`RunHandle` has been dissolved into `Agent` methods — see Step 2.
|
|
777
694
|
|
|
778
695
|
The scheduling concern (queue, concurrency counter, drain) is tangled into `AgentManager` alongside collection management and run orchestration.
|
|
779
696
|
`notifyConcurrencyChanged()` is a scheduling method exposed as a public API so settings can poke the queue — a cross-concern leak.
|
|
780
697
|
|
|
781
698
|
### Findings summary
|
|
782
699
|
|
|
783
|
-
| Finding
|
|
784
|
-
|
|
|
785
|
-
| `AgentRecord` is anemic — no behavior, manager reaches in 37×
|
|
786
|
-
| Scheduling tangled into `AgentManager` (3 fields, 3 methods)
|
|
787
|
-
|
|
|
788
|
-
| `onSessionCreated` callback flows through 3 layers
|
|
789
|
-
| `resume()` duplicates observer subscribe/unsubscribe pattern
|
|
790
|
-
| `exec`/`registry` relay-only deps on `AgentManager`
|
|
700
|
+
| Finding | Category | Impact | Risk | Priority |
|
|
701
|
+
| ----------------------------------------------------------------- | ------------ | ------ | ---- | -------- |
|
|
702
|
+
| `AgentRecord` is anemic — no behavior, manager reaches in 37× | B: Oversized | 5 | 3 | 15 |
|
|
703
|
+
| Scheduling tangled into `AgentManager` (3 fields, 3 methods) | A: Coupling | 4 | 2 | 12 |
|
|
704
|
+
| ~~`startAgent` uses `.then()`/`.catch()` instead of async/await~~ | C: Callbacks | 3 | 2 | ✅ |
|
|
705
|
+
| `onSessionCreated` callback flows through 3 layers | C: Callbacks | 3 | 2 | 10 |
|
|
706
|
+
| `resume()` duplicates observer subscribe/unsubscribe pattern | A: Redundant | 2 | 1 | 8 |
|
|
707
|
+
| `exec`/`registry` relay-only deps on `AgentManager` | C: Coupling | 2 | 1 | 6 |
|
|
791
708
|
|
|
792
|
-
### Step 1: Evolve AgentRecord into Agent with behavior — [#227]
|
|
709
|
+
### Step 1: Evolve AgentRecord into Agent with behavior — [#227] ✅ Complete
|
|
793
710
|
|
|
794
711
|
Rename `AgentRecord` → `Agent` (or wrap it).
|
|
795
712
|
Move per-agent behavior from `AgentManager` into the agent:
|
|
@@ -802,15 +719,17 @@ Move per-agent behavior from `AgentManager` into the agent:
|
|
|
802
719
|
- Smell: B (anemic domain model) + C (manager reaching into records)
|
|
803
720
|
- Outcome: `AgentManager` delegates via Tell-Don't-Ask; per-agent state lives on the agent
|
|
804
721
|
|
|
805
|
-
### Step 2: Convert startAgent to async/await — [#228]
|
|
722
|
+
### Step 2: Convert startAgent to async/await — [#228] ✅ Complete
|
|
806
723
|
|
|
807
|
-
|
|
724
|
+
Converted `startAgent` to `async` with `try/catch` and dissolved `RunHandle` into `Agent` methods.
|
|
808
725
|
`spawn()` assigns `record.promise = this.startAgent(...)` instead of calling `startAgent()` synchronously.
|
|
726
|
+
`Agent` gained run lifecycle methods: `completeRun`, `failRun`, `wireSignal`, `attachObserver`, `releaseListeners`, `setOnRunFinished`.
|
|
727
|
+
Worktree setup was hoisted to callers (`spawn`, `drainQueue`) to preserve the synchronous-throw contract.
|
|
809
728
|
|
|
810
729
|
- Depends on: #227
|
|
811
|
-
- Target: `src/lifecycle/agent-manager.ts`
|
|
730
|
+
- Target: `src/lifecycle/agent-manager.ts`, `src/lifecycle/agent.ts`
|
|
812
731
|
- Smell: C (raw promise callbacks)
|
|
813
|
-
- Outcome: zero `.then()`/`.catch()` in `agent-manager.ts`
|
|
732
|
+
- Outcome: zero `.then()`/`.catch()` in `agent-manager.ts`; `RunHandle` deleted; Agent owns run lifecycle
|
|
814
733
|
|
|
815
734
|
### Step 3: Replace onSessionCreated callback with observer method — [#229]
|
|
816
735
|
|
|
@@ -840,10 +759,10 @@ Move them to `ConcreteAgentRunner` construction.
|
|
|
840
759
|
- Smell: C (relay-only dependencies)
|
|
841
760
|
- Outcome: `AgentManager` loses 2 fields; `AgentManagerOptions` shrinks from 7 to 5 fields
|
|
842
761
|
|
|
843
|
-
### Step 6: Unify resume() with
|
|
762
|
+
### Step 6: Unify resume() with Agent run lifecycle methods — [#232]
|
|
844
763
|
|
|
845
|
-
After #
|
|
846
|
-
The agent manages its own observer subscription lifecycle.
|
|
764
|
+
After #228 dissolved `RunHandle` into Agent methods (`completeRun`, `failRun`, `releaseListeners`), `resume()` on `AgentManager` becomes a short delegation to `agent.resume(runner, prompt, signal)`.
|
|
765
|
+
The agent manages its own observer subscription lifecycle using the same methods that `startAgent` uses.
|
|
847
766
|
|
|
848
767
|
- Depends on: #227, #228
|
|
849
768
|
- Target: `src/lifecycle/agent-manager.ts`
|
|
@@ -854,12 +773,12 @@ The agent manages its own observer subscription lifecycle.
|
|
|
854
773
|
|
|
855
774
|
```mermaid
|
|
856
775
|
flowchart LR
|
|
857
|
-
S1["Step 1
|
|
858
|
-
S2["Step 2
|
|
859
|
-
S3["Step 3
|
|
860
|
-
S4["Step 4
|
|
861
|
-
S5["Step 5
|
|
862
|
-
S6["Step 6
|
|
776
|
+
S1["Step 1<br/>Agent with behavior"]
|
|
777
|
+
S2["Step 2<br/>async startAgent"]
|
|
778
|
+
S3["Step 3<br/>onSessionCreated observer"]
|
|
779
|
+
S4["Step 4<br/>ConcurrencyQueue"]
|
|
780
|
+
S5["Step 5<br/>relay deps"]
|
|
781
|
+
S6["Step 6<br/>resume unification"]
|
|
863
782
|
|
|
864
783
|
S1 --> S2
|
|
865
784
|
S1 --> S6
|
|
@@ -896,7 +815,7 @@ By this point the core is minimal and stable — the API boundary has been prove
|
|
|
896
815
|
|
|
897
816
|
## Refactoring history
|
|
898
817
|
|
|
899
|
-
Phases 1–5
|
|
818
|
+
Phases 1–5, 7–14 are complete.
|
|
900
819
|
Phase 6 (UI extraction to a separate package) is deferred.
|
|
901
820
|
Detailed records are preserved in per-phase history files:
|
|
902
821
|
|
|
@@ -915,7 +834,7 @@ Detailed records are preserved in per-phase history files:
|
|
|
915
834
|
| 11 | Closure factories to classes | Complete | [phase-11-closure-to-class.md](history/phase-11-closure-to-class.md) |
|
|
916
835
|
| 12 | Complexity reduction and test fixture extraction | Complete | [phase-12-complexity-test-fixtures.md](history/phase-12-complexity-test-fixtures.md) |
|
|
917
836
|
| 13 | Remaining structural smells | Complete | [phase-13-remaining-smells.md](history/phase-13-remaining-smells.md) |
|
|
918
|
-
| 14 | Strip policy from core |
|
|
837
|
+
| 14 | Strip policy from core | Complete | [phase-14-strip-policy.md](history/phase-14-strip-policy.md) |
|
|
919
838
|
| 15 | Domain model evolution | Planned | — |
|
|
920
839
|
| 16 | Invert dependencies | Planned | — |
|
|
921
840
|
| 17 | Extract UI to separate package | Planned | — |
|
|
@@ -936,7 +855,7 @@ Detailed records are preserved in per-phase history files:
|
|
|
936
855
|
| Phase 11 | #192, #193, #194, #195, #196 | SessionContext, runtime queries, interface alignment, tool classes, runner/menu classes, index.ts simplification |
|
|
937
856
|
| Phase 12 | #205, #206, #207, #208 | renderWidgetLines, showAgentDetail, widget update, shared test fixtures |
|
|
938
857
|
| Phase 13 | #214, #215, #216, #217, #218, #219 | Closure-to-class, buildParentContext, startAgent decomp, overwrite guard, settings SDK, test duplication |
|
|
939
|
-
| Phase 14 | #237, #238, #239
|
|
858
|
+
| Phase 14 | #237, #238, #239, #242 | Remove disallowed_tools, remove extensions filtering, collapse filterActiveTools, rename Agent to subagent |
|
|
940
859
|
| Phase 15 | #227, #228, #229, #230, #231, #232 | Agent domain model, async startAgent, onSessionCreated observer, ConcurrencyQueue, relay deps, resume unification |
|
|
941
860
|
|
|
942
861
|
The remaining open issue is #22 (parent-session resolution), a cross-extension track that does not gate the structural work.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Phase 14: Strip policy from core
|
|
2
|
+
|
|
3
|
+
## Summary
|
|
4
|
+
|
|
5
|
+
Phase 14 removed tool and extension policy enforcement from pi-subagents.
|
|
6
|
+
This code duplicated what pi-permission-system already provides with richer semantics (allow/ask/deny vs. binary hide).
|
|
7
|
+
Removing it simplified `runAgent`, shrunk `AgentConfig` and `SessionConfig`, and prepared a cleaner codebase for Phase 15's domain-model work.
|
|
8
|
+
|
|
9
|
+
All four steps are closed: [#237], [#238], [#239], [#242].
|
|
10
|
+
|
|
11
|
+
## Steps
|
|
12
|
+
|
|
13
|
+
### Step 1: Remove `disallowed_tools` — [#237]
|
|
14
|
+
|
|
15
|
+
Removed the `disallowedTools` field from `AgentConfig` and all code that processed it.
|
|
16
|
+
Users migrate to `permission:` frontmatter for tool restrictions.
|
|
17
|
+
|
|
18
|
+
- Target: `types.ts`, `custom-agents.ts`, `session-config.ts`, `agent-runner.ts`, `ui/agent-config-editor.ts`, `ui/agent-creation-wizard.ts`
|
|
19
|
+
- Outcome: single source of truth for access control in pi-permission-system
|
|
20
|
+
|
|
21
|
+
### Step 2: Remove `extensions` filtering — [#238]
|
|
22
|
+
|
|
23
|
+
Removed the `extensions: string[]` allowlist and simplified the field to a boolean.
|
|
24
|
+
The `extensions: false` case (used by `isolated`) was retained for Phase 16.
|
|
25
|
+
|
|
26
|
+
- Target: `types.ts`, `agent-runner.ts`, `session-config.ts`, `ui/agent-config-editor.ts`, `ui/agent-creation-wizard.ts`
|
|
27
|
+
- Outcome: `filterActiveTools` reduced to two concerns: recursion guard and `extensions: false` passthrough
|
|
28
|
+
|
|
29
|
+
### Step 3: Collapse `filterActiveTools` to recursion guard — [#239]
|
|
30
|
+
|
|
31
|
+
With Steps 1–2 complete, `filterActiveTools` was reduced to its essential purpose: filtering `EXCLUDED_TOOL_NAMES` to prevent recursive agent spawning.
|
|
32
|
+
|
|
33
|
+
- Removed `ToolFilterConfig` — the function no longer needs a config bag.
|
|
34
|
+
- Removed the pre-bind filter call — extension tools aren't in the active set pre-bind.
|
|
35
|
+
- Flattened `SessionConfig` — removed `toolFilter: ToolFilterConfig`; `toolNames` and `extensions` are top-level fields.
|
|
36
|
+
- Target: `agent-runner.ts`, `session-config.ts`
|
|
37
|
+
- Outcome: `filterActiveTools` is a one-liner; the pre-bind/post-bind dance is gone
|
|
38
|
+
|
|
39
|
+
### Step 4: Rename `Agent` tool to `subagent` — [#242]
|
|
40
|
+
|
|
41
|
+
Renamed the `Agent` tool to `subagent` to align with Pi's built-in tool naming convention (all lowercase).
|
|
42
|
+
|
|
43
|
+
- Target: `tools/agent-tool.ts`, `lifecycle/agent-runner.ts`, `docs/`, `../pi-permission-system/docs/`
|
|
44
|
+
- Outcome: all three tools use consistent lowercase naming
|
|
45
|
+
|
|
46
|
+
[#237]: https://github.com/gotgenes/pi-packages/issues/237
|
|
47
|
+
[#238]: https://github.com/gotgenes/pi-packages/issues/238
|
|
48
|
+
[#239]: https://github.com/gotgenes/pi-packages/issues/239
|
|
49
|
+
[#242]: https://github.com/gotgenes/pi-packages/issues/242
|