@gajae-code/coding-agent 0.15.5 → 0.16.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 (272) hide show
  1. package/CHANGELOG.md +85 -1
  2. package/dist/types/async/job-manager.d.ts +83 -0
  3. package/dist/types/cli/args.d.ts +2 -0
  4. package/dist/types/cli/auth-gateway-cli.d.ts +17 -0
  5. package/dist/types/cli/model-presets-cli.d.ts +9 -0
  6. package/dist/types/cli/root-flags.d.ts +14 -0
  7. package/dist/types/cli/update-cli.d.ts +15 -0
  8. package/dist/types/cli.d.ts +7 -0
  9. package/dist/types/commands/auth-gateway.d.ts +3 -0
  10. package/dist/types/commands/gc.d.ts +13 -0
  11. package/dist/types/commands/launch.d.ts +10 -0
  12. package/dist/types/commands/model-presets.d.ts +21 -0
  13. package/dist/types/config/autorouting-tier-map.d.ts +120 -0
  14. package/dist/types/config/file-lock.d.ts +54 -2
  15. package/dist/types/config/internal/model-preset-registry-test-state.d.ts +4 -0
  16. package/dist/types/config/internal/model-preset-registry-test-support.d.ts +3 -0
  17. package/dist/types/config/keybindings.d.ts +3 -2
  18. package/dist/types/config/model-preset-registry.d.ts +368 -0
  19. package/dist/types/config/model-profile-activation.d.ts +39 -0
  20. package/dist/types/config/model-profiles.d.ts +5 -3
  21. package/dist/types/config/model-registry.d.ts +17 -5
  22. package/dist/types/config/settings-schema.d.ts +19 -1
  23. package/dist/types/config/settings.d.ts +2 -0
  24. package/dist/types/coordinator-mcp/model-preset.d.ts +7 -5
  25. package/dist/types/coordinator-mcp/projection-scan.d.ts +54 -0
  26. package/dist/types/crash/record-loader.d.ts +15 -0
  27. package/dist/types/extensibility/extensions/types.d.ts +2 -5
  28. package/dist/types/gjc-runtime/empty-delete-gc.d.ts +58 -0
  29. package/dist/types/gjc-runtime/gc-runtime.d.ts +2 -0
  30. package/dist/types/gjc-runtime/launch-worktree-reservation.d.ts +21 -0
  31. package/dist/types/gjc-runtime/managed-owner-supervisor.d.ts +2 -0
  32. package/dist/types/gjc-runtime/session-state-lock.d.ts +35 -6
  33. package/dist/types/gjc-runtime/session-state-sidecar.d.ts +72 -1
  34. package/dist/types/gjc-runtime/tmux-owner-isolation.d.ts +1 -0
  35. package/dist/types/gjc-runtime/tmux-sessions.d.ts +27 -0
  36. package/dist/types/index.d.ts +1 -0
  37. package/dist/types/main.d.ts +3 -1
  38. package/dist/types/master-mode/context.d.ts +21 -0
  39. package/dist/types/master-mode/first-request.d.ts +34 -0
  40. package/dist/types/master-mode/snapshot.d.ts +32 -0
  41. package/dist/types/modes/components/frictionless-onboarding-selector.d.ts +10 -0
  42. package/dist/types/modes/components/jobs-overlay-model.d.ts +4 -2
  43. package/dist/types/modes/components/oauth-selector.d.ts +1 -0
  44. package/dist/types/modes/components/status-line/model-name.d.ts +18 -0
  45. package/dist/types/modes/components/status-line/priority-row.d.ts +34 -0
  46. package/dist/types/modes/components/status-line/segments.d.ts +10 -0
  47. package/dist/types/modes/jobs-observer.d.ts +36 -0
  48. package/dist/types/modes/print-mode.d.ts +17 -0
  49. package/dist/types/modes/ui-language.d.ts +7 -1
  50. package/dist/types/sdk/broker/broker.d.ts +80 -1
  51. package/dist/types/sdk/broker/endpoint-authority.d.ts +24 -0
  52. package/dist/types/sdk/broker/index.d.ts +3 -0
  53. package/dist/types/sdk/broker/lifecycle.d.ts +26 -0
  54. package/dist/types/sdk/broker/master-capability.d.ts +10 -0
  55. package/dist/types/sdk/broker/session-index.d.ts +40 -11
  56. package/dist/types/sdk/broker/session-scope.d.ts +72 -0
  57. package/dist/types/sdk/broker/spawn-authority.d.ts +201 -0
  58. package/dist/types/sdk/broker/spawn-substrate.d.ts +30 -0
  59. package/dist/types/sdk/broker/state-version.d.ts +4 -1
  60. package/dist/types/sdk/broker/worktree-occupancy.d.ts +28 -0
  61. package/dist/types/sdk/bus/chat-daemon-control.d.ts +3 -0
  62. package/dist/types/sdk/bus/index.d.ts +6 -0
  63. package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +3 -0
  64. package/dist/types/sdk/bus/prompt-reconciliation.d.ts +4 -0
  65. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +1 -1
  66. package/dist/types/sdk/cli/index.d.ts +1 -0
  67. package/dist/types/sdk/cli/master-cli.d.ts +63 -0
  68. package/dist/types/sdk/cli/rows.d.ts +4 -3
  69. package/dist/types/sdk/cli/session-cli.d.ts +18 -2
  70. package/dist/types/sdk/client/client.d.ts +3 -2
  71. package/dist/types/sdk/client/discovery.d.ts +1 -0
  72. package/dist/types/sdk/host/control/dispatch.d.ts +10 -0
  73. package/dist/types/sdk/host/control/index.d.ts +1 -1
  74. package/dist/types/sdk/host/control/operations.d.ts +2 -0
  75. package/dist/types/sdk/host/control/runtime-gate.d.ts +21 -7
  76. package/dist/types/sdk/host/host.d.ts +10 -0
  77. package/dist/types/sdk/host/model-pin.d.ts +7 -2
  78. package/dist/types/sdk/host/sdk-run-capability.d.ts +1 -0
  79. package/dist/types/sdk/host/session-runtime.d.ts +67 -1
  80. package/dist/types/sdk/lifecycle/broker-client.d.ts +6 -0
  81. package/dist/types/sdk/lifecycle/service.d.ts +15 -3
  82. package/dist/types/sdk/lifecycle-session.d.ts +2 -0
  83. package/dist/types/sdk/prompt-deadline-manager.d.ts +11 -1
  84. package/dist/types/sdk/protocol/adapter-validation.d.ts +2 -0
  85. package/dist/types/sdk/router/session-router.d.ts +11 -0
  86. package/dist/types/sdk/session.d.ts +16 -0
  87. package/dist/types/sdk/startup-capability.d.ts +2 -1
  88. package/dist/types/session/account-inventory.d.ts +1 -0
  89. package/dist/types/session/agent-session.d.ts +24 -7
  90. package/dist/types/session/credential-store-errors.d.ts +1 -0
  91. package/dist/types/session/fold-coordinator.d.ts +201 -0
  92. package/dist/types/session/sdk-run-capability-internal.d.ts +7 -0
  93. package/dist/types/session/sdk-run-capability.d.ts +2 -0
  94. package/dist/types/session/session-manager.d.ts +65 -0
  95. package/dist/types/session/yield-queue.d.ts +5 -4
  96. package/dist/types/setup/frictionless-onboarding.d.ts +1 -0
  97. package/dist/types/telemetry/control.d.ts +11 -0
  98. package/dist/types/telemetry/events.d.ts +20 -0
  99. package/dist/types/telemetry/index.d.ts +3 -0
  100. package/dist/types/telemetry/transport.d.ts +22 -0
  101. package/dist/types/tools/bash-interactive.d.ts +23 -0
  102. package/dist/types/tools/bash.d.ts +4 -0
  103. package/dist/types/tools/gh.d.ts +8 -0
  104. package/dist/types/tools/index.d.ts +10 -5
  105. package/dist/types/web/search/providers/base.d.ts +9 -4
  106. package/dist/types/web/search/providers/xai.d.ts +2 -1
  107. package/dist/types/web/search/types.d.ts +14 -0
  108. package/package.json +10 -7
  109. package/scripts/generate-hotkeys-docs.ts +4 -0
  110. package/scripts/generate-sdk-operation-inventory.ts +9 -3
  111. package/scripts/verify-gjc-sdk-canonicalization.ts +35 -1
  112. package/src/async/job-manager.ts +671 -39
  113. package/src/cli/accounts-cli.ts +9 -5
  114. package/src/cli/args.ts +17 -0
  115. package/src/cli/auth-broker-cli.ts +40 -12
  116. package/src/cli/auth-gateway-cli.ts +273 -97
  117. package/src/cli/config-cli.ts +2 -2
  118. package/src/cli/fast-help.ts +4 -0
  119. package/src/cli/model-presets-cli.ts +100 -0
  120. package/src/cli/root-flags.ts +5 -0
  121. package/src/cli/update-cli.ts +117 -16
  122. package/src/cli.ts +6 -2
  123. package/src/commands/auth-gateway.ts +12 -8
  124. package/src/commands/gc.ts +19 -0
  125. package/src/commands/launch.ts +86 -18
  126. package/src/commands/model-presets.ts +24 -0
  127. package/src/commands/sdk.ts +113 -21
  128. package/src/config/autorouting-tier-map.ts +44 -0
  129. package/src/config/file-lock-gc.ts +9 -4
  130. package/src/config/file-lock.ts +890 -99
  131. package/src/config/internal/model-preset-registry-test-state.ts +28 -0
  132. package/src/config/internal/model-preset-registry-test-support.ts +11 -0
  133. package/src/config/keybindings.ts +6 -2
  134. package/src/config/model-preset-registry.ts +2795 -0
  135. package/src/config/model-profile-activation.ts +115 -28
  136. package/src/config/model-profile-contract.ts +4 -1
  137. package/src/config/model-profiles.ts +56 -14
  138. package/src/config/model-registry.ts +1044 -122
  139. package/src/config/model-resolver.ts +5 -0
  140. package/src/config/settings-schema.ts +19 -1
  141. package/src/config/settings.ts +11 -1
  142. package/src/coordinator-mcp/model-preset.ts +32 -17
  143. package/src/coordinator-mcp/projection-scan.ts +592 -0
  144. package/src/coordinator-mcp/question-state.ts +9 -11
  145. package/src/coordinator-mcp/server.ts +111 -42
  146. package/src/coordinator-mcp/session-reaper.ts +9 -3
  147. package/src/crash/index-store.ts +2 -0
  148. package/src/crash/record-loader.ts +10 -0
  149. package/src/extensibility/extensions/loader.ts +0 -1
  150. package/src/extensibility/extensions/types.ts +2 -3
  151. package/src/extensibility/gjc-plugins/runtime-adapters.ts +1 -0
  152. package/src/gjc-runtime/empty-delete-gc.ts +301 -0
  153. package/src/gjc-runtime/gc-render.ts +29 -0
  154. package/src/gjc-runtime/gc-runtime.ts +174 -11
  155. package/src/gjc-runtime/launch-worktree-reservation.ts +242 -0
  156. package/src/gjc-runtime/managed-owner-supervisor.ts +63 -51
  157. package/src/gjc-runtime/session-state-lock.ts +1321 -147
  158. package/src/gjc-runtime/session-state-sidecar.ts +1004 -25
  159. package/src/gjc-runtime/tmux-owner-isolation-cli.ts +4 -7
  160. package/src/gjc-runtime/tmux-owner-isolation.ts +2 -2
  161. package/src/gjc-runtime/tmux-sessions.ts +252 -13
  162. package/src/hooks/skill-state.ts +6 -0
  163. package/src/index.ts +1 -0
  164. package/src/internal-urls/docs-index.generated.ts +14 -13
  165. package/src/internal-urls/issue-pr-protocol.ts +4 -2
  166. package/src/lsp/config.ts +4 -3
  167. package/src/lsp/path-trust.ts +12 -6
  168. package/src/main.ts +66 -4
  169. package/src/master-mode/context.ts +50 -0
  170. package/src/master-mode/first-request.ts +65 -0
  171. package/src/master-mode/snapshot.ts +205 -0
  172. package/src/modes/acp/acp-agent.ts +616 -161
  173. package/src/modes/components/footer.ts +4 -2
  174. package/src/modes/components/frictionless-onboarding-selector.ts +48 -2
  175. package/src/modes/components/jobs-overlay-model.ts +99 -16
  176. package/src/modes/components/model-selector.ts +158 -18
  177. package/src/modes/components/oauth-selector.ts +6 -1
  178. package/src/modes/components/settings-selector.ts +1 -0
  179. package/src/modes/components/status-line/model-name.ts +53 -0
  180. package/src/modes/components/status-line/priority-row.ts +107 -0
  181. package/src/modes/components/status-line/segments.ts +29 -10
  182. package/src/modes/components/tool-status-header.ts +151 -15
  183. package/src/modes/controllers/extension-ui-controller.ts +1 -1
  184. package/src/modes/controllers/input-controller.ts +51 -6
  185. package/src/modes/controllers/selector-controller.ts +191 -96
  186. package/src/modes/interactive-mode.ts +14 -1
  187. package/src/modes/jobs-observer.ts +149 -16
  188. package/src/modes/print-mode.ts +64 -0
  189. package/src/modes/runtime-init.ts +1 -1
  190. package/src/modes/ui-language.ts +49 -2
  191. package/src/modes/utils/injected-user-submission.ts +15 -1
  192. package/src/prompts/system/master-mode.md +28 -0
  193. package/src/prompts/tools/bash.md +2 -2
  194. package/src/prompts/tools/fold-receipt.md +3 -0
  195. package/src/prompts/tools/job.md +1 -1
  196. package/src/sdk/acp/adapter.ts +17 -2
  197. package/src/sdk/broker/broker.ts +1671 -34
  198. package/src/sdk/broker/endpoint-authority.ts +86 -0
  199. package/src/sdk/broker/ensure.ts +5 -0
  200. package/src/sdk/broker/index.ts +3 -0
  201. package/src/sdk/broker/lifecycle.ts +217 -46
  202. package/src/sdk/broker/master-capability.ts +232 -0
  203. package/src/sdk/broker/session-index.ts +121 -17
  204. package/src/sdk/broker/session-scope.ts +272 -0
  205. package/src/sdk/broker/spawn-authority.ts +1031 -0
  206. package/src/sdk/broker/spawn-substrate.ts +548 -0
  207. package/src/sdk/broker/state-version.ts +26 -14
  208. package/src/sdk/broker/transport.ts +1 -0
  209. package/src/sdk/broker/worktree-occupancy.ts +90 -0
  210. package/src/sdk/bus/chat-daemon-control.ts +5 -2
  211. package/src/sdk/bus/chat-daemon-runtime.ts +46 -5
  212. package/src/sdk/bus/index.ts +51 -4
  213. package/src/sdk/bus/kind-aware-reconciliation.ts +36 -6
  214. package/src/sdk/bus/prompt-reconciliation.ts +28 -4
  215. package/src/sdk/bus/slack-conversation.ts +5 -1
  216. package/src/sdk/bus/telegram-daemon-contract.ts +1 -1
  217. package/src/sdk/cli/index.ts +1 -0
  218. package/src/sdk/cli/master-cli.ts +259 -0
  219. package/src/sdk/cli/rows.ts +11 -8
  220. package/src/sdk/cli/session-cli.ts +276 -6
  221. package/src/sdk/client/client.ts +14 -8
  222. package/src/sdk/client/discovery.ts +3 -1
  223. package/src/sdk/host/control/dispatch.ts +101 -37
  224. package/src/sdk/host/control/index.ts +2 -0
  225. package/src/sdk/host/control/operations.ts +2 -0
  226. package/src/sdk/host/control/runtime-gate.ts +203 -11
  227. package/src/sdk/host/host.ts +27 -2
  228. package/src/sdk/host/model-pin.ts +185 -25
  229. package/src/sdk/host/sdk-run-capability.ts +1 -0
  230. package/src/sdk/host/session-runtime.test.ts +581 -43
  231. package/src/sdk/host/session-runtime.ts +655 -101
  232. package/src/sdk/lifecycle/broker-client.ts +28 -0
  233. package/src/sdk/lifecycle/service.ts +279 -20
  234. package/src/sdk/lifecycle-session.ts +10 -2
  235. package/src/sdk/prompt-deadline-manager.ts +16 -1
  236. package/src/sdk/protocol/adapter-validation.ts +27 -0
  237. package/src/sdk/protocol/operation-inventory.generated.json +53 -2
  238. package/src/sdk/protocol/operation-registry.ts +17 -4
  239. package/src/sdk/router/session-router.ts +294 -154
  240. package/src/sdk/session.ts +440 -167
  241. package/src/sdk/startup-capability.ts +1 -0
  242. package/src/session/account-inventory.ts +27 -11
  243. package/src/session/agent-session.ts +1292 -180
  244. package/src/session/blob-store.ts +15 -5
  245. package/src/session/credential-store-errors.ts +2 -0
  246. package/src/session/fold-coordinator.ts +433 -0
  247. package/src/session/internal/managed-session-storage.ts +153 -78
  248. package/src/session/sdk-run-capability-internal.ts +15 -0
  249. package/src/session/sdk-run-capability.ts +2 -0
  250. package/src/session/session-manager.ts +342 -28
  251. package/src/session/yield-queue.ts +24 -10
  252. package/src/setup/frictionless-onboarding.ts +2 -0
  253. package/src/setup/provider-presets.json +1 -1
  254. package/src/slash-commands/helpers/credential-switch.ts +6 -1
  255. package/src/task/executor.ts +19 -3
  256. package/src/telemetry/control.ts +26 -0
  257. package/src/telemetry/events.ts +1268 -0
  258. package/src/telemetry/index.ts +3 -0
  259. package/src/telemetry/transport.ts +87 -0
  260. package/src/tools/bash-interactive.ts +182 -85
  261. package/src/tools/bash.ts +1028 -109
  262. package/src/tools/gh.ts +104 -48
  263. package/src/tools/github-cache.ts +2 -2
  264. package/src/tools/index.ts +11 -5
  265. package/src/tools/tool-catalog.generated.ts +1 -1
  266. package/src/web/search/provider.ts +120 -11
  267. package/src/web/search/providers/anthropic.ts +89 -17
  268. package/src/web/search/providers/base.ts +9 -4
  269. package/src/web/search/providers/gemini.ts +87 -15
  270. package/src/web/search/providers/openai-compatible.ts +23 -8
  271. package/src/web/search/providers/xai.ts +98 -12
  272. package/src/web/search/types.ts +16 -0
