apex-code 0.0.5 → 0.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 (257) hide show
  1. package/CHANGELOG.md +40 -1
  2. package/README.md +7 -8
  3. package/dist/cli/agent-lifecycle.d.ts +24 -0
  4. package/dist/cli/agent-lifecycle.d.ts.map +1 -0
  5. package/dist/cli/agent-lifecycle.js +126 -0
  6. package/dist/cli/agent-lifecycle.js.map +1 -0
  7. package/dist/cli/args.d.ts +13 -12
  8. package/dist/cli/args.d.ts.map +1 -1
  9. package/dist/cli/args.js +80 -30
  10. package/dist/cli/args.js.map +1 -1
  11. package/dist/cli.d.ts.map +1 -1
  12. package/dist/cli.js +4 -130
  13. package/dist/cli.js.map +1 -1
  14. package/dist/config.d.ts +1 -1
  15. package/dist/config.d.ts.map +1 -1
  16. package/dist/config.js +1 -1
  17. package/dist/config.js.map +1 -1
  18. package/dist/core/agent-session-services.d.ts.map +1 -1
  19. package/dist/core/agent-session-services.js +0 -8
  20. package/dist/core/agent-session-services.js.map +1 -1
  21. package/dist/core/agent-session.d.ts +160 -0
  22. package/dist/core/agent-session.d.ts.map +1 -1
  23. package/dist/core/agent-session.js +265 -0
  24. package/dist/core/agent-session.js.map +1 -1
  25. package/dist/core/delegation/agents.d.ts.map +1 -1
  26. package/dist/core/delegation/agents.js +2 -1
  27. package/dist/core/delegation/agents.js.map +1 -1
  28. package/dist/core/delegation/runtime.d.ts +674 -1
  29. package/dist/core/delegation/runtime.d.ts.map +1 -1
  30. package/dist/core/delegation/runtime.js +1338 -66
  31. package/dist/core/delegation/runtime.js.map +1 -1
  32. package/dist/core/extensions/loader.d.ts.map +1 -1
  33. package/dist/core/extensions/loader.js +3 -4
  34. package/dist/core/extensions/loader.js.map +1 -1
  35. package/dist/core/extensions/source-runtime.d.ts +4 -5
  36. package/dist/core/extensions/source-runtime.d.ts.map +1 -1
  37. package/dist/core/extensions/source-runtime.js +4 -5
  38. package/dist/core/extensions/source-runtime.js.map +1 -1
  39. package/dist/core/formatter-lifecycle.d.ts +2 -1
  40. package/dist/core/formatter-lifecycle.d.ts.map +1 -1
  41. package/dist/core/formatter-lifecycle.js +2 -1
  42. package/dist/core/formatter-lifecycle.js.map +1 -1
  43. package/dist/core/hooks/types.d.ts +2 -3
  44. package/dist/core/hooks/types.d.ts.map +1 -1
  45. package/dist/core/hooks/types.js +2 -3
  46. package/dist/core/hooks/types.js.map +1 -1
  47. package/dist/core/http-idle-timeout.d.ts +3 -5
  48. package/dist/core/http-idle-timeout.d.ts.map +1 -1
  49. package/dist/core/http-idle-timeout.js +3 -5
  50. package/dist/core/http-idle-timeout.js.map +1 -1
  51. package/dist/core/mcp/config.d.ts +18 -1
  52. package/dist/core/mcp/config.d.ts.map +1 -1
  53. package/dist/core/mcp/config.js +24 -7
  54. package/dist/core/mcp/config.js.map +1 -1
  55. package/dist/core/mcp/connector.d.ts +2 -3
  56. package/dist/core/mcp/connector.d.ts.map +1 -1
  57. package/dist/core/mcp/connector.js.map +1 -1
  58. package/dist/core/mcp/oauth/authorize.d.ts +2 -0
  59. package/dist/core/mcp/oauth/authorize.d.ts.map +1 -1
  60. package/dist/core/mcp/oauth/authorize.js +5 -2
  61. package/dist/core/mcp/oauth/authorize.js.map +1 -1
  62. package/dist/core/mcp/oauth/mcp-token.d.ts +4 -6
  63. package/dist/core/mcp/oauth/mcp-token.d.ts.map +1 -1
  64. package/dist/core/mcp/oauth/mcp-token.js +5 -7
  65. package/dist/core/mcp/oauth/mcp-token.js.map +1 -1
  66. package/dist/core/mcp/runtime.d.ts +1 -0
  67. package/dist/core/mcp/runtime.d.ts.map +1 -1
  68. package/dist/core/mcp/runtime.js +2 -1
  69. package/dist/core/mcp/runtime.js.map +1 -1
  70. package/dist/core/package-manager.d.ts.map +1 -1
  71. package/dist/core/package-manager.js +0 -15
  72. package/dist/core/package-manager.js.map +1 -1
  73. package/dist/core/permissions/store.d.ts +6 -11
  74. package/dist/core/permissions/store.d.ts.map +1 -1
  75. package/dist/core/permissions/store.js +23 -51
  76. package/dist/core/permissions/store.js.map +1 -1
  77. package/dist/core/project-resources.d.ts +62 -0
  78. package/dist/core/project-resources.d.ts.map +1 -0
  79. package/dist/core/project-resources.js +42 -0
  80. package/dist/core/project-resources.js.map +1 -0
  81. package/dist/core/sdk.d.ts +62 -12
  82. package/dist/core/sdk.d.ts.map +1 -1
  83. package/dist/core/sdk.js +313 -44
  84. package/dist/core/sdk.js.map +1 -1
  85. package/dist/core/session-share.d.ts +6 -8
  86. package/dist/core/session-share.d.ts.map +1 -1
  87. package/dist/core/session-share.js +9 -12
  88. package/dist/core/session-share.js.map +1 -1
  89. package/dist/core/settings-manager.d.ts +0 -21
  90. package/dist/core/settings-manager.d.ts.map +1 -1
  91. package/dist/core/settings-manager.js +4 -12
  92. package/dist/core/settings-manager.js.map +1 -1
  93. package/dist/core/tools/bash.d.ts.map +1 -1
  94. package/dist/core/tools/bash.js +0 -47
  95. package/dist/core/tools/bash.js.map +1 -1
  96. package/dist/core/tools/delegate.d.ts +8 -0
  97. package/dist/core/tools/delegate.d.ts.map +1 -1
  98. package/dist/core/tools/delegate.js +33 -3
  99. package/dist/core/tools/delegate.js.map +1 -1
  100. package/dist/core/tools/web-fetch.d.ts.map +1 -1
  101. package/dist/core/tools/web-fetch.js +4 -8
  102. package/dist/core/tools/web-fetch.js.map +1 -1
  103. package/dist/core/tools/web-search-exa.d.ts +3 -6
  104. package/dist/core/tools/web-search-exa.d.ts.map +1 -1
  105. package/dist/core/tools/web-search-exa.js +5 -8
  106. package/dist/core/tools/web-search-exa.js.map +1 -1
  107. package/dist/core/trust-manager.d.ts +6 -5
  108. package/dist/core/trust-manager.d.ts.map +1 -1
  109. package/dist/core/trust-manager.js +42 -19
  110. package/dist/core/trust-manager.js.map +1 -1
  111. package/dist/core/web-search-provider.d.ts +0 -10
  112. package/dist/core/web-search-provider.d.ts.map +1 -1
  113. package/dist/core/web-search-provider.js +2 -16
  114. package/dist/core/web-search-provider.js.map +1 -1
  115. package/dist/core/workspace/git-observer.d.ts +16 -0
  116. package/dist/core/workspace/git-observer.d.ts.map +1 -1
  117. package/dist/core/workspace/git-observer.js +8 -1
  118. package/dist/core/workspace/git-observer.js.map +1 -1
  119. package/dist/core/workspace/git-worktree-owner.d.ts +89 -0
  120. package/dist/core/workspace/git-worktree-owner.d.ts.map +1 -0
  121. package/dist/core/workspace/git-worktree-owner.js +240 -0
  122. package/dist/core/workspace/git-worktree-owner.js.map +1 -0
  123. package/dist/main.d.ts +0 -1
  124. package/dist/main.d.ts.map +1 -1
  125. package/dist/main.js +22 -3
  126. package/dist/main.js.map +1 -1
  127. package/dist/modes/acp/server.d.ts +43 -1
  128. package/dist/modes/acp/server.d.ts.map +1 -1
  129. package/dist/modes/acp/server.js +78 -0
  130. package/dist/modes/acp/server.js.map +1 -1
  131. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  132. package/dist/modes/interactive/components/settings-selector.js +1 -1
  133. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  134. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  135. package/dist/modes/interactive/interactive-mode.js +0 -29
  136. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  137. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  138. package/dist/modes/rpc/rpc-mode.js +38 -0
  139. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  140. package/dist/modes/rpc/rpc-types.d.ts +110 -0
  141. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  142. package/dist/modes/rpc/rpc-types.js.map +1 -1
  143. package/dist/utils/tools-manager.d.ts +0 -25
  144. package/dist/utils/tools-manager.d.ts.map +1 -1
  145. package/dist/utils/tools-manager.js +3 -52
  146. package/dist/utils/tools-manager.js.map +1 -1
  147. package/dist/utils/version-check.d.ts +0 -2
  148. package/dist/utils/version-check.d.ts.map +1 -1
  149. package/dist/utils/version-check.js +0 -2
  150. package/dist/utils/version-check.js.map +1 -1
  151. package/docs/settings.md +2 -7
  152. package/npm-shrinkwrap.json +5 -5
  153. package/package.json +2 -2
  154. package/dist/core/sandbox/bwrap-arguments.d.ts +0 -41
  155. package/dist/core/sandbox/bwrap-arguments.d.ts.map +0 -1
  156. package/dist/core/sandbox/bwrap-arguments.js +0 -136
  157. package/dist/core/sandbox/bwrap-arguments.js.map +0 -1
  158. package/dist/core/sandbox/child-entry.d.ts +0 -2
  159. package/dist/core/sandbox/child-entry.d.ts.map +0 -1
  160. package/dist/core/sandbox/child-entry.js +0 -24
  161. package/dist/core/sandbox/child-entry.js.map +0 -1
  162. package/dist/core/sandbox/cli-launch.d.ts +0 -162
  163. package/dist/core/sandbox/cli-launch.d.ts.map +0 -1
  164. package/dist/core/sandbox/cli-launch.js +0 -366
  165. package/dist/core/sandbox/cli-launch.js.map +0 -1
  166. package/dist/core/sandbox/cli-supervisor.d.ts +0 -31
  167. package/dist/core/sandbox/cli-supervisor.d.ts.map +0 -1
  168. package/dist/core/sandbox/cli-supervisor.js +0 -147
  169. package/dist/core/sandbox/cli-supervisor.js.map +0 -1
  170. package/dist/core/sandbox/default-hosts.d.ts +0 -28
  171. package/dist/core/sandbox/default-hosts.d.ts.map +0 -1
  172. package/dist/core/sandbox/default-hosts.js +0 -69
  173. package/dist/core/sandbox/default-hosts.js.map +0 -1
  174. package/dist/core/sandbox/full-access.d.ts +0 -28
  175. package/dist/core/sandbox/full-access.d.ts.map +0 -1
  176. package/dist/core/sandbox/full-access.js +0 -63
  177. package/dist/core/sandbox/full-access.js.map +0 -1
  178. package/dist/core/sandbox/git-identity.d.ts +0 -57
  179. package/dist/core/sandbox/git-identity.d.ts.map +0 -1
  180. package/dist/core/sandbox/git-identity.js +0 -78
  181. package/dist/core/sandbox/git-identity.js.map +0 -1
  182. package/dist/core/sandbox/host-approval.d.ts +0 -42
  183. package/dist/core/sandbox/host-approval.d.ts.map +0 -1
  184. package/dist/core/sandbox/host-approval.js +0 -99
  185. package/dist/core/sandbox/host-approval.js.map +0 -1
  186. package/dist/core/sandbox/linux-backend.d.ts +0 -48
  187. package/dist/core/sandbox/linux-backend.d.ts.map +0 -1
  188. package/dist/core/sandbox/linux-backend.js +0 -328
  189. package/dist/core/sandbox/linux-backend.js.map +0 -1
  190. package/dist/core/sandbox/macos-backend.d.ts +0 -30
  191. package/dist/core/sandbox/macos-backend.d.ts.map +0 -1
  192. package/dist/core/sandbox/macos-backend.js +0 -385
  193. package/dist/core/sandbox/macos-backend.js.map +0 -1
  194. package/dist/core/sandbox/network-proxy.d.ts +0 -38
  195. package/dist/core/sandbox/network-proxy.d.ts.map +0 -1
  196. package/dist/core/sandbox/network-proxy.js +0 -153
  197. package/dist/core/sandbox/network-proxy.js.map +0 -1
  198. package/dist/core/sandbox/network-refusal.d.ts +0 -24
  199. package/dist/core/sandbox/network-refusal.d.ts.map +0 -1
  200. package/dist/core/sandbox/network-refusal.js +0 -72
  201. package/dist/core/sandbox/network-refusal.js.map +0 -1
  202. package/dist/core/sandbox/policy.d.ts +0 -40
  203. package/dist/core/sandbox/policy.d.ts.map +0 -1
  204. package/dist/core/sandbox/policy.js +0 -55
  205. package/dist/core/sandbox/policy.js.map +0 -1
  206. package/dist/core/sandbox/profiles.d.ts +0 -25
  207. package/dist/core/sandbox/profiles.d.ts.map +0 -1
  208. package/dist/core/sandbox/profiles.js +0 -23
  209. package/dist/core/sandbox/profiles.js.map +0 -1
  210. package/dist/core/sandbox/rpc/command-client.d.ts +0 -28
  211. package/dist/core/sandbox/rpc/command-client.d.ts.map +0 -1
  212. package/dist/core/sandbox/rpc/command-client.js +0 -86
  213. package/dist/core/sandbox/rpc/command-client.js.map +0 -1
  214. package/dist/core/sandbox/rpc/command-proxy.d.ts +0 -48
  215. package/dist/core/sandbox/rpc/command-proxy.d.ts.map +0 -1
  216. package/dist/core/sandbox/rpc/command-proxy.js +0 -120
  217. package/dist/core/sandbox/rpc/command-proxy.js.map +0 -1
  218. package/dist/core/sandbox/rpc/credential-client.d.ts +0 -20
  219. package/dist/core/sandbox/rpc/credential-client.d.ts.map +0 -1
  220. package/dist/core/sandbox/rpc/credential-client.js +0 -170
  221. package/dist/core/sandbox/rpc/credential-client.js.map +0 -1
  222. package/dist/core/sandbox/rpc/credential-proxy.d.ts +0 -44
  223. package/dist/core/sandbox/rpc/credential-proxy.d.ts.map +0 -1
  224. package/dist/core/sandbox/rpc/credential-proxy.js +0 -287
  225. package/dist/core/sandbox/rpc/credential-proxy.js.map +0 -1
  226. package/dist/core/sandbox/rpc/framing.d.ts +0 -35
  227. package/dist/core/sandbox/rpc/framing.d.ts.map +0 -1
  228. package/dist/core/sandbox/rpc/framing.js +0 -114
  229. package/dist/core/sandbox/rpc/framing.js.map +0 -1
  230. package/dist/core/sandbox/rpc/git-credential-helper.d.ts +0 -47
  231. package/dist/core/sandbox/rpc/git-credential-helper.d.ts.map +0 -1
  232. package/dist/core/sandbox/rpc/git-credential-helper.js +0 -222
  233. package/dist/core/sandbox/rpc/git-credential-helper.js.map +0 -1
  234. package/dist/core/sandbox/rpc/git-credential-proxy.d.ts +0 -66
  235. package/dist/core/sandbox/rpc/git-credential-proxy.d.ts.map +0 -1
  236. package/dist/core/sandbox/rpc/git-credential-proxy.js +0 -209
  237. package/dist/core/sandbox/rpc/git-credential-proxy.js.map +0 -1
  238. package/dist/core/sandbox/supervisor-temp.d.ts +0 -18
  239. package/dist/core/sandbox/supervisor-temp.d.ts.map +0 -1
  240. package/dist/core/sandbox/supervisor-temp.js +0 -21
  241. package/dist/core/sandbox/supervisor-temp.js.map +0 -1
  242. package/dist/core/sandbox/supervisor.d.ts +0 -62
  243. package/dist/core/sandbox/supervisor.d.ts.map +0 -1
  244. package/dist/core/sandbox/supervisor.js +0 -32
  245. package/dist/core/sandbox/supervisor.js.map +0 -1
  246. package/dist/core/sandbox/terminal-handoff.d.ts +0 -68
  247. package/dist/core/sandbox/terminal-handoff.d.ts.map +0 -1
  248. package/dist/core/sandbox/terminal-handoff.js +0 -221
  249. package/dist/core/sandbox/terminal-handoff.js.map +0 -1
  250. package/dist/core/sandbox/terminal-size.d.ts +0 -53
  251. package/dist/core/sandbox/terminal-size.d.ts.map +0 -1
  252. package/dist/core/sandbox/terminal-size.js +0 -126
  253. package/dist/core/sandbox/terminal-size.js.map +0 -1
  254. package/dist/core/sandbox/violations.d.ts +0 -23
  255. package/dist/core/sandbox/violations.d.ts.map +0 -1
  256. package/dist/core/sandbox/violations.js +0 -30
  257. package/dist/core/sandbox/violations.js.map +0 -1
