@fishwithcat/dsh-subagent 0.0.0-stage → 0.2.2-alpha.3

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 (59) hide show
  1. package/README.i18n.yaml +121 -0
  2. package/README.md +258 -2
  3. package/README.zh.md +259 -0
  4. package/lib/index.js +3065 -0
  5. package/lib/typert.host.d.ts +3 -0
  6. package/lib/typert.host.js +1086 -0
  7. package/lib/typert.remote-client.d.ts +29 -0
  8. package/lib/typert.remote-client.js +122 -0
  9. package/lib/types/activation.d.ts +110 -0
  10. package/lib/types/activation.js +112 -0
  11. package/lib/types/archive-admission.d.ts +23 -0
  12. package/lib/types/archive-admission.js +75 -0
  13. package/lib/types/assistant-output.d.ts +48 -0
  14. package/lib/types/assistant-output.js +73 -0
  15. package/lib/types/catalog.d.ts +87 -0
  16. package/lib/types/catalog.js +113 -0
  17. package/lib/types/child-agent.d.ts +145 -0
  18. package/lib/types/child-agent.js +229 -0
  19. package/lib/types/client.d.ts +8 -0
  20. package/lib/types/client.js +7 -0
  21. package/lib/types/continuation-messages.d.ts +66 -0
  22. package/lib/types/continuation-messages.js +116 -0
  23. package/lib/types/control-types.d.ts +121 -0
  24. package/lib/types/control-types.js +8 -0
  25. package/lib/types/control.d.ts +41 -0
  26. package/lib/types/control.js +75 -0
  27. package/lib/types/depth.d.ts +31 -0
  28. package/lib/types/depth.js +39 -0
  29. package/lib/types/descriptor.d.ts +105 -0
  30. package/lib/types/descriptor.js +192 -0
  31. package/lib/types/error.d.ts +11 -0
  32. package/lib/types/error.js +14 -0
  33. package/lib/types/index.d.ts +282 -0
  34. package/lib/types/index.js +398 -0
  35. package/lib/types/lifecycle.d.ts +54 -0
  36. package/lib/types/lifecycle.js +89 -0
  37. package/lib/types/list-children.d.ts +36 -0
  38. package/lib/types/list-children.js +166 -0
  39. package/lib/types/manager.d.ts +215 -0
  40. package/lib/types/manager.js +1171 -0
  41. package/lib/types/out-of-process.d.ts +92 -0
  42. package/lib/types/out-of-process.js +177 -0
  43. package/lib/types/projection-types.d.ts +93 -0
  44. package/lib/types/projection-types.js +7 -0
  45. package/lib/types/projection.d.ts +94 -0
  46. package/lib/types/projection.js +157 -0
  47. package/lib/types/structured.d.ts +49 -0
  48. package/lib/types/structured.js +130 -0
  49. package/lib/types/types.d.ts +331 -0
  50. package/lib/types/types.js +17 -0
  51. package/locale/de.json +6 -0
  52. package/locale/en.json +5 -0
  53. package/locale/es.json +6 -0
  54. package/locale/fr.json +6 -0
  55. package/locale/ja.json +6 -0
  56. package/locale/pt.json +6 -0
  57. package/locale/ru.json +6 -0
  58. package/locale/zh.json +6 -0
  59. package/package.json +131 -4