@@ -51,3 +51,31 @@ export class AgentDirSessionLifecycleClient implements SessionLifecycleClient {
51
51
  export function createBrokerSessionLifecycleService(agentDir: string): SessionLifecycleService {
52
52
  return new SessionLifecycleService(new AgentDirSessionLifecycleClient(agentDir));
53
53
  }
54
+
55
+ /**
56
+ * Dedicated dispatch for the local master `session.spawn` surface. It shares
57
+ * the lifecycle client's credential boundary but bypasses the generic mutation
58
+ * outcome types: spawn responses are validated by the caller's allowlist.
59
+ */
60
+ export async function dispatchSpawnGlobal(
61
+ agentDir: string,
62
+ input: Record<string, unknown>,
63
+ idempotencyKey: string,
64
+ timeoutMs: number,
65
+ ): Promise<unknown> {
66
+ await ensureBroker({ agentDir });
67
+ const discovery = await readSdkBrokerDiscovery(agentDir);
68
+ if (!discovery) throw new Error("SDK broker discovery is unavailable.");
69
+ const client = await SdkClient.connect(discovery.url, discovery.token, { timeoutMs });
70
+ try {
71
+ return await client.global("session.spawn", input, { idempotencyKey, timeoutMs });
72
+ } finally {
73
+ try {
74
+ await client.close();
75
+ } catch (error) {
76
+ logger.warn("SDK spawn client cleanup failed", {
77
+ error: error instanceof Error ? error.message : String(error),
78
+ });
79
+ }
80
+ }
81
+ }
@@ -1,5 +1,14 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import path from "node:path";
3
+ import {
4
+ resolvedScopeV1,
5
+ resolveScopeRequest,
6
+ type ScopeRequestV1,
7
+ type SdkSearchResultV1,
8
+ type SdkSearchRowV1,
9
+ scopeRequestV1,
10
+ searchRowV1,
11
+ } from "../broker/session-scope";
3
12
  import {
4
13
  SessionListTraversalError,
5
14
  type SessionListTraversalPage,
@@ -141,6 +150,9 @@ export interface SessionDeleteTarget {
141
150
  export interface SessionListTarget {
142
151
  readonly cwd?: string;
143
152
  readonly resolveSessionId?: string;
153
+ readonly scope?: ScopeRequestV1;
154
+ readonly limit?: number;
155
+ readonly cursor?: string;
144
156
  }
145
157
 
146
158
  interface SessionLifecycleMutationRequestBase<
@@ -197,7 +209,8 @@ export interface SessionLifecycleListEntry {
197
209
  readonly live?: boolean;
198
210
  readonly endpointGeneration?: number;
199
211
  readonly terminalUncertain?: boolean;
200
- readonly repo?: string;
212
+ readonly cwd?: string;
213
+ readonly locator?: { readonly cwd: string; readonly worktreeRoot: string | null; readonly stateRoot: string };
201
214
  }
202
215
 
203
216
  export interface SessionLifecycleListResult {
@@ -207,6 +220,8 @@ export interface SessionLifecycleListResult {
207
220
  readonly savedSession?: SessionLifecycleSavedSession;
208
221
  }
209
222
 
223
+ export type SessionScopedListResult = SdkSearchResultV1;
224
+
210
225
  export interface SessionCreateResult {
211
226
  readonly ok: true;
212
227
  readonly operation: "session.create";
@@ -240,7 +255,7 @@ export interface SessionReconcileUncertainResult {
240
255
  export interface SessionListSuccessResult {
241
256
  readonly ok: true;
242
257
  readonly operation: "session.list";
243
- readonly result: SessionLifecycleListResult;
258
+ readonly result: SessionLifecycleListResult | SessionScopedListResult;
244
259
  }
245
260
 
246
261
  export interface SessionLifecycleError {
@@ -289,6 +304,7 @@ export type SessionListFailure = {
289
304
  readonly operation: "session.list";
290
305
  readonly certainty: SessionLifecycleCertainty;
291
306
  readonly error: SessionLifecycleError;
307
+ readonly result?: SessionScopedListResult;
292
308
  };
293
309
 
294
310
  export type SessionCreateOutcome = SessionCreateResult | SessionCreateFailure;
@@ -582,12 +598,24 @@ function listResult(value: unknown): SessionLifecycleListResult | undefined {
582
598
  live?: boolean;
583
599
  endpointGeneration?: number;
584
600
  terminalUncertain?: boolean;
585
- repo?: string;
601
+ cwd?: string;
602
+ locator?: { cwd: string; worktreeRoot: string | null; stateRoot: string };
586
603
  } = { sessionId: entry.sessionId };
587
604
  if (typeof entry.live === "boolean") item.live = entry.live;
588
605
  if (typeof entry.endpointGeneration === "number") item.endpointGeneration = entry.endpointGeneration;
589
606
  if (typeof entry.terminalUncertain === "boolean") item.terminalUncertain = entry.terminalUncertain;
590
- if (isRecord(entry.locator) && typeof entry.locator.repo === "string") item.repo = entry.locator.repo;
607
+ if (isRecord(entry.locator) && typeof entry.locator.cwd === "string") item.cwd = entry.locator.cwd;
608
+ if (
609
+ isRecord(entry.locator) &&
610
+ typeof entry.locator.cwd === "string" &&
611
+ (entry.locator.worktreeRoot === null || typeof entry.locator.worktreeRoot === "string") &&
612
+ typeof entry.locator.stateRoot === "string"
613
+ )
614
+ item.locator = {
615
+ cwd: entry.locator.cwd,
616
+ worktreeRoot: entry.locator.worktreeRoot,
617
+ stateRoot: entry.locator.stateRoot,
618
+ };
591
619
  sessions.push(item);
592
620
  }
593
621
  const warnings: string[] = [];
@@ -600,10 +628,40 @@ function listResult(value: unknown): SessionLifecycleListResult | undefined {
600
628
  if (savedSessionPresent && !savedSession) return undefined;
601
629
  return { indexSeq, sessions, warnings, ...(savedSession ? { savedSession } : {}) };
602
630
  }
631
+
632
+ function scopedPage(value: unknown): { scope: SdkSearchResultV1["scope"]; observedAt: string } | undefined {
633
+ if (!isRecord(value)) return undefined;
634
+ const scope = resolvedScopeV1(value.scope);
635
+ return scope && typeof value.observedAt === "string" ? { scope, observedAt: value.observedAt } : undefined;
636
+ }
637
+
638
+ function scopedSearchRows(sessions: readonly SessionLifecycleListEntry[]): SdkSearchRowV1[] | undefined {
639
+ const rows: SdkSearchRowV1[] = [];
640
+ for (const session of sessions) {
641
+ const locator = session.locator;
642
+ if (
643
+ locator === undefined ||
644
+ typeof locator.cwd !== "string" ||
645
+ (locator.worktreeRoot !== null && typeof locator.worktreeRoot !== "string") ||
646
+ typeof locator.stateRoot !== "string"
647
+ )
648
+ return undefined;
649
+ rows.push(
650
+ searchRowV1({
651
+ sessionId: session.sessionId,
652
+ locator: { cwd: locator.cwd, worktreeRoot: locator.worktreeRoot, stateRoot: locator.stateRoot },
653
+ live: session.live === true,
654
+ }),
655
+ );
656
+ }
657
+ return rows;
658
+ }
603
659
  type LifecycleListPage = {
604
660
  readonly result: SessionLifecycleListResult;
605
661
  readonly sessions: readonly SessionLifecycleListEntry[];
606
662
  readonly continuationCursor?: unknown;
663
+ readonly scope?: SdkSearchResultV1["scope"];
664
+ readonly observedAt?: string;
607
665
  };
608
666
 
609
667
  function brokerError(value: unknown): { code: string; message: string } | undefined {
@@ -647,6 +705,24 @@ function brokerErrorFromThrown(value: unknown): { code: string; message: string;
647
705
  return { code, message, ...(requestSent === undefined ? {} : { requestSent }) };
648
706
  }
649
707
 
708
+ function unavailableScopedList(scope: SdkSearchResultV1["scope"]): SessionListFailure {
709
+ return {
710
+ ok: false,
711
+ operation: "session.list",
712
+ certainty: "retryable",
713
+ error: { code: "unavailable", message: "broker search is unavailable" },
714
+ result: {
715
+ version: 1,
716
+ scope,
717
+ status: "unavailable",
718
+ observedAt: new Date().toISOString(),
719
+ rows: [],
720
+ warnings: [],
721
+ error: { code: "unavailable", message: "broker search is unavailable" },
722
+ },
723
+ };
724
+ }
725
+
650
726
  const TRANSPORT_ERROR_CODES = new Set([
651
727
  "timeout",
652
728
  "connection_closed",
@@ -678,7 +754,110 @@ export class SessionLifecycleService {
678
754
  this.#client = client;
679
755
  }
680
756
 
681
- async #execute(
757
+ async scopedList(scope: ScopeRequestV1, limit?: number, cursor?: string): Promise<SessionListOutcome> {
758
+ return await this.#list(
759
+ {
760
+ actor: { id: "gjc-sdk-search-cli", namespace: "sdk:search-cli" },
761
+ capability: "session.list",
762
+ target: {
763
+ scope,
764
+ ...(limit === undefined ? {} : { limit }),
765
+ ...(cursor === undefined ? {} : { cursor }),
766
+ },
767
+ },
768
+ true,
769
+ );
770
+ }
771
+
772
+ async #singleScopedList(
773
+ request: Omit<SessionListRequest, "operation">,
774
+ target: Readonly<Record<string, unknown>>,
775
+ locallyResolvedScope: SdkSearchResultV1["scope"],
776
+ ): Promise<SessionListOutcome> {
777
+ let response: unknown;
778
+ try {
779
+ response = await this.#client.global(
780
+ "session.list",
781
+ { ...target },
782
+ {
783
+ ...(request.timeoutMs === undefined ? {} : { timeoutMs: request.timeoutMs }),
784
+ },
785
+ );
786
+ } catch (thrown) {
787
+ const error = brokerError(thrown) ?? brokerErrorFromThrown(thrown);
788
+ if (!error || error.code === "unavailable") return unavailableScopedList(locallyResolvedScope);
789
+ return failure("session.list", certaintyForThrownError(error), error.code, error.message);
790
+ }
791
+ const error = brokerError(response);
792
+ if (error) {
793
+ if (error.code === "unavailable") return unavailableScopedList(locallyResolvedScope);
794
+ return failure("session.list", certaintyForBrokerCode(error.code), error.code, error.message);
795
+ }
796
+ if (!isRecord(response) || response.ok !== true)
797
+ return failure(
798
+ "session.list",
799
+ "uncertain",
800
+ "malformed_response",
801
+ "lifecycle broker returned a malformed scoped list result",
802
+ );
803
+ const page = sessionListPageFromResponse(response);
804
+ const result = page === undefined ? undefined : listResult(page);
805
+ const pageScope = page === undefined ? undefined : scopedPage(page);
806
+ if (page === undefined || !result || !pageScope)
807
+ return failure(
808
+ "session.list",
809
+ "uncertain",
810
+ "malformed_response",
811
+ "lifecycle broker returned a malformed scoped list result",
812
+ );
813
+ if (JSON.stringify(pageScope.scope) !== JSON.stringify(locallyResolvedScope))
814
+ return failure(
815
+ "session.list",
816
+ "uncertain",
817
+ "scope_observation_drift",
818
+ "lifecycle broker scope does not match the locally resolved request scope",
819
+ );
820
+ const continuationCursor = page.continuationCursor;
821
+ if (
822
+ continuationCursor !== undefined &&
823
+ (typeof continuationCursor !== "string" || continuationCursor.length === 0)
824
+ )
825
+ return failure(
826
+ "session.list",
827
+ "uncertain",
828
+ "malformed_response",
829
+ "lifecycle broker returned a malformed scoped list result",
830
+ );
831
+ const rows = scopedSearchRows(result.sessions);
832
+ if (!rows)
833
+ return failure(
834
+ "session.list",
835
+ "uncertain",
836
+ "malformed_response",
837
+ "lifecycle broker returned a malformed scoped list result",
838
+ );
839
+ return {
840
+ ok: true,
841
+ operation: "session.list",
842
+ result: {
843
+ version: 1,
844
+ scope: pageScope.scope,
845
+ status:
846
+ pageScope.scope.resolution === "not-in-git-worktree"
847
+ ? "not-in-git-worktree"
848
+ : rows.length === 0
849
+ ? "empty"
850
+ : "populated",
851
+ observedAt: pageScope.observedAt,
852
+ indexSeq: result.indexSeq,
853
+ rows,
854
+ ...(continuationCursor === undefined ? {} : { cursor: continuationCursor }),
855
+ warnings: result.warnings,
856
+ },
857
+ };
858
+ }
859
+
860
+ async execute(
682
861
  request: SessionLifecycleMutationRequest,
683
862
  idempotencyKeyOverride?: string,
684
863
  ): Promise<
@@ -759,19 +938,6 @@ export class SessionLifecycleService {
759
938
  | SessionReconcileUncertainOutcome;
760
939
  }
761
940
 
762
- async execute(
763
- request: SessionLifecycleMutationRequest,
764
- ): Promise<
765
- | SessionCreateOutcome
766
- | SessionForkOutcome
767
- | SessionResumeOutcome
768
- | SessionCloseOutcome
769
- | SessionDeleteOutcome
770
- | SessionReconcileUncertainOutcome
771
- > {
772
- return this.#execute(request);
773
- }
774
-
775
941
  async executeWithIdempotencyKey(
776
942
  request: SessionLifecycleMutationRequest,
777
943
  idempotencyKey: string,
@@ -783,7 +949,7 @@ export class SessionLifecycleService {
783
949
  | SessionDeleteOutcome
784
950
  | SessionReconcileUncertainOutcome
785
951
  > {
786
- return this.#execute(request, idempotencyKey);
952
+ return this.execute(request, idempotencyKey);
787
953
  }
788
954
 
789
955
  async create(request: Omit<SessionCreateRequest, "operation">): Promise<SessionCreateOutcome> {
@@ -816,6 +982,9 @@ export class SessionLifecycleService {
816
982
  }
817
983
 
818
984
  async list(request: Omit<SessionListRequest, "operation">): Promise<SessionListOutcome> {
985
+ return await this.#list(request, false);
986
+ }
987
+ async #list(request: Omit<SessionListRequest, "operation">, singleScopedPage: boolean): Promise<SessionListOutcome> {
819
988
  if (!validActor((request as { actor?: unknown }).actor))
820
989
  return failure("session.list", "terminal", "unauthorized", "authenticated actor is required");
821
990
  if ((request as { capability?: unknown }).capability !== "session.list")
@@ -823,6 +992,24 @@ export class SessionLifecycleService {
823
992
  const target = request.target ?? {};
824
993
  if (!validTarget(target))
825
994
  return failure("session.list", "terminal", "invalid_request", "target must be an object");
995
+ const scopeRequest = target.scope === undefined ? undefined : scopeRequestV1(target.scope);
996
+ if (target.scope !== undefined && !scopeRequest)
997
+ return failure("session.list", "terminal", "invalid_request", "scope must be a valid ScopeRequestV1");
998
+ let locallyResolvedScope: SdkSearchResultV1["scope"] | undefined;
999
+ if (scopeRequest !== undefined) {
1000
+ try {
1001
+ locallyResolvedScope = await resolveScopeRequest(scopeRequest);
1002
+ } catch (cause) {
1003
+ return failure(
1004
+ "session.list",
1005
+ "terminal",
1006
+ "invalid_request",
1007
+ cause instanceof Error ? cause.message : "scope could not be resolved",
1008
+ );
1009
+ }
1010
+ }
1011
+ if (singleScopedPage && locallyResolvedScope !== undefined)
1012
+ return await this.#singleScopedList(request, target, locallyResolvedScope);
826
1013
  let pages: readonly SessionListTraversalPage<unknown, LifecycleListPage>[];
827
1014
  try {
828
1015
  pages = await traverseSessionList<Record<string, unknown>, unknown, LifecycleListPage>(
@@ -838,14 +1025,22 @@ export class SessionLifecycleService {
838
1025
  const page = sessionListPageFromResponse(response);
839
1026
  if (!page) return undefined;
840
1027
  const result = listResult(page);
1028
+ const scoped = scopedPage(page);
841
1029
  return result
842
- ? { result, sessions: result.sessions, continuationCursor: page.continuationCursor }
1030
+ ? {
1031
+ result,
1032
+ sessions: result.sessions,
1033
+ continuationCursor: page.continuationCursor,
1034
+ ...(scoped === undefined ? {} : scoped),
1035
+ }
843
1036
  : undefined;
844
1037
  },
845
1038
  );
846
1039
  } catch (thrown) {
847
1040
  if (thrown instanceof BrokerSessionListResponseError) {
848
1041
  const error = thrown.brokerError;
1042
+ if (error.code === "unavailable" && locallyResolvedScope)
1043
+ return unavailableScopedList(locallyResolvedScope);
849
1044
  return failure("session.list", certaintyForBrokerCode(error.code), error.code, error.message);
850
1045
  }
851
1046
  if (thrown instanceof SessionListTraversalError)
@@ -860,6 +1055,8 @@ export class SessionLifecycleService {
860
1055
  : "session.list exceeded the page budget",
861
1056
  );
862
1057
  const error = brokerError(thrown) ?? brokerErrorFromThrown(thrown);
1058
+ if (locallyResolvedScope && (!error || error.code === "unavailable"))
1059
+ return unavailableScopedList(locallyResolvedScope);
863
1060
  return error
864
1061
  ? failure("session.list", certaintyForThrownError(error), error.code, error.message)
865
1062
  : failure("session.list", "retryable", "unavailable", "lifecycle broker request was unavailable");
@@ -873,6 +1070,68 @@ export class SessionLifecycleService {
873
1070
  "lifecycle broker returned a malformed list result",
874
1071
  );
875
1072
  const { result } = firstPage.page;
1073
+ if (request.target?.scope !== undefined) {
1074
+ const scope = firstPage.page.scope;
1075
+ const observedAt = firstPage.page.observedAt;
1076
+ if (!scope || !observedAt)
1077
+ return failure(
1078
+ "session.list",
1079
+ "uncertain",
1080
+ "malformed_response",
1081
+ "lifecycle broker returned a malformed scoped list result",
1082
+ );
1083
+ const frozenScope = JSON.stringify(scope);
1084
+ const frozenIndexSeq = result.indexSeq;
1085
+ for (const page of pages) {
1086
+ const pageScope = page.page.scope;
1087
+ const pageObservedAt = page.page.observedAt;
1088
+ if (
1089
+ pageScope === undefined ||
1090
+ pageObservedAt !== observedAt ||
1091
+ page.page.result.indexSeq !== frozenIndexSeq ||
1092
+ JSON.stringify(pageScope) !== frozenScope
1093
+ )
1094
+ return failure(
1095
+ "session.list",
1096
+ "uncertain",
1097
+ "scope_observation_drift",
1098
+ "lifecycle broker changed the frozen scope observation across list pages",
1099
+ );
1100
+ }
1101
+ if (locallyResolvedScope && JSON.stringify(locallyResolvedScope) !== frozenScope)
1102
+ return failure(
1103
+ "session.list",
1104
+ "uncertain",
1105
+ "scope_observation_drift",
1106
+ "lifecycle broker scope does not match the locally resolved request scope",
1107
+ );
1108
+ const rows = scopedSearchRows(pages.flatMap(page => page.page.result.sessions));
1109
+ if (!rows)
1110
+ return failure(
1111
+ "session.list",
1112
+ "uncertain",
1113
+ "malformed_response",
1114
+ "lifecycle broker returned a malformed scoped list result",
1115
+ );
1116
+ return {
1117
+ ok: true,
1118
+ operation: "session.list",
1119
+ result: {
1120
+ version: 1,
1121
+ scope,
1122
+ status:
1123
+ scope.resolution === "not-in-git-worktree"
1124
+ ? "not-in-git-worktree"
1125
+ : rows.length === 0
1126
+ ? "empty"
1127
+ : "populated",
1128
+ observedAt,
1129
+ indexSeq: result.indexSeq,
1130
+ rows,
1131
+ warnings: result.warnings,
1132
+ },
1133
+ };
1134
+ }
876
1135
  return {
877
1136
  ok: true,
878
1137
  operation: "session.list",
@@ -55,6 +55,8 @@ export type CreateLifecycleAgentSessionOptions = Omit<CreateAgentSessionOptions,
55
55
  * a prepared signal instead of readiness until it is explicitly activated.
56
56
  */
57
57
  readiness?: "immediate" | "deferred";
58
+ /** Broker-issued lifecycle request identity published with host registration. */
59
+ lifecycleRequestId?: string;
58
60
  };
59
61
 
60
62
  /** Internal lifecycle-only session construction with an owner-bound SDK startup result. */
@@ -62,9 +64,15 @@ export async function createLifecycleAgentSession(
62
64
  options: CreateLifecycleAgentSessionOptions = {},
63
65
  ): Promise<CreateLifecycleAgentSessionResult> {
64
66
  const rollback = new SdkStartupRollbackTracker();
65
- const capability = new SdkStartupCapability(rollback, options.readiness ?? "immediate");
67
+ const capability = new SdkStartupCapability(rollback, options.readiness ?? "immediate", options.lifecycleRequestId);
66
68
  try {
67
- const { modelId, mcpStartupTimeoutMs, readiness: _readiness, ...sessionOptions } = options;
69
+ const {
70
+ modelId,
71
+ mcpStartupTimeoutMs,
72
+ readiness: _readiness,
73
+ lifecycleRequestId: _lifecycleRequestId,
74
+ ...sessionOptions
75
+ } = options;
68
76
  const internalOptions = {
69
77
  ...sessionOptions,
70
78
  // Explicit model pin (#4707): resolve through the staged selector
@@ -7,6 +7,7 @@ import {
7
7
  promptDeadlineAt,
8
8
  recordAttributableProgress,
9
9
  } from "./prompt-deadline-lease";
10
+ import type { TurnResultContent } from "./turn-result";
10
11
 
11
12
  const MAX_EXPIRY_RETRIES = 5;
12
13
  const MAX_UNCERTAINTY_RETRIES = 3;
@@ -22,6 +23,12 @@ export type PromptDeadlineOutcome = {
22
23
  provenance: "deadline";
23
24
  };
24
25
 
26
+ export interface PromptTerminalTransitionEvidence {
27
+ content?: TurnResultContent;
28
+ hasActivity?: boolean;
29
+ outcome?: { kind: "stopped"; reason: "cancelled"; provenance: "client_cancel" };
30
+ }
31
+
25
32
  function leaseKey(correlation: InvocationCorrelation): string {
26
33
  return `${correlation.commandId}:${correlation.turnId}`;
27
34
  }
@@ -37,6 +44,7 @@ export class PromptDeadlineManager {
37
44
  readonly #expiring = new Set<string>();
38
45
  readonly #pendingTerminalTransitions = new Set<string>();
39
46
  readonly #pendingTerminalFailureReasons = new Map<string, { code: string; message: string }>();
47
+ readonly #pendingTerminalEvidence = new Map<string, PromptTerminalTransitionEvidence>();
40
48
  readonly #getLeaseMs: () => number;
41
49
  readonly #getMaxMs: () => number;
42
50
  readonly #now: () => number;
@@ -102,7 +110,10 @@ export class PromptDeadlineManager {
102
110
  error: Object.assign(new Error(failureReason.message), { code: failureReason.code }),
103
111
  } as never);
104
112
  }
105
- await this.#reconciliation.noteTransition("prompt", correlation, { type: "agent_end" });
113
+ await this.#reconciliation.noteTransition("prompt", correlation, {
114
+ type: "agent_end",
115
+ ...this.#pendingTerminalEvidence.get(key),
116
+ });
106
117
  // Supersession check before retiring ownership (exact-head review P1):
107
118
  // attributable progress during the awaited writes renews the lease
108
119
  // past its deadline, so this replay instance must back off and
@@ -367,6 +378,7 @@ export class PromptDeadlineManager {
367
378
  noteTerminalTransition(
368
379
  correlation: InvocationCorrelation,
369
380
  pendingFailure?: { code: string; message: string },
381
+ evidence?: PromptTerminalTransitionEvidence,
370
382
  ): void {
371
383
  const key = leaseKey(correlation);
372
384
  if (!this.#leases.has(key)) {
@@ -377,6 +389,7 @@ export class PromptDeadlineManager {
377
389
  this.onAccepted(correlation);
378
390
  }
379
391
  this.#pendingTerminalTransitions.add(key);
392
+ if (evidence !== undefined) this.#pendingTerminalEvidence.set(key, evidence);
380
393
  // Compound failure-plus-terminal recovery intent (exact-head review HIGH):
381
394
  // when expiry replays this real terminal transition after a failed write, it
382
395
  // must re-record the failure reason BEFORE agent_end, or the abandoned or
@@ -395,6 +408,7 @@ export class PromptDeadlineManager {
395
408
  this.#expiring.delete(key);
396
409
  this.#pendingTerminalTransitions.delete(key);
397
410
  this.#pendingTerminalFailureReasons.delete(key);
411
+ this.#pendingTerminalEvidence.delete(key);
398
412
  }
399
413
 
400
414
  clearAll(): void {
@@ -407,6 +421,7 @@ export class PromptDeadlineManager {
407
421
  this.#expiring.clear();
408
422
  this.#pendingTerminalTransitions.clear();
409
423
  this.#pendingTerminalFailureReasons.clear();
424
+ this.#pendingTerminalEvidence.clear();
410
425
  }
411
426
 
412
427
  /** For tests: current deadline or undefined if no lease. */
@@ -28,8 +28,35 @@ export type AdapterValidationError = {
28
28
  message: string;
29
29
  };
30
30
 
31
+ const PROMPT_OPERATIONS = new Set(["turn.prompt", "turn.steer", "turn.follow_up", "turn.abort_and_prompt"]);
32
+
33
+ function hasUsablePromptImage(value: unknown): boolean {
34
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
35
+ const image = value as Record<string, unknown>;
36
+ return (
37
+ typeof image.data === "string" &&
38
+ image.data.trim().length > 0 &&
39
+ (image.mimeType === undefined || (typeof image.mimeType === "string" && image.mimeType.length > 0))
40
+ );
41
+ }
42
+
43
+ /** Rejects instruction-bearing controls before correlation or provider work. */
44
+ export function validateRequiredPromptText(operation: string, input: Input): AdapterValidationError | undefined {
45
+ const hasUsableImage =
46
+ operation === "turn.prompt" && Array.isArray(input.images) && input.images.some(hasUsablePromptImage);
47
+ if (
48
+ PROMPT_OPERATIONS.has(operation) &&
49
+ (typeof input.text !== "string" || (input.text.trim().length === 0 && !hasUsableImage))
50
+ ) {
51
+ return { code: "invalid_input", message: "Prompt must not be empty." };
52
+ }
53
+ return undefined;
54
+ }
55
+
31
56
  /** Validates controls that adapters must reject before forwarding them to a host. */
32
57
  export function validateAdapterControl(operation: string, input: Input): AdapterValidationError | undefined {
58
+ const promptError = validateRequiredPromptText(operation, input);
59
+ if (promptError) return promptError;
33
60
  if (operation === "runtime.reload") {
34
61
  if (
35
62
  !Array.isArray(input.components) ||
@@ -1097,6 +1097,24 @@
1097
1097
  "packages/coding-agent/test/sdk-operation-inventory.test.ts"
1098
1098
  ]
1099
1099
  },
1100
+ {
1101
+ "sourceId": "registry:G09",
1102
+ "sourceFile": "packages/coding-agent/src/sdk/protocol/operation-registry.ts",
1103
+ "sourceKind": "registry",
1104
+ "decision": "include",
1105
+ "sdkId": "session.spawn",
1106
+ "adapterMappings": {
1107
+ "telegram": "prohibited",
1108
+ "discord": "prohibited",
1109
+ "slack": "prohibited",
1110
+ "mcp": "prohibited",
1111
+ "acp": "prohibited",
1112
+ "daemonCli": "prohibited"
1113
+ },
1114
+ "testIds": [
1115
+ "packages/coding-agent/test/sdk-operation-inventory.test.ts"
1116
+ ]
1117
+ },
1100
1118
  {
1101
1119
  "sourceId": "registry:Q01",
1102
1120
  "sourceFile": "packages/coding-agent/src/sdk/protocol/operation-registry.ts",
@@ -2845,6 +2863,39 @@
2845
2863
  "testIds": "not_applicable"
2846
2864
  }
2847
2865
  },
2866
+ {
2867
+ "sourceId": "agent_session:queueCoordinatorRuntimeStatePersistForTests",
2868
+ "sourceFile": "packages/coding-agent/src/session/agent-session.ts",
2869
+ "sourceKind": "agent_session",
2870
+ "decision": "exclude",
2871
+ "rationale": "test-only coordinator persistence ordering seam, not a user-facing SDK control seam",
2872
+ "exclusionMetadata": {
2873
+ "adapterMappings": "not_applicable",
2874
+ "testIds": "not_applicable"
2875
+ }
2876
+ },
2877
+ {
2878
+ "sourceId": "agent_session:parkAgentEndForCoordinatorPersistForTests",
2879
+ "sourceFile": "packages/coding-agent/src/session/agent-session.ts",
2880
+ "sourceKind": "agent_session",
2881
+ "decision": "exclude",
2882
+ "rationale": "test-only parked terminal persistence seam, not a user-facing SDK control seam",
2883
+ "exclusionMetadata": {
2884
+ "adapterMappings": "not_applicable",
2885
+ "testIds": "not_applicable"
2886
+ }
2887
+ },
2888
+ {
2889
+ "sourceId": "agent_session:flushParkedAgentEndForCoordinatorPersistForTests",
2890
+ "sourceFile": "packages/coding-agent/src/session/agent-session.ts",
2891
+ "sourceKind": "agent_session",
2892
+ "decision": "exclude",
2893
+ "rationale": "test-only parked terminal flush seam, not a user-facing SDK control seam",
2894
+ "exclusionMetadata": {
2895
+ "adapterMappings": "not_applicable",
2896
+ "testIds": "not_applicable"
2897
+ }
2898
+ },
2848
2899
  {
2849
2900
  "sourceId": "agent_session:drainAsyncJobDeliveriesForAcp",
2850
2901
  "sourceFile": "packages/coding-agent/src/session/agent-session.ts",
@@ -2937,7 +2988,7 @@
2937
2988
  }
2938
2989
  },
2939
2990
  {
2940
- "sourceId": "agent_session:registerForegroundBashBackgroundRequestHandler",
2991
+ "sourceId": "agent_session:registerForegroundFoldParticipant",
2941
2992
  "sourceFile": "packages/coding-agent/src/session/agent-session.ts",
2942
2993
  "sourceKind": "agent_session",
2943
2994
  "decision": "exclude",
@@ -2992,7 +3043,7 @@
2992
3043
  "sourceFile": "packages/coding-agent/src/session/agent-session.ts",
2993
3044
  "sourceKind": "agent_session",
2994
3045
  "decision": "exclude",
2995
- "rationale": "internal accessor/plumbing, not a user-facing control seam",
3046
+ "rationale": "internal accessor/plumbing, not a user-facing SDK control seam",
2996
3047
  "exclusionMetadata": {
2997
3048
  "adapterMappings": "not_applicable",
2998
3049
  "testIds": "not_applicable"