@gotgenes/pi-subagents 12.1.0 → 13.1.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 +24 -0
- package/dist/public.d.ts +1 -3
- package/docs/architecture/architecture.md +86 -57
- package/docs/plans/0264-remove-extension-lifecycle-control.md +275 -0
- package/docs/plans/0265-born-complete-subagent-session.md +330 -0
- package/docs/retro/0264-remove-extension-lifecycle-control.md +89 -0
- package/docs/retro/0265-born-complete-subagent-session.md +58 -0
- package/package.json +1 -1
- package/src/config/agent-types.ts +0 -2
- package/src/config/custom-agents.ts +0 -30
- package/src/config/default-agents.ts +1 -7
- package/src/config/invocation-config.ts +0 -3
- package/src/index.ts +3 -5
- package/src/lifecycle/agent-manager.ts +9 -10
- package/src/lifecycle/agent.ts +56 -55
- package/src/lifecycle/create-subagent-session.ts +242 -0
- package/src/lifecycle/subagent-session.ts +204 -0
- package/src/lifecycle/turn-limits.ts +13 -0
- package/src/runtime.ts +1 -1
- package/src/service/service-adapter.ts +0 -1
- package/src/service/service.ts +0 -1
- package/src/session/conversation.ts +49 -0
- package/src/session/prompts.ts +2 -23
- package/src/session/session-config.ts +10 -45
- package/src/settings.ts +1 -1
- package/src/tools/agent-tool.ts +0 -5
- package/src/tools/background-spawner.ts +0 -1
- package/src/tools/foreground-runner.ts +0 -1
- package/src/tools/get-result-tool.ts +1 -1
- package/src/tools/spawn-config.ts +1 -5
- package/src/types.ts +0 -7
- package/src/ui/agent-config-editor.ts +0 -5
- package/src/ui/agent-creation-wizard.ts +0 -4
- package/src/ui/display.ts +1 -2
- package/src/lifecycle/agent-runner.ts +0 -472
- package/src/lifecycle/execution-state.ts +0 -17
- package/src/session/safe-fs.ts +0 -45
- package/src/session/skill-loader.ts +0 -104
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,30 @@ 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
|
+
## [13.1.0](https://github.com/gotgenes/pi-packages/compare/pi-subagents-v13.0.0...pi-subagents-v13.1.0) (2026-05-30)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* add createSubagentSession factory ([62c319d](https://github.com/gotgenes/pi-packages/commit/62c319d6703a6f58a829f372b609daea36170987))
|
|
14
|
+
* add SubagentSession with turn-loop and disposal behavior ([69f8f4b](https://github.com/gotgenes/pi-packages/commit/69f8f4bf78431be990a9eb6fbe592e59cc313912))
|
|
15
|
+
* dissolve the runner; Agent drives SubagentSession directly ([fbe71b0](https://github.com/gotgenes/pi-packages/commit/fbe71b02759551e60b4e22e96bb28299e444feb2))
|
|
16
|
+
|
|
17
|
+
## [13.0.0](https://github.com/gotgenes/pi-packages/compare/pi-subagents-v12.1.0...pi-subagents-v13.0.0) (2026-05-30)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### ⚠ BREAKING CHANGES
|
|
21
|
+
|
|
22
|
+
* the `skills:` custom-agent frontmatter key and skill preloading are removed; children always load the parent's skills.
|
|
23
|
+
* the `extensions:` custom-agent frontmatter key is removed; children always load the parent's extensions.
|
|
24
|
+
* `SpawnOptions.isolated` and the `isolated:` custom-agent frontmatter key are removed. Children always load the parent's extensions.
|
|
25
|
+
|
|
26
|
+
### Features
|
|
27
|
+
|
|
28
|
+
* always inherit extensions; make the recursion guard unconditional ([#264](https://github.com/gotgenes/pi-packages/issues/264)) ([3cc682e](https://github.com/gotgenes/pi-packages/commit/3cc682ec401167f922a1f892f6260a10f9fa99f2))
|
|
29
|
+
* always inherit skills; remove noSkills and the skill-preload path ([#264](https://github.com/gotgenes/pi-packages/issues/264)) ([93266ff](https://github.com/gotgenes/pi-packages/commit/93266ff4a204d154b357efac57912330fad240be))
|
|
30
|
+
* remove isolated from the subagent spawn API and lifecycle ([#264](https://github.com/gotgenes/pi-packages/issues/264)) ([d08f340](https://github.com/gotgenes/pi-packages/commit/d08f34066ea472d850423e67349b7a623ca72f42))
|
|
31
|
+
|
|
8
32
|
## [12.1.0](https://github.com/gotgenes/pi-packages/compare/pi-subagents-v12.0.0...pi-subagents-v12.1.0) (2026-05-29)
|
|
9
33
|
|
|
10
34
|
|
package/dist/public.d.ts
CHANGED
|
@@ -25,7 +25,6 @@ interface AgentInvocation {
|
|
|
25
25
|
modelName?: string;
|
|
26
26
|
thinking?: ThinkingLevel;
|
|
27
27
|
maxTurns?: number;
|
|
28
|
-
isolated?: boolean;
|
|
29
28
|
inheritContext?: boolean;
|
|
30
29
|
runInBackground?: boolean;
|
|
31
30
|
}
|
|
@@ -46,7 +45,7 @@ interface AgentInvocation {
|
|
|
46
45
|
* The child's working directory is supplied by a registered WorkspaceProvider
|
|
47
46
|
* (the workspace seam); with no provider the child runs in the parent cwd.
|
|
48
47
|
*
|
|
49
|
-
* Phase-specific collaborators (
|
|
48
|
+
* Phase-specific collaborators (subagentSession, notification) are attached
|
|
50
49
|
* after construction as lifecycle information becomes available.
|
|
51
50
|
*/
|
|
52
51
|
|
|
@@ -125,7 +124,6 @@ interface SpawnOptions {
|
|
|
125
124
|
model?: string;
|
|
126
125
|
maxTurns?: number;
|
|
127
126
|
thinkingLevel?: string;
|
|
128
|
-
isolated?: boolean;
|
|
129
127
|
inheritContext?: boolean;
|
|
130
128
|
foreground?: boolean;
|
|
131
129
|
bypassQueue?: boolean;
|
|
@@ -45,8 +45,6 @@ flowchart TB
|
|
|
45
45
|
SessionConfig["assembleSessionConfig<br/>(pure assembler)"]
|
|
46
46
|
Prompts["prompts<br/>(system prompt)"]
|
|
47
47
|
Context["context<br/>(parent history)"]
|
|
48
|
-
SafeFs["safe-fs<br/>(symlink/name guards)"]
|
|
49
|
-
SkillLoader["skill-loader<br/>(preload skills)"]
|
|
50
48
|
Env["env<br/>(git/platform)"]
|
|
51
49
|
ModelResolver["model-resolver<br/>(fuzzy match)"]
|
|
52
50
|
end
|
|
@@ -55,7 +53,8 @@ flowchart TB
|
|
|
55
53
|
direction TB
|
|
56
54
|
AgentManager["AgentManager<br/>(spawn, abort, collection)"]
|
|
57
55
|
ConcurrencyQueue["ConcurrencyQueue<br/>(scheduling, drain)"]
|
|
58
|
-
|
|
56
|
+
CreateSubagentSession["createSubagentSession<br/>(assembly factory)"]
|
|
57
|
+
SubagentSession["SubagentSession<br/>(turn loop, steer, dispose)"]
|
|
59
58
|
Agent["Agent<br/>(status, behavior: abort/steer/run lifecycle)"]
|
|
60
59
|
ParentSnapshot["ParentSnapshot<br/>(frozen parent state)"]
|
|
61
60
|
Workspace["workspace<br/>(provider seam: child cwd + teardown)"]
|
|
@@ -87,14 +86,15 @@ flowchart TB
|
|
|
87
86
|
end
|
|
88
87
|
|
|
89
88
|
AgentTool --> AgentManager
|
|
90
|
-
AgentManager -->
|
|
91
|
-
|
|
89
|
+
AgentManager --> Agent
|
|
90
|
+
Agent --> CreateSubagentSession & SubagentSession
|
|
91
|
+
CreateSubagentSession --> SubagentSession
|
|
92
|
+
CreateSubagentSession --> SessionConfig
|
|
92
93
|
SessionConfig --> AgentTypeRegistry
|
|
93
|
-
SessionConfig --> Prompts &
|
|
94
|
-
SkillLoader --> SafeFs
|
|
94
|
+
SessionConfig --> Prompts & Env
|
|
95
95
|
AgentTypeRegistry --> DefaultAgents & CustomAgents
|
|
96
|
-
RecordObserver -.->|subscribes|
|
|
97
|
-
UIObserver -.->|subscribes|
|
|
96
|
+
RecordObserver -.->|subscribes| SubagentSession
|
|
97
|
+
UIObserver -.->|subscribes| SubagentSession
|
|
98
98
|
Widget -.->|polls| AgentManager
|
|
99
99
|
```
|
|
100
100
|
|
|
@@ -111,7 +111,7 @@ classDiagram
|
|
|
111
111
|
+error?: string
|
|
112
112
|
+toolUses: number
|
|
113
113
|
+lifetimeUsage: LifetimeUsage
|
|
114
|
-
+
|
|
114
|
+
+subagentSession?: SubagentSession
|
|
115
115
|
+notification?: NotificationState
|
|
116
116
|
+markRunning()
|
|
117
117
|
+markCompleted()
|
|
@@ -124,13 +124,13 @@ classDiagram
|
|
|
124
124
|
+resume(prompt, signal)
|
|
125
125
|
+abort(): boolean
|
|
126
126
|
+queueSteer(message)
|
|
127
|
-
+flushPendingSteers(
|
|
127
|
+
+flushPendingSteers()
|
|
128
128
|
+completeRun(result)
|
|
129
129
|
+failRun(err)
|
|
130
|
+
+disposeSession()
|
|
130
131
|
+wireSignal(signal, onAbort)
|
|
131
132
|
+attachObserver(unsub)
|
|
132
133
|
+releaseListeners()
|
|
133
|
-
+setOnRunFinished(fn)
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
class AgentManager {
|
|
@@ -213,24 +213,31 @@ sequenceDiagram
|
|
|
213
213
|
participant Tool as subagent tool
|
|
214
214
|
participant Spawn as spawn-config
|
|
215
215
|
participant Mgr as AgentManager
|
|
216
|
-
participant
|
|
216
|
+
participant Ag as Agent
|
|
217
|
+
participant Factory as createSubagentSession
|
|
217
218
|
participant Asm as assembleSessionConfig
|
|
219
|
+
participant Sub as SubagentSession
|
|
218
220
|
participant Child as Child session
|
|
219
221
|
|
|
220
222
|
LLM->>Tool: subagent(type, prompt, ...)
|
|
221
223
|
Tool->>Spawn: resolveSpawnConfig(params)
|
|
222
224
|
Spawn-->>Tool: ResolvedSpawnConfig
|
|
223
225
|
Tool->>Mgr: spawn(snapshot, type, prompt, config)
|
|
224
|
-
Mgr->>
|
|
225
|
-
|
|
226
|
-
Asm
|
|
227
|
-
|
|
228
|
-
Child
|
|
229
|
-
|
|
230
|
-
Note over
|
|
231
|
-
|
|
226
|
+
Mgr->>Ag: run()
|
|
227
|
+
Ag->>Factory: createSubagentSession(params, deps)
|
|
228
|
+
Factory->>Asm: assembleSessionConfig(type, ctx, opts, env, registry, io)
|
|
229
|
+
Asm-->>Factory: SessionConfig
|
|
230
|
+
Factory->>Child: create session + bind extensions
|
|
231
|
+
Factory-->>Ag: SubagentSession (born complete)
|
|
232
|
+
Note over Ag: agent-observer + ui-observer subscribe to session events
|
|
233
|
+
Ag->>Sub: runTurnLoop(prompt, opts)
|
|
234
|
+
Sub->>Child: prompt + drive turn loop
|
|
235
|
+
Child-->>Sub: result text
|
|
236
|
+
Sub-->>Ag: TurnLoopResult
|
|
237
|
+
Ag-->>Mgr: update Agent
|
|
232
238
|
Mgr-->>Tool: Agent
|
|
233
239
|
Tool-->>LLM: formatted result
|
|
240
|
+
Note over Mgr: disposeSession() fires `disposed` at cleanup (resume-detectable)
|
|
234
241
|
```
|
|
235
242
|
|
|
236
243
|
## Module organization
|
|
@@ -260,19 +267,19 @@ src/
|
|
|
260
267
|
│ ├── prompts.ts system prompt building
|
|
261
268
|
│ ├── content-items.ts shared message content parsing (tool-call names, assistant content)
|
|
262
269
|
│ ├── context.ts parent conversation extraction
|
|
263
|
-
│ ├──
|
|
264
|
-
│ ├── skill-loader.ts skill preloading
|
|
270
|
+
│ ├── conversation.ts render a session's messages as formatted text
|
|
265
271
|
│ ├── env.ts git/platform detection
|
|
266
272
|
│ ├── model-resolver.ts fuzzy model name resolution
|
|
267
273
|
│ └── session-dir.ts session directory derivation
|
|
268
274
|
│
|
|
269
275
|
├── lifecycle/ agent execution and state tracking
|
|
270
276
|
│ ├── agent-manager.ts collection manager + observer wiring
|
|
271
|
-
│ ├──
|
|
277
|
+
│ ├── create-subagent-session.ts assembly factory: session creation, binding, tool filtering
|
|
278
|
+
│ ├── subagent-session.ts born-complete child session: turn loop, steer, dispose
|
|
279
|
+
│ ├── turn-limits.ts normalizeMaxTurns (turn-count policy)
|
|
272
280
|
│ ├── agent.ts owns full execution lifecycle (run, abort, steer, workspace)
|
|
273
281
|
│ ├── concurrency-queue.ts background agent scheduling with configurable concurrency limit
|
|
274
282
|
│ ├── parent-snapshot.ts immutable spawn-time parent state
|
|
275
|
-
│ ├── execution-state.ts session/output phase state
|
|
276
283
|
│ ├── child-lifecycle.ts child-execution lifecycle event publisher
|
|
277
284
|
│ ├── workspace.ts workspace provider seam (generative extension surface)
|
|
278
285
|
│ └── usage.ts token usage tracking
|
|
@@ -332,7 +339,7 @@ flowchart TD
|
|
|
332
339
|
subgraph core["@gotgenes/pi-subagents"]
|
|
333
340
|
direction TB
|
|
334
341
|
exports["SubagentsService API<br/>publish / getSubagentsService<br/>SubagentRecord, SubagentStatus"]
|
|
335
|
-
engine["Tools: subagent, get_subagent_result,<br/>steer_subagent<br/>AgentManager,
|
|
342
|
+
engine["Tools: subagent, get_subagent_result,<br/>steer_subagent<br/>AgentManager, createSubagentSession, SubagentSession"]
|
|
336
343
|
ui_int["Internal UI: widget, viewer,<br/>/agents menu"]
|
|
337
344
|
end
|
|
338
345
|
|
|
@@ -349,13 +356,14 @@ They declare this package as an optional peer dependency and use dynamic import
|
|
|
349
356
|
- The three tools: `subagent` (née `Agent`), `get_subagent_result`, `steer_subagent`.
|
|
350
357
|
- `AgentManager` — spawn, abort, resume, collection management, observer wiring.
|
|
351
358
|
- `ConcurrencyQueue` — background agent scheduling with configurable concurrency limit.
|
|
352
|
-
- `
|
|
359
|
+
- `createSubagentSession` — assembly factory: session creation and extension binding; returns a born-complete `SubagentSession`.
|
|
360
|
+
- `SubagentSession` — the born-complete child session: drives the turn loop (`runTurnLoop`/`resumeTurnLoop`), steers, and disposes (firing `disposed` at true session disposal, so resume executions are registry-detected).
|
|
353
361
|
- `child-lifecycle` — publishes the child-execution lifecycle (`spawning`, `session-created` before `bindExtensions()`, `completed`, `disposed`) on `pi.events`.
|
|
354
362
|
Reactive consumers subscribe: `@gotgenes/pi-permission-system` registers each child session on `session-created` and unregisters it on `disposed`.
|
|
355
363
|
This replaced the former outbound `permission-bridge` (#261, ADR 0002) — the core no longer looks up a named consumer.
|
|
356
364
|
- `workspace` — the single generative seam (#262, ADR 0002): a registered `WorkspaceProvider` supplies a child's cwd plus bracketed `dispose()` at run-start.
|
|
357
365
|
With no provider, children run in the parent cwd (default unchanged); the git worktree strategy lives behind this seam in `@gotgenes/pi-subagents-worktrees` (#263, the seam's first consumer).
|
|
358
|
-
- `session-config` — pure configuration assembler (
|
|
366
|
+
- `session-config` — pure configuration assembler (called by `createSubagentSession`).
|
|
359
367
|
- `SubagentRuntime` — session-scoped state bag with methods.
|
|
360
368
|
- `ParentSnapshot` — immutable snapshot of parent session state, captured once at spawn time.
|
|
361
369
|
- `record-observer` — session-event observer that updates record statistics without callback threading.
|
|
@@ -415,7 +423,7 @@ Key types:
|
|
|
415
423
|
|
|
416
424
|
- `SubagentsService` — `spawn`, `getRecord`, `listAgents`, `abort`, `steer`, `waitForAll`, `hasRunning`.
|
|
417
425
|
- `SubagentRecord` — serializable agent snapshot (no live session objects).
|
|
418
|
-
- `SpawnOptions` — `description`, `model`, `maxTurns`, `thinkingLevel`, `
|
|
426
|
+
- `SpawnOptions` — `description`, `model`, `maxTurns`, `thinkingLevel`, `inheritContext`, `foreground`, `bypassQueue`.
|
|
419
427
|
- `SUBAGENT_EVENTS` — channel constants for `pi.events` subscriptions.
|
|
420
428
|
|
|
421
429
|
### Accessor pattern
|
|
@@ -482,11 +490,11 @@ Latent extensibility is the deliverable; a vacant hook is not.
|
|
|
482
490
|
### Core responsibilities (keep)
|
|
483
491
|
|
|
484
492
|
- **Agent definitions** — name, model, thinking, system prompt, tools list.
|
|
485
|
-
- **Prompt composition** — system prompt assembly
|
|
493
|
+
- **Prompt composition** — system prompt assembly.
|
|
486
494
|
- **Session lifecycle** — create child sessions, bind extensions, run conversation loop, track results.
|
|
487
495
|
- **Concurrency management** — queue, abort, resume, max concurrency.
|
|
488
496
|
- **Recursion guard** — remove pi-subagents' own three tools from child sessions (prevent infinite nesting).
|
|
489
|
-
With `isolated` removed, children always load the parent's resources, so the guard
|
|
497
|
+
With `isolated` removed (#264), children always load the parent's resources, so the guard is unconditional rather than gated on `cfg.extensions`.
|
|
490
498
|
This is the core defending its own invariant, keyed off its own tool names — not policy.
|
|
491
499
|
- **Lifecycle events** — emit awaited, ordered events when child sessions spawn, are created, complete, and are disposed.
|
|
492
500
|
- **Workspace provider seam** — accept a registered `WorkspaceProvider` and consult it for the child's cwd; default to the parent's cwd when none is registered.
|
|
@@ -499,7 +507,8 @@ Latent extensibility is the deliverable; a vacant hook is not.
|
|
|
499
507
|
- **Worktree isolation** (`worktree.ts`, `worktree-isolation.ts`, `GitWorktreeManager`, the `isolation: "worktree"` spawn mode) — environment policy, not core.
|
|
500
508
|
Git worktrees are one *strategy* for choosing the child's working directory; containers, throwaway tmpdirs, and remote sandboxes are others.
|
|
501
509
|
Evicted to `@gotgenes/pi-subagents-worktrees` (#263), the first consumer of the workspace provider seam.
|
|
502
|
-
- **Extension lifecycle control** (`extensions: false`, `isolated`, `noSkills`) —
|
|
510
|
+
- **Extension lifecycle control** (`extensions: false`, `isolated`, `noSkills`) — removed in #264.
|
|
511
|
+
Deny-at-use (the in-child permission layer blocking disallowed tool calls) covers what `isolated` pretended to do for tools.
|
|
503
512
|
Prevent-load (refusing to bind an extension because of load-time side effects, cost, or true sandboxing) is genuinely generative and is left as a *latent* (un-built) provider seam, added only if a real consumer needs it.
|
|
504
513
|
|
|
505
514
|
### Composition model
|
|
@@ -536,20 +545,21 @@ This is achieved across phases: Phase 14 (strip policy), Phase 16 (invert depend
|
|
|
536
545
|
These interfaces carry hidden dependencies that obscure true coupling.
|
|
537
546
|
Bags with 10+ fields are the highest priority for decomposition.
|
|
538
547
|
|
|
539
|
-
| Interface
|
|
540
|
-
|
|
|
541
|
-
| `ResolvedSpawnConfig`
|
|
542
|
-
| `AgentSpawnConfig`
|
|
543
|
-
| `
|
|
544
|
-
| `
|
|
545
|
-
| `
|
|
546
|
-
| `
|
|
547
|
-
| `
|
|
548
|
-
| `
|
|
549
|
-
| `
|
|
550
|
-
| `
|
|
551
|
-
| `
|
|
552
|
-
| `
|
|
548
|
+
| Interface | Fields | Consumers | Severity |
|
|
549
|
+
| ----------------------------- | ------------------------------------------------------------ | ------------------------------------------------- | --------- |
|
|
550
|
+
| `ResolvedSpawnConfig` | 3 nested | foreground-runner, background-spawner, agent-tool | ✓ done |
|
|
551
|
+
| `AgentSpawnConfig` | 13 → 13 (ParentSessionInfo nested) | agent-manager (internal) | ✓ done |
|
|
552
|
+
| `CreateSubagentSessionParams` | 6 (snapshot, type, cwd, parentSession, model, thinkingLevel) | create-subagent-session | ✓ done |
|
|
553
|
+
| `TurnLoopOptions` | 4 (maxTurns, defaultMaxTurns, graceTurns, signal) | subagent-session | ✓ done |
|
|
554
|
+
| `SessionConfig` | 6 (flat fields; extensions/noSkills/extras removed in #264) | session-config (output of assembler) | ✓ done |
|
|
555
|
+
| `NotificationDetails` | 10 | notification | Low (DTO) |
|
|
556
|
+
| `ResourceLoaderOptions` | 10 | create-subagent-session (SDK bridge) | Low (SDK) |
|
|
557
|
+
| `SubagentSessionIO` | split → `EnvironmentIO` (3) + `SessionFactoryIO` (5+1) | create-subagent-session | ✓ done |
|
|
558
|
+
| `CreateSessionOptions` | 9 | create-subagent-session (SDK bridge) | Low (SDK) |
|
|
559
|
+
| `AgentToolDeps` | 8 | agent-tool | ✓ done |
|
|
560
|
+
| `AgentMenuDeps` | 8 | agent-menu | ✓ done |
|
|
561
|
+
| `ConversationViewerOptions` | 8 | conversation-viewer | Low |
|
|
562
|
+
| `AgentInit` | 8 | agent | Low |
|
|
553
563
|
|
|
554
564
|
### Complexity hotspots
|
|
555
565
|
|
|
@@ -579,6 +589,22 @@ The prior clone group between `agent-runner.ts` and `message-formatters.ts` was
|
|
|
579
589
|
The 20-line clone group between `agent-config-editor.ts` and `agent-creation-wizard.ts` was resolved in #217 — extracted into `ui/agent-file-writer.ts` (`writeAgentFile`).
|
|
580
590
|
One 11-line internal clone group remains within `agent-config-editor.ts` (lines 135–145 / 173–183).
|
|
581
591
|
|
|
592
|
+
### Session encapsulation debt (Law of Demeter) — [#277]
|
|
593
|
+
|
|
594
|
+
Discovered while planning [#265].
|
|
595
|
+
Consumers reach the raw SDK `AgentSession` through the `Agent.session` getter (`this.subagentSession?.session`) and operate on it directly, instead of telling the owning agent what they want.
|
|
596
|
+
These are Law of Demeter / Tell-Don't-Ask reach-throughs; the fix is intent-revealing methods on the owning object (`Subagent` / `SubagentSession`, introduced by [#265]).
|
|
597
|
+
|
|
598
|
+
| Reach-through | Sites | Missing method |
|
|
599
|
+
| ------------------------------------- | --------------------------------------------------- | ------------------------------------------------ |
|
|
600
|
+
| Steer (buffer-or-deliver, duplicated) | `service-adapter.ts` (~L93), `steer-tool.ts` (~L43) | `Subagent.steer(message)` |
|
|
601
|
+
| Conversation viewing | `get-result-tool.ts:84`, `agent-menu.ts:255` | `Subagent.getConversation()` |
|
|
602
|
+
| Session-readiness guard | `agent-tool.ts:111`, `agent-manager.ts:203` | `Subagent.isSessionReady()` |
|
|
603
|
+
| Session disposal | `agent-manager.ts:235,309` | `SubagentSession.dispose()` — resolved by [#265] |
|
|
604
|
+
|
|
605
|
+
[#265] introduces `SubagentSession` and routes the run / resume / dispose path (and steering during a run) through it; the consumer-facing reach-throughs above are deferred to [#277].
|
|
606
|
+
The steer buffer-or-deliver decision is duplicated across two call sites — two callers performing the same reach-through plus the same decision is the signal for the missing method.
|
|
607
|
+
|
|
582
608
|
### Proposed bag decompositions
|
|
583
609
|
|
|
584
610
|
#### ResolvedSpawnConfig (15 fields → 3 value objects)
|
|
@@ -604,7 +630,6 @@ interface SpawnExecution {
|
|
|
604
630
|
thinking: ThinkingLevel | undefined;
|
|
605
631
|
inheritContext: boolean;
|
|
606
632
|
runInBackground: boolean;
|
|
607
|
-
isolated: boolean;
|
|
608
633
|
agentInvocation: AgentInvocation;
|
|
609
634
|
}
|
|
610
635
|
|
|
@@ -648,7 +673,7 @@ export interface RunContext {
|
|
|
648
673
|
}
|
|
649
674
|
```
|
|
650
675
|
|
|
651
|
-
The remaining `RunOptions` fields (`model`, `maxTurns`, `signal`, `
|
|
676
|
+
The remaining `RunOptions` fields (`model`, `maxTurns`, `signal`, `thinkingLevel`, `defaultMaxTurns`, `graceTurns`, `onSessionCreated`) are genuine execution parameters.
|
|
652
677
|
`RunOptions` now has 9 fields: 1 nested `context: RunContext` (2 per-call fields) plus 8 flat execution fields.
|
|
653
678
|
|
|
654
679
|
#### SessionConfig (11 fields → extract ToolFilterConfig) — done ([#168][168])
|
|
@@ -781,19 +806,22 @@ Removed `worktree.ts`, `worktree-isolation.ts`, `GitWorktreeManager`, and the `i
|
|
|
781
806
|
From the release carrying #272, all five workspace types are importable by name: `WorkspaceProvider`, `Workspace`, `WorkspacePrepareContext`, `WorkspaceDisposeOutcome`, and `WorkspaceDisposeResult`.
|
|
782
807
|
- Outcome: git leaves the core; worktree users install one package, everyone else pays nothing.
|
|
783
808
|
|
|
784
|
-
#### Step 4: Remove `isolated` / `extensions: false` / `noSkills` — [#264]
|
|
809
|
+
#### Step 4: Remove `isolated` / `extensions: false` / `noSkills` — [#264] ✅ Delivered
|
|
785
810
|
|
|
786
|
-
Children always load the parent's extensions and skills; the recursion guard
|
|
811
|
+
Children always load the parent's extensions and skills; the recursion guard is now unconditional.
|
|
787
812
|
Deny-at-use (the in-child permission layer) covers tool restriction; prevent-load is left as a latent provider seam (not shipped).
|
|
813
|
+
The `skills` curation axis collapsed symmetrically with `extensions`: `AgentConfig.skills`, the skill-preload path (`skill-loader.ts`, `safe-fs.ts`, `preloadSkills`, `PromptExtras`), `SessionConfig.{extensions,noSkills,extras}`, and the `isolated:` / `extensions:` / `skills:` custom-agent frontmatter keys are all gone.
|
|
788
814
|
|
|
789
|
-
-
|
|
790
|
-
- Outcome: the `isolated`/`extensions`/`noSkills` axis is gone;
|
|
815
|
+
- Depended on: Step 1 (deny-at-use over events).
|
|
816
|
+
- Outcome: the `isolated`/`extensions`/`noSkills`/`skills` axis is gone; the guard is unconditional.
|
|
791
817
|
|
|
792
|
-
#### Step 5: Born-complete child execution; dissolve the runner — [#265]
|
|
818
|
+
#### Step 5: Born-complete child execution; dissolve the runner — [#265] ✅ Delivered
|
|
793
819
|
|
|
794
|
-
|
|
795
|
-
`
|
|
796
|
-
|
|
820
|
+
`createSubagentSession()` is an assembly factory that returns a born-complete `SubagentSession` (session created, extensions bound, recursion guard applied).
|
|
821
|
+
`SubagentSession` owns turn driving (`runTurnLoop`/`resumeTurnLoop`), steering, and disposal.
|
|
822
|
+
`Agent.run()` is coordination, not assembly; `runAgent` / `resumeAgent` / `ConcreteAgentRunner` / `AgentRunner` / `RunOptions` / `RunResult` / `ExecutionState` dissolved.
|
|
823
|
+
`getAgentConversation()` relocated to `session/conversation.ts`; `normalizeMaxTurns()` to `lifecycle/turn-limits.ts`.
|
|
824
|
+
`disposed` now fires at true session disposal (cleanup), so resume executions are registry-detected (closing the gap deferred from #261).
|
|
797
825
|
|
|
798
826
|
- Depends on: Steps 2–4.
|
|
799
827
|
- Outcome: the "runner" concept is gone; `Agent.run()` is coordination, not assembly — the structural goal of the abandoned collaborator plan, reached cleanly.
|
|
@@ -889,7 +917,7 @@ If they land, upstream gains the peer-dep fix and the two RepOne patches.
|
|
|
889
917
|
This fork continues independently regardless.
|
|
890
918
|
|
|
891
919
|
Upstream fixes and ideas are cherry-picked when they align with this fork's scope.
|
|
892
|
-
The upstream test suite is run periodically as a regression canary for the
|
|
920
|
+
The upstream test suite is run periodically as a regression canary for the session assembly core.
|
|
893
921
|
|
|
894
922
|
[earendil-works/pi#4207]: https://github.com/earendil-works/pi/issues/4207
|
|
895
923
|
[gotgenes/pi-packages]: https://github.com/gotgenes/pi-packages
|
|
@@ -919,3 +947,4 @@ The upstream test suite is run periodically as a regression canary for the agent
|
|
|
919
947
|
[#263]: https://github.com/gotgenes/pi-packages/issues/263
|
|
920
948
|
[#264]: https://github.com/gotgenes/pi-packages/issues/264
|
|
921
949
|
[#265]: https://github.com/gotgenes/pi-packages/issues/265
|
|
950
|
+
[#277]: https://github.com/gotgenes/pi-packages/issues/277
|