@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.
Files changed (38) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/public.d.ts +1 -3
  3. package/docs/architecture/architecture.md +86 -57
  4. package/docs/plans/0264-remove-extension-lifecycle-control.md +275 -0
  5. package/docs/plans/0265-born-complete-subagent-session.md +330 -0
  6. package/docs/retro/0264-remove-extension-lifecycle-control.md +89 -0
  7. package/docs/retro/0265-born-complete-subagent-session.md +58 -0
  8. package/package.json +1 -1
  9. package/src/config/agent-types.ts +0 -2
  10. package/src/config/custom-agents.ts +0 -30
  11. package/src/config/default-agents.ts +1 -7
  12. package/src/config/invocation-config.ts +0 -3
  13. package/src/index.ts +3 -5
  14. package/src/lifecycle/agent-manager.ts +9 -10
  15. package/src/lifecycle/agent.ts +56 -55
  16. package/src/lifecycle/create-subagent-session.ts +242 -0
  17. package/src/lifecycle/subagent-session.ts +204 -0
  18. package/src/lifecycle/turn-limits.ts +13 -0
  19. package/src/runtime.ts +1 -1
  20. package/src/service/service-adapter.ts +0 -1
  21. package/src/service/service.ts +0 -1
  22. package/src/session/conversation.ts +49 -0
  23. package/src/session/prompts.ts +2 -23
  24. package/src/session/session-config.ts +10 -45
  25. package/src/settings.ts +1 -1
  26. package/src/tools/agent-tool.ts +0 -5
  27. package/src/tools/background-spawner.ts +0 -1
  28. package/src/tools/foreground-runner.ts +0 -1
  29. package/src/tools/get-result-tool.ts +1 -1
  30. package/src/tools/spawn-config.ts +1 -5
  31. package/src/types.ts +0 -7
  32. package/src/ui/agent-config-editor.ts +0 -5
  33. package/src/ui/agent-creation-wizard.ts +0 -4
  34. package/src/ui/display.ts +1 -2
  35. package/src/lifecycle/agent-runner.ts +0 -472
  36. package/src/lifecycle/execution-state.ts +0 -17
  37. package/src/session/safe-fs.ts +0 -45
  38. 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 (execution, notification) are attached
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
- AgentRunner["agent-runner<br/>(session, turns, results)"]
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 --> AgentRunner
91
- AgentRunner --> SessionConfig
89
+ AgentManager --> Agent
90
+ Agent --> CreateSubagentSession & SubagentSession
91
+ CreateSubagentSession --> SubagentSession
92
+ CreateSubagentSession --> SessionConfig
92
93
  SessionConfig --> AgentTypeRegistry
93
- SessionConfig --> Prompts & SkillLoader & Env
94
- SkillLoader --> SafeFs
94
+ SessionConfig --> Prompts & Env
95
95
  AgentTypeRegistry --> DefaultAgents & CustomAgents
96
- RecordObserver -.->|subscribes| AgentRunner
97
- UIObserver -.->|subscribes| AgentRunner
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
- +execution?: ExecutionState
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(session)
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 Runner as agent-runner
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->>Runner: runAgent(record, snapshot, options, io)
225
- Runner->>Asm: assembleSessionConfig(type, ctx, opts, env, registry, io)
226
- Asm-->>Runner: SessionConfig
227
- Runner->>Child: create session + run turn loop
228
- Child-->>Runner: result text
229
- Runner-->>Mgr: update Agent
230
- Note over Mgr: agent-observer subscribes to session events for stats
231
- Note over Mgr: ui-observer subscribes for streaming state
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
- │ ├── safe-fs.ts symlink rejection and safe file reads
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
- │ ├── agent-runner.ts session creation, turn loop, tool filtering
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, agent-runner"]
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
- - `agent-runner` — session creation, turn loop, extension binding.
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 (extracted from `agent-runner`).
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`, `isolated`, `inheritContext`, `foreground`, `bypassQueue`.
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, skill preloading into prompt.
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 becomes unconditional rather than gated on `cfg.extensions`.
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`) — deny-at-use (the in-child permission layer blocking disallowed tool calls) covers what `isolated` pretended to do for tools.
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 | Fields | Consumers | Severity |
540
- | --------------------------- | ------------------------------------------------------ | ------------------------------------------------- | --------- |
541
- | `ResolvedSpawnConfig` | 3 nested | foreground-runner, background-spawner, agent-tool | ✓ done |
542
- | `AgentSpawnConfig` | 13 → 13 (ParentSessionInfo nested) | agent-manager (internal) | ✓ done |
543
- | `RunOptions` | 9 (`RunContext` nested) | agent-runner | ✓ done |
544
- | `SessionConfig` | 8 (flat fields, ToolFilterConfig removed) | agent-runner (output of assembler) | ✓ done |
545
- | `NotificationDetails` | 10 | notification | Low (DTO) |
546
- | `ResourceLoaderOptions` | 10 | agent-runner (SDK bridge) | Low (SDK) |
547
- | `RunnerIO` | split `EnvironmentIO` (3) + `SessionFactoryIO` (5+1) | agent-runner | ✓ done |
548
- | `CreateSessionOptions` | 9 | agent-runner (SDK bridge) | Low (SDK) |
549
- | `AgentToolDeps` | 8 | agent-tool | done |
550
- | `AgentMenuDeps` | 8 | agent-menu | ✓ done |
551
- | `ConversationViewerOptions` | 8 | conversation-viewer | Low |
552
- | `AgentInit` | 8 | agent | Low |
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`, `isolated`, `thinkingLevel`, `defaultMaxTurns`, `graceTurns`, `onSessionCreated`) are genuine execution parameters.
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 becomes unconditional.
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
- - Depends on: Step 1 (deny-at-use over events).
790
- - Outcome: the `isolated`/`extensions`/`noSkills` axis is gone; one fewer conditional in the guard.
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
- With the cwd resolved through the provider seam (not relayed by `Agent`), child-session creation produces a born-complete execution (`{ session, outputFile?, dispose() }`).
795
- `Agent` owns session interaction directly (prompt, steer, abort, resume, turn limits, response collection); `runAgent` / `resumeAgent` / `ConcreteAgentRunner` / `RunOptions` / `RunResult` dissolve.
796
- Retain `getAgentConversation()` and `normalizeMaxTurns()`.
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 agent-runner core.
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