@@ -12,6 +12,8 @@
12
12
  * `AgentSession`/`createAgentSession` and therefore free of the import cycle that
13
13
  * would create (`sdk.ts` already imports `agent-session.ts`).
14
14
  */
15
+ import type { AgentRunBudgetUsage } from "apex-code-agent-core";
16
+ import { type SessionEntry } from "../session-manager.ts";
15
17
  import type { Capability } from "../tools/contract.ts";
16
18
  /** A delegatable agent's static configuration. Markdown + frontmatter in production (`agents.ts`); a plain object in tests. */
17
19
  export interface AgentDefinition {
@@ -26,12 +28,105 @@ export interface AgentDefinition {
26
28
  /** Resolve an agent type to its definition, or `undefined` if unknown. Production implements this over markdown/frontmatter (`agents.ts`); tests inject plain functions with the same shape. */
27
29
  export type AgentDefinitionResolver = (agentType: string) => AgentDefinition | undefined;
28
30
  /** A running or completed child, as far as the runtime needs to know. */
31
+ export type ChildSessionStatus = "idle" | "running" | "interrupted" | "closed";
32
+ /** Terminal outcome of a child's latest settled turn. */
33
+ export type ChildTurnOutcome = "completed" | "failed" | "interrupted";
34
+ /**
35
+ * Token and cost totals for one child run, rolled up from the child's OWN
36
+ * session transcript (the session-file reading seam; never a second transcript
37
+ * cache). The numbers are summed exactly as the provider reported them -- cost
38
+ * is provider-reported, so cache reads are NOT re-priced, re-counted, or
39
+ * double-counted; an entry without usage counts as zero.
40
+ */
41
+ export interface ChildRunUsageTotals {
42
+ inputTokens: number;
43
+ outputTokens: number;
44
+ cacheReadTokens: number;
45
+ cacheWriteTokens: number;
46
+ totalTokens: number;
47
+ cost: {
48
+ input: number;
49
+ output: number;
50
+ cacheRead: number;
51
+ cacheWrite: number;
52
+ total: number;
53
+ };
54
+ /** Wall-clock time (ms) the rollup was computed at. */
55
+ asOf: number;
56
+ /** Usage-bearing transcript entries examined (assistant messages, compaction, branch summaries), including those without usage. */
57
+ entriesCounted: number;
58
+ }
59
+ /** The output and terminal outcome of a child's latest settled turn, as reported by its own handle. */
60
+ export interface ChildTurnResult {
61
+ output: string;
62
+ outcome: ChildTurnOutcome;
63
+ }
64
+ /** Terminal outcome of one attempt on a child run. `cancelled` is recorded only by an explicit interrupt-with-reason. */
65
+ export type ChildRunAttemptOutcome = "completed" | "failed" | "interrupted" | "cancelled";
66
+ /**
67
+ * One launch-or-resume epoch of a child run (spec 2026-09-09, "Child
68
+ * lifecycle"): a launch is attempt 1; a resume closes the prior attempt with
69
+ * its terminal outcome and opens a new one. A live run's follow-ups and
70
+ * steering stay inside the active attempt. `usage` snapshots the child's own
71
+ * budget controller when its session exposes one (optional on the handle).
72
+ * `tokensAtEnd` snapshots the run-level usage/cost rollup (see
73
+ * `ChildRunUsageTotals`) at the attempt's settlement: these are
74
+ * CUMULATIVE-AT-END snapshots of the child's whole transcript, never per-attempt
75
+ * deltas -- range attribution between attempts is not attempted because turns
76
+ * that settled after the last persisted boundary are re-run on resume, so the
77
+ * transcript alone cannot attribute usage to an epoch.
78
+ */
79
+ export interface ChildRunAttempt {
80
+ id: string;
81
+ startedAt: number;
82
+ endedAt?: number;
83
+ outcome?: ChildRunAttemptOutcome;
84
+ error?: string;
85
+ usage?: AgentRunBudgetUsage;
86
+ tokensAtEnd?: ChildRunUsageTotals;
87
+ }
29
88
  export interface ChildSessionHandle {
89
+ readonly status: ChildSessionStatus;
30
90
  /** Run the task to completion and return the child's final output text. */
31
91
  run(task: string): Promise<{
32
92
  output: string;
33
93
  }>;
34
- /** Release the child's resources. Always called, including after a failed run. */
94
+ /**
95
+ * The latest settled turn's output and terminal outcome, derived by this handle
96
+ * from the actual prompt resolution; `undefined` before any turn settles. This --
97
+ * not the registry's stored first-turn promise -- is the source of truth for
98
+ * background retrieval after `sendInput`/`followUp`/resume.
99
+ */
100
+ latestResult(): ChildTurnResult | undefined;
101
+ wait(): Promise<void>;
102
+ interrupt(): void;
103
+ close(): void;
104
+ sendInput(input: string): Promise<void>;
105
+ followUp(input: string): Promise<void>;
106
+ /**
107
+ * Point-in-time snapshot of the child's own run budget counters, when its
108
+ * session exposes a controller. Optional: handles whose child session does
109
+ * not surface a controller simply omit it, and every consumer treats
110
+ * attempt/status usage as optional.
111
+ */
112
+ usage?(): AgentRunBudgetUsage | undefined;
113
+ /**
114
+ * Read-only view of the child's own session entries, when the handle can
115
+ * reach its (possibly in-memory) session manager. Optional: fixture handles
116
+ * need not expose it, and the usage rollup consults it only when the child
117
+ * has no resolvable transcript file (an in-memory child never persisted
118
+ * one). Without this seam AND a transcript file, the run's usage totals are
119
+ * simply unreportable (`undefined`), never guessed.
120
+ */
121
+ sessionEntries?(): readonly SessionEntry[] | undefined;
122
+ /**
123
+ * The derived policy this handle's child was built with (populated by the
124
+ * sdk's `buildChildSession` from the request's admission projection and its
125
+ * own construction values). Optional: fixture handles may omit it, and the
126
+ * runtime relays it onto the child-run record when present.
127
+ */
128
+ policy?: ChildRunPolicySnapshot;
129
+ /** Release the child's resources. Called when the child or owning parent is closed. */
35
130
  dispose(): void;
36
131
  }
37
132
  export interface BuildChildSessionRequest {
@@ -39,12 +134,110 @@ export interface BuildChildSessionRequest {
39
134
  definition: AgentDefinition;
40
135
  /** The child's tool allowlist, already ceiling-checked -- exactly `definition.tools`, never narrowed. */
41
136
  toolNames: string[];
137
+ /**
138
+ * The admitted capability set from the shared admission projection
139
+ * (`resolveAdmittedDefinition`). Consumers use it to describe the child;
140
+ * they must never re-derive it (ADR 0010).
141
+ */
142
+ capabilities: ReadonlySet<Capability>;
42
143
  /** The child's own recursion depth (the parent's depth + 1), for the runtime constructing it to record on the child's session header (task 5.3). */
43
144
  depth: number;
44
145
  /** Stable id used for the child session and its artifact directory. */
45
146
  sessionId: string;
46
147
  /** Per-child artifact root, created before the child session is constructed. */
47
148
  artifactDir?: string;
149
+ workspace?: ChildWorkspaceRequest;
150
+ /**
151
+ * Reattachment marker (restart reconstruction): when set, `buildChildSession`
152
+ * opens this existing child session transcript instead of creating a new
153
+ * session. The path must be the child's own session file under its recorded
154
+ * artifact directory. Every other field keeps its fresh-delegation meaning,
155
+ * so permission/model/tool wiring has exactly one construction path.
156
+ */
157
+ reattachSessionPath?: string;
158
+ /**
159
+ * Optional wall-time cap for the child's OWN run budget (spec 2026-09-09,
160
+ * timeouts): forwarded as `maxWallTimeMs` so the existing AgentRunBudget
161
+ * wall-time gate enforces it mid-run. The launch also records
162
+ * `deadlineMs = Date.now() + timeoutMs` on the record for lazy observation.
163
+ */
164
+ timeoutMs?: number;
165
+ }
166
+ /** The workspace authority requested by a child. Paths are advisory claims,
167
+ * never a replacement for the path-permission gate. */
168
+ export interface ChildWorkspaceRequest {
169
+ isolation: "shared-read" | "worktree";
170
+ ownedPaths: readonly string[];
171
+ /**
172
+ * The resolved isolation root a workspace owner prepared for this child
173
+ * (worktree isolation): absent on the raw request, present on what
174
+ * `prepare()` returns, and the cwd the child session runs in.
175
+ */
176
+ root?: string;
177
+ }
178
+ /**
179
+ * Lifecycle state of a worktree-isolated child's workspace, persisted on the
180
+ * record (spec 2026-09-09, "Workspace states and explicit recovery"). Absent
181
+ * means "active" -- legacy records predate the field and a live worktree is
182
+ * active by definition. Release outcomes write "released" / "retained-dirty" /
183
+ * "retained-failed"; observing a vanished root at resume writes "missing".
184
+ * Explicit recovery (`recoverWorkspace`) verifies and writes "active".
185
+ */
186
+ export type ChildWorkspaceState = "active" | "released" | "retained-dirty" | "retained-failed" | "missing";
187
+ /** Success payload of explicit workspace recovery (`recoverChildWorkspace`). */
188
+ export interface ChildWorkspaceRecoveryResult {
189
+ /** Always "active": the workspace was verified and reactivated. */
190
+ workspaceState: ChildWorkspaceState;
191
+ /** The verified worktree holds uncommitted or untracked work. */
192
+ dirty: boolean;
193
+ }
194
+ /**
195
+ * Real isolation and cleanup for a child's requested workspace authority (spec
196
+ * 2026-09-09, "Parallel work and ownership"): the workspace subsystem owns git;
197
+ * delegation only negotiates the request and refuses worktree isolation when no
198
+ * owner is available. `prepare()` runs only for `isolation: "worktree"` -- a
199
+ * shared-read delegation never touches an owner and never invokes git -- and
200
+ * the request it returns (with `root` set) is what `buildChildSession` receives.
201
+ */
202
+ /**
203
+ * Terminal outcome of releasing a child workspace (worktree). A kept tree is
204
+ * never destroyed silently: "dirty" means uncommitted/untracked child work
205
+ * was preserved; "failed" means the remove failed for another reason and the
206
+ * tree was left in place.
207
+ */
208
+ export type WorkspaceReleaseOutcome = {
209
+ removed: true;
210
+ } | {
211
+ removed: false;
212
+ kept: "dirty" | "failed";
213
+ dir: string;
214
+ error?: string;
215
+ };
216
+ export interface ChildWorkspaceOwner {
217
+ prepare(request: ChildWorkspaceRequest & {
218
+ sessionId: string;
219
+ }): Promise<ChildWorkspaceRequest>;
220
+ /**
221
+ * Release the child's workspace, reporting what happened instead of
222
+ * throwing. `options.force` is the caller's explicit escape hatch to
223
+ * force-remove a dirty tree; without it a dirty tree must be kept.
224
+ */
225
+ release(sessionId: string, options?: {
226
+ force?: boolean;
227
+ }): Promise<WorkspaceReleaseOutcome> | WorkspaceReleaseOutcome;
228
+ /**
229
+ * Read-only verification that a recorded worktree root is still this
230
+ * owner's worktree for the session in the CURRENT workspace: layout,
231
+ * administrative entry, and checked-out branch. Never creates, checks out,
232
+ * resets, or force-removes anything; a failed check throws with the check
233
+ * named. Optional: owners that cannot verify simply never support explicit
234
+ * recovery, and `recoverWorkspace` refuses rather than guessing.
235
+ */
236
+ verify?(sessionId: string, root: string): Promise<{
237
+ dirty: boolean;
238
+ }> | {
239
+ dirty: boolean;
240
+ };
48
241
  }
49
242
  export interface DelegationRuntimeOptions {
50
243
  resolveAgent: AgentDefinitionResolver;
@@ -56,9 +249,102 @@ export interface DelegationRuntimeOptions {
56
249
  getDelegationDepth: () => number;
57
250
  /** Delegation is refused once `getDelegationDepth() >= maxDelegationDepth` -- assigned by the runtime, not by the tool, so the bound applies to any future delegation entry point. */
58
251
  maxDelegationDepth: number;
252
+ /**
253
+ * Maximum simultaneously-active child runs this runtime admits (spec
254
+ * 2026-09-09, "Shared budgets", concurrency cap). Checked at admission --
255
+ * before any child session is built -- and refused with an actionable error
256
+ * naming the limit. An admitted run holds one slot until terminal settlement
257
+ * (completed/failed/interrupted), close, registry disposal, or launch
258
+ * failure. `undefined` (default) is unlimited.
259
+ */
260
+ maxConcurrentChildren?: number;
59
261
  /** Parent session directory. When supplied, child artifacts are rooted beneath it. */
60
262
  getParentSessionDir?: () => string;
263
+ /**
264
+ * Parent session id. When supplied, child-run records carry
265
+ * `parentSessionId`, tying the durable record (and every protocol payload
266
+ * derived from it) to the parent session's own identity.
267
+ */
268
+ getParentSessionId?: () => string;
61
269
  buildChildSession: (request: BuildChildSessionRequest) => Promise<ChildSessionHandle>;
270
+ childRunRegistry?: ChildRunRegistry;
271
+ /** Durable session owner. Records are appended to the parent session's existing log. */
272
+ persistChildRun?: (record: ChildRunRecord) => void;
273
+ /** Optional workspace owner. It is responsible for real isolation and cleanup. */
274
+ workspaceOwner?: ChildWorkspaceOwner;
275
+ }
276
+ /**
277
+ * Compact, derivable snapshot of the derived policy a child session was built
278
+ * with (spec 2026-09-09, "Derive, do not reconstruct"). Populated at child
279
+ * construction from the values actually used -- never re-derived by consumers.
280
+ * `capabilities` come from the delegation runtime's single admission projection
281
+ * (`resolveAdmittedDefinition`), so no surface ever re-classifies authority
282
+ * (ADR 0010). Persisted on `ChildRunRecord` and surfaced through status/wait
283
+ * payloads; legacy records without it load unchanged.
284
+ */
285
+ export interface ChildRunPolicySnapshot {
286
+ /** The child's tool allowlist, exactly as construction received it (ceiling-checked `definition.tools`). */
287
+ tools: string[];
288
+ /** The admitted capability set from the same admission projection that gated the launch. */
289
+ capabilities: string[];
290
+ /** The delegation depth bound in force for this child's own delegations. */
291
+ maxDelegationDepth: number;
292
+ /** The child's resolved model id (its definition's model, or the parent's current model). */
293
+ model?: string;
294
+ /** The child Agent's budget scope; children are built session-scoped so follow-ups continue one controller. */
295
+ budgetScope: "prompt" | "session";
296
+ /** Whether the child answers to the tree's shared aggregate ceiling (present only when explicitly configured at the root). */
297
+ aggregateBudget: boolean;
298
+ }
299
+ export interface ChildRunRecord {
300
+ handleId: string;
301
+ agentType: string;
302
+ sessionId?: string;
303
+ task?: string;
304
+ parentSessionId?: string;
305
+ artifactDir?: string;
306
+ /** The derived policy this child was built with, persisted so session readers describe the child without re-deriving it. Optional: legacy records predate the field. */
307
+ policy?: ChildRunPolicySnapshot;
308
+ /**
309
+ * Legacy only. Records what a session written before ADR 0032 was told about OS
310
+ * containment. Absent on records written since, because nothing sets it: the
311
+ * harness ships no boundary and makes no containment claim. Retained so an older
312
+ * session still parses and still reports what it reported (ADR 0006).
313
+ */
314
+ sandboxEnforced?: boolean;
315
+ workspace?: ChildWorkspaceRequest;
316
+ /**
317
+ * Workspace lifecycle state for worktree-isolated records (see
318
+ * `ChildWorkspaceState`). Written by release outcomes, by resume-time
319
+ * observation of a vanished root ("missing"), and by explicit recovery
320
+ * ("active"). Absent -- on legacy records and shared-read runs -- means
321
+ * "active"; the field only ever appears for worktree isolation.
322
+ */
323
+ workspaceState?: ChildWorkspaceState;
324
+ depth?: number;
325
+ latestResult?: {
326
+ output: string;
327
+ outcome: ChildTurnOutcome;
328
+ };
329
+ status: "created" | "running" | "completed" | "failed" | "interrupted" | "closed";
330
+ updatedAt: number;
331
+ /**
332
+ * Attempt epochs (launch = attempt 1; resume opens a new one). Optional on
333
+ * the wire: legacy records predate the field and are synthesized on load --
334
+ * one attempt derived from the record's status/updatedAt -- so every
335
+ * in-memory record carries at least one.
336
+ */
337
+ attempts?: ChildRunAttempt[];
338
+ activeAttemptId?: string;
339
+ /** Caller-supplied spawn dedupe key; a restarted parent rebuilds the key->handle map from records. */
340
+ idempotencyKey?: string;
341
+ /** Wall-clock deadline recorded at launch (`Date.now() + timeoutMs`); observed lazily by status/list. */
342
+ deadlineMs?: number;
343
+ /** Explicit cancellation, recorded when the run is interrupted with a reason. */
344
+ cancelled?: {
345
+ reason: string;
346
+ at: number;
347
+ };
62
348
  }
63
349
  export interface DelegationResult {
64
350
  agentType: string;
@@ -66,6 +352,380 @@ export interface DelegationResult {
66
352
  output: string;
67
353
  /** Present for background work; pass this handle to retrieveDelegationResult. */
68
354
  handleId?: string;
355
+ /**
356
+ * Terminal outcome of the latest settled turn. Present on registry retrieval
357
+ * once any turn has settled; the foreground result of the initial run omits it.
358
+ */
359
+ outcome?: ChildTurnOutcome;
360
+ }
361
+ /**
362
+ * Non-blocking status snapshot of one child run (`agent/status`,
363
+ * `AgentSession.childRunStatus`). Built from the record/entry alone -- never by
364
+ * awaiting a turn -- so a caller can poll without blocking on the child.
365
+ */
366
+ export interface ChildRunStatus {
367
+ handleId: string;
368
+ agentType: string;
369
+ task: string;
370
+ status: ChildSessionStatus;
371
+ /** The active attempt's identity and its latest outcome, if any turn has settled (or a cancellation was recorded). */
372
+ attempt: {
373
+ id: string;
374
+ outcome?: ChildRunAttemptOutcome;
375
+ };
376
+ /** Total attempt epochs, including closed ones. */
377
+ attempts: number;
378
+ /** The latest settled turn, as persisted for retrieval. */
379
+ lastResult?: {
380
+ output: string;
381
+ outcome: ChildTurnOutcome;
382
+ };
383
+ /** Present when the run was interrupted with an explicit reason. */
384
+ cancelled?: {
385
+ reason: string;
386
+ at: number;
387
+ };
388
+ /** Wall-clock launch deadline (present when the spawn carried timeoutMs). */
389
+ deadlineMs?: number;
390
+ /** Snapshot of the child's own budget controller, when its handle exposes one. */
391
+ usage?: AgentRunBudgetUsage;
392
+ /**
393
+ * Cumulative token totals rolled up from the child's own session transcript
394
+ * (or its in-memory entries when no transcript exists), flattened from
395
+ * `ChildRunUsageTotals`. Present beside `cost` whenever a rollup is
396
+ * reachable; omitted -- never zero-filled -- when nothing is reachable.
397
+ */
398
+ tokens?: {
399
+ inputTokens: number;
400
+ outputTokens: number;
401
+ cacheReadTokens: number;
402
+ cacheWriteTokens: number;
403
+ totalTokens: number;
404
+ };
405
+ /** Provider-reported cost totals corresponding to `tokens`. Absent whenever `tokens` is. */
406
+ cost?: {
407
+ input: number;
408
+ output: number;
409
+ cacheRead: number;
410
+ cacheWrite: number;
411
+ total: number;
412
+ };
413
+ /** The run's negotiated workspace authority (isolation plus a prepared root, when a workspace owner provided one). */
414
+ workspace?: {
415
+ isolation: "shared-read" | "worktree";
416
+ root?: string;
417
+ };
418
+ /**
419
+ * Workspace lifecycle state (worktree-isolated runs only). Present whenever
420
+ * the workspace is worktree-isolated: the record's persisted state, or
421
+ * "active" while the entry is live and unretained.
422
+ */
423
+ workspaceState?: ChildWorkspaceState;
424
+ /** The child's per-run artifact directory, when the child is file-backed. */
425
+ artifactDir?: string;
426
+ /**
427
+ * The child's transcript path, resolved lazily from its artifact directory
428
+ * per SessionManager's `<timestamp>_<sessionId>.jsonl` naming. Absent when
429
+ * the child is in-memory or has not persisted a transcript yet; resolution
430
+ * never throws.
431
+ */
432
+ sessionFile?: string;
433
+ /** The parent session id the run belongs to, when the runtime supplies one. */
434
+ parentSessionId?: string;
435
+ /** The derived policy the child was built with; absent on legacy records and fixture handles that never carried one. */
436
+ policy?: ChildRunPolicySnapshot;
437
+ /** Legacy only, surfaced from the record; nothing sets it since ADR 0032. */
438
+ sandboxEnforced?: boolean;
439
+ }
440
+ /** The registry's record of a handle's latest settled turn. */
441
+ type LatestTurnSettlement = {
442
+ outcome: "completed";
443
+ output: string;
444
+ } | {
445
+ outcome: "interrupted";
446
+ output: string;
447
+ } | {
448
+ outcome: "failed";
449
+ error: unknown;
450
+ };
451
+ interface BackgroundDelegation {
452
+ agentType: string;
453
+ task: string;
454
+ promise: Promise<DelegationResult>;
455
+ child?: ChildSessionHandle;
456
+ closed?: boolean;
457
+ /** The latest settled turn; `undefined` until the first settlement is recorded. */
458
+ latest?: LatestTurnSettlement;
459
+ /** The turn whose settlement has not been observed through retrieval yet, if any. */
460
+ pending?: Promise<unknown>;
461
+ /** Durable fields, persisted on every save so a restart can reattach the child session. */
462
+ artifactDir?: string;
463
+ workspace?: ChildWorkspaceRequest;
464
+ depth?: number;
465
+ /** Record linkage persisted with every save (policy snapshot, sandbox flag, parent session id). */
466
+ policy?: ChildRunPolicySnapshot;
467
+ sandboxEnforced?: boolean;
468
+ parentSessionId?: string;
469
+ /** Attempt epochs (spec 2026-09-09, "Child lifecycle"). `register()` supplies attempt 1 when the caller did not. */
470
+ attempts?: ChildRunAttempt[];
471
+ activeAttemptId?: string;
472
+ idempotencyKey?: string;
473
+ deadlineMs?: number;
474
+ cancelled?: {
475
+ reason: string;
476
+ at: number;
477
+ };
478
+ }
479
+ /** Default follow-up prompt for resuming an interrupted child run. */
480
+ export declare const RESUME_CHILD_PROMPT = "Resume the interrupted task and continue from the existing session.";
481
+ export declare class ChildRunRegistry {
482
+ private readonly entries;
483
+ private readonly workspaceClaims;
484
+ private readonly children;
485
+ /**
486
+ * Session ids whose workspace this registry must release on close/dispose
487
+ * (spec 2026-09-09, "Parallel work and ownership"): populated by
488
+ * `trackWorkspace()` when a worktree-isolated delegation is prepared, and
489
+ * drained exactly once per session id by `releaseWorkspaceOnce()`.
490
+ */
491
+ private readonly trackedWorkspaces;
492
+ /** Session ids whose workspace release has already started -- release runs once, never twice. */
493
+ private readonly releasedWorkspaces;
494
+ /** Last release outcome per session id, surfaced through `workspaceReleaseOutcome()`. */
495
+ private readonly workspaceReleaseOutcomes;
496
+ private workspaceOwner?;
497
+ private disposed;
498
+ private persist?;
499
+ private records;
500
+ /**
501
+ * Spawn dedupe keys -> handle ids (spec 2026-09-09, idempotent spawn). A
502
+ * second spawn with a known key returns the existing handle and never builds
503
+ * a second child. Populated at launch and rebuilt from persisted records on
504
+ * `restore()`, so a restarted parent dedupes too.
505
+ */
506
+ private readonly idempotencyKeys;
507
+ /**
508
+ * Handle ids currently holding a concurrency slot (spec 2026-09-09,
509
+ * "Shared budgets"). Admission takes one slot per child run BEFORE any child
510
+ * session is built; the slot is released on terminal settlement
511
+ * (completed/failed/interrupted), close, registry disposal, or launch
512
+ * failure. Keyed by handle id, so release is idempotent.
513
+ */
514
+ private readonly heldRunSlots;
515
+ /**
516
+ * The delegation runtime this registry runs under, attached by the session
517
+ * that owns it (sdk wiring) or by the first `runDelegation` call. Historical
518
+ * resume reattaches through the SAME `buildChildSession` seam a live
519
+ * delegation uses; without an attached runtime, historical records are still
520
+ * listed and their persisted output retrievable, but they cannot reattach.
521
+ */
522
+ private runtimeOptions?;
523
+ /**
524
+ * Last-computed usage totals per handle id, keyed by what makes them stale
525
+ * (the transcript file's size+mtime, or the in-memory entry count+last id).
526
+ * The transcript file itself stays the one source: on every read the key is
527
+ * re-derived and a mismatch recomputes from the file -- this cache never
528
+ * becomes a second transcript.
529
+ */
530
+ private readonly usageCache;
531
+ /** First attach wins: a registry is owned by one session's runtime. */
532
+ setRuntimeOptions(options: DelegationRuntimeOptions): void;
533
+ setPersistence(persist: (record: ChildRunRecord) => void): void;
534
+ /** Load validated historical records. This never constructs or starts a child. */
535
+ restore(records: readonly ChildRunRecord[]): void;
536
+ /** The handle a spawn dedupe key already maps to, if any. */
537
+ handleForIdempotencyKey(key: string): string | undefined;
538
+ /** True when `id` is known only as a persisted record -- no live entry in this process. */
539
+ isHistorical(id: string): boolean;
540
+ /**
541
+ * Resolve a historical record's child session file. Verified against
542
+ * SessionManager's naming (`<timestamp>_<sessionId>.jsonl` inside the
543
+ * per-child artifact directory, which IS the child's session dir): the
544
+ * timestamp prefix is not recorded, so the directory is scanned for the file
545
+ * whose name ends in `_<sessionId>.jsonl`. Returns the validated triple so
546
+ * the reattachment request carries checked values, not optional record fields.
547
+ */
548
+ private resolveHistoricalSession;
549
+ /**
550
+ * Reattach a persisted child run to its existing child session and continue
551
+ * it with one turn (restart reconstruction). The child session file recorded
552
+ * under the run's artifact directory is reopened through the same
553
+ * `buildChildSession` seam a live delegation uses (reattachment marker), and
554
+ * the run then behaves like any live entry: settlement is observed and
555
+ * persisted, and wait/retrieve/sendInput work on the same handle id.
556
+ *
557
+ * Never-file-backed (in-memory) children, records whose artifact directory or
558
+ * session file is gone, closed runs, and runs whose recorded worktree was
559
+ * released all refuse with an actionable error; nothing is reconstructed
560
+ * from nothing.
561
+ */
562
+ resumeHistorical(id: string, input?: string): Promise<ChildSessionStatus>;
563
+ /**
564
+ * Gate a worktree-isolated historical resume on the workspace's persisted
565
+ * state (spec 2026-09-09, "Workspace states and explicit recovery"). A
566
+ * vanished root classifies the record "missing" (persisted) and refuses; a
567
+ * retained (dirty/failed) root refuses, naming the persisted state and
568
+ * pointing at explicit recovery. Legacy records and recovered ("active")
569
+ * workspaces pass. Read-only: nothing is recreated, checked out, or reset.
570
+ */
571
+ private rejectUnresumableWorktree;
572
+ /**
573
+ * Explicitly verify and reactivate a retained child worktree (spec
574
+ * 2026-09-09, "Workspace states and explicit recovery"). Read-only
575
+ * inspection only -- the workspace owner's verification reads the
576
+ * administrative entry and the checked-out branch and never creates,
577
+ * checks out, resets, or force-removes anything -- and on success the
578
+ * record's workspace state becomes "active" (persisted) so the child can be
579
+ * resumed in the SAME worktree. Automatic recreation stays out of scope by
580
+ * design: every failed check refuses with an actionable error naming the
581
+ * failed check, and the workspace state stays unverified.
582
+ */
583
+ recoverWorkspace(id: string): Promise<ChildWorkspaceRecoveryResult>;
584
+ /**
585
+ * The owner consulted when a tracked child's lifecycle ends. Optional:
586
+ * without one, close/dispose still clean claims but release nothing.
587
+ */
588
+ setWorkspaceOwner(owner: ChildWorkspaceOwner | undefined): void;
589
+ /** Record that a child session's workspace (worktree) must be released when its lifecycle ends. */
590
+ trackWorkspace(sessionId: string): void;
591
+ /**
592
+ * Release a tracked child's workspace through the owner, once per session
593
+ * id. Best effort: a missing owner is tolerated and an owner failure never
594
+ * propagates -- cleanup must never break close or dispose. The outcome is
595
+ * stored per session id (`workspaceReleaseOutcome()`), and a kept tree is
596
+ * warned about loudly so silent data loss cannot hide behind best-effort
597
+ * cleanup.
598
+ */
599
+ private releaseWorkspaceOnce;
600
+ /**
601
+ * Classify a finished release on the record (spec 2026-09-09, "Workspace
602
+ * states and explicit recovery"): removed -> "released", kept dirty ->
603
+ * "retained-dirty", kept failed -> "retained-failed". Only worktree-isolated
604
+ * records carry the state. The classified record persists immediately -- even
605
+ * though release is fire-and-forget -- so a restarted parent sees the
606
+ * classification and can refuse or recover accordingly.
607
+ */
608
+ private recordWorkspaceState;
609
+ /** The stored outcome of this session id's workspace release, if it has run. */
610
+ workspaceReleaseOutcome(sessionId: string): WorkspaceReleaseOutcome | undefined;
611
+ /** Awaitable variant for the delegation failure path, which must release before the throw surfaces. */
612
+ releaseWorkspaceNow(sessionId: string): Promise<void>;
613
+ releaseWorkspace(sessionId: string): void;
614
+ activeWorkspaceClaims(): string[];
615
+ claimWorkspace(sessionId: string, paths: string[]): void;
616
+ private save;
617
+ /**
618
+ * Record a turn settlement from the child handle's own report, falling back to
619
+ * the settlement value for handles that did not report. The latest settlement
620
+ * wins; retrieval serves it instead of the stored first-turn promise.
621
+ */
622
+ private recordCompletion;
623
+ private recordFailure;
624
+ /**
625
+ * Stamp the active attempt with the settled turn's outcome. A cancellation
626
+ * recorded on the entry wins for an interrupted settlement: the attempt
627
+ * stays `cancelled` instead of downgrading to plain `interrupted`. Attempt
628
+ * usage snapshots from the child's own controller where its handle exposes
629
+ * one; handles without a controller leave usage unset. `tokensAtEnd`
630
+ * snapshots the run-level token/cost rollup at settlement time (a
631
+ * cumulative-at-end snapshot of the whole transcript -- see
632
+ * `ChildRunAttempt`); when nothing is reachable it stays unset.
633
+ */
634
+ private stampAttemptSettlement;
635
+ /** Persist the settlement's status. A closed run's terminal status is never overwritten by late settlement. */
636
+ private persistSettlement;
637
+ assertOpen(): void;
638
+ /** The configured child-run concurrency limit, if any. */
639
+ private concurrencyLimit;
640
+ /**
641
+ * Concurrency admission (spec 2026-09-09, "Shared budgets"): refuse with an
642
+ * actionable error naming the limit BEFORE any child session is built when
643
+ * every slot is occupied. An admitted run holds one slot until terminal
644
+ * settlement, close, dispose, or a launch failure releases it.
645
+ */
646
+ admitChildRun(handleId: string): void;
647
+ /** Release a run's concurrency slot. Idempotent. */
648
+ releaseChildRunSlot(handleId: string): void;
649
+ own(child: ChildSessionHandle): void;
650
+ release(child: ChildSessionHandle): void;
651
+ register(id: string, entry: BackgroundDelegation): void;
652
+ retrieve(id: string, expected?: string): Promise<DelegationResult>;
653
+ private latestDelegationResult;
654
+ /**
655
+ * One entry per child run -- live entries first, then historical records --
656
+ * each as `{handleId, agentType, task, status, attemptCount}`. Backward
657
+ * compatible: fields were only ever added. Observing the list lazily
658
+ * interrupts a live running child whose wall-clock deadline has passed.
659
+ */
660
+ list(): {
661
+ handleId: string;
662
+ agentType: string;
663
+ task: string;
664
+ status: ChildSessionStatus;
665
+ attemptCount: number;
666
+ }[];
667
+ /**
668
+ * Non-blocking status snapshot for one handle (spec 2026-09-09, pollable
669
+ * status): built from the live entry or the persisted record alone, never by
670
+ * awaiting a turn. Unknown ids still error. Observing the status lazily
671
+ * interrupts a live running child whose wall-clock deadline has passed, so a
672
+ * timed-out run is reported (and stopped) at observation time.
673
+ */
674
+ status(id: string): ChildRunStatus;
675
+ /**
676
+ * The run's token/cost totals, rolled up on demand from the child's OWN
677
+ * session transcript (the session-file reading seam) -- or from the handle's
678
+ * in-memory session entries when no transcript file exists. Reads lazily and
679
+ * caches only the last-computed totals, keyed by transcript size/mtime or
680
+ * entry count, so the cache can never become a second transcript.
681
+ * `undefined` -- never zero-filled, never a throw -- when nothing is
682
+ * reachable: an in-memory child without a reachable transcript, or a
683
+ * historical record whose transcript is gone. Unknown ids error like
684
+ * `status`.
685
+ */
686
+ usageTotals(id: string): ChildRunUsageTotals | undefined;
687
+ /**
688
+ * One rollup read for both live entries and historical records: a
689
+ * resolvable transcript file wins (the persisted transcript is the source of
690
+ * truth, including after restart); the handle's in-memory session entries
691
+ * cover an in-memory child whose transcript was never written.
692
+ */
693
+ private usageTotalsFor;
694
+ /** The status payload's flattened view of the rollup, omitted when unreachable. */
695
+ private static usageSummaryOf;
696
+ private statusFromEntry;
697
+ private statusFromRecord;
698
+ /**
699
+ * Lazy deadline observation (spec 2026-09-09, timeouts): a live RUNNING child
700
+ * past its recorded wall-clock deadline is interrupted at observation time.
701
+ * The interrupt carries no reason -- a wall-time timeout is not a user
702
+ * cancellation -- so the attempt settles `interrupted`, and the child's own
703
+ * budget gate names "wall-time" in the settlement error path when the run's
704
+ * turn was refused for time. Historical records have no live child to
705
+ * interrupt and are left untouched.
706
+ */
707
+ private observeDeadlines;
708
+ private child;
709
+ wait(id: string): Promise<DelegationResult>;
710
+ sendInput(id: string, input: string): Promise<void>;
711
+ /**
712
+ * Interrupt a live child. An optional reason turns the interrupt into an
713
+ * explicit cancellation: `{reason, at}` is persisted on the record
714
+ * immediately and the active attempt is marked `cancelled`; without a
715
+ * reason the attempt settles plain `interrupted` at the turn's settlement.
716
+ */
717
+ interrupt(id: string, reason?: string): void;
718
+ /**
719
+ * Close a live run's active attempt with its latest settled outcome and open
720
+ * a new one for the resuming turn (spec 2026-09-09, "Child lifecycle"):
721
+ * `AgentSession.resumeChildRun` calls this on the live path before
722
+ * `sendInput` so a resume is a distinct attempt epoch, while ordinary
723
+ * follow-ups on a live run stay inside the active attempt.
724
+ */
725
+ beginResumeAttempt(id: string): void;
726
+ close(id: string): void;
727
+ /** Stop tracking handles and release any children and workspaces still owned by this registry. */
728
+ dispose(): void;
69
729
  }
70
730
  /**
71
731
  * Run one delegation to completion. Throws rather than returning a failure value,
@@ -87,9 +747,22 @@ export interface DelegationResult {
87
747
  * or `buildChildSession`. `buildChildSession` receives the child's depth (parent + 1)
88
748
  * so the caller can record it on the child's own session header.
89
749
  */
750
+ /**
751
+ * Whether two resolved paths denote the same directory or either contains the
752
+ * other. Comparison is separator-correct: forward-slash prefix matching
753
+ * silently never matches on platforms whose resolve() produces backslashes.
754
+ */
755
+ export declare function claimPathsOverlap(a: string, b: string): boolean;
90
756
  export declare function runDelegation(options: DelegationRuntimeOptions, agentType: string, task: string, request?: {
91
757
  background?: boolean;
758
+ workspace?: ChildWorkspaceRequest;
759
+ handleId?: string;
760
+ /** Spawn dedupe key (spec 2026-09-09, idempotent spawn): a known key returns the EXISTING handle without building a second child. */
761
+ idempotencyKey?: string;
762
+ /** Wall-time cap for the child's own run budget; also recorded as the record's deadlineMs for lazy observation. */
763
+ timeoutMs?: number;
92
764
  }): Promise<DelegationResult>;
93
765
  /** Retrieve a background delegation. Running children are awaited; unknown handles fail explicitly. */
94
766
  export declare function retrieveDelegationResult(options: DelegationRuntimeOptions, handleId: string, expectedAgentType?: string): Promise<DelegationResult>;
767
+ export {};
95
768
  //# sourceMappingURL=runtime.d.ts.map