@@ -0,0 +1,121 @@
1
+ # Bilingual-pair consistency record for README.md (docs/i18n/README.md): per heading
2
+ # section, a hash of its English and Chinese blocks outside code blocks and generated regions.
3
+ # After editing either side, bring the other along and re-record with:
4
+ # pnpm run verify-translation-pairing --write packages/subagent/subagent/README.md
5
+ /:
6
+ en: 384d01a27a111f49
7
+ zh: fbadc6917c3099c9
8
+ /deepseek-ai-dsh-subagent:
9
+ en: 425344cec61f5c70
10
+ zh: 48e8f2a2e3c1f418
11
+ /deepseek-ai-dsh-subagent/summary:
12
+ en: 6c90e012a583b27f
13
+ zh: 2ec29c0e91fdef60
14
+ /deepseek-ai-dsh-subagent/table-of-contents:
15
+ en: d152484eb41ac6b4
16
+ zh: 09388d293f9be9cb
17
+ /deepseek-ai-dsh-subagent/use-this-package:
18
+ en: 924b8c15f9529028
19
+ zh: 9fb0c399b5a79e3e
20
+ /deepseek-ai-dsh-subagent/use-this-package/enabling-delegation:
21
+ en: 025605eddae02478
22
+ zh: 5659cba4340735d8
23
+ /deepseek-ai-dsh-subagent/use-this-package/delegation-settings:
24
+ en: 86c982223fab1a3a
25
+ zh: 3d220d8ed84eab9a
26
+ /deepseek-ai-dsh-subagent/use-this-package/activation-capacity:
27
+ en: 20093dab58cd4909
28
+ zh: 10d10db250c9e4c9
29
+ /deepseek-ai-dsh-subagent/use-this-package/delegated-approval-policy:
30
+ en: 74e2486bed4b9b20
31
+ zh: 32102b1847731d35
32
+ /deepseek-ai-dsh-subagent/use-this-package/local-and-external-children:
33
+ en: 191ef1dabe2fce7c
34
+ zh: f799fdcbb5c5a171
35
+ /deepseek-ai-dsh-subagent/use-this-package/child-presets:
36
+ en: a740e5e9bdd661d9
37
+ zh: 712a5458fc8b3615
38
+ /deepseek-ai-dsh-subagent/use-this-package/messaging-interrupting-and-discovering:
39
+ en: bf3175c2218a16dd
40
+ zh: 4be9271efe71ddb7
41
+ /deepseek-ai-dsh-subagent/use-this-package/failure-and-recovery:
42
+ en: 0dc416ded19e304e
43
+ zh: 4726e5fe5f188709
44
+ /deepseek-ai-dsh-subagent/understand-the-implementation:
45
+ en: 74d91b364b23f88d
46
+ zh: 19cc558105efe8df
47
+ /deepseek-ai-dsh-subagent/understand-the-implementation/design-concept:
48
+ en: e6f77fc75a73b0ab
49
+ zh: 7133698a3923e192
50
+ /deepseek-ai-dsh-subagent/understand-the-implementation/source-map:
51
+ en: 5923a61c09d9ae04
52
+ zh: 15202a92872a11e9
53
+ /deepseek-ai-dsh-subagent/understand-the-implementation/provider-preparation-and-structured-output:
54
+ en: 61cddba23f4e7d1c
55
+ zh: 052c8331a747403f
56
+ /deepseek-ai-dsh-subagent/understand-the-implementation/activation-settlement:
57
+ en: fc8938de925b1a97
58
+ zh: b50e1f948d60b93c
59
+ /deepseek-ai-dsh-subagent/understand-the-implementation/restoring-child-composition:
60
+ en: 843f9f4319ca2ae3
61
+ zh: 218bf355816d4ff6
62
+ /deepseek-ai-dsh-subagent/understand-the-implementation/ownership-and-invariants:
63
+ en: ab5d2c41f06b8fea
64
+ zh: 13a9ca3685fa799b
65
+ /deepseek-ai-dsh-subagent/further-exploration:
66
+ en: 86a3e3ad13e29989
67
+ zh: e5138d34086252b2
68
+ /deepseek-ai-dsh-subagent/model-experience:
69
+ en: 215e7ba838619b7b
70
+ zh: a311da3843709f90
71
+ /deepseek-ai-dsh-subagent/model-experience/settlement-notice:
72
+ en: f7cec22ba9d3fb4f
73
+ zh: 67b1d40f9b136f71
74
+ /deepseek-ai-dsh-subagent/model-experience/settlement-notice/what-the-model-sees:
75
+ en: d5e6377fabfee1ca
76
+ zh: f5c442401264a60d
77
+ /deepseek-ai-dsh-subagent/model-experience/settlement-notice/token-effect:
78
+ en: f98ad834e8ce8950
79
+ zh: cf509805dd934094
80
+ /deepseek-ai-dsh-subagent/model-experience/settlement-notice/kv-cache-effect:
81
+ en: d6b1d618083da79b
82
+ zh: 9a28942b7d53c382
83
+ /deepseek-ai-dsh-subagent/model-experience/continuable-child-return-guidance:
84
+ en: 710ebcdce8e283e2
85
+ zh: cc07cf31e572b0cf
86
+ /deepseek-ai-dsh-subagent/model-experience/continuable-child-return-guidance/what-the-model-sees:
87
+ en: c4fd0220e51f1f20
88
+ zh: 0dc2a3ab3aced3eb
89
+ /deepseek-ai-dsh-subagent/model-experience/continuable-child-return-guidance/what-the-model-sees/return-guidance:
90
+ en: 24538ab91a15b0e4
91
+ zh: 86f96219c94ee1b1
92
+ /deepseek-ai-dsh-subagent/model-experience/continuable-child-return-guidance/token-effect:
93
+ en: 889c86126ff12689
94
+ zh: 67162193846cf83f
95
+ /deepseek-ai-dsh-subagent/model-experience/continuable-child-return-guidance/kv-cache-effect:
96
+ en: 7078382a73f743f7
97
+ zh: 1431825f5568a96b
98
+ /deepseek-ai-dsh-subagent/model-experience/child-delegation-scope-statement:
99
+ en: dc8544657916e194
100
+ zh: b0feff0764b5d903
101
+ /deepseek-ai-dsh-subagent/model-experience/child-delegation-scope-statement/what-the-model-sees:
102
+ en: 6e96e474c7a8f95c
103
+ zh: b69a8bc8042c2dca
104
+ /deepseek-ai-dsh-subagent/model-experience/child-delegation-scope-statement/what-the-model-sees/the-delegation-scope-statement-under-never:
105
+ en: 157378eaa0d5c0e6
106
+ zh: 45fb879d4c3e99c2
107
+ /deepseek-ai-dsh-subagent/model-experience/child-delegation-scope-statement/what-the-model-sees/the-delegation-scope-statement-under-ask:
108
+ en: e7fdbf3fbafb700b
109
+ zh: 704da32c0e6d9ee7
110
+ /deepseek-ai-dsh-subagent/model-experience/child-delegation-scope-statement/token-effect:
111
+ en: 4e0b922b186dc2a9
112
+ zh: 7453563417c5b9a2
113
+ /deepseek-ai-dsh-subagent/model-experience/child-delegation-scope-statement/kv-cache-effect:
114
+ en: 59e848fca82a46fb
115
+ zh: fcd6a8a2bb58609f
116
+ /deepseek-ai-dsh-subagent/known-limitations-and-deferred-work:
117
+ en: 746c75e25114ab8b
118
+ zh: 168d577f1fcc4281
119
+ /deepseek-ai-dsh-subagent/known-limitations-and-deferred-work/dev-note:
120
+ en: 25cc0909348666bb
121
+ zh: 95517f12de100049
package/README.md CHANGED
@@ -1,3 +1,259 @@
1
- # Temporary Holding Version
1
+ ---
2
+ description: "The subagent delegation seam for users and maintainers choosing a provider backend, composing delegation tools, or debugging child-agent runs."
3
+ kind: "package-reference"
4
+ ---
2
5
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
6
+ # @deepseek-ai/dsh-subagent
7
+
8
+ English | [中文](README.zh.md)
9
+
10
+ ## Summary
11
+
12
+ Use `dsh-subagent` to delegate work through named providers and collect managed activation results. Local spawn and fork children retain durable sessions for later messages; ACP, DSH SDK, Codex, and Claude Code execute once. Every child shares admission, cancellation, ownership, and discovery. Compose the service with a provider and a delegation tool.
13
+
14
+ ## Table of Contents
15
+
16
+ - [Use this package](#use-this-package)
17
+ - [Understand the implementation](#understand-the-implementation)
18
+ - [Further Exploration](#further-exploration)
19
+ - [Model Experience](#model-experience)
20
+ - [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
21
+ - [Dev Note](#dev-note)
22
+
23
+ -----
24
+
25
+ <a id="use-this-package"></a>
26
+ ## Use this package
27
+
28
+ Each start accepts an optional `cwd`; relative paths resolve against the parent's current working directory, and omission captures that current directory. The child keeps its parent's origin metadata and permission roots. A child-owned directory value follows any inherited history, survives continuation and restart, and is independent of later parent changes.
29
+
30
+ This package is the contract every delegation setup shares. You enable it by mounting the service together with one or more provider backends and the model-facing delegation tool; from then on, an agent can delegate work and the service routes each request to the named provider.
31
+
32
+ ### Enabling delegation
33
+
34
+ Mount the service with `@deepseek-ai/dsh-session-projection`, a provider, and the delegation tool; the service waits for the projection registry before initializing. The provider registers under its configured name; each tool row selects one provider. A minimal setup:
35
+
36
+ ```yaml
37
+ - name: '@deepseek-ai/dsh-subagent'
38
+ - name: '@deepseek-ai/dsh-subagent-spawn-in-process'
39
+ - name: '@deepseek-ai/dsh-tool-subagent'
40
+ config:
41
+ provider: spawn
42
+ toolName: subagent
43
+ ```
44
+
45
+ The tool returns a child session id immediately. The parent receives a completion notice when the background activation settles. Mounting the service alone enables no delegation.
46
+
47
+ ### Delegation settings
48
+
49
+ The limits section on the **Plugins → Subagent** page edits the Host’s `subagent` settings section. User values override this plugin's composition; reset removes the user override. `maxDepth` defaults to `1` and supplies the delegation tools' depth when their own configuration omits it. An explicit tool depth, including `provider-managed`, takes precedence. Depth `0` disables delegation through tools inheriting this setting; depth `1` permits direct children only. Changes apply on the next delegation attempt. Direct service callers continue to supply their own optional request depth.
50
+
51
+ ### Activation capacity
52
+
53
+ Set `maxActiveSubagents` on the host plugin to limit live and materializing children in each subagent tree. It defaults to `8` and accepts positive safe integers. A top-level parent starts a pool shared by its local and external descendants; the root parent consumes no slot. Creation and cold resume reserve before yielding, and disposal returns the slot only after cleanup. Instances with pending inbox work and stopping activations remain counted. Sending to a resident child reuses its slot. Delegation depth is a separate policy.
54
+
55
+ The current `maxActiveSubagents` value is sampled before every new or cold-resumed Activation. Raising it admits more children in existing trees; lowering it leaves resident children running and refuses further admissions until usage is below the limit.
56
+
57
+ ### Delegated approval policy
58
+
59
+ Every in-process child created with the approval capability composed records an `approval/policy` event with `source: 'delegation'` before publication. `delegatedApproval: 'never'` (the default) pins every ask to deterministic rejection, so an unattended child acts only inside the sandbox scope captured at delegation. `'inherit'` seeds the parent's current effective policy instead, letting a surface that also answers descendant Agents decide a child's escalation; the sandbox scope stays fixed and each grant remains one-shot. A parent running under `never` passes `never` to its children either way.
60
+
61
+ At capacity, creation or cold resume rejects with `ACTIVATION_LIMIT_REACHED` (browser prompts receive `subagent/delivery-unavailable`): wait for a child to finish or continue using the existing agents. Admission does not queue, because a parent waiting for descendants must not wait for its own occupied slot. Slots are process-local and do not constrain cumulative Session history or token usage.
62
+
63
+ ### Local and external children
64
+
65
+ `startActivation({ provider, label, prompt, parent, signal, delivery })` returns `{ childId, messageId?, result, dispose }`. Supplying `childId` selects a local backend and guarantees `messageId`. Local children accept later messages and can cold-resume; external children expose one execution and reject continuation. `agentOptions` overrides supported child model settings. `delivery: 'parent'` supplies the model-facing completion notice; `delivery: 'caller'` lets workflows await the result without a parent notice or initial return guidance. Local parent delivery requires persistence; caller delivery can use an ephemeral local session. Cold resume requires persistence and Session query.
66
+
67
+ `rootOf(agent)` resolves a managed local Agent through its existing Activation and checks the exact live child and root instances. Intermediate creators can leave without changing that root; same-id replacements cannot inherit membership. Ordinary live Agents resolve to themselves, while unmanaged delegated Agents are rejected. The query does not activate Sessions.
68
+
69
+ ### Child presets
70
+
71
+ In-process spawn accepts an independent `agentPreset`; fork and external backends reject this option. Without a selection, a local child joins the parent's current preset revision. An explicit id mounts the currently available revision, even when that id matches the parent's. Configure model choices through [`dsh-tool-subagent`](../tool-subagent/README.md#selecting-a-child-preset) and persona and tools in the [preset composition](../../preset/agent-preset-registry/README.md). Cold resume preserves persona and tool restrictions recorded in historical child descriptors.
72
+
73
+ ### Messaging, interrupting, and discovering
74
+
75
+ `sendMessage()` lets the live root and resident continuable subagents contact any other root or continuable member in the same tree by Session id. The target receives Steer input at its next step or starts an idle turn. Only the cold target resumes, under the subagent tree root; its creation ancestors stay offline and the message retains its actual sender. `rootOf()` resolves the caller’s live root. Agent interruption requires ancestor authority. Browser prompts and user interrupts address only the child Session; the Gateway checks the corresponding action on that Session before any side effect. Parent or global grants do not imply child access. Prompts require a live subagent tree root; the creator may be offline. User interrupts perform no restoration and accept absent targets as no-ops. They select Queue or Steer and admit image batches through the attachment store; incompatible target models reject images. `listDescendants()` discovers members recursively through parent-owned `subagentCatalog` projections. It preserves catalog order, reads each reachable Session once, skips external leaves, and reports unreadable branches without activating Agents.
76
+
77
+ ### Failure and recovery
78
+
79
+ Starting without the `agents` service rejects with `CONTINUATION_UNAVAILABLE`; an available runtime rejects a missing or replaced parent with `UNAUTHORIZED`. Providers implementing neither execution method are rejected at registration with `UNSUPPORTED_CAPABILITY`; unsupported requested capabilities reject creation with the same code. If a provider is removed or replaced while directory resolution is pending, creation rejects with `PROVIDER_CHANGED` before invoking either provider; retry the delegation against the current registration. The caller signal cancels only unpublished work; after publication, `dispose()` cancels the exact activation and waits for its resource cleanup. Creation descendants continue independently; hosts must await `drainDescendants([root])` before disposing the root handle to stop all members and await pending startup. `result` settles after teardown and notifications, carrying output, optional structured data, and a stop reason; capture failures reject it after teardown. Cleanup failures reject `dispose()` and mark the lifecycle end as failed; the result promise and parent notification retain the captured execution result.
80
+
81
+ -----
82
+
83
+ <a id="understand-the-implementation"></a>
84
+ ## Understand the implementation
85
+
86
+ <details>
87
+ <summary>Implementation internals — click to expand</summary>
88
+
89
+ This section explains how the service is built and where the observable behavior comes from; the full contract lives in [Use this package](#use-this-package).
90
+
91
+ ### Design concept
92
+
93
+ - **One service, many providers.** The service is a named-provider registry; each backend registers under a unique name and a request picks one by name.
94
+ - **One managed lifetime.** `SubagentManager` owns startup, message admission, capacity, runtime ownership, and disposal. Each activation retains its lifecycle identity and a local AgentHandle or external SubagentRun; the manager publishes paired events through the service's scoped emitter. Local inbox and idle state belong only to the local variant.
95
+ - **Fulfillment is publication.** `startActivation()` returns only after the child is accepted and its handle can cancel that exact execution.
96
+ - **Trusted same-process values.** Requests, descriptors, and results are borrowed immutable; serialization and hostile-input validation belong at process and wire boundaries.
97
+
98
+ ### Source map
99
+
100
+ | File | Role |
101
+ |---|---|
102
+ | [`src/index.ts`](src/index.ts) | Service entry: provider registry, start and continuation API, lifecycle events |
103
+ | [`src/manager.ts`](src/manager.ts) | Unified startup, message admission, cold resume, runtime ownership, settlement, and disposal |
104
+ | [`src/activation.ts`](src/activation.ts) | Execution records, capacity slots, child locks, and local output capture |
105
+ | [`src/continuation-messages.ts`](src/continuation-messages.ts) | Agent messages, return guidance, and settlement notices |
106
+ | [`src/structured.ts`](src/structured.ts) | Activation-scoped structured capture and guards |
107
+ | [`src/types.ts`](src/types.ts) | Public request, result, and provider contracts |
108
+ | [`src/descriptor.ts`](src/descriptor.ts) | Versioned `subagent/descriptor` session-event vocabulary |
109
+ | [`src/catalog.ts`](src/catalog.ts) | Parent-owned `subagent/catalog` event and chunked host projection |
110
+ | [`src/child-agent.ts`](src/child-agent.ts) | Child composition, delegated policy, depth helpers |
111
+ | [`src/list-children.ts`](src/list-children.ts) | Direct and recursive parent-catalog reads |
112
+ | [`src/control.ts`](src/control.ts) | Browser control request validation and stable failure codes |
113
+ | [`src/control-types.ts`](src/control-types.ts) | Client-safe catalog row, control requests, receipts, and failures |
114
+ | [`src/archive-admission.ts`](src/archive-admission.ts) | The `subagent` family of the Workspace registry's archive admission: running descendants and their parent-cause cancel |
115
+
116
+ ### Provider preparation and structured output
117
+
118
+ The service validates requested capabilities and binds execution to that exact provider instance before creation. The manager receives the bound operation rather than a provider lookup. Local providers supply only `prepareContinuable()`: spawn returns fresh state and fork returns a completed-turn seed. The manager captures the parent model settings, delegated permissions, and composition before creating the child. External providers retain `start()` as a transport adapter and retain their own permission systems. The common manager owns their published execution. Structured tools, instructions, validation, and terminal guards belong to one local activation; they are not persisted as resume configuration. The child can submit its structured result after consuming accepted input. Work that depends on descendants must explicitly wait for their results. Staging a result closes further input through tool-result policy and any enclosing PTC execution; a rejected result reopens input, while a committed result keeps it closed. Later cold resume has no structured schema.
119
+
120
+ External providers mint a fresh `SubagentRun.id` for each execution in the runtime's shared Session id namespace, across all parents and providers. A collision with a resident Agent, Session, or activation rejects startup with `DUPLICATE_CHILD` and disposes the new external handle without replacing the existing execution.
121
+
122
+ ### Activation settlement
123
+
124
+ The manager reserves child identity and capacity, materializes a local Agent or external execution, and accepts the initial task. Local admission closes after Agent activity and pending input finish, with activity revalidated after the final Session flush. Both local and external activations deliver their result after handle cleanup, capacity release, and settlement notifications. Host waits on the subagent tree root join progressing members and their cleanup, including failed executions; idle members with parked input remain resident without delaying host completion. Ordinary members do not wait for descendants. Closing admission and disposing the handle prevent late work from entering a released Agent. Parent delivery emits its notice after settlement only if the creator is still online; caller delivery leaves collection to the awaiting workflow. Headless hosts repeat `agent.whenIdle()` and `waitForTreeWork(agent)` until no child work remains and the parent stays idle with an unchanged Session sequence across the child check, so completion notices can produce the final parent answer.
125
+
126
+ Settlement attribution records the exact execution stop reason without altering model-facing notice content. Historical notices can omit this field; readers must not infer it from the English summary.
127
+
128
+ A local Agent failure without a subsequently committed `turn/end` settles as `error` independently of its descendants. Unclaimed input cannot keep that failed activation resident. A later committed turn ending supersedes the live failure and supplies the recovered outcome.
129
+
130
+ Successful local creation appends a `subagent/catalog` fact to the parent Session regardless of result delivery. External creation appends a catalog fact only with `delivery: 'parent'`; caller-owned external executions retain their caller's membership records. External entries use `mode: 'external'` to identify children without a local Session. Catalog entries record membership once at creation and carry no execution status. Complete results go to the caller or the parent completion notice. Projections exclude inherited facts. Direct lists read one parent projection, so completed local workflow children remain discoverable and can be opened or continued. Catalog payload v0 records local modes; v1 also accepts unknown mode; v2 records external executions. Readers support all three versions. Historical migration appends a v1 `subagent/catalog` from a readable child header when its descriptor is unavailable; local creation retains v0. Its `mode: 'unknown'` projection keeps the child visible without claiming continuation support; an existing complete entry remains authoritative.
131
+
132
+ <a id="restoring-child-composition"></a>
133
+ ### Restoring child composition
134
+
135
+ Cold resume mounts the target's saved preset from its `agentPreset` projection or creation header without reading its creator's current composition. A missing or broken saved preset rejects restoration. The original subagent provider need not remain registered.
136
+
137
+ Targets without a saved preset use the host composition and retain their historical descriptor's persona and tool restrictions. Persisted permission policies replay from the target's own log. Restoration uses the currently registered preset definition, without preserving an earlier revision across restarts.
138
+
139
+ ### Ownership and invariants
140
+
141
+ - **The manager owns accepted work** — unpublished failures roll back; published handles cancel and release only their exact activation. Every instance belongs to the subagent tree root; creation parent ids remain unchanged.
142
+ - **Registration is effect-scoped** — removing a provider blocks new starts but never revokes accepted runs.
143
+ - **Agent-message authority follows the tree** — the exact live sender and target must belong to one root. Cold delivery verifies the target descriptor and creation catalogs before restoring only the target. Final inbox admission rechecks the sender and subagent tree root; failed restoration releases the new instance.
144
+ - **The descriptor is log-only** — a session event absent from model history and retained across compaction; the writer records the resolved child provider, model, and reasoning effort for cold resume. Historical one-shot descriptors remain readable.
145
+ - **This runtime answers archive admission for children** ([seam](../../workspace/workspace/README.md)) — activity queries, parent-cause cancellation, and pre-step rejection use managed creation ancestors even after an intermediate creator goes offline. Agents without a published Activation use live header ancestry; ordinary forks remain independent. Labels use the current identity projection's latest descriptor only when it belongs to the child's own log; missing, invalid, inherited, or unlabelled identities report only the id. Reporting requires no Session query service and starts after identity projection registration. Each cancellation failure is contained. The Agent registry owns the parent’s turn, job providers own jobs, and the API Session Controller checks archived Sessions and available header ancestry.
146
+
147
+ </details>
148
+
149
+ -----
150
+
151
+ <a id="further-exploration"></a>
152
+ ## Further Exploration
153
+
154
+ Read these pages when the package-level contract is not enough. They move from the shared seam to the backends, the model-facing tools, and the design decisions.
155
+
156
+ - [Subagent subsystem](../../../docs/subsystems/subagent.md) — the service contract, provider contract, and terminal result semantics.
157
+ - [historical Subagent capability seam](../../../.agents/notes/archived/feature/2026-06-21-subagent-capability-seam.md) — the design record for the delegation capability family.
158
+ - [Continuable subagents](../../../.agents/notes/implemented/feature/2026-07-28-continuable-subagent-conversations.md) — durable children that accept follow-up turns.
159
+ - [In-process spawn backend](../subagent-spawn-in-process/README.md) — the simplest provider to compose.
160
+ - [Auto review](../../experimental/auto-review/README.md) — the current-session authorization mode inherited only by in-process DSH children.
161
+ - [Interactive delegated approvals](../../../.agents/notes/implemented/architecture/2026-10-22-interactive-delegated-approvals.md) — why the TUI answers live descendants while the package default stays non-interactive.
162
+ - [Out-of-process ACP backend](../subagent-acp/README.md) — children with their own runtime over the Agent Client Protocol.
163
+ - [DeepSeek input conversion](../../llm/llm-deepseek/README.md#model-experience) — provider replay rules for saved settlement notices.
164
+ - [tool-subagent-control README](../tool-subagent-control/README.md) — the follow-up, interrupt, and listing surface.
165
+
166
+ -----
167
+
168
+ <a id="model-experience"></a>
169
+ ## Model Experience
170
+
171
+ ### Settlement notice
172
+
173
+ #### What the model sees
174
+
175
+ Parent delivery sends a user-role status notice to the resident direct parent in the same tree, including an idle parent. It does not restore an offline parent. The notice contains the child’s nonempty final text blocks. When the child's last action before that text was a message to its parent, with no input claimed and no tool call logged after it, the notice replaces them with `It sent you a message just before finishing, so its closing message is omitted.`; the parent recovers omitted closing text only by messaging the child again. External notices also state that further messages are unsupported. Reasoning and other nontext blocks are excluded. Every parent notice includes available structured output as `Structured result: <JSON>` and the provider’s safe diagnostic as a separate text block. Empty closing text is reported as `It left no closing message.` Caller delivery emits no notice; SDK lifecycle notifications retain complete child output when cleanup succeeds.
176
+
177
+ #### Token effect
178
+
179
+ One notice per settled activation using parent delivery. Caller delivery adds no completion message; its consumer owns result presentation.
180
+
181
+ #### KV Cache effect
182
+
183
+ Append-only in the parent: the notice follows its reusable request prefix. Reaching an idle parent starts one independent model request; reaching a busy one does not.
184
+
185
+ ### Continuable child return guidance
186
+
187
+ #### What the model sees
188
+
189
+ Local children using `delivery: 'parent'` receive the result-delivery guidance below in their initial task, whether or not messaging tools are installed. Tool usage and communication identity belong to [tool-subagent-control](../tool-subagent-control/README.md).
190
+
191
+ ##### Return guidance
192
+
193
+ ```markdown
194
+ Your final answer is delivered automatically if your parent is still online. Include the result and relevant evidence in that answer; the parent does not receive your full transcript, tool output, or reasoning. If your last action is a message to your parent, the completion notice omits your final answer; include the result and relevant evidence in that message.
195
+ ```
196
+
197
+ #### Token effect
198
+
199
+ One fixed guidance block per local parent-delivered child's initial task; caller delivery adds none.
200
+
201
+ #### KV Cache effect
202
+
203
+ The guidance remains in the child's retained task history. It does not change the parent's system prompt.
204
+
205
+ ### Child delegation-scope statement
206
+
207
+ #### What the model sees
208
+
209
+ Every in-process child's runtime-context snapshot carries the `subagent:delegation` statement matching its effective approval policy, after the sandbox-policy and approval-policy sentences.
210
+
211
+ ##### The delegation-scope statement under `never`
212
+
213
+ ```markdown
214
+ You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the job needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it.
215
+ ```
216
+
217
+ ##### The delegation-scope statement under `ask`
218
+
219
+ ```markdown
220
+ You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session. An operation that needs access beyond that scope may request approval from the user, who can allow or reject it. Do not retry a rejected or denied operation; state the limitation in your reply so the delegating agent can handle it.
221
+ ```
222
+
223
+ #### Token effect
224
+
225
+ One fixed statement in each child's runtime-context snapshot; none in the parent's requests.
226
+
227
+ #### KV Cache effect
228
+
229
+ Prefix-stable within a child: the statement never changes during the child's lifetime, so it is written once into the first runtime-context snapshot. Parent-side, no direct invalidation; the named tool consumers own any request-prefix changes.
230
+
231
+ ## Known Limitations and Deferred Work
232
+
233
+ <a id="known-limitations-and-deferred-work"></a>
234
+
235
+
236
+ These limits define when the seam is a poor fit or needs special operational care. They are current package constraints, not a general delegation comparison or a task backlog.
237
+
238
+ - **Descendant reads are sequential** — each reachable catalog, including one-shot children, takes one observation. A cold Session without a valid prepared observation requires a full-log read; large cold trees can accumulate storage latency.
239
+ - **External children execute once** — ACP, DSH SDK, Codex, and Claude Code have no local child Session and accept no follow-up input. Their parent-owned records remain discoverable after disposal.
240
+ - **Messaging stays within one tree** — targets use Session ids and must be the root or continuable members. Only the restored target consumes activation capacity. Browser prompts retain their separate human Queue-or-Steer control path.
241
+ - **Wake gap during cancellation convergence** — a follow-up accepted after an interrupt signal but before the Agent becomes idle stays queued until another waking send.
242
+ - **Pending injected context retains an Activation** — settlement conservatively treats every Inbox occurrence as unfinished. Context parked after the Agent becomes idle keeps the child and its live ancestors resident until a waking delivery claims it, a queue mutation removes it, or manager teardown discards it. Host completion joins active work, pending child creation, and resource cleanup, but does not wait for a subtree containing only idle parked inboxes; it neither completes those activation results nor discards their messages.
243
+ - **Process-local residency** — the Activation inbox and ownership graph do not coordinate two harness processes; concurrent access to one persistence store needs a durable mailbox and cross-process lease protocol.
244
+ - **No replay of accepted-but-unlogged messages** — a crash can lose an accepted prompt that never reached the child's session log; the lost message is not replayed automatically.
245
+ - **Lifecycle events are observe-only** — a run-affecting `subagent/end` continuation or decision API waits for a concrete consumer.
246
+
247
+ <a id="dev-note"></a>
248
+ ### Dev Note
249
+
250
+ <details>
251
+ <summary>Working context for maintainers — click to expand</summary>
252
+
253
+ This Dev Note is working context for maintainers: open questions and undecided directions. It is explicitly non-authoritative — shipped behavior and limits live in the sections above and in the package code.
254
+
255
+ - **Cross-process continuation** — a durable mailbox and lease protocol would let two harness processes share one persistence store.
256
+ - **Continuable ACP children** — requires persisting the remote session id and a per-child continuation advertisement.
257
+ - **Host-user delivery** — a future host adapter needs a concrete authenticated interaction before the seam gains a user delivery capability.
258
+
259
+ </details>